docs: 添加Javadoc
This commit is contained in:
parent
418e85394c
commit
50856266d8
|
|
@ -8,14 +8,30 @@ import org.slf4j.LoggerFactory;
|
|||
import top.r3944realms.lib39.example.Lib39Example;
|
||||
import top.r3944realms.lib39.platform.Services;
|
||||
|
||||
/**
|
||||
* The type Lib 39.
|
||||
*/
|
||||
public class Lib39 {
|
||||
/**
|
||||
* The constant MOD_ID.
|
||||
*/
|
||||
public static final String MOD_ID = "lib39";
|
||||
/**
|
||||
* The constant MOD_NAME.
|
||||
*/
|
||||
public static final String MOD_NAME = "3944Realms 's Lib Mod";
|
||||
/**
|
||||
* The constant LOGGER.
|
||||
*/
|
||||
public static final Logger LOGGER = LoggerFactory.getLogger(MOD_NAME);
|
||||
/**
|
||||
* The constant ENABLE_EXAMPLES_PROPERTY_KEY.
|
||||
*/
|
||||
public static final String ENABLE_EXAMPLES_PROPERTY_KEY = "lib39.enable_examples";
|
||||
|
||||
/**
|
||||
* Initialize.
|
||||
*/
|
||||
public static void initialize() {
|
||||
Lib39.LOGGER.info("[Lib39-Common] Lib39-Common start initialization.");
|
||||
if (shouldRegisterExamples()) {
|
||||
|
|
@ -24,6 +40,7 @@ public class Lib39 {
|
|||
}
|
||||
Lib39.LOGGER.info("[Lib39-Common] Finished Lib39-Common!.");
|
||||
}
|
||||
|
||||
/**
|
||||
* Rl resource location.
|
||||
*
|
||||
|
|
@ -58,6 +75,11 @@ public class Lib39 {
|
|||
return new ResourceLocation(path);
|
||||
}
|
||||
|
||||
/**
|
||||
* Is client environment boolean.
|
||||
*
|
||||
* @return the boolean
|
||||
*/
|
||||
public static boolean isClientEnvironment() {
|
||||
return Services.PLATFORM.isClientEnvironment();
|
||||
}
|
||||
|
|
@ -87,6 +109,7 @@ public class Lib39 {
|
|||
LOGGER.error("[Lib39-Common] Failed to demonstrate examples", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The type Mod info.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -28,6 +28,8 @@ public class Lib39HelpCommand extends SimpleHelpCommand {
|
|||
/**
|
||||
* Instantiates a new Lib 39 help command.
|
||||
*
|
||||
* @param dispatcher the dispatcher
|
||||
* @param context the context
|
||||
*/
|
||||
public Lib39HelpCommand(CommandDispatcher<CommandSourceStack> dispatcher, CommandBuildContext context) {
|
||||
super(dispatcher, context);
|
||||
|
|
|
|||
|
|
@ -1,13 +1,6 @@
|
|||
package top.r3944realms.lib39.client.shader;
|
||||
|
||||
import com.mojang.blaze3d.vertex.DefaultVertexFormat;
|
||||
import net.minecraft.client.renderer.ShaderInstance;
|
||||
import net.minecraft.server.packs.resources.ResourceProvider;
|
||||
import top.r3944realms.lib39.Lib39;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
/**
|
||||
* The type Lib 39 shaders.
|
||||
|
|
@ -36,10 +29,20 @@ public class Lib39Shaders {
|
|||
return selectionShader;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets ring shader.
|
||||
*
|
||||
* @param ringShader the ring shader
|
||||
*/
|
||||
public static void setRingShader(ShaderInstance ringShader) {
|
||||
Lib39Shaders.ringShader = ringShader;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets selection shader.
|
||||
*
|
||||
* @param selectionShader the selection shader
|
||||
*/
|
||||
public static void setSelectionShader(ShaderInstance selectionShader) {
|
||||
Lib39Shaders.selectionShader = selectionShader;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -483,6 +483,7 @@ public interface ICommandHelpManager {
|
|||
/**
|
||||
* 获取命令树的字符串表示
|
||||
*
|
||||
* @param commandSourceStack the command source stack
|
||||
* @return 命令树列表 command tree
|
||||
*/
|
||||
default List<MutableComponent> getCommandTree(CommandSourceStack commandSourceStack) {
|
||||
|
|
@ -537,6 +538,7 @@ public interface ICommandHelpManager {
|
|||
/**
|
||||
* Build command tree help mutable component.
|
||||
*
|
||||
* @param commandSourceStack the command source stack
|
||||
* @return the mutable component
|
||||
*/
|
||||
default MutableComponent buildCommandTreeHelp(CommandSourceStack commandSourceStack) {
|
||||
|
|
|
|||
|
|
@ -35,9 +35,16 @@ public class CommandNode {
|
|||
// 展开/闭合状态
|
||||
private boolean expanded = true;
|
||||
|
||||
/**
|
||||
* Test permission boolean.
|
||||
*
|
||||
* @param source the source
|
||||
* @return the boolean
|
||||
*/
|
||||
public boolean testPermission(CommandSourceStack source) {
|
||||
return testPermission.test(source);
|
||||
}
|
||||
|
||||
/**
|
||||
* Instantiates a new Command node.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -14,20 +14,49 @@ import java.util.stream.Collectors;
|
|||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public abstract class CompatManager {
|
||||
/**
|
||||
* Gets id.
|
||||
*
|
||||
* @return the id
|
||||
*/
|
||||
public ResourceLocation getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
/**
|
||||
* The Logger.
|
||||
*/
|
||||
protected final Logger logger;
|
||||
/**
|
||||
* The Id.
|
||||
*/
|
||||
protected final ResourceLocation id;
|
||||
/**
|
||||
* The Compats.
|
||||
*/
|
||||
protected final Map<ResourceLocation, ICompat> compats = new HashMap<>();
|
||||
/**
|
||||
* The Initialized.
|
||||
*/
|
||||
protected boolean initialized = false;
|
||||
/**
|
||||
* The Pending tasks.
|
||||
*/
|
||||
protected final List<Runnable> pendingTasks = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* Initialize.
|
||||
*/
|
||||
public void initialize() {
|
||||
initializeAllCompat();
|
||||
onLoadComplete();
|
||||
}
|
||||
|
||||
/**
|
||||
* Instantiates a new Compat manager.
|
||||
*
|
||||
* @param id the id
|
||||
*/
|
||||
public CompatManager(@NotNull ResourceLocation id) {
|
||||
this.id = id;
|
||||
this.logger = LoggerFactory.getLogger(id.toString());
|
||||
|
|
@ -50,6 +79,12 @@ public abstract class CompatManager {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Do register compat.
|
||||
*
|
||||
* @param id the id
|
||||
* @param compat the compat
|
||||
*/
|
||||
protected void doRegisterCompat(ResourceLocation id, ICompat compat) {
|
||||
if (compats.containsKey(id)) {
|
||||
logger.warn("Compat with id {} is already registered!", id);
|
||||
|
|
|
|||
|
|
@ -8,8 +8,20 @@ import java.util.concurrent.Callable;
|
|||
* The interface Compat.
|
||||
*/
|
||||
public interface ICompat {
|
||||
/**
|
||||
* Sets initialize.
|
||||
*
|
||||
* @param initialize the initialize
|
||||
*/
|
||||
void setInitialize(boolean initialize);
|
||||
|
||||
/**
|
||||
* Is initialized boolean.
|
||||
*
|
||||
* @return the boolean
|
||||
*/
|
||||
boolean isInitialized();
|
||||
|
||||
/**
|
||||
* Id resource location.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -2,8 +2,23 @@ package top.r3944realms.lib39.core.sync;
|
|||
|
||||
import net.minecraft.nbt.Tag;
|
||||
|
||||
/**
|
||||
* The interface Inbt serializable.
|
||||
*
|
||||
* @param <T> the type parameter
|
||||
*/
|
||||
public interface INBTSerializable <T extends Tag>{
|
||||
/**
|
||||
* Serialize nbt t.
|
||||
*
|
||||
* @return the t
|
||||
*/
|
||||
T serializeNBT();
|
||||
|
||||
/**
|
||||
* Deserialize nbt.
|
||||
*
|
||||
* @param var1 the var 1
|
||||
*/
|
||||
void deserializeNBT(T var1);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,18 @@
|
|||
package top.r3944realms.lib39.core.sync;
|
||||
|
||||
/**
|
||||
* The interface Update.
|
||||
*/
|
||||
public interface IUpdate {
|
||||
/**
|
||||
* Update.
|
||||
*/
|
||||
void update();
|
||||
|
||||
/**
|
||||
* Gets sync data.
|
||||
*
|
||||
* @return the sync data
|
||||
*/
|
||||
NBTEntitySyncData getSyncData();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,6 +4,9 @@ import net.minecraft.nbt.CompoundTag;
|
|||
import net.minecraft.resources.ResourceLocation;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* The type Nbt entity sync data.
|
||||
*/
|
||||
public abstract class NBTEntitySyncData implements IEntity, ISyncData<NBTEntitySyncData>, INBTSerializable<CompoundTag>, IUpdate {
|
||||
/**
|
||||
* The Dirty.
|
||||
|
|
|
|||
|
|
@ -12,9 +12,16 @@ import java.util.function.Function;
|
|||
|
||||
/**
|
||||
* The type Sync data 2 manager.
|
||||
*
|
||||
* @param <V> the type parameter
|
||||
*/
|
||||
@SuppressWarnings({"unused", "DuplicatedCode"})
|
||||
public abstract class SyncData2Manager<V extends SyncData2Manager.TypedSyncEntry<?, ?>> {
|
||||
/**
|
||||
* Gets typed entries.
|
||||
*
|
||||
* @return the typed entries
|
||||
*/
|
||||
protected abstract Map<ResourceLocation, V> getTypedEntries();
|
||||
|
||||
/**
|
||||
|
|
@ -34,6 +41,12 @@ public abstract class SyncData2Manager<V extends SyncData2Manager.TypedSyncEntry
|
|||
Optional<T> getData(K key);
|
||||
}
|
||||
|
||||
/**
|
||||
* The type Typed sync entry.
|
||||
*
|
||||
* @param <K> the type parameter
|
||||
* @param <T> the type parameter
|
||||
*/
|
||||
protected static class TypedSyncEntry<K, T extends ISyncData<?>> {
|
||||
/**
|
||||
* The Manager.
|
||||
|
|
@ -397,7 +410,16 @@ public abstract class SyncData2Manager<V extends SyncData2Manager.TypedSyncEntry
|
|||
}
|
||||
}
|
||||
|
||||
// 辅助方法:更新条目的数据提供者
|
||||
/**
|
||||
* Update data provider in entry.
|
||||
*
|
||||
* @param <K> the type parameter
|
||||
* @param <T> the type parameter
|
||||
* @param id the id
|
||||
* @param entry the entry
|
||||
* @param newDataProvider the new data provider
|
||||
*/
|
||||
// 辅助方法:更新条目的数据提供者
|
||||
@SuppressWarnings("unchecked")
|
||||
protected <K, T extends ISyncData<?>> void updateDataProviderInEntry(
|
||||
ResourceLocation id,
|
||||
|
|
|
|||
|
|
@ -1,12 +1,6 @@
|
|||
package top.r3944realms.lib39.datagen.provider;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.TreeMap;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.function.Supplier;
|
||||
import net.minecraft.data.CachedOutput;
|
||||
import net.minecraft.data.DataProvider;
|
||||
import net.minecraft.data.PackOutput;
|
||||
|
|
@ -19,18 +13,38 @@ import net.minecraft.world.item.enchantment.Enchantment;
|
|||
import net.minecraft.world.level.block.Block;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.TreeMap;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
/**
|
||||
* The type Language provider.
|
||||
*/
|
||||
public abstract class LanguageProvider implements DataProvider {
|
||||
private final Map<String, String> data = new TreeMap<>();
|
||||
private final PackOutput output;
|
||||
private final String modid;
|
||||
private final String locale;
|
||||
|
||||
/**
|
||||
* Instantiates a new Language provider.
|
||||
*
|
||||
* @param output the output
|
||||
* @param modid the modid
|
||||
* @param locale the locale
|
||||
*/
|
||||
public LanguageProvider(PackOutput output, String modid, String locale) {
|
||||
this.output = output;
|
||||
this.modid = modid;
|
||||
this.locale = locale;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add translations.
|
||||
*/
|
||||
protected abstract void addTranslations();
|
||||
|
||||
public @NotNull CompletableFuture<?> run(@NotNull CachedOutput cache) {
|
||||
|
|
@ -49,54 +63,132 @@ public abstract class LanguageProvider implements DataProvider {
|
|||
return DataProvider.saveStable(cache, json, target);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add block.
|
||||
*
|
||||
* @param key the key
|
||||
* @param name the name
|
||||
*/
|
||||
public void addBlock(@NotNull Supplier<? extends Block> key, String name) {
|
||||
this.add(key.get(), name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add.
|
||||
*
|
||||
* @param key the key
|
||||
* @param name the name
|
||||
*/
|
||||
public void add(@NotNull Block key, String name) {
|
||||
this.add(key.getDescriptionId(), name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add item.
|
||||
*
|
||||
* @param key the key
|
||||
* @param name the name
|
||||
*/
|
||||
public void addItem(@NotNull Supplier<? extends Item> key, String name) {
|
||||
this.add(key.get(), name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add.
|
||||
*
|
||||
* @param key the key
|
||||
* @param name the name
|
||||
*/
|
||||
public void add(@NotNull Item key, String name) {
|
||||
this.add(key.getDescriptionId(), name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add item stack.
|
||||
*
|
||||
* @param key the key
|
||||
* @param name the name
|
||||
*/
|
||||
public void addItemStack(@NotNull Supplier<ItemStack> key, String name) {
|
||||
this.add(key.get(), name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add.
|
||||
*
|
||||
* @param key the key
|
||||
* @param name the name
|
||||
*/
|
||||
public void add(@NotNull ItemStack key, String name) {
|
||||
this.add(key.getDescriptionId(), name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add enchantment.
|
||||
*
|
||||
* @param key the key
|
||||
* @param name the name
|
||||
*/
|
||||
public void addEnchantment(@NotNull Supplier<? extends Enchantment> key, String name) {
|
||||
this.add(key.get(), name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add.
|
||||
*
|
||||
* @param key the key
|
||||
* @param name the name
|
||||
*/
|
||||
public void add(@NotNull Enchantment key, String name) {
|
||||
this.add(key.getDescriptionId(), name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add effect.
|
||||
*
|
||||
* @param key the key
|
||||
* @param name the name
|
||||
*/
|
||||
public void addEffect(@NotNull Supplier<? extends MobEffect> key, String name) {
|
||||
this.add(key.get(), name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add.
|
||||
*
|
||||
* @param key the key
|
||||
* @param name the name
|
||||
*/
|
||||
public void add(@NotNull MobEffect key, String name) {
|
||||
this.add(key.getDescriptionId(), name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add entity type.
|
||||
*
|
||||
* @param key the key
|
||||
* @param name the name
|
||||
*/
|
||||
public void addEntityType(@NotNull Supplier<? extends EntityType<?>> key, String name) {
|
||||
this.add(key.get(), name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add.
|
||||
*
|
||||
* @param key the key
|
||||
* @param name the name
|
||||
*/
|
||||
public void add(@NotNull EntityType<?> key, String name) {
|
||||
this.add(key.getDescriptionId(), name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add.
|
||||
*
|
||||
* @param key the key
|
||||
* @param value the value
|
||||
*/
|
||||
public void add(String key, String value) {
|
||||
if (this.data.put(key, value) != null) {
|
||||
throw new IllegalStateException("Duplicate translation key " + key);
|
||||
|
|
|
|||
|
|
@ -15,7 +15,11 @@ public class Lib39Example {
|
|||
registered = true;
|
||||
}
|
||||
}
|
||||
public void init() {
|
||||
|
||||
/**
|
||||
* Init.
|
||||
*/
|
||||
public void init() {
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -10,11 +10,27 @@ import top.r3944realms.lib39.core.sync.NBTEntitySyncData;
|
|||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public abstract class AbstractedTestSyncData extends NBTEntitySyncData {
|
||||
/**
|
||||
* The constant DEFAULT_TEST_STRING.
|
||||
*/
|
||||
public final static String DEFAULT_TEST_STRING = "default_value";
|
||||
/**
|
||||
* The constant DEFAULT_TEST_INT.
|
||||
*/
|
||||
public final static int DEFAULT_TEST_INT = 42;
|
||||
/**
|
||||
* The constant DEFAULT_TEST_BOOLEAN.
|
||||
*/
|
||||
public final static boolean DEFAULT_TEST_BOOLEAN = true;
|
||||
/**
|
||||
* The constant DEFAULT_TEST_DOUBLE.
|
||||
*/
|
||||
public final static double DEFAULT_TEST_DOUBLE = 3.14159;
|
||||
/**
|
||||
* The constant DEFAULT_TEST_DATA.
|
||||
*/
|
||||
public final static TestData DEFAULT_TEST_DATA = new TestData("default", 100, false);
|
||||
|
||||
/**
|
||||
* Instantiates a new Nbt sync data.
|
||||
*
|
||||
|
|
@ -92,6 +108,9 @@ public abstract class AbstractedTestSyncData extends NBTEntitySyncData {
|
|||
*/
|
||||
public abstract void incrementCounter();
|
||||
|
||||
/**
|
||||
* Clear counter.
|
||||
*/
|
||||
public abstract void clearCounter();
|
||||
|
||||
/**
|
||||
|
|
@ -106,7 +125,11 @@ public abstract class AbstractedTestSyncData extends NBTEntitySyncData {
|
|||
*/
|
||||
public abstract void updateSyncTime();
|
||||
|
||||
/**
|
||||
* Clear sync time.
|
||||
*/
|
||||
public abstract void clearSyncTime();
|
||||
|
||||
/**
|
||||
* Gets custom data.
|
||||
*
|
||||
|
|
@ -128,6 +151,9 @@ public abstract class AbstractedTestSyncData extends NBTEntitySyncData {
|
|||
*/
|
||||
public abstract boolean validateData();
|
||||
|
||||
/**
|
||||
* Reset to defaults.
|
||||
*/
|
||||
public void resetToDefaults() {
|
||||
setTestString(DEFAULT_TEST_STRING);
|
||||
setTestInt(DEFAULT_TEST_INT);
|
||||
|
|
@ -139,6 +165,9 @@ public abstract class AbstractedTestSyncData extends NBTEntitySyncData {
|
|||
markDirty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate random data.
|
||||
*/
|
||||
public void generateRandomData() {
|
||||
setTestString("random_" + System.currentTimeMillis());
|
||||
setTestInt((int) (Math.random() * 1000));
|
||||
|
|
@ -154,8 +183,20 @@ public abstract class AbstractedTestSyncData extends NBTEntitySyncData {
|
|||
markDirty();
|
||||
}
|
||||
|
||||
/**
|
||||
* To bytes.
|
||||
*
|
||||
* @param buf the buf
|
||||
*/
|
||||
public abstract void toBytes(FriendlyByteBuf buf);
|
||||
|
||||
/**
|
||||
* From bytes.
|
||||
*
|
||||
* @param buf the buf
|
||||
*/
|
||||
public abstract void fromBytes(@NotNull FriendlyByteBuf buf);
|
||||
|
||||
/**
|
||||
* 测试数据对象
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -151,9 +151,20 @@ public abstract class AbstractFabricItem extends Item {
|
|||
player.sendSystemMessage(Component.literal("§c请对准一个生物使用!"));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets data.
|
||||
*
|
||||
* @param target the target
|
||||
* @return the data
|
||||
*/
|
||||
protected abstract AbstractedTestSyncData getData(Entity target);
|
||||
|
||||
/**
|
||||
* 在客户端获取本地数据
|
||||
*
|
||||
* @param target the target
|
||||
* @return the local client data
|
||||
*/
|
||||
protected AbstractedTestSyncData getLocalClientData(LivingEntity target) {
|
||||
try {
|
||||
|
|
@ -166,6 +177,9 @@ public abstract class AbstractFabricItem extends Item {
|
|||
|
||||
/**
|
||||
* 发送客户端数据到服务器
|
||||
*
|
||||
* @param clientData the client data
|
||||
* @param targetEntityId the target entity id
|
||||
*/
|
||||
protected abstract void sendClientDataToServer(AbstractedTestSyncData clientData, int targetEntityId);
|
||||
|
||||
|
|
@ -299,6 +313,11 @@ public abstract class AbstractFabricItem extends Item {
|
|||
|
||||
/**
|
||||
* 显示双端比较结果
|
||||
*
|
||||
* @param player the player
|
||||
* @param target the target
|
||||
* @param serverData the server data
|
||||
* @param clientData the client data
|
||||
*/
|
||||
protected static void displayDualEndComparison(ServerPlayer player, LivingEntity target, AbstractedTestSyncData serverData, AbstractedTestSyncData clientData) {
|
||||
player.sendSystemMessage(Component.literal("§6=== 客户端-服务器双端同步检查结果 ==="));
|
||||
|
|
|
|||
|
|
@ -243,8 +243,20 @@ public abstract class AbstractNeoForgeItem extends Item {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets data.
|
||||
*
|
||||
* @param entity the entity
|
||||
* @return the data
|
||||
*/
|
||||
protected abstract AbstractedTestSyncData getData(Entity entity);
|
||||
|
||||
/**
|
||||
* Gets or create test sync data.
|
||||
*
|
||||
* @param entity the entity
|
||||
* @return the or create test sync data
|
||||
*/
|
||||
protected AbstractedTestSyncData getOrCreateTestSyncData(Entity entity) {
|
||||
try {
|
||||
return getData(entity);
|
||||
|
|
|
|||
|
|
@ -32,7 +32,10 @@ public class ForgeItem extends Item {
|
|||
return super.use(level, player, usedHand);
|
||||
}
|
||||
|
||||
static class ClientOpt implements IClientOnly {
|
||||
/**
|
||||
* The type Client opt.
|
||||
*/
|
||||
static class ClientOpt implements IClientOnly {
|
||||
private static void clientUse(@NotNull InteractionHand usedHand) {
|
||||
IClientOnly.check(() -> Minecraft.getInstance().setScreen(new ForgeScreen(usedHand, 0)));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,83 +8,166 @@ import org.spongepowered.asm.mixin.gen.Accessor;
|
|||
|
||||
import java.util.Comparator;
|
||||
|
||||
/**
|
||||
* The interface Creative mode tabs accessor.
|
||||
*/
|
||||
@Mixin(CreativeModeTabs.class)
|
||||
public interface CreativeModeTabsAccessor {
|
||||
/**
|
||||
* Gets building blocks.
|
||||
*
|
||||
* @return the building blocks
|
||||
*/
|
||||
@Accessor("BUILDING_BLOCKS")
|
||||
static ResourceKey<CreativeModeTab> getBuildingBlocks() {
|
||||
throw new AssertionError();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets colored blocks.
|
||||
*
|
||||
* @return the colored blocks
|
||||
*/
|
||||
@Accessor("COLORED_BLOCKS")
|
||||
static ResourceKey<CreativeModeTab> getColoredBlocks() {
|
||||
throw new AssertionError();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets natural blocks.
|
||||
*
|
||||
* @return the natural blocks
|
||||
*/
|
||||
@Accessor("NATURAL_BLOCKS")
|
||||
static ResourceKey<CreativeModeTab> getNaturalBlocks() {
|
||||
throw new AssertionError();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets functional blocks.
|
||||
*
|
||||
* @return the functional blocks
|
||||
*/
|
||||
@Accessor("FUNCTIONAL_BLOCKS")
|
||||
static ResourceKey<CreativeModeTab> getFunctionalBlocks() {
|
||||
throw new AssertionError();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets redstone blocks.
|
||||
*
|
||||
* @return the redstone blocks
|
||||
*/
|
||||
@Accessor("REDSTONE_BLOCKS")
|
||||
static ResourceKey<CreativeModeTab> getRedstoneBlocks() {
|
||||
throw new AssertionError();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets hotbar.
|
||||
*
|
||||
* @return the hotbar
|
||||
*/
|
||||
@Accessor("HOTBAR")
|
||||
static ResourceKey<CreativeModeTab> getHotbar() {
|
||||
throw new AssertionError();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets search.
|
||||
*
|
||||
* @return the search
|
||||
*/
|
||||
@Accessor("SEARCH")
|
||||
static ResourceKey<CreativeModeTab> getSearch() {
|
||||
throw new AssertionError();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets tools and utilities.
|
||||
*
|
||||
* @return the tools and utilities
|
||||
*/
|
||||
@Accessor("TOOLS_AND_UTILITIES")
|
||||
static ResourceKey<CreativeModeTab> getToolsAndUtilities() {
|
||||
throw new AssertionError();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets combat.
|
||||
*
|
||||
* @return the combat
|
||||
*/
|
||||
@Accessor("COMBAT")
|
||||
static ResourceKey<CreativeModeTab> getCombat() {
|
||||
throw new AssertionError();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets food and drinks.
|
||||
*
|
||||
* @return the food and drinks
|
||||
*/
|
||||
@Accessor("FOOD_AND_DRINKS")
|
||||
static ResourceKey<CreativeModeTab> getFoodAndDrinks() {
|
||||
throw new AssertionError();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets ingredients.
|
||||
*
|
||||
* @return the ingredients
|
||||
*/
|
||||
@Accessor("INGREDIENTS")
|
||||
static ResourceKey<CreativeModeTab> getIngredients() {
|
||||
throw new AssertionError();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets spawn eggs.
|
||||
*
|
||||
* @return the spawn eggs
|
||||
*/
|
||||
@Accessor("SPAWN_EGGS")
|
||||
static ResourceKey<CreativeModeTab> getSpawnEggs() {
|
||||
throw new AssertionError();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets op blocks.
|
||||
*
|
||||
* @return the op blocks
|
||||
*/
|
||||
@Accessor("OP_BLOCKS")
|
||||
static ResourceKey<CreativeModeTab> getOpBlocks() {
|
||||
throw new AssertionError();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets inventory.
|
||||
*
|
||||
* @return the inventory
|
||||
*/
|
||||
@Accessor("INVENTORY")
|
||||
static ResourceKey<CreativeModeTab> getInventory() {
|
||||
throw new AssertionError();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets cached parameters.
|
||||
*
|
||||
* @return the cached parameters
|
||||
*/
|
||||
@Accessor("CACHED_PARAMETERS")
|
||||
static CreativeModeTab.ItemDisplayParameters getCachedParameters() {
|
||||
throw new AssertionError();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets painting comparator.
|
||||
*
|
||||
* @return the painting comparator
|
||||
*/
|
||||
@Accessor("PAINTING_COMPARATOR")
|
||||
static Comparator<net.minecraft.world.item.CreativeModeTab> getPaintingComparator() {
|
||||
throw new AssertionError();
|
||||
|
|
|
|||
|
|
@ -7,8 +7,16 @@ import org.spongepowered.asm.mixin.gen.Accessor;
|
|||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* The interface Screen accessor.
|
||||
*/
|
||||
@Mixin(Screen.class)
|
||||
public interface ScreenAccessor {
|
||||
/**
|
||||
* Gets renderables.
|
||||
*
|
||||
* @return the renderables
|
||||
*/
|
||||
@Accessor("renderables")
|
||||
List<Renderable> getrRenderables();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,17 +5,30 @@ import top.r3944realms.lib39.platform.services.IPlatformHelper;
|
|||
|
||||
import java.util.ServiceLoader;
|
||||
|
||||
/**
|
||||
* The type Services.
|
||||
*/
|
||||
// Service loaders are a built-in Java feature that allow us to locate implementations of an interface that vary from one
|
||||
// environment to another. In the context of MultiLoader we use this feature to access a mock API in the common code that
|
||||
// is swapped out for the platform specific implementation at runtime.
|
||||
public class Services {
|
||||
|
||||
// In this example we provide a platform helper which provides information about what platform the mod is running on.
|
||||
/**
|
||||
* The constant PLATFORM.
|
||||
*/
|
||||
// In this example we provide a platform helper which provides information about what platform the mod is running on.
|
||||
// For example this can be used to check if the code is running on Forge vs Fabric, or to ask the modloader if another
|
||||
// mod is loaded.
|
||||
public static final IPlatformHelper PLATFORM = load(IPlatformHelper.class);
|
||||
|
||||
// This code is used to load a service for the current environment. Your implementation of the service must be defined
|
||||
/**
|
||||
* Load t.
|
||||
*
|
||||
* @param <T> the type parameter
|
||||
* @param clazz the clazz
|
||||
* @return the t
|
||||
*/
|
||||
// This code is used to load a service for the current environment. Your implementation of the service must be defined
|
||||
// manually by including a text file in META-INF/services named with the fully qualified class name of the service.
|
||||
// Inside the file you should write the fully qualified class name of the implementation to load for the platform. For
|
||||
// example our file on Forge points to ForgePlatformHelper while Fabric points to FabricPlatformHelper.
|
||||
|
|
|
|||
|
|
@ -5,7 +5,17 @@ import net.minecraft.commands.CommandBuildContext;
|
|||
import net.minecraft.commands.CommandSourceStack;
|
||||
import top.r3944realms.lib39.core.command.ICommandHelpManager;
|
||||
|
||||
/**
|
||||
* The interface Help command hook.
|
||||
*/
|
||||
@FunctionalInterface
|
||||
public interface IHelpCommandHook {
|
||||
/**
|
||||
* On register.
|
||||
*
|
||||
* @param tree the tree
|
||||
* @param manager the manager
|
||||
* @param context the context
|
||||
*/
|
||||
void onRegister(LiteralArgumentBuilder<CommandSourceStack> tree, ICommandHelpManager manager, CommandBuildContext context);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,6 +36,11 @@ public interface IPlatformHelper {
|
|||
return isDevelopmentEnvironment() ? "development" : "production";
|
||||
}
|
||||
|
||||
/**
|
||||
* Is client environment boolean.
|
||||
*
|
||||
* @return the boolean
|
||||
*/
|
||||
boolean isClientEnvironment();
|
||||
|
||||
|
||||
|
|
@ -46,7 +51,17 @@ public interface IPlatformHelper {
|
|||
*/
|
||||
String getModVersion();
|
||||
|
||||
/**
|
||||
* Gets util helper.
|
||||
*
|
||||
* @return the util helper
|
||||
*/
|
||||
IUtilHelper getUtilHelper();
|
||||
|
||||
/**
|
||||
* Gets help command hook.
|
||||
*
|
||||
* @return the help command hook
|
||||
*/
|
||||
IHelpCommandHook getHelpCommandHook();
|
||||
}
|
||||
|
|
@ -2,6 +2,14 @@ package top.r3944realms.lib39.platform.services;
|
|||
|
||||
import top.r3944realms.lib39.util.block.BlockRegistryBuilder;
|
||||
|
||||
/**
|
||||
* The interface Util helper.
|
||||
*/
|
||||
public interface IUtilHelper {
|
||||
/**
|
||||
* Gets block registry builder.
|
||||
*
|
||||
* @return the block registry builder
|
||||
*/
|
||||
BlockRegistryBuilder getBlockRegistryBuilder();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,12 +32,24 @@ public class GameProfileHelper {
|
|||
* Client Only Class
|
||||
*/
|
||||
public static class ClientOpt implements IClientOnly {
|
||||
/**
|
||||
* Resolve skin texture resource location.
|
||||
*
|
||||
* @param gameProfile the game profile
|
||||
* @return the resource location
|
||||
*/
|
||||
public static @NotNull ResourceLocation resolveSkinTexture(@NotNull GameProfile gameProfile) {
|
||||
return IClientOnly.check(() ->
|
||||
Minecraft.getInstance().getSkinManager()
|
||||
.getInsecureSkinLocation(gameProfile));
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets skin texture.
|
||||
*
|
||||
* @param gameProfile the game profile
|
||||
* @return the skin texture
|
||||
*/
|
||||
public static ResourceLocation getSkinTexture(@Nullable GameProfile gameProfile) {
|
||||
return IClientOnly.check(() -> {
|
||||
if (gameProfile == null) {
|
||||
|
|
@ -47,6 +59,12 @@ public class GameProfileHelper {
|
|||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Has slim arms client boolean.
|
||||
*
|
||||
* @param player the player
|
||||
* @return the boolean
|
||||
*/
|
||||
public static boolean hasSlimArmsClient(Player player) {
|
||||
return IClientOnly.check(() -> {
|
||||
if (player instanceof AbstractClientPlayer clientPlayer) {
|
||||
|
|
@ -59,6 +77,12 @@ public class GameProfileHelper {
|
|||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets skin model name.
|
||||
*
|
||||
* @param player the player
|
||||
* @return the skin model name
|
||||
*/
|
||||
public static @NotNull String getSkinModelName(@NotNull Player player) {
|
||||
return IClientOnly.check(() -> {
|
||||
if (player.level().isClientSide && player instanceof AbstractClientPlayer) {
|
||||
|
|
@ -71,6 +95,7 @@ public class GameProfileHelper {
|
|||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* The constant TAG_BE.
|
||||
*/
|
||||
|
|
@ -80,11 +105,23 @@ public class GameProfileHelper {
|
|||
*/
|
||||
public static final String TAG_OWN_PROFILE = "OwnerProfile";
|
||||
|
||||
/**
|
||||
* Gets skin texture.
|
||||
*
|
||||
* @param gameProfile the game profile
|
||||
* @return the skin texture
|
||||
*/
|
||||
public static ResourceLocation getSkinTexture(@Nullable GameProfile gameProfile) {
|
||||
return ClientOpt.getSkinTexture(gameProfile);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Resolve skin texture resource location.
|
||||
*
|
||||
* @param gameProfile the game profile
|
||||
* @return the resource location
|
||||
*/
|
||||
public static @NotNull ResourceLocation resolveSkinTexture(@NotNull GameProfile gameProfile) {
|
||||
return ClientOpt.resolveSkinTexture(gameProfile);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,7 +4,15 @@ import top.r3944realms.lib39.Lib39;
|
|||
|
||||
import java.util.function.Supplier;
|
||||
|
||||
/**
|
||||
* The interface Client only.
|
||||
*/
|
||||
public interface IClientOnly {
|
||||
/**
|
||||
* Check.
|
||||
*
|
||||
* @param runnable the runnable
|
||||
*/
|
||||
static void check(Runnable runnable) {
|
||||
if (Lib39.isClientEnvironment()) {
|
||||
runnable.run();
|
||||
|
|
@ -13,6 +21,12 @@ public interface IClientOnly {
|
|||
throw new RuntimeException("This method should be called in ClientEnvironment");
|
||||
}
|
||||
|
||||
/**
|
||||
* Check.
|
||||
*
|
||||
* @param runnable the runnable
|
||||
* @param fallback the fallback
|
||||
*/
|
||||
static void check(Runnable runnable, Runnable fallback) {
|
||||
if (Lib39.isClientEnvironment()) {
|
||||
runnable.run();
|
||||
|
|
@ -20,6 +34,14 @@ public interface IClientOnly {
|
|||
}
|
||||
fallback.run();
|
||||
}
|
||||
|
||||
/**
|
||||
* Check t.
|
||||
*
|
||||
* @param <T> the type parameter
|
||||
* @param supplier the supplier
|
||||
* @return the t
|
||||
*/
|
||||
static <T> T check(Supplier<T> supplier) {
|
||||
if (Lib39.isClientEnvironment()) {
|
||||
return supplier.get();
|
||||
|
|
@ -27,6 +49,14 @@ public interface IClientOnly {
|
|||
throw new RuntimeException("This method should be called in ClientEnvironment");
|
||||
}
|
||||
|
||||
/**
|
||||
* Check t.
|
||||
*
|
||||
* @param <T> the type parameter
|
||||
* @param supplier the supplier
|
||||
* @param fallback the fallback
|
||||
* @return the t
|
||||
*/
|
||||
static <T> T check(Supplier<T> supplier, Supplier<T> fallback) {
|
||||
if (Lib39.isClientEnvironment()) {
|
||||
return supplier.get();
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ import java.util.concurrent.TimeUnit;
|
|||
* <p><b>重要:</b>由于使用了 weakValues(),实现类必须被其他对象强引用,
|
||||
* 否则会被 GC 清理导致锁自动释放。通常这意味着将实现类实例存储在
|
||||
* 适当的管理器或容器中。
|
||||
*
|
||||
* @author sch246
|
||||
*/
|
||||
public interface IUniPosOwner {
|
||||
|
|
@ -67,8 +68,7 @@ public interface IUniPosOwner {
|
|||
*
|
||||
* @param level 维度 The level (dimension) of the position.
|
||||
* @param pos 坐标 The position to lock.
|
||||
* @return true if ownership was successfully claimed or was already held by this object,
|
||||
* false if the position is owned by another object.
|
||||
* @return true if ownership was successfully claimed or was already held by this object, false if the position is owned by another object.
|
||||
*/
|
||||
default boolean tryLock(Level level, BlockPos pos) {
|
||||
return UniPosManager.INSTANCE.tryLock(level, pos, this);
|
||||
|
|
@ -88,6 +88,7 @@ public interface IUniPosOwner {
|
|||
|
||||
/**
|
||||
* 续租,继续持有锁
|
||||
*
|
||||
* @param level 维度
|
||||
* @param pos 位置
|
||||
*/
|
||||
|
|
@ -97,16 +98,19 @@ public interface IUniPosOwner {
|
|||
}
|
||||
|
||||
/**
|
||||
管理 IUniPosOwner 系统的单例存储。
|
||||
该类是后台实现,大多数类不应直接使用。
|
||||
在同一维度键(ResourceKey<Level)范围内,确保任意时刻一个 BlockPos 只能被一个对象“拥有”。
|
||||
注意:锁的作用域是维度键级别,因此在服务端同一维度的不同 Level 实例之间共享。
|
||||
缓存以 BlockPos 的 long 值为键,以 IUniPosOwner 的弱值(weak values)为值;
|
||||
当所有者不再被强引用时,条目会自动移除,从而释放锁。
|
||||
该实现面向服务端使用。
|
||||
* 管理 IUniPosOwner 系统的单例存储。
|
||||
* 该类是后台实现,大多数类不应直接使用。
|
||||
* 在同一维度键(ResourceKey<Level)范围内,确保任意时刻一个 BlockPos 只能被一个对象“拥有”。
|
||||
* 注意:锁的作用域是维度键级别,因此在服务端同一维度的不同 Level 实例之间共享。
|
||||
* 缓存以 BlockPos 的 long 值为键,以 IUniPosOwner 的弱值(weak values)为值;
|
||||
* 当所有者不再被强引用时,条目会自动移除,从而释放锁。
|
||||
* 该实现面向服务端使用。
|
||||
*/
|
||||
final class UniPosManager {
|
||||
|
||||
/**
|
||||
* The constant INSTANCE.
|
||||
*/
|
||||
public static final UniPosManager INSTANCE = new UniPosManager();
|
||||
|
||||
// 顶层映射:维度键(ResourceKey<Level>) -> 每维度的坐标缓存。
|
||||
|
|
@ -139,7 +143,7 @@ final class UniPosManager {
|
|||
*
|
||||
* @param level 维度
|
||||
* @param pos 坐标
|
||||
* @return 如果存在所有者,则返回所有者对象;否则返回 null。
|
||||
* @return 如果存在所有者 ,则返回所有者对象;否则返回 null。
|
||||
*/
|
||||
@Nullable
|
||||
public IUniPosOwner getOwner(Level level, BlockPos pos) {
|
||||
|
|
@ -182,6 +186,7 @@ final class UniPosManager {
|
|||
|
||||
/**
|
||||
* 续租,继续持有锁
|
||||
*
|
||||
* @param level 维度
|
||||
* @param pos 位置
|
||||
* @param owner 对象
|
||||
|
|
|
|||
|
|
@ -23,9 +23,15 @@ public abstract class BlockRegistryBuilder {
|
|||
private boolean needBuildItem;
|
||||
private Item.Properties properties;
|
||||
|
||||
/**
|
||||
* Create block registry builder.
|
||||
*
|
||||
* @return the block registry builder
|
||||
*/
|
||||
public static BlockRegistryBuilder create() {
|
||||
return Services.PLATFORM.getUtilHelper().getBlockRegistryBuilder();
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置注册名称
|
||||
*
|
||||
|
|
@ -88,6 +94,9 @@ public abstract class BlockRegistryBuilder {
|
|||
|
||||
/**
|
||||
* 内部方法:注册对应的方块物品
|
||||
*
|
||||
* @param blockObject the block object
|
||||
* @param creativeTabs the creative tabs
|
||||
*/
|
||||
protected abstract void registerBlockItem(Supplier<Block> blockObject, ResourceKey<CreativeModeTab>... creativeTabs);
|
||||
|
||||
|
|
|
|||
|
|
@ -28,8 +28,8 @@ import net.minecraft.world.level.saveddata.maps.MapDecoration;
|
|||
import net.minecraft.world.level.saveddata.maps.MapItemSavedData;
|
||||
import org.jetbrains.annotations.Contract;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,10 @@ package top.r3944realms.lib39;
|
|||
|
||||
import net.fabricmc.api.ModInitializer;
|
||||
import top.r3944realms.lib39.core.event.FabricCommonEventHandler;
|
||||
import top.r3944realms.lib39.core.register.*;
|
||||
import top.r3944realms.lib39.core.register.FabricLib39BlockEntities;
|
||||
import top.r3944realms.lib39.core.register.FabricLib39Blocks;
|
||||
import top.r3944realms.lib39.core.register.FabricLib39Items;
|
||||
import top.r3944realms.lib39.core.register.FabricLib39SoundEvents;
|
||||
import top.r3944realms.lib39.example.FabricLib39Example;
|
||||
|
||||
public class Lib39Fabric implements ModInitializer {
|
||||
|
|
|
|||
|
|
@ -2,13 +2,11 @@ package top.r3944realms.lib39.core.event;
|
|||
|
||||
import com.mojang.authlib.GameProfile;
|
||||
import net.fabricmc.fabric.api.command.v2.CommandRegistrationCallback;
|
||||
import net.fabricmc.fabric.api.event.lifecycle.v1.CommonLifecycleEvents;
|
||||
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerEntityEvents;
|
||||
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerTickEvents;
|
||||
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerWorldEvents;
|
||||
import net.fabricmc.fabric.api.itemgroup.v1.ItemGroupEvents;
|
||||
import net.fabricmc.fabric.api.lookup.v1.entity.EntityApiLookup;
|
||||
import net.fabricmc.loader.impl.launch.FabricLauncher;
|
||||
import net.minecraft.Util;
|
||||
import net.minecraft.client.multiplayer.ClientLevel;
|
||||
import net.minecraft.network.chat.Component;
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@ package top.r3944realms.lib39.core.register;
|
|||
|
||||
import net.minecraft.core.Registry;
|
||||
import net.minecraft.core.registries.BuiltInRegistries;
|
||||
import net.minecraft.core.registries.Registries;
|
||||
import net.minecraft.world.level.block.entity.BlockEntityType;
|
||||
import org.jetbrains.annotations.Contract;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@ package top.r3944realms.lib39.core.register;
|
|||
import net.minecraft.core.Registry;
|
||||
import net.minecraft.core.registries.BuiltInRegistries;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.entity.BlockEntityType;
|
||||
import org.jetbrains.annotations.Contract;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import top.r3944realms.lib39.Lib39;
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@ package top.r3944realms.lib39.core.register;
|
|||
import net.minecraft.core.Registry;
|
||||
import net.minecraft.core.registries.BuiltInRegistries;
|
||||
import net.minecraft.world.item.Item;
|
||||
import net.minecraft.world.level.block.entity.BlockEntityType;
|
||||
import org.jetbrains.annotations.Contract;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import top.r3944realms.lib39.Lib39;
|
||||
|
|
|
|||
|
|
@ -2,9 +2,7 @@ package top.r3944realms.lib39.core.register;
|
|||
|
||||
import net.minecraft.core.Registry;
|
||||
import net.minecraft.core.registries.BuiltInRegistries;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.sounds.SoundEvent;
|
||||
import net.minecraft.sounds.SoundEvents;
|
||||
import org.jetbrains.annotations.Contract;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import top.r3944realms.lib39.Lib39;
|
||||
|
|
|
|||
|
|
@ -6,7 +6,9 @@ import net.minecraft.resources.ResourceLocation;
|
|||
import net.minecraft.world.entity.Entity;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
|
||||
public class SyncData2LookupManager extends SyncData2Manager<SyncData2LookupManager.TypedSyncEntry<? extends ISyncData<?>>> {
|
||||
protected final Map<ResourceLocation, TypedSyncEntry<?>> typedEntries = Maps.newConcurrentMap();
|
||||
|
|
|
|||
|
|
@ -2,24 +2,17 @@ package top.r3944realms.lib39.example.content.item;
|
|||
|
||||
import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking;
|
||||
import net.fabricmc.fabric.api.lookup.v1.entity.EntityApiLookup;
|
||||
import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking;
|
||||
import net.fabricmc.fabric.impl.screenhandler.client.ClientNetworking;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.server.players.PlayerList;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.entity.LivingEntity;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import top.r3944realms.lib39.Lib39;
|
||||
import top.r3944realms.lib39.core.event.FabricCommonEventHandler;
|
||||
import top.r3944realms.lib39.example.content.data.AbstractedTestSyncData;
|
||||
import top.r3944realms.lib39.example.content.data.FabricTestSyncData;
|
||||
import top.r3944realms.lib39.example.core.network.FabricClientDataPacket;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class FabricFabricItem extends AbstractFabricItem {
|
||||
|
||||
public FabricFabricItem(Properties properties) {
|
||||
|
|
|
|||
|
|
@ -3,8 +3,8 @@ package top.r3944realms.lib39.example.core.register;
|
|||
import net.minecraft.world.item.Item;
|
||||
import top.r3944realms.lib39.core.register.FabricLib39Items;
|
||||
import top.r3944realms.lib39.example.content.item.FabricFabricItem;
|
||||
import top.r3944realms.lib39.example.content.item.ForgeItem;
|
||||
import top.r3944realms.lib39.example.content.item.FabricNeoForgeItem;
|
||||
import top.r3944realms.lib39.example.content.item.ForgeItem;
|
||||
|
||||
/**
|
||||
* The type Ex lib 39 items.
|
||||
|
|
|
|||
|
|
@ -9,7 +9,9 @@ import org.spongepowered.asm.mixin.Mixin;
|
|||
import org.spongepowered.asm.mixin.Shadow;
|
||||
import org.spongepowered.asm.mixin.Unique;
|
||||
import top.r3944realms.lib39.core.event.FabricCommonEventHandler;
|
||||
import top.r3944realms.lib39.core.sync.*;
|
||||
import top.r3944realms.lib39.core.sync.ILib39SyncDataHolder;
|
||||
import top.r3944realms.lib39.core.sync.ISyncData;
|
||||
import top.r3944realms.lib39.core.sync.NBTEntitySyncData;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,12 +1,12 @@
|
|||
package top.r3944realms.lib39.platform;
|
||||
|
||||
import net.fabricmc.api.EnvType;
|
||||
import net.fabricmc.loader.api.FabricLoader;
|
||||
import net.fabricmc.loader.api.ModContainer;
|
||||
import net.fabricmc.loader.api.metadata.ModMetadata;
|
||||
import top.r3944realms.lib39.Lib39;
|
||||
import top.r3944realms.lib39.platform.services.IHelpCommandHook;
|
||||
import top.r3944realms.lib39.platform.services.IPlatformHelper;
|
||||
import net.fabricmc.loader.api.FabricLoader;
|
||||
import top.r3944realms.lib39.platform.services.IUtilHelper;
|
||||
|
||||
import java.util.Objects;
|
||||
|
|
|
|||
|
|
@ -8,7 +8,10 @@ import net.minecraftforge.fml.common.Mod;
|
|||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@ import net.minecraft.world.level.block.entity.BlockEntityType;
|
|||
import net.minecraftforge.eventbus.api.IEventBus;
|
||||
import net.minecraftforge.registries.DeferredRegister;
|
||||
import net.minecraftforge.registries.ForgeRegistries;
|
||||
import net.minecraftforge.registries.RegistryObject;
|
||||
import top.r3944realms.lib39.Lib39;
|
||||
import top.r3944realms.lib39.content.block.blockentity.DollBlockEntity;
|
||||
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@ import net.minecraft.world.level.block.Block;
|
|||
import net.minecraftforge.eventbus.api.IEventBus;
|
||||
import net.minecraftforge.registries.DeferredRegister;
|
||||
import net.minecraftforge.registries.ForgeRegistries;
|
||||
import net.minecraftforge.registries.RegistryObject;
|
||||
import top.r3944realms.lib39.Lib39;
|
||||
import top.r3944realms.lib39.content.block.DollBlock;
|
||||
import top.r3944realms.lib39.util.block.BlockRegistryBuilder;
|
||||
|
|
|
|||
|
|
@ -4,9 +4,7 @@ import net.minecraft.world.item.Item;
|
|||
import net.minecraftforge.eventbus.api.IEventBus;
|
||||
import net.minecraftforge.registries.DeferredRegister;
|
||||
import net.minecraftforge.registries.ForgeRegistries;
|
||||
import net.minecraftforge.registries.RegistryObject;
|
||||
import top.r3944realms.lib39.Lib39;
|
||||
import top.r3944realms.lib39.content.item.DollItem;
|
||||
import top.r3944realms.lib39.content.item.ForgeDollItem;
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -1,11 +1,9 @@
|
|||
package top.r3944realms.lib39.core.register;
|
||||
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.sounds.SoundEvent;
|
||||
import net.minecraftforge.eventbus.api.IEventBus;
|
||||
import net.minecraftforge.registries.DeferredRegister;
|
||||
import net.minecraftforge.registries.ForgeRegistries;
|
||||
import net.minecraftforge.registries.RegistryObject;
|
||||
import top.r3944realms.lib39.Lib39;
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -5,7 +5,9 @@ import net.minecraft.resources.ResourceLocation;
|
|||
import net.minecraftforge.common.capabilities.Capability;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* The type Sync data 2 manager.
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@ package top.r3944realms.lib39.example.compat;
|
|||
|
||||
import net.minecraftforge.eventbus.api.IEventBus;
|
||||
import top.r3944realms.lib39.Lib39;
|
||||
import top.r3944realms.lib39.core.compat.CompatManager;
|
||||
import top.r3944realms.lib39.core.compat.ForgeCompatManager;
|
||||
|
||||
public class Lib39CompatManager extends ForgeCompatManager {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
package top.r3944realms.lib39.example.core.network;
|
||||
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraftforge.network.NetworkRegistry;
|
||||
import net.minecraftforge.network.simple.SimpleChannel;
|
||||
import top.r3944realms.lib39.Lib39;
|
||||
|
|
|
|||
|
|
@ -1,2 +0,0 @@
|
|||
// 1.20.1 2026-01-16T18:15:18.0777323 Languages: zh_tw
|
||||
bd0f71ef9ae49f69627d3122efa3b426a89ecbdf assets/lib39/lang/zh_tw.json
|
||||
|
|
@ -1,2 +0,0 @@
|
|||
// 1.20.1 2026-01-16T18:15:18.0777323 Languages: zh_cn
|
||||
5d897b4cc975c19532c77ec60fd1eb487820a69d assets/lib39/lang/zh_cn.json
|
||||
|
|
@ -1,5 +0,0 @@
|
|||
// 1.20.1 2026-01-02T15:14:31.7762095 Item Models: lib39
|
||||
663f22009a9420c3eeae3c829fc9f37d16f0901b assets/lib39/models/item/doll.json
|
||||
14f581c8f8e7f0de004c57a180f371e60e7b12ae assets/lib39/models/item/fabric.json
|
||||
70583055336790fc837836ea6b49d16cfc8b64b8 assets/lib39/models/item/forge.json
|
||||
447b36747d0aa8748dcd86715f4cce2cff19aca7 assets/lib39/models/item/neoforge.json
|
||||
|
|
@ -1,2 +0,0 @@
|
|||
// 1.20.1 2026-01-02T15:29:13.3418663 Block States: lib39
|
||||
af9aae34357e6c630ed5037a6993ff211eba37ee assets/lib39/blockstates/doll.json
|
||||
|
|
@ -1,2 +0,0 @@
|
|||
// 1.20.1 2026-01-02T15:11:02.2242532 Loot Tables
|
||||
ac8ee9efcf316b2181fb0b56946ff6805b40c6f0 data/lib39/loot_tables/blocks/doll.json
|
||||
|
|
@ -1,2 +0,0 @@
|
|||
// 1.20.1 2026-01-02T20:50:48.567559 Sound Definitions
|
||||
474de39bdc277c91961609c6bddec279a755c846 assets/lib39/sounds.json
|
||||
|
|
@ -1,2 +0,0 @@
|
|||
// 1.20.1 2026-01-16T18:15:18.0777323 Languages: lzh
|
||||
4116ca2d84d4244b49a9ff8190c2faf0f2e57dc4 assets/lib39/lang/lzh.json
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
// 1.20.1 2026-01-02T20:34:46.0679751 Recipes
|
||||
d65b7847071b919cdda2351bee53d2693de856c8 data/lib39/advancements/recipes/misc/doll.json
|
||||
fbb6d29d5bfc1a2cef3888165671ac5e12ecc40f data/lib39/recipes/doll.json
|
||||
|
|
@ -1 +0,0 @@
|
|||
// 1.20.1 2026-01-02T15:11:02.2272522 Block Models: lib39
|
||||
|
|
@ -1,2 +0,0 @@
|
|||
// 1.20.1 2026-01-16T18:15:18.0777323 Languages: en_us
|
||||
c2a9985bbad60c04fbd5e085bd25bfd00aa8a529 assets/lib39/lang/en_us.json
|
||||
|
|
@ -1,64 +0,0 @@
|
|||
{
|
||||
"variants": {
|
||||
"facing=east,pose=default,waterlogged=false": {
|
||||
"model": "lib39:block/base_doll",
|
||||
"y": 90
|
||||
},
|
||||
"facing=east,pose=default,waterlogged=true": {
|
||||
"model": "lib39:block/base_doll",
|
||||
"y": 90
|
||||
},
|
||||
"facing=east,pose=further,waterlogged=false": {
|
||||
"model": "lib39:block/base_doll",
|
||||
"y": 90
|
||||
},
|
||||
"facing=east,pose=further,waterlogged=true": {
|
||||
"model": "lib39:block/base_doll",
|
||||
"y": 90
|
||||
},
|
||||
"facing=north,pose=default,waterlogged=false": {
|
||||
"model": "lib39:block/base_doll"
|
||||
},
|
||||
"facing=north,pose=default,waterlogged=true": {
|
||||
"model": "lib39:block/base_doll"
|
||||
},
|
||||
"facing=north,pose=further,waterlogged=false": {
|
||||
"model": "lib39:block/base_doll"
|
||||
},
|
||||
"facing=north,pose=further,waterlogged=true": {
|
||||
"model": "lib39:block/base_doll"
|
||||
},
|
||||
"facing=south,pose=default,waterlogged=false": {
|
||||
"model": "lib39:block/base_doll",
|
||||
"y": 180
|
||||
},
|
||||
"facing=south,pose=default,waterlogged=true": {
|
||||
"model": "lib39:block/base_doll",
|
||||
"y": 180
|
||||
},
|
||||
"facing=south,pose=further,waterlogged=false": {
|
||||
"model": "lib39:block/base_doll",
|
||||
"y": 180
|
||||
},
|
||||
"facing=south,pose=further,waterlogged=true": {
|
||||
"model": "lib39:block/base_doll",
|
||||
"y": 180
|
||||
},
|
||||
"facing=west,pose=default,waterlogged=false": {
|
||||
"model": "lib39:block/base_doll",
|
||||
"y": 270
|
||||
},
|
||||
"facing=west,pose=default,waterlogged=true": {
|
||||
"model": "lib39:block/base_doll",
|
||||
"y": 270
|
||||
},
|
||||
"facing=west,pose=further,waterlogged=false": {
|
||||
"model": "lib39:block/base_doll",
|
||||
"y": 270
|
||||
},
|
||||
"facing=west,pose=further,waterlogged=true": {
|
||||
"model": "lib39:block/base_doll",
|
||||
"y": 270
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,60 +0,0 @@
|
|||
{
|
||||
"block.lib39.doll": "Doll",
|
||||
"commands.lib39.calculate": "Calculate sum of two numbers",
|
||||
"commands.lib39.calculate.result": "%d + %d = %d",
|
||||
"commands.lib39.config": "Show configuration",
|
||||
"commands.lib39.debug": "Debug information",
|
||||
"commands.lib39.demo": "Demo command",
|
||||
"commands.lib39.demo.message": "This is a demo command showing Lib39 features!",
|
||||
"commands.lib39.game": "Game control",
|
||||
"commands.lib39.game.pause": "Pause current game",
|
||||
"commands.lib39.game.pause.success": "Game paused!",
|
||||
"commands.lib39.game.resume": "Resume paused game",
|
||||
"commands.lib39.game.resume.success": "Game resumed!",
|
||||
"commands.lib39.game.start": "Start a game",
|
||||
"commands.lib39.game.start.success": "Game '%s' started!",
|
||||
"commands.lib39.game.stop": "Stop current game",
|
||||
"commands.lib39.game.stop.success": "Game stopped!",
|
||||
"commands.lib39.greet.basic": "Greet everyone",
|
||||
"commands.lib39.greet.default": "Hello everyone from Lib39!",
|
||||
"commands.lib39.greet.player": "Greet specific player",
|
||||
"commands.lib39.greet.received": "%s greeted you!",
|
||||
"commands.lib39.help.basic.help": "Show Help Info",
|
||||
"commands.lib39.help.click_expand": "Click to expand",
|
||||
"commands.lib39.help.command_not_found": "Command not found: %s",
|
||||
"commands.lib39.help.header": "===== %s =====",
|
||||
"commands.lib39.help.hover.copy": "Copy to clipboard",
|
||||
"commands.lib39.help.no_entries": "No help entries available",
|
||||
"commands.lib39.help.node.expand": "%d subcommands collapsed",
|
||||
"commands.lib39.help.node.toggle.collapse": "Collapse",
|
||||
"commands.lib39.help.node.toggle.expand": "Expand",
|
||||
"commands.lib39.help.page_info": "Page %d of %d",
|
||||
"commands.lib39.help.subcommands_title": "Subcommands:",
|
||||
"commands.lib39.help.toggle_failed": "Toggle Failed: No Hash Cached",
|
||||
"commands.lib39.info": "Show player information",
|
||||
"commands.lib39.info.dimension": "Dimension: %s",
|
||||
"commands.lib39.info.message": "=== Player Information ===",
|
||||
"commands.lib39.info.position": "Position: X=%.1f, Y=%.1f, Z=%.1f",
|
||||
"commands.lib39.reload": "Reload configuration",
|
||||
"commands.lib39.root": "Lib39 Command System",
|
||||
"commands.lib39.settings": "Show settings",
|
||||
"commands.lib39.team": "Team management",
|
||||
"commands.lib39.team.create": "Create a new team",
|
||||
"commands.lib39.team.create.success": "Team '%s' created successfully!",
|
||||
"commands.lib39.team.join": "Join a team",
|
||||
"commands.lib39.team.join.success": "Joined team '%s'",
|
||||
"commands.lib39.team.leave": "Leave current team",
|
||||
"commands.lib39.team.leave.success": "Left the team",
|
||||
"commands.lib39.teleport": "Teleport to player (OP only)",
|
||||
"commands.lib39.teleport.success": "Teleported to %s",
|
||||
"commands.lib39.test": "Test command",
|
||||
"commands.lib39.test.success": "Test command executed successfully!",
|
||||
"commands.lib39.test.with_param": "Test command with parameter: %s",
|
||||
"invalid.player_name.too_long": "§c§lPlayer 's Name is too long than 16 characters.",
|
||||
"item.lib39.fabric": "Fabric",
|
||||
"item.lib39.forge": "Forge",
|
||||
"item.lib39.neoforge": "NeoForge",
|
||||
"sound.lib39.subtitle.duck_toy": "Duck Doll Sound",
|
||||
"tooltip.lib39.content.doll.hover.1": "§eSkinOwner §7:§a %s ",
|
||||
"tooltip.lib39.content.doll.hover.2": "§7Rename with a player name in an anvil to change skin"
|
||||
}
|
||||
|
|
@ -1,60 +0,0 @@
|
|||
{
|
||||
"block.lib39.doll": "偶",
|
||||
"commands.lib39.calculate": "算二數和",
|
||||
"commands.lib39.calculate.result": "%d 加 %d 等 %d",
|
||||
"commands.lib39.config": "示配",
|
||||
"commands.lib39.debug": "調訊",
|
||||
"commands.lib39.demo": "演令",
|
||||
"commands.lib39.demo.message": "此乃展 Lib39 能之演令!",
|
||||
"commands.lib39.game": "戲控",
|
||||
"commands.lib39.game.pause": "暫現戲",
|
||||
"commands.lib39.game.pause.success": "戲已暫!",
|
||||
"commands.lib39.game.resume": "復暫戲",
|
||||
"commands.lib39.game.resume.success": "戲已復!",
|
||||
"commands.lib39.game.start": "啟戲",
|
||||
"commands.lib39.game.start.success": "戲 '%s' 已啟!",
|
||||
"commands.lib39.game.stop": "止現戲",
|
||||
"commands.lib39.game.stop.success": "戲已止!",
|
||||
"commands.lib39.greet.basic": "問眾安",
|
||||
"commands.lib39.greet.default": "自 Lib39 問安!",
|
||||
"commands.lib39.greet.player": "問特者安",
|
||||
"commands.lib39.greet.received": "%s 問汝安!",
|
||||
"commands.lib39.help.basic.help": "示助之訊",
|
||||
"commands.lib39.help.click_expand": "點展",
|
||||
"commands.lib39.help.command_not_found": "令未見之: %s",
|
||||
"commands.lib39.help.header": "〇〇 %s 〇〇",
|
||||
"commands.lib39.help.hover.copy": "點之複刻",
|
||||
"commands.lib39.help.no_entries": "尚無助之目錄",
|
||||
"commands.lib39.help.node.expand": "%d 子令已收",
|
||||
"commands.lib39.help.node.toggle.collapse": "收",
|
||||
"commands.lib39.help.node.toggle.expand": "展",
|
||||
"commands.lib39.help.page_info": "第 %d 卷,凡 %d 卷",
|
||||
"commands.lib39.help.subcommands_title": "子令:",
|
||||
"commands.lib39.help.toggle_failed": "變更未果: 無貯存之哈希",
|
||||
"commands.lib39.info": "示者訊",
|
||||
"commands.lib39.info.dimension": "界:%s",
|
||||
"commands.lib39.info.message": "〇〇 者訊 〇〇",
|
||||
"commands.lib39.info.position": "位:X=%.1f, Y=%.1f, Z=%.1f",
|
||||
"commands.lib39.reload": "重載配",
|
||||
"commands.lib39.root": "Lib39 令系",
|
||||
"commands.lib39.settings": "示置",
|
||||
"commands.lib39.team": "隊管",
|
||||
"commands.lib39.team.create": "創新隊",
|
||||
"commands.lib39.team.create.success": "隊 '%s' 創新成!",
|
||||
"commands.lib39.team.join": "入隊",
|
||||
"commands.lib39.team.join.success": "已入隊 '%s'",
|
||||
"commands.lib39.team.leave": "離現隊",
|
||||
"commands.lib39.team.leave.success": "已離隊",
|
||||
"commands.lib39.teleport": "送至者(唯管)",
|
||||
"commands.lib39.teleport.success": "已送至 %s",
|
||||
"commands.lib39.test": "試令",
|
||||
"commands.lib39.test.success": "試令行成!",
|
||||
"commands.lib39.test.with_param": "帶參試令:%s",
|
||||
"invalid.player_name.too_long": "§c§l玩家名過長,限十六字",
|
||||
"item.lib39.fabric": "織",
|
||||
"item.lib39.forge": "砧",
|
||||
"item.lib39.neoforge": "狸",
|
||||
"sound.lib39.subtitle.duck_toy": "偶音",
|
||||
"tooltip.lib39.content.doll.hover.1": "§e膚主§7:§a%s",
|
||||
"tooltip.lib39.content.doll.hover.2": "§7鐵砧之上,更名以易膚"
|
||||
}
|
||||
|
|
@ -1,60 +0,0 @@
|
|||
{
|
||||
"block.lib39.doll": "人偶",
|
||||
"commands.lib39.calculate": "計算兩個數字的和",
|
||||
"commands.lib39.calculate.result": "%d + %d = %d",
|
||||
"commands.lib39.config": "顯示配置",
|
||||
"commands.lib39.debug": "調試信息",
|
||||
"commands.lib39.demo": "演示命令",
|
||||
"commands.lib39.demo.message": "這是一個展示 Lib39 功能的演示命令!",
|
||||
"commands.lib39.game": "遊戲控制",
|
||||
"commands.lib39.game.pause": "暫停當前遊戲",
|
||||
"commands.lib39.game.pause.success": "遊戲已暫停!",
|
||||
"commands.lib39.game.resume": "恢復暫停的遊戲",
|
||||
"commands.lib39.game.resume.success": "遊戲已恢復!",
|
||||
"commands.lib39.game.start": "開始遊戲",
|
||||
"commands.lib39.game.start.success": "遊戲 '%s' 已開始!",
|
||||
"commands.lib39.game.stop": "停止當前遊戲",
|
||||
"commands.lib39.game.stop.success": "遊戲已停止!",
|
||||
"commands.lib39.greet.basic": "向大家問好",
|
||||
"commands.lib39.greet.default": "來自 Lib39 的問候!",
|
||||
"commands.lib39.greet.player": "問候特定玩家",
|
||||
"commands.lib39.greet.received": "%s 向你問好!",
|
||||
"commands.lib39.help.basic.help": "显示帮助信息",
|
||||
"commands.lib39.help.click_expand": "點擊展開",
|
||||
"commands.lib39.help.command_not_found": "命令不存在: %s",
|
||||
"commands.lib39.help.header": "===== %s 命令帮助 =====",
|
||||
"commands.lib39.help.hover.copy": "点击复制",
|
||||
"commands.lib39.help.no_entries": "暂无帮助条目",
|
||||
"commands.lib39.help.node.expand": "%d 个子命令已折叠",
|
||||
"commands.lib39.help.node.toggle.collapse": "折叠",
|
||||
"commands.lib39.help.node.toggle.expand": "展开",
|
||||
"commands.lib39.help.page_info": "第 %d 页,共 %d 页",
|
||||
"commands.lib39.help.subcommands_title": "子命令:",
|
||||
"commands.lib39.help.toggle_failed": "切换失败: 无缓存Hash",
|
||||
"commands.lib39.info": "顯示玩家信息",
|
||||
"commands.lib39.info.dimension": "維度:%s",
|
||||
"commands.lib39.info.message": "=== 玩家信息 ===",
|
||||
"commands.lib39.info.position": "位置:X=%.1f, Y=%.1f, Z=%.1f",
|
||||
"commands.lib39.reload": "重新加載配置",
|
||||
"commands.lib39.root": "Lib39 命令系統",
|
||||
"commands.lib39.settings": "顯示設置",
|
||||
"commands.lib39.team": "隊伍管理",
|
||||
"commands.lib39.team.create": "創建新隊伍",
|
||||
"commands.lib39.team.create.success": "隊伍 '%s' 創建成功!",
|
||||
"commands.lib39.team.join": "加入隊伍",
|
||||
"commands.lib39.team.join.success": "已加入隊伍 '%s'",
|
||||
"commands.lib39.team.leave": "離開當前隊伍",
|
||||
"commands.lib39.team.leave.success": "已離開隊伍",
|
||||
"commands.lib39.teleport": "傳送到玩家(僅OP)",
|
||||
"commands.lib39.teleport.success": "已傳送至 %s",
|
||||
"commands.lib39.test": "測試命令",
|
||||
"commands.lib39.test.success": "測試命令執行成功!",
|
||||
"commands.lib39.test.with_param": "帶參數的測試命令:%s",
|
||||
"invalid.player_name.too_long": "§c§l玩家名称过长(最多16个字符)",
|
||||
"item.lib39.fabric": "织布",
|
||||
"item.lib39.forge": "铁砧",
|
||||
"item.lib39.neoforge": "小狐狸",
|
||||
"sound.lib39.subtitle.duck_toy": "玩偶声音",
|
||||
"tooltip.lib39.content.doll.hover.1": "§e皮肤所有者§7:§a%s",
|
||||
"tooltip.lib39.content.doll.hover.2": "§7在铁砧上可通过重命名对应玩家名来改变皮肤"
|
||||
}
|
||||
|
|
@ -1,60 +0,0 @@
|
|||
{
|
||||
"block.lib39.doll": "人偶",
|
||||
"commands.lib39.calculate": "計算兩個數字的和",
|
||||
"commands.lib39.calculate.result": "%d + %d = %d",
|
||||
"commands.lib39.config": "顯示設定",
|
||||
"commands.lib39.debug": "除錯資訊",
|
||||
"commands.lib39.demo": "演示指令",
|
||||
"commands.lib39.demo.message": "這是一個展示 Lib39 功能的演示指令!",
|
||||
"commands.lib39.game": "遊戲控制",
|
||||
"commands.lib39.game.pause": "暫停當前遊戲",
|
||||
"commands.lib39.game.pause.success": "遊戲已暫停!",
|
||||
"commands.lib39.game.resume": "恢復暫停的遊戲",
|
||||
"commands.lib39.game.resume.success": "遊戲已恢復!",
|
||||
"commands.lib39.game.start": "開始遊戲",
|
||||
"commands.lib39.game.start.success": "遊戲 '%s' 已開始!",
|
||||
"commands.lib39.game.stop": "停止當前遊戲",
|
||||
"commands.lib39.game.stop.success": "遊戲已停止!",
|
||||
"commands.lib39.greet.basic": "向大家問好",
|
||||
"commands.lib39.greet.default": "來自 Lib39 的問候!",
|
||||
"commands.lib39.greet.player": "問候特定玩家",
|
||||
"commands.lib39.greet.received": "%s 向你問好!",
|
||||
"commands.lib39.help.basic.help": "顯示幫助信息",
|
||||
"commands.lib39.help.click_expand": "點擊展開",
|
||||
"commands.lib39.help.command_not_found": "指令不存在: %s",
|
||||
"commands.lib39.help.header": "===== %s 命令幫助 =====",
|
||||
"commands.lib39.help.hover.copy": "點擊複製",
|
||||
"commands.lib39.help.no_entries": "暫無幫助條目",
|
||||
"commands.lib39.help.node.expand": "%d 個子指令已折疊",
|
||||
"commands.lib39.help.node.toggle.collapse": "折疊",
|
||||
"commands.lib39.help.node.toggle.expand": "展開",
|
||||
"commands.lib39.help.page_info": "第 %d 頁,共 %d 頁",
|
||||
"commands.lib39.help.subcommands_title": "子指令:",
|
||||
"commands.lib39.help.toggle_failed": "切換失敗: 無緩存Hash",
|
||||
"commands.lib39.info": "顯示玩家資訊",
|
||||
"commands.lib39.info.dimension": "維度:%s",
|
||||
"commands.lib39.info.message": "=== 玩家資訊 ===",
|
||||
"commands.lib39.info.position": "位置:X=%.1f, Y=%.1f, Z=%.1f",
|
||||
"commands.lib39.reload": "重新載入設定",
|
||||
"commands.lib39.root": "Lib39 指令系統",
|
||||
"commands.lib39.settings": "顯示設定",
|
||||
"commands.lib39.team": "隊伍管理",
|
||||
"commands.lib39.team.create": "創建新隊伍",
|
||||
"commands.lib39.team.create.success": "隊伍 '%s' 創建成功!",
|
||||
"commands.lib39.team.join": "加入隊伍",
|
||||
"commands.lib39.team.join.success": "已加入隊伍 '%s'",
|
||||
"commands.lib39.team.leave": "離開當前隊伍",
|
||||
"commands.lib39.team.leave.success": "已離開隊伍",
|
||||
"commands.lib39.teleport": "傳送到玩家(僅OP)",
|
||||
"commands.lib39.teleport.success": "已傳送至 %s",
|
||||
"commands.lib39.test": "測試指令",
|
||||
"commands.lib39.test.success": "測試指令執行成功!",
|
||||
"commands.lib39.test.with_param": "帶參數的測試指令:%s",
|
||||
"invalid.player_name.too_long": "§c§l玩家名稱過長(最多16個字符)",
|
||||
"item.lib39.fabric": "織布",
|
||||
"item.lib39.forge": "铁砧",
|
||||
"item.lib39.neoforge": "狐狸",
|
||||
"sound.lib39.subtitle.duck_toy": "玩偶聲音",
|
||||
"tooltip.lib39.content.doll.hover.1": "§e皮膚所有者§7:§a%s",
|
||||
"tooltip.lib39.content.doll.hover.2": "§7在鐵砧上可通過重命名對應玩家名來改變皮膚"
|
||||
}
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
{
|
||||
"parent": "lib39:block/base_doll"
|
||||
}
|
||||
|
|
@ -1,6 +0,0 @@
|
|||
{
|
||||
"parent": "minecraft:item/generated",
|
||||
"textures": {
|
||||
"layer0": "lib39:item/fabric"
|
||||
}
|
||||
}
|
||||
|
|
@ -1,6 +0,0 @@
|
|||
{
|
||||
"parent": "minecraft:item/generated",
|
||||
"textures": {
|
||||
"layer0": "lib39:item/forge"
|
||||
}
|
||||
}
|
||||
|
|
@ -1,6 +0,0 @@
|
|||
{
|
||||
"parent": "minecraft:item/generated",
|
||||
"textures": {
|
||||
"layer0": "lib39:item/neoforge"
|
||||
}
|
||||
}
|
||||
|
|
@ -1,8 +0,0 @@
|
|||
{
|
||||
"duck_toy": {
|
||||
"sounds": [
|
||||
"lib39:duck_toy"
|
||||
],
|
||||
"subtitle": "sound.lib39.subtitle.duck_toy"
|
||||
}
|
||||
}
|
||||
|
|
@ -1,35 +0,0 @@
|
|||
{
|
||||
"parent": "minecraft:recipes/root",
|
||||
"criteria": {
|
||||
"has_armor_stand": {
|
||||
"conditions": {
|
||||
"items": [
|
||||
{
|
||||
"items": [
|
||||
"minecraft:armor_stand"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"trigger": "minecraft:inventory_changed"
|
||||
},
|
||||
"has_the_recipe": {
|
||||
"conditions": {
|
||||
"recipe": "lib39:doll"
|
||||
},
|
||||
"trigger": "minecraft:recipe_unlocked"
|
||||
}
|
||||
},
|
||||
"requirements": [
|
||||
[
|
||||
"has_armor_stand",
|
||||
"has_the_recipe"
|
||||
]
|
||||
],
|
||||
"rewards": {
|
||||
"recipes": [
|
||||
"lib39:doll"
|
||||
]
|
||||
},
|
||||
"sends_telemetry_event": false
|
||||
}
|
||||
|
|
@ -1,21 +0,0 @@
|
|||
{
|
||||
"type": "minecraft:block",
|
||||
"pools": [
|
||||
{
|
||||
"bonus_rolls": 0.0,
|
||||
"conditions": [
|
||||
{
|
||||
"condition": "minecraft:survives_explosion"
|
||||
}
|
||||
],
|
||||
"entries": [
|
||||
{
|
||||
"type": "minecraft:item",
|
||||
"name": "lib39:doll"
|
||||
}
|
||||
],
|
||||
"rolls": 1.0
|
||||
}
|
||||
],
|
||||
"random_sequence": "lib39:blocks/doll"
|
||||
}
|
||||
|
|
@ -1,15 +0,0 @@
|
|||
{
|
||||
"type": "minecraft:crafting_shapeless",
|
||||
"category": "misc",
|
||||
"ingredients": [
|
||||
{
|
||||
"tag": "minecraft:wool"
|
||||
},
|
||||
{
|
||||
"item": "minecraft:armor_stand"
|
||||
}
|
||||
],
|
||||
"result": {
|
||||
"item": "lib39:doll"
|
||||
}
|
||||
}
|
||||
|
|
@ -1,140 +0,0 @@
|
|||
package top.r3944realms.lib39;
|
||||
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraftforge.eventbus.api.IEventBus;
|
||||
import net.minecraftforge.fml.ModList;
|
||||
import net.minecraftforge.fml.common.Mod;
|
||||
import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;
|
||||
import net.minecraftforge.fml.loading.FMLEnvironment;
|
||||
import org.jetbrains.annotations.Contract;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import top.r3944realms.lib39.content.register.Lib39BlockEntities;
|
||||
import top.r3944realms.lib39.content.register.Lib39Blocks;
|
||||
import top.r3944realms.lib39.content.register.Lib39Items;
|
||||
import top.r3944realms.lib39.content.register.Lib39SoundEvents;
|
||||
import top.r3944realms.lib39.core.network.NetworkHandler;
|
||||
import top.r3944realms.lib39.example.Lib39Example;
|
||||
|
||||
/**
|
||||
* The type Lib 39.
|
||||
*/
|
||||
@Mod(Lib39.MOD_ID)
|
||||
public class Lib39 {
|
||||
/**
|
||||
* The constant MOD_ID.
|
||||
*/
|
||||
public static final String MOD_ID = "lib39";
|
||||
/**
|
||||
* The constant LOGGER.
|
||||
*/
|
||||
public static final Logger LOGGER = LoggerFactory.getLogger(Lib39.class);
|
||||
|
||||
/**
|
||||
* Instantiates a new Lib 39.
|
||||
*/
|
||||
public Lib39() {
|
||||
initialize();
|
||||
}
|
||||
|
||||
/**
|
||||
* The constant ENABLE_EXAMPLES_PROPERTY_KEY.
|
||||
*/
|
||||
public static final String ENABLE_EXAMPLES_PROPERTY_KEY = "lib39.enable_examples";
|
||||
|
||||
/**
|
||||
* Initialize.
|
||||
*/
|
||||
public static void initialize() {
|
||||
LOGGER.info("[Lib39] Initializing Lib39");
|
||||
IEventBus modEventBus = FMLJavaModLoadingContext.get().getModEventBus();
|
||||
Lib39Blocks.register(modEventBus);
|
||||
Lib39BlockEntities.register(modEventBus);
|
||||
Lib39Items.register(modEventBus);
|
||||
Lib39SoundEvents.register(modEventBus);
|
||||
NetworkHandler.register();
|
||||
if (shouldRegisterExamples()) {
|
||||
LOGGER.info("[Lib39] Registering Examples");
|
||||
registerExamples();
|
||||
}
|
||||
LOGGER.info("[Lib39] Initialized Lib39");
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Rl resource location.
|
||||
*
|
||||
* @param path the path
|
||||
* @return the resource location
|
||||
*/
|
||||
@Contract("_ -> new")
|
||||
public static @NotNull ResourceLocation rl(String path) {
|
||||
return new ResourceLocation(MOD_ID, path);
|
||||
}
|
||||
|
||||
/**
|
||||
* Rl resource location.
|
||||
*
|
||||
* @param modId the mod id
|
||||
* @param path the path
|
||||
* @return the resource location
|
||||
*/
|
||||
@Contract("_, _ -> new")
|
||||
public static @NotNull ResourceLocation rl(String modId, String path) {
|
||||
return new ResourceLocation(modId, path);
|
||||
}
|
||||
|
||||
/**
|
||||
* Mrl resource location.
|
||||
*
|
||||
* @param path the path
|
||||
* @return the resource location
|
||||
*/
|
||||
@Contract("_ -> new")
|
||||
public static @NotNull ResourceLocation mrl(String path) {
|
||||
return new ResourceLocation(path);
|
||||
}
|
||||
|
||||
/**
|
||||
* The type Mod info.
|
||||
*/
|
||||
public static class ModInfo {
|
||||
/**
|
||||
* The constant VERSION.
|
||||
*/
|
||||
public static final String VERSION;
|
||||
static {
|
||||
// 从 ModList 获取当前 ModContainer 的元数据
|
||||
VERSION = ModList.get()
|
||||
.getModContainerById(MOD_ID)
|
||||
.map(c -> c.getModInfo().getVersion().toString())
|
||||
.orElse("UNKNOWN");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Should register examples boolean.
|
||||
*
|
||||
* @return the boolean
|
||||
*/
|
||||
public static boolean shouldRegisterExamples() {
|
||||
return !FMLEnvironment.production || Boolean.getBoolean(ENABLE_EXAMPLES_PROPERTY_KEY);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register examples.
|
||||
*/
|
||||
static void registerExamples() {
|
||||
LOGGER.info("[Lib39] Starting example demonstrations");
|
||||
try {
|
||||
// 创建示例实例并演示功能
|
||||
Lib39Example example = new Lib39Example();
|
||||
example.demonstrateFeature();
|
||||
|
||||
LOGGER.info("[Lib39] Example demonstrations completed successfully");
|
||||
} catch (Exception e) {
|
||||
LOGGER.error("[Lib39] Failed to demonstrate examples", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,31 +0,0 @@
|
|||
package top.r3944realms.lib39.api.event;
|
||||
|
||||
import net.minecraft.server.Services;
|
||||
import net.minecraftforge.eventbus.api.Event;
|
||||
|
||||
import java.util.concurrent.Executor;
|
||||
|
||||
/**
|
||||
* The type Minecraft set up service event.
|
||||
*/
|
||||
public class MinecraftSetUpServiceEvent extends Event {
|
||||
/**
|
||||
* The Services.
|
||||
*/
|
||||
public final Services services;
|
||||
/**
|
||||
* The Main thread executor.
|
||||
*/
|
||||
public final Executor mainThreadExecutor;
|
||||
|
||||
/**
|
||||
* Instantiates a new Minecraft set up service event.
|
||||
*
|
||||
* @param services the services
|
||||
* @param mainThreadExecutor the main thread executor
|
||||
*/
|
||||
public MinecraftSetUpServiceEvent(Services services, Executor mainThreadExecutor) {
|
||||
this.services = services;
|
||||
this.mainThreadExecutor = mainThreadExecutor;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,100 +0,0 @@
|
|||
package top.r3944realms.lib39.api.event;
|
||||
|
||||
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
||||
import net.minecraft.commands.CommandBuildContext;
|
||||
import net.minecraft.commands.CommandSourceStack;
|
||||
import net.minecraft.network.chat.MutableComponent;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraftforge.eventbus.api.Event;
|
||||
import top.r3944realms.lib39.core.command.ICommandHelpManager;
|
||||
import top.r3944realms.lib39.core.command.model.CommandNode;
|
||||
import top.r3944realms.lib39.core.command.model.CommandPath;
|
||||
import top.r3944realms.lib39.core.command.model.Parameter;
|
||||
|
||||
/**
|
||||
* The type Register command help event.
|
||||
*/
|
||||
public class RegisterCommandHelpEvent extends Event {
|
||||
private final LiteralArgumentBuilder<CommandSourceStack> builder;
|
||||
private final ICommandHelpManager helpManager;
|
||||
private final CommandBuildContext context;
|
||||
|
||||
/**
|
||||
* Instantiates a new Register command help event.
|
||||
*
|
||||
* @param builder the builder
|
||||
* @param helpManager the help manager
|
||||
* @param source the source
|
||||
*/
|
||||
public RegisterCommandHelpEvent(LiteralArgumentBuilder<CommandSourceStack> builder, ICommandHelpManager helpManager, CommandBuildContext source) {
|
||||
this.builder = builder;
|
||||
this.helpManager = helpManager;
|
||||
this.context = source;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets id.
|
||||
*
|
||||
* @return the id
|
||||
*/
|
||||
public ResourceLocation getID() {
|
||||
return helpManager.getID();
|
||||
}
|
||||
|
||||
/**
|
||||
* Add child.
|
||||
*
|
||||
* @param child the child
|
||||
*/
|
||||
public void addChild(LiteralArgumentBuilder<CommandSourceStack> child) {
|
||||
this.builder.then(child);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get context command build context.
|
||||
*
|
||||
* @return the command build context
|
||||
*/
|
||||
public CommandBuildContext getContext(){
|
||||
return this.context;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get tree literal argument builder.
|
||||
*
|
||||
* @return the literal argument builder
|
||||
*/
|
||||
public LiteralArgumentBuilder<CommandSourceStack> getTree(){
|
||||
return this.builder;
|
||||
}
|
||||
|
||||
/**
|
||||
* 注册命令帮助信息
|
||||
*
|
||||
* @param CommandNode 命令节点
|
||||
* @param description 命令描述
|
||||
*/
|
||||
public void registerHelp(CommandNode CommandNode, MutableComponent description) {
|
||||
this.helpManager.registerCommandHelp(CommandNode, description);
|
||||
}
|
||||
|
||||
/**
|
||||
* 注册命令帮助信息
|
||||
*
|
||||
* @param CommandNode 命令节点
|
||||
* @param descriptionKey 命令描述的语言键
|
||||
*/
|
||||
public void registerHelp(CommandNode CommandNode, String descriptionKey) {
|
||||
this.helpManager.registerCommandHelp(CommandNode, descriptionKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* 注册命令参数
|
||||
*
|
||||
* @param commandPath 命令节点
|
||||
* @param parametersBuilder 参数列表构造器
|
||||
*/
|
||||
public void registerParameters(CommandPath commandPath, Parameter.Builder parametersBuilder) {
|
||||
this.helpManager.registerCommandParameters(commandPath, parametersBuilder);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,170 +0,0 @@
|
|||
package top.r3944realms.lib39.api.event;
|
||||
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraftforge.common.capabilities.Capability;
|
||||
import net.minecraftforge.eventbus.api.Event;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import top.r3944realms.lib39.core.sync.ISyncData;
|
||||
import top.r3944realms.lib39.core.sync.ISyncManager;
|
||||
import top.r3944realms.lib39.core.sync.SyncData2Manager;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.function.Function;
|
||||
|
||||
/**
|
||||
* The type Sync manager register event.
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public class SyncManagerRegisterEvent extends Event {
|
||||
/**
|
||||
* The Syncs 2 manager.
|
||||
*/
|
||||
protected final SyncData2Manager syncs2Manager;
|
||||
|
||||
/**
|
||||
* Instantiates a new Sync manager register event.
|
||||
*
|
||||
* @param syncsManager the syncs manager
|
||||
*/
|
||||
public SyncManagerRegisterEvent(SyncData2Manager syncsManager) {
|
||||
this.syncs2Manager = syncsManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets syncs manager.
|
||||
*
|
||||
* @return the syncs manager
|
||||
*/
|
||||
public SyncData2Manager getSyncsManager() {
|
||||
return syncs2Manager;
|
||||
}
|
||||
|
||||
/**
|
||||
* 类型安全的同步管理器注册
|
||||
*
|
||||
* @param <K> the type parameter
|
||||
* @param <T> the type parameter
|
||||
* @param id the id
|
||||
* @param syncManager the sync manager
|
||||
* @param capability the capability
|
||||
*/
|
||||
public <K, T extends ISyncData<?>> void registerSyncManager(
|
||||
ResourceLocation id,
|
||||
ISyncManager<K, T> syncManager,
|
||||
Capability<T> capability
|
||||
) {
|
||||
syncs2Manager.registerManager(id, syncManager, entity -> entity.getCapability(capability).resolve());
|
||||
}
|
||||
|
||||
/**
|
||||
* 类型安全的同步管理器注册
|
||||
*
|
||||
* @param <K> the type parameter
|
||||
* @param <T> the type parameter
|
||||
* @param id the id
|
||||
* @param syncManager the sync manager
|
||||
* @param dataProvider the dataProvider
|
||||
*/
|
||||
public <K, T extends ISyncData<?>> void registerSyncManager(
|
||||
ResourceLocation id,
|
||||
ISyncManager<K, T> syncManager,
|
||||
Function<Entity, Optional<T>> dataProvider
|
||||
) {
|
||||
syncs2Manager.registerManager(id, syncManager, dataProvider);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Unregister sync manager.
|
||||
*
|
||||
* @param id the id
|
||||
*/
|
||||
public void unregisterSyncManager(ResourceLocation id) {
|
||||
syncs2Manager.removeManager(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* 允许实体类
|
||||
*
|
||||
* @param id the id
|
||||
* @param entityClasses the entity classes
|
||||
*/
|
||||
public final void addAllowEntityClass(ResourceLocation id, Class<?>... entityClasses) {
|
||||
syncs2Manager.allowEntityClass(id, entityClasses);
|
||||
}
|
||||
|
||||
/**
|
||||
* 移除允许的实体类
|
||||
*
|
||||
* @param id the id
|
||||
* @param entityClasses the entity classes
|
||||
*/
|
||||
public final void removeAllowEntityClass(ResourceLocation id, Class<?>... entityClasses) {
|
||||
syncs2Manager.disallowEntityClass(id, entityClasses);
|
||||
}
|
||||
|
||||
/**
|
||||
* 绑定能力(用于分离注册的情况)
|
||||
*
|
||||
* @param <T> the type parameter
|
||||
* @param id 必须先注册安全同步管理器,再绑定Cap,否则会抛出{@link IllegalStateException 未找到对应安全同步管理器}
|
||||
* @param capability the capability
|
||||
*/
|
||||
public <T extends ISyncData<?>> void bindCapability(ResourceLocation id, Capability<T> capability) {
|
||||
syncs2Manager.bindDataGetter(id, entity -> entity.getCapability(capability).resolve());
|
||||
}
|
||||
|
||||
/**
|
||||
* 解绑数据提供者
|
||||
*
|
||||
* @param id the id
|
||||
*/
|
||||
public void unbindDataProvider(ResourceLocation id) {
|
||||
syncs2Manager.unbindDataProvider(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* 完整的类型安全注册
|
||||
*
|
||||
* @param <K> the type parameter
|
||||
* @param <T> the type parameter
|
||||
* @param id the id
|
||||
* @param syncManager the sync manager
|
||||
* @param capability the capability
|
||||
* @param allowedEntityClasses the allowed entity classes
|
||||
*/
|
||||
public <K, T extends ISyncData<?>> void registerComplete(
|
||||
ResourceLocation id,
|
||||
ISyncManager<K, T> syncManager,
|
||||
Capability<T> capability,
|
||||
Class<?>... allowedEntityClasses
|
||||
) {
|
||||
registerSyncManager(id, syncManager, capability);
|
||||
if (allowedEntityClasses.length > 0) {
|
||||
addAllowEntityClass(id, allowedEntityClasses);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 完整的类型安全注册
|
||||
*
|
||||
* @param <K> the type parameter
|
||||
* @param <T> the type parameter
|
||||
* @param id the id
|
||||
* @param syncManager the sync manager
|
||||
* @param dataProvider the capability
|
||||
* @param allowedEntityClasses the allowed entity classes
|
||||
*/
|
||||
public <K, T extends ISyncData<?>> void registerComplete(
|
||||
ResourceLocation id,
|
||||
ISyncManager<K, T> syncManager,
|
||||
Function<Entity, Optional<T>> dataProvider,
|
||||
Class<?> @NotNull ... allowedEntityClasses
|
||||
) {
|
||||
registerSyncManager(id, syncManager, dataProvider);
|
||||
if (allowedEntityClasses.length > 0) {
|
||||
addAllowEntityClass(id, allowedEntityClasses);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,36 +0,0 @@
|
|||
package top.r3944realms.lib39.base.command;
|
||||
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import top.r3944realms.lib39.Lib39;
|
||||
import top.r3944realms.lib39.core.command.SimpleCommandHelpManager;
|
||||
|
||||
/**
|
||||
* The type Lib 39 command help manager.
|
||||
*/
|
||||
public class Lib39CommandHelpManager extends SimpleCommandHelpManager {
|
||||
/**
|
||||
* The constant INSTANCE.
|
||||
*/
|
||||
public static volatile Lib39CommandHelpManager INSTANCE = new Lib39CommandHelpManager();
|
||||
/**
|
||||
* The Id.
|
||||
*/
|
||||
ResourceLocation ID = Lib39.rl("command_helper");
|
||||
|
||||
/**
|
||||
* Instantiates a new Lib 39 command help manager.
|
||||
*/
|
||||
public Lib39CommandHelpManager() {
|
||||
initialize();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResourceLocation getID() {
|
||||
return ID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getHeadKey() {
|
||||
return "lib39";
|
||||
}
|
||||
}
|
||||
|
|
@ -1,404 +0,0 @@
|
|||
package top.r3944realms.lib39.base.command;
|
||||
|
||||
import com.mojang.brigadier.Command;
|
||||
import com.mojang.brigadier.CommandDispatcher;
|
||||
import com.mojang.brigadier.arguments.IntegerArgumentType;
|
||||
import com.mojang.brigadier.arguments.StringArgumentType;
|
||||
import com.mojang.brigadier.context.CommandContext;
|
||||
import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
||||
import net.minecraft.commands.CommandSourceStack;
|
||||
import net.minecraft.commands.Commands;
|
||||
import net.minecraft.commands.arguments.EntityArgument;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraftforge.event.RegisterCommandsEvent;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import top.r3944realms.lib39.Lib39;
|
||||
import top.r3944realms.lib39.core.command.ICommandHelpManager;
|
||||
import top.r3944realms.lib39.core.command.SimpleHelpCommand;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* The type Lib 39 help command.
|
||||
*/
|
||||
public class Lib39HelpCommand extends SimpleHelpCommand {
|
||||
|
||||
/**
|
||||
* Instantiates a new Lib 39 help command.
|
||||
*
|
||||
* @param event the event
|
||||
*/
|
||||
public Lib39HelpCommand(@NotNull RegisterCommandsEvent event) {
|
||||
super(event);
|
||||
if(Lib39.shouldRegisterExamples()) {
|
||||
// 在這裡註冊測試命令
|
||||
registerTestCommands(event.getDispatcher());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ICommandHelpManager getCommandHelpManager() {
|
||||
return Lib39CommandHelpManager.INSTANCE;
|
||||
}
|
||||
|
||||
/**
|
||||
* 註冊測試命令
|
||||
*/
|
||||
private void registerTestCommands(@NotNull CommandDispatcher<CommandSourceStack> dispatcher) {
|
||||
// 註冊幫助系統本身
|
||||
dispatcher.register(
|
||||
getRoot()
|
||||
.then(Commands.literal("test")
|
||||
.executes(this::executeTest)
|
||||
.then(Commands.argument("param", StringArgumentType.string())
|
||||
.executes(this::executeTestWithParam))
|
||||
)
|
||||
.then(Commands.literal("demo")
|
||||
.executes(this::executeDemo)
|
||||
)
|
||||
);
|
||||
|
||||
// 註冊其他測試命令
|
||||
registerTestCommandTree(dispatcher);
|
||||
|
||||
// 在幫助系統中註冊這些命令
|
||||
registerCommandsInHelpSystem();
|
||||
}
|
||||
|
||||
/**
|
||||
* 註冊測試命令樹
|
||||
*/
|
||||
private void registerTestCommandTree(@NotNull CommandDispatcher<CommandSourceStack> dispatcher) {
|
||||
// 基本命令
|
||||
dispatcher.register(
|
||||
Commands.literal("lib39")
|
||||
.then(Commands.literal("greet")
|
||||
.executes(this::executeGreet)
|
||||
.then(Commands.argument("player", EntityArgument.player())
|
||||
.executes(this::executeGreetPlayer))
|
||||
)
|
||||
.then(Commands.literal("calculate")
|
||||
.then(Commands.argument("a", IntegerArgumentType.integer())
|
||||
.then(Commands.argument("b", IntegerArgumentType.integer())
|
||||
.executes(this::executeCalculate)))
|
||||
)
|
||||
.then(Commands.literal("teleport")
|
||||
.requires(source -> source.hasPermission(2)) // 需要OP權限
|
||||
.then(Commands.argument("target", EntityArgument.player())
|
||||
.executes(this::executeTeleport))
|
||||
)
|
||||
.then(Commands.literal("info")
|
||||
.executes(this::executeInfo)
|
||||
)
|
||||
);
|
||||
|
||||
// 嵌套命令示例
|
||||
dispatcher.register(
|
||||
Commands.literal("lib39")
|
||||
.then(Commands.literal("team")
|
||||
.then(Commands.literal("create")
|
||||
.then(Commands.argument("teamName", StringArgumentType.string())
|
||||
.executes(this::executeTeamCreate))
|
||||
)
|
||||
.then(Commands.literal("join")
|
||||
.then(Commands.argument("teamName", StringArgumentType.string())
|
||||
.executes(this::executeTeamJoin))
|
||||
)
|
||||
.then(Commands.literal("leave")
|
||||
.executes(this::executeTeamLeave))
|
||||
)
|
||||
.then(Commands.literal("game")
|
||||
.then(Commands.literal("start")
|
||||
.then(Commands.argument("map", StringArgumentType.string())
|
||||
.executes(this::executeGameStart))
|
||||
)
|
||||
.then(Commands.literal("stop")
|
||||
.executes(this::executeGameStop))
|
||||
.then(Commands.literal("pause")
|
||||
.executes(this::executeGamePause))
|
||||
.then(Commands.literal("resume")
|
||||
.executes(this::executeGameResume))
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* 在幫助系統中註冊命令
|
||||
*/
|
||||
private void registerCommandsInHelpSystem() {
|
||||
ICommandHelpManager helpManager = getCommandHelpManager();
|
||||
|
||||
// 使用Builder模式註冊完整的命令樹
|
||||
helpManager.registerCommands(builder -> {
|
||||
builder.root("lib39", "commands.lib39.root")
|
||||
.expanded(true) // 根節點默認展開
|
||||
|
||||
// 問候命令 - 添加多個子命令
|
||||
.branch("greet", "commands.lib39.greet.basic", greetBuilder -> {
|
||||
greetBuilder.expanded(false); // 默認摺疊
|
||||
greetBuilder.leaf("hello", "commands.lib39.greet.hello");
|
||||
greetBuilder.leaf("morning", "commands.lib39.greet.morning");
|
||||
greetBuilder.leaf("evening", "commands.lib39.greet.evening");
|
||||
greetBuilder.push("player", "commands.lib39.greet.player")
|
||||
.required("player")
|
||||
.pop();
|
||||
})
|
||||
|
||||
// 計算命令
|
||||
.push("calculate", "commands.lib39.calculate")
|
||||
.required("a")
|
||||
.required("b")
|
||||
.pop()
|
||||
|
||||
// 傳送命令
|
||||
.push("teleport", "commands.lib39.teleport")
|
||||
.required("target")
|
||||
.pop()
|
||||
|
||||
// 信息命令
|
||||
.leaf("info", "commands.lib39.info")
|
||||
|
||||
// 隊伍系統 - 添加多個子命令
|
||||
.branch("team", "commands.lib39.team", teamBuilder -> {
|
||||
teamBuilder.expanded(false); // 默認摺疊
|
||||
teamBuilder.leaf("create", "commands.lib39.team.create")
|
||||
.required("teamName");
|
||||
teamBuilder.leaf("join", "commands.lib39.team.join")
|
||||
.required("teamName");
|
||||
teamBuilder.leaf("leave", "commands.lib39.team.leave");
|
||||
teamBuilder.leaf("list", "commands.lib39.team.list");
|
||||
teamBuilder.leaf("info", "commands.lib39.team.info");
|
||||
})
|
||||
|
||||
// 遊戲系統 - 添加多個子命令
|
||||
.branch("game", "commands.lib39.game", gameBuilder -> {
|
||||
gameBuilder.expanded(false); // 默認摺疊
|
||||
gameBuilder.leaf("start", "commands.lib39.game.start")
|
||||
.required("map");
|
||||
gameBuilder.leaf("stop", "commands.lib39.game.stop");
|
||||
gameBuilder.leaf("pause", "commands.lib39.game.pause");
|
||||
gameBuilder.leaf("resume", "commands.lib39.game.resume");
|
||||
gameBuilder.leaf("status", "commands.lib39.game.status");
|
||||
})
|
||||
|
||||
// 設置命令
|
||||
.leavesT(Map.of(
|
||||
"settings", "commands.lib39.settings",
|
||||
"config", "commands.lib39.config",
|
||||
"reload", "commands.lib39.reload",
|
||||
"debug", "commands.lib39.debug",
|
||||
"demo", "commands.lib39.demo",
|
||||
"test", "commands.lib39.test"
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
// ==================== 命令執行方法 ====================
|
||||
|
||||
private int executeTest(CommandContext<CommandSourceStack> context) {
|
||||
CommandSourceStack source = context.getSource();
|
||||
source.sendSuccess(() ->
|
||||
Component.translatable("commands.lib39.test.success")
|
||||
.withStyle(net.minecraft.ChatFormatting.GREEN),
|
||||
false
|
||||
);
|
||||
return Command.SINGLE_SUCCESS;
|
||||
}
|
||||
|
||||
private int executeTestWithParam(CommandContext<CommandSourceStack> context) {
|
||||
String param = StringArgumentType.getString(context, "param");
|
||||
CommandSourceStack source = context.getSource();
|
||||
source.sendSuccess(() ->
|
||||
Component.translatable("commands.lib39.test.with_param", param)
|
||||
.withStyle(net.minecraft.ChatFormatting.AQUA),
|
||||
false
|
||||
);
|
||||
return Command.SINGLE_SUCCESS;
|
||||
}
|
||||
|
||||
private int executeDemo(CommandContext<CommandSourceStack> context) {
|
||||
CommandSourceStack source = context.getSource();
|
||||
source.sendSuccess(() ->
|
||||
Component.translatable("commands.lib39.demo.message")
|
||||
.withStyle(net.minecraft.ChatFormatting.GOLD),
|
||||
false
|
||||
);
|
||||
return Command.SINGLE_SUCCESS;
|
||||
}
|
||||
|
||||
private int executeGreet(CommandContext<CommandSourceStack> context) {
|
||||
CommandSourceStack source = context.getSource();
|
||||
source.sendSuccess(() ->
|
||||
Component.translatable("commands.lib39.greet.default")
|
||||
.withStyle(net.minecraft.ChatFormatting.YELLOW),
|
||||
false
|
||||
);
|
||||
return Command.SINGLE_SUCCESS;
|
||||
}
|
||||
|
||||
private int executeGreetPlayer(CommandContext<CommandSourceStack> context) throws CommandSyntaxException {
|
||||
ServerPlayer player = EntityArgument.getPlayer(context, "player");
|
||||
CommandSourceStack source = context.getSource();
|
||||
|
||||
source.sendSuccess(() ->
|
||||
Component.translatable("commands.lib39.greet.player", player.getDisplayName())
|
||||
.withStyle(net.minecraft.ChatFormatting.GREEN),
|
||||
false
|
||||
);
|
||||
|
||||
player.sendSystemMessage(
|
||||
Component.translatable("commands.lib39.greet.received", source.getDisplayName())
|
||||
.withStyle(net.minecraft.ChatFormatting.AQUA)
|
||||
);
|
||||
|
||||
return Command.SINGLE_SUCCESS;
|
||||
}
|
||||
|
||||
private int executeCalculate(CommandContext<CommandSourceStack> context) {
|
||||
int a = IntegerArgumentType.getInteger(context, "a");
|
||||
int b = IntegerArgumentType.getInteger(context, "b");
|
||||
int sum = a + b;
|
||||
|
||||
CommandSourceStack source = context.getSource();
|
||||
source.sendSuccess(() ->
|
||||
Component.translatable("commands.lib39.calculate.result", a, b, sum)
|
||||
.withStyle(net.minecraft.ChatFormatting.LIGHT_PURPLE),
|
||||
false
|
||||
);
|
||||
|
||||
return Command.SINGLE_SUCCESS;
|
||||
}
|
||||
|
||||
private int executeTeleport(CommandContext<CommandSourceStack> context) throws CommandSyntaxException {
|
||||
ServerPlayer target = EntityArgument.getPlayer(context, "target");
|
||||
CommandSourceStack source = context.getSource();
|
||||
|
||||
if (source.getEntity() instanceof ServerPlayer player) {
|
||||
player.teleportTo(
|
||||
target.serverLevel(),
|
||||
target.getX(),
|
||||
target.getY(),
|
||||
target.getZ(),
|
||||
target.getYRot(),
|
||||
target.getXRot()
|
||||
);
|
||||
|
||||
source.sendSuccess(() ->
|
||||
Component.translatable("commands.lib39.teleport.success", target.getDisplayName())
|
||||
.withStyle(net.minecraft.ChatFormatting.GREEN),
|
||||
false
|
||||
);
|
||||
}
|
||||
|
||||
return Command.SINGLE_SUCCESS;
|
||||
}
|
||||
|
||||
private int executeInfo(CommandContext<CommandSourceStack> context) {
|
||||
CommandSourceStack source = context.getSource();
|
||||
ResourceLocation dimension = source.getLevel().dimension().location();
|
||||
|
||||
source.sendSuccess(() ->
|
||||
Component.translatable("commands.lib39.info.message")
|
||||
.append("\n")
|
||||
.append(Component.translatable("commands.lib39.info.dimension", dimension))
|
||||
.append("\n")
|
||||
.append(Component.translatable("commands.lib39.info.position",
|
||||
String.format("%.1f", source.getPosition().x()),
|
||||
String.format("%.1f", source.getPosition().y()),
|
||||
String.format("%.1f", source.getPosition().z())))
|
||||
.withStyle(net.minecraft.ChatFormatting.AQUA),
|
||||
false
|
||||
);
|
||||
|
||||
return Command.SINGLE_SUCCESS;
|
||||
}
|
||||
|
||||
private int executeTeamCreate(CommandContext<CommandSourceStack> context) {
|
||||
String teamName = StringArgumentType.getString(context, "teamName");
|
||||
CommandSourceStack source = context.getSource();
|
||||
|
||||
source.sendSuccess(() ->
|
||||
Component.translatable("commands.lib39.team.create.success", teamName)
|
||||
.withStyle(net.minecraft.ChatFormatting.GREEN),
|
||||
false
|
||||
);
|
||||
|
||||
return Command.SINGLE_SUCCESS;
|
||||
}
|
||||
|
||||
private int executeTeamJoin(CommandContext<CommandSourceStack> context) {
|
||||
String teamName = StringArgumentType.getString(context, "teamName");
|
||||
CommandSourceStack source = context.getSource();
|
||||
|
||||
source.sendSuccess(() ->
|
||||
Component.translatable("commands.lib39.team.join.success", teamName)
|
||||
.withStyle(net.minecraft.ChatFormatting.GREEN),
|
||||
false
|
||||
);
|
||||
|
||||
return Command.SINGLE_SUCCESS;
|
||||
}
|
||||
|
||||
private int executeTeamLeave(CommandContext<CommandSourceStack> context) {
|
||||
CommandSourceStack source = context.getSource();
|
||||
|
||||
source.sendSuccess(() ->
|
||||
Component.translatable("commands.lib39.team.leave.success")
|
||||
.withStyle(net.minecraft.ChatFormatting.YELLOW),
|
||||
false
|
||||
);
|
||||
|
||||
return Command.SINGLE_SUCCESS;
|
||||
}
|
||||
|
||||
private int executeGameStart(CommandContext<CommandSourceStack> context) {
|
||||
String map = StringArgumentType.getString(context, "map");
|
||||
CommandSourceStack source = context.getSource();
|
||||
|
||||
source.sendSuccess(() ->
|
||||
Component.translatable("commands.lib39.game.start.success", map)
|
||||
.withStyle(net.minecraft.ChatFormatting.GREEN),
|
||||
false
|
||||
);
|
||||
|
||||
return Command.SINGLE_SUCCESS;
|
||||
}
|
||||
|
||||
private int executeGameStop(CommandContext<CommandSourceStack> context) {
|
||||
CommandSourceStack source = context.getSource();
|
||||
|
||||
source.sendSuccess(() ->
|
||||
Component.translatable("commands.lib39.game.stop.success")
|
||||
.withStyle(net.minecraft.ChatFormatting.RED),
|
||||
false
|
||||
);
|
||||
|
||||
return Command.SINGLE_SUCCESS;
|
||||
}
|
||||
|
||||
private int executeGamePause(CommandContext<CommandSourceStack> context) {
|
||||
CommandSourceStack source = context.getSource();
|
||||
|
||||
source.sendSuccess(() ->
|
||||
Component.translatable("commands.lib39.game.pause.success")
|
||||
.withStyle(net.minecraft.ChatFormatting.YELLOW),
|
||||
false
|
||||
);
|
||||
|
||||
return Command.SINGLE_SUCCESS;
|
||||
}
|
||||
|
||||
private int executeGameResume(CommandContext<CommandSourceStack> context) {
|
||||
CommandSourceStack source = context.getSource();
|
||||
|
||||
source.sendSuccess(() ->
|
||||
Component.translatable("commands.lib39.game.resume.success")
|
||||
.withStyle(net.minecraft.ChatFormatting.GREEN),
|
||||
false
|
||||
);
|
||||
|
||||
return Command.SINGLE_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,85 +0,0 @@
|
|||
package top.r3944realms.lib39.base.datagen;
|
||||
|
||||
import net.minecraft.data.DataProvider;
|
||||
import net.minecraftforge.data.event.GatherDataEvent;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import top.r3944realms.lib39.Lib39;
|
||||
import top.r3944realms.lib39.base.datagen.provider.*;
|
||||
import top.r3944realms.lib39.base.datagen.value.Lib39LangKey;
|
||||
import top.r3944realms.lib39.datagen.provider.SimpleLanguageProvider;
|
||||
import top.r3944realms.lib39.datagen.provider.SimpleLootTableProvider;
|
||||
import top.r3944realms.lib39.datagen.provider.SubProvidersWrapper;
|
||||
import top.r3944realms.lib39.datagen.value.McLocale;
|
||||
|
||||
/**
|
||||
* The type Lib 39 base data gen event.
|
||||
*/
|
||||
public class Lib39BaseDataGenEvent {
|
||||
/**
|
||||
* The Logger.
|
||||
*/
|
||||
static Logger logger = LoggerFactory.getLogger(Lib39BaseDataGenEvent.class);
|
||||
|
||||
/**
|
||||
* Gather data.
|
||||
*
|
||||
* @param event the event
|
||||
*/
|
||||
public static void gatherData(GatherDataEvent event) {
|
||||
logger.info("GatherDataEvent thread: {}", Thread.currentThread().getName());
|
||||
LanguageGenerator(event, McLocale.EN_US);
|
||||
LanguageGenerator(event, McLocale.ZH_CN);
|
||||
LanguageGenerator(event, McLocale.ZH_TW);
|
||||
LanguageGenerator(event, McLocale.LZH);
|
||||
BlockModelDataGenerate(event);
|
||||
BlockStateDataGenerate(event);
|
||||
ItemModelDataGenerate(event);
|
||||
LootTableDataGenerate(event);
|
||||
SoundDefinitionDataGenerate(event);
|
||||
RecipeGenerator(event);
|
||||
}
|
||||
private static void LanguageGenerator(@NotNull GatherDataEvent event, McLocale language) {
|
||||
event.getGenerator().addProvider(
|
||||
event.includeClient(),
|
||||
(DataProvider.Factory<SimpleLanguageProvider>) pOutput -> new SimpleLanguageProvider(pOutput, Lib39.MOD_ID ,language , Lib39LangKey.INSTANCE)
|
||||
);
|
||||
}
|
||||
private static void ItemModelDataGenerate(@NotNull GatherDataEvent event) {
|
||||
event.getGenerator().addProvider(
|
||||
event.includeClient(),
|
||||
(DataProvider.Factory<Lib39ItemModelProvider>) pOutput -> new Lib39ItemModelProvider(pOutput, event.getExistingFileHelper())
|
||||
);
|
||||
}
|
||||
private static void BlockModelDataGenerate(@NotNull GatherDataEvent event) {
|
||||
event.getGenerator().addProvider(
|
||||
event.includeClient(),
|
||||
(DataProvider.Factory<Lib39BlockModelProvider>) pOutput -> new Lib39BlockModelProvider(pOutput, event.getExistingFileHelper())
|
||||
);
|
||||
}
|
||||
private static void BlockStateDataGenerate(@NotNull GatherDataEvent event) {
|
||||
event.getGenerator().addProvider(
|
||||
event.includeClient(),
|
||||
(DataProvider.Factory<Lib39BlockStatesProvider>) pOutput -> new Lib39BlockStatesProvider(pOutput, event.getExistingFileHelper())
|
||||
);
|
||||
}
|
||||
private static void SoundDefinitionDataGenerate(@NotNull GatherDataEvent event) {
|
||||
event.getGenerator().addProvider(
|
||||
event.includeClient(),
|
||||
(DataProvider.Factory<Lib39SoundDefinitionsProvider>) pOutput -> new Lib39SoundDefinitionsProvider(pOutput, event.getExistingFileHelper())
|
||||
);
|
||||
}
|
||||
private static void LootTableDataGenerate(@NotNull GatherDataEvent event) {
|
||||
event.getGenerator().addProvider(
|
||||
event.includeServer(),
|
||||
(DataProvider.Factory<SimpleLootTableProvider>) pOutput -> new SimpleLootTableProvider(pOutput, new SubProvidersWrapper().addBlockEntry(new Lib39BlockLootTable()))
|
||||
);
|
||||
}
|
||||
private static void RecipeGenerator(@NotNull GatherDataEvent event) {
|
||||
event.getGenerator().addProvider(
|
||||
event.includeServer(),
|
||||
(DataProvider.Factory<Lib39RecipeProvider>) Lib39RecipeProvider::new
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,17 +0,0 @@
|
|||
package top.r3944realms.lib39.base.datagen.provider;
|
||||
|
||||
import top.r3944realms.lib39.content.register.Lib39Blocks;
|
||||
import top.r3944realms.lib39.datagen.provider.subprovider.BlockLootTables;
|
||||
|
||||
/**
|
||||
* The type Lib 39 block loot table.
|
||||
*/
|
||||
public class Lib39BlockLootTable extends BlockLootTables {
|
||||
/**
|
||||
* Instantiates a new Lib 39 block loot table.
|
||||
*/
|
||||
public Lib39BlockLootTable() {
|
||||
super(Lib39Blocks.BLOCKS);
|
||||
dropSelf(Lib39Blocks.DOLL);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,44 +0,0 @@
|
|||
package top.r3944realms.lib39.base.datagen.provider;
|
||||
|
||||
import net.minecraft.data.PackOutput;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraftforge.client.model.generators.BlockModelProvider;
|
||||
import net.minecraftforge.common.data.ExistingFileHelper;
|
||||
import top.r3944realms.lib39.Lib39;
|
||||
import top.r3944realms.lib39.util.PlantHelper;
|
||||
|
||||
/**
|
||||
* The type Lib 39 block model provider.
|
||||
*/
|
||||
public class Lib39BlockModelProvider extends BlockModelProvider {
|
||||
/**
|
||||
* Instantiates a new Lib 39 block model provider.
|
||||
*
|
||||
* @param output the output
|
||||
* @param existingFileHelper the existing file helper
|
||||
*/
|
||||
public Lib39BlockModelProvider(PackOutput output, ExistingFileHelper existingFileHelper) {
|
||||
super(output, Lib39.MOD_ID, existingFileHelper);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void registerModels() {
|
||||
// registerPlants();
|
||||
}
|
||||
|
||||
/**
|
||||
* Register plants.
|
||||
*/
|
||||
protected void registerPlants() {
|
||||
for (PlantHelper.Plant plant: PlantHelper.Plant.values()) {
|
||||
createPlantsModel(plant);
|
||||
}
|
||||
}
|
||||
private void createPlantsModel(PlantHelper.Plant plant) {
|
||||
ResourceLocation rl = PlantHelper.getTextureRL(plant);
|
||||
getBuilder("block/doll_item/" + plant)
|
||||
.parent(getExistingFile(Lib39.rl("block/base_doll_item")))
|
||||
.texture("item", rl)
|
||||
.ao(false);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,74 +0,0 @@
|
|||
package top.r3944realms.lib39.base.datagen.provider;
|
||||
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.data.PackOutput;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.state.properties.BlockStateProperties;
|
||||
import net.minecraftforge.client.model.generators.BlockStateProvider;
|
||||
import net.minecraftforge.client.model.generators.ConfiguredModel;
|
||||
import net.minecraftforge.client.model.generators.ModelFile;
|
||||
import net.minecraftforge.common.data.ExistingFileHelper;
|
||||
import org.jetbrains.annotations.Contract;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import top.r3944realms.lib39.Lib39;
|
||||
import top.r3944realms.lib39.content.register.Lib39Blocks;
|
||||
|
||||
/**
|
||||
* The type Lib 39 block states provider.
|
||||
*/
|
||||
public class Lib39BlockStatesProvider extends BlockStateProvider {
|
||||
/**
|
||||
* Instantiates a new Lib 39 block states provider.
|
||||
*
|
||||
* @param output the output
|
||||
* @param exFileHelper the ex file helper
|
||||
*/
|
||||
public Lib39BlockStatesProvider(PackOutput output, ExistingFileHelper exFileHelper) {
|
||||
super(output, Lib39.MOD_ID, exFileHelper);
|
||||
}
|
||||
@Override
|
||||
protected void registerStatesAndModels() {
|
||||
generateDollBlockStatesSimple();
|
||||
}
|
||||
private void generateDollBlockStatesSimple() {
|
||||
Block doll = Lib39Blocks.DOLL.get();
|
||||
|
||||
// 创建GeckoLib模型引用
|
||||
ModelFile modelFile = new ModelFile.ExistingModelFile(
|
||||
Lib39.rl( "block/base_doll"),
|
||||
models().existingFileHelper
|
||||
);
|
||||
|
||||
getVariantBuilder(doll).forAllStates(state -> {
|
||||
Direction direction = state.getValue(BlockStateProperties.HORIZONTAL_FACING);
|
||||
int rotationY = getMainNorthRotationY(direction);
|
||||
|
||||
return ConfiguredModel.builder()
|
||||
.modelFile(modelFile)
|
||||
.rotationY(rotationY)
|
||||
.build();
|
||||
});
|
||||
}
|
||||
|
||||
@Contract(pure = true)
|
||||
private int getMainWestRotationY(@NotNull Direction direction) {
|
||||
return switch (direction) {
|
||||
case WEST -> 0; // 西 - 基准方向,0度
|
||||
case NORTH -> 90; // 北 - 相对于西旋转90度
|
||||
case EAST -> 180; // 东 - 相对于西旋转180度
|
||||
case SOUTH -> 270; // 南 - 相对于西旋转270度
|
||||
default -> 0;
|
||||
};
|
||||
}
|
||||
|
||||
@Contract(pure = true)
|
||||
private int getMainNorthRotationY(@NotNull Direction direction) {
|
||||
return switch (direction) {
|
||||
case WEST -> 270; // 西 - 基准方向,270度
|
||||
case NORTH -> 0; // 北 - 相对于西旋转0度
|
||||
case EAST -> 90; // 东 - 相对于西旋转90度
|
||||
case SOUTH -> 180; // 南 - 相对于西旋转180度
|
||||
default -> 0;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
@ -1,123 +0,0 @@
|
|||
/*
|
||||
* Super Lead rope mod
|
||||
* Copyright (C) 2025 R3944Realms
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package top.r3944realms.lib39.base.datagen.provider;
|
||||
|
||||
import net.minecraft.data.PackOutput;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.item.Item;
|
||||
import net.minecraftforge.common.data.ExistingFileHelper;
|
||||
import net.minecraftforge.registries.ForgeRegistries;
|
||||
import top.r3944realms.lib39.Lib39;
|
||||
import top.r3944realms.lib39.base.datagen.value.Lib39LangKey;
|
||||
import top.r3944realms.lib39.datagen.value.LangKeyValue;
|
||||
import top.r3944realms.lib39.datagen.value.ModPartEnum;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* The type item model provider.
|
||||
*/
|
||||
public class Lib39ItemModelProvider extends net.minecraftforge.client.model.generators.ItemModelProvider {
|
||||
private static List<Item> objectList;
|
||||
/**
|
||||
* The constant GENERATED.
|
||||
*/
|
||||
public static final String GENERATED = "item/generated";
|
||||
/**
|
||||
* The constant HANDHELD.
|
||||
*/
|
||||
public static final String HANDHELD = "item/handheld";
|
||||
|
||||
/**
|
||||
* Instantiates a new item model provider.
|
||||
*
|
||||
* @param output the output
|
||||
* @param existingFileHelper the existing file helper
|
||||
*/
|
||||
public Lib39ItemModelProvider(PackOutput output, ExistingFileHelper existingFileHelper) {
|
||||
super(output, Lib39.MOD_ID, existingFileHelper);
|
||||
objectList = new ArrayList<>();
|
||||
init();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void registerModels() {
|
||||
defaultModItemModelRegister();
|
||||
generateDollItemModel();
|
||||
}
|
||||
private void init() {
|
||||
for(LangKeyValue obj : Lib39LangKey.INSTANCE.getValues()) {
|
||||
if(!(obj.isDefault() && obj.getMPE().equals(ModPartEnum.ITEM))) continue;
|
||||
objectList.add(obj.getItem());
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @implNote <br/> 先有纹理才会成功构建
|
||||
*/
|
||||
private void defaultModItemModelRegister() {
|
||||
objectList.forEach(this::basicItem);
|
||||
}
|
||||
|
||||
/**
|
||||
* Item generate model.
|
||||
*
|
||||
* @param item the item
|
||||
* @param location the location
|
||||
*/
|
||||
public void itemGenerateModel(Item item, ResourceLocation location){
|
||||
withExistingParent(itemName(item), GENERATED).texture("layer0", location);
|
||||
}
|
||||
|
||||
/**
|
||||
* Item hand held model.
|
||||
*
|
||||
* @param item the item
|
||||
* @param location the location
|
||||
*/
|
||||
public void itemHandHeldModel(Item item, ResourceLocation location){
|
||||
withExistingParent(itemName(item), HANDHELD).texture("layer0", location);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate doll item model.
|
||||
*/
|
||||
protected void generateDollItemModel() {
|
||||
getBuilder("doll")
|
||||
.parent(getExistingFile(Lib39.rl("block/base_doll")));
|
||||
}
|
||||
|
||||
/**
|
||||
* Item name string.
|
||||
*
|
||||
* @param item the item
|
||||
* @return the string
|
||||
*/
|
||||
public String itemName(Item item){
|
||||
return Objects.requireNonNull(ForgeRegistries.ITEMS.getKey(item)).getPath();
|
||||
}
|
||||
|
||||
/**
|
||||
* Resource item resource location.
|
||||
*
|
||||
* @param path the path
|
||||
* @return the resource location
|
||||
*/
|
||||
public ResourceLocation resourceItem(String path){
|
||||
return modLoc("item/" + path);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,36 +0,0 @@
|
|||
package top.r3944realms.lib39.base.datagen.provider;
|
||||
|
||||
import net.minecraft.data.PackOutput;
|
||||
import net.minecraft.data.recipes.FinishedRecipe;
|
||||
import net.minecraft.data.recipes.RecipeCategory;
|
||||
import net.minecraft.data.recipes.RecipeProvider;
|
||||
import net.minecraft.data.recipes.ShapelessRecipeBuilder;
|
||||
import net.minecraft.tags.ItemTags;
|
||||
import net.minecraft.world.item.Items;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import top.r3944realms.lib39.content.register.Lib39Items;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
|
||||
/**
|
||||
* The type Lib 39 recipe provider.
|
||||
*/
|
||||
public class Lib39RecipeProvider extends RecipeProvider {
|
||||
/**
|
||||
* Instantiates a new Lib 39 recipe provider.
|
||||
*
|
||||
* @param output the output
|
||||
*/
|
||||
public Lib39RecipeProvider(PackOutput output) {
|
||||
super(output);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void buildRecipes(@NotNull Consumer<FinishedRecipe> consumer) {
|
||||
ShapelessRecipeBuilder.shapeless(RecipeCategory.MISC, Lib39Items.DOLL.get())
|
||||
.requires(ItemTags.WOOL)
|
||||
.requires(Items.ARMOR_STAND)
|
||||
.unlockedBy("has_armor_stand",has(Items.ARMOR_STAND))
|
||||
.save(consumer);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,45 +0,0 @@
|
|||
package top.r3944realms.lib39.base.datagen.provider;
|
||||
|
||||
import net.minecraft.data.PackOutput;
|
||||
import net.minecraftforge.common.data.ExistingFileHelper;
|
||||
import net.minecraftforge.common.data.SoundDefinition;
|
||||
import net.minecraftforge.common.data.SoundDefinitionsProvider;
|
||||
import top.r3944realms.lib39.Lib39;
|
||||
import top.r3944realms.lib39.content.register.Lib39SoundEvents;
|
||||
|
||||
/**
|
||||
* The type Lib 39 sound definitions provider.
|
||||
*/
|
||||
public class Lib39SoundDefinitionsProvider extends SoundDefinitionsProvider {
|
||||
/**
|
||||
* Instantiates a new Lib 39 sound definitions provider.
|
||||
*
|
||||
* @param output the output
|
||||
* @param helper the helper
|
||||
*/
|
||||
public Lib39SoundDefinitionsProvider(PackOutput output, ExistingFileHelper helper) {
|
||||
super(output, Lib39.MOD_ID, helper);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets sound definition.
|
||||
*
|
||||
* @param subTitle the sub title
|
||||
* @param sounds the sounds
|
||||
* @return the sound definition
|
||||
*/
|
||||
public SoundDefinition getSoundDefinition(String subTitle, SoundDefinition.Sound... sounds) {
|
||||
return SoundDefinition.definition().subtitle(subTitle).with(sounds);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerSounds() {
|
||||
add(
|
||||
Lib39SoundEvents.DUCK_TOY,
|
||||
getSoundDefinition(
|
||||
Lib39SoundEvents.getSubTitleTranslateKey("duck_toy"),
|
||||
sound(Lib39SoundEvents.RL_DUCK_TOY, SoundDefinition.SoundType.SOUND)
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,874 +0,0 @@
|
|||
package top.r3944realms.lib39.base.datagen.value;
|
||||
|
||||
import org.jetbrains.annotations.Contract;
|
||||
import org.jetbrains.annotations.Unmodifiable;
|
||||
import top.r3944realms.lib39.Lib39;
|
||||
import top.r3944realms.lib39.content.register.Lib39Blocks;
|
||||
import top.r3944realms.lib39.content.register.Lib39Items;
|
||||
import top.r3944realms.lib39.content.register.Lib39SoundEvents;
|
||||
import top.r3944realms.lib39.datagen.value.ILangKeyValueCollection;
|
||||
import top.r3944realms.lib39.datagen.value.LangKeyValue;
|
||||
import top.r3944realms.lib39.datagen.value.ModPartEnum;
|
||||
import top.r3944realms.lib39.example.core.register.ExLib39Items;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* The enum Lib 39 lang key.
|
||||
*/
|
||||
public enum Lib39LangKey implements ILangKeyValueCollection {
|
||||
/**
|
||||
* Instance lib 39 lang key.
|
||||
*/
|
||||
INSTANCE;
|
||||
Lib39LangKey() {
|
||||
initLangKeyValues();
|
||||
}
|
||||
|
||||
/**
|
||||
* The type Message.
|
||||
*/
|
||||
public static final class Message {
|
||||
private static final Set<LangKeyValue> items = new HashSet<>();
|
||||
/**
|
||||
* The constant HELP_HEADER.
|
||||
*/
|
||||
public static final LangKeyValue HELP_HEADER = addAndRet(
|
||||
LangKeyValue.ofKey(
|
||||
"commands.lib39.help.header", ModPartEnum.MESSAGE,
|
||||
"===== %s =====",
|
||||
"===== %s 命令帮助 =====",
|
||||
"===== %s 命令幫助 =====",
|
||||
"〇〇 %s 〇〇", // 文言文:用〇〇表示分隔線
|
||||
true
|
||||
)
|
||||
);
|
||||
|
||||
/**
|
||||
* The constant HELP_CLICK_EXPAND.
|
||||
*/
|
||||
public static final LangKeyValue HELP_CLICK_EXPAND = addAndRet(
|
||||
LangKeyValue.ofKey(
|
||||
"commands.lib39.help.click_expand", ModPartEnum.MESSAGE,
|
||||
"Click to expand",
|
||||
"點擊展開",
|
||||
"點擊展開",
|
||||
"點展",
|
||||
true
|
||||
)
|
||||
);
|
||||
|
||||
/**
|
||||
* The constant HELP_PAGE_INFO.
|
||||
*/
|
||||
public static final LangKeyValue HELP_PAGE_INFO = addAndRet(
|
||||
LangKeyValue.ofKey(
|
||||
"commands.lib39.help.page_info", ModPartEnum.MESSAGE,
|
||||
"Page %d of %d",
|
||||
"第 %d 页,共 %d 页",
|
||||
"第 %d 頁,共 %d 頁",
|
||||
"第 %d 卷,凡 %d 卷", // 文言文:用「卷」表示頁
|
||||
true
|
||||
)
|
||||
);
|
||||
|
||||
/**
|
||||
* The constant HELP_NO_ENTRIES.
|
||||
*/
|
||||
public static final LangKeyValue HELP_NO_ENTRIES = addAndRet(
|
||||
LangKeyValue.ofKey(
|
||||
"commands.lib39.help.no_entries", ModPartEnum.MESSAGE,
|
||||
"No help entries available",
|
||||
"暂无帮助条目",
|
||||
"暫無幫助條目",
|
||||
"尚無助之目錄", // 文言文:尚無幫助的目錄
|
||||
true
|
||||
)
|
||||
);
|
||||
|
||||
/**
|
||||
* The constant HELP_TOGGLE_FAILED.
|
||||
*/
|
||||
public static final LangKeyValue HELP_TOGGLE_FAILED = addAndRet(
|
||||
LangKeyValue.ofKey(
|
||||
"commands.lib39.help.toggle_failed", ModPartEnum.MESSAGE,
|
||||
"Toggle Failed: No Hash Cached",
|
||||
"切换失败: 无缓存Hash",
|
||||
"切換失敗: 無緩存Hash",
|
||||
"變更未果: 無貯存之哈希", // 文言文:變更沒有成功,沒有貯存的哈希
|
||||
true
|
||||
)
|
||||
);
|
||||
|
||||
/**
|
||||
* The constant HELP_COMMAND_NOT_FOUND.
|
||||
*/
|
||||
public static final LangKeyValue HELP_COMMAND_NOT_FOUND = addAndRet(
|
||||
LangKeyValue.ofKey(
|
||||
"commands.lib39.help.command_not_found", ModPartEnum.MESSAGE,
|
||||
"Command not found: %s",
|
||||
"命令不存在: %s",
|
||||
"指令不存在: %s",
|
||||
"令未見之: %s", // 文言文:命令沒有見到
|
||||
true
|
||||
)
|
||||
);
|
||||
/**
|
||||
* The constant DOLL_SOUND.
|
||||
*/
|
||||
public static final LangKeyValue DOLL_SOUND = addAndRet(
|
||||
LangKeyValue.ofKey(
|
||||
Lib39SoundEvents.getSubTitleTranslateKey("duck_toy"), ModPartEnum.SOUND,
|
||||
"Duck Doll Sound",
|
||||
"玩偶声音",
|
||||
"玩偶聲音",
|
||||
"偶音",
|
||||
true
|
||||
)
|
||||
);
|
||||
|
||||
|
||||
/**
|
||||
* The constant HELP_SUBCOMMANDS_TITLE.
|
||||
*/
|
||||
public static final LangKeyValue HELP_SUBCOMMANDS_TITLE = addAndRet(
|
||||
LangKeyValue.ofKey(
|
||||
"commands.lib39.help.subcommands_title", ModPartEnum.MESSAGE,
|
||||
"Subcommands:",
|
||||
"子命令:",
|
||||
"子指令:",
|
||||
"子令:", // 文言文:子命令
|
||||
true
|
||||
)
|
||||
);
|
||||
|
||||
/**
|
||||
* The constant HELP_NODE_EXPAND.
|
||||
*/
|
||||
public static final LangKeyValue HELP_NODE_EXPAND = addAndRet(
|
||||
LangKeyValue.ofKey(
|
||||
"commands.lib39.help.node.expand", ModPartEnum.MESSAGE,
|
||||
"%d subcommands collapsed",
|
||||
"%d 个子命令已折叠",
|
||||
"%d 個子指令已折疊",
|
||||
"%d 子令已收", // 文言文:子命令已經收起
|
||||
true
|
||||
)
|
||||
);
|
||||
|
||||
/**
|
||||
* The constant HELP_NODE_TOGGLE_EXPAND.
|
||||
*/
|
||||
public static final LangKeyValue HELP_NODE_TOGGLE_EXPAND = addAndRet(
|
||||
LangKeyValue.ofKey(
|
||||
"commands.lib39.help.node.toggle.expand", ModPartEnum.MESSAGE,
|
||||
"Expand",
|
||||
"展开",
|
||||
"展開",
|
||||
"展", // 文言文:展開
|
||||
true
|
||||
)
|
||||
);
|
||||
|
||||
/**
|
||||
* The constant HELP_NODE_TOGGLE_COLLAPSE.
|
||||
*/
|
||||
public static final LangKeyValue HELP_NODE_TOGGLE_COLLAPSE = addAndRet(
|
||||
LangKeyValue.ofKey(
|
||||
"commands.lib39.help.node.toggle.collapse", ModPartEnum.MESSAGE,
|
||||
"Collapse",
|
||||
"折叠",
|
||||
"折疊",
|
||||
"收", // 文言文:收起
|
||||
true
|
||||
)
|
||||
);
|
||||
|
||||
/**
|
||||
* The constant BASIC_HELP.
|
||||
*/
|
||||
public static final LangKeyValue BASIC_HELP = addAndRet(
|
||||
LangKeyValue.ofKey(
|
||||
"commands.lib39.help.basic.help", ModPartEnum.MESSAGE,
|
||||
"Show Help Info",
|
||||
"显示帮助信息",
|
||||
"顯示幫助信息",
|
||||
"示助之訊", // 文言文:顯示幫助的訊息
|
||||
true
|
||||
)
|
||||
);
|
||||
|
||||
/**
|
||||
* The constant HELP_HOVER_COPY_TIP.
|
||||
*/
|
||||
public static final LangKeyValue HELP_HOVER_COPY_TIP = addAndRet(
|
||||
LangKeyValue.ofKey(
|
||||
"commands.lib39.help.hover.copy", ModPartEnum.MESSAGE,
|
||||
"Copy to clipboard",
|
||||
"点击复制",
|
||||
"點擊複製",
|
||||
"點之複刻", // 文言文:點之複刻
|
||||
true
|
||||
)
|
||||
);
|
||||
private static LangKeyValue addAndRet(LangKeyValue item) {
|
||||
items.add(item);
|
||||
return item;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets items.
|
||||
*
|
||||
* @return the items
|
||||
*/
|
||||
public static Set<LangKeyValue> getItems() {
|
||||
return items;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The Lang key values.
|
||||
*/
|
||||
final List<LangKeyValue> langKeyValues = new ArrayList<>();
|
||||
|
||||
|
||||
/**
|
||||
* Init lang key values.
|
||||
*/
|
||||
public void initLangKeyValues() {
|
||||
Message.getItems().forEach(this::addLang);
|
||||
LangKeyValue dollName = LangKeyValue.ofSupplier(
|
||||
Lib39Items.DOLL, ModPartEnum.ITEM,
|
||||
"Doll", "人偶", "人偶", "偶", false
|
||||
);
|
||||
addLang(dollName);
|
||||
addLang(LangKeyValue.copyOf(
|
||||
Lib39Blocks.DOLL, ModPartEnum.BLOCK, dollName
|
||||
));
|
||||
addLang(LangKeyValue.ofKey(
|
||||
"tooltip.lib39.content.doll.hover.1", ModPartEnum.DESCRIPTION,
|
||||
"§eSkinOwner §7:§a %s ", "§e皮肤所有者§7:§a%s", "§e皮膚所有者§7:§a%s", "§e膚主§7:§a%s"
|
||||
));
|
||||
addLang(LangKeyValue.ofKey(
|
||||
"tooltip.lib39.content.doll.hover.2", ModPartEnum.DESCRIPTION,
|
||||
"§7Rename with a player name in an anvil to change skin",
|
||||
"§7在铁砧上可通过重命名对应玩家名来改变皮肤", "§7在鐵砧上可通過重命名對應玩家名來改變皮膚", "§7鐵砧之上,更名以易膚"
|
||||
));
|
||||
addLang(LangKeyValue.ofKey(
|
||||
"invalid.player_name.too_long", ModPartEnum.DESCRIPTION,
|
||||
"§c§lPlayer 's Name is too long than 16 characters.",
|
||||
"§c§l玩家名称过长(最多16个字符)", "§c§l玩家名稱過長(最多16個字符)", "§c§l玩家名過長,限十六字"
|
||||
));
|
||||
if (Lib39.shouldRegisterExamples()) {
|
||||
addLang(LangKeyValue.ofSupplier(
|
||||
ExLib39Items.FABRIC, ModPartEnum.ITEM,
|
||||
"Fabric", "织布", "織布", "織", true
|
||||
));
|
||||
addLang(LangKeyValue.ofSupplier(
|
||||
ExLib39Items.NEOFORGE, ModPartEnum.ITEM,
|
||||
"NeoForge", "小狐狸", "狐狸", "狸", true
|
||||
));
|
||||
addLang(LangKeyValue.ofSupplier(
|
||||
ExLib39Items.FORGE, ModPartEnum.ITEM,
|
||||
"Forge", "铁砧", "铁砧", "砧", true
|
||||
));
|
||||
TestMessage.getItems().forEach(this::addLang);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Add lang.
|
||||
*
|
||||
* @param keyValue the key value
|
||||
*/
|
||||
public void addLang(LangKeyValue keyValue) {
|
||||
langKeyValues.add(keyValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear.
|
||||
*/
|
||||
public void clear() {
|
||||
langKeyValues.clear();
|
||||
}
|
||||
|
||||
|
||||
@Contract(pure = true)
|
||||
@Override
|
||||
public @Unmodifiable List<LangKeyValue> getValues() {
|
||||
return List.copyOf(langKeyValues);
|
||||
}
|
||||
|
||||
/**
|
||||
* The type Test message.
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public static final class TestMessage {
|
||||
private static final Set<LangKeyValue> items = new HashSet<>();
|
||||
|
||||
// ===== lib39 測試命令翻譯 =====
|
||||
|
||||
/**
|
||||
* The constant LIB39_ROOT.
|
||||
*/
|
||||
// 根命令
|
||||
public static final LangKeyValue LIB39_ROOT = addAndRet(
|
||||
LangKeyValue.ofKey(
|
||||
"commands.lib39.root", ModPartEnum.MESSAGE,
|
||||
"Lib39 Command System",
|
||||
"Lib39 命令系統",
|
||||
"Lib39 指令系統",
|
||||
"Lib39 令系",
|
||||
true
|
||||
)
|
||||
);
|
||||
|
||||
/**
|
||||
* The constant LIB39_TEST.
|
||||
*/
|
||||
// 測試命令
|
||||
public static final LangKeyValue LIB39_TEST = addAndRet(
|
||||
LangKeyValue.ofKey(
|
||||
"commands.lib39.test", ModPartEnum.MESSAGE,
|
||||
"Test command",
|
||||
"測試命令",
|
||||
"測試指令",
|
||||
"試令",
|
||||
true
|
||||
)
|
||||
);
|
||||
|
||||
/**
|
||||
* The constant LIB39_TEST_SUCCESS.
|
||||
*/
|
||||
public static final LangKeyValue LIB39_TEST_SUCCESS = addAndRet(
|
||||
LangKeyValue.ofKey(
|
||||
"commands.lib39.test.success", ModPartEnum.MESSAGE,
|
||||
"Test command executed successfully!",
|
||||
"測試命令執行成功!",
|
||||
"測試指令執行成功!",
|
||||
"試令行成!",
|
||||
true
|
||||
)
|
||||
);
|
||||
|
||||
/**
|
||||
* The constant LIB39_TEST_WITH_PARAM.
|
||||
*/
|
||||
public static final LangKeyValue LIB39_TEST_WITH_PARAM = addAndRet(
|
||||
LangKeyValue.ofKey(
|
||||
"commands.lib39.test.with_param", ModPartEnum.MESSAGE,
|
||||
"Test command with parameter: %s",
|
||||
"帶參數的測試命令:%s",
|
||||
"帶參數的測試指令:%s",
|
||||
"帶參試令:%s",
|
||||
true
|
||||
)
|
||||
);
|
||||
|
||||
/**
|
||||
* The constant LIB39_DEMO.
|
||||
*/
|
||||
public static final LangKeyValue LIB39_DEMO = addAndRet(
|
||||
LangKeyValue.ofKey(
|
||||
"commands.lib39.demo", ModPartEnum.MESSAGE,
|
||||
"Demo command",
|
||||
"演示命令",
|
||||
"演示指令",
|
||||
"演令",
|
||||
true
|
||||
)
|
||||
);
|
||||
|
||||
/**
|
||||
* The constant LIB39_DEMO_MESSAGE.
|
||||
*/
|
||||
public static final LangKeyValue LIB39_DEMO_MESSAGE = addAndRet(
|
||||
LangKeyValue.ofKey(
|
||||
"commands.lib39.demo.message", ModPartEnum.MESSAGE,
|
||||
"This is a demo command showing Lib39 features!",
|
||||
"這是一個展示 Lib39 功能的演示命令!",
|
||||
"這是一個展示 Lib39 功能的演示指令!",
|
||||
"此乃展 Lib39 能之演令!",
|
||||
true
|
||||
)
|
||||
);
|
||||
|
||||
/**
|
||||
* The constant LIB39_GREET_BASIC.
|
||||
*/
|
||||
// 問候命令
|
||||
public static final LangKeyValue LIB39_GREET_BASIC = addAndRet(
|
||||
LangKeyValue.ofKey(
|
||||
"commands.lib39.greet.basic", ModPartEnum.MESSAGE,
|
||||
"Greet everyone",
|
||||
"向大家問好",
|
||||
"向大家問好",
|
||||
"問眾安",
|
||||
true
|
||||
)
|
||||
);
|
||||
|
||||
/**
|
||||
* The constant LIB39_GREET_DEFAULT.
|
||||
*/
|
||||
public static final LangKeyValue LIB39_GREET_DEFAULT = addAndRet(
|
||||
LangKeyValue.ofKey(
|
||||
"commands.lib39.greet.default", ModPartEnum.MESSAGE,
|
||||
"Hello everyone from Lib39!",
|
||||
"來自 Lib39 的問候!",
|
||||
"來自 Lib39 的問候!",
|
||||
"自 Lib39 問安!",
|
||||
true
|
||||
)
|
||||
);
|
||||
|
||||
/**
|
||||
* The constant LIB39_GREET_PLAYER.
|
||||
*/
|
||||
public static final LangKeyValue LIB39_GREET_PLAYER = addAndRet(
|
||||
LangKeyValue.ofKey(
|
||||
"commands.lib39.greet.player", ModPartEnum.MESSAGE,
|
||||
"Greet specific player",
|
||||
"問候特定玩家",
|
||||
"問候特定玩家",
|
||||
"問特者安",
|
||||
true
|
||||
)
|
||||
);
|
||||
|
||||
/**
|
||||
* The constant LIB39_GREET_RECEIVED.
|
||||
*/
|
||||
public static final LangKeyValue LIB39_GREET_RECEIVED = addAndRet(
|
||||
LangKeyValue.ofKey(
|
||||
"commands.lib39.greet.received", ModPartEnum.MESSAGE,
|
||||
"%s greeted you!",
|
||||
"%s 向你問好!",
|
||||
"%s 向你問好!",
|
||||
"%s 問汝安!",
|
||||
true
|
||||
)
|
||||
);
|
||||
|
||||
/**
|
||||
* The constant LIB39_CALCULATE.
|
||||
*/
|
||||
// 計算命令
|
||||
public static final LangKeyValue LIB39_CALCULATE = addAndRet(
|
||||
LangKeyValue.ofKey(
|
||||
"commands.lib39.calculate", ModPartEnum.MESSAGE,
|
||||
"Calculate sum of two numbers",
|
||||
"計算兩個數字的和",
|
||||
"計算兩個數字的和",
|
||||
"算二數和",
|
||||
true
|
||||
)
|
||||
);
|
||||
|
||||
/**
|
||||
* The constant LIB39_CALCULATE_RESULT.
|
||||
*/
|
||||
public static final LangKeyValue LIB39_CALCULATE_RESULT = addAndRet(
|
||||
LangKeyValue.ofKey(
|
||||
"commands.lib39.calculate.result", ModPartEnum.MESSAGE,
|
||||
"%d + %d = %d",
|
||||
"%d + %d = %d",
|
||||
"%d + %d = %d",
|
||||
"%d 加 %d 等 %d",
|
||||
true
|
||||
)
|
||||
);
|
||||
|
||||
/**
|
||||
* The constant LIB39_TELEPORT.
|
||||
*/
|
||||
// 傳送命令
|
||||
public static final LangKeyValue LIB39_TELEPORT = addAndRet(
|
||||
LangKeyValue.ofKey(
|
||||
"commands.lib39.teleport", ModPartEnum.MESSAGE,
|
||||
"Teleport to player (OP only)",
|
||||
"傳送到玩家(僅OP)",
|
||||
"傳送到玩家(僅OP)",
|
||||
"送至者(唯管)",
|
||||
true
|
||||
)
|
||||
);
|
||||
|
||||
/**
|
||||
* The constant LIB39_TELEPORT_SUCCESS.
|
||||
*/
|
||||
public static final LangKeyValue LIB39_TELEPORT_SUCCESS = addAndRet(
|
||||
LangKeyValue.ofKey(
|
||||
"commands.lib39.teleport.success", ModPartEnum.MESSAGE,
|
||||
"Teleported to %s",
|
||||
"已傳送至 %s",
|
||||
"已傳送至 %s",
|
||||
"已送至 %s",
|
||||
true
|
||||
)
|
||||
);
|
||||
|
||||
/**
|
||||
* The constant LIB39_INFO.
|
||||
*/
|
||||
// 信息命令
|
||||
public static final LangKeyValue LIB39_INFO = addAndRet(
|
||||
LangKeyValue.ofKey(
|
||||
"commands.lib39.info", ModPartEnum.MESSAGE,
|
||||
"Show player information",
|
||||
"顯示玩家信息",
|
||||
"顯示玩家資訊",
|
||||
"示者訊",
|
||||
true
|
||||
)
|
||||
);
|
||||
|
||||
/**
|
||||
* The constant LIB39_INFO_MESSAGE.
|
||||
*/
|
||||
public static final LangKeyValue LIB39_INFO_MESSAGE = addAndRet(
|
||||
LangKeyValue.ofKey(
|
||||
"commands.lib39.info.message", ModPartEnum.MESSAGE,
|
||||
"=== Player Information ===",
|
||||
"=== 玩家信息 ===",
|
||||
"=== 玩家資訊 ===",
|
||||
"〇〇 者訊 〇〇",
|
||||
true
|
||||
)
|
||||
);
|
||||
|
||||
/**
|
||||
* The constant LIB39_INFO_DIMENSION.
|
||||
*/
|
||||
public static final LangKeyValue LIB39_INFO_DIMENSION = addAndRet(
|
||||
LangKeyValue.ofKey(
|
||||
"commands.lib39.info.dimension", ModPartEnum.MESSAGE,
|
||||
"Dimension: %s",
|
||||
"維度:%s",
|
||||
"維度:%s",
|
||||
"界:%s",
|
||||
true
|
||||
)
|
||||
);
|
||||
|
||||
/**
|
||||
* The constant LIB39_INFO_POSITION.
|
||||
*/
|
||||
public static final LangKeyValue LIB39_INFO_POSITION = addAndRet(
|
||||
LangKeyValue.ofKey(
|
||||
"commands.lib39.info.position", ModPartEnum.MESSAGE,
|
||||
"Position: X=%.1f, Y=%.1f, Z=%.1f",
|
||||
"位置:X=%.1f, Y=%.1f, Z=%.1f",
|
||||
"位置:X=%.1f, Y=%.1f, Z=%.1f",
|
||||
"位:X=%.1f, Y=%.1f, Z=%.1f",
|
||||
true
|
||||
)
|
||||
);
|
||||
|
||||
/**
|
||||
* The constant LIB39_TEAM.
|
||||
*/
|
||||
// 隊伍系統
|
||||
public static final LangKeyValue LIB39_TEAM = addAndRet(
|
||||
LangKeyValue.ofKey(
|
||||
"commands.lib39.team", ModPartEnum.MESSAGE,
|
||||
"Team management",
|
||||
"隊伍管理",
|
||||
"隊伍管理",
|
||||
"隊管",
|
||||
true
|
||||
)
|
||||
);
|
||||
|
||||
/**
|
||||
* The constant LIB39_TEAM_CREATE.
|
||||
*/
|
||||
public static final LangKeyValue LIB39_TEAM_CREATE = addAndRet(
|
||||
LangKeyValue.ofKey(
|
||||
"commands.lib39.team.create", ModPartEnum.MESSAGE,
|
||||
"Create a new team",
|
||||
"創建新隊伍",
|
||||
"創建新隊伍",
|
||||
"創新隊",
|
||||
true
|
||||
)
|
||||
);
|
||||
|
||||
/**
|
||||
* The constant LIB39_TEAM_CREATE_SUCCESS.
|
||||
*/
|
||||
public static final LangKeyValue LIB39_TEAM_CREATE_SUCCESS = addAndRet(
|
||||
LangKeyValue.ofKey(
|
||||
"commands.lib39.team.create.success", ModPartEnum.MESSAGE,
|
||||
"Team '%s' created successfully!",
|
||||
"隊伍 '%s' 創建成功!",
|
||||
"隊伍 '%s' 創建成功!",
|
||||
"隊 '%s' 創新成!",
|
||||
true
|
||||
)
|
||||
);
|
||||
|
||||
/**
|
||||
* The constant LIB39_TEAM_JOIN.
|
||||
*/
|
||||
public static final LangKeyValue LIB39_TEAM_JOIN = addAndRet(
|
||||
LangKeyValue.ofKey(
|
||||
"commands.lib39.team.join", ModPartEnum.MESSAGE,
|
||||
"Join a team",
|
||||
"加入隊伍",
|
||||
"加入隊伍",
|
||||
"入隊",
|
||||
true
|
||||
)
|
||||
);
|
||||
|
||||
/**
|
||||
* The constant LIB39_TEAM_JOIN_SUCCESS.
|
||||
*/
|
||||
public static final LangKeyValue LIB39_TEAM_JOIN_SUCCESS = addAndRet(
|
||||
LangKeyValue.ofKey(
|
||||
"commands.lib39.team.join.success", ModPartEnum.MESSAGE,
|
||||
"Joined team '%s'",
|
||||
"已加入隊伍 '%s'",
|
||||
"已加入隊伍 '%s'",
|
||||
"已入隊 '%s'",
|
||||
true
|
||||
)
|
||||
);
|
||||
|
||||
/**
|
||||
* The constant LIB39_TEAM_LEAVE.
|
||||
*/
|
||||
public static final LangKeyValue LIB39_TEAM_LEAVE = addAndRet(
|
||||
LangKeyValue.ofKey(
|
||||
"commands.lib39.team.leave", ModPartEnum.MESSAGE,
|
||||
"Leave current team",
|
||||
"離開當前隊伍",
|
||||
"離開當前隊伍",
|
||||
"離現隊",
|
||||
true
|
||||
)
|
||||
);
|
||||
|
||||
/**
|
||||
* The constant LIB39_TEAM_LEAVE_SUCCESS.
|
||||
*/
|
||||
public static final LangKeyValue LIB39_TEAM_LEAVE_SUCCESS = addAndRet(
|
||||
LangKeyValue.ofKey(
|
||||
"commands.lib39.team.leave.success", ModPartEnum.MESSAGE,
|
||||
"Left the team",
|
||||
"已離開隊伍",
|
||||
"已離開隊伍",
|
||||
"已離隊",
|
||||
true
|
||||
)
|
||||
);
|
||||
|
||||
/**
|
||||
* The constant LIB39_GAME.
|
||||
*/
|
||||
// 遊戲系統
|
||||
public static final LangKeyValue LIB39_GAME = addAndRet(
|
||||
LangKeyValue.ofKey(
|
||||
"commands.lib39.game", ModPartEnum.MESSAGE,
|
||||
"Game control",
|
||||
"遊戲控制",
|
||||
"遊戲控制",
|
||||
"戲控",
|
||||
true
|
||||
)
|
||||
);
|
||||
|
||||
/**
|
||||
* The constant LIB39_GAME_START.
|
||||
*/
|
||||
public static final LangKeyValue LIB39_GAME_START = addAndRet(
|
||||
LangKeyValue.ofKey(
|
||||
"commands.lib39.game.start", ModPartEnum.MESSAGE,
|
||||
"Start a game",
|
||||
"開始遊戲",
|
||||
"開始遊戲",
|
||||
"啟戲",
|
||||
true
|
||||
)
|
||||
);
|
||||
|
||||
/**
|
||||
* The constant LIB39_GAME_START_SUCCESS.
|
||||
*/
|
||||
public static final LangKeyValue LIB39_GAME_START_SUCCESS = addAndRet(
|
||||
LangKeyValue.ofKey(
|
||||
"commands.lib39.game.start.success", ModPartEnum.MESSAGE,
|
||||
"Game '%s' started!",
|
||||
"遊戲 '%s' 已開始!",
|
||||
"遊戲 '%s' 已開始!",
|
||||
"戲 '%s' 已啟!",
|
||||
true
|
||||
)
|
||||
);
|
||||
|
||||
/**
|
||||
* The constant LIB39_GAME_STOP.
|
||||
*/
|
||||
public static final LangKeyValue LIB39_GAME_STOP = addAndRet(
|
||||
LangKeyValue.ofKey(
|
||||
"commands.lib39.game.stop", ModPartEnum.MESSAGE,
|
||||
"Stop current game",
|
||||
"停止當前遊戲",
|
||||
"停止當前遊戲",
|
||||
"止現戲",
|
||||
true
|
||||
)
|
||||
);
|
||||
|
||||
/**
|
||||
* The constant LIB39_GAME_STOP_SUCCESS.
|
||||
*/
|
||||
public static final LangKeyValue LIB39_GAME_STOP_SUCCESS = addAndRet(
|
||||
LangKeyValue.ofKey(
|
||||
"commands.lib39.game.stop.success", ModPartEnum.MESSAGE,
|
||||
"Game stopped!",
|
||||
"遊戲已停止!",
|
||||
"遊戲已停止!",
|
||||
"戲已止!",
|
||||
true
|
||||
)
|
||||
);
|
||||
|
||||
/**
|
||||
* The constant LIB39_GAME_PAUSE.
|
||||
*/
|
||||
public static final LangKeyValue LIB39_GAME_PAUSE = addAndRet(
|
||||
LangKeyValue.ofKey(
|
||||
"commands.lib39.game.pause", ModPartEnum.MESSAGE,
|
||||
"Pause current game",
|
||||
"暫停當前遊戲",
|
||||
"暫停當前遊戲",
|
||||
"暫現戲",
|
||||
true
|
||||
)
|
||||
);
|
||||
|
||||
/**
|
||||
* The constant LIB39_GAME_PAUSE_SUCCESS.
|
||||
*/
|
||||
public static final LangKeyValue LIB39_GAME_PAUSE_SUCCESS = addAndRet(
|
||||
LangKeyValue.ofKey(
|
||||
"commands.lib39.game.pause.success", ModPartEnum.MESSAGE,
|
||||
"Game paused!",
|
||||
"遊戲已暫停!",
|
||||
"遊戲已暫停!",
|
||||
"戲已暫!",
|
||||
true
|
||||
)
|
||||
);
|
||||
|
||||
/**
|
||||
* The constant LIB39_GAME_RESUME.
|
||||
*/
|
||||
public static final LangKeyValue LIB39_GAME_RESUME = addAndRet(
|
||||
LangKeyValue.ofKey(
|
||||
"commands.lib39.game.resume", ModPartEnum.MESSAGE,
|
||||
"Resume paused game",
|
||||
"恢復暫停的遊戲",
|
||||
"恢復暫停的遊戲",
|
||||
"復暫戲",
|
||||
true
|
||||
)
|
||||
);
|
||||
|
||||
/**
|
||||
* The constant LIB39_GAME_RESUME_SUCCESS.
|
||||
*/
|
||||
public static final LangKeyValue LIB39_GAME_RESUME_SUCCESS = addAndRet(
|
||||
LangKeyValue.ofKey(
|
||||
"commands.lib39.game.resume.success", ModPartEnum.MESSAGE,
|
||||
"Game resumed!",
|
||||
"遊戲已恢復!",
|
||||
"遊戲已恢復!",
|
||||
"戲已復!",
|
||||
true
|
||||
)
|
||||
);
|
||||
|
||||
/**
|
||||
* The constant LIB39_SETTINGS.
|
||||
*/
|
||||
// 設置命令
|
||||
public static final LangKeyValue LIB39_SETTINGS = addAndRet(
|
||||
LangKeyValue.ofKey(
|
||||
"commands.lib39.settings", ModPartEnum.MESSAGE,
|
||||
"Show settings",
|
||||
"顯示設置",
|
||||
"顯示設定",
|
||||
"示置",
|
||||
true
|
||||
)
|
||||
);
|
||||
|
||||
/**
|
||||
* The constant LIB39_CONFIG.
|
||||
*/
|
||||
public static final LangKeyValue LIB39_CONFIG = addAndRet(
|
||||
LangKeyValue.ofKey(
|
||||
"commands.lib39.config", ModPartEnum.MESSAGE,
|
||||
"Show configuration",
|
||||
"顯示配置",
|
||||
"顯示設定",
|
||||
"示配",
|
||||
true
|
||||
)
|
||||
);
|
||||
|
||||
/**
|
||||
* The constant LIB39_RELOAD.
|
||||
*/
|
||||
public static final LangKeyValue LIB39_RELOAD = addAndRet(
|
||||
LangKeyValue.ofKey(
|
||||
"commands.lib39.reload", ModPartEnum.MESSAGE,
|
||||
"Reload configuration",
|
||||
"重新加載配置",
|
||||
"重新載入設定",
|
||||
"重載配",
|
||||
true
|
||||
)
|
||||
);
|
||||
|
||||
/**
|
||||
* The constant LIB39_DEBUG.
|
||||
*/
|
||||
public static final LangKeyValue LIB39_DEBUG = addAndRet(
|
||||
LangKeyValue.ofKey(
|
||||
"commands.lib39.debug", ModPartEnum.MESSAGE,
|
||||
"Debug information",
|
||||
"調試信息",
|
||||
"除錯資訊",
|
||||
"調訊",
|
||||
true
|
||||
)
|
||||
);
|
||||
|
||||
// ===== 添加缺失的導入 =====
|
||||
private static final java.util.function.Consumer<LangKeyValue> addConsumer = items::add;
|
||||
|
||||
private static LangKeyValue addAndRet(LangKeyValue item) {
|
||||
items.add(item);
|
||||
return item;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets items.
|
||||
*
|
||||
* @return the items
|
||||
*/
|
||||
public static Set<LangKeyValue> getItems() {
|
||||
return items;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,769 +0,0 @@
|
|||
package top.r3944realms.lib39.client.gui.component;
|
||||
|
||||
import com.mojang.blaze3d.platform.Window;
|
||||
import com.mojang.blaze3d.systems.RenderSystem;
|
||||
import com.mojang.blaze3d.vertex.*;
|
||||
import net.minecraft.MethodsReturnNonnullByDefault;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.GuiGraphics;
|
||||
import net.minecraft.client.gui.components.AbstractWidget;
|
||||
import net.minecraft.client.gui.narration.NarrationElementOutput;
|
||||
import net.minecraft.client.renderer.ShaderInstance;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import org.joml.Matrix4f;
|
||||
import org.joml.Vector2f;
|
||||
import top.r3944realms.lib39.client.shader.Lib39Shaders;
|
||||
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.
|
||||
*/
|
||||
public static final int IGNORE_CURSOR_MOVE_LENGTH = 15;
|
||||
private static final Vector2f ROTATION_START = new Vector2f(0, 1);
|
||||
private static final int SELECTION_EFFECT_COLOR = 0xddFFFF00;
|
||||
private static final int SELECTION_EFFECT_RADIUS = 20;
|
||||
|
||||
private final Minecraft minecraft = Minecraft.getInstance();
|
||||
private final Vector2f centerPos;
|
||||
private final float ringInnerRadius;
|
||||
private final float ringOuterRadius;
|
||||
private final int delay;
|
||||
private final int animationMs;
|
||||
private final int closingAnimationMs; //ms
|
||||
private final int ringColor;
|
||||
private final int selectionEffectColor;
|
||||
private final int selectionEffectRadius;
|
||||
private final float selectionAnimationSpeedFactor;
|
||||
private final int textColor;
|
||||
private final float textScale;
|
||||
private final List<WheelSection> sections = new ArrayList<>();
|
||||
|
||||
private long displayTime = System.currentTimeMillis();
|
||||
private float currentAngle = 0;
|
||||
|
||||
/**
|
||||
* Gets current section index.
|
||||
*
|
||||
* @return the current section index
|
||||
*/
|
||||
public int getCurrentSectionIndex() {
|
||||
return currentSectionIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
* Is closing animation started boolean.
|
||||
*
|
||||
* @return the boolean
|
||||
*/
|
||||
public boolean isClosingAnimationStarted() {
|
||||
return closingAnimationStarted;
|
||||
}
|
||||
|
||||
private int currentSectionIndex = -1;
|
||||
private Vector2f selectionEffectPos;
|
||||
private boolean animationStarted = false;
|
||||
|
||||
/**
|
||||
* Sets closing animation started.
|
||||
*
|
||||
* @param closingAnimationStarted the closing animation started
|
||||
*/
|
||||
public void setClosingAnimationStarted(boolean closingAnimationStarted) {
|
||||
this.closingAnimationStarted = closingAnimationStarted;
|
||||
}
|
||||
|
||||
private boolean closingAnimationStarted = false;
|
||||
|
||||
/**
|
||||
* Instantiates a new Wheel widget.
|
||||
*
|
||||
* @param x the x
|
||||
* @param y the y
|
||||
* @param width the width
|
||||
* @param height the height
|
||||
* @param ringInnerRadius the ring inner radius
|
||||
* @param ringOuterRadius the ring outer radius
|
||||
* @param textScale the text scale
|
||||
* @param sections the sections
|
||||
*/
|
||||
public WheelWidget(
|
||||
int x, int y, int width, int height,
|
||||
float ringInnerRadius, float ringOuterRadius, float textScale,
|
||||
List<Pair<Component, FourConsumer<GuiGraphics, PoseStack, Integer, Integer>>> sections
|
||||
) {
|
||||
this(x, y, width, height, Component.empty(), ringInnerRadius, ringOuterRadius, textScale, sections);
|
||||
}
|
||||
|
||||
/**
|
||||
* Instantiates a new Wheel widget.
|
||||
*
|
||||
* @param x the x
|
||||
* @param y the y
|
||||
* @param width the width
|
||||
* @param height the height
|
||||
* @param ringInnerRadius the ring inner radius
|
||||
* @param ringOuterRadius the ring outer radius
|
||||
* @param textScale the text scale
|
||||
* @param degreeOffsetAngle the degree offset angle
|
||||
* @param sections the sections
|
||||
*/
|
||||
public WheelWidget(
|
||||
int x, int y, int width, int height,
|
||||
float ringInnerRadius, float ringOuterRadius, float textScale, float degreeOffsetAngle,
|
||||
List<Pair<Component, FourConsumer<GuiGraphics, PoseStack, Integer, Integer>>> sections
|
||||
) {
|
||||
this(x, y, width, height, Component.empty(), ringInnerRadius, ringOuterRadius, textScale, degreeOffsetAngle, sections);
|
||||
}
|
||||
|
||||
/**
|
||||
* Instantiates a new Wheel widget.
|
||||
*
|
||||
* @param x the x
|
||||
* @param y the y
|
||||
* @param width the width
|
||||
* @param height the height
|
||||
* @param ringInnerRadius the ring inner radius
|
||||
* @param ringOuterRadius the ring outer radius
|
||||
* @param sections the sections
|
||||
*/
|
||||
public WheelWidget(
|
||||
int x, int y, int width, int height,
|
||||
float ringInnerRadius, float ringOuterRadius,
|
||||
List<Pair<Component, FourConsumer<GuiGraphics, PoseStack, Integer, Integer>>> sections
|
||||
) {
|
||||
this(x, y, width, height, Component.empty(), ringInnerRadius, ringOuterRadius, sections);
|
||||
}
|
||||
|
||||
/**
|
||||
* Instantiates a new Wheel widget.
|
||||
*
|
||||
* @param x the x
|
||||
* @param y the y
|
||||
* @param width the width
|
||||
* @param height the height
|
||||
* @param message the message
|
||||
* @param ringInnerRadius the ring inner radius
|
||||
* @param ringOuterRadius the ring outer radius
|
||||
* @param textScale the text scale
|
||||
* @param degreeOffsetAngle the degree offset angle
|
||||
* @param sections the sections
|
||||
*/
|
||||
public WheelWidget(
|
||||
int x, int y, int width, int height, Component message,
|
||||
float ringInnerRadius, float ringOuterRadius, float textScale, float degreeOffsetAngle,
|
||||
List<Pair<Component, FourConsumer<GuiGraphics, PoseStack, Integer, Integer>>> sections
|
||||
) {
|
||||
this(
|
||||
x, y, width, height, message,
|
||||
ringInnerRadius, ringOuterRadius,
|
||||
150, 300, 150,
|
||||
0x00000000,
|
||||
0xddffff00, 20, 5f,
|
||||
0xfdfdfd, textScale, degreeOffsetAngle,
|
||||
sections
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Instantiates a new Wheel widget.
|
||||
*
|
||||
* @param x the x
|
||||
* @param y the y
|
||||
* @param width the width
|
||||
* @param height the height
|
||||
* @param message the message
|
||||
* @param ringInnerRadius the ring inner radius
|
||||
* @param ringOuterRadius the ring outer radius
|
||||
* @param sections the sections
|
||||
*/
|
||||
public WheelWidget(
|
||||
int x, int y, int width, int height, Component message,
|
||||
float ringInnerRadius, float ringOuterRadius,
|
||||
List<Pair<Component, FourConsumer<GuiGraphics, PoseStack, Integer, Integer>>> sections
|
||||
) {
|
||||
this(
|
||||
x, y, width, height, message,
|
||||
ringInnerRadius, ringOuterRadius,
|
||||
150, 300, 150,
|
||||
0x00000000,
|
||||
0xddffff00, 20, 5f,
|
||||
0xfdfdfd, 1f, 0f,
|
||||
sections
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Instantiates a new Wheel widget.
|
||||
*
|
||||
* @param x the x
|
||||
* @param y the y
|
||||
* @param width the width
|
||||
* @param height the height
|
||||
* @param message the message
|
||||
* @param ringInnerRadius the ring inner radius
|
||||
* @param ringOuterRadius the ring outer radius
|
||||
* @param degreeOffsetAngle the degree offset angle
|
||||
* @param sections the sections
|
||||
*/
|
||||
public WheelWidget(
|
||||
int x, int y, int width, int height, Component message,
|
||||
float ringInnerRadius, float ringOuterRadius, float degreeOffsetAngle,
|
||||
List<Pair<Component, FourConsumer<GuiGraphics, PoseStack, Integer, Integer>>> sections
|
||||
) {
|
||||
this(
|
||||
x, y, width, height, message,
|
||||
ringInnerRadius, ringOuterRadius,
|
||||
150, 300, 150,
|
||||
0x00000000,
|
||||
0xddffff00, 20, 5f,
|
||||
0xfdfdfd, 1f, degreeOffsetAngle,
|
||||
sections
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Instantiates a new Wheel widget.
|
||||
*
|
||||
* @param x the x
|
||||
* @param y the y
|
||||
* @param width the width
|
||||
* @param height the height
|
||||
* @param ringInnerRadius the ring inner radius
|
||||
* @param ringOuterRadius the ring outer radius
|
||||
* @param delay the delay
|
||||
* @param animationMs the animation ms
|
||||
* @param closingAnimationMs the closing animation ms
|
||||
* @param ringColor the ring color
|
||||
* @param selectionEffectColor the selection effect color
|
||||
* @param selectionEffectRadius the selection effect radius
|
||||
* @param selectionAnimationSpeedFactor the selection animation speed factor
|
||||
* @param textColor the text color
|
||||
* @param textScale the text scale
|
||||
* @param sections the sections
|
||||
*/
|
||||
public WheelWidget(
|
||||
int x, int y, int width, int height,
|
||||
float ringInnerRadius, float ringOuterRadius,
|
||||
int delay, int animationMs, int closingAnimationMs,
|
||||
int ringColor,
|
||||
int selectionEffectColor, int selectionEffectRadius, float selectionAnimationSpeedFactor,
|
||||
int textColor, float textScale,
|
||||
List<Pair<Component, FourConsumer<GuiGraphics, PoseStack, Integer, Integer>>> sections
|
||||
) {
|
||||
this(
|
||||
x, y, width, height, Component.empty(),
|
||||
ringInnerRadius, ringOuterRadius,
|
||||
delay, animationMs, closingAnimationMs,
|
||||
ringColor,
|
||||
selectionEffectColor, selectionEffectRadius, selectionAnimationSpeedFactor,
|
||||
textColor, textScale, 0f,
|
||||
sections
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Instantiates a new Wheel widget.
|
||||
*
|
||||
* @param x the x
|
||||
* @param y the y
|
||||
* @param width the width
|
||||
* @param height the height
|
||||
* @param message the message
|
||||
* @param ringInnerRadius the ring inner radius
|
||||
* @param ringOuterRadius the ring outer radius
|
||||
* @param delay the delay
|
||||
* @param animationMs the animation ms
|
||||
* @param closingAnimationMs the closing animation ms
|
||||
* @param ringColor the ring color
|
||||
* @param selectionEffectColor the selection effect color
|
||||
* @param selectionEffectRadius the selection effect radius
|
||||
* @param selectionAnimationSpeedFactor the selection animation speed factor
|
||||
* @param textColor the text color
|
||||
* @param textScale the text scale
|
||||
* @param degreeOffsetAngle the degree offset angle
|
||||
* @param sections the sections
|
||||
*/
|
||||
public WheelWidget(
|
||||
int x, int y, int width, int height, Component message,
|
||||
float ringInnerRadius, float ringOuterRadius,
|
||||
int delay, int animationMs, int closingAnimationMs,
|
||||
int ringColor,
|
||||
int selectionEffectColor, int selectionEffectRadius, float selectionAnimationSpeedFactor,
|
||||
int textColor, float textScale, float degreeOffsetAngle,
|
||||
List<Pair<Component, FourConsumer<GuiGraphics, PoseStack, Integer, Integer>>> sections
|
||||
) {
|
||||
super(x, y, width, height, message);
|
||||
this.centerPos = new Vector2f(this.getX() + this.getWidth() / 2f, this.getY() + this.getHeight() / 2f);
|
||||
this.ringInnerRadius = Math.max(ringInnerRadius, IGNORE_CURSOR_MOVE_LENGTH);
|
||||
this.ringOuterRadius = ringOuterRadius;
|
||||
this.delay = delay;
|
||||
this.animationMs = animationMs;
|
||||
this.closingAnimationMs = closingAnimationMs;
|
||||
this.ringColor = ringColor;
|
||||
this.selectionEffectColor = selectionEffectColor;
|
||||
this.selectionEffectRadius = selectionEffectRadius;
|
||||
this.selectionAnimationSpeedFactor = selectionAnimationSpeedFactor;
|
||||
this.textColor = textColor;
|
||||
this.textScale = textScale;
|
||||
float degreeEachRotation = 360f / sections.size();
|
||||
for (int i = 0; i < sections.size(); i++) {
|
||||
Pair<Component, FourConsumer<GuiGraphics, PoseStack, Integer, Integer>> section = sections.get(i);
|
||||
float rotation = MathUtil.clampWithProportion((degreeEachRotation * i + degreeOffsetAngle) % 360, 0, 360);
|
||||
Vector2f rotated = MathUtil.rotationDegrees(ROTATION_START, rotation)
|
||||
.mul(1, -1)
|
||||
.mul(this.getSectionCircleDiameter())
|
||||
.add(this.centerPos);
|
||||
float detectionStart = (float) (Math.toRadians(rotation - degreeEachRotation / 2f) + Math.PI * 2);
|
||||
float detectionEnd = (float) (Math.toRadians(rotation + degreeEachRotation / 2f) + Math.PI * 2);
|
||||
detectionStart = detectionStart % (float) (Math.PI * 2);
|
||||
detectionEnd = detectionEnd % (float) (Math.PI * 2);
|
||||
this.sections.add(new WheelSection(
|
||||
rotated,
|
||||
(float) (Math.toRadians(rotation) % (Math.PI * 2)),
|
||||
detectionStart,
|
||||
detectionEnd,
|
||||
section.first,
|
||||
section.second
|
||||
));
|
||||
}
|
||||
this.selectionEffectPos = MathUtil.rotate(
|
||||
MathUtil.copy(ROTATION_START)
|
||||
.mul(this.getSectionCircleDiameter()),
|
||||
this.currentAngle
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets section circle diameter.
|
||||
*
|
||||
* @return the section circle diameter
|
||||
*/
|
||||
// 滚轮选择器中每个扇形的圆形直径
|
||||
public float getSectionCircleDiameter() {
|
||||
return this.ringOuterRadius + this.ringInnerRadius;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets current index.
|
||||
*
|
||||
* @param index the index
|
||||
* @return the current index
|
||||
*/
|
||||
public WheelWidget setCurrentIndex(int index) {
|
||||
this.currentSectionIndex = index;
|
||||
this.currentAngle = this.sections.get(index).angle;
|
||||
this.selectionEffectPos = MathUtil.rotate(
|
||||
MathUtil.copy(ROTATION_START)
|
||||
.mul(this.getSectionCircleDiameter()),
|
||||
this.currentAngle
|
||||
);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets section size.
|
||||
*
|
||||
* @return the section size
|
||||
*/
|
||||
public int getSectionSize() {
|
||||
return this.sections.size();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean mouseScrolled(double mouseX, double mouseY, double delta) {
|
||||
if (delta > 0) {
|
||||
if (this.currentSectionIndex == this.getSectionSize() - 1) {
|
||||
this.currentSectionIndex = 0;
|
||||
} else {
|
||||
this.currentSectionIndex++;
|
||||
}
|
||||
} else if (delta < 0) {
|
||||
if (this.currentSectionIndex == 0) {
|
||||
this.currentSectionIndex = this.getSectionSize() - 1;
|
||||
} else {
|
||||
this.currentSectionIndex--;
|
||||
}
|
||||
}
|
||||
for (WheelSection section : this.sections) {
|
||||
if (this.sections.indexOf(section) == this.currentSectionIndex) {
|
||||
this.currentAngle = section.angle;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check mouse pos.
|
||||
*
|
||||
* @param mouseX the mouse x
|
||||
* @param mouseY the mouse y
|
||||
*/
|
||||
public void checkMousePos(double mouseX, double mouseY) {
|
||||
if (this.closingAnimationStarted) return;
|
||||
float centerX = this.centerPos.x;
|
||||
float centerY = this.centerPos.y;
|
||||
// 鼠标距离屏幕中心的位置向量
|
||||
Vector2f cursorPos = new Vector2f((float) mouseX - centerX, (float) mouseY - centerY);
|
||||
|
||||
if (cursorPos.length() < IGNORE_CURSOR_MOVE_LENGTH) return;
|
||||
|
||||
Vector2f rotationStart = new Vector2f(0, 1);
|
||||
cursorPos.normalize();
|
||||
// 计算夹角弧度
|
||||
double rot = Math.acos(rotationStart.dot(cursorPos) / (rotationStart.length() * cursorPos.length()));
|
||||
double rotation = cursorPos.x < 0 ? Math.PI - rot : Math.PI + rot;
|
||||
for (WheelSection section : this.sections) {
|
||||
if (section.angleStart > section.angleEnd && rotation >= section.angleStart
|
||||
|| rotation >= section.angleStart && rotation <= section.angleEnd
|
||||
) {
|
||||
this.currentAngle = section.angle;
|
||||
this.currentSectionIndex = this.sections.indexOf(section);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Should render boolean.
|
||||
*
|
||||
* @return the boolean
|
||||
*/
|
||||
public boolean shouldRender() {
|
||||
if (this.animationStarted) return true;
|
||||
return (this.displayTime + this.delay) <= System.currentTimeMillis();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render(GuiGraphics guiGraphics, int mouseX, int mouseY, float partialTick) {
|
||||
this.checkMousePos(mouseX, mouseY);
|
||||
this.renderWidget(guiGraphics, mouseX, mouseY, partialTick);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderWidget(GuiGraphics guiGraphics, int i, int i1, float v) {
|
||||
RenderSystem.enableDepthTest();
|
||||
RenderSystem.enableBlend();
|
||||
this.renderClosingAnimation(guiGraphics);
|
||||
if (!this.shouldRender()) {
|
||||
return;
|
||||
}
|
||||
if (this.closingAnimationStarted) return;
|
||||
if (!this.animationStarted) {
|
||||
this.animationStarted = true;
|
||||
this.displayTime = System.currentTimeMillis();
|
||||
}
|
||||
PoseStack poseStack = guiGraphics.pose();
|
||||
float delta = this.displayTime + this.animationMs - System.currentTimeMillis();
|
||||
if (delta > 0) {
|
||||
float progress = 1 - (delta / this.animationMs);
|
||||
progress = (float) (-Math.pow(progress, 2) + 2 * progress);
|
||||
if (progress == 0) return;
|
||||
this.renderProgressAnimation(guiGraphics, progress);
|
||||
return;
|
||||
}
|
||||
renderRing(
|
||||
guiGraphics,
|
||||
this.centerPos.x,
|
||||
this.centerPos.y,
|
||||
this.ringColor,
|
||||
this.ringInnerRadius * 2,
|
||||
this.ringOuterRadius * 2
|
||||
);
|
||||
this.renderSelection(guiGraphics);
|
||||
for (WheelSection value : this.sections) {
|
||||
float x = value.center.x;
|
||||
float y = value.center.y;
|
||||
poseStack.pushPose();
|
||||
poseStack.translate(x - 10, y - 10, 100);
|
||||
value.renderer.accept(guiGraphics, poseStack, 20, 20);
|
||||
poseStack.popPose();
|
||||
poseStack.pushPose();
|
||||
float coordinateScale = 0.7f;
|
||||
float offsetX = 0.1f * this.width;
|
||||
float offsetY = 0.1f * this.height;
|
||||
float adjustedX = (x - offsetX) / coordinateScale;
|
||||
float adjustedY = (y - offsetY - 20 * this.textScale) / coordinateScale;
|
||||
|
||||
poseStack.translate(offsetX, offsetY, 0);
|
||||
poseStack.scale(coordinateScale, coordinateScale, coordinateScale);
|
||||
poseStack.translate(adjustedX, adjustedY, 0);
|
||||
poseStack.scale(this.textScale / coordinateScale, this.textScale / coordinateScale, this.textScale / coordinateScale);
|
||||
guiGraphics.drawCenteredString(
|
||||
minecraft.font,
|
||||
value.subTitle,
|
||||
0,
|
||||
0,
|
||||
(0xff << 24) | this.textColor
|
||||
);
|
||||
poseStack.popPose();
|
||||
}
|
||||
RenderSystem.disableDepthTest();
|
||||
RenderSystem.disableBlend();
|
||||
}
|
||||
|
||||
/**
|
||||
* Render closing animation.
|
||||
*
|
||||
* @param guiGraphics the gui graphics
|
||||
*/
|
||||
public void renderClosingAnimation(GuiGraphics guiGraphics) {
|
||||
if (!this.closingAnimationStarted) return;
|
||||
float delta = this.displayTime + this.closingAnimationMs - System.currentTimeMillis();
|
||||
float progress = delta / this.closingAnimationMs;
|
||||
if(progress >= 1 || progress <= 0) {
|
||||
this.minecraft.setScreen(null);
|
||||
}
|
||||
this.renderProgressAnimation(guiGraphics, progress);
|
||||
}
|
||||
private void renderProgressAnimation(GuiGraphics guiGraphics, float progress) {
|
||||
progress = (float) (-Math.pow(progress, 2) + 2 * progress);
|
||||
if (progress == 0) return;
|
||||
PoseStack poseStack = guiGraphics.pose();
|
||||
poseStack.pushPose();
|
||||
renderRing(
|
||||
guiGraphics,
|
||||
this.centerPos.x,
|
||||
this.centerPos.y,
|
||||
this.ringColor,
|
||||
this.ringInnerRadius * 2 * progress,
|
||||
this.ringOuterRadius * 2 * progress
|
||||
);
|
||||
poseStack.popPose();
|
||||
if(this.currentSectionIndex != -1) {
|
||||
WheelSection section = this.sections.get(this.currentSectionIndex);
|
||||
Vector2f center = new Vector2f(
|
||||
(section.center.x - this.centerPos.x) / this.getSectionCircleDiameter(),
|
||||
(section.center.y - this.centerPos.y) / this.getSectionCircleDiameter()
|
||||
).mul(this.getSectionCircleDiameter() * progress).add(this.centerPos.x, this.centerPos.y);
|
||||
renderSelectionEffect(
|
||||
guiGraphics,
|
||||
center.x,
|
||||
center.y,
|
||||
this.selectionEffectColor,
|
||||
this.selectionEffectRadius
|
||||
);
|
||||
}
|
||||
for (WheelSection value : this.sections) {
|
||||
if (sections.get(0) != value) continue;
|
||||
Vector2f center = new Vector2f(
|
||||
(value.center.x - this.centerPos.x) / this.getSectionCircleDiameter(),
|
||||
(value.center.y - this.centerPos.y) / this.getSectionCircleDiameter()
|
||||
).mul(this.getSectionCircleDiameter() * progress).add(this.centerPos.x, this.centerPos.y);
|
||||
float x = center.x;
|
||||
float y = center.y;
|
||||
poseStack.pushPose();
|
||||
poseStack.translate(x - 10, y - 10, 100);
|
||||
value.renderer.accept(guiGraphics, poseStack, 20, 20);
|
||||
poseStack.pushPose();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Render ring.
|
||||
*
|
||||
* @param guiGraphics the gui graphics
|
||||
* @param centerX the center x
|
||||
* @param centerY the center y
|
||||
* @param color the color
|
||||
* @param innerRadius the inner radius
|
||||
* @param outerRadius the outer radius
|
||||
*/
|
||||
public static void renderRing(
|
||||
GuiGraphics guiGraphics,
|
||||
float centerX,
|
||||
float centerY,
|
||||
int color,
|
||||
float innerRadius, // 改为半径
|
||||
float outerRadius // 改为半径
|
||||
) {
|
||||
PoseStack poseStack = guiGraphics.pose();
|
||||
poseStack.pushPose();
|
||||
|
||||
Tesselator tesselator = Tesselator.getInstance();
|
||||
BufferBuilder buffer = tesselator.getBuilder();
|
||||
|
||||
// 计算足够大的绘制区域来覆盖整个环形(基于外半径)
|
||||
float margin = outerRadius + 100f; // 使用半径计算边距
|
||||
float x1 = centerX - margin;
|
||||
float y1 = centerY - margin;
|
||||
float x2 = centerX + margin;
|
||||
float y2 = centerY + margin;
|
||||
|
||||
buffer.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION_COLOR);
|
||||
|
||||
Matrix4f matrix = poseStack.last().pose();
|
||||
buffer.vertex(matrix, x1, y1, -300).color(color).endVertex();
|
||||
buffer.vertex(matrix, x1, y2, -300).color(color).endVertex();
|
||||
buffer.vertex(matrix, x2, y2, -300).color(color).endVertex();
|
||||
buffer.vertex(matrix, x2, y1, -300).color(color).endVertex();
|
||||
|
||||
setupRingShader(centerX, centerY, innerRadius, outerRadius);
|
||||
|
||||
BufferUploader.drawWithShader(buffer.end());
|
||||
poseStack.popPose();
|
||||
}
|
||||
|
||||
private static void setupRingShader(float centerX, float centerY, float innerRadius, float outerRadius) {
|
||||
Window window = Minecraft.getInstance().getWindow();
|
||||
float guiScale = (float) window.getGuiScale();
|
||||
|
||||
RenderSystem.setShader(Lib39Shaders::getRingShader);
|
||||
|
||||
// 转换到像素坐标(考虑GUI缩放)
|
||||
float pixelCenterX = centerX * guiScale;
|
||||
float pixelCenterY = window.getHeight() - (centerY * guiScale); // 翻转Y坐标
|
||||
|
||||
// 半径考虑GUI缩放
|
||||
float pixelInnerRadius = innerRadius * guiScale;
|
||||
float pixelOuterRadius = outerRadius * guiScale;
|
||||
float pixelAntiAliasing = 2.0f * guiScale; // 抗锯齿范围
|
||||
|
||||
System.out.println("Shader Params - Center: (" + pixelCenterX + ", " + pixelCenterY +
|
||||
"), InnerRadius: " + pixelInnerRadius + ", OuterRadius: " + pixelOuterRadius);
|
||||
|
||||
ShaderInstance shader = Lib39Shaders.getRingShader();
|
||||
shader.safeGetUniform("Center").set(pixelCenterX, pixelCenterY);
|
||||
shader.safeGetUniform("InnerRadius").set(pixelInnerRadius);
|
||||
shader.safeGetUniform("OuterRadius").set(pixelOuterRadius);
|
||||
shader.safeGetUniform("AntiAliasing").set(pixelAntiAliasing);
|
||||
shader.safeGetUniform("ColorModulator").set(1.0f, 1.0f, 1.0f, .5f);
|
||||
}
|
||||
|
||||
private void renderSelection(GuiGraphics guiGraphics) {
|
||||
float selectionEffectAngle = MathUtil.angle(
|
||||
MathUtil.copy(ROTATION_START),
|
||||
this.selectionEffectPos
|
||||
);
|
||||
|
||||
float diffAngle = this.currentAngle - selectionEffectAngle;
|
||||
|
||||
if (diffAngle > Math.PI) {
|
||||
diffAngle -= (float) (Math.PI * 2);
|
||||
} else if (diffAngle < -Math.PI) {
|
||||
diffAngle += (float) (Math.PI * 2);
|
||||
}
|
||||
|
||||
this.selectionEffectPos = MathUtil.rotate(
|
||||
this.selectionEffectPos,
|
||||
diffAngle / this.selectionAnimationSpeedFactor
|
||||
);
|
||||
|
||||
Vector2f pos = MathUtil.copy(this.selectionEffectPos)
|
||||
.mul(1, -1)
|
||||
.add(this.centerPos);
|
||||
|
||||
// 调用时使用半径
|
||||
renderSelectionEffect(
|
||||
guiGraphics,
|
||||
pos.x,
|
||||
pos.y,
|
||||
SELECTION_EFFECT_COLOR,
|
||||
SELECTION_EFFECT_RADIUS // 确保这是半径值
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Render selection effect.
|
||||
*
|
||||
* @param guiGraphics the gui graphics
|
||||
* @param centerX the center x
|
||||
* @param centerY the center y
|
||||
* @param color the color
|
||||
* @param radius the radius
|
||||
*/
|
||||
public static void renderSelectionEffect(
|
||||
GuiGraphics guiGraphics,
|
||||
float centerX,
|
||||
float centerY,
|
||||
int color,
|
||||
float radius
|
||||
) {
|
||||
RenderSystem.enableBlend();
|
||||
RenderSystem.defaultBlendFunc();
|
||||
RenderSystem.disableDepthTest();
|
||||
PoseStack poseStack = guiGraphics.pose();
|
||||
Matrix4f matrix4f = poseStack.last().pose();
|
||||
Tesselator tesselator = Tesselator.getInstance();
|
||||
BufferBuilder buffer = tesselator.getBuilder();
|
||||
buffer.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION_COLOR);
|
||||
|
||||
float x1 = centerX - radius - 5;
|
||||
float y1 = centerY - radius - 5;
|
||||
float x2 = centerX + radius + 5;
|
||||
float y2 = centerY + radius + 5;
|
||||
buffer.vertex(matrix4f, x1, y1, -200).color(color).endVertex();
|
||||
buffer.vertex(matrix4f, x1, y2, -200).color(color).endVertex();
|
||||
buffer.vertex(matrix4f, x2, y2, -200).color(color).endVertex();
|
||||
buffer.vertex(matrix4f, x2, y1, -200).color(color).endVertex();
|
||||
|
||||
Window window = Minecraft.getInstance().getWindow();
|
||||
float guiScale = (float) window.getGuiScale();
|
||||
RenderSystem.setShader(Lib39Shaders::getSelectionShader);
|
||||
System.out.println("Selection Effect Params:");
|
||||
System.out.println(" Center: " + centerX + ", " + centerY);
|
||||
System.out.println(" Radius: " + radius);
|
||||
System.out.println(" GUI Scale: " + guiScale);
|
||||
System.out.println(" Framebuffer: " + window.getWidth() + "x" + window.getHeight());
|
||||
Lib39Shaders.getSelectionShader()
|
||||
.safeGetUniform("Center")
|
||||
.set(centerX * guiScale, centerY * guiScale);
|
||||
Lib39Shaders.getSelectionShader()
|
||||
.safeGetUniform("FramebufferSize")
|
||||
.set((float) window.getWidth(), (float) window.getHeight());
|
||||
Lib39Shaders.getSelectionShader()
|
||||
.safeGetUniform("Radius")
|
||||
.set(radius * guiScale);
|
||||
Lib39Shaders.getSelectionShader()
|
||||
.safeGetUniform("AntiAliasingRadius")
|
||||
.set(guiScale); // 根据需要调整
|
||||
RenderSystem.setShaderColor(1, 1, 1, 1);
|
||||
BufferUploader.drawWithShader(Objects.requireNonNull(buffer.end()));
|
||||
RenderSystem.enableDepthTest();
|
||||
}
|
||||
|
||||
/**
|
||||
* On closing.
|
||||
*/
|
||||
public void onClosing() {
|
||||
if (this.shouldRender() && !this.closingAnimationStarted) {
|
||||
this.displayTime = System.currentTimeMillis();
|
||||
this.closingAnimationStarted = true;
|
||||
} else {
|
||||
this.minecraft.setScreen(null);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void updateWidgetNarration(NarrationElementOutput narrationElementOutput) {
|
||||
}
|
||||
|
||||
/**
|
||||
* The type Wheel section.
|
||||
*/
|
||||
public record WheelSection(
|
||||
Vector2f center,
|
||||
float angle,
|
||||
float angleStart,
|
||||
float angleEnd,
|
||||
Component subTitle,
|
||||
FourConsumer<GuiGraphics, PoseStack, Integer, Integer> renderer
|
||||
) {
|
||||
}
|
||||
}
|
||||
|
|
@ -1,91 +0,0 @@
|
|||
package top.r3944realms.lib39.client.model;
|
||||
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import com.mojang.blaze3d.vertex.VertexConsumer;
|
||||
import net.minecraft.client.model.Model;
|
||||
import net.minecraft.client.model.geom.ModelLayerLocation;
|
||||
import net.minecraft.client.model.geom.ModelPart;
|
||||
import net.minecraft.client.model.geom.PartPose;
|
||||
import net.minecraft.client.model.geom.builders.*;
|
||||
import net.minecraft.client.renderer.RenderType;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import top.r3944realms.lib39.Lib39;
|
||||
|
||||
/**
|
||||
* The type Doll model.
|
||||
*/
|
||||
public class DollModel extends Model {
|
||||
/**
|
||||
* The constant LAYER_LOCATION.
|
||||
*/
|
||||
public static final ModelLayerLocation LAYER_LOCATION = new ModelLayerLocation(Lib39.rl("doll_model"), "main");
|
||||
/**
|
||||
* The Slim.
|
||||
*/
|
||||
public boolean slim = false;
|
||||
private final ModelPart head;
|
||||
private final ModelPart body;
|
||||
private final ModelPart rightArm;
|
||||
private final ModelPart leftArm;
|
||||
private final ModelPart rightLeg;
|
||||
private final ModelPart rightArmSlim;
|
||||
private final ModelPart leftArmSlim;
|
||||
private final ModelPart leftLeg;
|
||||
|
||||
/**
|
||||
* Instantiates a new Doll model.
|
||||
*
|
||||
* @param root the root
|
||||
*/
|
||||
public DollModel(ModelPart root) {
|
||||
super(RenderType::entityTranslucent);
|
||||
this.head = root.getChild("head");
|
||||
this.body = root.getChild("body");
|
||||
this.rightArm = root.getChild("right_arm");
|
||||
this.leftArm = root.getChild("left_arm");
|
||||
this.rightArmSlim = root.getChild("right_arm_slim");
|
||||
this.leftArmSlim = root.getChild("left_arm_slim");
|
||||
this.rightLeg = root.getChild("right_leg");
|
||||
this.leftLeg = root.getChild("left_leg");
|
||||
}
|
||||
|
||||
/**
|
||||
* Create body layer layer definition.
|
||||
*
|
||||
* @return the layer definition
|
||||
*/
|
||||
public static LayerDefinition createBodyLayer() {
|
||||
MeshDefinition meshdefinition = new MeshDefinition();
|
||||
PartDefinition partdefinition = meshdefinition.getRoot();
|
||||
partdefinition.addOrReplaceChild("head", CubeListBuilder.create().texOffs(0, 0).addBox(-4.0F, -8.0F, -4.0F, 8.0F, 8.0F, 8.0F, new CubeDeformation(0.0F)).texOffs(32, 0).addBox(-4.0F, -8.0F, -4.0F, 8.0F, 8.0F, 8.0F, new CubeDeformation(0.5F)), PartPose.offset(0.0F, 9.0F, 0.0F));
|
||||
partdefinition.addOrReplaceChild("body", CubeListBuilder.create().texOffs(16, 16).addBox(-4.0F, 0.0F, -2.0F, 8.0F, 12.0F, 4.0F, new CubeDeformation(0.0F)).texOffs(16, 32).addBox(-4.0F, 0.0F, -2.0F, 8.0F, 12.0F, 4.0F, new CubeDeformation(0.25F)), PartPose.offset(0.0F, 9.0F, 0.0F));
|
||||
partdefinition.addOrReplaceChild("right_arm", CubeListBuilder.create().texOffs(40, 16).addBox(-3.0F, -2.0F, -2.0F, 4.0F, 12.0F, 4.0F, new CubeDeformation(0.0F)).texOffs(40, 32).addBox(-3.0F, -2.0F, -2.0F, 4.0F, 12.0F, 4.0F, new CubeDeformation(0.25F)), PartPose.offsetAndRotation(-5.0F, 11.0F, 0.0F, 0.0F, 0.0F, 0.3927F));
|
||||
partdefinition.addOrReplaceChild("right_arm_slim", CubeListBuilder.create().texOffs(40, 16).addBox(-2.0F, -2.0F, -2.0F, 3.0F, 12.0F, 4.0F, new CubeDeformation(0.0F)).texOffs(40, 32).addBox(-2.0F, -2.0F, -2.0F, 3.0F, 12.0F, 4.0F, new CubeDeformation(0.25F)), PartPose.offsetAndRotation(-5.0F, 11.0F, 0.0F, 0.0F, 0.0F, 0.3927F));
|
||||
partdefinition.addOrReplaceChild("left_arm_slim", CubeListBuilder.create().texOffs(32, 48).addBox(-1.0F, -2.0F, -2.0F, 3.0F, 12.0F, 4.0F, new CubeDeformation(0.0F)).texOffs(48, 48).addBox(-1.0F, -2.0F, -2.0F, 3.0F, 12.0F, 4.0F, new CubeDeformation(0.25F)), PartPose.offsetAndRotation(5.0F, 11.0F, 0.0F, 0.0F, 0.0F, -0.3927F));
|
||||
partdefinition.addOrReplaceChild("left_arm", CubeListBuilder.create().texOffs(32, 48).addBox(-1.0F, -2.0F, -2.0F, 4.0F, 12.0F, 4.0F, new CubeDeformation(0.0F)).texOffs(48, 48).addBox(-1.0F, -2.0F, -2.0F, 4.0F, 12.0F, 4.0F, new CubeDeformation(0.25F)), PartPose.offsetAndRotation(5.0F, 11.0F, 0.0F, 0.0F, 0.0F, -0.3927F));
|
||||
partdefinition.addOrReplaceChild("right_leg", CubeListBuilder.create().texOffs(0, 16).addBox(-2.0F, 0.0F, -2.0F, 4.0F, 12.0F, 4.0F, new CubeDeformation(0.0F)).texOffs(0, 32).addBox(-2.0F, 0.0F, -2.0F, 4.0F, 12.0F, 4.0F, new CubeDeformation(0.25F)), PartPose.offsetAndRotation(-2.0F, 19.0F, -2.0F, -1.5708F, 0.3927F, 0.0F));
|
||||
partdefinition.addOrReplaceChild("left_leg", CubeListBuilder.create().texOffs(16, 48).addBox(-2.0F, 0.0F, -2.0F, 4.0F, 12.0F, 4.0F, new CubeDeformation(0.0F)).texOffs(0, 48).addBox(-2.0F, 0.0F, -2.0F, 4.0F, 12.0F, 4.0F, new CubeDeformation(0.25F)), PartPose.offsetAndRotation(2.0F, 19.0F, -2.0F, -1.5708F, -0.3927F, 0.0F));
|
||||
return LayerDefinition.create(meshdefinition, 64, 64);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void renderToBuffer(PoseStack poseStack, @NotNull VertexConsumer vertexConsumer, int packedLight, int packedOverlay, float red, float green, float blue, float alpha) {
|
||||
poseStack.pushPose();
|
||||
poseStack.scale(0.5F, 0.5F, 0.5F);
|
||||
poseStack.translate(0.0, 1.5010000467300415, 0.0);
|
||||
this.head.render(poseStack, vertexConsumer, packedLight, packedOverlay, red, green, blue, alpha);
|
||||
this.body.render(poseStack, vertexConsumer, packedLight, packedOverlay, red, green, blue, alpha);
|
||||
if (this.slim) {
|
||||
this.rightArmSlim.render(poseStack, vertexConsumer, packedLight, packedOverlay, red, green, blue, alpha);
|
||||
this.leftArmSlim.render(poseStack, vertexConsumer, packedLight, packedOverlay, red, green, blue, alpha);
|
||||
} else {
|
||||
this.rightArm.render(poseStack, vertexConsumer, packedLight, packedOverlay, red, green, blue, alpha);
|
||||
this.leftArm.render(poseStack, vertexConsumer, packedLight, packedOverlay, red, green, blue, alpha);
|
||||
}
|
||||
|
||||
this.rightLeg.render(poseStack, vertexConsumer, packedLight, packedOverlay, red, green, blue, alpha);
|
||||
this.leftLeg.render(poseStack, vertexConsumer, packedLight, packedOverlay, red, green, blue, alpha);
|
||||
poseStack.popPose();
|
||||
}
|
||||
}
|
||||
|
|
@ -1,381 +0,0 @@
|
|||
package top.r3944realms.lib39.client.renderer;
|
||||
|
||||
import com.mojang.blaze3d.systems.RenderSystem;
|
||||
import com.mojang.blaze3d.vertex.*;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.GuiGraphics;
|
||||
import net.minecraft.client.renderer.GameRenderer;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.util.Mth;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import org.joml.Matrix4f;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.function.Function;
|
||||
|
||||
/**
|
||||
* 圆形径向菜单渲染器
|
||||
* 用于创建美观的圆形选择菜单
|
||||
*
|
||||
* @param <T> the type parameter
|
||||
*/
|
||||
public class RadialMenuRenderer<T> {
|
||||
/**
|
||||
* The constant DEFAULT_INNER_RADIUS.
|
||||
*/
|
||||
// 默认配置常量
|
||||
public static final float DEFAULT_INNER_RADIUS = 30f;
|
||||
/**
|
||||
* The constant DEFAULT_OUTER_RADIUS.
|
||||
*/
|
||||
public static final float DEFAULT_OUTER_RADIUS = 80f;
|
||||
/**
|
||||
* The constant DEFAULT_MIDDLE_RADIUS.
|
||||
*/
|
||||
public static final float DEFAULT_MIDDLE_RADIUS = 55f;
|
||||
/**
|
||||
* The constant DEFAULT_SEGMENTS.
|
||||
*/
|
||||
public static final int DEFAULT_SEGMENTS = 64;
|
||||
|
||||
// 配置选项
|
||||
private final float innerRadius;
|
||||
private final float outerRadius;
|
||||
private final float middleRadius;
|
||||
private final int segments;
|
||||
private final boolean enableHoverAnimation;
|
||||
private final ColorScheme colorScheme;
|
||||
|
||||
// 状态
|
||||
private int hoveredIndex = -1;
|
||||
private final float[] hoverAnimations;
|
||||
private long lastAnimationTime = 0;
|
||||
|
||||
/**
|
||||
* The type Color scheme.
|
||||
*/
|
||||
public static class ColorScheme {
|
||||
/**
|
||||
* The Normal color.
|
||||
*/
|
||||
public final float[] normalColor;
|
||||
/**
|
||||
* The Hovered color.
|
||||
*/
|
||||
public final float[] hoveredColor;
|
||||
/**
|
||||
* The Selected color.
|
||||
*/
|
||||
public final float[] selectedColor;
|
||||
/**
|
||||
* The Background color.
|
||||
*/
|
||||
public final float[] backgroundColor;
|
||||
|
||||
/**
|
||||
* Instantiates a new Color scheme.
|
||||
*
|
||||
* @param normalColor the normal color
|
||||
* @param hoveredColor the hovered color
|
||||
* @param selectedColor the selected color
|
||||
* @param backgroundColor the background color
|
||||
*/
|
||||
public ColorScheme(float[] normalColor, float[] hoveredColor, float[] selectedColor, float[] backgroundColor) {
|
||||
this.normalColor = normalColor;
|
||||
this.hoveredColor = hoveredColor;
|
||||
this.selectedColor = selectedColor;
|
||||
this.backgroundColor = backgroundColor;
|
||||
}
|
||||
|
||||
/**
|
||||
* The constant DEFAULT.
|
||||
*/
|
||||
// 预定义颜色方案
|
||||
public static final ColorScheme DEFAULT = new ColorScheme(
|
||||
new float[]{0.3f, 0.3f, 0.8f, 0.6f}, // 正常 - 蓝色
|
||||
new float[]{0.9f, 0.7f, 0.1f, 0.8f}, // 悬停 - 金色
|
||||
new float[]{0.2f, 0.8f, 0.2f, 0.9f}, // 选中 - 绿色
|
||||
new float[]{0.1f, 0.1f, 0.1f, 0.7f} // 背景
|
||||
);
|
||||
|
||||
/**
|
||||
* The constant FIRE.
|
||||
*/
|
||||
public static final ColorScheme FIRE = new ColorScheme(
|
||||
new float[]{0.8f, 0.3f, 0.1f, 0.6f}, // 正常 - 红色
|
||||
new float[]{1.0f, 0.5f, 0.0f, 0.8f}, // 悬停 - 橙色
|
||||
new float[]{1.0f, 0.9f, 0.0f, 0.9f}, // 选中 - 黄色
|
||||
new float[]{0.2f, 0.1f, 0.0f, 0.7f} // 背景
|
||||
);
|
||||
|
||||
/**
|
||||
* The constant NATURE.
|
||||
*/
|
||||
public static final ColorScheme NATURE = new ColorScheme(
|
||||
new float[]{0.2f, 0.6f, 0.3f, 0.6f}, // 正常 - 绿色
|
||||
new float[]{0.4f, 0.8f, 0.4f, 0.8f}, // 悬停 - 亮绿
|
||||
new float[]{0.1f, 0.9f, 0.7f, 0.9f}, // 选中 - 青绿
|
||||
new float[]{0.1f, 0.2f, 0.1f, 0.7f} // 背景
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Instantiates a new Radial menu renderer.
|
||||
*/
|
||||
public RadialMenuRenderer() {
|
||||
this(DEFAULT_INNER_RADIUS, DEFAULT_OUTER_RADIUS, ColorScheme.DEFAULT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Instantiates a new Radial menu renderer.
|
||||
*
|
||||
* @param innerRadius the inner radius
|
||||
* @param outerRadius the outer radius
|
||||
*/
|
||||
public RadialMenuRenderer(float innerRadius, float outerRadius) {
|
||||
this(innerRadius, outerRadius, ColorScheme.DEFAULT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Instantiates a new Radial menu renderer.
|
||||
*
|
||||
* @param innerRadius the inner radius
|
||||
* @param outerRadius the outer radius
|
||||
* @param colorScheme the color scheme
|
||||
*/
|
||||
public RadialMenuRenderer(float innerRadius, float outerRadius, ColorScheme colorScheme) {
|
||||
this(innerRadius, outerRadius, (innerRadius + outerRadius) / 2f, DEFAULT_SEGMENTS, true, colorScheme);
|
||||
}
|
||||
|
||||
/**
|
||||
* Instantiates a new Radial menu renderer.
|
||||
*
|
||||
* @param innerRadius the inner radius
|
||||
* @param outerRadius the outer radius
|
||||
* @param middleRadius the middle radius
|
||||
* @param segments the segments
|
||||
* @param enableHoverAnimation the enable hover animation
|
||||
* @param colorScheme the color scheme
|
||||
*/
|
||||
public RadialMenuRenderer(float innerRadius, float outerRadius, float middleRadius,
|
||||
int segments, boolean enableHoverAnimation, ColorScheme colorScheme) {
|
||||
this.innerRadius = innerRadius;
|
||||
this.outerRadius = outerRadius;
|
||||
this.middleRadius = middleRadius;
|
||||
this.segments = segments;
|
||||
this.enableHoverAnimation = enableHoverAnimation;
|
||||
this.colorScheme = colorScheme;
|
||||
this.hoverAnimations = new float[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* 渲染圆形菜单
|
||||
*
|
||||
* @param guiGraphics the gui graphics
|
||||
* @param entries the entries
|
||||
* @param titleProvider the title provider
|
||||
* @param iconProvider the icon provider
|
||||
* @param selectedIndex the selected index
|
||||
* @param trackMouse the track mouse
|
||||
*/
|
||||
public void render(GuiGraphics guiGraphics, List<T> entries,
|
||||
Function<T, Component> titleProvider,
|
||||
Function<T, ItemStack> iconProvider,
|
||||
int selectedIndex, boolean trackMouse) {
|
||||
if (entries.isEmpty()) return;
|
||||
|
||||
// 更新动画状态
|
||||
updateHoverAnimations(entries.size());
|
||||
|
||||
// 设置渲染状态
|
||||
RenderSystem.enableBlend();
|
||||
RenderSystem.defaultBlendFunc();
|
||||
RenderSystem.setShader(GameRenderer::getPositionColorShader);
|
||||
|
||||
float centerX = guiGraphics.guiWidth() / 2f;
|
||||
float centerY = guiGraphics.guiHeight() / 2f;
|
||||
|
||||
guiGraphics.pose().pushPose();
|
||||
guiGraphics.pose().translate(centerX, centerY, 0f);
|
||||
|
||||
// 渲染所有扇形区域
|
||||
renderSectors(guiGraphics, entries, selectedIndex);
|
||||
|
||||
// 渲染图标和文本
|
||||
renderIconsAndText(guiGraphics, entries, titleProvider, iconProvider);
|
||||
|
||||
guiGraphics.pose().popPose();
|
||||
|
||||
RenderSystem.disableBlend();
|
||||
}
|
||||
|
||||
/**
|
||||
* 渲染扇形区域
|
||||
*/
|
||||
private void renderSectors(GuiGraphics guiGraphics, List<T> entries, int selectedIndex) {
|
||||
int count = entries.size();
|
||||
float angleSize = 360f / count;
|
||||
|
||||
for (int i = 0; i < count; i++) {
|
||||
float startAngle = -90f + i * angleSize;
|
||||
float currentOuterRadius = outerRadius;
|
||||
|
||||
// 悬停动画效果
|
||||
if (enableHoverAnimation && i < hoverAnimations.length) {
|
||||
currentOuterRadius += hoverAnimations[i] * 5f;
|
||||
}
|
||||
|
||||
// 颜色设置
|
||||
float[] color = getSectorColor(i, selectedIndex, entries.get(i));
|
||||
|
||||
// 绘制扇形
|
||||
drawSector(guiGraphics, startAngle, angleSize, innerRadius, currentOuterRadius, color);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取扇形颜色
|
||||
*/
|
||||
private float[] getSectorColor(int index, int selectedIndex, T entry) {
|
||||
if (index == selectedIndex) {
|
||||
return colorScheme.selectedColor; // 选中状态
|
||||
} else if (index == hoveredIndex) {
|
||||
return colorScheme.hoveredColor; // 悬停状态
|
||||
} else {
|
||||
return colorScheme.normalColor; // 普通状态
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 绘制单个扇形
|
||||
*/
|
||||
private void drawSector(GuiGraphics guiGraphics, float startAngle, float angleSize,
|
||||
float innerRadius, float outerRadius, float[] color) {
|
||||
BufferBuilder buffer = Tesselator.getInstance().getBuilder();
|
||||
buffer.begin(VertexFormat.Mode.TRIANGLE_STRIP, DefaultVertexFormat.POSITION_COLOR);
|
||||
|
||||
Matrix4f matrix = guiGraphics.pose().last().pose();
|
||||
float segments = Math.max(8, this.segments * (angleSize / 360f));
|
||||
|
||||
for (int i = 0; i <= segments; i++) {
|
||||
float progress = i / segments;
|
||||
float angle = startAngle + progress * angleSize;
|
||||
float rad = angle * Mth.DEG_TO_RAD;
|
||||
|
||||
float cos = Mth.cos(rad);
|
||||
float sin = Mth.sin(rad);
|
||||
|
||||
// 外圈顶点
|
||||
buffer.vertex(matrix, outerRadius * cos, outerRadius * sin, 0)
|
||||
.color(color[0], color[1], color[2], color[3]).endVertex();
|
||||
// 内圈顶点
|
||||
buffer.vertex(matrix, innerRadius * cos, innerRadius * sin, 0)
|
||||
.color(color[0], color[1], color[2], color[3] * 0.6f).endVertex();
|
||||
}
|
||||
|
||||
BufferUploader.drawWithShader(buffer.end());
|
||||
}
|
||||
|
||||
/**
|
||||
* 渲染图标和文本
|
||||
*/
|
||||
private void renderIconsAndText(GuiGraphics guiGraphics, List<T> entries,
|
||||
Function<T, Component> titleProvider,
|
||||
Function<T, ItemStack> iconProvider) {
|
||||
int count = entries.size();
|
||||
var font = Minecraft.getInstance().font;
|
||||
|
||||
for (int i = 0; i < count; i++) {
|
||||
T entry = entries.get(i);
|
||||
float angle = (-90f + 360f * (i + 0.5f) / count) * Mth.DEG_TO_RAD;
|
||||
|
||||
// 计算位置
|
||||
float x = Mth.cos(angle) * middleRadius;
|
||||
float y = Mth.sin(angle) * middleRadius;
|
||||
|
||||
// 渲染图标
|
||||
ItemStack icon = iconProvider.apply(entry);
|
||||
if (!icon.isEmpty()) {
|
||||
guiGraphics.renderItem(icon, (int)(x - 8), (int)(y - 8));
|
||||
}
|
||||
|
||||
// 渲染文本
|
||||
Component title = titleProvider.apply(entry);
|
||||
guiGraphics.pose().pushPose();
|
||||
guiGraphics.pose().translate(x, y + 12, 0);
|
||||
guiGraphics.pose().scale(0.7f, 0.7f, 0.7f);
|
||||
guiGraphics.drawString(font, title, -font.width(title) / 2, 0, 0xFFFFFF, true);
|
||||
guiGraphics.pose().popPose();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新悬停动画
|
||||
*/
|
||||
private void updateHoverAnimations(int entryCount) {
|
||||
if (!enableHoverAnimation) return;
|
||||
|
||||
long currentTime = System.currentTimeMillis();
|
||||
float deltaTime = Math.min((currentTime - lastAnimationTime) / 1000f, 0.1f);
|
||||
lastAnimationTime = currentTime;
|
||||
|
||||
// 确保数组大小正确
|
||||
if (hoverAnimations.length != entryCount) {
|
||||
// 这里需要重新初始化数组,实际使用时应该处理数组大小变化
|
||||
}
|
||||
|
||||
// 更新动画值
|
||||
for (int i = 0; i < hoverAnimations.length && i < entryCount; i++) {
|
||||
if (i == hoveredIndex) {
|
||||
hoverAnimations[i] = Mth.clamp(hoverAnimations[i] + deltaTime * 2f, 0f, 1f);
|
||||
} else {
|
||||
hoverAnimations[i] = Mth.clamp(hoverAnimations[i] - deltaTime * 3f, 0f, 1f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取鼠标下的条目索引
|
||||
*
|
||||
* @param entries the entries
|
||||
* @param mouseX the mouse x
|
||||
* @param mouseY the mouse y
|
||||
* @return the hovered entry
|
||||
*/
|
||||
public int getHoveredEntry(List<T> entries, double mouseX, double mouseY) {
|
||||
float centerX = Minecraft.getInstance().getWindow().getGuiScaledWidth() / 2f;
|
||||
float centerY = Minecraft.getInstance().getWindow().getGuiScaledHeight() / 2f;
|
||||
|
||||
double relX = mouseX - centerX;
|
||||
double relY = mouseY - centerY;
|
||||
double distance = Math.sqrt(relX * relX + relY * relY);
|
||||
|
||||
// 检查是否在有效范围内
|
||||
if (distance < innerRadius || distance > outerRadius) {
|
||||
hoveredIndex = -1;
|
||||
return -1;
|
||||
}
|
||||
|
||||
// 计算角度
|
||||
double angle = Math.atan2(relY, relX) * Mth.RAD_TO_DEG;
|
||||
angle = (angle + 450) % 360; // 标准化到 0-360
|
||||
|
||||
int count = entries.size();
|
||||
int index = (int) (angle / (360f / count)) % count;
|
||||
|
||||
hoveredIndex = index;
|
||||
return index;
|
||||
}
|
||||
|
||||
/**
|
||||
* 清除状态
|
||||
*/
|
||||
public void clearState() {
|
||||
hoveredIndex = -1;
|
||||
// 重置动画数组
|
||||
Arrays.fill(hoverAnimations, 0f);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,55 +0,0 @@
|
|||
package top.r3944realms.lib39.client.renderer.block;
|
||||
|
||||
import com.mojang.authlib.GameProfile;
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import com.mojang.blaze3d.vertex.VertexConsumer;
|
||||
import com.mojang.math.Axis;
|
||||
import net.minecraft.client.renderer.MultiBufferSource;
|
||||
import net.minecraft.client.renderer.RenderType;
|
||||
import net.minecraft.client.renderer.blockentity.BlockEntityRenderer;
|
||||
import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider;
|
||||
import net.minecraft.client.renderer.texture.OverlayTexture;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import top.r3944realms.lib39.client.model.DollModel;
|
||||
import top.r3944realms.lib39.client.renderer.item.DollItemRenderer;
|
||||
import top.r3944realms.lib39.content.block.DollBlock;
|
||||
import top.r3944realms.lib39.content.block.blockentity.DollBlockEntity;
|
||||
import top.r3944realms.lib39.util.lang.Pair;
|
||||
|
||||
/**
|
||||
* The type Doll block entity renderer.
|
||||
*/
|
||||
public class DollBlockEntityRenderer implements BlockEntityRenderer<DollBlockEntity> {
|
||||
private final DollModel dollModel;
|
||||
|
||||
/**
|
||||
* Instantiates a new Doll block entity renderer.
|
||||
*
|
||||
* @param context the context
|
||||
*/
|
||||
public DollBlockEntityRenderer(BlockEntityRendererProvider.@NotNull Context context) {
|
||||
this.dollModel = new DollModel(context.bakeLayer(DollModel.LAYER_LOCATION));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render(@NotNull DollBlockEntity dollBlockEntity, float partialTick, @NotNull PoseStack poseStack, @NotNull MultiBufferSource buffer, int packedLight, int packedOverlay) {
|
||||
BlockState blockState = dollBlockEntity.getBlockState();
|
||||
if (blockState.getBlock() instanceof DollBlock) {
|
||||
Direction facing = blockState.getValue(DollBlock.FACING);
|
||||
GameProfile profile = dollBlockEntity.getOwnerProfile();
|
||||
Pair<ResourceLocation, Boolean> resourceLocationBooleanPair = DollItemRenderer.loadSkin(profile);
|
||||
poseStack.pushPose();
|
||||
poseStack.translate(0.5, 1.5, 0.5);
|
||||
poseStack.scale(1.0F, -1.0F, -1.0F);
|
||||
float rotation = facing.toYRot();
|
||||
poseStack.mulPose(Axis.YP.rotationDegrees(rotation));
|
||||
VertexConsumer vertexConsumer = buffer.getBuffer(RenderType.entityTranslucent(resourceLocationBooleanPair.first));
|
||||
this.dollModel.slim = resourceLocationBooleanPair.second;
|
||||
this.dollModel.renderToBuffer(poseStack, vertexConsumer, packedLight, OverlayTexture.NO_OVERLAY, 1.0F, 1.0F, 1.0F, 1.0F);
|
||||
poseStack.popPose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,98 +0,0 @@
|
|||
package top.r3944realms.lib39.client.renderer.item;
|
||||
|
||||
import com.mojang.authlib.GameProfile;
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import com.mojang.blaze3d.vertex.VertexConsumer;
|
||||
import com.mojang.math.Axis;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.renderer.BlockEntityWithoutLevelRenderer;
|
||||
import net.minecraft.client.renderer.MultiBufferSource;
|
||||
import net.minecraft.client.renderer.RenderType;
|
||||
import net.minecraft.client.resources.DefaultPlayerSkin;
|
||||
import net.minecraft.client.resources.SkinManager;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.item.ItemDisplayContext;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import top.r3944realms.lib39.client.model.DollModel;
|
||||
import top.r3944realms.lib39.content.item.DollItem;
|
||||
import top.r3944realms.lib39.util.GameProfileHelper;
|
||||
import top.r3944realms.lib39.util.lang.Pair;
|
||||
|
||||
/**
|
||||
* The type Doll item renderer.
|
||||
*/
|
||||
public class DollItemRenderer extends BlockEntityWithoutLevelRenderer {
|
||||
private static DollItemRenderer instance;
|
||||
private final DollModel dollModel;
|
||||
private DollItemRenderer() {
|
||||
super(
|
||||
Minecraft.getInstance().getBlockEntityRenderDispatcher(),
|
||||
Minecraft.getInstance().getEntityModels()
|
||||
);
|
||||
this.dollModel = new DollModel(
|
||||
Minecraft.getInstance().getEntityModels().bakeLayer(DollModel.LAYER_LOCATION)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets instance.
|
||||
*
|
||||
* @return the instance
|
||||
*/
|
||||
public static DollItemRenderer getInstance() {
|
||||
if (instance == null) {
|
||||
instance = new DollItemRenderer();
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void renderByItem(@NotNull ItemStack stack, @NotNull ItemDisplayContext displayContext, @NotNull PoseStack poseStack, @NotNull MultiBufferSource buffer, int packedLight, int packedOverlay) {
|
||||
if (!(stack.getItem() instanceof DollItem)) {
|
||||
return;
|
||||
}
|
||||
GameProfile profile = GameProfileHelper.getProfileFromItemStack(stack);
|
||||
Pair<ResourceLocation, Boolean> resourceLocationBooleanPair = loadSkin(profile);
|
||||
ResourceLocation playerSkin = resourceLocationBooleanPair.first;
|
||||
boolean isSlim = resourceLocationBooleanPair.second;
|
||||
poseStack.pushPose();
|
||||
VertexConsumer vertexConsumer = buffer.getBuffer(
|
||||
RenderType.entityTranslucent(playerSkin)
|
||||
);
|
||||
|
||||
poseStack.translate(0.5, 2.6, 0.8);
|
||||
poseStack.scale(1.8F, -1.8F, -1.8F);
|
||||
poseStack.mulPose(Axis.YP.rotationDegrees(180));
|
||||
this.dollModel.slim = isSlim;
|
||||
this.dollModel.renderToBuffer(
|
||||
poseStack,
|
||||
vertexConsumer,
|
||||
packedLight,
|
||||
packedOverlay,
|
||||
1.0F, 1.0F, 1.0F, 1.0F
|
||||
);
|
||||
|
||||
poseStack.popPose();
|
||||
}
|
||||
|
||||
/**
|
||||
* Load skin pair.
|
||||
*
|
||||
* @param profile the profile
|
||||
* @return the pair
|
||||
*/
|
||||
public static @NotNull Pair<ResourceLocation,Boolean> loadSkin(GameProfile profile) {
|
||||
SkinManager skinManager = Minecraft.getInstance().getSkinManager();
|
||||
ResourceLocation playerSkin;
|
||||
boolean isSlim;
|
||||
if (profile != null) {
|
||||
playerSkin = skinManager.getInsecureSkinLocation(profile);
|
||||
isSlim = GameProfileHelper.isSlimArms(profile);
|
||||
} else {
|
||||
playerSkin = DefaultPlayerSkin.getDefaultSkin(); //6 new SkinType("textures/entity/player/slim/steve.png", DefaultPlayerSkin.ModelType.SLIM),
|
||||
isSlim = true;
|
||||
}
|
||||
return Pair.of(playerSkin, isSlim);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,73 +0,0 @@
|
|||
package top.r3944realms.lib39.client.shader;
|
||||
|
||||
import com.mojang.blaze3d.vertex.DefaultVertexFormat;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.renderer.ShaderInstance;
|
||||
import net.minecraftforge.client.event.RegisterShadersEvent;
|
||||
import top.r3944realms.lib39.Lib39;
|
||||
|
||||
/**
|
||||
* The type Lib 39 shaders.
|
||||
*/
|
||||
public class Lib39Shaders {
|
||||
/**
|
||||
* The Minecraft.
|
||||
*/
|
||||
static final Minecraft MINECRAFT = Minecraft.getInstance();
|
||||
|
||||
/**
|
||||
* Gets ring shader.
|
||||
*
|
||||
* @return the ring shader
|
||||
*/
|
||||
public static ShaderInstance getRingShader() {
|
||||
return ringShader;
|
||||
}
|
||||
|
||||
/**
|
||||
* The Ring shader.
|
||||
*/
|
||||
static ShaderInstance ringShader;
|
||||
|
||||
/**
|
||||
* Gets selection shader.
|
||||
*
|
||||
* @return the selection shader
|
||||
*/
|
||||
public static ShaderInstance getSelectionShader() {
|
||||
return selectionShader;
|
||||
}
|
||||
|
||||
/**
|
||||
* The Selection shader.
|
||||
*/
|
||||
static ShaderInstance selectionShader;
|
||||
|
||||
/**
|
||||
* Register.
|
||||
*
|
||||
* @param event the event
|
||||
*/
|
||||
public static void register(RegisterShadersEvent event) {
|
||||
try {
|
||||
event.registerShader(
|
||||
new ShaderInstance(
|
||||
event.getResourceProvider(),
|
||||
Lib39.rl("ring"),
|
||||
DefaultVertexFormat.POSITION_COLOR
|
||||
),
|
||||
it -> ringShader = it
|
||||
);
|
||||
event.registerShader(
|
||||
new ShaderInstance(
|
||||
event.getResourceProvider(),
|
||||
Lib39.rl("selection"),
|
||||
DefaultVertexFormat.POSITION_COLOR
|
||||
),
|
||||
it -> selectionShader = it
|
||||
);
|
||||
} catch (Exception e) {
|
||||
Lib39.LOGGER.error("Failed to register shader", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,241 +0,0 @@
|
|||
package top.r3944realms.lib39.content.block;
|
||||
|
||||
import com.mojang.authlib.GameProfile;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.core.particles.ParticleTypes;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.sounds.SoundSource;
|
||||
import net.minecraft.world.InteractionHand;
|
||||
import net.minecraft.world.InteractionResult;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.item.context.BlockPlaceContext;
|
||||
import net.minecraft.world.level.BlockGetter;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.LevelAccessor;
|
||||
import net.minecraft.world.level.block.*;
|
||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.block.state.StateDefinition;
|
||||
import net.minecraft.world.level.block.state.properties.BlockStateProperties;
|
||||
import net.minecraft.world.level.block.state.properties.BooleanProperty;
|
||||
import net.minecraft.world.level.block.state.properties.EnumProperty;
|
||||
import net.minecraft.world.level.block.state.properties.NoteBlockInstrument;
|
||||
import net.minecraft.world.level.material.FluidState;
|
||||
import net.minecraft.world.level.material.Fluids;
|
||||
import net.minecraft.world.level.material.PushReaction;
|
||||
import net.minecraft.world.level.storage.loot.LootParams;
|
||||
import net.minecraft.world.level.storage.loot.parameters.LootContextParams;
|
||||
import net.minecraft.world.phys.BlockHitResult;
|
||||
import net.minecraft.world.phys.HitResult;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import net.minecraft.world.phys.shapes.CollisionContext;
|
||||
import net.minecraft.world.phys.shapes.VoxelShape;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import top.r3944realms.lib39.content.block.blockentity.DollBlockEntity;
|
||||
import top.r3944realms.lib39.content.block.property.DollPose;
|
||||
import top.r3944realms.lib39.content.register.Lib39BlockEntities;
|
||||
import top.r3944realms.lib39.content.register.Lib39Items;
|
||||
import top.r3944realms.lib39.content.register.Lib39SoundEvents;
|
||||
import top.r3944realms.lib39.util.GameProfileHelper;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* The type Doll block.
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
public class DollBlock extends HorizontalDirectionalBlock implements SimpleWaterloggedBlock, EntityBlock {
|
||||
private static final BooleanProperty WATERLOGGED = BlockStateProperties.WATERLOGGED;
|
||||
/**
|
||||
* The constant POSE.
|
||||
*/
|
||||
public static final EnumProperty<DollPose> POSE = EnumProperty.create("pose", DollPose.class);
|
||||
|
||||
private static final VoxelShape DOLL_SHAPE = Block.box(2.0d, 0.0d, 2.0d, 14.0d, 12.0d, 14.0d);
|
||||
private static final Properties properties = Properties.of()
|
||||
.instrument(NoteBlockInstrument.BASEDRUM)
|
||||
.sound(SoundType.WOOL)
|
||||
.strength(0f, 10f)
|
||||
.noOcclusion();
|
||||
|
||||
private static final double PARTICLE_OFFSET_RANGE = 0.25;
|
||||
private static final double PARTICLE_HEIGHT_OFFSET = 1.0;
|
||||
private static final double PARTICLE_HEIGHT_VARIANCE = 0.2;
|
||||
private static final float NOTE_COLOR_DIVISOR = 24.0F;
|
||||
private static final int MAX_NOTE_COLORS = 4;
|
||||
|
||||
private static final float BASE_VOLUME = 1.0f;
|
||||
private static final float PITCH_VARIANCE = 0.5f;
|
||||
private static final float BASE_PITCH = 0.75f;
|
||||
|
||||
/**
|
||||
* Instantiates a new Doll block.
|
||||
*/
|
||||
public DollBlock() {
|
||||
super(properties);
|
||||
this.registerDefaultState(this.stateDefinition.any().setValue(FACING, Direction.SOUTH)
|
||||
.setValue(POSE, DollPose.DEFAULT)
|
||||
.setValue(WATERLOGGED, false));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canBeReplaced(@NotNull BlockState state, @NotNull BlockPlaceContext useContext) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable PushReaction getPistonPushReaction(BlockState state) {
|
||||
return PushReaction.DESTROY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull BlockState updateShape(@NotNull BlockState currentState, @NotNull Direction direction, @NotNull BlockState neighborState,
|
||||
@NotNull LevelAccessor level, @NotNull BlockPos currentPos, @NotNull BlockPos neighborPos) {
|
||||
if (currentState.getValue(WATERLOGGED)) {
|
||||
level.scheduleTick(currentPos, Fluids.WATER, Fluids.WATER.getTickDelay(level));
|
||||
}
|
||||
return super.updateShape(currentState, direction, neighborState, level, currentPos, neighborPos);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull FluidState getFluidState(@NotNull BlockState blockState) {
|
||||
return blockState.getValue(WATERLOGGED) ? Fluids.WATER.getSource(false) : super.getFluidState(blockState);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull InteractionResult use(@NotNull BlockState blockState, @NotNull Level level, @NotNull BlockPos blockPos, @NotNull Player player,
|
||||
@NotNull InteractionHand hand, @NotNull BlockHitResult hitResult) {
|
||||
if (level instanceof ServerLevel serverLevel) {
|
||||
// 播放粒子效果
|
||||
spawnNoteParticles(serverLevel, blockPos);
|
||||
// 播放音效
|
||||
playDollSound(serverLevel, blockPos);
|
||||
}
|
||||
return InteractionResult.SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* 在玩偶位置生成音符粒子效果
|
||||
*/
|
||||
private void spawnNoteParticles(ServerLevel serverLevel, BlockPos blockPos) {
|
||||
Vec3 particlePosition = calculateParticlePosition(serverLevel, blockPos);
|
||||
float noteColor = calculateNoteColor(serverLevel);
|
||||
|
||||
serverLevel.sendParticles(ParticleTypes.NOTE,
|
||||
particlePosition.x(), particlePosition.y(), particlePosition.z(),
|
||||
0, noteColor, 0, 0, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* 计算粒子生成位置,添加随机偏移
|
||||
*/
|
||||
private @NotNull Vec3 calculateParticlePosition(@NotNull ServerLevel serverLevel, BlockPos blockPos) {
|
||||
return Vec3.atBottomCenterOf(blockPos).add(
|
||||
(serverLevel.getRandom().nextFloat() - 0.5) * PARTICLE_OFFSET_RANGE * 2,
|
||||
PARTICLE_HEIGHT_OFFSET + serverLevel.getRandom().nextFloat() * PARTICLE_HEIGHT_VARIANCE,
|
||||
(serverLevel.getRandom().nextFloat() - 0.5) * PARTICLE_OFFSET_RANGE * 2
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* 计算音符粒子的颜色
|
||||
*/
|
||||
private float calculateNoteColor(@NotNull ServerLevel serverLevel) {
|
||||
return serverLevel.getRandom().nextInt(MAX_NOTE_COLORS) / NOTE_COLOR_DIVISOR;
|
||||
}
|
||||
|
||||
/**
|
||||
* 播放玩偶音效
|
||||
*/
|
||||
private void playDollSound(@NotNull ServerLevel serverLevel, BlockPos blockPos) {
|
||||
float pitch = BASE_PITCH + serverLevel.random.nextFloat() * PITCH_VARIANCE;
|
||||
serverLevel.playSound(null, blockPos, Lib39SoundEvents.DUCK_TOY.get(),
|
||||
SoundSource.BLOCKS, BASE_VOLUME, pitch);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable BlockState getStateForPlacement(@NotNull BlockPlaceContext context) {
|
||||
FluidState fluidState = context.getLevel().getFluidState(context.getClickedPos());
|
||||
boolean isWaterlogged = fluidState.getType() == Fluids.WATER;
|
||||
|
||||
return this.defaultBlockState()
|
||||
.setValue(FACING, context.getHorizontalDirection().getOpposite())
|
||||
.setValue(WATERLOGGED, isWaterlogged)
|
||||
.setValue(POSE, DollPose.DEFAULT);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull VoxelShape getShape(@NotNull BlockState blockState, @NotNull BlockGetter level, @NotNull BlockPos blockPos, @NotNull CollisionContext context) {
|
||||
return DOLL_SHAPE;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void createBlockStateDefinition(StateDefinition.@NotNull Builder<Block, BlockState> builder) {
|
||||
super.createBlockStateDefinition(builder);
|
||||
builder.add(FACING, WATERLOGGED, POSE);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public BlockEntity newBlockEntity(@NotNull BlockPos blockPos, @NotNull BlockState blockState) {
|
||||
return Lib39BlockEntities.DOLL_BLOCK_ENTITY.get().create(blockPos, blockState);
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
@Override
|
||||
public @NotNull RenderShape getRenderShape(@NotNull BlockState state) {
|
||||
return RenderShape.ENTITYBLOCK_ANIMATED;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack getCloneItemStack(BlockState state, HitResult target, BlockGetter level, BlockPos pos, Player player) {
|
||||
ItemStack stack = super.getCloneItemStack(state, target, level, pos, player);
|
||||
|
||||
BlockEntity blockEntity = level.getBlockEntity(pos);
|
||||
if (blockEntity instanceof DollBlockEntity doll) {
|
||||
GameProfile profile = doll.getOwnerProfile();
|
||||
if (profile != null) {
|
||||
GameProfileHelper.saveProfileToItemStack(stack, profile);
|
||||
}
|
||||
}
|
||||
return stack;
|
||||
}
|
||||
|
||||
/**
|
||||
* 最重要的方法:重写掉落逻辑
|
||||
*/
|
||||
@Override
|
||||
@NotNull
|
||||
public List<ItemStack> getDrops(@NotNull BlockState state, @NotNull LootParams.Builder params) {
|
||||
// 获取方块实体
|
||||
BlockEntity blockEntity = params.getOptionalParameter(LootContextParams.BLOCK_ENTITY);
|
||||
|
||||
if (blockEntity instanceof DollBlockEntity dollEntity) {
|
||||
List<ItemStack> customDrops = getCustomDrops(dollEntity, params);
|
||||
if (customDrops != null) return customDrops;
|
||||
}
|
||||
return super.getDrops(state, params);
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成自定义掉落物
|
||||
*/
|
||||
@Nullable
|
||||
private List<ItemStack> getCustomDrops(DollBlockEntity dollEntity, LootParams.Builder params) {
|
||||
if (params.getOptionalParameter(LootContextParams.THIS_ENTITY) instanceof Player player) {
|
||||
if (player.isCreative()) {
|
||||
return List.of();
|
||||
}
|
||||
}
|
||||
GameProfile profile = dollEntity.getOwnerProfile();
|
||||
if (profile != null) {
|
||||
ItemStack instance = Lib39Items.DOLL.get().getDefaultInstance();
|
||||
GameProfileHelper.saveProfileToItemStack(instance, profile);
|
||||
return List.of(instance);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,98 +0,0 @@
|
|||
package top.r3944realms.lib39.content.block.blockentity;
|
||||
|
||||
import com.mojang.authlib.GameProfile;
|
||||
import net.minecraft.Util;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.nbt.NbtUtils;
|
||||
import net.minecraft.network.protocol.game.ClientboundBlockEntityDataPacket;
|
||||
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 top.r3944realms.lib39.content.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.
|
||||
*/
|
||||
public class DollBlockEntity extends BlockEntity {
|
||||
|
||||
@Nullable
|
||||
private GameProfile owner;
|
||||
|
||||
/**
|
||||
* Instantiates a new Doll block entity.
|
||||
*
|
||||
* @param pos the pos
|
||||
* @param blockState the block state
|
||||
*/
|
||||
public DollBlockEntity(BlockPos pos, BlockState blockState) {
|
||||
super(Lib39BlockEntities.DOLL_BLOCK_ENTITY.get(), pos, blockState);
|
||||
}
|
||||
|
||||
protected void saveAdditional(@NotNull CompoundTag tag) {
|
||||
super.saveAdditional(tag);
|
||||
NBTWriter.of(tag)
|
||||
.compoundIf(GameProfileHelper.TAG_OWN_PROFILE, owner != null, () -> NbtUtils.writeGameProfile(new CompoundTag(), this.owner));
|
||||
}
|
||||
|
||||
public void load(@NotNull CompoundTag tag) {
|
||||
super.load(tag);
|
||||
NBTReader.of(tag)
|
||||
.compound(GameProfileHelper.TAG_OWN_PROFILE, compoundTag -> setOwner(NbtUtils.readGameProfile(compoundTag)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets owner profile.
|
||||
*
|
||||
* @return the owner profile
|
||||
*/
|
||||
@Nullable
|
||||
public GameProfile getOwnerProfile() {
|
||||
return this.owner;
|
||||
}
|
||||
|
||||
|
||||
public ClientboundBlockEntityDataPacket getUpdatePacket() {
|
||||
return ClientboundBlockEntityDataPacket.create(this);
|
||||
}
|
||||
|
||||
public @NotNull CompoundTag getUpdateTag() {
|
||||
return this.saveWithoutMetadata();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets owner.
|
||||
*
|
||||
* @param owner the owner
|
||||
*/
|
||||
public void setOwner(@Nullable GameProfile owner) {
|
||||
synchronized (this) {
|
||||
this.owner = owner;
|
||||
}
|
||||
|
||||
this.updateOwnerProfile();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets owner.
|
||||
*
|
||||
* @param ownerName the owner name
|
||||
*/
|
||||
public void setOwner(@Nullable String ownerName) {
|
||||
setOwner(new GameProfile(Util.NIL_UUID, ownerName));
|
||||
}
|
||||
|
||||
private void updateOwnerProfile() {
|
||||
SkullBlockEntity.updateGameprofile(this.owner, gameProfile -> {
|
||||
this.owner = gameProfile;
|
||||
this.setChanged();
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,28 +0,0 @@
|
|||
package top.r3944realms.lib39.content.block.property;
|
||||
|
||||
import net.minecraft.util.StringRepresentable;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* The enum Doll pose.
|
||||
*/
|
||||
public enum DollPose implements StringRepresentable {
|
||||
/**
|
||||
* Default doll pose.
|
||||
*/
|
||||
DEFAULT("default"),
|
||||
/**
|
||||
* further support
|
||||
*/
|
||||
FURTHER("further"),
|
||||
;
|
||||
private final String name;
|
||||
DollPose(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull String getSerializedName() {
|
||||
return name;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,58 +0,0 @@
|
|||
package top.r3944realms.lib39.content.item;
|
||||
|
||||
import com.mojang.authlib.GameProfile;
|
||||
import net.minecraft.client.renderer.BlockEntityWithoutLevelRenderer;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.entity.EquipmentSlot;
|
||||
import net.minecraft.world.item.BlockItem;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.item.TooltipFlag;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraftforge.client.extensions.common.IClientItemExtensions;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import top.r3944realms.lib39.client.renderer.item.DollItemRenderer;
|
||||
import top.r3944realms.lib39.content.register.Lib39Blocks;
|
||||
import top.r3944realms.lib39.util.GameProfileHelper;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
/**
|
||||
* The type Doll item.
|
||||
*/
|
||||
public class DollItem extends BlockItem {
|
||||
/**
|
||||
* Instantiates a new Doll item.
|
||||
*
|
||||
* @param properties the properties
|
||||
*/
|
||||
public DollItem(Properties properties) {
|
||||
super(Lib39Blocks.DOLL.get(), properties);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initializeClient(@NotNull Consumer<IClientItemExtensions> consumer) {
|
||||
consumer.accept(new IClientItemExtensions() {
|
||||
@Override
|
||||
public BlockEntityWithoutLevelRenderer getCustomRenderer() {
|
||||
return DollItemRenderer.getInstance();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canEquip(ItemStack stack, EquipmentSlot armorType, Entity entity) {
|
||||
return armorType == EquipmentSlot.HEAD;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void appendHoverText(@NotNull ItemStack stack, @Nullable Level level, @NotNull List<Component> tooltip, @NotNull TooltipFlag flag) {
|
||||
GameProfile profileFromItemStack = GameProfileHelper.getProfileFromItemStack(stack);
|
||||
if (profileFromItemStack != null && profileFromItemStack.getName() != null) {
|
||||
tooltip.add(Component.translatable("tooltip.lib39.content.doll.hover.1", profileFromItemStack.getName()));
|
||||
}
|
||||
tooltip.add(Component.translatable("tooltip.lib39.content.doll.hover.2"));
|
||||
}
|
||||
}
|
||||
|
|
@ -1,37 +0,0 @@
|
|||
package top.r3944realms.lib39.content.register;
|
||||
|
||||
import net.minecraft.world.level.block.entity.BlockEntityType;
|
||||
import net.minecraftforge.eventbus.api.IEventBus;
|
||||
import net.minecraftforge.registries.DeferredRegister;
|
||||
import net.minecraftforge.registries.ForgeRegistries;
|
||||
import net.minecraftforge.registries.RegistryObject;
|
||||
import top.r3944realms.lib39.Lib39;
|
||||
import top.r3944realms.lib39.content.block.blockentity.DollBlockEntity;
|
||||
|
||||
/**
|
||||
* The type Lib 39 block entities.
|
||||
*/
|
||||
public class Lib39BlockEntities {
|
||||
/**
|
||||
* The constant BLOCK_ENTITY_TYPES.
|
||||
*/
|
||||
public static final DeferredRegister<BlockEntityType<?>> BLOCK_ENTITY_TYPES = DeferredRegister.create(ForgeRegistries.BLOCK_ENTITY_TYPES, Lib39.MOD_ID);
|
||||
/**
|
||||
* The constant DOLL_BLOCK_ENTITY.
|
||||
*/
|
||||
@SuppressWarnings("DataFlowIssue")
|
||||
public static final RegistryObject<BlockEntityType<DollBlockEntity>> DOLL_BLOCK_ENTITY = BLOCK_ENTITY_TYPES.register("doll",
|
||||
() -> BlockEntityType.Builder
|
||||
.of(DollBlockEntity::new, Lib39Blocks.DOLL.get())
|
||||
.build(null)
|
||||
);
|
||||
|
||||
/**
|
||||
* Register.
|
||||
*
|
||||
* @param bus the bus
|
||||
*/
|
||||
public static void register(IEventBus bus) {
|
||||
BLOCK_ENTITY_TYPES.register(bus);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,39 +0,0 @@
|
|||
package top.r3944realms.lib39.content.register;
|
||||
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraftforge.eventbus.api.IEventBus;
|
||||
import net.minecraftforge.registries.DeferredRegister;
|
||||
import net.minecraftforge.registries.ForgeRegistries;
|
||||
import net.minecraftforge.registries.RegistryObject;
|
||||
import top.r3944realms.lib39.Lib39;
|
||||
import top.r3944realms.lib39.content.block.DollBlock;
|
||||
import top.r3944realms.lib39.util.block.BlockRegistryBuilder;
|
||||
|
||||
/**
|
||||
* The type Lib 39 blocks.
|
||||
*/
|
||||
public class Lib39Blocks {
|
||||
/**
|
||||
* The constant BLOCKS.
|
||||
*/
|
||||
public static final DeferredRegister<Block> BLOCKS = DeferredRegister.create(ForgeRegistries.BLOCKS, Lib39.MOD_ID);
|
||||
|
||||
/**
|
||||
* The constant DOLL.
|
||||
*/
|
||||
public static final RegistryObject<Block> DOLL = BlockRegistryBuilder
|
||||
.create()
|
||||
.withName("doll")
|
||||
.registerBlock(BLOCKS, DollBlock::new)
|
||||
.build();
|
||||
|
||||
|
||||
/**
|
||||
* Register.
|
||||
*
|
||||
* @param bus the bus
|
||||
*/
|
||||
public static void register(IEventBus bus) {
|
||||
BLOCKS.register(bus);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,34 +0,0 @@
|
|||
package top.r3944realms.lib39.content.register;
|
||||
|
||||
import net.minecraft.world.item.Item;
|
||||
import net.minecraftforge.eventbus.api.IEventBus;
|
||||
import net.minecraftforge.registries.DeferredRegister;
|
||||
import net.minecraftforge.registries.ForgeRegistries;
|
||||
import net.minecraftforge.registries.RegistryObject;
|
||||
import top.r3944realms.lib39.Lib39;
|
||||
import top.r3944realms.lib39.content.item.DollItem;
|
||||
|
||||
/**
|
||||
* The type Ex lib 39 items.
|
||||
*/
|
||||
public class Lib39Items {
|
||||
/**
|
||||
* The constant ITEMS.
|
||||
*/
|
||||
public static final DeferredRegister<Item> ITEMS = DeferredRegister.create(ForgeRegistries.ITEMS, Lib39.MOD_ID);
|
||||
|
||||
/**
|
||||
* The constant DOLL.
|
||||
*/
|
||||
public static final RegistryObject<Item> DOLL = ITEMS.register("doll", () -> new DollItem(new Item.Properties()));
|
||||
|
||||
/**
|
||||
* Register.
|
||||
*
|
||||
* @param bus the bus
|
||||
*/
|
||||
public static void register(IEventBus bus) {
|
||||
ITEMS.register(bus);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,48 +0,0 @@
|
|||
package top.r3944realms.lib39.content.register;
|
||||
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.sounds.SoundEvent;
|
||||
import net.minecraftforge.eventbus.api.IEventBus;
|
||||
import net.minecraftforge.registries.DeferredRegister;
|
||||
import net.minecraftforge.registries.ForgeRegistries;
|
||||
import net.minecraftforge.registries.RegistryObject;
|
||||
import top.r3944realms.lib39.Lib39;
|
||||
|
||||
/**
|
||||
* The type Lib 39 sound events.
|
||||
*/
|
||||
public class Lib39SoundEvents {
|
||||
/**
|
||||
* The constant SOUND_EVENTS.
|
||||
*/
|
||||
public static final DeferredRegister<SoundEvent> SOUND_EVENTS = DeferredRegister.create(ForgeRegistries.SOUND_EVENTS, Lib39.MOD_ID);
|
||||
/**
|
||||
* The constant RL_DUCK_TOY.
|
||||
*/
|
||||
public static final ResourceLocation RL_DUCK_TOY = Lib39.rl("duck_toy");
|
||||
/**
|
||||
* The constant DUCK_TOY.
|
||||
*/
|
||||
public static final RegistryObject<SoundEvent> DUCK_TOY = SOUND_EVENTS.register("duck_toy",
|
||||
() -> SoundEvent.createFixedRangeEvent(RL_DUCK_TOY, 32.0f));
|
||||
|
||||
/**
|
||||
* Register.
|
||||
*
|
||||
* @param bus the bus
|
||||
*/
|
||||
public static void register(IEventBus bus) {
|
||||
SOUND_EVENTS.register(bus);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets sub title translate key.
|
||||
*
|
||||
* @param name the name
|
||||
* @return the sub title translate key
|
||||
*/
|
||||
public static String getSubTitleTranslateKey(String name) {
|
||||
return "sound." + Lib39.MOD_ID + ".subtitle." + name;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,547 +0,0 @@
|
|||
package top.r3944realms.lib39.core.command;
|
||||
|
||||
import net.minecraft.ChatFormatting;
|
||||
import net.minecraft.commands.CommandSourceStack;
|
||||
import net.minecraft.network.chat.*;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import top.r3944realms.lib39.base.datagen.value.Lib39LangKey;
|
||||
import top.r3944realms.lib39.core.command.model.CommandNode;
|
||||
import top.r3944realms.lib39.core.command.model.CommandPath;
|
||||
import top.r3944realms.lib39.core.command.model.Parameter;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
/**
|
||||
* The interface Command help manager.
|
||||
*/
|
||||
public interface ICommandHelpManager {
|
||||
/**
|
||||
* The constant NEWLINE.
|
||||
*/
|
||||
String NEWLINE = "\n";
|
||||
|
||||
/**
|
||||
* Gets id.
|
||||
*
|
||||
* @return the id
|
||||
*/
|
||||
ResourceLocation getID();
|
||||
|
||||
/**
|
||||
* Gets head key.
|
||||
*
|
||||
* @return the head key
|
||||
*/
|
||||
String getHeadKey();
|
||||
|
||||
/**
|
||||
* Gets command head.
|
||||
*
|
||||
* @return the command head
|
||||
*/
|
||||
default String getCommandHead() {
|
||||
return getID().getNamespace();
|
||||
}
|
||||
|
||||
/**
|
||||
* Init command node.
|
||||
*
|
||||
* @return the command node
|
||||
*/
|
||||
default CommandNode init() {
|
||||
CommandNode root;
|
||||
root = new CommandNode(this, getCommandHead(), Component.translatable(Lib39LangKey.Message.HELP_HEADER.getKey(), Component.translatable(getHeadKey())), true);
|
||||
root.addChild(new CommandNode(this, "help", Component.translatable(Lib39LangKey.Message.BASIC_HELP.getKey())));
|
||||
return root;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets cache.
|
||||
*
|
||||
* @return the cache
|
||||
*/
|
||||
Map<Integer, CommandNode> getCache();
|
||||
|
||||
/**
|
||||
* Gets root node.
|
||||
*
|
||||
* @return the root node
|
||||
*/
|
||||
CommandNode getRootNode();
|
||||
|
||||
/**
|
||||
* Register command help.
|
||||
*
|
||||
* @param commandNode the command node
|
||||
* @param description the description
|
||||
*/
|
||||
default void registerCommandHelp(@NotNull CommandNode commandNode, MutableComponent description) {
|
||||
registerCommandHelp(commandNode.getFullPath(), description);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register command help.
|
||||
*
|
||||
* @param commandNode the command node
|
||||
* @param descriptionKey the description key
|
||||
*/
|
||||
default void registerCommandHelp(@NotNull CommandNode commandNode, String descriptionKey) {
|
||||
registerCommandHelp(commandNode.getFullPath(), Component.translatable(descriptionKey));
|
||||
}
|
||||
|
||||
/**
|
||||
* Register command help.
|
||||
*
|
||||
* @param commandPath the command path
|
||||
*/
|
||||
default void registerCommandHelp(@NotNull CommandPath commandPath) {
|
||||
registerCommandHelp(commandPath.fullPath(), Component.literal(""));
|
||||
}
|
||||
|
||||
/**
|
||||
* Register command parameters.
|
||||
*
|
||||
* @param commandPath the command path
|
||||
* @param parameters the parameters
|
||||
*/
|
||||
default void registerCommandParameters(@NotNull CommandPath commandPath, @NotNull Parameter.Builder parameters) {
|
||||
registerCommandParameters(commandPath.fullPath(), parameters.build());
|
||||
}
|
||||
|
||||
private void registerCommandHelp(@NotNull String commandPath, MutableComponent description) {
|
||||
String[] pathParts = commandPath.split(" ");
|
||||
CommandNode currentNode = getRootNode();
|
||||
|
||||
int startIndex = pathParts[0].equals(getRootNode().getName()) ? 1 : 0;
|
||||
|
||||
for (int i = startIndex; i < pathParts.length; i++) {
|
||||
String part = pathParts[i];
|
||||
CommandNode child = currentNode.getChild(part);
|
||||
|
||||
if (child == null) {
|
||||
MutableComponent nodeDescription = (i == pathParts.length - 1) ? description : Component.literal("");
|
||||
child = new CommandNode(this, part, nodeDescription);
|
||||
currentNode.addChild(child);
|
||||
}
|
||||
|
||||
currentNode = child;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 註冊命令幫助節點
|
||||
*
|
||||
* @param builder the builder
|
||||
*/
|
||||
default void registerCommand(@NotNull CommandNode.Builder builder) {
|
||||
CommandNode newRoot = builder.build();
|
||||
mergeTree(getRootNode(), newRoot);
|
||||
}
|
||||
|
||||
/**
|
||||
* Merge tree.
|
||||
*
|
||||
* @param target the target
|
||||
* @param source the source
|
||||
*/
|
||||
void mergeTree(@NotNull CommandNode target, @NotNull CommandNode source);
|
||||
|
||||
/**
|
||||
* 使用Builder模式註冊命令樹
|
||||
*
|
||||
* @param builder the builder
|
||||
*/
|
||||
default void registerCommandTree(@NotNull CommandNode.Builder builder) {
|
||||
registerCommand(builder);
|
||||
}
|
||||
|
||||
/**
|
||||
* 使用Builder模式快速註冊命令
|
||||
*
|
||||
* @param configurator the configurator
|
||||
*/
|
||||
default void registerCommands(@NotNull Consumer<CommandNode.Builder> configurator) {
|
||||
CommandNode.Builder builder = CommandNode.Builder.of(this);
|
||||
configurator.accept(builder);
|
||||
registerCommand(builder);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据路径查找节点
|
||||
*
|
||||
* @param path the path
|
||||
* @return the optional
|
||||
*/
|
||||
default Optional<CommandNode> findNode(CommandPath path) {
|
||||
CommandNode currentNode = getRootNode();
|
||||
String[] segments = path.segments();
|
||||
|
||||
// 跳过根节点(如果路径包含)
|
||||
int startIndex = segments[0].equals(getRootNode().getName()) ? 1 : 0;
|
||||
|
||||
for (int i = startIndex; i < segments.length; i++) {
|
||||
currentNode = currentNode.getChild(segments[i]);
|
||||
if (currentNode == null) {
|
||||
return Optional.empty();
|
||||
}
|
||||
}
|
||||
|
||||
return Optional.of(currentNode);
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查命令是否存在
|
||||
*
|
||||
* @param path the path
|
||||
* @return the boolean
|
||||
*/
|
||||
default boolean hasCommand(CommandPath path) {
|
||||
return findNode(path).isPresent();
|
||||
}
|
||||
|
||||
private void registerCommandHelp(String commandPath, String descriptionKey) {
|
||||
registerCommandHelp(commandPath, Component.translatable(descriptionKey));
|
||||
}
|
||||
|
||||
private void registerCommandHelp(String commandPath) {
|
||||
registerCommandHelp(commandPath, Component.literal(""));
|
||||
}
|
||||
|
||||
/**
|
||||
* 注册命令参数(支持单个参数可选标记,使用*前缀表示必选参数)
|
||||
*
|
||||
* @param commandPath 命令路径,如 "fpsm tacz dummy"
|
||||
* @param parameters 参数列表,如 "*requiredParam", "optionalParam"
|
||||
*/
|
||||
private void registerCommandParameters(@NotNull String commandPath, Parameter... parameters) {
|
||||
String[] pathParts = commandPath.split(" ");
|
||||
CommandNode currentNode = getRootNode();
|
||||
|
||||
// 遍历命令路径,找到目标节点
|
||||
int startIndex = pathParts[0].equals(getRootNode().getName()) ? 1 : 0;
|
||||
|
||||
for (int i = startIndex; i < pathParts.length; i++) {
|
||||
String part = pathParts[i];
|
||||
CommandNode child = currentNode.getChild(part);
|
||||
|
||||
if (child == null) {
|
||||
// 如果节点不存在,创建空描述节点
|
||||
child = new CommandNode(this, part, Component.literal(""));
|
||||
currentNode.addChild(child);
|
||||
}
|
||||
|
||||
currentNode = child;
|
||||
}
|
||||
|
||||
// 添加参数,处理可选标记
|
||||
for (Parameter param : parameters) {
|
||||
currentNode.addParameter(param.name(), param.required());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 动态添加子指令到指定命令路径
|
||||
*
|
||||
* @param commandPath 命令路径,如 "fpsm map modify"
|
||||
* @param childName 子指令名称
|
||||
* @param description 子指令描述
|
||||
* @return 是否添加成功 boolean
|
||||
*/
|
||||
default boolean addChildCommand(@NotNull String commandPath, String childName, MutableComponent description) {
|
||||
String[] pathParts = commandPath.split(" ");
|
||||
CommandNode currentNode = getRootNode();
|
||||
|
||||
// 遍历命令路径,找到目标父节点
|
||||
for (String part : pathParts) {
|
||||
if (!part.equals(currentNode.getName())) {
|
||||
CommandNode child = currentNode.getChild(part);
|
||||
if (child == null) {
|
||||
// 路径不存在,创建中间节点
|
||||
child = new CommandNode(this, part, Component.literal(""));
|
||||
currentNode.addChild(child);
|
||||
}
|
||||
currentNode = child;
|
||||
}
|
||||
}
|
||||
|
||||
// 添加子指令
|
||||
CommandNode childNode = new CommandNode(this, childName, description);
|
||||
currentNode.addChild(childNode);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建单个命令节点的显示格式
|
||||
*
|
||||
* @param node 当前命令节点
|
||||
* @param indent 当前缩进
|
||||
* @param isRoot 是否为根节点
|
||||
* @return 格式化后的命令节点组件
|
||||
*/
|
||||
private @NotNull MutableComponent buildCommandLine(CommandNode node, String indent, boolean isRoot, @Nullable String currentFullPath) {
|
||||
if (isRoot) {
|
||||
// 根节点特殊处理
|
||||
String rootCommand = "/" + node.getName();
|
||||
return Component.literal(rootCommand)
|
||||
.withStyle(ChatFormatting.AQUA)
|
||||
.withStyle(Style.EMPTY
|
||||
.withClickEvent(new ClickEvent(
|
||||
ClickEvent.Action.SUGGEST_COMMAND,
|
||||
rootCommand + " "
|
||||
))
|
||||
.withHoverEvent(new HoverEvent(
|
||||
HoverEvent.Action.SHOW_TEXT,
|
||||
Component.translatable(Lib39LangKey.Message.HELP_HOVER_COPY_TIP.getKey())
|
||||
))
|
||||
);
|
||||
} else {
|
||||
// 构建完整命令路径
|
||||
String fullCommand = (currentFullPath != null && !currentFullPath.isEmpty())
|
||||
? currentFullPath + " " + node.getName()
|
||||
: "/" + getRootNode().getName() + " " + node.getFullPath();
|
||||
|
||||
// 构建建议的命令(带参数占位符)
|
||||
String suggestedCommand = buildSuggestedCommand(node, fullCommand);
|
||||
|
||||
// 非根节点:显示命令和描述
|
||||
MutableComponent prefix = Component.literal(indent + "└─ ").withStyle(ChatFormatting.GRAY);
|
||||
|
||||
// 命令名称(可点击)
|
||||
MutableComponent commandName = Component.literal(node.getName())
|
||||
.withStyle(ChatFormatting.DARK_AQUA)
|
||||
.withStyle(Style.EMPTY
|
||||
.withClickEvent(new ClickEvent(
|
||||
ClickEvent.Action.SUGGEST_COMMAND,
|
||||
suggestedCommand
|
||||
))
|
||||
.withHoverEvent(new HoverEvent(
|
||||
HoverEvent.Action.SHOW_TEXT,
|
||||
Component.translatable(Lib39LangKey.Message.HELP_HOVER_COPY_TIP.getKey(), suggestedCommand)
|
||||
))
|
||||
);
|
||||
|
||||
MutableComponent displayLine = prefix.append(commandName);
|
||||
|
||||
// 添加参数显示(只显示,不添加额外空格)
|
||||
if (!node.getParameters().isEmpty()) {
|
||||
displayLine.append(Component.literal(" ")); // 命令名和参数之间的空格
|
||||
|
||||
for (int i = 0; i < node.getParameters().size(); i++) {
|
||||
Parameter param = node.getParameters().get(i);
|
||||
if (param.required()) {
|
||||
displayLine.append(Component.literal("<").withStyle(ChatFormatting.GRAY))
|
||||
.append(Component.literal(param.name()).withStyle(ChatFormatting.WHITE))
|
||||
.append(Component.literal(">").withStyle(ChatFormatting.GRAY));
|
||||
} else {
|
||||
displayLine.append(Component.literal("[").withStyle(ChatFormatting.GRAY))
|
||||
.append(Component.literal(param.name()).withStyle(ChatFormatting.WHITE))
|
||||
.append(Component.literal("]").withStyle(ChatFormatting.GRAY));
|
||||
}
|
||||
|
||||
// 参数之间添加空格(除了最后一个)
|
||||
if (i < node.getParameters().size() - 1) {
|
||||
displayLine.append(Component.literal(" "));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 添加分隔符和描述
|
||||
displayLine.append(Component.literal(" - ").withStyle(ChatFormatting.DARK_GRAY))
|
||||
.append(node.getDescription().copy().withStyle(ChatFormatting.GRAY));
|
||||
|
||||
// 如果有子节点,添加展开/折叠按钮
|
||||
boolean shouldShowToggle = node.hasChildren() && !node.isLeaf();
|
||||
|
||||
if (shouldShowToggle) {
|
||||
String toggleKey = node.isExpanded()
|
||||
? Lib39LangKey.Message.HELP_NODE_TOGGLE_COLLAPSE.getKey()
|
||||
: Lib39LangKey.Message.HELP_NODE_TOGGLE_EXPAND.getKey();
|
||||
|
||||
MutableComponent toggleButton = Component.literal(" [")
|
||||
.withStyle(ChatFormatting.GRAY)
|
||||
.append(Component.translatable(toggleKey).withStyle(ChatFormatting.YELLOW))
|
||||
.append(Component.literal("]").withStyle(ChatFormatting.GRAY));
|
||||
|
||||
// 为按钮添加点击事件
|
||||
toggleButton.withStyle(Style.EMPTY
|
||||
.withClickEvent(new ClickEvent(
|
||||
ClickEvent.Action.RUN_COMMAND,
|
||||
"/" + getCommandHead() + " help toggle " + node.hashCode()
|
||||
))
|
||||
.withHoverEvent(new HoverEvent(
|
||||
HoverEvent.Action.SHOW_TEXT,
|
||||
Component.translatable(Lib39LangKey.Message.HELP_CLICK_EXPAND.getKey())
|
||||
.withStyle(ChatFormatting.GRAY)
|
||||
))
|
||||
);
|
||||
|
||||
displayLine.append(toggleButton);
|
||||
}
|
||||
|
||||
return displayLine;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建建议的命令(包含参数占位符)
|
||||
*/
|
||||
private @NotNull String buildSuggestedCommand(@NotNull CommandNode node, @NotNull String baseCommand) {
|
||||
StringBuilder sb = new StringBuilder(baseCommand);
|
||||
|
||||
// 如果有参数,添加参数占位符
|
||||
if (!node.getParameters().isEmpty()) {
|
||||
for (Parameter param : node.getParameters()) {
|
||||
sb.append(" ");
|
||||
if (param.required()) {
|
||||
sb.append("<").append(param.name()).append(">");
|
||||
} else {
|
||||
sb.append("[").append(param.name()).append("]");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 如果是叶子节点且没有参数,添加空格以便继续输入
|
||||
if (node.isLeaf() && node.getParameters().isEmpty()) {
|
||||
sb.append(" ");
|
||||
}
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 檢查節點是否應該顯示摺疊信息
|
||||
*/
|
||||
private boolean shouldShowCollapsedInfo(@NotNull CommandNode node) {
|
||||
return node.hasChildren() && !node.isExpanded() && !node.getChildren().isEmpty();
|
||||
}
|
||||
|
||||
/**
|
||||
* 獲取有效的子命令數量(過濾掉空描述的命令)
|
||||
*/
|
||||
private long getValidChildCount(@NotNull CommandNode node) {
|
||||
return node.getChildren().stream()
|
||||
.filter(child -> !child.getDescription().getString().isEmpty())
|
||||
.count();
|
||||
}
|
||||
|
||||
/**
|
||||
* 遞歸構建命令樹
|
||||
*/
|
||||
private void buildCommandTreeString(@NotNull CommandNode node,
|
||||
@NotNull String indent,
|
||||
@Nullable String currentFullPath,
|
||||
@NotNull List<MutableComponent> result,
|
||||
CommandSourceStack commandSourceStack) {
|
||||
boolean isRoot = indent.isEmpty();
|
||||
if (node.testPermission(commandSourceStack)) {
|
||||
MutableComponent commandLine = buildCommandLine(node, indent, isRoot, currentFullPath);
|
||||
result.add(commandLine.append(Component.literal(NEWLINE)));
|
||||
|
||||
// 遞歸處理子節點
|
||||
String childIndent = indent + "| ";
|
||||
if (node.isExpanded()) {
|
||||
String newFullPath = (currentFullPath != null && !currentFullPath.isEmpty())
|
||||
? currentFullPath + " " + node.getName()
|
||||
: "/" + node.getName();
|
||||
|
||||
for (CommandNode child : node.getChildren()) {
|
||||
// 只顯示有描述的子命令
|
||||
if (!child.getDescription().getString().isEmpty() && node.testPermission(commandSourceStack)) {
|
||||
buildCommandTreeString(child, childIndent, newFullPath, result, commandSourceStack);
|
||||
}
|
||||
}
|
||||
} else if (shouldShowCollapsedInfo(node)) {
|
||||
long childCount = getValidChildCount(node);
|
||||
if (childCount > 0) {
|
||||
MutableComponent collapsedInfo = Component.literal(indent + "| " + "└─ ")
|
||||
.withStyle(ChatFormatting.GRAY)
|
||||
.append(Component.translatable(
|
||||
Lib39LangKey.Message.HELP_NODE_EXPAND.getKey(),
|
||||
childCount
|
||||
).withStyle(ChatFormatting.GRAY));
|
||||
|
||||
collapsedInfo.withStyle(Style.EMPTY
|
||||
.withClickEvent(new ClickEvent(
|
||||
ClickEvent.Action.RUN_COMMAND,
|
||||
"/" + getCommandHead() + " help toggle " + node.hashCode()
|
||||
))
|
||||
.withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, Component.translatable(Lib39LangKey.Message.HELP_CLICK_EXPAND.getKey())))
|
||||
);
|
||||
|
||||
result.add(collapsedInfo.append(Component.literal(NEWLINE)));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取命令树的字符串表示
|
||||
*
|
||||
* @return 命令树列表 command tree
|
||||
*/
|
||||
default List<MutableComponent> getCommandTree(CommandSourceStack commandSourceStack) {
|
||||
List<MutableComponent> result = new ArrayList<>();
|
||||
buildCommandTreeString(getRootNode(), "", "", result, commandSourceStack);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 切换指定节点的展开/闭合状态
|
||||
*
|
||||
* @param hashCode 节点哈希值
|
||||
* @return 是否成功切换 boolean
|
||||
*/
|
||||
default boolean toggleNodeExpanded(int hashCode) {
|
||||
CommandNode currentNode = getCache().getOrDefault(hashCode, null);
|
||||
if (currentNode == null || currentNode.getChildren().isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
currentNode.toggleExpanded();
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建帮助消息
|
||||
*
|
||||
* @param header 帮助头部
|
||||
* @param entries 帮助条目列表
|
||||
* @return the mutable component
|
||||
*/
|
||||
default MutableComponent buildHelpMessage(@NotNull Component header, @NotNull List<MutableComponent> entries) {
|
||||
MutableComponent helpMessage = Component.empty();
|
||||
// 添加头部
|
||||
helpMessage.append(header.copy()).append(NEWLINE);
|
||||
|
||||
// 添加分隔线
|
||||
helpMessage.append(Component.literal("\n"));
|
||||
|
||||
|
||||
// 添加当前页的帮助内容
|
||||
if (entries.isEmpty()) {
|
||||
helpMessage.append(Component.translatable(Lib39LangKey.Message.HELP_NO_ENTRIES.getKey())).append(NEWLINE);
|
||||
} else {
|
||||
for (MutableComponent entry : entries) {
|
||||
helpMessage.append(entry);
|
||||
}
|
||||
}
|
||||
|
||||
return helpMessage;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build command tree help mutable component.
|
||||
*
|
||||
* @return the mutable component
|
||||
*/
|
||||
default MutableComponent buildCommandTreeHelp(CommandSourceStack commandSourceStack) {
|
||||
List<MutableComponent> commandTree = getCommandTree(commandSourceStack);
|
||||
return buildHelpMessage(Component.translatable(Lib39LangKey.Message.HELP_HEADER.getKey(), Component.translatable(getHeadKey())), commandTree);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,133 +0,0 @@
|
|||
package top.r3944realms.lib39.core.command;
|
||||
|
||||
import com.mojang.brigadier.CommandDispatcher;
|
||||
import com.mojang.brigadier.arguments.IntegerArgumentType;
|
||||
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
||||
import com.mojang.brigadier.context.CommandContext;
|
||||
import net.minecraft.commands.CommandBuildContext;
|
||||
import net.minecraft.commands.CommandSourceStack;
|
||||
import net.minecraft.commands.Commands;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.network.chat.MutableComponent;
|
||||
import net.minecraftforge.common.MinecraftForge;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import top.r3944realms.lib39.api.event.RegisterCommandHelpEvent;
|
||||
import top.r3944realms.lib39.base.datagen.value.Lib39LangKey;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* The interface Help command.
|
||||
*/
|
||||
public interface IHelpCommand {
|
||||
/**
|
||||
* Should show toggle failed boolean.
|
||||
*
|
||||
* @return the boolean
|
||||
*/
|
||||
default boolean shouldShowToggleFailed() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets help head.
|
||||
*
|
||||
* @return the help head
|
||||
*/
|
||||
@Nullable
|
||||
default LiteralArgumentBuilder<CommandSourceStack> getHelpHead() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets command help manager.
|
||||
*
|
||||
* @return the command help manager
|
||||
*/
|
||||
ICommandHelpManager getCommandHelpManager();
|
||||
|
||||
/**
|
||||
* Build command literal argument builder.
|
||||
*
|
||||
* @param dispatcher the dispatcher
|
||||
* @param context the context
|
||||
* @return the literal argument builder
|
||||
*/
|
||||
default LiteralArgumentBuilder<CommandSourceStack> buildCommand(CommandDispatcher<CommandSourceStack> dispatcher, CommandBuildContext context) {
|
||||
LiteralArgumentBuilder<CommandSourceStack> head = getHelpHead();
|
||||
if (head == null) {
|
||||
head = LiteralArgumentBuilder.literal(getCommandHelpManager().getID().getNamespace());
|
||||
}
|
||||
LiteralArgumentBuilder<CommandSourceStack> tree = head.requires(this::requestPermission)
|
||||
.then(Commands.literal("help").executes(this::handleHelp)
|
||||
.then(Commands.literal("toggle")
|
||||
.then(Commands.argument("hash", IntegerArgumentType.integer()).executes(this::handleHelpToggle))
|
||||
));
|
||||
RegisterCommandHelpEvent registerHelpCommandEvent = new RegisterCommandHelpEvent(tree, getCommandHelpManager(), context);
|
||||
MinecraftForge.EVENT_BUS.post(registerHelpCommandEvent);
|
||||
dispatcher.register(head);
|
||||
return head;
|
||||
}
|
||||
|
||||
/**
|
||||
* Request permission boolean.
|
||||
*
|
||||
* @param context the context
|
||||
* @return the boolean
|
||||
*/
|
||||
default boolean requestPermission(CommandSourceStack context) {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle help int.
|
||||
*
|
||||
* @param context the context
|
||||
* @return the int
|
||||
*/
|
||||
default int handleHelp(@NotNull CommandContext<CommandSourceStack> context) {
|
||||
ICommandHelpManager commandHelpManager = getCommandHelpManager();
|
||||
MutableComponent helpMessage = commandHelpManager.buildCommandTreeHelp(context.getSource());
|
||||
sendSuccess(context.getSource(), helpMessage);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle help toggle int.
|
||||
*
|
||||
* @param context the context
|
||||
* @return the int
|
||||
*/
|
||||
default int handleHelpToggle(@NotNull CommandContext<CommandSourceStack> context) {
|
||||
int hash = IntegerArgumentType.getInteger(context, "hash");
|
||||
ICommandHelpManager commandHelpManager = getCommandHelpManager();
|
||||
boolean success = commandHelpManager.toggleNodeExpanded(hash);
|
||||
if (success) {
|
||||
MutableComponent helpMessage = Component.literal("\n".repeat(2)).append(commandHelpManager.buildCommandTreeHelp(context.getSource()));
|
||||
sendSuccess(context.getSource(), helpMessage);
|
||||
} else if (shouldShowToggleFailed()) {
|
||||
sendFailure(context.getSource(), Component.translatable(Lib39LangKey.Message.HELP_TOGGLE_FAILED.getKey()));
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send success.
|
||||
*
|
||||
* @param source the source
|
||||
* @param key the key
|
||||
*/
|
||||
static void sendSuccess(@NotNull CommandSourceStack source, Component key) {
|
||||
source.sendSuccess(() -> key, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send failure.
|
||||
*
|
||||
* @param source the source
|
||||
* @param key the key
|
||||
*/
|
||||
static void sendFailure(@NotNull CommandSourceStack source, Component key) {
|
||||
source.sendFailure(key);
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user