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 {
id 'fabric-loom' version '1.9-SNAPSHOT' apply(false)
id 'net.neoforged.moddev.legacyforge' version '2.0.103' apply(false)
id 'fabric-loom' version '1.9-SNAPSHOT' 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.addBooleanOption('Xdoclint:none', true)
options.addStringOption('doctitle', "${mod_id} ${minecraft_version} ${version} Javadoc")
}
tasks.named('sourcesJar', Jar) {

View File

@ -24,7 +24,7 @@ public class Lib39RecipeProvider extends RecipeProvider {
}
@Override
protected void buildRecipes(RecipeOutput recipeOutput) {
public void buildRecipes(RecipeOutput recipeOutput) {
ShapelessRecipeBuilder.shapeless(RecipeCategory.MISC, Lib39Items.DOLL.get())
.requires(ItemTags.WOOL)
.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.Pair;
import javax.annotation.ParametersAreNonnullByDefault;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
/**
* The type Wheel widget.
*
* @author QiuShui1012
*/
@MethodsReturnNonnullByDefault
@ParametersAreNonnullByDefault
public class WheelWidget extends AbstractWidget {
/**
* The constant IGNORE_CURSOR_MOVE_LENGTH.
@ -749,8 +745,15 @@ public class WheelWidget extends AbstractWidget {
protected void updateWidgetNarration(NarrationElementOutput narrationElementOutput) {
}
/**
* The type Wheel section.
* @param center 中心
* @param angle 角度
* @param angleStart 开始角度
* @param angleEnd 结束角度
* @param subTitle 副标题
* @param renderer 渲染操作
*/
public record WheelSection(
Vector2f center,

View File

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

View File

@ -6,7 +6,13 @@ import net.minecraft.world.phys.Vec3;
import org.jetbrains.annotations.NotNull;
import top.r3944realms.lib39.Lib39;
/**
* The enum Doll poses.
*/
public enum DollPoses implements IDollPose{
/**
* Default doll poses.
*/
DEFAULT(
"default",
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 org.jetbrains.annotations.NotNull;
/**
* The interface Doll pose.
*/
public interface IDollPose {
/**
* Gets id.
*
* @return the id
*/
@NotNull ResourceLocation getId();
/**
* Gets total offset.
*
* @return the total offset
*/
@NotNull default Vec3 getTotalOffset() {
return Vec3.ZERO;
}
/**
* Gets head pose.
*
* @return the head pose
*/
@NotNull PartPose getHeadPose();
/**
* Gets body pose.
*
* @return the body pose
*/
@NotNull PartPose getBodyPose();
/**
* Gets right arm pose.
*
* @return the right arm pose
*/
@NotNull PartPose getRightArmPose();
/**
* Gets left arm pose.
*
* @return the left arm pose
*/
@NotNull PartPose getLeftArmPose();
/**
* Gets right leg pose.
*
* @return the right leg pose
*/
@NotNull PartPose getRightLegPose();
/**
* Gets left leg pose.
*
* @return the left leg pose
*/
@NotNull PartPose getLeftLegPose();
}

View File

@ -5,20 +5,17 @@ import net.minecraft.Util;
import net.minecraft.core.BlockPos;
import net.minecraft.core.HolderLookup;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.NbtUtils;
import net.minecraft.network.protocol.game.ClientboundBlockEntityDataPacket;
import net.minecraft.world.item.component.ResolvableProfile;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.entity.SkullBlockEntity;
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.util.GameProfileHelper;
import top.r3944realms.lib39.util.nbt.NBTReader;
import top.r3944realms.lib39.util.nbt.NBTWriter;
import javax.annotation.Nullable;
/**
* 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.MutableComponent;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import top.r3944realms.lib39.base.datagen.value.Lib39LangKey;
import top.r3944realms.lib39.platform.Services;
import javax.annotation.Nullable;
/**
* The interface Help command.
*/

View File

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

View File

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

View File

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

View File

@ -127,12 +127,12 @@ public class TradeBuilder {
/**
* 创建宝藏地图交易
*
* @param emeraldCost 绿宝石价格
* @param destination the destination
* @param displayName 显示名称
* @param emeraldCost 绿宝石价格
* @param destination the destination
* @param displayName 显示名称
* @param destinationType the destination type
* @param maxUses 最大使用次数
* @param villagerXp 村民获得的经验
* @param maxUses 最大使用次数
* @param villagerXp 村民获得的经验
* @return 交易实例 treasure map for emeralds
*/
@Contract(pure = true)

View File

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

View File

@ -1,7 +1,8 @@
package top.r3944realms.lib39.core.network;
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.
@ -12,10 +13,13 @@ public class FabricNetworkHandler {
* 注册客户端接收的数据包
*/
public static void registerClientReceivers() {
ClientPlayNetworking.registerGlobalReceiver(
SyncNBTLookupDataEntityS2CPacket.TYPE,
SyncNBTLookupDataEntityS2CPacket::handle
PayloadTypeRegistry.playS2C().register(
SyncNBTLookupDataEntityS2CPayload.TYPE,
SyncNBTLookupDataEntityS2CPayload.STREAM_CODEC
);
ClientPlayNetworking.registerGlobalReceiver(
SyncNBTLookupDataEntityS2CPayload.TYPE,
SyncNBTLookupDataEntityS2CPayload::handle
);
}
}

View File

@ -1,18 +1,15 @@
package top.r3944realms.lib39.core.network.toClient;
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.nbt.CompoundTag;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.network.RegistryFriendlyByteBuf;
import net.minecraft.network.codec.StreamCodec;
import net.minecraft.network.protocol.PacketType;
import net.minecraft.network.protocol.common.custom.CustomPacketPayload;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.level.Level;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;
import top.r3944realms.lib39.Lib39;
import top.r3944realms.lib39.core.event.FabricCommonEventHandler;
@ -23,9 +20,9 @@ import top.r3944realms.lib39.core.sync.SyncData2Manager;
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.
*/
@ -34,7 +31,14 @@ public record SyncNBTLookupDataEntityS2CPacket(int entityId, ResourceLocation id
/**
* 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.
@ -42,7 +46,7 @@ public record SyncNBTLookupDataEntityS2CPacket(int entityId, ResourceLocation id
* @param entityId the entity id
* @param data the data
*/
public SyncNBTLookupDataEntityS2CPacket(int entityId, @NotNull NBTEntitySyncData data) {
public SyncNBTLookupDataEntityS2CPayload(int entityId, @NotNull NBTEntitySyncData data) {
this(entityId, data.id(), data.serializeNBT());
}
@ -51,48 +55,48 @@ public record SyncNBTLookupDataEntityS2CPacket(int entityId, ResourceLocation id
*
* @param buf the buffer
*/
public SyncNBTLookupDataEntityS2CPacket(RegistryFriendlyByteBuf buf) {
public SyncNBTLookupDataEntityS2CPayload(RegistryFriendlyByteBuf buf) {
this(buf.readInt(), buf.readResourceLocation(), buf.readNbt());
}
/**
* Write.
*
* @param friendlyByteBuf the friendly byte buf
*/
public void write(@NotNull FriendlyByteBuf friendlyByteBuf) {
friendlyByteBuf.writeInt(entityId);
friendlyByteBuf.writeResourceLocation(id);
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.
*
* @param packet the packet
* @param context the context
* @param payload the packet
* @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();
Level level = localPlayer.level();
Entity entity = level.getEntity(packet.entityId);
Entity entity = level.getEntity(payload.entityId);
if (entity != null) {
Optional<SyncData2Manager.DataProvider<Entity, ISyncData<?>>> lookupOpt =
FabricCommonEventHandler
.getSyncData2Manager()
.getDataProvider(packet.id);
.getDataProvider(payload.id);
lookupOpt.flatMap(dataProvider -> dataProvider.getData(entity))
.ifPresent(lookup -> {
if (lookup instanceof NBTEntitySyncData nbtLookup) {
CompoundTag current = nbtLookup.serializeNBT();
if (!current.equals(packet.data)) {
nbtLookup.deserializeNBT(packet.data);
if (!current.equals(payload.data)) {
nbtLookup.deserializeNBT(payload.data);
}
} 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.players.PlayerList;
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;
@ -19,8 +19,8 @@ public interface IFabricUpdate extends IUpdate {
PlayerList playerList = serverLevel.getServer().getPlayerList();
List<ServerPlayer> players = playerList.getPlayers();
for (ServerPlayer player : players) {
if (ServerPlayNetworking.canSend(player, SyncNBTLookupDataEntityS2CPacket.TYPE)) {
ServerPlayNetworking.send(player, new SyncNBTLookupDataEntityS2CPacket(getSyncData().entityId(), getSyncData()));
if (ServerPlayNetworking.canSend(player, SyncNBTLookupDataEntityS2CPayload.TYPE)) {
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.
* Register this with ServerPlayNetworking.registerGlobalReceiver
*
* @param packet the packet
* @param context the context
*/
public static void handle(FabricClientDataPacket packet, ServerPlayNetworking.Context context) {
ServerPlayer serverPlayer = context.player();

View File

@ -46,6 +46,7 @@ public abstract class MixinMinecraft extends ReentrantBlockableEventLoop<Runnabl
* Set clientLevel callback.
*
* @param clientLevel the clientLevel client
* @param reason the reason
* @param original the original
*/
@WrapMethod(method = "setLevel")
@ -57,7 +58,8 @@ public abstract class MixinMinecraft extends ReentrantBlockableEventLoop<Runnabl
/**
* Clear level callback.
*
* @param original the original
* @param nextScreen the next screen
* @param original the original
*/
@WrapMethod(method = "clearClientLevel")
public void clearLevel$callback(Screen nextScreen, Operation<Void> original) {
@ -68,9 +70,10 @@ public abstract class MixinMinecraft extends ReentrantBlockableEventLoop<Runnabl
/**
* Set level setup.
*
* @param level the level client
* @param ci the ci
* @param services the services
* @param level the level client
* @param reason the reason
* @param ci the ci
* @param services the services
*/
@Inject(
method = "setLevel",
@ -87,7 +90,7 @@ public abstract class MixinMinecraft extends ReentrantBlockableEventLoop<Runnabl
/**
* Do world load setup.
*
* @param levelStorage the level id
* @param levelStorage the level id
* @param packRepository the pack repository
* @param worldStem the world stem
* @param newWorld the new world

View File

@ -2,7 +2,7 @@
"required": true,
"minVersion": "0.8",
"package": "top.r3944realms.lib39.mixin",
"refmap": "${mod_id}.refmap.json",
"refmap": "${mod_id}.fabric.refmap.json",
"compatibilityLevel": "JAVA_18",
"mixins": [
"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.
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
parchment_minecraft=1.21
parchment_version=2024.11.10
parchment_minecraft=1.21.1
parchment_version=2024.11.17
neo_form_version=1.21.1-20240808.144430
# NeoForge

View File

@ -14,9 +14,15 @@ import top.r3944realms.lib39.example.NeoForgeLib39Example;
*/
@Mod(Lib39.MOD_ID)
public class Lib39NeoForge {
/**
* The constant modEventBus.
*/
public static IEventBus modEventBus;
/**
* Instantiates a new Lib 39.
*
* @param modEventBus the mod event bus
*/
public Lib39NeoForge(IEventBus modEventBus) {
Lib39.initialize();
@ -28,35 +34,38 @@ public class Lib39NeoForge {
/**
* Initialize.
*
* @param modEventBus the mod event bus
*/
public static void initialize(IEventBus modEventBus) {
Lib39.LOGGER.info("[Lib39-Forge] Hello Forge");
Lib39.LOGGER.info("[Lib39-NeoForge] Hello NeoForge");
NeoForgeLib39Blocks.register(modEventBus);
NeoForgeLib39Items.register(modEventBus);
NeoForgeLib39BlockEntities.register(modEventBus);
NeoForgeLib39SoundEvents.register(modEventBus);
NetworkHandler.register();
if (Lib39.shouldRegisterExamples()) {
Lib39.LOGGER.info("[Lib39-Forge] Registering Examples");
Lib39.LOGGER.info("[Lib39-NeoForge] Registering Examples");
registerExamples(modEventBus);
}
Lib39.LOGGER.info("[Lib39-Forge] Finished Initializing.");
Lib39.LOGGER.info("[Lib39-NeoForge] Finished Initializing.");
}
/**
* Register examples.
*
* @param modEventBus the mod event bus
*/
static void registerExamples(IEventBus modEventBus) {
Lib39.LOGGER.info("[Lib39-Forge] Starting example demonstrations");
Lib39.LOGGER.info("[Lib39-NeoForge] Starting example demonstrations");
try {
// 创建示例实例并演示功能
NeoForgeLib39Example example = new NeoForgeLib39Example(modEventBus);
example.demonstrateFeature();
Lib39.LOGGER.info("[Lib39-Forge] Example demonstrations completed successfully");
Lib39.LOGGER.info("[Lib39-NeoForge] Example demonstrations completed successfully");
} 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.neoforged.bus.api.Event;
import net.neoforged.neoforge.capabilities.EntityCapability;
import top.r3944realms.lib39.core.sync.ISyncData;
import top.r3944realms.lib39.core.sync.ISyncManager;
import top.r3944realms.lib39.core.sync.SyncData2CapManager;
@ -45,8 +46,8 @@ public class SyncManagerRegisterEvent extends Event {
*/
public <K, T extends ISyncData<?>> void registerSyncManager(
ResourceLocation id,
ISyncManager<Capability<T>, T> syncManager,
Capability<T> capability
ISyncManager<EntityCapability<T, Void>, T> syncManager,
EntityCapability<T, Void> capability
) {
syncs2Manager.registerManager(id, syncManager, capability);
}
@ -87,7 +88,7 @@ public class SyncManagerRegisterEvent extends Event {
* @param id 必须先注册安全同步管理器再绑定Cap否则会抛出{@link IllegalStateException 未找到对应安全同步管理器}
* @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);
}
@ -112,8 +113,8 @@ public class SyncManagerRegisterEvent extends Event {
*/
public <K, T extends ISyncData<?>> void registerComplete(
ResourceLocation id,
ISyncManager<Capability<T>, T> syncManager,
Capability<T> capability,
ISyncManager<EntityCapability<T, Void>, T> syncManager,
EntityCapability<T, Void> capability,
Class<?>... allowedEntityClasses
) {
registerSyncManager(id, syncManager, capability);

View File

@ -73,7 +73,7 @@ public class Lib39BaseDataGenEvent {
private static void LootTableDataGenerate(@NotNull GatherDataEvent event) {
event.getGenerator().addProvider(
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) {

View File

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

View File

@ -67,6 +67,12 @@ public class ClientEventHandler {
public static void registerLayerDefinitions(EntityRenderersEvent.@NotNull RegisterLayerDefinitions event) {
event.registerLayerDefinition(DollModel.LAYER_LOCATION, DollModel::createBodyLayer);
}
/**
* On register client ex.
*
* @param event the event
*/
@SubscribeEvent
public static void onRegisterClientEx (@NotNull RegisterClientExtensionsEvent event) {
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 net.minecraft.Util;
import net.minecraft.client.multiplayer.ClientLevel;
import net.minecraft.core.component.DataComponents;
import net.minecraft.network.chat.Component;
import net.minecraft.resources.ResourceKey;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.CreativeModeTab;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Items;
import net.minecraft.world.item.component.ResolvableProfile;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.LevelAccessor;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.entity.SkullBlockEntity;
import net.neoforged.bus.api.SubscribeEvent;
import net.neoforged.fml.common.EventBusSubscriber;
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.EntityLeaveLevelEvent;
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.api.event.SyncManagerRegisterEvent;
import top.r3944realms.lib39.base.command.Lib39HelpCommand;
import top.r3944realms.lib39.base.datagen.Lib39BaseDataGenEvent;
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.sync.ISyncData;
import top.r3944realms.lib39.core.sync.SyncData2CapManager;
@ -132,13 +137,11 @@ public class CommonEventHandler {
* @param event the event
*/
@SubscribeEvent
public static void onServerTick(TickEvent.ServerTickEvent event) {
if (event.phase == TickEvent.Phase.END) {
if (syncData2Manager == null) return;
if (event.getServer().getTickCount() % 10 == 0)
syncData2Manager.forEach(((resourceLocation, iSyncManager) -> iSyncManager.foreach(ISyncData::markDirty)));
syncData2Manager.forEach(((resourceLocation, iSyncManager) -> iSyncManager.foreach(ISyncData::checkIfDirtyThenUpdate)));
}
public static void onServerTick(ServerTickEvent.Post event) {
if (syncData2Manager == null) return;
if (event.getServer().getTickCount() % 10 == 0)
syncData2Manager.forEach(((resourceLocation, iSyncManager) -> iSyncManager.foreach(ISyncData::markDirty)));
syncData2Manager.forEach(((resourceLocation, iSyncManager) -> iSyncManager.foreach(ISyncData::checkIfDirtyThenUpdate)));
}
/**
@ -150,18 +153,27 @@ public class CommonEventHandler {
public static void onAnvilRename(AnvilUpdateEvent event) {
if (event.getLeft().getItem() instanceof DollItem) {
String name = event.getName();
Player player = event.getPlayer();
if (name != null && name.length() < 15) {
GameProfile profile = new GameProfile(Util.NIL_UUID, name);
ItemStack copied = Lib39Items.DOLL.get().getDefaultInstance();
SkullBlockEntity.updateGameprofile(profile,
profile1 -> GameProfileHelper.saveProfileToItemStack(copied, profile1)
);
ResolvableProfile resolvableProfile = new ResolvableProfile(profile);
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());
event.setOutput(copied);
event.setCost(1);
} else {
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);
}
}
@ -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.
*

View File

@ -1,9 +1,10 @@
package top.r3944realms.lib39.core.event;
import net.minecraft.server.level.ServerLevel;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.event.level.LevelEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.neoforged.api.distmarker.Dist;
import net.neoforged.bus.api.SubscribeEvent;
import net.neoforged.fml.common.EventBusSubscriber;
import net.neoforged.neoforge.event.level.LevelEvent;
import top.r3944realms.lib39.Lib39;
import top.r3944realms.lib39.util.ILevelHelper;
@ -19,7 +20,7 @@ public class ServerEventHandler {
/**
* 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 {
/**
* Register layer definitions.

View File

@ -1,72 +1,28 @@
package top.r3944realms.lib39.core.network;
import net.minecraft.server.level.ServerPlayer;
import net.minecraftforge.network.NetworkDirection;
import net.minecraftforge.network.NetworkRegistry;
import net.minecraftforge.network.PacketDistributor;
import net.minecraftforge.network.simple.SimpleChannel;
import net.neoforged.neoforge.network.event.RegisterPayloadHandlersEvent;
import net.neoforged.neoforge.network.registration.PayloadRegistrar;
import org.jetbrains.annotations.NotNull;
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.
*/
@SuppressWarnings("unused")
public class NetworkHandler {
private static int cid = 0;
/**
* The constant INSTANCE.
*/
public static final SimpleChannel INSTANCE = NetworkRegistry.newSimpleChannel(
Lib39.rl(Lib39.MOD_ID, "main"),
() -> Lib39.ModInfo.VERSION,
Lib39.ModInfo.VERSION::equals,
Lib39.ModInfo.VERSION::equals
);
/**
* 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.
* Register packets.
*
* @param <MSG> the type parameter
* @param message the message
* @param player the player
* @param event the event
*/
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);
public static void register(@NotNull RegisterPayloadHandlersEvent event) {
PayloadRegistrar registrar = event.registrar(Lib39.ModInfo.VERSION);
registrar
.playToClient(
SyncNBTCapDataEntityS2CPayload.TYPE,
SyncNBTCapDataEntityS2CPayload.STREAM_CODEC,
SyncNBTCapDataEntityS2CPayload::handle
);
}
}

View File

@ -4,9 +4,12 @@ import net.minecraft.client.Minecraft;
import net.minecraft.client.multiplayer.ClientLevel;
import net.minecraft.nbt.CompoundTag;
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.world.entity.Entity;
import net.minecraftforge.network.NetworkEvent;
import net.neoforged.neoforge.network.handling.IPayloadContext;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;
import top.r3944realms.lib39.Lib39;
@ -19,10 +22,25 @@ import java.util.Optional;
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")
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.
@ -30,7 +48,7 @@ public record SyncNBTCapDataEntityS2CPacket(int entityId, ResourceLocation id, C
* @param entityId the entity id
* @param data the data
*/
public SyncNBTCapDataEntityS2CPacket(int entityId, @NotNull NBTEntitySyncData data) {
public SyncNBTCapDataEntityS2CPayload(int entityId, @NotNull NBTEntitySyncData data) {
this(entityId, data.id(), data.serializeNBT());
}
@ -40,7 +58,7 @@ public record SyncNBTCapDataEntityS2CPacket(int entityId, ResourceLocation id, C
* @param msg the msg
* @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.writeResourceLocation(msg.id);
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
*/
@Contract("_ -> new")
public static @NotNull SyncNBTCapDataEntityS2CPacket decode(@NotNull FriendlyByteBuf buffer) {
return new SyncNBTCapDataEntityS2CPacket(buffer.readInt(), buffer.readResourceLocation(), buffer.readNbt());
public static @NotNull SyncNBTCapDataEntityS2CPayload decode(@NotNull FriendlyByteBuf buffer) {
return new SyncNBTCapDataEntityS2CPayload(buffer.readInt(), buffer.readResourceLocation(), buffer.readNbt());
}
/**
* Handle.
*
* @param msg the msg
* @param ctx the ctx
* @param payload the msg
* @param context the context
*/
public static void handle(SyncNBTCapDataEntityS2CPacket msg, @NotNull Supplier<NetworkEvent.Context> ctx) {
NetworkEvent.Context context = ctx.get();
public static void handle(SyncNBTCapDataEntityS2CPayload payload, @NotNull IPayloadContext context) {
context.enqueueWork(() -> {
ClientLevel level = Minecraft.getInstance().level;
if (level != null) {
Entity entity = level.getEntity(msg.entityId);
Entity entity = level.getEntity(payload.entityId);
if (entity != null) {
Optional<SyncData2Manager.DataProvider<Entity, ISyncData<?>>> capOpt =
CommonEventHandler.Game
.getSyncData2Manager()
.getDataProvider(msg.id);
.getDataProvider(payload.id);
capOpt.flatMap(dataProvider -> dataProvider.getData(entity))
.ifPresent(cap -> {
if (cap instanceof NBTEntitySyncData nbtCap) {
CompoundTag current = nbtCap.serializeNBT();
if (!current.equals(msg.data)) {
nbtCap.deserializeNBT(msg.data);
if (!current.equals(payload.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;
import net.neoforged.neoforge.network.PacketDistributor;
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.
*/
public interface INeoForgeUpdate extends IUpdate {
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 net.minecraft.resources.ResourceLocation;
import net.minecraftforge.common.capabilities.Capability;
import net.neoforged.neoforge.capabilities.EntityCapability;
import org.jetbrains.annotations.Nullable;
import java.util.Map;
@ -29,15 +29,15 @@ public class SyncData2CapManager extends SyncData2Manager<SyncData2CapManager.Ty
*
* @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.
*
* @param manager the manager
* @param capability the capability
*/
public TypedSyncEntry(ISyncManager<Capability<T>, T> manager,@Nullable Capability<T> capability) {
super(manager, key -> capability != null ? key.getCapability(capability).resolve() : Optional.empty());
public TypedSyncEntry(ISyncManager<EntityCapability<T, Void>, T> manager,@Nullable EntityCapability<T, Void> capability) {
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(
ResourceLocation key,
ISyncManager<Capability<T>, T> manager,
Capability<T> capability
ISyncManager<EntityCapability<T, Void>, T> manager,
EntityCapability<T, Void> capability
) {
Objects.requireNonNull(key, "ResourceLocation key 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 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(capability, "Capability cannot be null");
@ -103,7 +103,7 @@ public class SyncData2CapManager extends SyncData2Manager<SyncData2CapManager.Ty
* @param entry the entry
* @param newCapability the new capability
*/
protected <T extends ISyncData<?>> void updateCapabilityInEntry(ResourceLocation id, TypedSyncEntry<?> entry, Capability<T> newCapability) {
updateDataProviderInEntry(id, entry, key -> newCapability != null ? key.getCapability(newCapability).resolve() : Optional.empty());
protected <T extends ISyncData<?>> void updateCapabilityInEntry(ResourceLocation id, TypedSyncEntry<?> entry, EntityCapability<T, Void> newCapability) {
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;
import net.minecraft.core.HolderLookup;
import net.minecraft.core.WritableRegistry;
import net.minecraft.data.PackOutput;
import net.minecraft.data.loot.LootTableProvider;
import net.minecraft.resources.ResourceKey;
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.ValidationContext;
import org.jetbrains.annotations.NotNull;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
/**
* The type Simple loot table provider.
@ -19,9 +24,10 @@ public class SimpleLootTableProvider extends LootTableProvider {
*
* @param output the output
* @param subProvidersWrapper the sub providers wrapper
* @param registries the registries
*/
public SimpleLootTableProvider(PackOutput output, @NotNull SubProvidersWrapper subProvidersWrapper) {
super(output, Set.of(), subProvidersWrapper.entries);
public SimpleLootTableProvider(PackOutput output, @NotNull SubProvidersWrapper subProvidersWrapper, CompletableFuture<HolderLookup.Provider> registries) {
super(output, Set.of(), subProvidersWrapper.entries, registries);
}
/**
@ -30,13 +36,14 @@ public class SimpleLootTableProvider extends LootTableProvider {
* @param output the output
* @param requiredTables the required tables
* @param subProvidersWrapper the sub providers wrapper
* @param registries the registries
*/
public SimpleLootTableProvider(PackOutput output, Set<ResourceLocation> requiredTables, @NotNull SubProvidersWrapper subProvidersWrapper) {
super(output, requiredTables, subProvidersWrapper.entries);
public SimpleLootTableProvider(PackOutput output, Set<ResourceKey<LootTable>> requiredTables, @NotNull SubProvidersWrapper subProvidersWrapper, CompletableFuture<HolderLookup.Provider> registries) {
super(output, requiredTables, subProvidersWrapper.entries, registries);
}
@Override
protected void validate(@NotNull Map<ResourceLocation, LootTable> map, @NotNull ValidationContext validationcontext) {
map.forEach((id, table) -> table.validate(validationcontext));
protected void validate(WritableRegistry<LootTable> writableregistry, ValidationContext validationcontext, ProblemReporter.Collector problemreporter$collector) {
writableregistry.forEach(lootTable -> lootTable.validate(validationcontext));
}
}

View File

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

View File

@ -1,24 +1,25 @@
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.world.flag.FeatureFlags;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.enchantment.Enchantment;
import net.minecraft.world.item.enchantment.Enchantments;
import net.minecraft.world.level.ItemLike;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.FlowerPotBlock;
import net.minecraft.world.level.block.*;
import net.minecraft.world.level.block.state.properties.Property;
import net.minecraft.world.level.storage.loot.LootPool;
import net.minecraft.world.level.storage.loot.LootTable;
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.SetItemCountFunction;
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.functions.*;
import net.minecraft.world.level.storage.loot.predicates.*;
import net.minecraft.world.level.storage.loot.providers.number.ConstantValue;
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.NotNull;
@ -42,9 +43,10 @@ public class BlockLootTables extends BlockLootSubProvider {
* Instantiates a new Block loot tables.
*
* @param deferredRegister the deferred register
* @param registries the registries
*/
public BlockLootTables(DeferredRegister<Block> deferredRegister) {
super(Set.of(), FeatureFlags.REGISTRY.allFlags());
public BlockLootTables(DeferredRegister<Block> deferredRegister, HolderLookup.Provider registries) {
super(Set.of(), FeatureFlags.REGISTRY.allFlags(), registries);
knowBlocks = deferredRegister;
}
@ -86,7 +88,7 @@ public class BlockLootTables extends BlockLootSubProvider {
* @return the block loot tables
*/
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
*/
public BlockLootTables dropFlowerPot(Supplier<Block> block) {
return addEntry(block, (pBlock) -> this.createPotFlowerItemTable(((FlowerPotBlock)pBlock).getContent()));
return addEntry(block, this::createPotFlowerItemTable);
}
/**
@ -336,32 +338,44 @@ public class BlockLootTables extends BlockLootSubProvider {
* 创建新的战利品表生成器
*
* @param deferredRegister the deferred register
* @param registries the registries
* @return the block loot tables
*/
@Contract("_ -> new")
public static @NotNull BlockLootTables create(DeferredRegister<Block> deferredRegister) {
return new BlockLootTables(deferredRegister);
public static @NotNull BlockLootTables create(DeferredRegister<Block> deferredRegister, HolderLookup.Provider registries) {
return new BlockLootTables(deferredRegister, registries);
}
/**
* 快速创建基本矿物的掉落表
*
* @param oreBlock the ore block
* @param oreItem the ore item
* @param oreBlock the ore block
* @param oreItem the ore item
* @param registries the registries
* @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()
.withPool(LootPool.lootPool()
.setRolls(ConstantValue.exactly(1))
.add(LootItem.lootTableItem(oreItem)
.when(MatchTool.toolMatches(ItemPredicate.Builder.item()
.hasEnchantment(new net.minecraft.advancements.critereon.EnchantmentPredicate(
Enchantments.SILK_TOUCH,
net.minecraft.advancements.critereon.MinMaxBounds.Ints.atLeast(1)
))).invert())
.when(MatchTool.toolMatches(silkTouchPredicates).invert())
.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 dropItem the drop item
* @param registries the registries
* @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()
.withPool(LootPool.lootPool()
.setRolls(ConstantValue.exactly(1))
.add(LootItem.lootTableItem(dropItem)
.when(MatchTool.toolMatches(ItemPredicate.Builder.item()
.hasEnchantment(new net.minecraft.advancements.critereon.EnchantmentPredicate(
Enchantments.SILK_TOUCH,
net.minecraft.advancements.critereon.MinMaxBounds.Ints.atLeast(1)
))))));
.when(MatchTool.toolMatches(silkTouchPredicate))));
}
/**
* 快速创建基本矿物的掉落表需要获取附魔的 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.
*
* @param modEventBus the mod event bus
*/
public NeoForgeLib39Example(IEventBus modEventBus) {
if (!registered) {
@ -25,25 +27,16 @@ public class NeoForgeLib39Example {
/**
* Init.
*
* @param modEventBus the mod event bus
*/
public void init(IEventBus modEventBus) {
NeoForgeExLib39Items.register(modEventBus);
ExNetworkHandler.register();
}
private void registerToEventBus(IEventBus modEventBus) {
IEventBus modBus = modEventBus;
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);
gameBus.register(ExCommonEventHandler.Game.class);

View File

@ -1,12 +1,13 @@
package top.r3944realms.lib39.example.content.data;
import net.minecraft.world.entity.Entity;
import net.minecraftforge.common.capabilities.Capability;
import net.minecraftforge.common.capabilities.CapabilityManager;
import net.minecraftforge.common.capabilities.CapabilityToken;
import net.minecraftforge.common.capabilities.RegisterCapabilitiesEvent;
import net.minecraftforge.event.AttachCapabilitiesEvent;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.vehicle.Boat;
import net.minecraft.world.entity.vehicle.Minecart;
import net.neoforged.neoforge.capabilities.EntityCapability;
import net.neoforged.neoforge.capabilities.RegisterCapabilitiesEvent;
import org.jetbrains.annotations.NotNull;
import top.r3944realms.lib39.Lib39;
import top.r3944realms.lib39.util.EntityCapabilityHelper;
/**
* The type Ex capability handler.
@ -15,7 +16,10 @@ public class ExCapabilityHandler {
/**
* 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.
@ -23,18 +27,23 @@ public class ExCapabilityHandler {
* @param event the event
*/
public static void registerCapability(@NotNull RegisterCapabilitiesEvent event) {
event.register(AbstractedTestSyncData.class);
}
/**
* Attach capability.
*
* @param event the event
*/
public static void attachCapability(@NotNull AttachCapabilitiesEvent<?> event) {
Object object = event.getObject();
if(object instanceof Entity entity) {
event.addCapability(TestSyncCapProvider.TEST_SYNC_REL, new TestSyncCapProvider(entity));
}
EntityCapabilityHelper.registerForEntityClass(
event,
TEST_CAP,
(entity, context) -> entity.getCapability(TEST_CAP),
LivingEntity.class
);
EntityCapabilityHelper.registerForEntityClass(
event,
TEST_CAP,
(entity, context) -> entity.getCapability(TEST_CAP),
Boat.class
);
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.world.entity.Entity;
import net.minecraft.world.entity.LivingEntity;
import net.neoforged.neoforge.network.PacketDistributor;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import top.r3944realms.lib39.Lib39;
import top.r3944realms.lib39.example.content.data.AbstractedTestSyncData;
import top.r3944realms.lib39.example.content.data.ExCapabilityHandler;
import top.r3944realms.lib39.example.content.data.TestSyncData;
import top.r3944realms.lib39.example.core.network.ClientDataPacket;
import top.r3944realms.lib39.example.core.network.ExNetworkHandler;
import top.r3944realms.lib39.example.core.network.toServer.ClientDataPayload;
/**
* The type Forge fabric item.
@ -34,7 +34,7 @@ public class NeoForgeFabricItem extends AbstractFabricItem {
@Override
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) {
try {
AbstractedTestSyncData abstractData = target.getCapability(ExCapabilityHandler.TEST_CAP).resolve().orElse(null);
AbstractedTestSyncData abstractData = target.getCapability(ExCapabilityHandler.TEST_CAP);
if (abstractData instanceof TestSyncData) {
return abstractData;
}

View File

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

View File

@ -1,10 +1,17 @@
package top.r3944realms.lib39.example.core.event;
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.SubscribeEvent;
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.network.event.RegisterPayloadHandlersEvent;
import top.r3944realms.lib39.Lib39NeoForge;
import top.r3944realms.lib39.api.event.SyncManagerRegisterEvent;
import top.r3944realms.lib39.core.compat.ICompatManager;
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.ExCapabilityHandler;
import top.r3944realms.lib39.example.content.data.TestSyncData;
import top.r3944realms.lib39.example.core.network.ExNetworkHandler;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
@ -28,15 +36,6 @@ public class ExCommonEventHandler {
@SuppressWarnings("unused")
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.
@ -48,16 +47,16 @@ public class ExCommonEventHandler {
event.registerSyncManager(
TestSyncData.ID,
new CachedSyncManager<>() {
private final Map<Capability<AbstractedTestSyncData>, AbstractedTestSyncData> syncDataMap = new ConcurrentHashMap<>();
private final Map<EntityCapability<AbstractedTestSyncData, Void>, AbstractedTestSyncData> syncDataMap = new ConcurrentHashMap<>();
@Override
public Map<Capability<AbstractedTestSyncData>, AbstractedTestSyncData> getSyncMap() {
public Map<EntityCapability<AbstractedTestSyncData, Void>, AbstractedTestSyncData> getSyncMap() {
return syncDataMap;
}
},
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) {
synchronized (CommonEventHandler.Mod.class) {
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);
}
/**
* 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;
import net.minecraftforge.network.NetworkRegistry;
import net.minecraftforge.network.simple.SimpleChannel;
import net.neoforged.neoforge.network.event.RegisterPayloadHandlersEvent;
import net.neoforged.neoforge.network.registration.PayloadRegistrar;
import top.r3944realms.lib39.Lib39;
import top.r3944realms.lib39.example.core.network.toServer.ClientDataPayload;
/**
* The type Ex network handler.
*/
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.
*
* @param event the event
*/
public static void register() {
// 注册数据包
INSTANCE.registerMessage(ID++, ClientDataPacket.class,
ClientDataPacket::toBytes,
ClientDataPacket::new,
ClientDataPacket::handle);
public static void register(RegisterPayloadHandlersEvent event) {
PayloadRegistrar registrar = event.registrar(Lib39.ModInfo.VERSION);
registrar.playToServer(
ClientDataPayload.TYPE,
ClientDataPayload.STREAM_CODEC,
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

@ -34,9 +34,10 @@ public abstract class MixinMinecraft extends ReentrantBlockableEventLoop<Runnabl
/**
* Set level setup.
*
* @param level the level client
* @param ci the ci
* @param services the services
* @param level the level client
* @param reason the reason
* @param ci the ci
* @param services the services
*/
@Inject(
method = "setLevel",

View File

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

View File

@ -1,7 +1,7 @@
package top.r3944realms.lib39.platform;
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;
/**
@ -14,6 +14,6 @@ public enum NeoForgeUtilHelper implements IUtilHelper {
INSTANCE;
@Override
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;
/**
* The type Forge block registry builder.
* The type NeoForge block registry builder.
*/
public class ForgeBlockRegistryBuilder extends BlockRegistryBuilder {
public class NeoForgeBlockRegistryBuilder extends BlockRegistryBuilder {
@SafeVarargs
@Override
protected final void registerBlockItem(Supplier<Block> blockObject, ResourceKey<CreativeModeTab>... creativeTabs) {

View File

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