diff --git a/Common/src/main/java/tschipp/carryon/Constants.java b/Common/src/main/java/tschipp/carryon/Constants.java index c4f33f3..47290e5 100644 --- a/Common/src/main/java/tschipp/carryon/Constants.java +++ b/Common/src/main/java/tschipp/carryon/Constants.java @@ -38,5 +38,6 @@ public class Constants { public static final ResourceLocation PACKET_ID_START_RIDING = ResourceLocation.fromNamespaceAndPath(Constants.MOD_ID, "start_riding"); public static final ResourceLocation PACKET_ID_SYNC_SCRIPTS = ResourceLocation.fromNamespaceAndPath(Constants.MOD_ID, "sync_scripts"); public static final ResourceLocation PACKET_ID_START_RIDING_OTHER = ResourceLocation.fromNamespaceAndPath(Constants.MOD_ID, "start_riding_other"); + public static final ResourceLocation PACKET_ID_SYNC_CARRY_ON_DATA = ResourceLocation.fromNamespaceAndPath(Constants.MOD_ID, "sync_carry_data"); } \ No newline at end of file diff --git a/Common/src/main/java/tschipp/carryon/common/carry/CarryOnData.java b/Common/src/main/java/tschipp/carryon/common/carry/CarryOnData.java index 78016c6..9224cfb 100644 --- a/Common/src/main/java/tschipp/carryon/common/carry/CarryOnData.java +++ b/Common/src/main/java/tschipp/carryon/common/carry/CarryOnData.java @@ -30,6 +30,9 @@ import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.NbtOps; import net.minecraft.nbt.NbtUtils; import net.minecraft.nbt.Tag; +import net.minecraft.network.RegistryFriendlyByteBuf; +import net.minecraft.network.codec.ByteBufCodecs; +import net.minecraft.network.codec.StreamCodec; import net.minecraft.server.level.ServerPlayer; import net.minecraft.util.ProblemReporter; import net.minecraft.world.entity.AreaEffectCloud; @@ -47,6 +50,7 @@ import tschipp.carryon.Constants; import tschipp.carryon.common.scripting.CarryOnScript; import javax.annotation.Nullable; +import java.util.Objects; import java.util.Optional; public class CarryOnData { @@ -58,6 +62,7 @@ public class CarryOnData { private int selectedSlot = 0; private static final ProblemReporter problemReporter = new ProblemReporter.ScopedCollector(Constants.LOG); + public static final Codec CODEC = CompoundTag.CODEC.flatXmap( tag -> { try { @@ -75,6 +80,10 @@ public class CarryOnData { } ); + public static final StreamCodec STREAM_CODEC = ByteBufCodecs.fromCodecWithRegistries(CODEC); + + public static final String SERIALIZATION_KEY = "CarryOnData"; + public CarryOnData(CompoundTag data) { if(data.contains("type")) @@ -236,11 +245,14 @@ public class CarryOnData { public int getTick() { - if(!this.nbt.contains("tick")) - return -1; return this.nbt.getIntOr("tick", -1); } + public void setTick(int tick) { + this.nbt.putInt("tick", tick); + } + + public enum CarryType { BLOCK, ENTITY, diff --git a/Common/src/main/java/tschipp/carryon/common/carry/CarryOnDataManager.java b/Common/src/main/java/tschipp/carryon/common/carry/CarryOnDataManager.java index 10d7fa2..8a96518 100644 --- a/Common/src/main/java/tschipp/carryon/common/carry/CarryOnDataManager.java +++ b/Common/src/main/java/tschipp/carryon/common/carry/CarryOnDataManager.java @@ -24,25 +24,22 @@ import net.minecraft.nbt.CompoundTag; import net.minecraft.network.syncher.EntityDataAccessor; import net.minecraft.network.syncher.EntityDataSerializers; import net.minecraft.network.syncher.SynchedEntityData; +import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.entity.player.Player; +import tschipp.carryon.platform.Services; public class CarryOnDataManager { public static CarryOnData getCarryData(Player player) { - return ((ICarrying)player).getCarryOnData(); + return Services.PLATFORM.getCarryData(player); } public static void setCarryData(Player player, CarryOnData data) { - ((ICarrying)player).setCarryOnData(data); - } - - public interface ICarrying { - - void setCarryOnData(CarryOnData data); - - CarryOnData getCarryOnData(); + data.setSelected(player.getInventory().getSelectedSlot()); + data.setTick(player.tickCount); + Services.PLATFORM.setCarryData(player, data); } } diff --git a/Common/src/main/java/tschipp/carryon/common/carry/PickupHandler.java b/Common/src/main/java/tschipp/carryon/common/carry/PickupHandler.java index 6a6773d..6f3d371 100644 --- a/Common/src/main/java/tschipp/carryon/common/carry/PickupHandler.java +++ b/Common/src/main/java/tschipp/carryon/common/carry/PickupHandler.java @@ -154,7 +154,7 @@ public class PickupHandler { level.playSound(null, pos, state.getSoundType().getHitSound(), SoundSource.BLOCKS, 1.0f, 0.5f); player.swing(InteractionHand.MAIN_HAND, true); if (!player.isCreative() || Constants.COMMON_CONFIG.settings.slownessInCreative) - player.addEffect(new MobEffectInstance(MobEffects.SLOWNESS, 1000000, CarryOnCommon.potionLevel(carry, player.level()), false, false)); + player.addEffect(new MobEffectInstance(MobEffects.SLOWNESS, 100000000, CarryOnCommon.potionLevel(carry, player.level()), false, false)); return true; } @@ -242,7 +242,7 @@ public class PickupHandler { player.level().playSound(null, player.getOnPos(), SoundEvents.ARMOR_EQUIP_GENERIC.value(), SoundSource.AMBIENT, 1.0f, 0.5f); CarryOnDataManager.setCarryData(player, carry); if (!player.isCreative() || Constants.COMMON_CONFIG.settings.slownessInCreative) - player.addEffect(new MobEffectInstance(MobEffects.SLOWNESS, 1000000, CarryOnCommon.potionLevel(carry, player.level()), false, false)); + player.addEffect(new MobEffectInstance(MobEffects.SLOWNESS, 100000000, CarryOnCommon.potionLevel(carry, player.level()), false, false)); return true; } @@ -267,7 +267,7 @@ public class PickupHandler { CarryOnDataManager.setCarryData(player, carry); player.swing(InteractionHand.MAIN_HAND, true); if (!player.isCreative() || Constants.COMMON_CONFIG.settings.slownessInCreative) - player.addEffect(new MobEffectInstance(MobEffects.SLOWNESS, 1000000, CarryOnCommon.potionLevel(carry, player.level()), false, false)); + player.addEffect(new MobEffectInstance(MobEffects.SLOWNESS, 100000000, CarryOnCommon.potionLevel(carry, player.level()), false, false)); return true; } diff --git a/Common/src/main/java/tschipp/carryon/mixin/InventoryMixin.java b/Common/src/main/java/tschipp/carryon/mixin/InventoryMixin.java index 363cc5b..78a701f 100644 --- a/Common/src/main/java/tschipp/carryon/mixin/InventoryMixin.java +++ b/Common/src/main/java/tschipp/carryon/mixin/InventoryMixin.java @@ -23,6 +23,7 @@ package tschipp.carryon.mixin; import com.llamalad7.mixinextras.injector.wrapoperation.Operation; import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; import net.minecraft.core.NonNullList; +import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.entity.player.Inventory; import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.ItemStack; @@ -34,6 +35,7 @@ import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.Redirect; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import tschipp.carryon.common.carry.CarryOnData; import tschipp.carryon.common.carry.CarryOnDataManager; @Mixin(Inventory.class) @@ -77,9 +79,10 @@ public class InventoryMixin } @Inject(method = "setSelectedSlot(I)V", at = @At("HEAD"), cancellable = true) - private void onSwapPaint(int $$0, CallbackInfo info) + private void onSwapPaint(int slot, CallbackInfo info) { - if(CarryOnDataManager.getCarryData(player).isCarrying()) + CarryOnData data = CarryOnDataManager.getCarryData(player); + if(data.isCarrying() && data.getSelected() != slot) info.cancel(); } } diff --git a/Common/src/main/java/tschipp/carryon/mixin/PlayerMixin.java b/Common/src/main/java/tschipp/carryon/mixin/PlayerMixin.java index 738f9c9..7248965 100644 --- a/Common/src/main/java/tschipp/carryon/mixin/PlayerMixin.java +++ b/Common/src/main/java/tschipp/carryon/mixin/PlayerMixin.java @@ -44,54 +44,18 @@ import tschipp.carryon.common.carry.CarryOnDataManager; import java.util.Optional; @Mixin(Player.class) -public abstract class PlayerMixin extends LivingEntity implements CarryOnDataManager.ICarrying { - - @Unique - private static final EntityDataAccessor CARRY_DATA_KEY = SynchedEntityData.defineId(Player.class, EntityDataSerializers.COMPOUND_TAG); - - @Override - public void setCarryOnData(CarryOnData data) - { - data.setSelected(this.getInventory().getSelectedSlot()); - CompoundTag nbt = data.getNbt(); - nbt.putInt("tick", tickCount); - this.getEntityData().set(CARRY_DATA_KEY, nbt); - } - - @Override - public CarryOnData getCarryOnData() - { - CompoundTag data = this.getEntityData().get(CARRY_DATA_KEY); - return new CarryOnData(data.copy()); - } - - @Shadow - public abstract Inventory getInventory(); - +public abstract class PlayerMixin extends LivingEntity { private PlayerMixin(EntityType type, Level level) { super(type, level); } - - @Inject(method = "defineSynchedData(Lnet/minecraft/network/syncher/SynchedEntityData$Builder;)V", at = @At("RETURN")) - private void onDefineSynchedData(SynchedEntityData.Builder builder, CallbackInfo ci) { - builder.define(CARRY_DATA_KEY, new CompoundTag()); - } - - - @Inject(method = "addAdditionalSaveData(Lnet/minecraft/world/level/storage/ValueOutput;)V", at = @At("RETURN")) - private void onAddAdditionalSaveData(ValueOutput output, CallbackInfo ci) - { - CarryOnData carry = CarryOnDataManager.getCarryData((Player)(Object)this); - output.store("CarryOnData", CarryOnData.CODEC, carry); - } - + //We leave this in here to ensure cross-compatibility if world are upgraded from <1.21.8. Should be removed in the future. @Inject(method = "readAdditionalSaveData(Lnet/minecraft/world/level/storage/ValueInput;)V", at = @At("RETURN")) private void onReadAdditionalSaveData(ValueInput input, CallbackInfo ci) { Optional res = input.read("CarryOnData", CarryOnData.CODEC); - res.ifPresent(this::setCarryOnData); + res.ifPresent(data -> CarryOnDataManager.setCarryData((Player)((Object)this), data)); } } diff --git a/Common/src/main/java/tschipp/carryon/networking/clientbound/ClientboundSyncCarryDataPacket.java b/Common/src/main/java/tschipp/carryon/networking/clientbound/ClientboundSyncCarryDataPacket.java deleted file mode 100644 index ba3cec7..0000000 --- a/Common/src/main/java/tschipp/carryon/networking/clientbound/ClientboundSyncCarryDataPacket.java +++ /dev/null @@ -1,6 +0,0 @@ -package tschipp.carryon.networking.clientbound; - -import tschipp.carryon.common.carry.CarryOnData; - -public record ClientboundSyncCarryDataPacket(CarryOnData data) { -} diff --git a/Common/src/main/java/tschipp/carryon/platform/services/IPlatformHelper.java b/Common/src/main/java/tschipp/carryon/platform/services/IPlatformHelper.java index 3082ed4..07c1d68 100644 --- a/Common/src/main/java/tschipp/carryon/platform/services/IPlatformHelper.java +++ b/Common/src/main/java/tschipp/carryon/platform/services/IPlatformHelper.java @@ -29,6 +29,8 @@ import net.minecraft.resources.ResourceLocation; import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.entity.player.Player; +import tschipp.carryon.common.carry.CarryOnData; +import tschipp.carryon.common.carry.CarryOnDataManager; import tschipp.carryon.config.BuiltConfig; import tschipp.carryon.networking.PacketBase; @@ -74,4 +76,8 @@ public interface IPlatformHelper { sendPacketToPlayer(id, packet, p); } + CarryOnData getCarryData(Player player); + + void setCarryData(Player player, CarryOnData data); + } diff --git a/Fabric/src/main/java/tschipp/carryon/CarryOnFabricMod.java b/Fabric/src/main/java/tschipp/carryon/CarryOnFabricMod.java index 9cbb4cc..e5c7c43 100644 --- a/Fabric/src/main/java/tschipp/carryon/CarryOnFabricMod.java +++ b/Fabric/src/main/java/tschipp/carryon/CarryOnFabricMod.java @@ -21,13 +21,29 @@ package tschipp.carryon; import net.fabricmc.api.ModInitializer; +import net.fabricmc.fabric.api.attachment.v1.AttachmentRegistry; +import net.fabricmc.fabric.api.attachment.v1.AttachmentSyncPredicate; +import net.fabricmc.fabric.api.attachment.v1.AttachmentType; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.resources.ResourceLocation; +import tschipp.carryon.common.carry.CarryOnData; import tschipp.carryon.config.fabric.ConfigLoaderImpl; import tschipp.carryon.events.CommonEvents; import java.io.IOException; public class CarryOnFabricMod implements ModInitializer { - + + public static final AttachmentType CARRY_ON_DATA_ATTACHMENT_TYPE = AttachmentRegistry.create( + ResourceLocation.fromNamespaceAndPath(Constants.MOD_ID, "carry_on_data"), + builder -> builder + .initializer(() -> new CarryOnData(new CompoundTag())) + .persistent(CarryOnData.CODEC) + .syncWith(CarryOnData.STREAM_CODEC, (t, p) -> p.connection != null) + .copyOnDeath() + + ); + @Override public void onInitialize() { diff --git a/Fabric/src/main/java/tschipp/carryon/platform/FabricPlatformHelper.java b/Fabric/src/main/java/tschipp/carryon/platform/FabricPlatformHelper.java index 020ac7d..64d4bdf 100644 --- a/Fabric/src/main/java/tschipp/carryon/platform/FabricPlatformHelper.java +++ b/Fabric/src/main/java/tschipp/carryon/platform/FabricPlatformHelper.java @@ -25,6 +25,7 @@ import net.fabricmc.fabric.api.networking.v1.PayloadTypeRegistry; import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking; import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking.PlayPayloadHandler; import net.fabricmc.loader.api.FabricLoader; +import net.minecraft.nbt.CompoundTag; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.network.RegistryFriendlyByteBuf; import net.minecraft.network.codec.StreamCodec; @@ -35,6 +36,8 @@ import net.minecraft.resources.ResourceLocation; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.entity.player.Player; import tschipp.carryon.CarryOnFabricClientMod; +import tschipp.carryon.CarryOnFabricMod; +import tschipp.carryon.common.carry.CarryOnData; import tschipp.carryon.config.BuiltConfig; import tschipp.carryon.config.fabric.ConfigLoaderImpl; import tschipp.carryon.networking.PacketBase; @@ -101,4 +104,15 @@ public class FabricPlatformHelper implements IPlatformHelper { { ServerPlayNetworking.send(player, packet); } + + @Override + public CarryOnData getCarryData(Player player) { + CarryOnData data = player.getAttachedOrCreate(CarryOnFabricMod.CARRY_ON_DATA_ATTACHMENT_TYPE); + return data.clone(); + } + + @Override + public void setCarryData(Player player, CarryOnData data) { + player.setAttached(CarryOnFabricMod.CARRY_ON_DATA_ATTACHMENT_TYPE, data); + } } diff --git a/Forge/src/main/java/tschipp/carryon/CarryOnForge.java b/Forge/src/main/java/tschipp/carryon/CarryOnForge.java index 546ab7d..292bf7b 100644 --- a/Forge/src/main/java/tschipp/carryon/CarryOnForge.java +++ b/Forge/src/main/java/tschipp/carryon/CarryOnForge.java @@ -29,6 +29,9 @@ import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext; import net.minecraftforge.network.ChannelBuilder; import net.minecraftforge.network.SimpleChannel; import tschipp.carryon.config.forge.ConfigLoaderImpl; +import tschipp.carryon.networking.ClientboundSyncCarryDataPacket; +import tschipp.carryon.networking.clientbound.ClientboundStartRidingPacket; +import tschipp.carryon.platform.Services; @Mod(Constants.MOD_ID) @EventBusSubscriber(bus = Mod.EventBusSubscriber.Bus.MOD) @@ -54,6 +57,13 @@ public class CarryOnForge { CarryOnCommon.registerServerPackets(); CarryOnCommon.registerClientPackets(); + + Services.PLATFORM.registerClientboundPacket( + ClientboundSyncCarryDataPacket.TYPE, + ClientboundSyncCarryDataPacket.class, + ClientboundSyncCarryDataPacket.CODEC, + ClientboundSyncCarryDataPacket::handle + ); } } \ No newline at end of file diff --git a/Forge/src/main/java/tschipp/carryon/carry/CarryOnDataCapability.java b/Forge/src/main/java/tschipp/carryon/carry/CarryOnDataCapability.java new file mode 100644 index 0000000..a4f4f14 --- /dev/null +++ b/Forge/src/main/java/tschipp/carryon/carry/CarryOnDataCapability.java @@ -0,0 +1,23 @@ +package tschipp.carryon.carry; + +import net.minecraft.nbt.CompoundTag; +import tschipp.carryon.common.carry.CarryOnData; + +public class CarryOnDataCapability implements ICarryOnDataCapability { + + private CarryOnData data; + + public CarryOnDataCapability() { + this.data = new CarryOnData(new CompoundTag()); + } + + @Override + public CarryOnData getCarryData() { + return data; + } + + @Override + public void setCarryData(CarryOnData data) { + this.data = data; + } +} diff --git a/Forge/src/main/java/tschipp/carryon/carry/CarryOnDataCapabilityProvider.java b/Forge/src/main/java/tschipp/carryon/carry/CarryOnDataCapabilityProvider.java new file mode 100644 index 0000000..e30ebdb --- /dev/null +++ b/Forge/src/main/java/tschipp/carryon/carry/CarryOnDataCapabilityProvider.java @@ -0,0 +1,38 @@ +package tschipp.carryon.carry; + +import net.minecraft.core.Direction; +import net.minecraft.core.HolderLookup; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.NbtOps; +import net.minecraftforge.common.capabilities.Capability; +import net.minecraftforge.common.capabilities.CapabilityManager; +import net.minecraftforge.common.capabilities.CapabilityToken; +import net.minecraftforge.common.capabilities.ICapabilitySerializable; +import net.minecraftforge.common.util.LazyOptional; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import tschipp.carryon.common.carry.CarryOnData; + +public class CarryOnDataCapabilityProvider implements ICapabilitySerializable { + + public static final Capability CARRY_ON_DATA_CAPABILITY = CapabilityManager.get(new CapabilityToken() {}); + + private final CarryOnDataCapability impl = new CarryOnDataCapability(); + private final LazyOptional opt = LazyOptional.of(() -> impl); + + @Override + public @NotNull LazyOptional getCapability(@NotNull Capability cap, @Nullable Direction side) { + return cap == CARRY_ON_DATA_CAPABILITY ? opt.cast() : LazyOptional.empty(); + } + + @Override + public CompoundTag serializeNBT(HolderLookup.Provider registryAccess) { + return (CompoundTag) CarryOnData.CODEC.encodeStart(NbtOps.INSTANCE, impl.getCarryData()).getOrThrow(); + } + + @Override + public void deserializeNBT(HolderLookup.Provider registryAccess, CompoundTag nbt) { + CarryOnData data = CarryOnData.CODEC.parse(NbtOps.INSTANCE, nbt).getOrThrow(); + impl.setCarryData(data); + } +} diff --git a/Forge/src/main/java/tschipp/carryon/carry/ICarryOnDataCapability.java b/Forge/src/main/java/tschipp/carryon/carry/ICarryOnDataCapability.java new file mode 100644 index 0000000..49ab1f8 --- /dev/null +++ b/Forge/src/main/java/tschipp/carryon/carry/ICarryOnDataCapability.java @@ -0,0 +1,14 @@ +package tschipp.carryon.carry; + +import net.minecraftforge.common.capabilities.AutoRegisterCapability; +import tschipp.carryon.common.carry.CarryOnData; +import tschipp.carryon.common.carry.CarryOnDataManager; + +@AutoRegisterCapability +public interface ICarryOnDataCapability { + + CarryOnData getCarryData(); + + void setCarryData(CarryOnData data); + +} diff --git a/Forge/src/main/java/tschipp/carryon/events/CommonEvents.java b/Forge/src/main/java/tschipp/carryon/events/CommonEvents.java index 2e3352f..b91d5f9 100644 --- a/Forge/src/main/java/tschipp/carryon/events/CommonEvents.java +++ b/Forge/src/main/java/tschipp/carryon/events/CommonEvents.java @@ -21,6 +21,7 @@ package tschipp.carryon.events; import net.minecraft.core.BlockPos; +import net.minecraft.resources.ResourceLocation; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.InteractionResult; import net.minecraft.world.entity.Entity; @@ -32,12 +33,10 @@ import net.minecraft.world.level.ServerLevelAccessor; import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.common.util.BlockSnapshot; import net.minecraftforge.common.util.Result; -import net.minecraftforge.event.AddReloadListenerEvent; -import net.minecraftforge.event.OnDatapackSyncEvent; -import net.minecraftforge.event.RegisterCommandsEvent; -import net.minecraftforge.event.TagsUpdatedEvent; +import net.minecraftforge.event.*; import net.minecraftforge.event.TickEvent.Phase; import net.minecraftforge.event.TickEvent.ServerTickEvent; +import net.minecraftforge.event.entity.EntityJoinLevelEvent; import net.minecraftforge.event.entity.living.LivingAttackEvent; import net.minecraftforge.event.entity.living.MobSpawnEvent.FinalizeSpawn; import net.minecraftforge.event.entity.player.AttackEntityEvent; @@ -54,6 +53,7 @@ import net.minecraftforge.fml.common.Mod; import oshi.jna.platform.mac.SystemB; import tschipp.carryon.CarryOnCommon; import tschipp.carryon.Constants; +import tschipp.carryon.carry.CarryOnDataCapabilityProvider; import tschipp.carryon.common.carry.CarryOnData; import tschipp.carryon.common.carry.CarryOnData.CarryType; import tschipp.carryon.common.carry.CarryOnDataManager; @@ -61,6 +61,8 @@ import tschipp.carryon.common.carry.PickupHandler; import tschipp.carryon.common.carry.PlacementHandler; import tschipp.carryon.common.scripting.ScriptReloadListener; import tschipp.carryon.config.ConfigLoader; +import tschipp.carryon.networking.ClientboundSyncCarryDataPacket; +import tschipp.carryon.platform.Services; @Mod.EventBusSubscriber(bus = Mod.EventBusSubscriber.Bus.FORGE, modid = Constants.MOD_ID) public class CommonEvents @@ -178,8 +180,16 @@ public class CommonEvents @SubscribeEvent public static void onClone(Clone event) { - if (!event.getOriginal().level().isClientSide) - PlacementHandler.placeCarriedOnDeath((ServerPlayer) event.getOriginal(), (ServerPlayer) event.getEntity(), event.isWasDeath()); + if (!event.getOriginal().level().isClientSide) { + Player newPlayer = event.getEntity(); + Player oldPlayer = event.getOriginal(); + oldPlayer.reviveCaps(); + + PlacementHandler.placeCarriedOnDeath((ServerPlayer) oldPlayer, (ServerPlayer) newPlayer, event.isWasDeath()); + + oldPlayer.invalidateCaps(); + + } } @SubscribeEvent @@ -214,4 +224,25 @@ public class CommonEvents CarryOnCommon.onRiderDisconnected(player); } + @SubscribeEvent + public static void onAttachCapabilities(AttachCapabilitiesEvent.Entities event) { + if (event.getObject() instanceof Player player) { + event.addCapability(ResourceLocation.fromNamespaceAndPath(Constants.MOD_ID, "carry_on_data"), new CarryOnDataCapabilityProvider()); + } + } + + @SubscribeEvent + public static void onStartTracking(PlayerEvent.StartTracking event) { + if(event.getEntity() instanceof ServerPlayer sp && event.getTarget() instanceof ServerPlayer target) { + Services.PLATFORM.sendPacketToPlayer(Constants.PACKET_ID_SYNC_CARRY_ON_DATA, new ClientboundSyncCarryDataPacket(sp.getId(), CarryOnDataManager.getCarryData(sp)), target); + } + } + + @SubscribeEvent + public static void onJoinWorld(EntityJoinLevelEvent event) { + if (event.getEntity() instanceof ServerPlayer sp) { + Services.PLATFORM.sendPacketToPlayer(Constants.PACKET_ID_SYNC_CARRY_ON_DATA, new ClientboundSyncCarryDataPacket(sp.getId(), CarryOnDataManager.getCarryData(sp)), sp); + } + } + } diff --git a/Forge/src/main/java/tschipp/carryon/networking/ClientboundSyncCarryDataPacket.java b/Forge/src/main/java/tschipp/carryon/networking/ClientboundSyncCarryDataPacket.java new file mode 100644 index 0000000..25e37c4 --- /dev/null +++ b/Forge/src/main/java/tschipp/carryon/networking/ClientboundSyncCarryDataPacket.java @@ -0,0 +1,36 @@ +package tschipp.carryon.networking; + +import net.minecraft.network.RegistryFriendlyByteBuf; +import net.minecraft.network.codec.ByteBufCodecs; +import net.minecraft.network.codec.StreamCodec; +import net.minecraft.network.protocol.common.custom.CustomPacketPayload; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.player.Player; +import tschipp.carryon.Constants; +import tschipp.carryon.common.carry.CarryOnData; +import tschipp.carryon.common.carry.CarryOnDataManager; +import tschipp.carryon.networking.clientbound.ClientboundStartRidingPacket; + +public record ClientboundSyncCarryDataPacket(int iden, CarryOnData data) implements PacketBase { + + public static final StreamCodec CODEC = StreamCodec.composite( + ByteBufCodecs.INT, ClientboundSyncCarryDataPacket::iden, + CarryOnData.STREAM_CODEC, ClientboundSyncCarryDataPacket::data, + ClientboundSyncCarryDataPacket::new + ); + + public static final CustomPacketPayload.Type TYPE = new Type<>(Constants.PACKET_ID_SYNC_CARRY_ON_DATA); + + @Override + public void handle(Player player) { + Entity e = player.level().getEntity(this.iden); + if(e instanceof Player p) { + CarryOnDataManager.setCarryData(p, data); + } + } + + @Override + public Type type() { + return TYPE; + } +} diff --git a/Forge/src/main/java/tschipp/carryon/platform/ForgePlatformHelper.java b/Forge/src/main/java/tschipp/carryon/platform/ForgePlatformHelper.java index 0d67a3d..54d6fbd 100644 --- a/Forge/src/main/java/tschipp/carryon/platform/ForgePlatformHelper.java +++ b/Forge/src/main/java/tschipp/carryon/platform/ForgePlatformHelper.java @@ -25,6 +25,7 @@ import net.minecraft.network.RegistryFriendlyByteBuf; import net.minecraft.network.codec.StreamCodec; import net.minecraft.network.protocol.common.custom.CustomPacketPayload; import net.minecraft.resources.ResourceLocation; +import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.entity.player.Player; import net.minecraftforge.event.network.CustomPayloadEvent; @@ -34,8 +35,14 @@ import net.minecraftforge.network.NetworkDirection; import net.minecraftforge.network.PacketDistributor; import tschipp.carryon.CarryOnCommonClient; import tschipp.carryon.CarryOnForge; +import tschipp.carryon.Constants; +import tschipp.carryon.carry.CarryOnDataCapability; +import tschipp.carryon.carry.CarryOnDataCapabilityProvider; +import tschipp.carryon.carry.ICarryOnDataCapability; +import tschipp.carryon.common.carry.CarryOnData; import tschipp.carryon.config.BuiltConfig; import tschipp.carryon.config.forge.ConfigLoaderImpl; +import tschipp.carryon.networking.ClientboundSyncCarryDataPacket; import tschipp.carryon.networking.PacketBase; import tschipp.carryon.platform.services.IPlatformHelper; @@ -111,4 +118,19 @@ public class ForgePlatformHelper implements IPlatformHelper { { CarryOnForge.network.send(packet, PacketDistributor.PLAYER.with(player)); } + + @Override + public CarryOnData getCarryData(Player player) { + var cap = player.getCapability(CarryOnDataCapabilityProvider.CARRY_ON_DATA_CAPABILITY).orElse(new CarryOnDataCapability()); + return cap.getCarryData(); + } + + @Override + public void setCarryData(Player player, CarryOnData data) { + var cap = player.getCapability(CarryOnDataCapabilityProvider.CARRY_ON_DATA_CAPABILITY).orElse(new CarryOnDataCapability()); + cap.setCarryData(data); + if(!player.level().isClientSide) { + sendPacketToAllPlayers(Constants.PACKET_ID_SYNC_SCRIPTS, new ClientboundSyncCarryDataPacket(player.getId(), data), (ServerLevel) player.level()); + } + } } diff --git a/NeoForge/src/main/java/tschipp/carryon/CarryOnNeoForge.java b/NeoForge/src/main/java/tschipp/carryon/CarryOnNeoForge.java index 945f10f..d7db9dc 100644 --- a/NeoForge/src/main/java/tschipp/carryon/CarryOnNeoForge.java +++ b/NeoForge/src/main/java/tschipp/carryon/CarryOnNeoForge.java @@ -20,20 +20,38 @@ package tschipp.carryon; +import net.minecraft.nbt.CompoundTag; import net.neoforged.bus.api.IEventBus; import net.neoforged.bus.api.SubscribeEvent; import net.neoforged.fml.ModContainer; import net.neoforged.fml.common.Mod; import net.neoforged.fml.event.lifecycle.FMLCommonSetupEvent; +import net.neoforged.neoforge.attachment.AttachmentType; import net.neoforged.neoforge.client.gui.ConfigurationScreen; import net.neoforged.neoforge.common.NeoForge; import net.neoforged.neoforge.network.event.RegisterPayloadHandlersEvent; import net.neoforged.neoforge.network.registration.PayloadRegistrar; +import net.neoforged.neoforge.registries.DeferredRegister; +import net.neoforged.neoforge.registries.NeoForgeRegistries; +import tschipp.carryon.carry.CarryOnDataSyncHandler; +import tschipp.carryon.common.carry.CarryOnData; import tschipp.carryon.config.neoforge.ConfigLoaderImpl; +import java.util.function.Supplier; + @Mod(Constants.MOD_ID) public class CarryOnNeoForge { + private static final DeferredRegister> ATTACHMENT_TYPES = DeferredRegister.create(NeoForgeRegistries.ATTACHMENT_TYPES, Constants.MOD_ID); + + public static final Supplier> CARRY_ON_DATA_ATTACHMENT = ATTACHMENT_TYPES.register( + "carry_on_data", + () -> AttachmentType.builder(() -> new CarryOnData(new CompoundTag())) + .sync(new CarryOnDataSyncHandler()) + .serialize(CarryOnData.CODEC.fieldOf(CarryOnData.SERIALIZATION_KEY)) + .build() + ); + public CarryOnNeoForge(ModContainer container) { // This method is invoked by the Forge mod loader when it is ready @@ -45,6 +63,8 @@ public class CarryOnNeoForge { container.getEventBus().addListener(this::registerPackets); ConfigLoaderImpl.initialize(container); + + ATTACHMENT_TYPES.register(container.getEventBus()); } private void setup(final FMLCommonSetupEvent event) @@ -57,6 +77,8 @@ public class CarryOnNeoForge { CarryOnCommon.registerServerPackets(registrar); CarryOnCommon.registerClientPackets(registrar); + + } } \ No newline at end of file diff --git a/NeoForge/src/main/java/tschipp/carryon/carry/CarryOnDataSyncHandler.java b/NeoForge/src/main/java/tschipp/carryon/carry/CarryOnDataSyncHandler.java new file mode 100644 index 0000000..16fa62f --- /dev/null +++ b/NeoForge/src/main/java/tschipp/carryon/carry/CarryOnDataSyncHandler.java @@ -0,0 +1,27 @@ +package tschipp.carryon.carry; + +import net.minecraft.network.RegistryFriendlyByteBuf; +import net.minecraft.server.level.ServerPlayer; +import net.neoforged.neoforge.attachment.AttachmentSyncHandler; +import net.neoforged.neoforge.attachment.IAttachmentHolder; +import org.jetbrains.annotations.Nullable; +import tschipp.carryon.common.carry.CarryOnData; + +public class CarryOnDataSyncHandler implements AttachmentSyncHandler { + @Override + public void write(RegistryFriendlyByteBuf registryFriendlyByteBuf, CarryOnData carryOnData, boolean b) { + CarryOnData.STREAM_CODEC.encode(registryFriendlyByteBuf, carryOnData); + } + + @Override + public @Nullable CarryOnData read(IAttachmentHolder iAttachmentHolder, RegistryFriendlyByteBuf registryFriendlyByteBuf, @Nullable CarryOnData carryOnData) { + return CarryOnData.STREAM_CODEC.decode(registryFriendlyByteBuf); + } + + @Override + public boolean sendToPlayer(IAttachmentHolder holder, ServerPlayer to) { + if (to.connection == null) + return false; + return AttachmentSyncHandler.super.sendToPlayer(holder, to); + } +} diff --git a/NeoForge/src/main/java/tschipp/carryon/platform/NeoForgePlatformHelper.java b/NeoForge/src/main/java/tschipp/carryon/platform/NeoForgePlatformHelper.java index 2098723..00ba272 100644 --- a/NeoForge/src/main/java/tschipp/carryon/platform/NeoForgePlatformHelper.java +++ b/NeoForge/src/main/java/tschipp/carryon/platform/NeoForgePlatformHelper.java @@ -20,6 +20,7 @@ package tschipp.carryon.platform; +import net.minecraft.nbt.CompoundTag; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.network.RegistryFriendlyByteBuf; import net.minecraft.network.codec.StreamCodec; @@ -35,7 +36,9 @@ import net.neoforged.neoforge.network.PacketDistributor; import net.neoforged.neoforge.network.handling.IPayloadHandler; import net.neoforged.neoforge.network.registration.PayloadRegistrar; import tschipp.carryon.CarryOnCommonClient; +import tschipp.carryon.CarryOnNeoForge; import tschipp.carryon.CarryOnNeoForgeClient; +import tschipp.carryon.common.carry.CarryOnData; import tschipp.carryon.config.BuiltConfig; import tschipp.carryon.config.neoforge.ConfigLoaderImpl; import tschipp.carryon.networking.PacketBase; @@ -106,4 +109,14 @@ public class NeoForgePlatformHelper implements IPlatformHelper { public void sendPacketToPlayer(ResourceLocation id, PacketBase packet, ServerPlayer player) { PacketDistributor.sendToPlayer(player, packet); } + + @Override + public CarryOnData getCarryData(Player player) { + return player.getData(CarryOnNeoForge.CARRY_ON_DATA_ATTACHMENT); + } + + @Override + public void setCarryData(Player player, CarryOnData data) { + player.setData(CarryOnNeoForge.CARRY_ON_DATA_ATTACHMENT, data); + } } diff --git a/buildSrc/src/main/groovy/multiloader-common.gradle b/buildSrc/src/main/groovy/multiloader-common.gradle index 982e675..9efb48d 100644 --- a/buildSrc/src/main/groovy/multiloader-common.gradle +++ b/buildSrc/src/main/groovy/multiloader-common.gradle @@ -4,7 +4,7 @@ plugins { } base { - archivesName = "${mod_id}-${project.name}-${minecraft_version}" + archivesName = "${mod_id}-${project.name.toLowerCase()}-${minecraft_version}" } java { diff --git a/gradle.properties b/gradle.properties index 8a9ef2d..51e46db 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,36 +1,36 @@ # Project -version=2.6.0 +version=2.7.0 group=tschipp.carryon # Common -minecraft_version=1.21.7 +minecraft_version=1.21.8 mod_name=Carry On mod_author=Tschipp, PurpliciousCow mod_id=carryon license=GNU LGPLv3 credits= description=Carry On is a simple mod that improves game interaction by allowing players to pick up, carry, and place single block Tile Entities using only their empty hands. -minecraft_version_range=[1.21.7, 1.22) -neo_form_version=1.21.7-20250711.194848 +minecraft_version_range=[1.21.8, 1.22) +neo_form_version=1.21.8-20250717.133445 java_version=21 -parchment_version=2025.07.18 +parchment_version=2025.07.20 mod_dev_version=2.0.107 # Forge -forge_version=57.0.3 -forge_loader_version_range=[56,) -parchment_mappings=2025.07.18-1.21.7 +forge_version=58.0.10 +forge_loader_version_range=[57,) +parchment_mappings=2025.07.20-1.21.8 //forge_ats_enabled=true # Fabric -fabric_version=0.129.0+1.21.7 +fabric_version=0.132.0+1.21.8 fabric_loader_version=0.17.2 -parchment_mappings_fabric=1.21.7:2025.07.18 +parchment_mappings_fabric=1.21.8:2025.07.20 # Neoforge -neoforge_version=21.7.25-beta +neoforge_version=21.8.36 neoforge_loader_version_range=[4,) -neogradle.subsystems.parchment.minecraftVersion=1.21.7 -neogradle.subsystems.parchment.mappingsVersion=2025.07.18 +neogradle.subsystems.parchment.minecraftVersion=1.21.8 +neogradle.subsystems.parchment.mappingsVersion=2025.07.20 # Gradle