untested, but make the client sync code less bad and make trinkets/cyphers actually unable to draw from inventory

This commit is contained in:
gamma-delta 2022-02-04 10:21:20 -06:00
parent 8cd849d2db
commit c15d4cac24
9 changed files with 57 additions and 63 deletions

View file

@ -17,7 +17,7 @@ apply plugin: 'maven-publish'
apply plugin: 'net.minecraftforge.gradle'
apply plugin: 'org.parchmentmc.librarian.forgegradle'
version = '0.4.1'
version = '0.5.0-dev'
group = 'at.petra-k.hexcasting' // http://maven.apache.org/guides/mini/guide-naming-conventions.html
archivesBaseName = 'hexcasting'

View file

@ -41,17 +41,17 @@ class GuiSpellcasting(private val handOpenedWith: InteractionHand) : Screen(Text
private var stackDescs: List<Component> = emptyList()
fun recvServerUpdate(info: ControllerInfo, stackDescs: List<Component>) {
fun recvServerUpdate(info: ControllerInfo) {
this.stackDescs = stackDescs
this.patterns.lastOrNull()?.let {
it.valid = if (info.status == ControllerInfo.Status.PREV_PATTERN_INVALID)
it.valid = if (info.wasPrevPatternInvalid)
PatternValidity.ERROR
else
PatternValidity.OK
}
val sound =
if (info.status == ControllerInfo.Status.PREV_PATTERN_INVALID) HexSounds.FAIL_PATTERN.get() else HexSounds.ADD_PATTERN.get()
if (info.wasPrevPatternInvalid) HexSounds.FAIL_PATTERN.get() else HexSounds.ADD_PATTERN.get()
Minecraft.getInstance().soundManager.play(
SimpleSoundInstance.forUI(
sound,

View file

@ -14,6 +14,7 @@ import at.petrak.hexcasting.hexmath.HexPattern
import net.minecraft.nbt.CompoundTag
import net.minecraft.nbt.ListTag
import net.minecraft.nbt.Tag
import net.minecraft.network.chat.Component
import net.minecraft.server.level.ServerLevel
import net.minecraft.server.level.ServerPlayer
import net.minecraft.world.InteractionHand
@ -87,24 +88,27 @@ class CastingHarness private constructor(
* Execute the side effects of a cast, and then tell the client what to think about it.
*/
fun performSideEffects(sideEffects: List<OperatorSideEffect>): ControllerInfo {
var status = ControllerInfo.Status.NONE
var wasSpellCast = false
var wasPrevPatternInvalid = false
for (haskellProgrammersShakingandCryingRN in sideEffects) {
if (haskellProgrammersShakingandCryingRN is OperatorSideEffect.Mishap)
status = ControllerInfo.Status.PREV_PATTERN_INVALID
wasPrevPatternInvalid = true
val mustStop = haskellProgrammersShakingandCryingRN.performEffect(this)
if (mustStop)
break
if (haskellProgrammersShakingandCryingRN is OperatorSideEffect.AttemptSpell)
status = ControllerInfo.Status.SPELL_CAST
wasSpellCast = true
}
if (status == ControllerInfo.Status.SPELL_CAST && this.stack.isEmpty())
status = ControllerInfo.Status.SPELL_CAST_AND_DONE
val descs: ArrayList<Component> = ArrayList<Component>(this.stack.size)
for (datum in this.stack) {
descs.add(datum.display())
}
return ControllerInfo(
status,
wasSpellCast, this.stack.isEmpty(), wasPrevPatternInvalid, descs
)
}
@ -243,22 +247,22 @@ class CastingHarness private constructor(
if (costLeft <= 0)
break
}
if (allowOvercast && costLeft > 0) {
// Cast from HP!
val manaToHealth = HexMod.CONFIG.manaToHealthRate.get()
val healthtoRemove = costLeft.toDouble() / manaToHealth
val manaAbleToCastFromHP = this.ctx.caster.health * manaToHealth
val manaToActuallyPayFor = min(manaAbleToCastFromHP.toInt(), costLeft)
Advancements.OVERCAST_TRIGGER.trigger(this.ctx.caster, manaToActuallyPayFor)
this.ctx.caster.awardStat(HexStatistics.MANA_OVERCASTED, manaCost - costLeft)
this.ctx.caster.hurt(HexDamageSources.OVERCAST, healthtoRemove.toFloat())
costLeft -= manaToActuallyPayFor
}
}
if (allowOvercast && costLeft > 0) {
// Cast from HP!
val manaToHealth = HexMod.CONFIG.manaToHealthRate.get()
val healthtoRemove = costLeft.toDouble() / manaToHealth
val manaAbleToCastFromHP = this.ctx.caster.health * manaToHealth
val manaToActuallyPayFor = min(manaAbleToCastFromHP.toInt(), costLeft)
Advancements.OVERCAST_TRIGGER.trigger(this.ctx.caster, manaToActuallyPayFor)
this.ctx.caster.awardStat(HexStatistics.MANA_OVERCASTED, manaCost - costLeft)
this.ctx.caster.hurt(HexDamageSources.OVERCAST, healthtoRemove.toFloat())
costLeft -= manaToActuallyPayFor
}
// this might be more than the mana cost! for example if we waste a lot of mana from an item
this.ctx.caster.awardStat(HexStatistics.MANA_USED, manaCost - costLeft)
Advancements.SPEND_MANA_TRIGGER.trigger(

View file

@ -1,16 +1,13 @@
package at.petrak.hexcasting.common.casting
import net.minecraft.network.chat.Component
/**
* Information for the sake of the GUI.
*/
data class ControllerInfo(val status: Status) {
enum class Status {
NONE,
SPELL_CAST,
SPELL_CAST_AND_DONE,
PREV_PATTERN_INVALID,
}
fun shouldQuit(): Boolean = this.status == Status.SPELL_CAST_AND_DONE
fun wasSpellCast(): Boolean = this.status == Status.SPELL_CAST || this.status == Status.SPELL_CAST_AND_DONE
}
data class ControllerInfo(
val wasSpellCast: Boolean,
val isStackEmpty: Boolean,
val wasPrevPatternInvalid: Boolean,
val stackDesc: List<Component>
)

View file

@ -58,7 +58,7 @@ public abstract class ItemPackagedSpell extends Item {
List<HexPattern> patterns = getPatterns(tag);
for (var pattern : patterns) {
var info = harness.executeNewPattern(pattern, sPlayer.getLevel());
if (info.shouldQuit()) {
if (info.getWasPrevPatternInvalid()) {
break;
}
}

View file

@ -12,19 +12,19 @@ import net.minecraftforge.fml.DistExecutor;
import net.minecraftforge.network.NetworkEvent;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Supplier;
/**
* Sent server->client when the player finishes casting a spell.
*/
public record MsgNewSpellPatternAck(ControllerInfo info, List<Component> stackDesc) {
private static final String TAG_DESC = "desc";
public record MsgNewSpellPatternAck(ControllerInfo info) {
public static MsgNewSpellPatternAck deserialize(ByteBuf buffer) {
var buf = new FriendlyByteBuf(buffer);
var status = ControllerInfo.Status.values()[buf.readInt()];
var wasSpellCast = buf.readBoolean();
var isStackEmpty = buf.readBoolean();
var wasPrevPatternInvalid = buf.readBoolean();
var descsLen = buf.readInt();
var desc = new ArrayList<Component>(descsLen);
for (int i = 0; i < descsLen; i++) {
@ -32,17 +32,18 @@ public record MsgNewSpellPatternAck(ControllerInfo info, List<Component> stackDe
}
return new MsgNewSpellPatternAck(
new ControllerInfo(status),
desc
new ControllerInfo(wasSpellCast, isStackEmpty, wasPrevPatternInvalid, desc)
);
}
public void serialize(ByteBuf buffer) {
var buf = new FriendlyByteBuf(buffer);
buf.writeInt(this.info.getStatus().ordinal());
buf.writeInt(this.stackDesc.size());
for (var desc : this.stackDesc) {
buf.writeBoolean(this.info.getWasSpellCast());
buf.writeBoolean(this.info.isStackEmpty());
buf.writeBoolean(this.info.getWasPrevPatternInvalid());
buf.writeInt(this.info.getStackDesc().size());
for (var desc : this.info.getStackDesc()) {
buf.writeComponent(desc);
}
}
@ -51,16 +52,16 @@ public record MsgNewSpellPatternAck(ControllerInfo info, List<Component> stackDe
ctx.get().enqueueWork(() ->
DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> {
var mc = Minecraft.getInstance();
if (this.info.shouldQuit()) {
if (this.info.isStackEmpty()) {
// don't pay attention to the screen, so it also stops when we die
mc.getSoundManager().stop(HexSounds.CASTING_AMBIANCE.getId(), null);
}
var screen = Minecraft.getInstance().screen;
if (screen instanceof GuiSpellcasting spellGui) {
if (this.info.shouldQuit()) {
if (this.info.isStackEmpty()) {
mc.setScreen(null);
} else {
spellGui.recvServerUpdate(this.info, this.stackDesc);
spellGui.recvServerUpdate(this.info);
}
}
})

View file

@ -7,14 +7,12 @@ import at.petrak.hexcasting.hexmath.HexPattern;
import io.netty.buffer.ByteBuf;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.network.chat.Component;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.sounds.SoundSource;
import net.minecraft.world.InteractionHand;
import net.minecraftforge.network.NetworkEvent;
import net.minecraftforge.network.PacketDistributor;
import java.util.ArrayList;
import java.util.function.Supplier;
/**
@ -47,14 +45,14 @@ public record MsgNewSpellPatternSyn(InteractionHand handUsed, HexPattern pattern
var clientInfo = harness.executeNewPattern(this.pattern, sender.getLevel());
if (clientInfo.wasSpellCast()) {
if (clientInfo.getWasSpellCast()) {
sender.level.playSound(null, sender.getX(), sender.getY(), sender.getZ(),
HexSounds.ACTUALLY_CAST.get(), SoundSource.PLAYERS, 1f,
1f + ((float) Math.random() - 0.5f) * 0.2f);
}
CompoundTag nextHarnessTag;
if (clientInfo.shouldQuit()) {
if (clientInfo.isStackEmpty()) {
// discard the changes
nextHarnessTag = new CompoundTag();
} else {
@ -63,14 +61,8 @@ public record MsgNewSpellPatternSyn(InteractionHand handUsed, HexPattern pattern
}
tag.put(ItemWand.TAG_HARNESS, nextHarnessTag);
var descs = new ArrayList<Component>(harness.getStack().size());
for (var datum : harness.getStack()) {
descs.add(datum.display());
}
HexMessages.getNetwork()
.send(PacketDistributor.PLAYER.with(() -> sender),
new MsgNewSpellPatternAck(clientInfo, descs));
.send(PacketDistributor.PLAYER.with(() -> sender), new MsgNewSpellPatternAck(clientInfo));
}
}
});

View file

@ -8,11 +8,11 @@
"pages": [
{
"type": "patchouli:text",
"text": "Although their names were lost to time, the old practitioners of my art were often known for a color, emblematic of them and their spells. It seems a special kind of pigment, offered to Nature in the right way, would \"[...] paint one's thoughts in a manner pleasing to Nature, inducing a miraculous change in color.\""
"text": "Although the names of the old practitioners of my art were lost to time, they were often known for a color, emblematic of them and their spells. It seems a special kind of pigment, offered to Nature in the right way, would \"[...] paint one's thoughts in a manner pleasing to Nature, inducing a miraculous change in color.\""
},
{
"type": "patchouli:text",
"text": "I'm not certain on the specifics of how it works, but I believe I have isolated the formulae for many different colors of pigments. To use one, I hold it in my other hand while casting $(l:patterns/spells/colorize)$(action)Internalize Pigment/$, which will consume the pigment and mark my mind with that color.$(br2)The pigments seem to affect the color of the spare media coming out of a staff when I cast a _Hex, as well as my $(l:hexcasting/patterns/sentinels)$(thing)Sentinel/$."
"text": "I'm not certain on the specifics of how it works, but I believe I have isolated the formulae for many different colors of pigments. To use one, I hold it in my other hand while casting $(l:patterns/spells/colorize)$(action)Internalize Pigment/$, which will consume the pigment and mark my mind with that color.$(br2)The pigments seem to affect the color of the spare media coming out of a staff when I cast a _Hex, as well as my $(l:patterns/sentinels)$(thing)Sentinel/$."
},
{
"type": "hexcasting:crafting_multi",

View file

@ -8,7 +8,7 @@
"pages": [
{
"type": "patchouli:text",
"text": "$(italic)Hence, away! Now all is well,$(br)One aloof stand sentinel./$$(br2)A $(thing)Sentinel/$ is a mysterious force I can summon to assist in the casting of _Hexes, like a familiar or guardian spirit. It appears as a small blob of light to my eyes, but is invisible to everyone else."
"text": "$(italic)Hence, away! Now all is well,$(br)One aloof stand sentinel./$$(br2)A $(thing)Sentinel/$ is a mysterious force I can summon to assist in the casting of _Hexes, like a familiar or guardian spirit. It appears as a spinning geometric shape to my eyes, but is invisible to everyone else."
},
{
"type": "patchouli:text",