diff --git a/gradle.properties b/gradle.properties index 1792643..5151cce 100644 --- a/gradle.properties +++ b/gradle.properties @@ -5,11 +5,11 @@ org.gradle.jvmargs=-Xmx1G minecraft_version=1.20.4 supported_version=>=1.20.2 yarn_mappings=1.20.4+build.3 -loader_version=0.15.6 +loader_version=0.15.7 # Mod Properties -mod_version=5.2.0 +mod_version=6.0.0 maven_group=dev.louis archives_base_name=Nebula # Dependencies # check this on https://modmuss50.me/fabric.html -fabric_version=0.95.0+1.20.4 +fabric_version=0.96.4+1.20.4 diff --git a/nebulo/src/main/java/dev/louis/nebulo/manager/ManagerRegisterer.java b/nebulo/src/main/java/dev/louis/nebulo/manager/ManagerRegisterer.java index 45662fe..76d752b 100644 --- a/nebulo/src/main/java/dev/louis/nebulo/manager/ManagerRegisterer.java +++ b/nebulo/src/main/java/dev/louis/nebulo/manager/ManagerRegisterer.java @@ -4,13 +4,8 @@ import dev.louis.nebula.api.manager.mana.registerable.ManaManagerRegistrableView; import dev.louis.nebula.api.manager.spell.entrypoint.RegisterSpellManagerEntrypoint; import dev.louis.nebula.api.manager.spell.registerable.SpellManagerRegistrableView; -import dev.louis.nebula.manager.mana.NebulaManaManager; -import dev.louis.nebula.manager.spell.NebulaSpellManager; -import dev.louis.nebula.networking.SyncManaS2CPacket; -import dev.louis.nebula.networking.UpdateSpellCastabilityS2CPacket; import dev.louis.nebulo.manager.mana.NebuloManaManager; import dev.louis.nebulo.manager.spell.NebuloSpellManager; -import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking; public class ManagerRegisterer implements RegisterManaManagerEntrypoint, RegisterSpellManagerEntrypoint { @Override @@ -18,21 +13,11 @@ public void registerManaManager(ManaManagerRegistrableView manaManagerRegistrabl manaManagerRegistrableView.registerManaManager(NebuloManaManager::new); } - @Override - public void registerManaPacketReceiver() { - ClientPlayNetworking.registerGlobalReceiver(SyncManaS2CPacket.TYPE, NebulaManaManager::receiveSync); - } - @Override public void registerSpellManager(SpellManagerRegistrableView spellManagerRegistrableView) { spellManagerRegistrableView.registerSpellManager(NebuloSpellManager::new); } - @Override - public void registerSpellPacketReceiver() { - ClientPlayNetworking.registerGlobalReceiver(UpdateSpellCastabilityS2CPacket.TYPE, NebulaSpellManager::receiveSync); - } - @Override public boolean shouldRegister() { return true; diff --git a/nebulo/src/main/java/dev/louis/nebulo/spell/CloudJumpSpell.java b/nebulo/src/main/java/dev/louis/nebulo/spell/CloudJumpSpell.java index 6f961ed..39cd079 100644 --- a/nebulo/src/main/java/dev/louis/nebulo/spell/CloudJumpSpell.java +++ b/nebulo/src/main/java/dev/louis/nebulo/spell/CloudJumpSpell.java @@ -2,14 +2,15 @@ import dev.louis.nebula.api.spell.Spell; import dev.louis.nebula.api.spell.SpellType; +import net.minecraft.entity.player.PlayerEntity; import net.minecraft.particle.ParticleTypes; import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.sound.SoundCategory; import net.minecraft.sound.SoundEvents; public class CloudJumpSpell extends Spell { - public CloudJumpSpell(SpellType spellType) { - super(spellType); + public CloudJumpSpell(SpellType spellType, PlayerEntity player) { + super(spellType, player); } @Override @@ -48,7 +49,7 @@ public int getDuration() { } @Override - public void onEnd() { + public void finish() { if(!this.getCaster().getWorld().isClient()) { var serverPlayer = (ServerPlayerEntity) this.getCaster(); serverPlayer.playSound(SoundEvents.ENTITY_CAMEL_DASH, SoundCategory.PLAYERS, 2f, -1f); diff --git a/settings.gradle b/settings.gradle index 120b173..265d2c0 100644 --- a/settings.gradle +++ b/settings.gradle @@ -8,4 +8,4 @@ pluginManagement { } } -include(":nebulo") +//include(":nebulo") diff --git a/src/main/java/dev/louis/nebula/Nebula.java b/src/main/java/dev/louis/nebula/Nebula.java index c5c2087..f32b940 100644 --- a/src/main/java/dev/louis/nebula/Nebula.java +++ b/src/main/java/dev/louis/nebula/Nebula.java @@ -3,6 +3,7 @@ import com.mojang.logging.LogUtils; import dev.louis.nebula.api.spell.SpellType; import dev.louis.nebula.command.NebulaCommand; +import dev.louis.nebula.manager.NebulaManager; import dev.louis.nebula.networking.SpellCastC2SPacket; import net.fabricmc.api.ModInitializer; import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking; diff --git a/src/main/java/dev/louis/nebula/NebulaClient.java b/src/main/java/dev/louis/nebula/NebulaClient.java index fe6e28d..c223e43 100644 --- a/src/main/java/dev/louis/nebula/NebulaClient.java +++ b/src/main/java/dev/louis/nebula/NebulaClient.java @@ -1,11 +1,21 @@ package dev.louis.nebula; +import dev.louis.nebula.manager.mana.NebulaManaManager; +import dev.louis.nebula.manager.spell.NebulaSpellManager; +import dev.louis.nebula.networking.SyncManaS2CPacket; +import dev.louis.nebula.networking.UpdateSpellCastabilityS2CPacket; import net.fabricmc.api.ClientModInitializer; +import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking; public class NebulaClient implements ClientModInitializer { @Override public void onInitializeClient() { - NebulaManager.registerPacketReceivers(); + registerPacketReceivers(); + } + + public void registerPacketReceivers() { + ClientPlayNetworking.registerGlobalReceiver(UpdateSpellCastabilityS2CPacket.TYPE, NebulaSpellManager::receiveSync); + ClientPlayNetworking.registerGlobalReceiver(SyncManaS2CPacket.TYPE, NebulaManaManager::receiveSync); } } diff --git a/src/main/java/dev/louis/nebula/api/NebulaPlayer.java b/src/main/java/dev/louis/nebula/api/NebulaPlayer.java index f5cac54..9b6e704 100644 --- a/src/main/java/dev/louis/nebula/api/NebulaPlayer.java +++ b/src/main/java/dev/louis/nebula/api/NebulaPlayer.java @@ -3,6 +3,7 @@ import dev.louis.nebula.api.manager.mana.ManaManager; import dev.louis.nebula.api.manager.spell.SpellManager; import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.server.network.ServerPlayerEntity; /** * This interface will be injected into {@link PlayerEntity}. @@ -25,6 +26,22 @@ default SpellManager setSpellManager(SpellManager spellManager) { throw new UnsupportedOperationException("Injected Interface method was not overridden!"); } + static ManaManager getManaManager(ServerPlayerEntity serverPlayer) { + return serverPlayer.getManaManager(); + } + + static ManaManager setManaManager(ServerPlayerEntity serverPlayer, ManaManager manaManager) { + return serverPlayer.setManaManager(manaManager); + } + + static SpellManager getSpellManager(ServerPlayerEntity serverPlayer) { + return serverPlayer.getSpellManager(); + } + + static SpellManager setSpellManager(ServerPlayerEntity serverPlayer, SpellManager spellManager) { + return serverPlayer.setSpellManager(spellManager); + } + /** * This creates the ManaManager and the SpellManager if they are not already created. * This should not be called manually, unless you know what you are doing. diff --git a/src/main/java/dev/louis/nebula/api/manager/mana/ManaManager.java b/src/main/java/dev/louis/nebula/api/manager/mana/ManaManager.java index c2444e0..1002dfa 100644 --- a/src/main/java/dev/louis/nebula/api/manager/mana/ManaManager.java +++ b/src/main/java/dev/louis/nebula/api/manager/mana/ManaManager.java @@ -36,12 +36,6 @@ public interface ManaManager { */ void drainMana(int mana); - /** - * Drains amount of mana from {@link SpellType#getManaCost()} - * @param spellType The SpellType where the amount of mana to drain is got from. - */ - void drainMana(SpellType spellType); - /** * @return The maximum amount of mana that can be stored. */ @@ -57,7 +51,7 @@ public interface ManaManager { * @param spellType The SpellType which should be checked. * @return If enough mana is available for the specified SpellType. */ - boolean isCastable(SpellType spellType); + boolean hasEnoughMana(SpellType spellType); /** * Sends the ManaManager's state to the client. @@ -132,11 +126,6 @@ public void drainMana(int mana) { } - @Override - public void drainMana(SpellType spellType) { - - } - @Override public int getMaxMana() { return 0; @@ -148,7 +137,7 @@ public boolean hasEnoughMana(int mana) { } @Override - public boolean isCastable(SpellType spellType) { + public boolean hasEnoughMana(SpellType spellType) { return false; } diff --git a/src/main/java/dev/louis/nebula/api/manager/mana/entrypoint/RegisterManaManagerEntrypoint.java b/src/main/java/dev/louis/nebula/api/manager/mana/entrypoint/RegisterManaManagerEntrypoint.java index 46c2600..4629892 100644 --- a/src/main/java/dev/louis/nebula/api/manager/mana/entrypoint/RegisterManaManagerEntrypoint.java +++ b/src/main/java/dev/louis/nebula/api/manager/mana/entrypoint/RegisterManaManagerEntrypoint.java @@ -8,8 +8,6 @@ public interface RegisterManaManagerEntrypoint { void registerManaManager(ManaManagerRegistrableView manaManagerRegistrableView); - void registerManaPacketReceiver(); - default boolean shouldRegister() { return true; }; diff --git a/src/main/java/dev/louis/nebula/api/manager/spell/entrypoint/RegisterSpellManagerEntrypoint.java b/src/main/java/dev/louis/nebula/api/manager/spell/entrypoint/RegisterSpellManagerEntrypoint.java index 86947cb..7232d1f 100644 --- a/src/main/java/dev/louis/nebula/api/manager/spell/entrypoint/RegisterSpellManagerEntrypoint.java +++ b/src/main/java/dev/louis/nebula/api/manager/spell/entrypoint/RegisterSpellManagerEntrypoint.java @@ -8,8 +8,6 @@ public interface RegisterSpellManagerEntrypoint { void registerSpellManager(SpellManagerRegistrableView spellManagerRegistrableView); - void registerSpellPacketReceiver(); - default boolean shouldRegister() { return true; }; diff --git a/src/main/java/dev/louis/nebula/api/spell/Spell.java b/src/main/java/dev/louis/nebula/api/spell/Spell.java index 5abccd5..b6e65db 100644 --- a/src/main/java/dev/louis/nebula/api/spell/Spell.java +++ b/src/main/java/dev/louis/nebula/api/spell/Spell.java @@ -1,48 +1,26 @@ package dev.louis.nebula.api.spell; import dev.louis.nebula.api.manager.spell.SpellManager; -import net.minecraft.entity.data.TrackedDataHandler; import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.network.PacketByteBuf; -import net.minecraft.util.Identifier; - -import java.util.Optional; /** * This class represents an attempt to cast a spell. It holds a reference to the caster of the Spell. * */ public abstract class Spell { - public static final TrackedDataHandler> OPTIONAL_SPELL = new TrackedDataHandler.ImmutableHandler<>() { - public void write(PacketByteBuf buf, Optional optionalSpell) { - buf.writeBoolean(optionalSpell.isPresent()); - optionalSpell.ifPresent(spell -> { - buf.writeRegistryValue(SpellType.REGISTRY, spell.getType()); - spell.writeBuf(buf); - }); - } - - public Optional read(PacketByteBuf buf) { - if(!buf.readBoolean()) return Optional.empty(); - SpellType spellType = buf.readRegistryValue(SpellType.REGISTRY); - if(spellType == null) throw new IllegalStateException("Spell type not found in registry"); - var spell = spellType.create(); - spell.readBuf(buf); - return Optional.of(spell); - } - }; - private static final int DEFAULT_SPELL_AGE = 3 * 20; - - private final SpellType spellType; - private PlayerEntity caster; - - protected int spellAge = 0; + private static final int DEFAULT_SPELL_AGE = 0; + + protected final SpellType spellType; + protected final PlayerEntity caster; + protected boolean wasInterrupted; - protected boolean hasEnded; protected boolean stopped; - public Spell(SpellType spellType) { + public int age = 0; + + public Spell(SpellType spellType, PlayerEntity caster) { this.spellType = spellType; + this.caster = caster; } /** @@ -59,18 +37,9 @@ public void applyCost() { this.getCaster().getManaManager().drainMana(getType().getManaCost()); } - public final void baseTick() { - spellAge++; - this.tick(); - } - public void tick() { } - public Identifier getId() { - return this.getType().getId(); - } - public PlayerEntity getCaster() { return this.caster; } @@ -79,10 +48,6 @@ public SpellType getType() { return this.spellType; } - public int getAge() { - return this.spellAge; - } - public int getDuration() { return DEFAULT_SPELL_AGE; } @@ -92,12 +57,7 @@ public int getDuration() { * After this method is called {@link Spell#tick()} will not be called anymore.
* Use this to finish all remaining logic of the spell. */ - public void onEnd() { - this.hasEnded = true; - } - - public void setCaster(PlayerEntity caster) { - this.caster = caster; + public void finish() { } /** @@ -105,14 +65,14 @@ public void setCaster(PlayerEntity caster) { * It is important to check super or check if the spell was interrupted {@link Spell#wasInterrupted()}.
*/ public boolean shouldStop() { - return this.stopped || this.spellAge > this.getDuration(); + return this.stopped || this.age > this.getDuration(); } /** * Interrupts the spell.
* This method is final as no Spell is immune to being interrupted
*
- * If you want to show to the player that the spell was interrupted check {@link Spell#wasInterrupted()} in {@link Spell#onEnd()} as it is called after this. + * If you want to show to the player that the spell was interrupted check {@link Spell#wasInterrupted()} in {@link Spell#finish()} as it is called after this. */ public final void interrupt() { this.wasInterrupted = true; @@ -121,11 +81,11 @@ public final void interrupt() { /** * Stop the spell.
- * This method is final as post-spell action shall be handled in {@link Spell#onEnd()}
+ * This method is final as post-spell action shall be handled in {@link Spell#finish()}
*
* Unlike {@link Spell#interrupt()} if you call this method it is expected that the spell has finished execution.
*/ - public final void stop() { + protected final void stop() { this.stopped = true; } @@ -146,35 +106,12 @@ public boolean wasInterrupted() { return this.wasInterrupted; } - public boolean hasEnded() { - return this.hasEnded; - } - - /** - * Read additional casting data about the spell from the buf. - * @param buf The buf to be read from. - * @return The buf after being read from. - */ - public PacketByteBuf readBuf(PacketByteBuf buf) { - return buf; - } - - /** - * Write additional casting data about the spell to the buf. - * @param buf The buf to be written to. - * @return The buf after being written to. - */ - public PacketByteBuf writeBuf(PacketByteBuf buf) { - return buf; - } - - @Override public String toString() { return this.getClass().getSimpleName() + "[spellType=" + this.spellType + ", caster=" + this.caster + - ", spellAge=" + this.spellAge + + ", spellAge=" + this.age + ", wasInterrupted=" + this.wasInterrupted + "]"; } } diff --git a/src/main/java/dev/louis/nebula/api/spell/SpellType.java b/src/main/java/dev/louis/nebula/api/spell/SpellType.java index 253f93a..475dc14 100644 --- a/src/main/java/dev/louis/nebula/api/spell/SpellType.java +++ b/src/main/java/dev/louis/nebula/api/spell/SpellType.java @@ -18,21 +18,20 @@ public class SpellType { public static final SimpleRegistry> REGISTRY = FabricRegistryBuilder.createSimple(REGISTRY_KEY).attribute(RegistryAttribute.SYNCED).buildAndRegister(); - private final SpellFactory factory; + private final SpellFactory spellFactory; private final int manaCost; - private final boolean allowsMultipleCasts; - private final boolean needLearning; - private final Castability castability; + private final boolean allowsParallelCasts; + private final boolean needsLearning; @ApiStatus.Internal - public SpellType(SpellFactory factory, int manaCost, boolean allowsMultipleCasts, boolean needLearning, Castability castability) { - this.factory = factory; + public SpellType(SpellFactory spellFactory, int manaCost, boolean allowsParallelCasts, boolean needsLearning) { + this.spellFactory = spellFactory; this.manaCost = manaCost; - this.allowsMultipleCasts = allowsMultipleCasts; - this.needLearning = needLearning; - this.castability = castability; + this.allowsParallelCasts = allowsParallelCasts; + this.needsLearning = needsLearning; } + @ApiStatus.Internal public static void init() { } @@ -52,40 +51,49 @@ public Identifier getId() { * This should be used to check if the player can cast the spell. */ public boolean isCastable(PlayerEntity player) { - return castability.isCastable(this, player); + return player.getSpellManager().isCastable(this); } - public boolean allowsMultipleCasts() { - return allowsMultipleCasts; + /** + * Utility method for checking if the spell has been learned by the given player. + * @param player Player to check. + * @return If the spell has been learned. + */ + public boolean isLearnedBy(PlayerEntity player) { + return player.getSpellManager().hasLearned(this); } - public boolean needsLearning() { - return needLearning; + public boolean allowsParallelCasts() { + return allowsParallelCasts; } - public boolean hasLearned(PlayerEntity player) { - return player.getSpellManager().hasLearned(this); + public boolean needsLearning() { + return needsLearning; } public int getManaCost() { return manaCost; } - public T create() { - return this.factory.create(this); + public T create(PlayerEntity caster) { + return this.spellFactory.create(this, caster); } @Override public String toString() { - return this.getClass().getSimpleName() + "{id=" + this.getId() + ", manaCost=" + this.getManaCost() + "}"; + return "SpellType{" + + "spellFactory=" + spellFactory + + ", manaCost=" + manaCost + + ", allowsParallelCasts=" + allowsParallelCasts + + ", needLearning=" + needsLearning + + '}'; } public static class Builder { private final SpellFactory factory; private final int manaCost; - private boolean allowsMultipleCasts; + private boolean allowParallelCast; private boolean needsLearning = true; - private Castability castability = Castability.DEFAULT; private Builder(SpellFactory factory, int manaCost) { this.factory = factory; @@ -101,7 +109,7 @@ public static Builder create(SpellFactory factory, int m * That means that a spell could be cast while it is already ticking */ public Builder parallelCast() { - this.allowsMultipleCasts = true; + this.allowParallelCast = true; return this; } @@ -113,41 +121,18 @@ public Builder needsLearning(boolean needsLearning) { return this; } - public Builder castability(Castability castability) { - this.castability = castability; - return this; - } - public SpellType build() { return new SpellType<>( this.factory, this.manaCost, - this.allowsMultipleCasts, - this.needsLearning, - this.castability + this.allowParallelCast, + this.needsLearning ); } } @FunctionalInterface public interface SpellFactory { - T create(SpellType spellType); - } - - @FunctionalInterface - public interface Castability { - Castability ALWAYS = (spellType, player) -> true; - Castability DEFAULT = (spellType, player) -> player.getManaManager().isCastable(spellType) && player.getSpellManager().isCastable(spellType); - Castability NEVER = (spellType, player) -> false; - - boolean isCastable(SpellType spellType, PlayerEntity player); - - default Castability and(Castability other) { - return (spellType, player) -> this.isCastable(spellType, player) && other.isCastable(spellType, player); - } - - default Castability or(Castability other) { - return (spellType, player) -> this.isCastable(spellType, player) || other.isCastable(spellType, player); - } + T create(SpellType spellType, PlayerEntity caster); } } diff --git a/src/main/java/dev/louis/nebula/api/spell/entity/SpellEntity.java b/src/main/java/dev/louis/nebula/api/spell/entity/SpellEntity.java deleted file mode 100644 index cd7163b..0000000 --- a/src/main/java/dev/louis/nebula/api/spell/entity/SpellEntity.java +++ /dev/null @@ -1,95 +0,0 @@ -package dev.louis.nebula.api.spell.entity; - -import dev.louis.nebula.api.spell.Spell; -import net.minecraft.entity.Entity; -import net.minecraft.entity.EntityType; -import net.minecraft.entity.data.DataTracker; -import net.minecraft.entity.data.TrackedData; -import net.minecraft.nbt.NbtCompound; -import net.minecraft.world.World; - -import java.util.Optional; - -/** - * An Entity that holds a Spell. Saving is disabled by default. - * This class can be extended to implement complex Logic for spells. - *

- * The Entity will not be removed when the spell is stopped.
- * This needs to be done by the spell a good place to do this is {@link Spell#onEnd()} - *

- * @param The Spell that is being represented. - */ -public abstract class SpellEntity extends Entity { - protected static final TrackedData> SPELL = DataTracker.registerData(SpellEntity.class, Spell.OPTIONAL_SPELL); - - public SpellEntity(EntityType type, World world) { - super(type, world); - } - - @Override - protected void initDataTracker() { - this.dataTracker.startTracking(SPELL, Optional.empty()); - } - - @Override - public void baseTick() { - if(shouldDiscardWithSpell() && (this.getSpell().isEmpty() || this.getSpell().get().hasEnded())) { - this.remove(RemovalReason.DISCARDED); - return; - } - super.baseTick(); - } - - /** - * Replaces the current spell with the given spell. - * This syncs the spell to the client. Regardless of the current state of the TrackedData. - * @param spell The spell to set. If the spell is null, the spell will be empty. - */ - public void setSpell(T spell) { - //We always force set as the Spell is mutable and setting is the only way to force a sync. - this.dataTracker.set(SPELL, Optional.ofNullable(spell), true); - } - - /** - * Syncs the spell to the client. - * This needs to be done manually because the spell is mutable. - */ - public void syncSpell() { - this.dataTracker.set(SPELL, this.dataTracker.get(SPELL), true); - } - - public Optional getSpell() { - //noinspection unchecked - return (Optional) this.dataTracker.get(SPELL); - } - - public boolean shouldDiscardWithSpell() { - return true; - } - - /** - * SpellEntity does not save to disk by default. - * Still call super as future Versions might implement logic here. - */ - @Override - protected void readCustomDataFromNbt(NbtCompound nbt) { - - } - - /** - * SpellEntity does not save to disk by default. - * Still call super as future Versions might implement logic here. - */ - @Override - protected void writeCustomDataToNbt(NbtCompound nbt) { - - } - - /** - * SpellEntity does not save to disk by default. - */ - @Override - public boolean shouldSave() { - return false; - } -} diff --git a/src/main/java/dev/louis/nebula/command/NebulaCommand.java b/src/main/java/dev/louis/nebula/command/NebulaCommand.java index 8089bcf..6520ab1 100644 --- a/src/main/java/dev/louis/nebula/command/NebulaCommand.java +++ b/src/main/java/dev/louis/nebula/command/NebulaCommand.java @@ -9,10 +9,13 @@ import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.text.Text; +import java.util.Collection; +import java.util.List; + import static com.mojang.brigadier.arguments.IntegerArgumentType.getInteger; import static com.mojang.brigadier.arguments.IntegerArgumentType.integer; -import static net.minecraft.command.argument.EntityArgumentType.getPlayer; -import static net.minecraft.command.argument.EntityArgumentType.player; +import static net.minecraft.command.argument.EntityArgumentType.getPlayers; +import static net.minecraft.command.argument.EntityArgumentType.players; import static net.minecraft.server.command.CommandManager.argument; import static net.minecraft.server.command.CommandManager.literal; @@ -22,51 +25,65 @@ public static void init() { } private static void register(CommandDispatcher dispatcher, CommandRegistryAccess commandRegistryAccess, CommandManager.RegistrationEnvironment registrationEnvironment) { - var command = literal("nebula").requires(source -> source.hasPermissionLevel(4)); - var getManaCommand = literal("getPlayerMana").executes(context -> getMana(context.getSource())); - var getManaWithPlayerCommand = argument("player", player()) - .executes(ctx -> getMana(ctx.getSource(), getPlayer(ctx, "player"))); - var setManaCommand = literal("setPlayerMana") - .then(argument("player", player()) - .then(argument("mana", integer(0)) - .executes(context -> setMana(context.getSource(), getPlayer(context, "player"), getInteger(context, "mana"))))); - - getManaCommand.then(getManaWithPlayerCommand); - command.then(getManaCommand); - command.then(setManaCommand); var learnSpellCommand = literal("learnSpell"); SpellType.REGISTRY.forEach(spellType -> { + if (!spellType.needsLearning()) return; learnSpellCommand.then(CommandManager.literal(spellType.getId().toString()).executes(context -> { if(context.getSource().isExecutedByPlayer()) { - context.getSource().getPlayer().getSpellManager().learnSpell(spellType); + learnSpell(context.getSource(), spellType); } return 0; })); }); + var command = literal("nebula").requires(source -> source.hasPermissionLevel(4)) + .then(literal("getMana") + .executes(context -> getMana(context.getSource())) + .then(argument("players", players()) + .executes(context -> getMana(context.getSource(), getPlayers(context, "players"))))) + .then(literal("setMana") + .then(argument("players", players()) + .then(argument("mana", integer(0)) + .executes(context -> setMana( + context.getSource(), + getPlayers(context, "players"), + getInteger(context, "mana")))))) + .then(learnSpellCommand); + command.then(learnSpellCommand); dispatcher.register(command); } - private static int setMana(ServerCommandSource source, ServerPlayerEntity player, int mana) { - if(source.getPlayer() != null) { + private static int setMana(ServerCommandSource source, Collection players, int mana) { + for (ServerPlayerEntity player : players) { player.getManaManager().setMana(mana); source.sendMessage(Text.of(player.getName().getString() + " now has " + player.getManaManager().getMana() + " Mana.")); } + return 1; } private static int getMana(ServerCommandSource source) { if(source.getPlayer() != null) { - source.sendMessage(Text.of(String.valueOf(source.getPlayer().getManaManager().getMana()))); + return getMana(source, List.of(source.getPlayer())); + } + return 0; + } + + private static int getMana(ServerCommandSource source, Collection players) { + for (ServerPlayerEntity player : players) { + source.sendMessage(Text.of(player.getName().getString() + " has " + source.getPlayer().getManaManager().getMana() + " mana.")); } return 1; } - private static int getMana(ServerCommandSource source, ServerPlayerEntity player) { - source.sendMessage(Text.of(String.valueOf(player.getManaManager().getMana()))); + private static int learnSpell(ServerCommandSource source, SpellType spellType) { + if(source.getPlayer() != null) { + source.getPlayer().getSpellManager().learnSpell(spellType); + source.sendMessage(Text.of("Learned spell " + spellType.getId())); + } return 1; } } diff --git a/src/main/java/dev/louis/nebula/NebulaManager.java b/src/main/java/dev/louis/nebula/manager/NebulaManager.java similarity index 81% rename from src/main/java/dev/louis/nebula/NebulaManager.java rename to src/main/java/dev/louis/nebula/manager/NebulaManager.java index 4661c93..05bec12 100644 --- a/src/main/java/dev/louis/nebula/NebulaManager.java +++ b/src/main/java/dev/louis/nebula/manager/NebulaManager.java @@ -1,5 +1,6 @@ -package dev.louis.nebula; +package dev.louis.nebula.manager; +import dev.louis.nebula.Nebula; import dev.louis.nebula.api.manager.mana.ManaManager; import dev.louis.nebula.api.manager.mana.entrypoint.RegisterManaManagerEntrypoint; import dev.louis.nebula.api.manager.mana.registerable.ManaManagerRegistrableView; @@ -8,11 +9,6 @@ import dev.louis.nebula.api.manager.spell.registerable.SpellManagerRegistrableView; import dev.louis.nebula.manager.mana.NebulaManaManager; import dev.louis.nebula.manager.spell.NebulaSpellManager; -import dev.louis.nebula.networking.SyncManaS2CPacket; -import dev.louis.nebula.networking.UpdateSpellCastabilityS2CPacket; -import net.fabricmc.api.EnvType; -import net.fabricmc.api.Environment; -import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking; import net.fabricmc.loader.api.FabricLoader; import net.fabricmc.loader.api.ModContainer; import net.fabricmc.loader.api.entrypoint.EntrypointContainer; @@ -28,19 +24,17 @@ public class NebulaManager implements ManaManagerRegistrableView, SpellManagerRe private static RegisterManaManagerEntrypoint manaManagerEntrypoint; private static ModContainer manaManagerMod; private static ManaManager.Factory manaManagerFactory; - private static Runnable manaPacketRegisterer = () -> manaManagerEntrypoint.registerManaPacketReceiver(); private static RegisterSpellManagerEntrypoint spellManagerEntrypoint; private static ModContainer spellManagerMod; private static SpellManager.Factory spellManagerFactory; - private static Runnable spellPacketRegisterer = () -> spellManagerEntrypoint.registerSpellPacketReceiver(); private NebulaManager() {} public static void init() { - if(NebulaManager.isLocked) throw new IllegalStateException("Registration of Managers is locked!"); + if (NebulaManager.isLocked) throw new IllegalStateException("Registration of Managers is locked!"); NebulaManager nebulaManager = new NebulaManager(); nebulaManager.runEntrypointsOrThrow(); nebulaManager.lock(); @@ -64,17 +58,13 @@ public static SpellManager createSpellManager(PlayerEntity player) { } public void lock() { - if(spellManagerFactory == null) { + if (spellManagerFactory == null) { registerSpellManager(NebulaSpellManager::new); spellManagerMod = FabricLoader.getInstance().getModContainer(Nebula.MOD_ID).orElseThrow(); - spellPacketRegisterer = () -> - ClientPlayNetworking.registerGlobalReceiver(SyncManaS2CPacket.TYPE, NebulaManaManager::receiveSync); } - if(manaManagerFactory == null) { + if (manaManagerFactory == null) { registerManaManager(NebulaManaManager::new); - manaPacketRegisterer = () -> - ClientPlayNetworking.registerGlobalReceiver(UpdateSpellCastabilityS2CPacket.TYPE, NebulaSpellManager::receiveSync); manaManagerMod = FabricLoader.getInstance().getModContainer(Nebula.MOD_ID).orElseThrow(); } @@ -147,17 +137,15 @@ private void printInfo() { Nebula.LOGGER.info("SpellManager is registered by: " + NebulaManager.spellManagerMod.getMetadata().getName()); } - private static T getFirstOrNull(List list) { - return list.isEmpty() ? null : list.get(0); + public static ModContainer getManaManagerMod() { + return manaManagerMod; } - @Environment(EnvType.CLIENT) - public static void registerPacketReceivers() { - if(!NebulaManager.isLocked) { - throw new IllegalStateException("NebulaManager is not locked yet!"); - } - NebulaManager.manaPacketRegisterer.run(); - NebulaManager.spellPacketRegisterer.run(); + public static ModContainer getSpellManagerMod() { + return spellManagerMod; + } + private static T getFirstOrNull(List list) { + return list.isEmpty() ? null : list.get(0); } } diff --git a/src/main/java/dev/louis/nebula/manager/mana/NebulaManaManager.java b/src/main/java/dev/louis/nebula/manager/mana/NebulaManaManager.java index 83bff36..6477e3d 100644 --- a/src/main/java/dev/louis/nebula/manager/mana/NebulaManaManager.java +++ b/src/main/java/dev/louis/nebula/manager/mana/NebulaManaManager.java @@ -29,7 +29,7 @@ public NebulaManaManager(PlayerEntity player) { @Override public void tick() { - if(this.dirty) { + if (this.dirty) { this.sendSync(); this.dirty = false; } @@ -47,7 +47,7 @@ public void setMana(int mana) { public void setMana(int mana, boolean syncToClient) { this.mana = Math.max(Math.min(mana, this.getMaxMana()), 0); - if(syncToClient) this.markDirty(); + if (syncToClient) this.markDirty(); } @Override @@ -60,11 +60,6 @@ public void drainMana(int mana) { this.setMana(this.getMana() - mana); } - @Override - public void drainMana(SpellType spellType) { - this.drainMana(spellType.getManaCost()); - } - @Override public int getMaxMana() { return 20; @@ -76,7 +71,7 @@ public boolean hasEnoughMana(int mana) { } @Override - public boolean isCastable(SpellType spellType) { + public boolean hasEnoughMana(SpellType spellType) { return this.hasEnoughMana(spellType.getManaCost()); } diff --git a/src/main/java/dev/louis/nebula/manager/spell/NebulaSpellManager.java b/src/main/java/dev/louis/nebula/manager/spell/NebulaSpellManager.java index 6981437..230525f 100644 --- a/src/main/java/dev/louis/nebula/manager/spell/NebulaSpellManager.java +++ b/src/main/java/dev/louis/nebula/manager/spell/NebulaSpellManager.java @@ -43,14 +43,15 @@ public NebulaSpellManager(PlayerEntity player) { public void tick() { this.activeSpells.removeIf(spell -> { boolean shouldStop = spell.shouldStop(); - if(shouldStop) spell.onEnd(); + if (shouldStop) spell.finish(); return shouldStop; }); - for (Spell tickingSpell : this.activeSpells) { - tickingSpell.baseTick(); + for (Spell spell : this.activeSpells) { + spell.age++; + spell.tick(); } - if(dirty) this.sendSync(); + if (dirty) this.sendSync(); } @Override @@ -61,29 +62,20 @@ public Collection> getLearnedSpells() { @Override public boolean learnSpell(SpellType spellType) { boolean shouldSync = this.learnedSpells.add(spellType); - if(shouldSync) this.markDirty(); - return true; + if (shouldSync) this.markDirty(); + return shouldSync; } @Override public boolean forgetSpell(SpellType spellType) { boolean shouldSync = this.learnedSpells.remove(spellType); - if(shouldSync) this.markDirty(); - return true; - } - - /** - * This Method does not return an unmodifiable set. - * So that it could theoretically be modified. - */ - protected Set> getCastableSpells() { - return learnedSpells; + if (shouldSync) this.markDirty(); + return shouldSync; } @Override public boolean cast(SpellType spellType) { - var spell = spellType.create(); - spell.setCaster(this.player); + var spell = spellType.create(this.player); return this.cast(spell); } @@ -91,14 +83,14 @@ public boolean cast(SpellType spellType) { public boolean cast(Spell spell) { this.ensurePlayerEqualsCaster(spell); this.ensureSpellIsNotAlreadyActive(spell); - if(SpellCastCallback.EVENT.invoker().interact(this.player, spell) != ActionResult.PASS) return false; - if(spell.isCastable()) { - if(this.isServer()) { + if (SpellCastCallback.EVENT.invoker().interact(this.player, spell) != ActionResult.PASS) return false; + if (spell.isCastable()) { + if (this.isServer()) { spell.applyCost(); spell.cast(); this.activeSpells.add(spell); } else { - ClientPlayNetworking.send(new SpellCastC2SPacket(spell)); + ClientPlayNetworking.send(new SpellCastC2SPacket(spell.getType())); } return true; } @@ -116,7 +108,7 @@ public void onDeath(DamageSource damageSource) { @Override public boolean isCastable(SpellType spellType) { - return this.player.isAlive() && (!spellType.needsLearning() || this.hasLearned(spellType)) && (spellType.allowsMultipleCasts() || !player.getSpellManager().isSpellTypeActive(spellType)); + return this.player.isAlive() && player.getManaManager().hasEnoughMana(spellType) && (!spellType.needsLearning() || this.hasLearned(spellType)) && (spellType.allowsParallelCasts() || !player.getSpellManager().isSpellTypeActive(spellType)); } public void markDirty() { @@ -131,12 +123,12 @@ public Collection getActiveSpells() { @Override public boolean isSpellTypeActive(SpellType spellType) { return this.activeSpells.stream().anyMatch(spell -> spell.getType().equals(spellType)); - }; + } @Override public boolean isSpellActive(Spell spell) { return this.activeSpells.contains(spell); - }; + } @Override public boolean hasLearned(SpellType spellType) { @@ -145,7 +137,7 @@ public boolean hasLearned(SpellType spellType) { @Override public boolean sendSync() { - if(this.player instanceof ServerPlayerEntity serverPlayerEntity && serverPlayerEntity.networkHandler != null) { + if (this.player instanceof ServerPlayerEntity serverPlayerEntity && serverPlayerEntity.networkHandler != null) { Map, Boolean> castableSpells = new HashMap<>(); SpellType.REGISTRY.forEach(spellType -> castableSpells.put(spellType, this.hasLearned(spellType))); ServerPlayNetworking.send(serverPlayerEntity, new UpdateSpellCastabilityS2CPacket(castableSpells)); @@ -170,9 +162,9 @@ public static boolean receiveSync(UpdateSpellCastabilityS2CPacket packet, Client @Override public void writeNbt(NbtCompound nbt) { NbtList nbtList = new NbtList(); - for (SpellType spell : getCastableSpells()) { + for (SpellType spellType : this.getLearnedSpells()) { NbtCompound nbtCompound = new NbtCompound(); - nbtCompound.putString(SPELL_NBT_KEY, spell.getId().toString()); + nbtCompound.putString(SPELL_NBT_KEY, spellType.getId().toString()); nbtList.add(nbtCompound); } @@ -184,7 +176,7 @@ public void writeNbt(NbtCompound nbt) { @Override public void readNbt(NbtCompound nbt) { NbtList nbtList = (NbtList) nbt.getCompound(Nebula.MOD_ID).get(SPELLS_NBT_KEY); - if(nbtList == null)return; + if (nbtList == null) return; for (int x = 0; x < nbtList.size(); ++x) { NbtCompound nbtCompound = nbtList.getCompound(x); Identifier spell = new Identifier(nbtCompound.getString(SPELL_NBT_KEY)); @@ -198,7 +190,6 @@ public SpellManager setPlayer(PlayerEntity player) { return this; } - private void ensureSpellIsNotAlreadyActive(Spell spell) { if(this.activeSpells.contains(spell)) { throw new IllegalStateException("Spell " + spell.getType() + " is already ticking!"); diff --git a/src/main/java/dev/louis/nebula/mixin/DebugHudMixin.java b/src/main/java/dev/louis/nebula/mixin/DebugHudMixin.java new file mode 100644 index 0000000..1b1b2bb --- /dev/null +++ b/src/main/java/dev/louis/nebula/mixin/DebugHudMixin.java @@ -0,0 +1,23 @@ +package dev.louis.nebula.mixin; + +import com.llamalad7.mixinextras.injector.ModifyReturnValue; +import dev.louis.nebula.manager.NebulaManager; +import net.minecraft.client.gui.hud.DebugHud; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; + +import java.util.List; + +@Mixin(DebugHud.class) +public class DebugHudMixin { + + @ModifyReturnValue( + at = @At("RETURN"), + method = "getLeftText" + ) + protected List getLeftText(List original) { + original.add("[Nebula] Mana Manager Mod: " + NebulaManager.getManaManagerMod().getMetadata().getName()); + original.add("[Nebula] Spell Manager Mod: " + NebulaManager.getSpellManagerMod().getMetadata().getName()); + return original; + } +} diff --git a/src/main/java/dev/louis/nebula/mixin/PlayerMixin.java b/src/main/java/dev/louis/nebula/mixin/PlayerMixin.java index 5458c0e..67b6261 100644 --- a/src/main/java/dev/louis/nebula/mixin/PlayerMixin.java +++ b/src/main/java/dev/louis/nebula/mixin/PlayerMixin.java @@ -1,9 +1,9 @@ package dev.louis.nebula.mixin; -import dev.louis.nebula.NebulaManager; import dev.louis.nebula.api.NebulaPlayer; import dev.louis.nebula.api.manager.mana.ManaManager; import dev.louis.nebula.api.manager.spell.SpellManager; +import dev.louis.nebula.manager.NebulaManager; import net.minecraft.entity.EntityType; import net.minecraft.entity.LivingEntity; import net.minecraft.entity.damage.DamageSource; diff --git a/src/main/java/dev/louis/nebula/networking/SpellCastC2SPacket.java b/src/main/java/dev/louis/nebula/networking/SpellCastC2SPacket.java index 8cd053a..4a7f586 100644 --- a/src/main/java/dev/louis/nebula/networking/SpellCastC2SPacket.java +++ b/src/main/java/dev/louis/nebula/networking/SpellCastC2SPacket.java @@ -1,7 +1,6 @@ package dev.louis.nebula.networking; import dev.louis.nebula.Nebula; -import dev.louis.nebula.api.spell.Spell; import dev.louis.nebula.api.spell.SpellType; import net.fabricmc.fabric.api.networking.v1.FabricPacket; import net.fabricmc.fabric.api.networking.v1.PacketSender; @@ -13,21 +12,23 @@ /** * Not a FabricPacket because of Restriction in the api. */ -public record SpellCastC2SPacket(Spell spell) implements FabricPacket { - public static final Identifier ID = new Identifier(Nebula.MOD_ID, "spellcast"); +public class SpellCastC2SPacket implements FabricPacket { + private static final Identifier ID = new Identifier(Nebula.MOD_ID, "spellcast"); public static final PacketType TYPE = PacketType.create(ID, SpellCastC2SPacket::read); + public final SpellType spellType; + + public SpellCastC2SPacket(SpellType spellType) { + this.spellType = spellType; + } public static SpellCastC2SPacket read(PacketByteBuf buf) { SpellType spellType = buf.readRegistryValue(SpellType.REGISTRY); - if(spellType == null) throw new IllegalStateException("Spell type not found in registry"); - Spell spell = spellType.create(); - spell.readBuf(buf); - return new SpellCastC2SPacket(spell); + if (spellType == null) throw new IllegalStateException("Spell type not found in registry"); + return new SpellCastC2SPacket(spellType); } public void write(PacketByteBuf buf) { - buf.writeRegistryValue(SpellType.REGISTRY, spell.getType()); - spell.writeBuf(buf); + buf.writeRegistryValue(SpellType.REGISTRY, spellType); } @Override @@ -36,10 +37,13 @@ public PacketType getType() { } public static void receive(SpellCastC2SPacket packet, ServerPlayerEntity player, PacketSender responseSender) { - var spell = packet.spell(); - spell.setCaster(player); - player.server.executeSync(() -> { - player.getSpellManager().cast(spell); - }); + player.server.executeSync(() -> player.getSpellManager().cast(packet.spellType)); + } + + @Override + public String toString() { + return "SpellCastC2SPacket[" + + "spellType=" + spellType + ']'; } + } diff --git a/src/main/resources/Nebula.mixins.json b/src/main/resources/Nebula.mixins.json index 9ad8dfb..4edddf7 100644 --- a/src/main/resources/Nebula.mixins.json +++ b/src/main/resources/Nebula.mixins.json @@ -10,7 +10,8 @@ "client": [ "ClientPlayerEntityAccessor", "ClientPlayerEntityMixin", - "ClientPlayNetworkHandlerMixin" + "ClientPlayNetworkHandlerMixin", + "DebugHudMixin" ], "injectors": { "defaultRequire": 1