feat: 升级到1.21.1,neoforge代码待测试

This commit is contained in:
叁玖领域 2026-05-11 17:36:27 +08:00
parent 4a22bbe4a9
commit fbaeaf857b
50 changed files with 832 additions and 410 deletions

View File

@ -1,4 +1,4 @@
plugins { plugins {
id 'fabric-loom' version '1.9-SNAPSHOT' apply(false) id 'fabric-loom' version '1.9-SNAPSHOT' apply false
id 'net.neoforged.moddev.legacyforge' version '2.0.103' apply(false) id 'net.neoforged.moddev' version '2.0.141' apply false
} }

View File

@ -40,6 +40,7 @@ tasks.named('javadoc', Javadoc).configure {
options.memberLevel = JavadocMemberLevel.PUBLIC options.memberLevel = JavadocMemberLevel.PUBLIC
options.addBooleanOption('Xdoclint:none', true) options.addBooleanOption('Xdoclint:none', true)
options.addStringOption('doctitle', "${mod_id} ${minecraft_version} ${version} Javadoc") options.addStringOption('doctitle', "${mod_id} ${minecraft_version} ${version} Javadoc")
} }
tasks.named('sourcesJar', Jar) { tasks.named('sourcesJar', Jar) {

View File

@ -24,7 +24,7 @@ public class Lib39RecipeProvider extends RecipeProvider {
} }
@Override @Override
protected void buildRecipes(RecipeOutput recipeOutput) { public void buildRecipes(RecipeOutput recipeOutput) {
ShapelessRecipeBuilder.shapeless(RecipeCategory.MISC, Lib39Items.DOLL.get()) ShapelessRecipeBuilder.shapeless(RecipeCategory.MISC, Lib39Items.DOLL.get())
.requires(ItemTags.WOOL) .requires(ItemTags.WOOL)
.requires(Items.ARMOR_STAND) .requires(Items.ARMOR_STAND)

View File

@ -17,18 +17,14 @@ import top.r3944realms.lib39.util.MathUtil;
import top.r3944realms.lib39.util.lang.FourConsumer; import top.r3944realms.lib39.util.lang.FourConsumer;
import top.r3944realms.lib39.util.lang.Pair; import top.r3944realms.lib39.util.lang.Pair;
import javax.annotation.ParametersAreNonnullByDefault;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Objects; import java.util.Objects;
/** /**
* The type Wheel widget. * The type Wheel widget.
*
* @author QiuShui1012
*/ */
@MethodsReturnNonnullByDefault
@ParametersAreNonnullByDefault
public class WheelWidget extends AbstractWidget { public class WheelWidget extends AbstractWidget {
/** /**
* The constant IGNORE_CURSOR_MOVE_LENGTH. * The constant IGNORE_CURSOR_MOVE_LENGTH.
@ -749,8 +745,15 @@ public class WheelWidget extends AbstractWidget {
protected void updateWidgetNarration(NarrationElementOutput narrationElementOutput) { protected void updateWidgetNarration(NarrationElementOutput narrationElementOutput) {
} }
/** /**
* The type Wheel section. * The type Wheel section.
* @param center 中心
* @param angle 角度
* @param angleStart 开始角度
* @param angleEnd 结束角度
* @param subTitle 副标题
* @param renderer 渲染操作
*/ */
public record WheelSection( public record WheelSection(
Vector2f center, Vector2f center,

View File

@ -34,10 +34,21 @@ public class DollModel extends Model {
@Nullable @Nullable
private IDollPose currentPose; private IDollPose currentPose;
/**
* Gets current pose.
*
* @return the current pose
*/
@Nullable @Nullable
public IDollPose getCurrentPose() { public IDollPose getCurrentPose() {
return currentPose; return currentPose;
} }
/**
* Sets doll pose.
*
* @param dollPose the doll pose
*/
public void setDollPose(@NotNull IDollPose dollPose) { public void setDollPose(@NotNull IDollPose dollPose) {
this.currentPose = dollPose; this.currentPose = dollPose;
this.head.loadPose(dollPose.getHeadPose()); this.head.loadPose(dollPose.getHeadPose());
@ -50,6 +61,9 @@ public class DollModel extends Model {
this.leftLeg.loadPose(dollPose.getLeftLegPose()); this.leftLeg.loadPose(dollPose.getLeftLegPose());
} }
/**
* Reset pose.
*/
public void resetPose() { public void resetPose() {
this.currentPose = DollPoses.DEFAULT; this.currentPose = DollPoses.DEFAULT;
this.head.resetPose(); this.head.resetPose();
@ -61,6 +75,7 @@ public class DollModel extends Model {
this.rightLeg.resetPose(); this.rightLeg.resetPose();
this.leftLeg.resetPose(); this.leftLeg.resetPose();
} }
/** /**
* Instantiates a new Doll model. * Instantiates a new Doll model.
* *
@ -77,6 +92,7 @@ public class DollModel extends Model {
this.rightLeg = root.getChild("right_leg"); this.rightLeg = root.getChild("right_leg");
this.leftLeg = root.getChild("left_leg"); this.leftLeg = root.getChild("left_leg");
} }
/** /**
* Create body layer layer definition. * Create body layer layer definition.
* *

View File

@ -6,7 +6,13 @@ import net.minecraft.world.phys.Vec3;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import top.r3944realms.lib39.Lib39; import top.r3944realms.lib39.Lib39;
/**
* The enum Doll poses.
*/
public enum DollPoses implements IDollPose{ public enum DollPoses implements IDollPose{
/**
* Default doll poses.
*/
DEFAULT( DEFAULT(
"default", "default",
PartPose.offset(0.0F, 9.0F, 0.0F), PartPose.offset(0.0F, 9.0F, 0.0F),

View File

@ -5,15 +5,65 @@ import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.phys.Vec3; import net.minecraft.world.phys.Vec3;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
/**
* The interface Doll pose.
*/
public interface IDollPose { public interface IDollPose {
/**
* Gets id.
*
* @return the id
*/
@NotNull ResourceLocation getId(); @NotNull ResourceLocation getId();
/**
* Gets total offset.
*
* @return the total offset
*/
@NotNull default Vec3 getTotalOffset() { @NotNull default Vec3 getTotalOffset() {
return Vec3.ZERO; return Vec3.ZERO;
} }
/**
* Gets head pose.
*
* @return the head pose
*/
@NotNull PartPose getHeadPose(); @NotNull PartPose getHeadPose();
/**
* Gets body pose.
*
* @return the body pose
*/
@NotNull PartPose getBodyPose(); @NotNull PartPose getBodyPose();
/**
* Gets right arm pose.
*
* @return the right arm pose
*/
@NotNull PartPose getRightArmPose(); @NotNull PartPose getRightArmPose();
/**
* Gets left arm pose.
*
* @return the left arm pose
*/
@NotNull PartPose getLeftArmPose(); @NotNull PartPose getLeftArmPose();
/**
* Gets right leg pose.
*
* @return the right leg pose
*/
@NotNull PartPose getRightLegPose(); @NotNull PartPose getRightLegPose();
/**
* Gets left leg pose.
*
* @return the left leg pose
*/
@NotNull PartPose getLeftLegPose(); @NotNull PartPose getLeftLegPose();
} }

View File

@ -5,20 +5,17 @@ import net.minecraft.Util;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.core.HolderLookup; import net.minecraft.core.HolderLookup;
import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.NbtUtils;
import net.minecraft.network.protocol.game.ClientboundBlockEntityDataPacket; import net.minecraft.network.protocol.game.ClientboundBlockEntityDataPacket;
import net.minecraft.world.item.component.ResolvableProfile; import net.minecraft.world.item.component.ResolvableProfile;
import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.entity.SkullBlockEntity; import net.minecraft.world.level.block.entity.SkullBlockEntity;
import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.BlockState;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable;
import top.r3944realms.lib39.core.register.Lib39BlockEntities; import top.r3944realms.lib39.core.register.Lib39BlockEntities;
import top.r3944realms.lib39.util.GameProfileHelper; import top.r3944realms.lib39.util.GameProfileHelper;
import top.r3944realms.lib39.util.nbt.NBTReader; import top.r3944realms.lib39.util.nbt.NBTReader;
import top.r3944realms.lib39.util.nbt.NBTWriter; import top.r3944realms.lib39.util.nbt.NBTWriter;
import javax.annotation.Nullable;
/** /**
* The type Doll block entity. * The type Doll block entity.
*/ */

View File

@ -10,11 +10,10 @@ import net.minecraft.commands.Commands;
import net.minecraft.network.chat.Component; import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.MutableComponent; import net.minecraft.network.chat.MutableComponent;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import top.r3944realms.lib39.base.datagen.value.Lib39LangKey; import top.r3944realms.lib39.base.datagen.value.Lib39LangKey;
import top.r3944realms.lib39.platform.Services; import top.r3944realms.lib39.platform.Services;
import javax.annotation.Nullable;
/** /**
* The interface Help command. * The interface Help command.
*/ */

View File

@ -1109,6 +1109,8 @@ public class CommandNode {
/** /**
* 葉子節點配置記錄 * 葉子節點配置記錄
* @param description 介绍
* @param parameters 参数列表
*/ */
public record LeafConfig(@NotNull MutableComponent description, public record LeafConfig(@NotNull MutableComponent description,
@Nullable List<Parameter> parameters) { @Nullable List<Parameter> parameters) {

View File

@ -8,6 +8,8 @@ import java.util.List;
/** /**
* The type Parameter. * The type Parameter.
* @param name 参数名
* @param required 是否必须
*/ */
public record Parameter(String name, boolean required) { public record Parameter(String name, boolean required) {

View File

@ -98,6 +98,7 @@ public class GameProfileHelper {
} }
} }
/** /**
* The constant TAG_OWN_PROFILE. * The constant TAG_OWN_PROFILE.
*/ */

View File

@ -1,5 +1,3 @@
import net.fabricmc.loom.task.RemapJarTask
plugins { plugins {
id 'multiloader-loader' id 'multiloader-loader'
id 'fabric-loom' id 'fabric-loom'
@ -32,7 +30,7 @@ loom {
accessWidenerPath.set(project(":common").file("src/main/resources/${mod_id}.accesswidener")) accessWidenerPath.set(project(":common").file("src/main/resources/${mod_id}.accesswidener"))
} }
mixin { mixin {
defaultRefmapName.set("${mod_id}.refmap.json") defaultRefmapName.set("${mod_id}.fabric.refmap.json")
} }
runs { runs {
client { client {

View File

@ -1,7 +1,8 @@
package top.r3944realms.lib39.core.network; package top.r3944realms.lib39.core.network;
import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking; import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking;
import top.r3944realms.lib39.core.network.toClient.SyncNBTLookupDataEntityS2CPacket; import net.fabricmc.fabric.api.networking.v1.PayloadTypeRegistry;
import top.r3944realms.lib39.core.network.toClient.SyncNBTLookupDataEntityS2CPayload;
/** /**
* The type Fabric network handler. * The type Fabric network handler.
@ -12,10 +13,13 @@ public class FabricNetworkHandler {
* 注册客户端接收的数据包 * 注册客户端接收的数据包
*/ */
public static void registerClientReceivers() { public static void registerClientReceivers() {
ClientPlayNetworking.registerGlobalReceiver( PayloadTypeRegistry.playS2C().register(
SyncNBTLookupDataEntityS2CPacket.TYPE, SyncNBTLookupDataEntityS2CPayload.TYPE,
SyncNBTLookupDataEntityS2CPacket::handle SyncNBTLookupDataEntityS2CPayload.STREAM_CODEC
);
ClientPlayNetworking.registerGlobalReceiver(
SyncNBTLookupDataEntityS2CPayload.TYPE,
SyncNBTLookupDataEntityS2CPayload::handle
); );
} }
} }

View File

@ -1,18 +1,15 @@
package top.r3944realms.lib39.core.network.toClient; package top.r3944realms.lib39.core.network.toClient;
import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking; import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking;
import net.fabricmc.fabric.api.networking.v1.PacketSender;
import net.minecraft.client.player.LocalPlayer; import net.minecraft.client.player.LocalPlayer;
import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.CompoundTag;
import net.minecraft.network.FriendlyByteBuf; import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.network.RegistryFriendlyByteBuf; import net.minecraft.network.RegistryFriendlyByteBuf;
import net.minecraft.network.codec.StreamCodec; import net.minecraft.network.codec.StreamCodec;
import net.minecraft.network.protocol.PacketType;
import net.minecraft.network.protocol.common.custom.CustomPacketPayload; import net.minecraft.network.protocol.common.custom.CustomPacketPayload;
import net.minecraft.resources.ResourceLocation; import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.Entity;
import net.minecraft.world.level.Level; import net.minecraft.world.level.Level;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import top.r3944realms.lib39.Lib39; import top.r3944realms.lib39.Lib39;
import top.r3944realms.lib39.core.event.FabricCommonEventHandler; import top.r3944realms.lib39.core.event.FabricCommonEventHandler;
@ -23,9 +20,9 @@ import top.r3944realms.lib39.core.sync.SyncData2Manager;
import java.util.Optional; import java.util.Optional;
/** /**
* The type Sync nbt lookup data entity s 2 c packet. * The type Sync nbt lookup data entity s 2 c payload.
*/ */
public record SyncNBTLookupDataEntityS2CPacket(int entityId, ResourceLocation id, CompoundTag data) implements CustomPacketPayload { public record SyncNBTLookupDataEntityS2CPayload(int entityId, ResourceLocation id, CompoundTag data) implements CustomPacketPayload {
/** /**
* The constant SYNC_NBT_LOOKUP_PACKET_ID. * The constant SYNC_NBT_LOOKUP_PACKET_ID.
*/ */
@ -34,7 +31,14 @@ public record SyncNBTLookupDataEntityS2CPacket(int entityId, ResourceLocation id
/** /**
* The constant TYPE. * The constant TYPE.
*/ */
public static final Type<SyncNBTLookupDataEntityS2CPacket> TYPE = new Type<>(SYNC_NBT_LOOKUP_PACKET_ID); public static final Type<SyncNBTLookupDataEntityS2CPayload> TYPE = new Type<>(SYNC_NBT_LOOKUP_PACKET_ID);
/**
* Stream codec for serializing/deserializing the packet.
*/
public static final StreamCodec<RegistryFriendlyByteBuf, SyncNBTLookupDataEntityS2CPayload> STREAM_CODEC =
StreamCodec.ofMember(SyncNBTLookupDataEntityS2CPayload::write, SyncNBTLookupDataEntityS2CPayload::new);
/** /**
* Instantiates a new Sync nbt data s 2 c pack. * Instantiates a new Sync nbt data s 2 c pack.
@ -42,7 +46,7 @@ public record SyncNBTLookupDataEntityS2CPacket(int entityId, ResourceLocation id
* @param entityId the entity id * @param entityId the entity id
* @param data the data * @param data the data
*/ */
public SyncNBTLookupDataEntityS2CPacket(int entityId, @NotNull NBTEntitySyncData data) { public SyncNBTLookupDataEntityS2CPayload(int entityId, @NotNull NBTEntitySyncData data) {
this(entityId, data.id(), data.serializeNBT()); this(entityId, data.id(), data.serializeNBT());
} }
@ -51,48 +55,48 @@ public record SyncNBTLookupDataEntityS2CPacket(int entityId, ResourceLocation id
* *
* @param buf the buffer * @param buf the buffer
*/ */
public SyncNBTLookupDataEntityS2CPacket(RegistryFriendlyByteBuf buf) { public SyncNBTLookupDataEntityS2CPayload(RegistryFriendlyByteBuf buf) {
this(buf.readInt(), buf.readResourceLocation(), buf.readNbt()); this(buf.readInt(), buf.readResourceLocation(), buf.readNbt());
} }
/**
* Write.
*
* @param friendlyByteBuf the friendly byte buf
*/
public void write(@NotNull FriendlyByteBuf friendlyByteBuf) { public void write(@NotNull FriendlyByteBuf friendlyByteBuf) {
friendlyByteBuf.writeInt(entityId); friendlyByteBuf.writeInt(entityId);
friendlyByteBuf.writeResourceLocation(id); friendlyByteBuf.writeResourceLocation(id);
friendlyByteBuf.writeNbt(data); friendlyByteBuf.writeNbt(data);
} }
/**
* Stream codec for serializing/deserializing the packet.
*/
public static final StreamCodec<RegistryFriendlyByteBuf, SyncNBTLookupDataEntityS2CPacket> STREAM_CODEC =
StreamCodec.ofMember(SyncNBTLookupDataEntityS2CPacket::write, SyncNBTLookupDataEntityS2CPacket::new);
/** /**
* Receive. * Receive.
* *
* @param packet the packet * @param payload the packet
* @param context the context * @param context the context
*/ */
public static void handle(@NotNull SyncNBTLookupDataEntityS2CPacket packet, ClientPlayNetworking.Context context) { public static void handle(@NotNull SyncNBTLookupDataEntityS2CPayload payload, ClientPlayNetworking.Context context) {
LocalPlayer localPlayer = context.player(); LocalPlayer localPlayer = context.player();
Level level = localPlayer.level(); Level level = localPlayer.level();
Entity entity = level.getEntity(packet.entityId); Entity entity = level.getEntity(payload.entityId);
if (entity != null) { if (entity != null) {
Optional<SyncData2Manager.DataProvider<Entity, ISyncData<?>>> lookupOpt = Optional<SyncData2Manager.DataProvider<Entity, ISyncData<?>>> lookupOpt =
FabricCommonEventHandler FabricCommonEventHandler
.getSyncData2Manager() .getSyncData2Manager()
.getDataProvider(packet.id); .getDataProvider(payload.id);
lookupOpt.flatMap(dataProvider -> dataProvider.getData(entity)) lookupOpt.flatMap(dataProvider -> dataProvider.getData(entity))
.ifPresent(lookup -> { .ifPresent(lookup -> {
if (lookup instanceof NBTEntitySyncData nbtLookup) { if (lookup instanceof NBTEntitySyncData nbtLookup) {
CompoundTag current = nbtLookup.serializeNBT(); CompoundTag current = nbtLookup.serializeNBT();
if (!current.equals(packet.data)) { if (!current.equals(payload.data)) {
nbtLookup.deserializeNBT(packet.data); nbtLookup.deserializeNBT(payload.data);
} }
} else { } else {
Lib39.LOGGER.debug("Unhandled sync data: {}", packet.data); Lib39.LOGGER.debug("Unhandled sync data: {}", payload.data);
} }
}); });
} }

View File

@ -5,7 +5,7 @@ import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer; import net.minecraft.server.level.ServerPlayer;
import net.minecraft.server.players.PlayerList; import net.minecraft.server.players.PlayerList;
import top.r3944realms.lib39.core.event.FabricCommonEventHandler; import top.r3944realms.lib39.core.event.FabricCommonEventHandler;
import top.r3944realms.lib39.core.network.toClient.SyncNBTLookupDataEntityS2CPacket; import top.r3944realms.lib39.core.network.toClient.SyncNBTLookupDataEntityS2CPayload;
import java.util.List; import java.util.List;
@ -19,8 +19,8 @@ public interface IFabricUpdate extends IUpdate {
PlayerList playerList = serverLevel.getServer().getPlayerList(); PlayerList playerList = serverLevel.getServer().getPlayerList();
List<ServerPlayer> players = playerList.getPlayers(); List<ServerPlayer> players = playerList.getPlayers();
for (ServerPlayer player : players) { for (ServerPlayer player : players) {
if (ServerPlayNetworking.canSend(player, SyncNBTLookupDataEntityS2CPacket.TYPE)) { if (ServerPlayNetworking.canSend(player, SyncNBTLookupDataEntityS2CPayload.TYPE)) {
ServerPlayNetworking.send(player, new SyncNBTLookupDataEntityS2CPacket(getSyncData().entityId(), getSyncData())); ServerPlayNetworking.send(player, new SyncNBTLookupDataEntityS2CPayload(getSyncData().entityId(), getSyncData()));
} }
} }
} }

View File

@ -61,6 +61,9 @@ public record FabricClientDataPacket(AbstractedTestSyncData clientData, int targ
/** /**
* Handle packet on server side. * Handle packet on server side.
* Register this with ServerPlayNetworking.registerGlobalReceiver * Register this with ServerPlayNetworking.registerGlobalReceiver
*
* @param packet the packet
* @param context the context
*/ */
public static void handle(FabricClientDataPacket packet, ServerPlayNetworking.Context context) { public static void handle(FabricClientDataPacket packet, ServerPlayNetworking.Context context) {
ServerPlayer serverPlayer = context.player(); ServerPlayer serverPlayer = context.player();

View File

@ -46,6 +46,7 @@ public abstract class MixinMinecraft extends ReentrantBlockableEventLoop<Runnabl
* Set clientLevel callback. * Set clientLevel callback.
* *
* @param clientLevel the clientLevel client * @param clientLevel the clientLevel client
* @param reason the reason
* @param original the original * @param original the original
*/ */
@WrapMethod(method = "setLevel") @WrapMethod(method = "setLevel")
@ -57,6 +58,7 @@ public abstract class MixinMinecraft extends ReentrantBlockableEventLoop<Runnabl
/** /**
* Clear level callback. * Clear level callback.
* *
* @param nextScreen the next screen
* @param original the original * @param original the original
*/ */
@WrapMethod(method = "clearClientLevel") @WrapMethod(method = "clearClientLevel")
@ -69,6 +71,7 @@ public abstract class MixinMinecraft extends ReentrantBlockableEventLoop<Runnabl
* Set level setup. * Set level setup.
* *
* @param level the level client * @param level the level client
* @param reason the reason
* @param ci the ci * @param ci the ci
* @param services the services * @param services the services
*/ */

View File

@ -2,7 +2,7 @@
"required": true, "required": true,
"minVersion": "0.8", "minVersion": "0.8",
"package": "top.r3944realms.lib39.mixin", "package": "top.r3944realms.lib39.mixin",
"refmap": "${mod_id}.refmap.json", "refmap": "${mod_id}.fabric.refmap.json",
"compatibilityLevel": "JAVA_18", "compatibilityLevel": "JAVA_18",
"mixins": [ "mixins": [
"MixinApiLookUpImpl", "MixinApiLookUpImpl",

View File

@ -17,8 +17,8 @@ credits=Logo created by Shanyi43, edited by R3944Realms
description=Lib39 is a general-purpose dependency library that provides utility methods and core functionality for other mods. description=Lib39 is a general-purpose dependency library that provides utility methods and core functionality for other mods.
minecraft_version_range=[1.20.1, 1.22) minecraft_version_range=[1.20.1, 1.22)
# The version of ParchmentMC that is used, see https://parchmentmc.org/docs/getting-started#choose-a-version for new versions # The version of ParchmentMC that is used, see https://parchmentmc.org/docs/getting-started#choose-a-version for new versions
parchment_minecraft=1.21 parchment_minecraft=1.21.1
parchment_version=2024.11.10 parchment_version=2024.11.17
neo_form_version=1.21.1-20240808.144430 neo_form_version=1.21.1-20240808.144430
# NeoForge # NeoForge

View File

@ -14,9 +14,15 @@ import top.r3944realms.lib39.example.NeoForgeLib39Example;
*/ */
@Mod(Lib39.MOD_ID) @Mod(Lib39.MOD_ID)
public class Lib39NeoForge { public class Lib39NeoForge {
/**
* The constant modEventBus.
*/
public static IEventBus modEventBus; public static IEventBus modEventBus;
/** /**
* Instantiates a new Lib 39. * Instantiates a new Lib 39.
*
* @param modEventBus the mod event bus
*/ */
public Lib39NeoForge(IEventBus modEventBus) { public Lib39NeoForge(IEventBus modEventBus) {
Lib39.initialize(); Lib39.initialize();
@ -28,35 +34,38 @@ public class Lib39NeoForge {
/** /**
* Initialize. * Initialize.
*
* @param modEventBus the mod event bus
*/ */
public static void initialize(IEventBus modEventBus) { public static void initialize(IEventBus modEventBus) {
Lib39.LOGGER.info("[Lib39-Forge] Hello Forge"); Lib39.LOGGER.info("[Lib39-NeoForge] Hello NeoForge");
NeoForgeLib39Blocks.register(modEventBus); NeoForgeLib39Blocks.register(modEventBus);
NeoForgeLib39Items.register(modEventBus); NeoForgeLib39Items.register(modEventBus);
NeoForgeLib39BlockEntities.register(modEventBus); NeoForgeLib39BlockEntities.register(modEventBus);
NeoForgeLib39SoundEvents.register(modEventBus); NeoForgeLib39SoundEvents.register(modEventBus);
NetworkHandler.register();
if (Lib39.shouldRegisterExamples()) { if (Lib39.shouldRegisterExamples()) {
Lib39.LOGGER.info("[Lib39-Forge] Registering Examples"); Lib39.LOGGER.info("[Lib39-NeoForge] Registering Examples");
registerExamples(modEventBus); registerExamples(modEventBus);
} }
Lib39.LOGGER.info("[Lib39-Forge] Finished Initializing."); Lib39.LOGGER.info("[Lib39-NeoForge] Finished Initializing.");
} }
/** /**
* Register examples. * Register examples.
*
* @param modEventBus the mod event bus
*/ */
static void registerExamples(IEventBus modEventBus) { static void registerExamples(IEventBus modEventBus) {
Lib39.LOGGER.info("[Lib39-Forge] Starting example demonstrations"); Lib39.LOGGER.info("[Lib39-NeoForge] Starting example demonstrations");
try { try {
// 创建示例实例并演示功能 // 创建示例实例并演示功能
NeoForgeLib39Example example = new NeoForgeLib39Example(modEventBus); NeoForgeLib39Example example = new NeoForgeLib39Example(modEventBus);
example.demonstrateFeature(); example.demonstrateFeature();
Lib39.LOGGER.info("[Lib39-Forge] Example demonstrations completed successfully"); Lib39.LOGGER.info("[Lib39-NeoForge] Example demonstrations completed successfully");
} catch (Exception e) { } catch (Exception e) {
Lib39.LOGGER.error("[Lib39-Forge] Failed to demonstrate examples", e); Lib39.LOGGER.error("[Lib39-NeoForge] Failed to demonstrate examples", e);
} }
} }
} }

View File

@ -2,6 +2,7 @@ package top.r3944realms.lib39.api.event;
import net.minecraft.resources.ResourceLocation; import net.minecraft.resources.ResourceLocation;
import net.neoforged.bus.api.Event; import net.neoforged.bus.api.Event;
import net.neoforged.neoforge.capabilities.EntityCapability;
import top.r3944realms.lib39.core.sync.ISyncData; import top.r3944realms.lib39.core.sync.ISyncData;
import top.r3944realms.lib39.core.sync.ISyncManager; import top.r3944realms.lib39.core.sync.ISyncManager;
import top.r3944realms.lib39.core.sync.SyncData2CapManager; import top.r3944realms.lib39.core.sync.SyncData2CapManager;
@ -45,8 +46,8 @@ public class SyncManagerRegisterEvent extends Event {
*/ */
public <K, T extends ISyncData<?>> void registerSyncManager( public <K, T extends ISyncData<?>> void registerSyncManager(
ResourceLocation id, ResourceLocation id,
ISyncManager<Capability<T>, T> syncManager, ISyncManager<EntityCapability<T, Void>, T> syncManager,
Capability<T> capability EntityCapability<T, Void> capability
) { ) {
syncs2Manager.registerManager(id, syncManager, capability); syncs2Manager.registerManager(id, syncManager, capability);
} }
@ -87,7 +88,7 @@ public class SyncManagerRegisterEvent extends Event {
* @param id 必须先注册安全同步管理器再绑定Cap否则会抛出{@link IllegalStateException 未找到对应安全同步管理器} * @param id 必须先注册安全同步管理器再绑定Cap否则会抛出{@link IllegalStateException 未找到对应安全同步管理器}
* @param capability the capability * @param capability the capability
*/ */
public <T extends ISyncData<?>> void bindCapability(ResourceLocation id, Capability<T> capability) { public <T extends ISyncData<?>> void bindCapability(ResourceLocation id, EntityCapability<T, Void> capability) {
syncs2Manager.bindCapability(id, capability); syncs2Manager.bindCapability(id, capability);
} }
@ -112,8 +113,8 @@ public class SyncManagerRegisterEvent extends Event {
*/ */
public <K, T extends ISyncData<?>> void registerComplete( public <K, T extends ISyncData<?>> void registerComplete(
ResourceLocation id, ResourceLocation id,
ISyncManager<Capability<T>, T> syncManager, ISyncManager<EntityCapability<T, Void>, T> syncManager,
Capability<T> capability, EntityCapability<T, Void> capability,
Class<?>... allowedEntityClasses Class<?>... allowedEntityClasses
) { ) {
registerSyncManager(id, syncManager, capability); registerSyncManager(id, syncManager, capability);

View File

@ -73,7 +73,7 @@ public class Lib39BaseDataGenEvent {
private static void LootTableDataGenerate(@NotNull GatherDataEvent event) { private static void LootTableDataGenerate(@NotNull GatherDataEvent event) {
event.getGenerator().addProvider( event.getGenerator().addProvider(
event.includeServer(), event.includeServer(),
(DataProvider.Factory<SimpleLootTableProvider>) pOutput -> new SimpleLootTableProvider(pOutput, new SubProvidersWrapper().addBlockEntry(new Lib39BlockLootTable())) (DataProvider.Factory<SimpleLootTableProvider>) pOutput -> new SimpleLootTableProvider(pOutput, new SubProvidersWrapper().addBlockEntry(new Lib39BlockLootTable()), event.getLookupProvider())
); );
} }
private static void RecipeGenerator(@NotNull GatherDataEvent event) { private static void RecipeGenerator(@NotNull GatherDataEvent event) {

View File

@ -18,7 +18,15 @@ public class NeoForgeDollItem extends DollItem {
super(properties); super(properties);
} }
/**
* The type Client opt.
*/
public static class ClientOpt implements IClientOnly { public static class ClientOpt implements IClientOnly {
/**
* Gets extensions.
*
* @return the extensions
*/
public static IClientItemExtensions getExtensions() { public static IClientItemExtensions getExtensions() {
return IClientOnly.check(() -> new IClientItemExtensions() { return IClientOnly.check(() -> new IClientItemExtensions() {
@Override @Override

View File

@ -67,6 +67,12 @@ public class ClientEventHandler {
public static void registerLayerDefinitions(EntityRenderersEvent.@NotNull RegisterLayerDefinitions event) { public static void registerLayerDefinitions(EntityRenderersEvent.@NotNull RegisterLayerDefinitions event) {
event.registerLayerDefinition(DollModel.LAYER_LOCATION, DollModel::createBodyLayer); event.registerLayerDefinition(DollModel.LAYER_LOCATION, DollModel::createBodyLayer);
} }
/**
* On register client ex.
*
* @param event the event
*/
@SubscribeEvent @SubscribeEvent
public static void onRegisterClientEx (@NotNull RegisterClientExtensionsEvent event) { public static void onRegisterClientEx (@NotNull RegisterClientExtensionsEvent event) {
event.registerItem(NeoForgeDollItem.ClientOpt.getExtensions(), Lib39Items.DOLL.get()); event.registerItem(NeoForgeDollItem.ClientOpt.getExtensions(), Lib39Items.DOLL.get());

View File

@ -3,18 +3,20 @@ package top.r3944realms.lib39.core.event;
import com.mojang.authlib.GameProfile; import com.mojang.authlib.GameProfile;
import net.minecraft.Util; import net.minecraft.Util;
import net.minecraft.client.multiplayer.ClientLevel; import net.minecraft.client.multiplayer.ClientLevel;
import net.minecraft.core.component.DataComponents;
import net.minecraft.network.chat.Component; import net.minecraft.network.chat.Component;
import net.minecraft.resources.ResourceKey; import net.minecraft.resources.ResourceKey;
import net.minecraft.resources.ResourceLocation; import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.CreativeModeTab; import net.minecraft.world.item.CreativeModeTab;
import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Items; import net.minecraft.world.item.Items;
import net.minecraft.world.item.component.ResolvableProfile;
import net.minecraft.world.level.Level; import net.minecraft.world.level.Level;
import net.minecraft.world.level.LevelAccessor; import net.minecraft.world.level.LevelAccessor;
import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.entity.SkullBlockEntity;
import net.neoforged.bus.api.SubscribeEvent; import net.neoforged.bus.api.SubscribeEvent;
import net.neoforged.fml.common.EventBusSubscriber; import net.neoforged.fml.common.EventBusSubscriber;
import net.neoforged.fml.event.lifecycle.FMLCommonSetupEvent; import net.neoforged.fml.event.lifecycle.FMLCommonSetupEvent;
@ -26,11 +28,14 @@ import net.neoforged.neoforge.event.RegisterCommandsEvent;
import net.neoforged.neoforge.event.entity.EntityJoinLevelEvent; import net.neoforged.neoforge.event.entity.EntityJoinLevelEvent;
import net.neoforged.neoforge.event.entity.EntityLeaveLevelEvent; import net.neoforged.neoforge.event.entity.EntityLeaveLevelEvent;
import net.neoforged.neoforge.event.level.LevelEvent; import net.neoforged.neoforge.event.level.LevelEvent;
import net.neoforged.neoforge.event.tick.ServerTickEvent;
import net.neoforged.neoforge.network.event.RegisterPayloadHandlersEvent;
import top.r3944realms.lib39.Lib39; import top.r3944realms.lib39.Lib39;
import top.r3944realms.lib39.api.event.SyncManagerRegisterEvent; import top.r3944realms.lib39.api.event.SyncManagerRegisterEvent;
import top.r3944realms.lib39.base.command.Lib39HelpCommand; import top.r3944realms.lib39.base.command.Lib39HelpCommand;
import top.r3944realms.lib39.base.datagen.Lib39BaseDataGenEvent; import top.r3944realms.lib39.base.datagen.Lib39BaseDataGenEvent;
import top.r3944realms.lib39.content.item.DollItem; import top.r3944realms.lib39.content.item.DollItem;
import top.r3944realms.lib39.core.network.NetworkHandler;
import top.r3944realms.lib39.core.register.Lib39Items; import top.r3944realms.lib39.core.register.Lib39Items;
import top.r3944realms.lib39.core.sync.ISyncData; import top.r3944realms.lib39.core.sync.ISyncData;
import top.r3944realms.lib39.core.sync.SyncData2CapManager; import top.r3944realms.lib39.core.sync.SyncData2CapManager;
@ -132,14 +137,12 @@ public class CommonEventHandler {
* @param event the event * @param event the event
*/ */
@SubscribeEvent @SubscribeEvent
public static void onServerTick(TickEvent.ServerTickEvent event) { public static void onServerTick(ServerTickEvent.Post event) {
if (event.phase == TickEvent.Phase.END) {
if (syncData2Manager == null) return; if (syncData2Manager == null) return;
if (event.getServer().getTickCount() % 10 == 0) if (event.getServer().getTickCount() % 10 == 0)
syncData2Manager.forEach(((resourceLocation, iSyncManager) -> iSyncManager.foreach(ISyncData::markDirty))); syncData2Manager.forEach(((resourceLocation, iSyncManager) -> iSyncManager.foreach(ISyncData::markDirty)));
syncData2Manager.forEach(((resourceLocation, iSyncManager) -> iSyncManager.foreach(ISyncData::checkIfDirtyThenUpdate))); syncData2Manager.forEach(((resourceLocation, iSyncManager) -> iSyncManager.foreach(ISyncData::checkIfDirtyThenUpdate)));
} }
}
/** /**
* On anvil rename. * On anvil rename.
@ -150,18 +153,27 @@ public class CommonEventHandler {
public static void onAnvilRename(AnvilUpdateEvent event) { public static void onAnvilRename(AnvilUpdateEvent event) {
if (event.getLeft().getItem() instanceof DollItem) { if (event.getLeft().getItem() instanceof DollItem) {
String name = event.getName(); String name = event.getName();
Player player = event.getPlayer();
if (name != null && name.length() < 15) { if (name != null && name.length() < 15) {
GameProfile profile = new GameProfile(Util.NIL_UUID, name); GameProfile profile = new GameProfile(Util.NIL_UUID, name);
ItemStack copied = Lib39Items.DOLL.get().getDefaultInstance(); ItemStack copied = Lib39Items.DOLL.get().getDefaultInstance();
SkullBlockEntity.updateGameprofile(profile, ResolvableProfile resolvableProfile = new ResolvableProfile(profile);
profile1 -> GameProfileHelper.saveProfileToItemStack(copied, profile1) if (!resolvableProfile.isResolved()) {
); resolvableProfile.resolve().thenAcceptAsync(resolved -> {
// 解析完成后保存到 ItemStack
GameProfile resolvedProfile = resolved.gameProfile();
GameProfileHelper.saveProfileToItemStack(copied, resolvedProfile);
}, player.getServer());
} else {
GameProfileHelper.saveProfileToItemStack(copied, profile);
}
copied.setCount(event.getLeft().getCount()); copied.setCount(event.getLeft().getCount());
event.setOutput(copied); event.setOutput(copied);
event.setCost(1); event.setCost(1);
} else { } else {
ItemStack defaultInstance = Items.BARRIER.getDefaultInstance(); ItemStack defaultInstance = Items.BARRIER.getDefaultInstance();
defaultInstance.setHoverName(Component.translatable("invalid.player_name.too_long")); defaultInstance.set(DataComponents.CUSTOM_NAME,
Component.translatable("invalid.player_name.too_long"));
event.setOutput(defaultInstance); event.setOutput(defaultInstance);
} }
} }
@ -266,6 +278,16 @@ public class CommonEventHandler {
} }
} }
/**
* On register payload.
*
* @param event the event
*/
@SubscribeEvent
public static void onRegisterPayload (RegisterPayloadHandlersEvent event) {
NetworkHandler.register(event);
}
/** /**
* Gather data. * Gather data.
* *

View File

@ -1,9 +1,10 @@
package top.r3944realms.lib39.core.event; package top.r3944realms.lib39.core.event;
import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerLevel;
import net.minecraftforge.api.distmarker.Dist; import net.neoforged.api.distmarker.Dist;
import net.minecraftforge.event.level.LevelEvent; import net.neoforged.bus.api.SubscribeEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent; import net.neoforged.fml.common.EventBusSubscriber;
import net.neoforged.neoforge.event.level.LevelEvent;
import top.r3944realms.lib39.Lib39; import top.r3944realms.lib39.Lib39;
import top.r3944realms.lib39.util.ILevelHelper; import top.r3944realms.lib39.util.ILevelHelper;
@ -19,7 +20,7 @@ public class ServerEventHandler {
/** /**
* The type Game. * The type Game.
*/ */
@net.minecraftforge.fml.common.Mod.EventBusSubscriber(value = Dist.DEDICATED_SERVER, bus = net.minecraftforge.fml.common.Mod.EventBusSubscriber.Bus.FORGE, modid = Lib39.MOD_ID) @EventBusSubscriber(value = Dist.DEDICATED_SERVER, bus = EventBusSubscriber.Bus.GAME, modid = Lib39.MOD_ID)
public static class Game extends ServerEventHandler { public static class Game extends ServerEventHandler {
/** /**
* Register layer definitions. * Register layer definitions.

View File

@ -1,72 +1,28 @@
package top.r3944realms.lib39.core.network; package top.r3944realms.lib39.core.network;
import net.minecraft.server.level.ServerPlayer; import net.neoforged.neoforge.network.event.RegisterPayloadHandlersEvent;
import net.minecraftforge.network.NetworkDirection; import net.neoforged.neoforge.network.registration.PayloadRegistrar;
import net.minecraftforge.network.NetworkRegistry;
import net.minecraftforge.network.PacketDistributor;
import net.minecraftforge.network.simple.SimpleChannel;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import top.r3944realms.lib39.Lib39; import top.r3944realms.lib39.Lib39;
import top.r3944realms.lib39.core.network.toClient.SyncNBTCapDataEntityS2CPacket; import top.r3944realms.lib39.core.network.toClient.SyncNBTCapDataEntityS2CPayload;
/** /**
* The type Network handler. * The type Network handler.
*/ */
@SuppressWarnings("unused") @SuppressWarnings("unused")
public class NetworkHandler { public class NetworkHandler {
private static int cid = 0;
/** /**
* The constant INSTANCE. * Register packets.
*
* @param event the event
*/ */
public static final SimpleChannel INSTANCE = NetworkRegistry.newSimpleChannel( public static void register(@NotNull RegisterPayloadHandlersEvent event) {
Lib39.rl(Lib39.MOD_ID, "main"), PayloadRegistrar registrar = event.registrar(Lib39.ModInfo.VERSION);
() -> Lib39.ModInfo.VERSION, registrar
Lib39.ModInfo.VERSION::equals, .playToClient(
Lib39.ModInfo.VERSION::equals SyncNBTCapDataEntityS2CPayload.TYPE,
SyncNBTCapDataEntityS2CPayload.STREAM_CODEC,
SyncNBTCapDataEntityS2CPayload::handle
); );
/**
* Register.
*/
public static void register() {
INSTANCE.messageBuilder(SyncNBTCapDataEntityS2CPacket.class, cid++, NetworkDirection.PLAY_TO_CLIENT)
.encoder(SyncNBTCapDataEntityS2CPacket::encode)
.decoder(SyncNBTCapDataEntityS2CPacket::decode)
.consumerNetworkThread(SyncNBTCapDataEntityS2CPacket::handle)
.add();
}
/**
* Send to player.
*
* @param <MSG> the type parameter
* @param message the message
* @param player the player
*/
public static <MSG> void sendToPlayer(MSG message, ServerPlayer player){
INSTANCE.send(PacketDistributor.PLAYER.with(() -> player), message);
}
/**
* Send to player.
*
* @param <MSG> the type parameter
* @param <T> the type parameter
* @param message the message
* @param entity the entity
* @param packetDistributor the packet distributor
*/
public static <MSG, T> void sendToPlayer(MSG message, T entity, @NotNull PacketDistributor<T> packetDistributor){
INSTANCE.send(packetDistributor.with(() -> entity), message);
}
/**
* Send to player.
*
* @param <MSG> the type parameter
* @param message the message
*/
public static <MSG> void sendToAllPlayer(MSG message){
INSTANCE.send(PacketDistributor.ALL.noArg(), message);
} }
} }

View File

@ -4,9 +4,12 @@ import net.minecraft.client.Minecraft;
import net.minecraft.client.multiplayer.ClientLevel; import net.minecraft.client.multiplayer.ClientLevel;
import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.CompoundTag;
import net.minecraft.network.FriendlyByteBuf; import net.minecraft.network.FriendlyByteBuf;
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.resources.ResourceLocation;
import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.Entity;
import net.minecraftforge.network.NetworkEvent; import net.neoforged.neoforge.network.handling.IPayloadContext;
import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import top.r3944realms.lib39.Lib39; import top.r3944realms.lib39.Lib39;
@ -19,10 +22,25 @@ import java.util.Optional;
import java.util.function.Supplier; import java.util.function.Supplier;
/** /**
* The type Sync nbt data s 2 c pack. * The type Sync nbt data s 2 c payload.
*/ */
@SuppressWarnings("unused") @SuppressWarnings("unused")
public record SyncNBTCapDataEntityS2CPacket(int entityId, ResourceLocation id, CompoundTag data) { public record SyncNBTCapDataEntityS2CPayload(int entityId, ResourceLocation id, CompoundTag data) implements CustomPacketPayload {
/**
* The constant SYNC_NBT_CAP_PACKET_ID.
*/
public static final ResourceLocation SYNC_NBT_CAP_PACKET_ID =
Lib39.rl("sync_nbt_cap_data_entity");
/**
* The constant TYPE.
*/
public static final Type<SyncNBTCapDataEntityS2CPayload> TYPE = new Type<>(SYNC_NBT_CAP_PACKET_ID);
/**
* The constant STREAM_CODEC.
*/
public static final StreamCodec<RegistryFriendlyByteBuf, SyncNBTCapDataEntityS2CPayload> STREAM_CODEC =
StreamCodec.ofMember(SyncNBTCapDataEntityS2CPayload::encode, SyncNBTCapDataEntityS2CPayload::decode);
/** /**
* Instantiates a new Sync nbt data s 2 c pack. * Instantiates a new Sync nbt data s 2 c pack.
@ -30,7 +48,7 @@ public record SyncNBTCapDataEntityS2CPacket(int entityId, ResourceLocation id, C
* @param entityId the entity id * @param entityId the entity id
* @param data the data * @param data the data
*/ */
public SyncNBTCapDataEntityS2CPacket(int entityId, @NotNull NBTEntitySyncData data) { public SyncNBTCapDataEntityS2CPayload(int entityId, @NotNull NBTEntitySyncData data) {
this(entityId, data.id(), data.serializeNBT()); this(entityId, data.id(), data.serializeNBT());
} }
@ -40,7 +58,7 @@ public record SyncNBTCapDataEntityS2CPacket(int entityId, ResourceLocation id, C
* @param msg the msg * @param msg the msg
* @param buffer the buffer * @param buffer the buffer
*/ */
public static void encode(@NotNull SyncNBTCapDataEntityS2CPacket msg, @NotNull FriendlyByteBuf buffer) { public static void encode(@NotNull SyncNBTCapDataEntityS2CPayload msg, @NotNull FriendlyByteBuf buffer) {
buffer.writeInt(msg.entityId); buffer.writeInt(msg.entityId);
buffer.writeResourceLocation(msg.id); buffer.writeResourceLocation(msg.id);
buffer.writeNbt(msg.data); buffer.writeNbt(msg.data);
@ -53,41 +71,43 @@ public record SyncNBTCapDataEntityS2CPacket(int entityId, ResourceLocation id, C
* @return the sync nbt data s 2 c pack * @return the sync nbt data s 2 c pack
*/ */
@Contract("_ -> new") @Contract("_ -> new")
public static @NotNull SyncNBTCapDataEntityS2CPacket decode(@NotNull FriendlyByteBuf buffer) { public static @NotNull SyncNBTCapDataEntityS2CPayload decode(@NotNull FriendlyByteBuf buffer) {
return new SyncNBTCapDataEntityS2CPacket(buffer.readInt(), buffer.readResourceLocation(), buffer.readNbt()); return new SyncNBTCapDataEntityS2CPayload(buffer.readInt(), buffer.readResourceLocation(), buffer.readNbt());
} }
/** /**
* Handle. * Handle.
* *
* @param msg the msg * @param payload the msg
* @param ctx the ctx * @param context the context
*/ */
public static void handle(SyncNBTCapDataEntityS2CPacket msg, @NotNull Supplier<NetworkEvent.Context> ctx) { public static void handle(SyncNBTCapDataEntityS2CPayload payload, @NotNull IPayloadContext context) {
NetworkEvent.Context context = ctx.get();
context.enqueueWork(() -> { context.enqueueWork(() -> {
ClientLevel level = Minecraft.getInstance().level; ClientLevel level = Minecraft.getInstance().level;
if (level != null) { if (level != null) {
Entity entity = level.getEntity(msg.entityId); Entity entity = level.getEntity(payload.entityId);
if (entity != null) { if (entity != null) {
Optional<SyncData2Manager.DataProvider<Entity, ISyncData<?>>> capOpt = Optional<SyncData2Manager.DataProvider<Entity, ISyncData<?>>> capOpt =
CommonEventHandler.Game CommonEventHandler.Game
.getSyncData2Manager() .getSyncData2Manager()
.getDataProvider(msg.id); .getDataProvider(payload.id);
capOpt.flatMap(dataProvider -> dataProvider.getData(entity)) capOpt.flatMap(dataProvider -> dataProvider.getData(entity))
.ifPresent(cap -> { .ifPresent(cap -> {
if (cap instanceof NBTEntitySyncData nbtCap) { if (cap instanceof NBTEntitySyncData nbtCap) {
CompoundTag current = nbtCap.serializeNBT(); CompoundTag current = nbtCap.serializeNBT();
if (!current.equals(msg.data)) { if (!current.equals(payload.data)) {
nbtCap.deserializeNBT(msg.data); nbtCap.deserializeNBT(payload.data);
} }
} else Lib39.LOGGER.debug("Unhandled sync data: {}", msg.data); } else Lib39.LOGGER.debug("Unhandled sync data: {}", payload.data);
} }
); );
} }
} }
}); });
context.setPacketHandled(true);
} }
@Override
public Type<? extends CustomPacketPayload> type() {
return TYPE;
}
} }

View File

@ -1,13 +1,14 @@
package top.r3944realms.lib39.core.sync; package top.r3944realms.lib39.core.sync;
import net.neoforged.neoforge.network.PacketDistributor;
import top.r3944realms.lib39.core.network.NetworkHandler; import top.r3944realms.lib39.core.network.NetworkHandler;
import top.r3944realms.lib39.core.network.toClient.SyncNBTCapDataEntityS2CPacket; import top.r3944realms.lib39.core.network.toClient.SyncNBTCapDataEntityS2CPayload;
/** /**
* The interface NeoForge update. * The interface NeoForge update.
*/ */
public interface INeoForgeUpdate extends IUpdate { public interface INeoForgeUpdate extends IUpdate {
default void update() { default void update() {
NetworkHandler.sendToAllPlayer(new SyncNBTCapDataEntityS2CPacket(getSyncData().entityId(), getSyncData().id, getSyncData().serializeNBT())); PacketDistributor.sendToAllPlayers(new SyncNBTCapDataEntityS2CPayload(getSyncData().entityId(), getSyncData().id, getSyncData().serializeNBT()));
} }
} }

View File

@ -2,7 +2,7 @@ package top.r3944realms.lib39.core.sync;
import com.google.common.collect.Maps; import com.google.common.collect.Maps;
import net.minecraft.resources.ResourceLocation; import net.minecraft.resources.ResourceLocation;
import net.minecraftforge.common.capabilities.Capability; import net.neoforged.neoforge.capabilities.EntityCapability;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import java.util.Map; import java.util.Map;
@ -29,15 +29,15 @@ public class SyncData2CapManager extends SyncData2Manager<SyncData2CapManager.Ty
* *
* @param <T> the type parameter * @param <T> the type parameter
*/ */
protected static class TypedSyncEntry<T extends ISyncData<?>> extends SyncData2Manager.TypedSyncEntry<Capability<T>, T> { protected static class TypedSyncEntry<T extends ISyncData<?>> extends SyncData2Manager.TypedSyncEntry<EntityCapability<T, Void>, T> {
/** /**
* Instantiates a new Typed sync entry. * Instantiates a new Typed sync entry.
* *
* @param manager the manager * @param manager the manager
* @param capability the capability * @param capability the capability
*/ */
public TypedSyncEntry(ISyncManager<Capability<T>, T> manager,@Nullable Capability<T> capability) { public TypedSyncEntry(ISyncManager<EntityCapability<T, Void>, T> manager,@Nullable EntityCapability<T, Void> capability) {
super(manager, key -> capability != null ? key.getCapability(capability).resolve() : Optional.empty()); super(manager, key -> capability != null ? Optional.ofNullable(key.getCapability(capability)) : Optional.empty());
} }
} }
@ -51,8 +51,8 @@ public class SyncData2CapManager extends SyncData2Manager<SyncData2CapManager.Ty
*/ */
public <T extends ISyncData<?>> void registerManager( public <T extends ISyncData<?>> void registerManager(
ResourceLocation key, ResourceLocation key,
ISyncManager<Capability<T>, T> manager, ISyncManager<EntityCapability<T, Void>, T> manager,
Capability<T> capability EntityCapability<T, Void> capability
) { ) {
Objects.requireNonNull(key, "ResourceLocation key cannot be null"); Objects.requireNonNull(key, "ResourceLocation key cannot be null");
Objects.requireNonNull(manager, "Sync manager cannot be null"); Objects.requireNonNull(manager, "Sync manager cannot be null");
@ -69,7 +69,7 @@ public class SyncData2CapManager extends SyncData2Manager<SyncData2CapManager.Ty
* @param key the key * @param key the key
* @param capability the capability * @param capability the capability
*/ */
public <T extends ISyncData<?>> void bindCapability(ResourceLocation key, Capability<T> capability) { public <T extends ISyncData<?>> void bindCapability(ResourceLocation key, EntityCapability<T, Void> capability) {
Objects.requireNonNull(key, "ResourceLocation key cannot be null"); Objects.requireNonNull(key, "ResourceLocation key cannot be null");
Objects.requireNonNull(capability, "Capability cannot be null"); Objects.requireNonNull(capability, "Capability cannot be null");
@ -103,7 +103,7 @@ public class SyncData2CapManager extends SyncData2Manager<SyncData2CapManager.Ty
* @param entry the entry * @param entry the entry
* @param newCapability the new capability * @param newCapability the new capability
*/ */
protected <T extends ISyncData<?>> void updateCapabilityInEntry(ResourceLocation id, TypedSyncEntry<?> entry, Capability<T> newCapability) { protected <T extends ISyncData<?>> void updateCapabilityInEntry(ResourceLocation id, TypedSyncEntry<?> entry, EntityCapability<T, Void> newCapability) {
updateDataProviderInEntry(id, entry, key -> newCapability != null ? key.getCapability(newCapability).resolve() : Optional.empty()); updateDataProviderInEntry(id, entry, key -> newCapability != null ? Optional.ofNullable(key.getCapability(newCapability)) : Optional.empty());
} }
} }

View File

@ -1,14 +1,19 @@
package top.r3944realms.lib39.datagen.provider; package top.r3944realms.lib39.datagen.provider;
import net.minecraft.core.HolderLookup;
import net.minecraft.core.WritableRegistry;
import net.minecraft.data.PackOutput; import net.minecraft.data.PackOutput;
import net.minecraft.data.loot.LootTableProvider; import net.minecraft.data.loot.LootTableProvider;
import net.minecraft.resources.ResourceKey;
import net.minecraft.resources.ResourceLocation; import net.minecraft.resources.ResourceLocation;
import net.minecraft.util.ProblemReporter;
import net.minecraft.world.level.storage.loot.LootTable; import net.minecraft.world.level.storage.loot.LootTable;
import net.minecraft.world.level.storage.loot.ValidationContext; import net.minecraft.world.level.storage.loot.ValidationContext;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.concurrent.CompletableFuture;
/** /**
* The type Simple loot table provider. * The type Simple loot table provider.
@ -19,9 +24,10 @@ public class SimpleLootTableProvider extends LootTableProvider {
* *
* @param output the output * @param output the output
* @param subProvidersWrapper the sub providers wrapper * @param subProvidersWrapper the sub providers wrapper
* @param registries the registries
*/ */
public SimpleLootTableProvider(PackOutput output, @NotNull SubProvidersWrapper subProvidersWrapper) { public SimpleLootTableProvider(PackOutput output, @NotNull SubProvidersWrapper subProvidersWrapper, CompletableFuture<HolderLookup.Provider> registries) {
super(output, Set.of(), subProvidersWrapper.entries); super(output, Set.of(), subProvidersWrapper.entries, registries);
} }
/** /**
@ -30,13 +36,14 @@ public class SimpleLootTableProvider extends LootTableProvider {
* @param output the output * @param output the output
* @param requiredTables the required tables * @param requiredTables the required tables
* @param subProvidersWrapper the sub providers wrapper * @param subProvidersWrapper the sub providers wrapper
* @param registries the registries
*/ */
public SimpleLootTableProvider(PackOutput output, Set<ResourceLocation> requiredTables, @NotNull SubProvidersWrapper subProvidersWrapper) { public SimpleLootTableProvider(PackOutput output, Set<ResourceKey<LootTable>> requiredTables, @NotNull SubProvidersWrapper subProvidersWrapper, CompletableFuture<HolderLookup.Provider> registries) {
super(output, requiredTables, subProvidersWrapper.entries); super(output, requiredTables, subProvidersWrapper.entries, registries);
} }
@Override @Override
protected void validate(@NotNull Map<ResourceLocation, LootTable> map, @NotNull ValidationContext validationcontext) { protected void validate(WritableRegistry<LootTable> writableregistry, ValidationContext validationcontext, ProblemReporter.Collector problemreporter$collector) {
map.forEach((id, table) -> table.validate(validationcontext)); writableregistry.forEach(lootTable -> lootTable.validate(validationcontext));
} }
} }

View File

@ -42,7 +42,7 @@ public class SubProvidersWrapper {
* @return the sub providers wrapper * @return the sub providers wrapper
*/ */
public SubProvidersWrapper addEntry(LootTableSubProvider subProvider, LootContextParamSet subParamSet) { public SubProvidersWrapper addEntry(LootTableSubProvider subProvider, LootContextParamSet subParamSet) {
entries.add(new LootTableProvider.SubProviderEntry(() -> subProvider, subParamSet)); entries.add(new LootTableProvider.SubProviderEntry(provider -> subProvider, subParamSet));
return this; return this;
} }
@ -53,7 +53,7 @@ public class SubProvidersWrapper {
* @return the sub providers wrapper * @return the sub providers wrapper
*/ */
public SubProvidersWrapper addBlockEntry(BlockLootTables blockLootTables) { public SubProvidersWrapper addBlockEntry(BlockLootTables blockLootTables) {
entries.add(new LootTableProvider.SubProviderEntry(() -> blockLootTables, LootContextParamSets.BLOCK)); entries.add(new LootTableProvider.SubProviderEntry(provider -> blockLootTables, LootContextParamSets.BLOCK));
return this; return this;
} }

View File

@ -1,24 +1,25 @@
package top.r3944realms.lib39.datagen.provider.subprovider; package top.r3944realms.lib39.datagen.provider.subprovider;
import net.minecraft.advancements.critereon.ItemPredicate; import net.minecraft.advancements.critereon.*;
import net.minecraft.core.Holder;
import net.minecraft.core.HolderLookup;
import net.minecraft.core.registries.Registries;
import net.minecraft.data.loot.BlockLootSubProvider; import net.minecraft.data.loot.BlockLootSubProvider;
import net.minecraft.world.flag.FeatureFlags; import net.minecraft.world.flag.FeatureFlags;
import net.minecraft.world.item.Item; import net.minecraft.world.item.Item;
import net.minecraft.world.item.enchantment.Enchantment;
import net.minecraft.world.item.enchantment.Enchantments; import net.minecraft.world.item.enchantment.Enchantments;
import net.minecraft.world.level.ItemLike; import net.minecraft.world.level.ItemLike;
import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.*;
import net.minecraft.world.level.block.FlowerPotBlock;
import net.minecraft.world.level.block.state.properties.Property; import net.minecraft.world.level.block.state.properties.Property;
import net.minecraft.world.level.storage.loot.LootPool; import net.minecraft.world.level.storage.loot.LootPool;
import net.minecraft.world.level.storage.loot.LootTable; import net.minecraft.world.level.storage.loot.LootTable;
import net.minecraft.world.level.storage.loot.entries.LootItem; import net.minecraft.world.level.storage.loot.entries.LootItem;
import net.minecraft.world.level.storage.loot.functions.ApplyBonusCount; import net.minecraft.world.level.storage.loot.functions.*;
import net.minecraft.world.level.storage.loot.functions.SetItemCountFunction; import net.minecraft.world.level.storage.loot.predicates.*;
import net.minecraft.world.level.storage.loot.predicates.LootItemBlockStatePropertyCondition;
import net.minecraft.world.level.storage.loot.predicates.MatchTool;
import net.minecraft.world.level.storage.loot.providers.number.ConstantValue; import net.minecraft.world.level.storage.loot.providers.number.ConstantValue;
import net.minecraft.world.level.storage.loot.providers.number.UniformGenerator; import net.minecraft.world.level.storage.loot.providers.number.UniformGenerator;
import net.minecraftforge.registries.DeferredRegister; import net.neoforged.neoforge.registries.DeferredRegister;
import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
@ -42,9 +43,10 @@ public class BlockLootTables extends BlockLootSubProvider {
* Instantiates a new Block loot tables. * Instantiates a new Block loot tables.
* *
* @param deferredRegister the deferred register * @param deferredRegister the deferred register
* @param registries the registries
*/ */
public BlockLootTables(DeferredRegister<Block> deferredRegister) { public BlockLootTables(DeferredRegister<Block> deferredRegister, HolderLookup.Provider registries) {
super(Set.of(), FeatureFlags.REGISTRY.allFlags()); super(Set.of(), FeatureFlags.REGISTRY.allFlags(), registries);
knowBlocks = deferredRegister; knowBlocks = deferredRegister;
} }
@ -86,7 +88,7 @@ public class BlockLootTables extends BlockLootSubProvider {
* @return the block loot tables * @return the block loot tables
*/ */
public BlockLootTables dropWhenSilkTouch(Supplier<Block> block) { public BlockLootTables dropWhenSilkTouch(Supplier<Block> block) {
return addEntry(block, BlockLootSubProvider::createSilkTouchOnlyTable); return addEntry(block, this::createSilkTouchOnlyTable);
} }
/** /**
@ -192,7 +194,7 @@ public class BlockLootTables extends BlockLootSubProvider {
* @return the block loot tables * @return the block loot tables
*/ */
public BlockLootTables dropFlowerPot(Supplier<Block> block) { public BlockLootTables dropFlowerPot(Supplier<Block> block) {
return addEntry(block, (pBlock) -> this.createPotFlowerItemTable(((FlowerPotBlock)pBlock).getContent())); return addEntry(block, this::createPotFlowerItemTable);
} }
/** /**
@ -336,11 +338,12 @@ public class BlockLootTables extends BlockLootSubProvider {
* 创建新的战利品表生成器 * 创建新的战利品表生成器
* *
* @param deferredRegister the deferred register * @param deferredRegister the deferred register
* @param registries the registries
* @return the block loot tables * @return the block loot tables
*/ */
@Contract("_ -> new") @Contract("_ -> new")
public static @NotNull BlockLootTables create(DeferredRegister<Block> deferredRegister) { public static @NotNull BlockLootTables create(DeferredRegister<Block> deferredRegister, HolderLookup.Provider registries) {
return new BlockLootTables(deferredRegister); return new BlockLootTables(deferredRegister, registries);
} }
/** /**
@ -348,20 +351,31 @@ public class BlockLootTables extends BlockLootSubProvider {
* *
* @param oreBlock the ore block * @param oreBlock the ore block
* @param oreItem the ore item * @param oreItem the ore item
* @param registries the registries
* @return the loot table .@ not null builder * @return the loot table .@ not null builder
*/ */
public static LootTable.@NotNull Builder simpleOreDrop(Block oreBlock, Item oreItem) { public static LootTable.@NotNull Builder simpleOreDrop(Block oreBlock, Item oreItem,
HolderLookup.Provider registries) {
HolderLookup.RegistryLookup<Enchantment> enchantments = registries.lookupOrThrow(Registries.ENCHANTMENT);
Holder<Enchantment> silkTouch = enchantments.getOrThrow(Enchantments.SILK_TOUCH);
Holder<Enchantment> fortune = enchantments.getOrThrow(Enchantments.FORTUNE);
// 创建 Silk Touch 谓词
ItemPredicate.Builder silkTouchPredicates = ItemPredicate.Builder.item()
.withSubPredicate(
ItemSubPredicates.ENCHANTMENTS,
ItemEnchantmentsPredicate.enchantments(List.of(
new EnchantmentPredicate(silkTouch, MinMaxBounds.Ints.atLeast(1))
))
);
return LootTable.lootTable() return LootTable.lootTable()
.withPool(LootPool.lootPool() .withPool(LootPool.lootPool()
.setRolls(ConstantValue.exactly(1)) .setRolls(ConstantValue.exactly(1))
.add(LootItem.lootTableItem(oreItem) .add(LootItem.lootTableItem(oreItem)
.when(MatchTool.toolMatches(ItemPredicate.Builder.item() .when(MatchTool.toolMatches(silkTouchPredicates).invert())
.hasEnchantment(new net.minecraft.advancements.critereon.EnchantmentPredicate(
Enchantments.SILK_TOUCH,
net.minecraft.advancements.critereon.MinMaxBounds.Ints.atLeast(1)
))).invert())
.apply(SetItemCountFunction.setCount(UniformGenerator.between(1, 1))) .apply(SetItemCountFunction.setCount(UniformGenerator.between(1, 1)))
.apply(ApplyBonusCount.addOreBonusCount(Enchantments.BLOCK_FORTUNE)))); .apply(ApplyBonusCount.addOreBonusCount(fortune))));
} }
/** /**
@ -369,17 +383,59 @@ public class BlockLootTables extends BlockLootSubProvider {
* *
* @param stoneBlock the stone block * @param stoneBlock the stone block
* @param dropItem the drop item * @param dropItem the drop item
* @param registries the registries
* @return the loot table .@ not null builder * @return the loot table .@ not null builder
*/ */
public static LootTable.@NotNull Builder stoneDrop(Block stoneBlock, Item dropItem) { public static LootTable.@NotNull Builder stoneDrop(Block stoneBlock, Item dropItem,
HolderLookup.Provider registries) {
HolderLookup.RegistryLookup<Enchantment> enchantments = registries.lookupOrThrow(Registries.ENCHANTMENT);
Holder<Enchantment> silkTouch = enchantments.getOrThrow(Enchantments.SILK_TOUCH);
// 创建 Silk Touch 谓词
ItemPredicate.Builder silkTouchPredicate = ItemPredicate.Builder.item()
.withSubPredicate(
ItemSubPredicates.ENCHANTMENTS,
ItemEnchantmentsPredicate.enchantments(List.of(
new EnchantmentPredicate(silkTouch, MinMaxBounds.Ints.atLeast(1))
))
);
return LootTable.lootTable() return LootTable.lootTable()
.withPool(LootPool.lootPool() .withPool(LootPool.lootPool()
.setRolls(ConstantValue.exactly(1)) .setRolls(ConstantValue.exactly(1))
.add(LootItem.lootTableItem(dropItem) .add(LootItem.lootTableItem(dropItem)
.when(MatchTool.toolMatches(ItemPredicate.Builder.item() .when(MatchTool.toolMatches(silkTouchPredicate))));
.hasEnchantment(new net.minecraft.advancements.critereon.EnchantmentPredicate( }
Enchantments.SILK_TOUCH,
net.minecraft.advancements.critereon.MinMaxBounds.Ints.atLeast(1) /**
)))))); * 快速创建基本矿物的掉落表需要获取附魔的 Holder
* 适用于需要动态获取附魔引用的场景
*
* @param oreBlock the ore block
* @param oreItem the ore item
* @param silkTouch the silk touch enchantment holder
* @param blockFortune the block fortune enchantment holder
* @return the loot table builder
*/
public static LootTable.@NotNull Builder simpleOreDrop(Block oreBlock, Item oreItem,
Holder<Enchantment> silkTouch,
Holder<Enchantment> blockFortune) {
// 创建 Silk Touch 谓词
ItemPredicate.Builder silkTouchPredicate = ItemPredicate.Builder.item()
.withSubPredicate(
ItemSubPredicates.ENCHANTMENTS,
ItemEnchantmentsPredicate.enchantments(List.of(
new EnchantmentPredicate(silkTouch, MinMaxBounds.Ints.atLeast(1))
))
);
return LootTable.lootTable()
.withPool(LootPool.lootPool()
.setRolls(ConstantValue.exactly(1))
.add(LootItem.lootTableItem(oreItem)
.when(MatchTool.toolMatches(silkTouchPredicate).invert())
.apply(SetItemCountFunction.setCount(UniformGenerator.between(1, 1)))
.apply(ApplyBonusCount.addOreBonusCount(blockFortune))));
} }
} }

View File

@ -14,6 +14,8 @@ public class NeoForgeLib39Example {
/** /**
* Instantiates a new Lib 39 example. * Instantiates a new Lib 39 example.
*
* @param modEventBus the mod event bus
*/ */
public NeoForgeLib39Example(IEventBus modEventBus) { public NeoForgeLib39Example(IEventBus modEventBus) {
if (!registered) { if (!registered) {
@ -25,25 +27,16 @@ public class NeoForgeLib39Example {
/** /**
* Init. * Init.
*
* @param modEventBus the mod event bus
*/ */
public void init(IEventBus modEventBus) { public void init(IEventBus modEventBus) {
NeoForgeExLib39Items.register(modEventBus); NeoForgeExLib39Items.register(modEventBus);
ExNetworkHandler.register();
} }
private void registerToEventBus(IEventBus modEventBus) { private void registerToEventBus(IEventBus modEventBus) {
IEventBus modBus = modEventBus; IEventBus modBus = modEventBus;
IEventBus gameBus = NeoForge.EVENT_BUS; IEventBus gameBus = NeoForge.EVENT_BUS;
// DistExecutor.unsafeCallWhenOn(Dist.CLIENT, () -> {
// modBus.register(ExClientEventHandler.Mod.class);
// gameBus.register(ExClientEventHandler.Game.class);
// return null;
// });
// DistExecutor.unsafeCallWhenOn(Dist.DEDICATED_SERVER, () -> {
// modBus.register(ExServerEventHandler.Mod.class);
// gameBus.register(ExServerEventHandler.Game.class);
// return null;
// });
modBus.register(ExCommonEventHandler.Mod.class); modBus.register(ExCommonEventHandler.Mod.class);
gameBus.register(ExCommonEventHandler.Game.class); gameBus.register(ExCommonEventHandler.Game.class);

View File

@ -1,12 +1,13 @@
package top.r3944realms.lib39.example.content.data; package top.r3944realms.lib39.example.content.data;
import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.LivingEntity;
import net.minecraftforge.common.capabilities.Capability; import net.minecraft.world.entity.vehicle.Boat;
import net.minecraftforge.common.capabilities.CapabilityManager; import net.minecraft.world.entity.vehicle.Minecart;
import net.minecraftforge.common.capabilities.CapabilityToken; import net.neoforged.neoforge.capabilities.EntityCapability;
import net.minecraftforge.common.capabilities.RegisterCapabilitiesEvent; import net.neoforged.neoforge.capabilities.RegisterCapabilitiesEvent;
import net.minecraftforge.event.AttachCapabilitiesEvent;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import top.r3944realms.lib39.Lib39;
import top.r3944realms.lib39.util.EntityCapabilityHelper;
/** /**
* The type Ex capability handler. * The type Ex capability handler.
@ -15,7 +16,10 @@ public class ExCapabilityHandler {
/** /**
* The constant TEST_CAP. * The constant TEST_CAP.
*/ */
public static final Capability<AbstractedTestSyncData> TEST_CAP = CapabilityManager.get(new CapabilityToken<>() {}); public static final EntityCapability<AbstractedTestSyncData, Void> TEST_CAP = EntityCapability.createVoid(
Lib39.rl("test_data"),
AbstractedTestSyncData.class
);
/** /**
* Register capability. * Register capability.
@ -23,18 +27,23 @@ public class ExCapabilityHandler {
* @param event the event * @param event the event
*/ */
public static void registerCapability(@NotNull RegisterCapabilitiesEvent event) { public static void registerCapability(@NotNull RegisterCapabilitiesEvent event) {
event.register(AbstractedTestSyncData.class); EntityCapabilityHelper.registerForEntityClass(
} event,
TEST_CAP,
/** (entity, context) -> entity.getCapability(TEST_CAP),
* Attach capability. LivingEntity.class
* );
* @param event the event EntityCapabilityHelper.registerForEntityClass(
*/ event,
public static void attachCapability(@NotNull AttachCapabilitiesEvent<?> event) { TEST_CAP,
Object object = event.getObject(); (entity, context) -> entity.getCapability(TEST_CAP),
if(object instanceof Entity entity) { Boat.class
event.addCapability(TestSyncCapProvider.TEST_SYNC_REL, new TestSyncCapProvider(entity)); );
} EntityCapabilityHelper.registerForEntityClass(
event,
TEST_CAP,
(entity, context) -> entity.getCapability(TEST_CAP),
Minecart.class
);
} }
} }

View File

@ -1,49 +0,0 @@
package top.r3944realms.lib39.example.content.data;
import net.minecraft.core.Direction;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.entity.Entity;
import net.minecraftforge.common.capabilities.Capability;
import net.minecraftforge.common.capabilities.ICapabilitySerializable;
import net.minecraftforge.common.util.LazyOptional;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import top.r3944realms.lib39.Lib39;
/**
* The type Test sync cap provider.
*/
public class TestSyncCapProvider implements ICapabilitySerializable<CompoundTag> {
/**
* The constant TEST_SYNC_REL.
*/
public static final ResourceLocation TEST_SYNC_REL = Lib39.rl(Lib39.MOD_ID, "test_sync_data");
private final AbstractedTestSyncData instance;
private final LazyOptional<AbstractedTestSyncData> optional;
/**
* Instantiates a new Test sync cap provider.
*
* @param entity the entity
*/
public TestSyncCapProvider(Entity entity) {
this.instance = new TestSyncData(entity);
this.optional = LazyOptional.of(() -> instance);
}
@Override
public @NotNull <T> LazyOptional<T> getCapability(@NotNull Capability<T> cap, @Nullable Direction side) {
return ExCapabilityHandler.TEST_CAP.orEmpty(cap, optional);
}
@Override
public CompoundTag serializeNBT() {
return instance.serializeNBT();
}
@Override
public void deserializeNBT(CompoundTag nbt) {
instance.deserializeNBT(nbt);
}
}

View File

@ -4,14 +4,14 @@ import net.minecraft.network.chat.Component;
import net.minecraft.server.level.ServerPlayer; import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.LivingEntity;
import net.neoforged.neoforge.network.PacketDistributor;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import top.r3944realms.lib39.Lib39; import top.r3944realms.lib39.Lib39;
import top.r3944realms.lib39.example.content.data.AbstractedTestSyncData; import top.r3944realms.lib39.example.content.data.AbstractedTestSyncData;
import top.r3944realms.lib39.example.content.data.ExCapabilityHandler; import top.r3944realms.lib39.example.content.data.ExCapabilityHandler;
import top.r3944realms.lib39.example.content.data.TestSyncData; import top.r3944realms.lib39.example.content.data.TestSyncData;
import top.r3944realms.lib39.example.core.network.ClientDataPacket; import top.r3944realms.lib39.example.core.network.toServer.ClientDataPayload;
import top.r3944realms.lib39.example.core.network.ExNetworkHandler;
/** /**
* The type Forge fabric item. * The type Forge fabric item.
@ -34,7 +34,7 @@ public class NeoForgeFabricItem extends AbstractFabricItem {
@Override @Override
protected void sendClientDataToServer(AbstractedTestSyncData clientData, int targetEntityId) { protected void sendClientDataToServer(AbstractedTestSyncData clientData, int targetEntityId) {
ExNetworkHandler.INSTANCE.sendToServer(new ClientDataPacket(clientData, targetEntityId)); PacketDistributor.sendToServer(new ClientDataPayload(clientData, targetEntityId));
} }
/** /**
@ -45,7 +45,7 @@ public class NeoForgeFabricItem extends AbstractFabricItem {
*/ */
public static @Nullable AbstractedTestSyncData getStaticData(Entity target) { public static @Nullable AbstractedTestSyncData getStaticData(Entity target) {
try { try {
AbstractedTestSyncData abstractData = target.getCapability(ExCapabilityHandler.TEST_CAP).resolve().orElse(null); AbstractedTestSyncData abstractData = target.getCapability(ExCapabilityHandler.TEST_CAP);
if (abstractData instanceof TestSyncData) { if (abstractData instanceof TestSyncData) {
return abstractData; return abstractData;
} }

View File

@ -35,7 +35,7 @@ public class NeoForgeNeoForgeItem extends AbstractNeoForgeItem{
@SuppressWarnings("JavaExistingMethodCanBeUsed") @SuppressWarnings("JavaExistingMethodCanBeUsed")
public static @Nullable AbstractedTestSyncData getStaticData(Entity target) { public static @Nullable AbstractedTestSyncData getStaticData(Entity target) {
try { try {
AbstractedTestSyncData abstractData = target.getCapability(ExCapabilityHandler.TEST_CAP).resolve().orElse(null); AbstractedTestSyncData abstractData = target.getCapability(ExCapabilityHandler.TEST_CAP);
if (abstractData instanceof TestSyncData) { if (abstractData instanceof TestSyncData) {
return abstractData; return abstractData;
} }

View File

@ -1,10 +1,17 @@
package top.r3944realms.lib39.example.core.event; package top.r3944realms.lib39.example.core.event;
import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.vehicle.Boat;
import net.minecraft.world.entity.vehicle.Minecart;
import net.neoforged.bus.api.IEventBus; import net.neoforged.bus.api.IEventBus;
import net.neoforged.bus.api.SubscribeEvent; import net.neoforged.bus.api.SubscribeEvent;
import net.neoforged.fml.ModLoadingContext; import net.neoforged.fml.ModLoadingContext;
import net.neoforged.fml.event.lifecycle.FMLConstructModEvent;
import net.neoforged.neoforge.capabilities.EntityCapability;
import net.neoforged.neoforge.capabilities.RegisterCapabilitiesEvent;
import net.neoforged.neoforge.common.NeoForge; import net.neoforged.neoforge.common.NeoForge;
import net.neoforged.neoforge.network.event.RegisterPayloadHandlersEvent;
import top.r3944realms.lib39.Lib39NeoForge;
import top.r3944realms.lib39.api.event.SyncManagerRegisterEvent; import top.r3944realms.lib39.api.event.SyncManagerRegisterEvent;
import top.r3944realms.lib39.core.compat.ICompatManager; import top.r3944realms.lib39.core.compat.ICompatManager;
import top.r3944realms.lib39.core.event.CommonEventHandler; import top.r3944realms.lib39.core.event.CommonEventHandler;
@ -14,6 +21,7 @@ import top.r3944realms.lib39.example.compat.Lib39CompatManager;
import top.r3944realms.lib39.example.content.data.AbstractedTestSyncData; import top.r3944realms.lib39.example.content.data.AbstractedTestSyncData;
import top.r3944realms.lib39.example.content.data.ExCapabilityHandler; import top.r3944realms.lib39.example.content.data.ExCapabilityHandler;
import top.r3944realms.lib39.example.content.data.TestSyncData; import top.r3944realms.lib39.example.content.data.TestSyncData;
import top.r3944realms.lib39.example.core.network.ExNetworkHandler;
import java.util.Map; import java.util.Map;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
@ -28,15 +36,6 @@ public class ExCommonEventHandler {
@SuppressWarnings("unused") @SuppressWarnings("unused")
public static class Game extends ExCommonEventHandler { public static class Game extends ExCommonEventHandler {
/**
* Attach capability.
*
* @param event the event
*/
@SubscribeEvent
public static void attachCapability(AttachCapabilitiesEvent<?> event) {
ExCapabilityHandler.attachCapability(event);
}
/** /**
* On register sync. * On register sync.
@ -48,16 +47,16 @@ public class ExCommonEventHandler {
event.registerSyncManager( event.registerSyncManager(
TestSyncData.ID, TestSyncData.ID,
new CachedSyncManager<>() { new CachedSyncManager<>() {
private final Map<Capability<AbstractedTestSyncData>, AbstractedTestSyncData> syncDataMap = new ConcurrentHashMap<>(); private final Map<EntityCapability<AbstractedTestSyncData, Void>, AbstractedTestSyncData> syncDataMap = new ConcurrentHashMap<>();
@Override @Override
public Map<Capability<AbstractedTestSyncData>, AbstractedTestSyncData> getSyncMap() { public Map<EntityCapability<AbstractedTestSyncData, Void>, AbstractedTestSyncData> getSyncMap() {
return syncDataMap; return syncDataMap;
} }
}, },
ExCapabilityHandler.TEST_CAP ExCapabilityHandler.TEST_CAP
); );
event.addAllowEntityClass(TestSyncData.ID, LivingEntity.class); event.addAllowEntityClass(TestSyncData.ID, LivingEntity.class, Boat.class, Minecart.class);
} }
} }
@ -77,7 +76,7 @@ public class ExCommonEventHandler {
if (compatManager == null) { if (compatManager == null) {
synchronized (CommonEventHandler.Mod.class) { synchronized (CommonEventHandler.Mod.class) {
if (compatManager == null) { if (compatManager == null) {
compatManager = new Lib39CompatManager("compat", EVENT_BUS, NeoForge.EVENT_BUS); compatManager = new Lib39CompatManager("compat", Lib39NeoForge.modEventBus, NeoForge.EVENT_BUS);
} }
} }
} }
@ -115,5 +114,15 @@ public class ExCommonEventHandler {
ExCapabilityHandler.registerCapability(event); ExCapabilityHandler.registerCapability(event);
} }
/**
* On register payload.
*
* @param event the event
*/
@SubscribeEvent
public static void onRegisterPayload (RegisterPayloadHandlersEvent event) {
ExNetworkHandler.register(event);
}
} }
} }

View File

@ -1,70 +0,0 @@
package top.r3944realms.lib39.example.core.network;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.server.level.ServerPlayer;
import net.minecraftforge.network.NetworkEvent;
import top.r3944realms.lib39.example.content.data.AbstractedTestSyncData;
import top.r3944realms.lib39.example.content.data.TestSyncData;
import top.r3944realms.lib39.example.content.item.NeoForgeFabricItem;
import java.util.function.Supplier;
/**
* The type Client data packet.
*/
public class ClientDataPacket {
private final AbstractedTestSyncData clientData;
private final int targetEntityId;
/**
* Instantiates a new Client data packet.
*
* @param clientData the client data
* @param targetEntityId the target entity id
*/
public ClientDataPacket(AbstractedTestSyncData clientData, int targetEntityId) {
this.clientData = clientData;
this.targetEntityId = targetEntityId;
}
/**
* Instantiates a new Client data packet.
*
* @param buf the buf
*/
public ClientDataPacket(FriendlyByteBuf buf) {
this.clientData = TestSyncData.staticFromBytes(buf);
this.targetEntityId = buf.readInt();
}
/**
* To bytes.
*
* @param buf the buf
*/
public void toBytes(FriendlyByteBuf buf) {
clientData.toBytes(buf);
buf.writeInt(targetEntityId);
}
/**
* Handle.
*
* @param supplier the supplier
*/
public void handle(Supplier<NetworkEvent.Context> supplier) {
NetworkEvent.Context context = supplier.get();
context.enqueueWork(() -> {
ServerPlayer player = context.getSender();
if (player != null) {
// 处理客户端发送的数据
handleClientData(player, clientData, targetEntityId);
}
});
context.setPacketHandled(true);
}
private void handleClientData(ServerPlayer player, AbstractedTestSyncData clientData, int targetEntityId) {
NeoForgeFabricItem.handleClientDataFromPacket(player, clientData, targetEntityId);
}
}

View File

@ -1,36 +1,26 @@
package top.r3944realms.lib39.example.core.network; package top.r3944realms.lib39.example.core.network;
import net.minecraftforge.network.NetworkRegistry; import net.neoforged.neoforge.network.event.RegisterPayloadHandlersEvent;
import net.minecraftforge.network.simple.SimpleChannel; import net.neoforged.neoforge.network.registration.PayloadRegistrar;
import top.r3944realms.lib39.Lib39; import top.r3944realms.lib39.Lib39;
import top.r3944realms.lib39.example.core.network.toServer.ClientDataPayload;
/** /**
* The type Ex network handler. * The type Ex network handler.
*/ */
public class ExNetworkHandler { public class ExNetworkHandler {
/**
* The constant INSTANCE.
*/
public static final SimpleChannel INSTANCE;
private static int ID = 0;
static {
INSTANCE = NetworkRegistry.newSimpleChannel(
Lib39.rl(Lib39.MOD_ID, "test"),
() -> "1.0",
s -> true,
s -> true
);
}
/** /**
* Register. * Register.
*
* @param event the event
*/ */
public static void register() { public static void register(RegisterPayloadHandlersEvent event) {
// 注册数据包 PayloadRegistrar registrar = event.registrar(Lib39.ModInfo.VERSION);
INSTANCE.registerMessage(ID++, ClientDataPacket.class, registrar.playToServer(
ClientDataPacket::toBytes, ClientDataPayload.TYPE,
ClientDataPacket::new, ClientDataPayload.STREAM_CODEC,
ClientDataPacket::handle); ClientDataPayload::handle
);
} }
} }

View File

@ -0,0 +1,83 @@
package top.r3944realms.lib39.example.core.network.toServer;
import net.minecraft.network.FriendlyByteBuf;
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.ServerPlayer;
import net.minecraft.world.entity.player.Player;
import net.neoforged.neoforge.network.handling.IPayloadContext;
import org.jetbrains.annotations.NotNull;
import top.r3944realms.lib39.Lib39;
import top.r3944realms.lib39.example.content.data.AbstractedTestSyncData;
import top.r3944realms.lib39.example.content.data.TestSyncData;
import top.r3944realms.lib39.example.content.item.NeoForgeFabricItem;
/**
* The type Client data packet.
*/
public record ClientDataPayload(AbstractedTestSyncData clientData, int targetEntityId) implements CustomPacketPayload {
/**
* The constant CLIENT_DATA_PACKET_ID.
*/
public static final ResourceLocation CLIENT_DATA_PACKET_ID =
Lib39.rl("client_data");
/**
* The constant TYPE.
*/
public static final Type<ClientDataPayload> TYPE = new Type<>(CLIENT_DATA_PACKET_ID);
/**
* The constant STREAM_CODEC.
*/
public static final StreamCodec<RegistryFriendlyByteBuf, ClientDataPayload> STREAM_CODEC =
StreamCodec.ofMember(ClientDataPayload::toBytes, ClientDataPayload::new);
/**
* Instantiates a new Client data packet.
*
* @param buf the buf
*/
public ClientDataPayload(FriendlyByteBuf buf) {
this(TestSyncData.staticFromBytes(buf), buf.readInt());
}
/**
* To bytes.
*
* @param buf the buf
*/
public void toBytes(FriendlyByteBuf buf) {
clientData.toBytes(buf);
buf.writeInt(targetEntityId);
}
/**
* Handle.
*
* @param payload the payload
* @param context the context
*/
public static void handle(ClientDataPayload payload, @NotNull IPayloadContext context) {
context.enqueueWork(() -> {
Player player = context.player();
if (player instanceof ServerPlayer serverPlayer) {
// 处理客户端发送的数据
handleClientData(serverPlayer, payload.clientData(), payload.targetEntityId());
}
});
}
private static void handleClientData(ServerPlayer player, AbstractedTestSyncData clientData, int targetEntityId) {
NeoForgeFabricItem.handleClientDataFromPacket(player, clientData, targetEntityId);
}
@Override
public Type<? extends CustomPacketPayload> type() {
return TYPE;
}
}

View File

@ -35,6 +35,7 @@ public abstract class MixinMinecraft extends ReentrantBlockableEventLoop<Runnabl
* Set level setup. * Set level setup.
* *
* @param level the level client * @param level the level client
* @param reason the reason
* @param ci the ci * @param ci the ci
* @param services the services * @param services the services
*/ */

View File

@ -3,7 +3,6 @@ package top.r3944realms.lib39.platform;
import com.mojang.brigadier.builder.LiteralArgumentBuilder; import com.mojang.brigadier.builder.LiteralArgumentBuilder;
import net.minecraft.commands.CommandBuildContext; import net.minecraft.commands.CommandBuildContext;
import net.minecraft.commands.CommandSourceStack; import net.minecraft.commands.CommandSourceStack;
import net.minecraftforge.common.MinecraftForge;
import net.neoforged.neoforge.common.NeoForge; import net.neoforged.neoforge.common.NeoForge;
import top.r3944realms.lib39.api.event.RegisterCommandHelpEvent; import top.r3944realms.lib39.api.event.RegisterCommandHelpEvent;
import top.r3944realms.lib39.core.command.ICommandHelpManager; import top.r3944realms.lib39.core.command.ICommandHelpManager;

View File

@ -1,7 +1,7 @@
package top.r3944realms.lib39.platform; package top.r3944realms.lib39.platform;
import top.r3944realms.lib39.platform.services.IUtilHelper; import top.r3944realms.lib39.platform.services.IUtilHelper;
import top.r3944realms.lib39.util.ForgeBlockRegistryBuilder; import top.r3944realms.lib39.util.NeoForgeBlockRegistryBuilder;
import top.r3944realms.lib39.util.block.BlockRegistryBuilder; import top.r3944realms.lib39.util.block.BlockRegistryBuilder;
/** /**
@ -14,6 +14,6 @@ public enum NeoForgeUtilHelper implements IUtilHelper {
INSTANCE; INSTANCE;
@Override @Override
public BlockRegistryBuilder getBlockRegistryBuilder() { public BlockRegistryBuilder getBlockRegistryBuilder() {
return new ForgeBlockRegistryBuilder(); return new NeoForgeBlockRegistryBuilder();
} }
} }

View File

@ -0,0 +1,281 @@
package top.r3944realms.lib39.util;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.entity.*;
import net.minecraft.world.entity.animal.Animal;
import net.minecraft.world.entity.monster.Monster;
import net.neoforged.neoforge.capabilities.EntityCapability;
import net.neoforged.neoforge.capabilities.ICapabilityProvider;
import net.neoforged.neoforge.capabilities.RegisterCapabilitiesEvent;
import org.jetbrains.annotations.Nullable;
import java.util.Arrays;
import java.util.Collection;
import java.util.function.Predicate;
/**
* 实体 Capability 注册工具类
* 简化批量注册实体能力的过程
*/
@SuppressWarnings("unused")
public class EntityCapabilityHelper {
/**
* 为多个实体类型注册相同的 Capability Provider
*
* @param <T> the type parameter
* @param <C> the type parameter
* @param event the event
* @param capability the capability
* @param provider the provider
* @param entityTypes the entity types
*/
public static <T, C extends @Nullable Object> void registerForEntityTypes(
RegisterCapabilitiesEvent event,
EntityCapability<T, C> capability,
ICapabilityProvider<Entity, C, T> provider,
EntityType<?>... entityTypes) {
if (entityTypes.length == 0) {
throw new IllegalArgumentException("Must specify at least one entity type");
}
for (EntityType<?> entityType : entityTypes) {
event.registerEntity(capability, entityType, provider);
}
}
/**
* 为继承自某个基类的所有实体注册 Capability
*
* @param <T> the type parameter
* @param <C> the type parameter
* @param event the event
* @param capability the capability
* @param provider the provider
* @param baseClass the base class
*/
public static <T, C extends @Nullable Object> void registerForEntityClass(
RegisterCapabilitiesEvent event,
EntityCapability<T, C> capability,
ICapabilityProvider<Entity, C, T> provider,
Class<? extends Entity> baseClass) {
BuiltInRegistries.ENTITY_TYPE.stream()
.filter(entityType -> entityType.getBaseClass().isAssignableFrom(baseClass))
.forEach(entityType -> event.registerEntity(capability, entityType, provider));
}
/**
* 为特定命名空间的所有实体注册 Capability
*
* @param <T> the type parameter
* @param <C> the type parameter
* @param event the event
* @param capability the capability
* @param provider the provider
* @param namespace the namespace
*/
public static <T, C extends @Nullable Object> void registerForModEntities(
RegisterCapabilitiesEvent event,
EntityCapability<T, C> capability,
ICapabilityProvider<Entity, C, T> provider,
String namespace) {
BuiltInRegistries.ENTITY_TYPE.stream()
.filter(entityType -> {
ResourceLocation key = BuiltInRegistries.ENTITY_TYPE.getKey(entityType);
return namespace.equals(key.getNamespace());
})
.forEach(entityType -> event.registerEntity(capability, entityType, provider));
}
/**
* 为特定生物类别的所有实体注册 Capability
*
* @param <T> the type parameter
* @param <C> the type parameter
* @param event the event
* @param capability the capability
* @param provider the provider
* @param category the category
*/
public static <T, C extends @Nullable Object> void registerForMobCategory(
RegisterCapabilitiesEvent event,
EntityCapability<T, C> capability,
ICapabilityProvider<Entity, C, T> provider,
MobCategory category) {
BuiltInRegistries.ENTITY_TYPE.stream()
.filter(entityType -> entityType.getCategory() == category)
.forEach(entityType -> event.registerEntity(capability, entityType, provider));
}
/**
* 基于条件筛选注册实体 Capability
*
* @param <T> the type parameter
* @param <C> the type parameter
* @param event the event
* @param capability the capability
* @param provider the provider
* @param condition the condition
*/
public static <T, C extends @Nullable Object> void registerEntitiesByCondition(
RegisterCapabilitiesEvent event,
EntityCapability<T, C> capability,
ICapabilityProvider<Entity, C, T> provider,
Predicate<EntityType<?>> condition) {
BuiltInRegistries.ENTITY_TYPE.stream()
.filter(condition)
.forEach(entityType -> event.registerEntity(capability, entityType, provider));
}
/**
* 为所有生物实体注册 Capability包括玩家
*
* @param <T> the type parameter
* @param <C> the type parameter
* @param event the event
* @param capability the capability
* @param provider the provider
*/
public static <T, C extends @Nullable Object> void registerForAllLivingEntities(
RegisterCapabilitiesEvent event,
EntityCapability<T, C> capability,
ICapabilityProvider<Entity, C, T> provider) {
registerForEntityClass(event, capability, provider, LivingEntity.class);
}
/**
* 为所有怪物实体注册 Capability
*
* @param <T> the type parameter
* @param <C> the type parameter
* @param event the event
* @param capability the capability
* @param provider the provider
*/
public static <T, C extends @Nullable Object> void registerForAllMonsters(
RegisterCapabilitiesEvent event,
EntityCapability<T, C> capability,
ICapabilityProvider<Entity, C, T> provider) {
registerForEntityClass(event, capability, provider, Monster.class);
}
/**
* 为所有动物实体注册 Capability
*
* @param <T> the type parameter
* @param <C> the type parameter
* @param event the event
* @param capability the capability
* @param provider the provider
*/
public static <T, C extends @Nullable Object> void registerForAllAnimals(
RegisterCapabilitiesEvent event,
EntityCapability<T, C> capability,
ICapabilityProvider<Entity, C, T> provider) {
registerForEntityClass(event, capability, provider, Animal.class);
}
/**
* 为所有玩家注册 Capability
*
* @param <T> the type parameter
* @param <C> the type parameter
* @param event the event
* @param capability the capability
* @param provider the provider
*/
public static <T, C extends @Nullable Object> void registerForPlayers(
RegisterCapabilitiesEvent event,
EntityCapability<T, C> capability,
ICapabilityProvider<Entity, C, T> provider) {
registerForEntityTypes(event, capability, provider, EntityType.PLAYER);
}
/**
* 为所有BOSS实体注册 Capability
*
* @param <T> the type parameter
* @param <C> the type parameter
* @param event the event
* @param capability the capability
* @param provider the provider
*/
public static <T, C extends @Nullable Object> void registerForBossEntities(
RegisterCapabilitiesEvent event,
EntityCapability<T, C> capability,
ICapabilityProvider<Entity, C, T> provider) {
registerEntitiesByCondition(event, capability, provider, entityType ->
entityType == EntityType.ENDER_DRAGON ||
entityType == EntityType.WITHER ||
entityType == EntityType.WARDEN
);
}
/**
* 排除特定实体类型进行注册
*
* @param <T> the type parameter
* @param <C> the type parameter
* @param event the event
* @param capability the capability
* @param provider the provider
* @param includedEntities the included entities
* @param excludedTypes the excluded types
*/
public static <T, C extends @Nullable Object> void registerWithExclusions(
RegisterCapabilitiesEvent event,
EntityCapability<T, C> capability,
ICapabilityProvider<Entity, C, T> provider,
Collection<EntityType<?>> includedEntities,
EntityType<?>... excludedTypes) {
Collection<EntityType<?>> excludedSet = Arrays.asList(excludedTypes);
includedEntities.stream()
.filter(entityType -> !excludedSet.contains(entityType))
.forEach(entityType -> event.registerEntity(capability, entityType, provider));
}
/**
* 检查某个实体类型是否已经注册了指定的 Capability
*
* @param event the event
* @param capability the capability
* @param entityType the entity type
* @return the boolean
*/
public static boolean isEntityCapabilityRegistered(
RegisterCapabilitiesEvent event,
EntityCapability<?, ?> capability,
EntityType<?> entityType) {
return event.isEntityRegistered(capability, entityType);
}
/**
* 获取已注册指定 Capability 的实体类型数量
*
* @param event the event
* @param capability the capability
* @return the registered entity count
*/
public static long getRegisteredEntityCount(
RegisterCapabilitiesEvent event,
EntityCapability<?, ?> capability) {
return BuiltInRegistries.ENTITY_TYPE.stream()
.filter(entityType -> event.isEntityRegistered(capability, entityType))
.count();
}
}

View File

@ -9,9 +9,9 @@ import top.r3944realms.lib39.util.block.BlockRegistryBuilder;
import java.util.function.Supplier; import java.util.function.Supplier;
/** /**
* The type Forge block registry builder. * The type NeoForge block registry builder.
*/ */
public class ForgeBlockRegistryBuilder extends BlockRegistryBuilder { public class NeoForgeBlockRegistryBuilder extends BlockRegistryBuilder {
@SafeVarargs @SafeVarargs
@Override @Override
protected final void registerBlockItem(Supplier<Block> blockObject, ResourceKey<CreativeModeTab>... creativeTabs) { protected final void registerBlockItem(Supplier<Block> blockObject, ResourceKey<CreativeModeTab>... creativeTabs) {

View File

@ -2,7 +2,7 @@
"required": true, "required": true,
"minVersion": "0.8", "minVersion": "0.8",
"package": "top.r3944realms.lib39.mixin", "package": "top.r3944realms.lib39.mixin",
"refmap": "${mod_id}.refmap.json", "refmap": "${mod_id}.neoforge.refmap.json",
"compatibilityLevel": "JAVA_21", "compatibilityLevel": "JAVA_21",
"mixins": [ "mixins": [
], ],