diff --git a/src/main/java/com/atsuishio/superbwarfare/ModUtils.java b/src/main/java/com/atsuishio/superbwarfare/ModUtils.java index fbb3b1ea9..1cb500437 100644 --- a/src/main/java/com/atsuishio/superbwarfare/ModUtils.java +++ b/src/main/java/com/atsuishio/superbwarfare/ModUtils.java @@ -1,11 +1,11 @@ package com.atsuishio.superbwarfare; -import com.atsuishio.superbwarfare.capability.CapabilityHandler; import com.atsuishio.superbwarfare.component.ModDataComponents; import com.atsuishio.superbwarfare.config.ClientConfig; import com.atsuishio.superbwarfare.config.CommonConfig; import com.atsuishio.superbwarfare.config.ServerConfig; import com.atsuishio.superbwarfare.init.*; +import com.atsuishio.superbwarfare.network.NetworkRegistry; import net.minecraft.resources.ResourceLocation; import net.neoforged.bus.api.IEventBus; import net.neoforged.bus.api.SubscribeEvent; @@ -56,7 +56,7 @@ public class ModUtils { // bus.addListener(this::onCommonSetup); // bus.addListener(this::onClientSetup); - CapabilityHandler.register(bus); + bus.addListener(NetworkRegistry::register); NeoForge.EVENT_BUS.register(this); } diff --git a/src/main/java/com/atsuishio/superbwarfare/block/JumpPadBlock.java b/src/main/java/com/atsuishio/superbwarfare/block/JumpPadBlock.java index 70d685947..c3cb294a4 100644 --- a/src/main/java/com/atsuishio/superbwarfare/block/JumpPadBlock.java +++ b/src/main/java/com/atsuishio/superbwarfare/block/JumpPadBlock.java @@ -1,5 +1,6 @@ package com.atsuishio.superbwarfare.block; +import com.atsuishio.superbwarfare.capability.ModCapabilities; import com.atsuishio.superbwarfare.init.ModSounds; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; @@ -122,10 +123,10 @@ public class JumpPadBlock extends Block { level.playLocalSound(pos.getX(), pos.getY(), pos.getZ(), ModSounds.JUMP.get(), SoundSource.BLOCKS, 1, 1, false); } - // TODO capability -// entity.getCapability(ModVariables.PLAYER_VARIABLES_CAPABILITY, null).ifPresent(capability -> { -// capability.playerDoubleJump = true; -// capability.syncPlayerVariables(entity); -// }); + var capability = entity.getCapability(ModCapabilities.PLAYER_VARIABLE); + if (capability != null) { + capability.playerDoubleJump = true; + capability.syncPlayerVariables(entity); + } } } diff --git a/src/main/java/com/atsuishio/superbwarfare/capability/CapabilityHandler.java b/src/main/java/com/atsuishio/superbwarfare/capability/CapabilityHandler.java deleted file mode 100644 index 452395e1b..000000000 --- a/src/main/java/com/atsuishio/superbwarfare/capability/CapabilityHandler.java +++ /dev/null @@ -1,29 +0,0 @@ -package com.atsuishio.superbwarfare.capability; - -import net.minecraft.core.registries.BuiltInRegistries; -import net.minecraft.world.entity.EntityType; -import net.minecraft.world.entity.player.Player; -import net.neoforged.bus.api.IEventBus; -import net.neoforged.neoforge.capabilities.RegisterCapabilitiesEvent; - -public class CapabilityHandler { - - private static final CapabilityHandler INSTANCE = new CapabilityHandler(); - - public static void register(IEventBus bus) { - bus.addListener(INSTANCE::registerCapabilities); - } - - public void registerCapabilities(RegisterCapabilitiesEvent event) { - for (EntityType entityType : BuiltInRegistries.ENTITY_TYPE) { - event.registerEntity(ModCapabilities.LASER_CAPABILITY, entityType, - (entity, ctx) -> { - if (entity instanceof Player) { - return new LaserCapability.LaserCapabilityImpl(); - } - return null; - }); - } - } - -} diff --git a/src/main/java/com/atsuishio/superbwarfare/capability/LaserCapability.java b/src/main/java/com/atsuishio/superbwarfare/capability/LaserCapability.java deleted file mode 100644 index f228bcd8e..000000000 --- a/src/main/java/com/atsuishio/superbwarfare/capability/LaserCapability.java +++ /dev/null @@ -1,100 +0,0 @@ -package com.atsuishio.superbwarfare.capability; - -import com.atsuishio.superbwarfare.ModUtils; -import net.minecraft.core.HolderLookup; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.world.entity.player.Player; -import net.neoforged.neoforge.capabilities.ICapabilityProvider; -import net.neoforged.neoforge.common.util.INBTSerializable; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.jetbrains.annotations.UnknownNullability; - -public class LaserCapability { - - public static ResourceLocation ID = ModUtils.loc("laser_capability"); - - public interface ILaserCapability extends INBTSerializable { - - void init(LaserHandler handler); - - void start(); - - void tick(); - - void stop(); - - void end(); - - } - - public static class LaserCapabilityImpl implements ILaserCapability { - - public LaserHandler laserHandler; - - @Override - public void init(LaserHandler handler) { - this.laserHandler = handler; - } - - @Override - public void start() { - this.laserHandler.start(); - } - - @Override - public void tick() { - } - - @Override - public void stop() { - if (this.laserHandler != null) { - this.laserHandler.stop(); - } - } - - @Override - public void end() { - if (this.laserHandler != null) { - this.laserHandler.end(); - } - } - - @Override - public @UnknownNullability CompoundTag serializeNBT(HolderLookup.@NotNull Provider provider) { - CompoundTag tag = new CompoundTag(); - if (this.laserHandler != null) { - tag.put("Laser", this.laserHandler.writeNBT()); - } - return tag; - } - - @Override - public void deserializeNBT(HolderLookup.@NotNull Provider provider, @NotNull CompoundTag compoundTag) { - if (compoundTag.contains("Laser") && this.laserHandler != null) { - this.laserHandler.readNBT(compoundTag.getCompound("Laser")); - } - } - } - - public static class LaserCapabilityProvider implements ICapabilityProvider, INBTSerializable { - - private final LaserCapabilityImpl instance = new LaserCapabilityImpl(); - - @Override - public @Nullable ILaserCapability getCapability(@NotNull Player object, Void context) { - return object.getCapability(ModCapabilities.LASER_CAPABILITY, context); - } - - @Override - public @UnknownNullability CompoundTag serializeNBT(HolderLookup.@NotNull Provider provider) { - return instance.serializeNBT(provider); - } - - @Override - public void deserializeNBT(HolderLookup.@NotNull Provider provider, @NotNull CompoundTag nbt) { - instance.deserializeNBT(provider, nbt); - } - } -} diff --git a/src/main/java/com/atsuishio/superbwarfare/capability/ModCapabilities.java b/src/main/java/com/atsuishio/superbwarfare/capability/ModCapabilities.java index f7a6cd558..1d7a487e8 100644 --- a/src/main/java/com/atsuishio/superbwarfare/capability/ModCapabilities.java +++ b/src/main/java/com/atsuishio/superbwarfare/capability/ModCapabilities.java @@ -1,10 +1,13 @@ package com.atsuishio.superbwarfare.capability; import com.atsuishio.superbwarfare.ModUtils; +import com.atsuishio.superbwarfare.capability.laser.LaserCapability; +import com.atsuishio.superbwarfare.capability.player.PlayerVariable; import net.neoforged.neoforge.capabilities.EntityCapability; public class ModCapabilities { - public static final EntityCapability LASER_CAPABILITY = EntityCapability.createVoid(ModUtils.loc("laser_capability"), LaserCapability.ILaserCapability.class); + public static final EntityCapability LASER_CAPABILITY = EntityCapability.createVoid(ModUtils.loc("laser_capability"), LaserCapability.class); + public static final EntityCapability PLAYER_VARIABLE = EntityCapability.createVoid(ModUtils.loc("player_variable"), PlayerVariable.class); } diff --git a/src/main/java/com/atsuishio/superbwarfare/capability/energy/ItemEnergyProvider.java b/src/main/java/com/atsuishio/superbwarfare/capability/energy/ItemEnergyProvider.java index 4ddd907bb..df6911d0e 100644 --- a/src/main/java/com/atsuishio/superbwarfare/capability/energy/ItemEnergyProvider.java +++ b/src/main/java/com/atsuishio/superbwarfare/capability/energy/ItemEnergyProvider.java @@ -1,18 +1,22 @@ package com.atsuishio.superbwarfare.capability.energy; import net.minecraft.world.item.ItemStack; -import net.neoforged.neoforge.capabilities.Capabilities; import net.neoforged.neoforge.capabilities.ICapabilityProvider; +import net.neoforged.neoforge.energy.EnergyStorage; import net.neoforged.neoforge.energy.IEnergyStorage; import org.jetbrains.annotations.NotNull; public class ItemEnergyProvider implements ICapabilityProvider { + private final ItemStack stack; + private final EnergyStorage energyStorage; public ItemEnergyProvider(ItemStack stack, int energyCapacity) { + this.stack = stack; + this.energyStorage = new EnergyStorage(energyCapacity); } @Override public @org.jetbrains.annotations.Nullable IEnergyStorage getCapability(@NotNull ItemStack object, Void context) { - return object.getCapability(Capabilities.EnergyStorage.ITEM); + return energyStorage; } } diff --git a/src/main/java/com/atsuishio/superbwarfare/capability/laser/LaserCapability.java b/src/main/java/com/atsuishio/superbwarfare/capability/laser/LaserCapability.java new file mode 100644 index 000000000..5125fbd0c --- /dev/null +++ b/src/main/java/com/atsuishio/superbwarfare/capability/laser/LaserCapability.java @@ -0,0 +1,51 @@ +package com.atsuishio.superbwarfare.capability.laser; + +import net.minecraft.core.HolderLookup; +import net.minecraft.nbt.CompoundTag; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.UnknownNullability; + + +public class LaserCapability { + + + public LaserHandler laserHandler; + + public void init(LaserHandler handler) { + this.laserHandler = handler; + } + + public void start() { + this.laserHandler.start(); + } + + public void tick() { + } + + public void stop() { + if (this.laserHandler != null) { + this.laserHandler.stop(); + } + } + + public void end() { + if (this.laserHandler != null) { + this.laserHandler.end(); + } + } + + public @UnknownNullability CompoundTag serializeNBT(HolderLookup.@NotNull Provider provider) { + CompoundTag tag = new CompoundTag(); + if (this.laserHandler != null) { + tag.put("Laser", this.laserHandler.writeNBT()); + } + return tag; + } + + public void deserializeNBT(HolderLookup.@NotNull Provider provider, @NotNull CompoundTag compoundTag) { + if (compoundTag.contains("Laser") && this.laserHandler != null) { + this.laserHandler.readNBT(compoundTag.getCompound("Laser")); + } + } + +} diff --git a/src/main/java/com/atsuishio/superbwarfare/capability/laser/LaserCapabilityProvider.java b/src/main/java/com/atsuishio/superbwarfare/capability/laser/LaserCapabilityProvider.java new file mode 100644 index 000000000..ce1363064 --- /dev/null +++ b/src/main/java/com/atsuishio/superbwarfare/capability/laser/LaserCapabilityProvider.java @@ -0,0 +1,42 @@ +package com.atsuishio.superbwarfare.capability.laser; + +import com.atsuishio.superbwarfare.ModUtils; +import com.atsuishio.superbwarfare.capability.ModCapabilities; +import net.minecraft.core.HolderLookup; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.player.Player; +import net.neoforged.bus.api.SubscribeEvent; +import net.neoforged.fml.common.EventBusSubscriber; +import net.neoforged.neoforge.capabilities.ICapabilityProvider; +import net.neoforged.neoforge.capabilities.RegisterCapabilitiesEvent; +import net.neoforged.neoforge.common.util.INBTSerializable; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.annotations.UnknownNullability; + +@EventBusSubscriber(modid = ModUtils.MODID, bus = EventBusSubscriber.Bus.MOD) +public class LaserCapabilityProvider implements ICapabilityProvider, INBTSerializable { + + private final LaserCapability instance = new LaserCapability(); + + @Override + public @Nullable LaserCapability getCapability(@NotNull Player object, Void context) { + return object.getCapability(ModCapabilities.LASER_CAPABILITY, context); + } + + @Override + public @UnknownNullability CompoundTag serializeNBT(HolderLookup.@NotNull Provider provider) { + return instance.serializeNBT(provider); + } + + @Override + public void deserializeNBT(HolderLookup.@NotNull Provider provider, @NotNull CompoundTag nbt) { + instance.deserializeNBT(provider, nbt); + } + + @SubscribeEvent + public static void registerCapabilities(RegisterCapabilitiesEvent event) { + event.registerEntity(ModCapabilities.LASER_CAPABILITY, EntityType.PLAYER, new LaserCapabilityProvider()); + } +} \ No newline at end of file diff --git a/src/main/java/com/atsuishio/superbwarfare/capability/LaserHandler.java b/src/main/java/com/atsuishio/superbwarfare/capability/laser/LaserHandler.java similarity index 97% rename from src/main/java/com/atsuishio/superbwarfare/capability/LaserHandler.java rename to src/main/java/com/atsuishio/superbwarfare/capability/laser/LaserHandler.java index fdff3308b..2c6fe8791 100644 --- a/src/main/java/com/atsuishio/superbwarfare/capability/LaserHandler.java +++ b/src/main/java/com/atsuishio/superbwarfare/capability/laser/LaserHandler.java @@ -1,4 +1,4 @@ -package com.atsuishio.superbwarfare.capability; +package com.atsuishio.superbwarfare.capability.laser; import com.atsuishio.superbwarfare.entity.projectile.AbstractLaserEntity; import net.minecraft.nbt.CompoundTag; diff --git a/src/main/java/com/atsuishio/superbwarfare/capability/player/ModVariables.java b/src/main/java/com/atsuishio/superbwarfare/capability/player/ModVariables.java new file mode 100644 index 000000000..671cc96cc --- /dev/null +++ b/src/main/java/com/atsuishio/superbwarfare/capability/player/ModVariables.java @@ -0,0 +1,54 @@ +package com.atsuishio.superbwarfare.capability.player; + +import com.atsuishio.superbwarfare.ModUtils; +import com.atsuishio.superbwarfare.network.message.SavedDataSyncMessage; +import net.minecraft.core.HolderLookup; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.LevelAccessor; +import net.minecraft.world.level.saveddata.SavedData; +import net.neoforged.neoforge.network.PacketDistributor; +import org.jetbrains.annotations.NotNull; + + +public class ModVariables { + + // 这玩意有用吗? + + public static class WorldVariables extends SavedData { + public static final String DATA_NAME = ModUtils.MODID + "_world_variables"; + + public static WorldVariables load(CompoundTag tag, HolderLookup.Provider provider) { + WorldVariables data = new WorldVariables(); + data.read(tag); + return data; + } + + public void read(CompoundTag nbt) { + } + + @Override + public @NotNull CompoundTag save(@NotNull CompoundTag tag, HolderLookup.@NotNull Provider registries) { + return tag; + } + + public void syncData(LevelAccessor world) { + this.setDirty(); + if (world instanceof Level level && !level.isClientSide()) { + PacketDistributor.sendToAllPlayers(new SavedDataSyncMessage(1, this, null)); + } + } + + public static WorldVariables clientSide = new WorldVariables(); + + public static WorldVariables get(LevelAccessor world) { + if (world instanceof ServerLevel level) + return level.getDataStorage().computeIfAbsent(new Factory<>( + WorldVariables::new, WorldVariables::load, null + ), DATA_NAME); + return clientSide; + } + } + +} diff --git a/src/main/java/com/atsuishio/superbwarfare/capability/player/PlayerVariable.java b/src/main/java/com/atsuishio/superbwarfare/capability/player/PlayerVariable.java new file mode 100644 index 000000000..02de3da5f --- /dev/null +++ b/src/main/java/com/atsuishio/superbwarfare/capability/player/PlayerVariable.java @@ -0,0 +1,167 @@ +package com.atsuishio.superbwarfare.capability.player; + +import com.atsuishio.superbwarfare.ModUtils; +import com.atsuishio.superbwarfare.capability.ModCapabilities; +import com.atsuishio.superbwarfare.network.message.PlayerVariablesSyncMessage; +import com.atsuishio.superbwarfare.network.message.SavedDataSyncMessage; +import com.atsuishio.superbwarfare.tools.AmmoType; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.Tag; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.level.saveddata.SavedData; +import net.neoforged.bus.api.SubscribeEvent; +import net.neoforged.fml.common.EventBusSubscriber; +import net.neoforged.neoforge.event.entity.player.PlayerEvent; +import net.neoforged.neoforge.network.PacketDistributor; + +@EventBusSubscriber(modid = ModUtils.MODID) +public class PlayerVariable { + public boolean zoom = false; + public boolean holdFire = false; + public int rifleAmmo = 0; + public int handgunAmmo = 0; + public int shotgunAmmo = 0; + public int sniperAmmo = 0; + public int heavyAmmo = 0; + public boolean bowPullHold = false; + public boolean bowPull = false; + public boolean playerDoubleJump = false; + public boolean tacticalSprint = false; + public int tacticalSprintTime = 600; + public boolean tacticalSprintExhaustion = false; + public boolean breath = false; + public int breathTime = 160; + public boolean breathExhaustion = false; + public boolean edit = false; + + public void syncPlayerVariables(Entity entity) { + if (entity instanceof ServerPlayer) { + PacketDistributor.sendToAllPlayers(new PlayerVariablesSyncMessage(entity.getId(), this.writeToNBT())); + } + } + + public CompoundTag writeToNBT() { + CompoundTag nbt = new CompoundTag(); + nbt.putBoolean("Zoom", zoom); + nbt.putBoolean("HoldFire", holdFire); + + for (var type : AmmoType.values()) { + type.set(nbt, type.get(this)); + } + + nbt.putBoolean("BowPullHold", bowPullHold); + nbt.putBoolean("BowPull", bowPull); + nbt.putBoolean("DoubleJump", playerDoubleJump); + nbt.putBoolean("TacticalSprint", tacticalSprint); + nbt.putInt("TacticalSprintTime", tacticalSprintTime); + nbt.putBoolean("TacticalSprintExhaustion", tacticalSprintExhaustion); + nbt.putBoolean("Breath", breath); + nbt.putInt("BreathTime", breathTime); + nbt.putBoolean("BreathExhaustion", breathExhaustion); + nbt.putBoolean("EditMode", edit); + + return nbt; + } + + public PlayerVariable readFromNBT(Tag tag) { + CompoundTag nbt = (CompoundTag) tag; + + zoom = nbt.getBoolean("Zoom"); + holdFire = nbt.getBoolean("HoldFire"); + + for (var type : AmmoType.values()) { + type.set(this, type.get(nbt)); + } + + bowPullHold = nbt.getBoolean("BowPullHold"); + bowPull = nbt.getBoolean("BowPull"); + playerDoubleJump = nbt.getBoolean("DoubleJump"); + tacticalSprint = nbt.getBoolean("TacticalSprint"); + tacticalSprintTime = nbt.getInt("TacticalSprintTime"); + tacticalSprintExhaustion = nbt.getBoolean("TacticalSprintExhaustion"); + breath = nbt.getBoolean("Breath"); + breathTime = nbt.getInt("BreathTime"); + breathExhaustion = nbt.getBoolean("BreathExhaustion"); + edit = nbt.getBoolean("EditMode"); + + return this; + } + + @SubscribeEvent + public static void onPlayerLoggedInSyncPlayerVariables(PlayerEvent.PlayerLoggedInEvent event) { + if (event.getEntity().level().isClientSide()) return; + + var player = event.getEntity(); + var cap = player.getCapability(ModCapabilities.PLAYER_VARIABLE, null); + if (cap != null) cap.syncPlayerVariables(player); + } + + @SubscribeEvent + public static void onPlayerRespawnedSyncPlayerVariables(PlayerEvent.PlayerRespawnEvent event) { + if (event.getEntity().level().isClientSide()) return; + + var player = event.getEntity(); + var cap = player.getCapability(ModCapabilities.PLAYER_VARIABLE, null); + if (cap != null) cap.syncPlayerVariables(player); + } + + @SubscribeEvent + public static void onPlayerChangedDimensionSyncPlayerVariables(PlayerEvent.PlayerChangedDimensionEvent event) { + if (event.getEntity().level().isClientSide()) return; + + var player = event.getEntity(); + var cap = player.getCapability(ModCapabilities.PLAYER_VARIABLE, null); + if (cap != null) cap.syncPlayerVariables(player); + } + + @SubscribeEvent + public static void clonePlayer(PlayerEvent.Clone event) { + event.getOriginal().revive(); + var original = event.getOriginal().getCapability(ModCapabilities.PLAYER_VARIABLE, null); + var clone = event.getEntity().getCapability(ModCapabilities.PLAYER_VARIABLE, null); + if (clone == null || original == null) return; + + clone.zoom = original.zoom; + clone.holdFire = original.holdFire; + clone.rifleAmmo = original.rifleAmmo; + clone.handgunAmmo = original.handgunAmmo; + clone.shotgunAmmo = original.shotgunAmmo; + clone.sniperAmmo = original.sniperAmmo; + clone.heavyAmmo = original.heavyAmmo; + clone.bowPullHold = original.bowPullHold; + clone.bowPull = original.bowPull; + clone.playerDoubleJump = original.playerDoubleJump; + clone.tacticalSprint = original.tacticalSprint; + clone.tacticalSprintTime = original.tacticalSprintTime; + clone.tacticalSprintExhaustion = original.tacticalSprintExhaustion; + clone.breath = original.breath; + clone.breathTime = original.breathTime; + clone.breathExhaustion = original.breathExhaustion; + clone.edit = original.edit; + + if (event.getEntity().level().isClientSide()) return; + + var player = event.getEntity(); + var cap = player.getCapability(ModCapabilities.PLAYER_VARIABLE, null); + if (cap != null) cap.syncPlayerVariables(player); + } + + @SubscribeEvent + public static void onPlayerLoggedIn(PlayerEvent.PlayerLoggedInEvent event) { + if (event.getEntity().level().isClientSide()) return; + SavedData worldData = ModVariables.WorldVariables.get(event.getEntity().level()); + if (worldData != null) { + PacketDistributor.sendToPlayer((ServerPlayer) event.getEntity(), new SavedDataSyncMessage(1, worldData, null)); + } + } + + @SubscribeEvent + public static void onPlayerChangedDimension(PlayerEvent.PlayerChangedDimensionEvent event) { + if (event.getEntity().level().isClientSide()) return; + SavedData worldData = ModVariables.WorldVariables.get(event.getEntity().level()); + if (worldData != null) { + PacketDistributor.sendToPlayer((ServerPlayer) event.getEntity(), new SavedDataSyncMessage(1, worldData, null)); + } + } +} diff --git a/src/main/java/com/atsuishio/superbwarfare/capability/player/PlayerVariablesProvider.java b/src/main/java/com/atsuishio/superbwarfare/capability/player/PlayerVariablesProvider.java new file mode 100644 index 000000000..7c084fbff --- /dev/null +++ b/src/main/java/com/atsuishio/superbwarfare/capability/player/PlayerVariablesProvider.java @@ -0,0 +1,42 @@ +package com.atsuishio.superbwarfare.capability.player; + +import com.atsuishio.superbwarfare.ModUtils; +import com.atsuishio.superbwarfare.capability.ModCapabilities; +import net.minecraft.core.HolderLookup; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.player.Player; +import net.neoforged.bus.api.SubscribeEvent; +import net.neoforged.fml.common.EventBusSubscriber; +import net.neoforged.neoforge.capabilities.ICapabilityProvider; +import net.neoforged.neoforge.capabilities.RegisterCapabilitiesEvent; +import net.neoforged.neoforge.common.util.INBTSerializable; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.annotations.UnknownNullability; + +@EventBusSubscriber(modid = ModUtils.MODID, bus = EventBusSubscriber.Bus.MOD) +public class PlayerVariablesProvider implements ICapabilityProvider, INBTSerializable { + private final PlayerVariable playerVariables = new PlayerVariable(); + + @Override + public @Nullable PlayerVariable getCapability(@NotNull Player object, Void context) { + return playerVariables; + } + + @Override + public @UnknownNullability CompoundTag serializeNBT(HolderLookup.@NotNull Provider provider) { + return playerVariables.writeToNBT(); + } + + @Override + public void deserializeNBT(HolderLookup.@NotNull Provider provider, @NotNull CompoundTag nbt) { + playerVariables.readFromNBT(nbt); + } + + @SubscribeEvent + public static void init(RegisterCapabilitiesEvent event) { + event.registerEntity(ModCapabilities.PLAYER_VARIABLE, EntityType.PLAYER, new PlayerVariablesProvider()); + } + +} \ No newline at end of file diff --git a/src/main/java/com/atsuishio/superbwarfare/client/overlay/AmmoOverlay.java b/src/main/java/com/atsuishio/superbwarfare/client/overlay/AmmoOverlay.java new file mode 100644 index 000000000..5ec43d13a --- /dev/null +++ b/src/main/java/com/atsuishio/superbwarfare/client/overlay/AmmoOverlay.java @@ -0,0 +1,202 @@ +package com.atsuishio.superbwarfare.client.overlay; + +import com.atsuishio.superbwarfare.ModUtils; +import com.atsuishio.superbwarfare.capability.ModCapabilities; +import com.atsuishio.superbwarfare.component.ModDataComponents; +import com.atsuishio.superbwarfare.init.ModItems; +import com.atsuishio.superbwarfare.item.common.ammo.AmmoSupplierItem; +import com.atsuishio.superbwarfare.item.common.ammo.box.AmmoBoxInfo; +import com.atsuishio.superbwarfare.tools.AmmoType; +import com.atsuishio.superbwarfare.tools.animation.AnimationCurves; +import com.atsuishio.superbwarfare.tools.animation.AnimationTimer; +import com.atsuishio.superbwarfare.tools.animation.ValueAnimator; +import com.mojang.blaze3d.systems.RenderSystem; +import net.minecraft.client.Minecraft; +import net.minecraft.network.chat.Component; +import net.minecraft.util.FastColor; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.ItemStack; +import net.neoforged.api.distmarker.Dist; +import net.neoforged.bus.api.SubscribeEvent; +import net.neoforged.fml.common.EventBusSubscriber; +import net.neoforged.neoforge.client.event.RenderGuiEvent; + +@EventBusSubscriber(modid = ModUtils.MODID, value = Dist.CLIENT) +public class AmmoOverlay { + + private static final AnimationTimer ammoInfoTimer = new AnimationTimer(500, 2000) + .forwardAnimation(AnimationCurves.EASE_OUT_EXPO) + .backwardAnimation(AnimationCurves.EASE_IN_EXPO); + private static final AnimationTimer ammoBoxTimer = new AnimationTimer(500) + .forwardAnimation(AnimationCurves.EASE_OUT_EXPO) + .backwardAnimation(AnimationCurves.EASE_IN_EXPO); + + private static final ValueAnimator[] ammoCountAnimators = ValueAnimator.create( + AmmoType.values().length, 800, 0 + ); + private static final ValueAnimator[] ammoBoxAnimators = ValueAnimator.create( + AmmoType.values().length, 800, 0 + ); + + + /** + * 在手持弹药或弹药盒时,渲染玩家弹药总量信息 + */ + @SubscribeEvent + public static void renderAmmoInfo(RenderGuiEvent.Pre event) { + boolean startRenderingAmmoInfo = false; + Player player = Minecraft.getInstance().player; + if (player == null || player.isSpectator()) return; + + boolean isAmmoBox = false; + + // 动画计算 + var currentTime = System.currentTimeMillis(); + ItemStack stack = player.getMainHandItem(); + if ((stack.getItem() instanceof AmmoSupplierItem || stack.getItem() == ModItems.AMMO_BOX.get()) + // TODO vehicle +// && !(player.getVehicle() instanceof ArmedVehicleEntity vehicle && vehicle.banHand(player)) + ) { + // 刚拿出弹药物品时,视为开始弹药信息渲染 + startRenderingAmmoInfo = ammoInfoTimer.getProgress(currentTime) == 0; + ammoInfoTimer.forward(currentTime); + + if (stack.getItem() == ModItems.AMMO_BOX.get()) { + isAmmoBox = true; + ammoBoxTimer.forward(currentTime); + } else { + ammoBoxTimer.backward(currentTime); + } + } else { + ammoInfoTimer.backward(currentTime); + ammoBoxTimer.backward(currentTime); + } + if (!ammoInfoTimer.isForward() && ammoInfoTimer.finished(currentTime)) return; + + var poseStack = event.getGuiGraphics().pose(); + poseStack.pushPose(); + + int w = event.getGuiGraphics().guiWidth(); + int h = event.getGuiGraphics().guiHeight(); + + var ammoX = ammoInfoTimer.lerp(w + 120, (float) w / 2 + 40, currentTime); + final int fontHeight = 15; + var yOffset = (-h - AmmoType.values().length * fontHeight) / 2f; + + // 渲染总弹药数量 + var cap = player.getCapability(ModCapabilities.PLAYER_VARIABLE, null); + if (cap == null) return; + var font = Minecraft.getInstance().font; + + for (var type : AmmoType.values()) { + var index = type.ordinal(); + var ammoCount = type.get(cap); + var animator = ammoCountAnimators[index]; + + var boxAnimator = ammoBoxAnimators[index]; + var boxAmmoCount = boxAnimator.newValue(); + boolean boxAmmoSelected = false; + + if (isAmmoBox) { + var info = stack.get(ModDataComponents.AMMO_BOX_INFO); + if (info == null) info = new AmmoBoxInfo("All", false); + + var ammoBoxType = info.type(); + boxAmmoCount = type.get(stack); + if (ammoBoxType.equals("All") || ammoBoxType.equals(type.name)) { + boxAnimator.forward(currentTime); + boxAmmoSelected = true; + } else { + boxAnimator.reset(boxAmmoCount); + } + } + + // 首次开始渲染弹药信息时,记录弹药数量,便于后续播放动画 + if (startRenderingAmmoInfo) { + animator.reset(ammoCount); + animator.endForward(currentTime); + if (isAmmoBox) { + boxAnimator.reset(type.get(stack)); + boxAnimator.endForward(currentTime); + } + } + + int ammoAdd = Integer.compare(ammoCount, animator.oldValue()); + // 弹药数量变化时,更新并开始播放弹药数量更改动画 + animator.compareAndUpdate(ammoCount, () -> { + // 弹药数量变化时,开始播放弹药数量更改动画 + animator.beginForward(currentTime); + }); + + var progress = animator.getProgress(currentTime); + var ammoCountStr = Integer.toString( + Math.round(animator.lerp(animator.oldValue(), ammoCount, currentTime)) + ); + + // 弹药增加时,颜色由绿变白,否则由红变白 + var fontColor = FastColor.ARGB32.lerp(progress, switch (ammoAdd) { + case 1 -> 0xFF00FF00; + case -1 -> 0xFFFF0000; + default -> 0xFFFFFFFF; + }, 0xFFFFFFFF); + + RenderSystem.setShaderColor(1, 1, 1, ammoInfoTimer.lerp(0, 1, currentTime)); + + // 弹药数量 + event.getGuiGraphics().drawString( + font, + ammoCountStr, + ammoX + (30 - font.width(ammoCountStr)), + h + yOffset, + fontColor, + true + ); + + // 弹药类型 + event.getGuiGraphics().drawString( + font, + Component.translatable(type.translatableKey).getString(), + ammoX + 35, + h + yOffset, + fontColor, + true + ); + + // 弹药盒信息渲染 + RenderSystem.setShaderColor(1, 1, 1, ammoBoxTimer.lerp(0, 1, currentTime)); + var ammoBoxX = ammoBoxTimer.lerp(-30, (float) w / 2, currentTime); + + int ammoBoxAdd = Integer.compare(boxAmmoCount, boxAnimator.oldValue()); + boxAnimator.compareAndUpdate(boxAmmoCount, () -> boxAnimator.beginForward(currentTime)); + + // 选中时显示为黄色,否则为白色 + var targetColor = boxAmmoSelected ? 0xFFFFFF00 : 0xFFFFFFFF; + + var boxFontColor = FastColor.ARGB32.lerp(boxAnimator.getProgress(currentTime), + switch (ammoBoxAdd) { + case 1 -> 0xFF00FF00; + case -1 -> 0xFFFF0000; + default -> targetColor; + }, + targetColor + ); + + // 弹药盒内弹药数量 + event.getGuiGraphics().drawString( + Minecraft.getInstance().font, + Integer.toString( + Math.round(boxAnimator.lerp(boxAnimator.oldValue(), boxAmmoCount, currentTime)) + ), + ammoBoxX - 70, + h + yOffset, + boxFontColor, + true + ); + + yOffset += fontHeight; + } + + RenderSystem.setShaderColor(1, 1, 1, 1); + poseStack.popPose(); + } +} diff --git a/src/main/java/com/atsuishio/superbwarfare/component/ModDataComponents.java b/src/main/java/com/atsuishio/superbwarfare/component/ModDataComponents.java index 9365eaff8..cb79f2400 100644 --- a/src/main/java/com/atsuishio/superbwarfare/component/ModDataComponents.java +++ b/src/main/java/com/atsuishio/superbwarfare/component/ModDataComponents.java @@ -1,6 +1,8 @@ package com.atsuishio.superbwarfare.component; import com.atsuishio.superbwarfare.ModUtils; +import com.atsuishio.superbwarfare.item.common.ammo.box.AmmoBoxInfo; +import com.atsuishio.superbwarfare.tools.AmmoType; import com.mojang.serialization.Codec; import net.minecraft.core.BlockPos; import net.minecraft.core.component.DataComponentType; @@ -25,11 +27,20 @@ public class ModDataComponents { builder -> builder.persistent(Codec.INT) ); + public static final DeferredHolder, DataComponentType> AMMO_BOX_INFO = register( + "ammo_box_type", + builder -> builder.persistent(AmmoBoxInfo.CODEC) + ); + private static DeferredHolder, DataComponentType> register(String name, UnaryOperator> builderOperator) { return DATA_COMPONENT_TYPES.register(name, () -> builderOperator.apply(DataComponentType.builder()).build()); } public static void register(IEventBus eventBus) { + for (var type : AmmoType.values()) { + type.dataComponent = register("ammo_" + type.name.toLowerCase(), builder -> builder.persistent(Codec.INT)); + } + DATA_COMPONENT_TYPES.register(eventBus); } diff --git a/src/main/java/com/atsuishio/superbwarfare/init/ModItems.java b/src/main/java/com/atsuishio/superbwarfare/init/ModItems.java index c51aa84b0..561ab1f35 100644 --- a/src/main/java/com/atsuishio/superbwarfare/init/ModItems.java +++ b/src/main/java/com/atsuishio/superbwarfare/init/ModItems.java @@ -5,6 +5,9 @@ import com.atsuishio.superbwarfare.item.*; import com.atsuishio.superbwarfare.item.common.BlueprintItem; import com.atsuishio.superbwarfare.item.common.CannonShellItem; import com.atsuishio.superbwarfare.item.common.MaterialPack; +import com.atsuishio.superbwarfare.item.common.ammo.*; +import com.atsuishio.superbwarfare.item.common.ammo.box.AmmoBox; +import com.atsuishio.superbwarfare.tools.AmmoType; import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.core.registries.Registries; import net.minecraft.world.item.BlockItem; @@ -64,23 +67,23 @@ public class ModItems { */ public static final DeferredRegister AMMO = DeferredRegister.create(BuiltInRegistries.ITEM, ModUtils.MODID); - // public static final DeferredHolder HANDGUN_AMMO = AMMO.register("handgun_ammo", () -> new AmmoSupplierItem(AmmoType.HANDGUN, 1, new Item.Properties())); -// public static final DeferredHolder RIFLE_AMMO = AMMO.register("rifle_ammo", () -> new AmmoSupplierItem(AmmoType.RIFLE, 1, new Item.Properties())); -// public static final DeferredHolder SNIPER_AMMO = AMMO.register("sniper_ammo", () -> new AmmoSupplierItem(AmmoType.SNIPER, 1, new Item.Properties())); -// public static final DeferredHolder SHOTGUN_AMMO = AMMO.register("shotgun_ammo", () -> new AmmoSupplierItem(AmmoType.SHOTGUN, 1, new Item.Properties())); -// public static final DeferredHolder HEAVY_AMMO = AMMO.register("heavy_ammo", () -> new AmmoSupplierItem(AmmoType.HEAVY, 1, new Item.Properties())); -// public static final DeferredHolder HANDGUN_AMMO_BOX = AMMO.register("handgun_ammo_box", HandgunAmmoBox::new); -// public static final DeferredHolder RIFLE_AMMO_BOX = AMMO.register("rifle_ammo_box", RifleAmmoBox::new); -// public static final DeferredHolder SNIPER_AMMO_BOX = AMMO.register("sniper_ammo_box", SniperAmmoBox::new); -// public static final DeferredHolder SHOTGUN_AMMO_BOX = AMMO.register("shotgun_ammo_box", ShotgunAmmoBox::new); -// public static final DeferredHolder CREATIVE_AMMO_BOX = AMMO.register("creative_ammo_box", CreativeAmmoBox::new); -// public static final DeferredHolder AMMO_BOX = AMMO.register("ammo_box", AmmoBox::new); + public static final DeferredHolder HANDGUN_AMMO = AMMO.register("handgun_ammo", () -> new AmmoSupplierItem(AmmoType.HANDGUN, 1, new Item.Properties())); + public static final DeferredHolder RIFLE_AMMO = AMMO.register("rifle_ammo", () -> new AmmoSupplierItem(AmmoType.RIFLE, 1, new Item.Properties())); + public static final DeferredHolder SNIPER_AMMO = AMMO.register("sniper_ammo", () -> new AmmoSupplierItem(AmmoType.SNIPER, 1, new Item.Properties())); + public static final DeferredHolder SHOTGUN_AMMO = AMMO.register("shotgun_ammo", () -> new AmmoSupplierItem(AmmoType.SHOTGUN, 1, new Item.Properties())); + public static final DeferredHolder HEAVY_AMMO = AMMO.register("heavy_ammo", () -> new AmmoSupplierItem(AmmoType.HEAVY, 1, new Item.Properties())); + public static final DeferredHolder HANDGUN_AMMO_BOX = AMMO.register("handgun_ammo_box", HandgunAmmoBox::new); + public static final DeferredHolder RIFLE_AMMO_BOX = AMMO.register("rifle_ammo_box", RifleAmmoBox::new); + public static final DeferredHolder SNIPER_AMMO_BOX = AMMO.register("sniper_ammo_box", SniperAmmoBox::new); + public static final DeferredHolder SHOTGUN_AMMO_BOX = AMMO.register("shotgun_ammo_box", ShotgunAmmoBox::new); + public static final DeferredHolder CREATIVE_AMMO_BOX = AMMO.register("creative_ammo_box", CreativeAmmoBox::new); + public static final DeferredHolder AMMO_BOX = AMMO.register("ammo_box", AmmoBox::new); public static final DeferredHolder TASER_ELECTRODE = AMMO.register("taser_electrode", () -> new Item(new Item.Properties())); public static final DeferredHolder GRENADE_40MM = AMMO.register("grenade_40mm", () -> new Item(new Item.Properties())); public static final DeferredHolder JAVELIN_MISSILE = AMMO.register("javelin_missile", () -> new Item(new Item.Properties())); - // public static final DeferredHolder MORTAR_SHELL = AMMO.register("mortar_shell", MortarShell::new); -// public static final DeferredHolder POTION_MORTAR_SHELL = AMMO.register("potion_mortar_shell", PotionMortarShell::new); -// public static final DeferredHolder ROCKET = AMMO.register("rocket", Rocket::new); + public static final DeferredHolder MORTAR_SHELL = AMMO.register("mortar_shell", MortarShell::new); + public static final DeferredHolder POTION_MORTAR_SHELL = AMMO.register("potion_mortar_shell", PotionMortarShell::new); + public static final DeferredHolder ROCKET = AMMO.register("rocket", Rocket::new); // public static final DeferredHolder LUNGE_MINE = AMMO.register("lunge_mine", LungeMine::new); public static final DeferredHolder HE_5_INCHES = AMMO.register("he_5_inches", () -> new CannonShellItem(new Item.Properties().rarity(Rarity.RARE))); public static final DeferredHolder AP_5_INCHES = AMMO.register("ap_5_inches", () -> new CannonShellItem(new Item.Properties().rarity(Rarity.RARE))); @@ -116,7 +119,7 @@ public class ModItems { // public static final DeferredHolder KNIFE = ITEMS.register("knife", Knife::new); // public static final DeferredHolder HAMMER = ITEMS.register("hammer", Hammer::new); public static final DeferredHolder CROWBAR = ITEMS.register("crowbar", Crowbar::new); -// public static final DeferredHolder DEFUSER = ITEMS.register("defuser", Defuser::new); + // public static final DeferredHolder DEFUSER = ITEMS.register("defuser", Defuser::new); // public static final DeferredHolder ARMOR_PLATE = ITEMS.register("armor_plate", ArmorPlate::new); // // public static final DeferredHolder RU_HELMET_6B47 = ITEMS.register("ru_helmet_6b47", RuHelmet6b47::new); diff --git a/src/main/java/com/atsuishio/superbwarfare/init/ModTabs.java b/src/main/java/com/atsuishio/superbwarfare/init/ModTabs.java index 3b1f890cd..0413e7896 100644 --- a/src/main/java/com/atsuishio/superbwarfare/init/ModTabs.java +++ b/src/main/java/com/atsuishio/superbwarfare/init/ModTabs.java @@ -16,7 +16,7 @@ public class ModTabs { public static final DeferredRegister TABS = DeferredRegister.create(Registries.CREATIVE_MODE_TAB, ModUtils.MODID); -// public static final DeferredHolder GUN_TAB = TABS.register("guns", + // public static final DeferredHolder GUN_TAB = TABS.register("guns", // () -> CreativeModeTab.builder() // .title(Component.translatable("item_group.superbwarfare.guns")) // .icon(() -> new ItemStack(ModItems.TASER.get())) @@ -60,34 +60,34 @@ public class ModTabs { // ) // .build()); // -public static final DeferredHolder PERK_TAB = TABS.register("perk", - () -> CreativeModeTab.builder() - .title(Component.translatable("item_group.superbwarfare.perk")) - .icon(() -> new ItemStack(ModItems.AP_BULLET.get())) + public static final DeferredHolder PERK_TAB = TABS.register("perk", + () -> CreativeModeTab.builder() + .title(Component.translatable("item_group.superbwarfare.perk")) + .icon(() -> new ItemStack(ModItems.AP_BULLET.get())) // .withTabsBefore(GUN_TAB.getKey()) - .displayItems((param, output) -> ModItems.PERKS.getEntries().forEach(registryObject -> output.accept(registryObject.get()))) - .build()); -// -public static final DeferredHolder AMMO_TAB = TABS.register("ammo", - () -> CreativeModeTab.builder() - .title(Component.translatable("item_group.superbwarfare.ammo")) -// .icon(() -> new ItemStack(ModItems.SHOTGUN_AMMO_BOX.get())) - .withTabsBefore(PERK_TAB.getKey()) - .displayItems((param, output) -> { - ModItems.AMMO.getEntries().forEach(registryObject -> { -// if (registryObject.get() != ModItems.POTION_MORTAR_SHELL.get()) { -// output.accept(registryObject.get()); -// + .displayItems((param, output) -> ModItems.PERKS.getEntries().forEach(registryObject -> output.accept(registryObject.get()))) + .build()); + // + public static final DeferredHolder AMMO_TAB = TABS.register("ammo", + () -> CreativeModeTab.builder() + .title(Component.translatable("item_group.superbwarfare.ammo")) + .icon(() -> new ItemStack(ModItems.SHOTGUN_AMMO_BOX.get())) + .withTabsBefore(PERK_TAB.getKey()) + .displayItems((param, output) -> { + ModItems.AMMO.getEntries().forEach(registryObject -> { + if (registryObject.get() != ModItems.POTION_MORTAR_SHELL.get()) { + output.accept(registryObject.get()); + // if (registryObject.get() == ModItems.C4_BOMB.get()) { // output.accept(C4Bomb.makeInstance()); // } -// } - }); + } + }); // param.holders().lookup(Registries.POTION) // .ifPresent(potion -> generatePotionEffectTypes(output, potion, ModItems.POTION_MORTAR_SHELL.get())); - }) - .build()); + }) + .build()); public static final DeferredHolder ITEM_TAB = TABS.register("item", () -> CreativeModeTab.builder() diff --git a/src/main/java/com/atsuishio/superbwarfare/item/BeamTest.java b/src/main/java/com/atsuishio/superbwarfare/item/BeamTest.java index a42fddbba..9eeac7cad 100644 --- a/src/main/java/com/atsuishio/superbwarfare/item/BeamTest.java +++ b/src/main/java/com/atsuishio/superbwarfare/item/BeamTest.java @@ -1,7 +1,7 @@ package com.atsuishio.superbwarfare.item; -import com.atsuishio.superbwarfare.capability.LaserHandler; import com.atsuishio.superbwarfare.capability.ModCapabilities; +import com.atsuishio.superbwarfare.capability.laser.LaserHandler; import com.atsuishio.superbwarfare.entity.projectile.LaserEntity; import com.atsuishio.superbwarfare.init.ModSounds; import com.atsuishio.superbwarfare.tools.TraceTool; diff --git a/src/main/java/com/atsuishio/superbwarfare/item/common/ammo/AmmoSupplierItem.java b/src/main/java/com/atsuishio/superbwarfare/item/common/ammo/AmmoSupplierItem.java new file mode 100644 index 000000000..555ebc54b --- /dev/null +++ b/src/main/java/com/atsuishio/superbwarfare/item/common/ammo/AmmoSupplierItem.java @@ -0,0 +1,66 @@ +package com.atsuishio.superbwarfare.item.common.ammo; + +import com.atsuishio.superbwarfare.capability.ModCapabilities; +import com.atsuishio.superbwarfare.init.ModItems; +import com.atsuishio.superbwarfare.init.ModSounds; +import com.atsuishio.superbwarfare.tools.AmmoType; +import net.minecraft.ChatFormatting; +import net.minecraft.network.chat.Component; +import net.minecraft.sounds.SoundSource; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.InteractionResultHolder; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.TooltipFlag; +import net.minecraft.world.level.Level; +import org.jetbrains.annotations.NotNull; + +import java.util.List; + +public class AmmoSupplierItem extends Item { + + public final AmmoType type; + public final int ammoToAdd; + + public AmmoSupplierItem(AmmoType type, int ammoToAdd, Properties properties) { + super(properties); + this.type = type; + this.ammoToAdd = ammoToAdd; + } + + @Override + public void appendHoverText(@NotNull ItemStack stack, @NotNull TooltipContext context, List tooltipComponents, @NotNull TooltipFlag tooltipFlag) { + tooltipComponents.add(Component.translatable("des.superbwarfare.ammo_supplier").withStyle(ChatFormatting.AQUA)); + } + + @Override + public @NotNull InteractionResultHolder use(@NotNull Level level, Player player, @NotNull InteractionHand hand) { + ItemStack stack = player.getItemInHand(hand); + int count = stack.getCount(); + player.getCooldowns().addCooldown(this, 10); + + if (!player.isCreative()) { + stack.shrink(count); + } + + ItemStack offhandItem = player.getOffhandItem(); + + if (offhandItem.is(ModItems.AMMO_BOX.get())) { + this.type.add(offhandItem, ammoToAdd * count); + } else { + var capability = player.getCapability(ModCapabilities.PLAYER_VARIABLE, null); + + if (capability != null) { + this.type.add(capability, ammoToAdd * count); + capability.syncPlayerVariables(player); + } + } + + if (!level.isClientSide()) { + player.displayClientMessage(Component.translatable("item.superbwarfare.ammo_supplier.supply", Component.translatable(this.type.translatableKey), ammoToAdd * count), true); + level.playSound(null, player.blockPosition(), ModSounds.BULLET_SUPPLY.get(), SoundSource.PLAYERS, 1, 1); + } + return InteractionResultHolder.success(stack); + } +} diff --git a/src/main/java/com/atsuishio/superbwarfare/item/common/ammo/CannonShellItem.java b/src/main/java/com/atsuishio/superbwarfare/item/common/ammo/CannonShellItem.java new file mode 100644 index 000000000..5769c644e --- /dev/null +++ b/src/main/java/com/atsuishio/superbwarfare/item/common/ammo/CannonShellItem.java @@ -0,0 +1,10 @@ +package com.atsuishio.superbwarfare.item.common.ammo; + +import net.minecraft.world.item.Item; + +public class CannonShellItem extends Item { + + public CannonShellItem(Properties properties) { + super(properties); + } +} diff --git a/src/main/java/com/atsuishio/superbwarfare/item/common/ammo/CreativeAmmoBox.java b/src/main/java/com/atsuishio/superbwarfare/item/common/ammo/CreativeAmmoBox.java new file mode 100644 index 000000000..6bcf5ddc9 --- /dev/null +++ b/src/main/java/com/atsuishio/superbwarfare/item/common/ammo/CreativeAmmoBox.java @@ -0,0 +1,24 @@ +package com.atsuishio.superbwarfare.item.common.ammo; + +import net.minecraft.ChatFormatting; +import net.minecraft.network.chat.Component; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.Rarity; +import net.minecraft.world.item.TooltipFlag; + +import javax.annotation.ParametersAreNonnullByDefault; +import java.util.List; + +public class CreativeAmmoBox extends Item { + + public CreativeAmmoBox() { + super(new Properties().rarity(Rarity.EPIC).stacksTo(1)); + } + + @Override + @ParametersAreNonnullByDefault + public void appendHoverText(ItemStack stack, TooltipContext context, List tooltipComponents, TooltipFlag tooltipFlag) { + tooltipComponents.add(Component.translatable("des.superbwarfare.creative_ammo_box").withStyle(ChatFormatting.GRAY)); + } +} diff --git a/src/main/java/com/atsuishio/superbwarfare/item/common/ammo/HandgunAmmoBox.java b/src/main/java/com/atsuishio/superbwarfare/item/common/ammo/HandgunAmmoBox.java new file mode 100644 index 000000000..b9be96af8 --- /dev/null +++ b/src/main/java/com/atsuishio/superbwarfare/item/common/ammo/HandgunAmmoBox.java @@ -0,0 +1,24 @@ +package com.atsuishio.superbwarfare.item.common.ammo; + +import com.atsuishio.superbwarfare.tools.AmmoType; +import net.minecraft.ChatFormatting; +import net.minecraft.network.chat.Component; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.TooltipFlag; +import org.jetbrains.annotations.NotNull; + +import java.util.List; + +public class HandgunAmmoBox extends AmmoSupplierItem { + + public HandgunAmmoBox() { + super(AmmoType.HANDGUN, 30, new Properties()); + } + + + @Override + public void appendHoverText(@NotNull ItemStack stack, @NotNull TooltipContext context, List tooltipComponents, @NotNull TooltipFlag tooltipFlag) { + super.appendHoverText(stack, context, tooltipComponents, tooltipFlag); + tooltipComponents.add(Component.translatable("des.superbwarfare.handgun_ammo_box").withStyle(ChatFormatting.GRAY)); + } +} diff --git a/src/main/java/com/atsuishio/superbwarfare/item/common/ammo/MortarShell.java b/src/main/java/com/atsuishio/superbwarfare/item/common/ammo/MortarShell.java new file mode 100644 index 000000000..8dee786d5 --- /dev/null +++ b/src/main/java/com/atsuishio/superbwarfare/item/common/ammo/MortarShell.java @@ -0,0 +1,19 @@ +package com.atsuishio.superbwarfare.item.common.ammo; + +//import com.atsuishio.superbwarfare.entity.projectile.MortarShellEntity; + +import net.minecraft.world.item.Item; + +public class MortarShell extends Item { + + public MortarShell() { + super(new Properties()); + } + + // TODO createShell +// public MortarShellEntity createShell(LivingEntity entity, Level level, ItemStack stack) { +// MortarShellEntity shellEntity = new MortarShellEntity(entity, level); +// shellEntity.setEffectsFromItem(stack); +// return shellEntity; +// } +} diff --git a/src/main/java/com/atsuishio/superbwarfare/item/common/ammo/PotionMortarShell.java b/src/main/java/com/atsuishio/superbwarfare/item/common/ammo/PotionMortarShell.java new file mode 100644 index 000000000..0d8ca591a --- /dev/null +++ b/src/main/java/com/atsuishio/superbwarfare/item/common/ammo/PotionMortarShell.java @@ -0,0 +1,25 @@ +package com.atsuishio.superbwarfare.item.common.ammo; + +//@EventBusSubscriber(bus = EventBusSubscriber.Bus.MOD, value = Dist.CLIENT) +public class PotionMortarShell extends MortarShell { + + public PotionMortarShell() { + super(); + } + + // TODO default instance +// @Override +// public ItemStack getDefaultInstance() { +// return PotionUtils.setPotion(super.getDefaultInstance(), Potions.POISON); +// } + +// @Override +// public void appendHoverText(ItemStack pStack, @Nullable Level pLevel, List pTooltip, TooltipFlag pFlag) { +// PotionUtils.addPotionTooltip(pStack, pTooltip, 0.125F); +// } + +// @SubscribeEvent +// public static void onRegisterColorHandlers(final RegisterColorHandlersEvent.Item event) { +// event.register((stack, layer) -> layer == 1 ? PotionUtils.getColor(stack) : -1, ModItems.POTION_MORTAR_SHELL.get()); +// } +} diff --git a/src/main/java/com/atsuishio/superbwarfare/item/common/ammo/RifleAmmoBox.java b/src/main/java/com/atsuishio/superbwarfare/item/common/ammo/RifleAmmoBox.java new file mode 100644 index 000000000..decba516c --- /dev/null +++ b/src/main/java/com/atsuishio/superbwarfare/item/common/ammo/RifleAmmoBox.java @@ -0,0 +1,23 @@ +package com.atsuishio.superbwarfare.item.common.ammo; + +import com.atsuishio.superbwarfare.tools.AmmoType; +import net.minecraft.ChatFormatting; +import net.minecraft.network.chat.Component; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.TooltipFlag; +import org.jetbrains.annotations.NotNull; + +import java.util.List; + +public class RifleAmmoBox extends AmmoSupplierItem { + + public RifleAmmoBox() { + super(AmmoType.RIFLE, 30, new Properties()); + } + + @Override + public void appendHoverText(@NotNull ItemStack stack, @NotNull TooltipContext context, List tooltipComponents, @NotNull TooltipFlag tooltipFlag) { + super.appendHoverText(stack, context, tooltipComponents, tooltipFlag); + tooltipComponents.add(Component.translatable("des.superbwarfare.rifle_ammo_box").withStyle(ChatFormatting.GRAY)); + } +} diff --git a/src/main/java/com/atsuishio/superbwarfare/item/common/ammo/Rocket.java b/src/main/java/com/atsuishio/superbwarfare/item/common/ammo/Rocket.java new file mode 100644 index 000000000..0be4ab8f6 --- /dev/null +++ b/src/main/java/com/atsuishio/superbwarfare/item/common/ammo/Rocket.java @@ -0,0 +1,86 @@ +package com.atsuishio.superbwarfare.item.common.ammo; + +import com.atsuishio.superbwarfare.tools.ParticleTool; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.ItemDisplayContext; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.Level; +import org.jetbrains.annotations.NotNull; + +//public class Rocket extends Item implements GeoItem { +// TODO rewrite +public class Rocket extends Item { + // private final AnimatableInstanceCache cache = GeckoLibUtil.createInstanceCache(this); + public static ItemDisplayContext transformType; + + public Rocket() { + super(new Properties().stacksTo(16)); + } + +// @Override +// public void initializeClient(@NotNull Consumer consumer) { +// super.initializeClient(consumer); +// consumer.accept(new IClientItemExtensions() { +// private final BlockEntityWithoutLevelRenderer renderer = new RocketItemRenderer(); +// +// @Override +// public BlockEntityWithoutLevelRenderer getCustomRenderer() { +// return renderer; +// } +// }); +// } + + public void getTransformType(ItemDisplayContext type) { + transformType = type; + } + + +// @Override +// public void registerControllers(AnimatableManager.ControllerRegistrar data) { +// } + +// @Override +// public AnimatableInstanceCache getAnimatableInstanceCache() { +// return this.cache; +// } + +// @Override +// public Multimap getAttributeModifiers(EquipmentSlot slot, ItemStack stack) { +// Multimap map = super.getAttributeModifiers(slot, stack); +// if (slot == EquipmentSlot.MAINHAND) { +// map = HashMultimap.create(map); +// map.put(Attributes.ATTACK_DAMAGE, new AttributeModifier(BASE_ATTACK_DAMAGE_UUID, "Item modifier", 6d, AttributeModifier.Operation.ADDITION)); +// map.put(Attributes.ATTACK_SPEED, new AttributeModifier(BASE_ATTACK_SPEED_UUID, "Item modifier", -2.4, AttributeModifier.Operation.ADDITION)); +// } +// return map; +// } + + @Override + public boolean hurtEnemy(@NotNull ItemStack stack, LivingEntity entity, @NotNull LivingEntity source) { + if (entity.level() instanceof ServerLevel level && Math.random() < 0.25) { + + level.explode(source, source.getX(), source.getY() + 1, source.getZ(), 6, Level.ExplosionInteraction.NONE); + level.explode(null, source.getX(), source.getY() + 1, source.getZ(), 6, Level.ExplosionInteraction.NONE); + + if (!source.level().isClientSide() && source.getServer() != null) { + ParticleTool.spawnMediumExplosionParticles(source.level(), source.getPosition(0)); + } + + if (source instanceof ServerPlayer player) { + // TODO criteria +// CriteriaRegister.RPG_MELEE_EXPLOSION.trigger(player); + if (!player.isCreative()) { + stack.shrink(1); + } + } else { + stack.shrink(1); + } + } + + return super.hurtEnemy(stack, entity, source); + } + +} \ No newline at end of file diff --git a/src/main/java/com/atsuishio/superbwarfare/item/common/ammo/ShotgunAmmoBox.java b/src/main/java/com/atsuishio/superbwarfare/item/common/ammo/ShotgunAmmoBox.java new file mode 100644 index 000000000..1f2a00978 --- /dev/null +++ b/src/main/java/com/atsuishio/superbwarfare/item/common/ammo/ShotgunAmmoBox.java @@ -0,0 +1,23 @@ +package com.atsuishio.superbwarfare.item.common.ammo; + +import com.atsuishio.superbwarfare.tools.AmmoType; +import net.minecraft.ChatFormatting; +import net.minecraft.network.chat.Component; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.TooltipFlag; +import org.jetbrains.annotations.NotNull; + +import java.util.List; + +public class ShotgunAmmoBox extends AmmoSupplierItem { + + public ShotgunAmmoBox() { + super(AmmoType.SHOTGUN, 12, new Properties()); + } + + @Override + public void appendHoverText(@NotNull ItemStack stack, @NotNull TooltipContext context, List tooltipComponents, @NotNull TooltipFlag tooltipFlag) { + super.appendHoverText(stack, context, tooltipComponents, tooltipFlag); + tooltipComponents.add(Component.translatable("des.superbwarfare.shotgun_ammo_box").withStyle(ChatFormatting.GRAY)); + } +} diff --git a/src/main/java/com/atsuishio/superbwarfare/item/common/ammo/SniperAmmoBox.java b/src/main/java/com/atsuishio/superbwarfare/item/common/ammo/SniperAmmoBox.java new file mode 100644 index 000000000..2aa7b2cd8 --- /dev/null +++ b/src/main/java/com/atsuishio/superbwarfare/item/common/ammo/SniperAmmoBox.java @@ -0,0 +1,23 @@ +package com.atsuishio.superbwarfare.item.common.ammo; + +import com.atsuishio.superbwarfare.tools.AmmoType; +import net.minecraft.ChatFormatting; +import net.minecraft.network.chat.Component; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.TooltipFlag; +import org.jetbrains.annotations.NotNull; + +import java.util.List; + +public class SniperAmmoBox extends AmmoSupplierItem { + + public SniperAmmoBox() { + super(AmmoType.SNIPER, 12, new Properties()); + } + + @Override + public void appendHoverText(@NotNull ItemStack stack, @NotNull TooltipContext context, List tooltipComponents, @NotNull TooltipFlag tooltipFlag) { + super.appendHoverText(stack, context, tooltipComponents, tooltipFlag); + tooltipComponents.add(Component.translatable("des.superbwarfare.sniper_ammo_box").withStyle(ChatFormatting.GRAY)); + } +} diff --git a/src/main/java/com/atsuishio/superbwarfare/item/common/ammo/box/AmmoBox.java b/src/main/java/com/atsuishio/superbwarfare/item/common/ammo/box/AmmoBox.java new file mode 100644 index 000000000..7ac65730d --- /dev/null +++ b/src/main/java/com/atsuishio/superbwarfare/item/common/ammo/box/AmmoBox.java @@ -0,0 +1,152 @@ +package com.atsuishio.superbwarfare.item.common.ammo.box; + +import com.atsuishio.superbwarfare.capability.ModCapabilities; +import com.atsuishio.superbwarfare.component.ModDataComponents; +import com.atsuishio.superbwarfare.init.ModSounds; +import com.atsuishio.superbwarfare.tools.AmmoType; +import com.atsuishio.superbwarfare.tools.FormatTool; +import net.minecraft.ChatFormatting; +import net.minecraft.network.chat.Component; +import net.minecraft.sounds.SoundEvents; +import net.minecraft.sounds.SoundSource; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.InteractionResultHolder; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.TooltipFlag; +import net.minecraft.world.level.Level; +import org.jetbrains.annotations.NotNull; + +import javax.annotation.ParametersAreNonnullByDefault; +import java.util.ArrayList; +import java.util.List; + +public class AmmoBox extends Item { + + public AmmoBox() { + super(new Properties().stacksTo(1)); + } + + // TODO 修复弹药存储问题 + @Override + public @NotNull InteractionResultHolder use(@NotNull Level level, Player player, @NotNull InteractionHand hand) { + ItemStack stack = player.getItemInHand(hand); + + if (hand == InteractionHand.OFF_HAND) return InteractionResultHolder.fail(stack); + + player.getCooldowns().addCooldown(this, 10); + var info = stack.get(ModDataComponents.AMMO_BOX_INFO); + if (info == null) info = new AmmoBoxInfo("All", false); + String type = info.type(); + + var cap = player.getCapability(ModCapabilities.PLAYER_VARIABLE, null); + if (cap != null) { + var types = type.equals("All") ? AmmoType.values() : new AmmoType[]{AmmoType.getType(type)}; + + for (var ammoType : types) { + if (ammoType == null) continue; + + if (player.isCrouching()) { + // 存入弹药 + ammoType.add(stack, ammoType.get(cap)); + ammoType.set(cap, 0); + } else { + // 取出弹药 + ammoType.add(cap, ammoType.get(stack)); + ammoType.set(stack, 0); + } + } + cap.syncPlayerVariables(player); + + if (!level.isClientSide()) { + level.playSound(null, player.blockPosition(), SoundEvents.ARROW_HIT_PLAYER, SoundSource.PLAYERS, 1, 1); + } + + // 取出弹药时,若弹药盒为掉落物版本,则移除弹药盒物品 + if (!player.isCrouching() && info.isDrop()) { + stack.shrink(1); + } + } + return InteractionResultHolder.consume(stack); + } + + private static final List ammoTypeList = generateAmmoTypeList(); + + private static List generateAmmoTypeList() { + var list = new ArrayList(); + list.add("All"); + + for (var ammoType : AmmoType.values()) { + list.add(ammoType.name); + } + + return list; + } + + @Override + @ParametersAreNonnullByDefault + public boolean onEntitySwing(ItemStack stack, LivingEntity entity, InteractionHand hand) { + if (entity instanceof Player player && player.isCrouching()) { + var info = stack.get(ModDataComponents.AMMO_BOX_INFO) == null ? new AmmoBoxInfo("All", false) : stack.get(ModDataComponents.AMMO_BOX_INFO); + assert info != null; + + var index = Math.max(0, ammoTypeList.indexOf(info.type())); + var typeString = ammoTypeList.get((index + 1) % ammoTypeList.size()); + + stack.set(ModDataComponents.AMMO_BOX_INFO, new AmmoBoxInfo(typeString, info.isDrop())); + entity.playSound(ModSounds.FIRE_RATE.get(), 1f, 1f); + + var type = AmmoType.getType(typeString); + if (type == null) { + player.displayClientMessage(Component.translatable("des.superbwarfare.ammo_box.type.all").withStyle(ChatFormatting.WHITE), true); + return true; + } + + switch (type) { + case RIFLE -> + player.displayClientMessage(Component.translatable("des.superbwarfare.ammo_box.type.rifle").withStyle(ChatFormatting.GREEN), true); + case HANDGUN -> + player.displayClientMessage(Component.translatable("des.superbwarfare.ammo_box.type.handgun").withStyle(ChatFormatting.AQUA), true); + case SHOTGUN -> + player.displayClientMessage(Component.translatable("des.superbwarfare.ammo_box.type.shotgun").withStyle(ChatFormatting.RED), true); + case SNIPER -> + player.displayClientMessage(Component.translatable("des.superbwarfare.ammo_box.type.sniper").withStyle(ChatFormatting.GOLD), true); + case HEAVY -> + player.displayClientMessage(Component.translatable("des.superbwarfare.ammo_box.type.heavy").withStyle(ChatFormatting.LIGHT_PURPLE), true); + } + } + + return true; + } + + @Override + public void appendHoverText(ItemStack stack, @NotNull TooltipContext context, List tooltipComponents, @NotNull TooltipFlag tooltipFlag) { + var info = stack.get(ModDataComponents.AMMO_BOX_INFO); + if (info == null) info = new AmmoBoxInfo("All", false); + var type = AmmoType.getType(info.type()); + + tooltipComponents.add(Component.translatable("des.superbwarfare.ammo_box").withStyle(ChatFormatting.GRAY)); + + tooltipComponents.add(Component.translatable("des.superbwarfare.ammo_box.handgun").withStyle(ChatFormatting.AQUA) + .append(Component.literal("").withStyle(ChatFormatting.RESET)) + .append(Component.literal(FormatTool.format0D(AmmoType.HANDGUN.get(stack)) + ((type != AmmoType.HANDGUN) ? " " : " ←-")).withStyle(ChatFormatting.BOLD))); + + tooltipComponents.add(Component.translatable("des.superbwarfare.ammo_box.rifle").withStyle(ChatFormatting.GREEN) + .append(Component.literal("").withStyle(ChatFormatting.RESET)) + .append(Component.literal(FormatTool.format0D(AmmoType.RIFLE.get(stack)) + ((type != AmmoType.RIFLE) ? " " : " ←-")).withStyle(ChatFormatting.BOLD))); + + tooltipComponents.add(Component.translatable("des.superbwarfare.ammo_box.shotgun").withStyle(ChatFormatting.RED) + .append(Component.literal("").withStyle(ChatFormatting.RESET)) + .append(Component.literal(FormatTool.format0D(AmmoType.SHOTGUN.get(stack)) + ((type != AmmoType.SHOTGUN) ? " " : " ←-")).withStyle(ChatFormatting.BOLD))); + + tooltipComponents.add(Component.translatable("des.superbwarfare.ammo_box.sniper").withStyle(ChatFormatting.GOLD) + .append(Component.literal("").withStyle(ChatFormatting.RESET)) + .append(Component.literal(FormatTool.format0D(AmmoType.SNIPER.get(stack)) + ((type != AmmoType.SNIPER) ? " " : " ←-")).withStyle(ChatFormatting.BOLD))); + + tooltipComponents.add(Component.translatable("des.superbwarfare.ammo_box.heavy").withStyle(ChatFormatting.LIGHT_PURPLE) + .append(Component.literal("").withStyle(ChatFormatting.RESET)) + .append(Component.literal(FormatTool.format0D(AmmoType.HEAVY.get(stack)) + ((type != AmmoType.HEAVY) ? " " : " ←-")).withStyle(ChatFormatting.BOLD))); + } +} diff --git a/src/main/java/com/atsuishio/superbwarfare/item/common/ammo/box/AmmoBoxInfo.java b/src/main/java/com/atsuishio/superbwarfare/item/common/ammo/box/AmmoBoxInfo.java new file mode 100644 index 000000000..2fdc9b02b --- /dev/null +++ b/src/main/java/com/atsuishio/superbwarfare/item/common/ammo/box/AmmoBoxInfo.java @@ -0,0 +1,11 @@ +package com.atsuishio.superbwarfare.item.common.ammo.box; + +import com.mojang.serialization.Codec; +import com.mojang.serialization.codecs.RecordCodecBuilder; + +public record AmmoBoxInfo(String type, boolean isDrop) { + public static final Codec CODEC = RecordCodecBuilder.create(instance -> instance.group( + Codec.STRING.fieldOf("type").forGetter(AmmoBoxInfo::type), + Codec.BOOL.fieldOf("is_drop").forGetter(AmmoBoxInfo::isDrop) + ).apply(instance, AmmoBoxInfo::new)); +} diff --git a/src/main/java/com/atsuishio/superbwarfare/network/NetworkRegistry.java b/src/main/java/com/atsuishio/superbwarfare/network/NetworkRegistry.java new file mode 100644 index 000000000..43036f603 --- /dev/null +++ b/src/main/java/com/atsuishio/superbwarfare/network/NetworkRegistry.java @@ -0,0 +1,24 @@ +package com.atsuishio.superbwarfare.network; + +import com.atsuishio.superbwarfare.network.message.PlayerVariablesSyncMessage; +import com.atsuishio.superbwarfare.network.message.SavedDataSyncMessage; +import net.neoforged.neoforge.network.event.RegisterPayloadHandlersEvent; +import net.neoforged.neoforge.network.registration.PayloadRegistrar; + +public class NetworkRegistry { + public static void register(final RegisterPayloadHandlersEvent event) { + final PayloadRegistrar registrar = event.registrar("1"); + + registrar.playToClient( + PlayerVariablesSyncMessage.TYPE, + PlayerVariablesSyncMessage.STREAM_CODEC, + PlayerVariablesSyncMessage::handler + ); + + registrar.playToClient( + SavedDataSyncMessage.TYPE, + SavedDataSyncMessage.STREAM_CODEC, + SavedDataSyncMessage::handler + ); + } +} diff --git a/src/main/java/com/atsuishio/superbwarfare/network/message/PlayerVariablesSyncMessage.java b/src/main/java/com/atsuishio/superbwarfare/network/message/PlayerVariablesSyncMessage.java new file mode 100644 index 000000000..28d237858 --- /dev/null +++ b/src/main/java/com/atsuishio/superbwarfare/network/message/PlayerVariablesSyncMessage.java @@ -0,0 +1,60 @@ +package com.atsuishio.superbwarfare.network.message; + +import com.atsuishio.superbwarfare.ModUtils; +import com.atsuishio.superbwarfare.capability.ModCapabilities; +import com.atsuishio.superbwarfare.capability.player.PlayerVariable; +import io.netty.buffer.ByteBuf; +import net.minecraft.client.Minecraft; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.network.codec.ByteBufCodecs; +import net.minecraft.network.codec.StreamCodec; +import net.minecraft.network.protocol.common.custom.CustomPacketPayload; +import net.neoforged.neoforge.network.handling.IPayloadContext; +import org.jetbrains.annotations.NotNull; + +public record PlayerVariablesSyncMessage(int target, CompoundTag data) implements CustomPacketPayload { + public static final CustomPacketPayload.Type TYPE = new CustomPacketPayload.Type<>(ModUtils.loc("player_variable_sync")); + + public static final StreamCodec STREAM_CODEC = StreamCodec.composite( + ByteBufCodecs.INT, + PlayerVariablesSyncMessage::target, + ByteBufCodecs.COMPOUND_TAG, + PlayerVariablesSyncMessage::data, + PlayerVariablesSyncMessage::new + ); + + + public static void handler(final PlayerVariablesSyncMessage message, final IPayloadContext context) { + var data = new PlayerVariable().readFromNBT(message.data()); + + if (Minecraft.getInstance().player == null) return; + var entity = Minecraft.getInstance().player.level().getEntity(message.target()); + if (entity == null) return; + + var variables = entity.getCapability(ModCapabilities.PLAYER_VARIABLE, null); + if (variables == null) return; + + variables.zoom = data.zoom; + variables.holdFire = data.holdFire; + variables.rifleAmmo = data.rifleAmmo; + variables.handgunAmmo = data.handgunAmmo; + variables.shotgunAmmo = data.shotgunAmmo; + variables.sniperAmmo = data.sniperAmmo; + variables.heavyAmmo = data.heavyAmmo; + variables.bowPullHold = data.bowPullHold; + variables.bowPull = data.bowPull; + variables.playerDoubleJump = data.playerDoubleJump; + variables.tacticalSprint = data.tacticalSprint; + variables.tacticalSprintTime = data.tacticalSprintTime; + variables.tacticalSprintExhaustion = data.tacticalSprintExhaustion; + variables.breath = data.breath; + variables.breathTime = data.breathTime; + variables.breathExhaustion = data.breathExhaustion; + variables.edit = data.edit; + } + + @Override + public @NotNull Type type() { + return TYPE; + } +} \ No newline at end of file diff --git a/src/main/java/com/atsuishio/superbwarfare/network/message/SavedDataSyncMessage.java b/src/main/java/com/atsuishio/superbwarfare/network/message/SavedDataSyncMessage.java new file mode 100644 index 000000000..7e493bc24 --- /dev/null +++ b/src/main/java/com/atsuishio/superbwarfare/network/message/SavedDataSyncMessage.java @@ -0,0 +1,44 @@ +package com.atsuishio.superbwarfare.network.message; + +import com.atsuishio.superbwarfare.ModUtils; +import com.atsuishio.superbwarfare.capability.player.ModVariables; +import io.netty.buffer.ByteBuf; +import net.minecraft.core.HolderLookup; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.network.codec.ByteBufCodecs; +import net.minecraft.network.codec.StreamCodec; +import net.minecraft.network.protocol.common.custom.CustomPacketPayload; +import net.minecraft.world.level.saveddata.SavedData; +import net.neoforged.neoforge.network.handling.IPayloadContext; +import org.jetbrains.annotations.NotNull; + +public record SavedDataSyncMessage( + int messageType, + SavedData data, + HolderLookup.Provider registries +) implements CustomPacketPayload { + public static final CustomPacketPayload.Type TYPE = new CustomPacketPayload.Type<>(ModUtils.loc("saved_data_sync")); + + public static final StreamCodec STREAM_CODEC = StreamCodec.composite( + ByteBufCodecs.INT, + SavedDataSyncMessage::messageType, + ByteBufCodecs.COMPOUND_TAG, + SavedDataSyncMessage::getNBT, + (type, nbt) -> new SavedDataSyncMessage(type, null, null) + ); + + public CompoundTag getNBT() { + return this.data.save(new CompoundTag(), registries); + } + + public static void handler(final SavedDataSyncMessage message, final IPayloadContext context) { + if (message.data != null && message.messageType != 0) { + ModVariables.WorldVariables.clientSide = (ModVariables.WorldVariables) message.data; + } + } + + @Override + public @NotNull Type type() { + return TYPE; + } +} diff --git a/src/main/java/com/atsuishio/superbwarfare/tools/AmmoType.java b/src/main/java/com/atsuishio/superbwarfare/tools/AmmoType.java index a38505221..29d826cd1 100644 --- a/src/main/java/com/atsuishio/superbwarfare/tools/AmmoType.java +++ b/src/main/java/com/atsuishio/superbwarfare/tools/AmmoType.java @@ -1,6 +1,12 @@ package com.atsuishio.superbwarfare.tools; +import com.atsuishio.superbwarfare.capability.ModCapabilities; +import com.atsuishio.superbwarfare.capability.player.PlayerVariable; +import net.minecraft.core.component.DataComponentType; import net.minecraft.nbt.CompoundTag; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.item.ItemStack; +import net.neoforged.neoforge.registries.DeferredHolder; public enum AmmoType { HANDGUN("item.superbwarfare.ammo.handgun", "HandgunAmmo"), @@ -10,6 +16,7 @@ public enum AmmoType { HEAVY("item.superbwarfare.ammo.heavy", "HeavyAmmo"); public final String translatableKey; public final String name; + public DeferredHolder, DataComponentType> dataComponent; AmmoType(String translatableKey, String name) { this.translatableKey = translatableKey; @@ -26,17 +33,18 @@ public enum AmmoType { } // ItemStack -// public int get(ItemStack stack) { -// return get(stack.get(DataComponents.CUSTOM_DATA).getOrCreateTag()); -// } + public int get(ItemStack stack) { + var count = stack.get(this.dataComponent); + return count == null ? 0 : count; + } -// public void set(ItemStack stack, int count) { -// set(stack.getOrCreateTag(), count); -// } + public void set(ItemStack stack, int count) { + stack.set(this.dataComponent, count); + } -// public void add(ItemStack stack, int count) { -// add(stack.getOrCreateTag(), count); -// } + public void add(ItemStack stack, int count) { + set(stack, safeAdd(get(stack), count)); + } // NBTTag public int get(CompoundTag tag) { @@ -53,52 +61,52 @@ public enum AmmoType { } // PlayerVariables -// public int get(ModVariables.PlayerVariables variable) { -// return switch (this) { -// case HANDGUN -> variable.handgunAmmo; -// case RIFLE -> variable.rifleAmmo; -// case SHOTGUN -> variable.shotgunAmmo; -// case SNIPER -> variable.sniperAmmo; -// case HEAVY -> variable.heavyAmmo; -// }; -// } -// -// public void set(ModVariables.PlayerVariables variable, int count) { -// if (count < 0) count = 0; -// -// switch (this) { -// case HANDGUN -> variable.handgunAmmo = count; -// case RIFLE -> variable.rifleAmmo = count; -// case SHOTGUN -> variable.shotgunAmmo = count; -// case SNIPER -> variable.sniperAmmo = count; -// case HEAVY -> variable.heavyAmmo = count; -// } -// } -// -// public void add(ModVariables.PlayerVariables variable, int count) { -// set(variable, safeAdd(get(variable), count)); -// } -// -// -// // Entity -// public int get(Entity entity) { -// var cap = entity.getCapability(ModVariables.PLAYER_VARIABLES_CAPABILITY); -// if (cap == null) return 0; -// -// return get(cap); -// } -// -// public void set(Entity entity, int count) { -// var cap = entity.getCapability(ModVariables.PLAYER_VARIABLES_CAPABILITY); -// if (cap == null) return; -// -// set(cap, count); -// cap.syncPlayerVariables(entity); -// } + public int get(PlayerVariable variable) { + return switch (this) { + case HANDGUN -> variable.handgunAmmo; + case RIFLE -> variable.rifleAmmo; + case SHOTGUN -> variable.shotgunAmmo; + case SNIPER -> variable.sniperAmmo; + case HEAVY -> variable.heavyAmmo; + }; + } -// public void add(Entity entity, int count) { -// set(entity, safeAdd(get(entity), count)); -// } + public void set(PlayerVariable variable, int count) { + if (count < 0) count = 0; + + switch (this) { + case HANDGUN -> variable.handgunAmmo = count; + case RIFLE -> variable.rifleAmmo = count; + case SHOTGUN -> variable.shotgunAmmo = count; + case SNIPER -> variable.sniperAmmo = count; + case HEAVY -> variable.heavyAmmo = count; + } + } + + public void add(PlayerVariable variable, int count) { + set(variable, safeAdd(get(variable), count)); + } + + + // Entity + public int get(Entity entity) { + var cap = entity.getCapability(ModCapabilities.PLAYER_VARIABLE); + if (cap == null) return 0; + + return get(cap); + } + + public void set(Entity entity, int count) { + var cap = entity.getCapability(ModCapabilities.PLAYER_VARIABLE); + if (cap == null) return; + + set(cap, count); + cap.syncPlayerVariables(entity); + } + + public void add(Entity entity, int count) { + set(entity, safeAdd(get(entity), count)); + } private int safeAdd(int a, int b) {