diff --git a/src/main/java/com/thebrokenrail/sorcerycraft/block/CastingTableBlock.java b/src/main/java/com/thebrokenrail/sorcerycraft/block/CastingTableBlock.java index 4c22b7f..60cbb12 100644 --- a/src/main/java/com/thebrokenrail/sorcerycraft/block/CastingTableBlock.java +++ b/src/main/java/com/thebrokenrail/sorcerycraft/block/CastingTableBlock.java @@ -2,6 +2,7 @@ package com.thebrokenrail.sorcerycraft.block; import com.thebrokenrail.sorcerycraft.SorceryCraft; import com.thebrokenrail.sorcerycraft.gui.CastingTableScreenHandler; +import com.thebrokenrail.sorcerycraft.spell.util.SpellServerPlayerEntity; import net.fabricmc.fabric.api.block.FabricBlockSettings; import net.fabricmc.fabric.api.container.ContainerProviderRegistry; import net.minecraft.block.Block; @@ -36,6 +37,11 @@ public class CastingTableBlock extends Block { @Override public NamedScreenHandlerFactory createScreenHandlerFactory(BlockState state, World world, BlockPos pos) { - return new SimpleNamedScreenHandlerFactory((i, playerInventory, playerEntity) -> new CastingTableScreenHandler(i, playerInventory, ScreenHandlerContext.create(world, pos)), new TranslatableText("container." + SorceryCraft.NAMESPACE + ".casting_table")); + return new SimpleNamedScreenHandlerFactory((i, playerInventory, playerEntity) -> { + if (!playerEntity.getEntityWorld().isClient()) { + ((SpellServerPlayerEntity) playerEntity).sync(); + } + return new CastingTableScreenHandler(i, playerInventory, ScreenHandlerContext.create(world, pos)); + }, new TranslatableText("container." + SorceryCraft.NAMESPACE + ".casting_table")); } } diff --git a/src/main/java/com/thebrokenrail/sorcerycraft/command/SpellCommand.java b/src/main/java/com/thebrokenrail/sorcerycraft/command/SpellCommand.java index 3bc703b..f8c5e8c 100644 --- a/src/main/java/com/thebrokenrail/sorcerycraft/command/SpellCommand.java +++ b/src/main/java/com/thebrokenrail/sorcerycraft/command/SpellCommand.java @@ -27,36 +27,41 @@ public class SpellCommand { public static void register(CommandDispatcher dispatcher) { dispatcher.register(CommandManager.literal("spell") - .requires(source -> source.hasPermissionLevel(4)) + .requires(source -> source.hasPermissionLevel(2)) .then(CommandManager.literal("list") .then(CommandManager.argument("player", EntityArgumentType.players()) .executes(ctx -> { + int i = 0; Collection players = EntityArgumentType.getPlayers(ctx, "player"); for (PlayerEntity player : players) { SpellPlayerEntity spellPlayer = (SpellPlayerEntity) player; Map spellMap = spellPlayer.getDiscoveredSpells(); ctx.getSource().sendFeedback(new TranslatableText("command." + SorceryCraft.NAMESPACE + ".spell.listing_spells", player.getDisplayName(), Texts.join(spellMap.entrySet(), spell -> SpellHelper.getTranslatedSpell(spell.getKey(), spell.getValue()))), false); + i++; } - return 0; + return i; }) ) ) .then(CommandManager.literal("forget") .then(CommandManager.argument("player", EntityArgumentType.players()) .executes(ctx -> { + int i = 0; Collection players = EntityArgumentType.getPlayers(ctx, "player"); for (PlayerEntity player : players) { SpellPlayerEntity spellPlayer = (SpellPlayerEntity) player; Map spells = spellPlayer.getDiscoveredSpells(); for (Map.Entry entry : spells.entrySet()) { ctx.getSource().sendFeedback(new TranslatableText("command." + SorceryCraft.NAMESPACE + ".spell.forgotten_spell", player.getDisplayName(), SpellHelper.getTranslatedSpellChat(entry.getKey(), entry.getValue())), true); + i++; } spellPlayer.setDiscoveredSpells(new HashMap<>()); } - return 1; + return i; }) .then(CommandManager.argument("spell", SpellArgumentType.spell()) .executes(ctx -> { + int i = 0; Collection players = EntityArgumentType.getPlayers(ctx, "player"); for (PlayerEntity player : players) { Identifier spell = SpellArgumentType.getSpell(ctx, "spell"); @@ -65,10 +70,11 @@ public class SpellCommand { if (spells.containsKey(spell)) { ctx.getSource().sendFeedback(new TranslatableText("command." + SorceryCraft.NAMESPACE + ".spell.forgotten_spell", player.getDisplayName(), SpellHelper.getTranslatedSpellChat(spell, spells.get(spell))), true); spells.remove(spell); + i++; } spellPlayer.setDiscoveredSpells(spells); } - return 1; + return i; }) ) ) @@ -76,29 +82,33 @@ public class SpellCommand { .then(CommandManager.literal("discover") .then(CommandManager.argument("player", EntityArgumentType.players()) .executes(ctx -> { + int i = 0; Collection players = EntityArgumentType.getPlayers(ctx, "player"); for (PlayerEntity player : players) { Map spellMap = new HashMap<>(); Spell[] maxSpells = SpellRegistry.getMaxSpells(); for (Spell spell : maxSpells) { spellMap.put(spell.getID(), spell.getLevel()); + i++; } SpellHelper.learnSpells(player, spellMap); } - return 1; + return i; }) .then(CommandManager.argument("spell", SpellArgumentType.spell()) .then(CommandManager.argument("level", IntegerArgumentType.integer()) .executes(ctx -> { + int i = 0; Collection players = EntityArgumentType.getPlayers(ctx, "player"); for (PlayerEntity player : players) { Identifier spell = SpellArgumentType.getSpell(ctx, "spell"); int level = IntegerArgumentType.getInteger(ctx, "level") - 1; Map spellMap = new HashMap<>(); spellMap.put(spell, level); + i++; SpellHelper.learnSpells(player, spellMap); } - return 1; + return i; }) ) ) @@ -109,6 +119,7 @@ public class SpellCommand { .then(CommandManager.argument("spell", SpellArgumentType.spell()) .then(CommandManager.argument("level", IntegerArgumentType.integer()) .executes(ctx -> { + int i = 0; Collection players = EntityArgumentType.getPlayers(ctx, "player"); for (PlayerEntity player : players) { Identifier spell = SpellArgumentType.getSpell(ctx, "spell"); @@ -122,11 +133,12 @@ public class SpellCommand { Map spellMap = SpellHelper.getSpells(stack); spellMap.put(spell, level); + i++; SpellHelper.setSpells(stack, spellMap); ctx.getSource().sendFeedback(new TranslatableText("command." + SorceryCraft.NAMESPACE + ".spell.applied_spell", SpellHelper.getTranslatedSpell(spell, level)), true); } - return 1; + return i; }) ) ) @@ -136,6 +148,7 @@ public class SpellCommand { .then(CommandManager.argument("player", EntityArgumentType.players()) .then(CommandManager.argument("spell", SpellArgumentType.spell()) .executes(ctx -> { + int i = 0; Collection players = EntityArgumentType.getPlayers(ctx, "player"); for (PlayerEntity player : players) { Identifier spell = SpellArgumentType.getSpell(ctx, "spell"); @@ -150,10 +163,11 @@ public class SpellCommand { if (spellMap.containsKey(spell)) { ctx.getSource().sendFeedback(new TranslatableText("command." + SorceryCraft.NAMESPACE + ".spell.removed_spell", SpellHelper.getTranslatedSpell(spell, spellMap.get(spell))), true); spellMap.remove(spell); + i++; } SpellHelper.setSpells(stack, spellMap); } - return 1; + return i; }) ) ) diff --git a/src/main/java/com/thebrokenrail/sorcerycraft/gui/CastingTableScreenHandler.java b/src/main/java/com/thebrokenrail/sorcerycraft/gui/CastingTableScreenHandler.java index 9010756..432795f 100644 --- a/src/main/java/com/thebrokenrail/sorcerycraft/gui/CastingTableScreenHandler.java +++ b/src/main/java/com/thebrokenrail/sorcerycraft/gui/CastingTableScreenHandler.java @@ -28,7 +28,7 @@ import java.util.function.BiConsumer; public class CastingTableScreenHandler extends ScreenHandler { private final Inventory inventory; private final Inventory result; - private final Spell[] spells; + private Spell[] spells = new Spell[0]; private final ScreenHandlerContext context; private int index = 0; @@ -44,21 +44,7 @@ public class CastingTableScreenHandler extends ScreenHandler { context = blockContext; result = new CraftingResultInventory(); - if (playerInventory.player.isCreative() ? SorceryCraft.getConfig().limitCastingTable.creative : SorceryCraft.getConfig().limitCastingTable.survival) { - SpellPlayerEntity spellPlayer = (SpellPlayerEntity) playerInventory.player; - Map spellsMap = spellPlayer.getDiscoveredSpells(); - List spellsArray = new ArrayList<>(); - - Spell[] allSpells = SpellRegistry.getSpells(); - for (Spell spell : allSpells) { - if (spellsMap.containsKey(spell.getID()) && spellsMap.get(spell.getID()) >= spell.getLevel()) { - spellsArray.add(spell); - } - } - spells = spellsArray.toArray(new Spell[0]); - } else { - spells = SpellRegistry.getSpells(); - } + setSpells(playerInventory.player); addSlot(new Slot(inventory, 0, 136, 37) { @Override @@ -123,6 +109,26 @@ public class CastingTableScreenHandler extends ScreenHandler { } } + public void setSpells(PlayerEntity player) { + if (player.isCreative() ? SorceryCraft.getConfig().limitCastingTable.creative : SorceryCraft.getConfig().limitCastingTable.survival) { + SpellPlayerEntity spellPlayer = (SpellPlayerEntity) player; + Map spellsMap = spellPlayer.getDiscoveredSpells(); + List spellsArray = new ArrayList<>(); + + Spell[] allSpells = SpellRegistry.getSpells(); + for (Spell spell : allSpells) { + if (spellsMap.containsKey(spell.getID()) && spellsMap.get(spell.getID()) >= spell.getLevel()) { + spellsArray.add(spell); + } + } + spells = spellsArray.toArray(new Spell[0]); + } else { + spells = SpellRegistry.getSpells(); + } + index = 0; + onContentChanged(inventory); + } + public boolean canTakeResult(PlayerEntity playerEntity) { return playerEntity.isCreative() || playerEntity.experienceLevel >= spells[index].getXPCost(); } diff --git a/src/main/java/com/thebrokenrail/sorcerycraft/mixin/MixinPlayerEntity.java b/src/main/java/com/thebrokenrail/sorcerycraft/mixin/MixinPlayerEntity.java index d1f2628..b1880a6 100644 --- a/src/main/java/com/thebrokenrail/sorcerycraft/mixin/MixinPlayerEntity.java +++ b/src/main/java/com/thebrokenrail/sorcerycraft/mixin/MixinPlayerEntity.java @@ -4,8 +4,10 @@ import com.thebrokenrail.sorcerycraft.spell.util.SpellHelper; import com.thebrokenrail.sorcerycraft.spell.util.SpellPlayerEntity; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.nbt.CompoundTag; +import net.minecraft.screen.ScreenHandler; import net.minecraft.util.Identifier; import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; @@ -16,6 +18,7 @@ import java.util.Map; @SuppressWarnings("unused") @Mixin(PlayerEntity.class) public class MixinPlayerEntity implements SpellPlayerEntity { + @Shadow public ScreenHandler currentScreenHandler; // Namespace Fields private Map sorceryCraftDiscoveredSpells = new HashMap<>(); diff --git a/src/main/java/com/thebrokenrail/sorcerycraft/mixin/MixinServerPlayerEntity.java b/src/main/java/com/thebrokenrail/sorcerycraft/mixin/MixinServerPlayerEntity.java index bd5e0c4..493abbe 100644 --- a/src/main/java/com/thebrokenrail/sorcerycraft/mixin/MixinServerPlayerEntity.java +++ b/src/main/java/com/thebrokenrail/sorcerycraft/mixin/MixinServerPlayerEntity.java @@ -1,18 +1,24 @@ package com.thebrokenrail.sorcerycraft.mixin; +import com.thebrokenrail.sorcerycraft.gui.CastingTableScreenHandler; import com.thebrokenrail.sorcerycraft.packet.UpdateKnownSpellsS2CPacket; import com.thebrokenrail.sorcerycraft.spell.util.SpellHelper; import com.thebrokenrail.sorcerycraft.spell.util.SpellPlayerEntity; +import com.thebrokenrail.sorcerycraft.spell.util.SpellServerPlayerEntity; +import net.minecraft.entity.player.PlayerEntity; import net.minecraft.nbt.CompoundTag; import net.minecraft.server.network.ServerPlayerEntity; +import net.minecraft.util.Identifier; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import java.util.Map; + @SuppressWarnings("unused") @Mixin(ServerPlayerEntity.class) -public abstract class MixinServerPlayerEntity implements SpellPlayerEntity { +public abstract class MixinServerPlayerEntity extends MixinPlayerEntity implements SpellServerPlayerEntity { @Inject(at = @At("HEAD"), method = "copyFrom") public void copyFrom(ServerPlayerEntity oldPlayer, boolean alive, CallbackInfo info) { SpellPlayerEntity oldSpellPlayer = (SpellPlayerEntity) oldPlayer; @@ -21,11 +27,22 @@ public abstract class MixinServerPlayerEntity implements SpellPlayerEntity { newSpellPlayer.setDiscoveredSpells(oldSpellPlayer.getDiscoveredSpells()); } - @Inject(at = @At("HEAD"), method = "playerTick") - public void playerTick(CallbackInfo info) { + @Override + public void setDiscoveredSpells(Map spells) { + super.setDiscoveredSpells(spells); + sync(); + } + + @Override + public void sync() { CompoundTag tag = new CompoundTag(); tag.put(SpellHelper.SPELL_TAG, SpellHelper.createSpellsTag(getDiscoveredSpells())); //noinspection ConstantConditions UpdateKnownSpellsS2CPacket.send((ServerPlayerEntity) (Object) this, tag); + + if (currentScreenHandler instanceof CastingTableScreenHandler) { + //noinspection ConstantConditions + ((CastingTableScreenHandler) currentScreenHandler).setSpells((PlayerEntity) (Object) this); + } } } \ No newline at end of file diff --git a/src/main/java/com/thebrokenrail/sorcerycraft/packet/UpdateKnownSpellsS2CPacket.java b/src/main/java/com/thebrokenrail/sorcerycraft/packet/UpdateKnownSpellsS2CPacket.java index 5ff6e8b..24ca673 100644 --- a/src/main/java/com/thebrokenrail/sorcerycraft/packet/UpdateKnownSpellsS2CPacket.java +++ b/src/main/java/com/thebrokenrail/sorcerycraft/packet/UpdateKnownSpellsS2CPacket.java @@ -1,6 +1,7 @@ package com.thebrokenrail.sorcerycraft.packet; import com.thebrokenrail.sorcerycraft.SorceryCraft; +import com.thebrokenrail.sorcerycraft.gui.CastingTableScreenHandler; import com.thebrokenrail.sorcerycraft.spell.util.SpellPlayerEntity; import com.thebrokenrail.sorcerycraft.spell.util.SpellHelper; import io.netty.buffer.Unpooled; @@ -17,6 +18,9 @@ public class UpdateKnownSpellsS2CPacket { if (context.getPlayer() != null) { SpellPlayerEntity spellPlayer = (SpellPlayerEntity) context.getPlayer(); spellPlayer.setDiscoveredSpells(SpellHelper.getSpells(tag)); + if (context.getPlayer().currentScreenHandler instanceof CastingTableScreenHandler) { + ((CastingTableScreenHandler) context.getPlayer().currentScreenHandler).setSpells(context.getPlayer()); + } } } diff --git a/src/main/java/com/thebrokenrail/sorcerycraft/spell/util/SpellServerPlayerEntity.java b/src/main/java/com/thebrokenrail/sorcerycraft/spell/util/SpellServerPlayerEntity.java new file mode 100644 index 0000000..6663bfd --- /dev/null +++ b/src/main/java/com/thebrokenrail/sorcerycraft/spell/util/SpellServerPlayerEntity.java @@ -0,0 +1,5 @@ +package com.thebrokenrail.sorcerycraft.spell.util; + +public interface SpellServerPlayerEntity extends SpellPlayerEntity { + void sync(); +}