Compare commits
6 Commits
MultiLoade
...
MultiLoade
| Author | SHA1 | Date | |
|---|---|---|---|
| 15ab233b04 | |||
| fe186cd36b | |||
| fe3d3478a9 | |||
| 805d880ed9 | |||
| fbaeaf857b | |||
| 4a22bbe4a9 |
18
AITask.md
Normal file
18
AITask.md
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
# 任务:多平台模组项目迁移(1.21.1 → 26.1.2)
|
||||
|
||||
## 背景
|
||||
我的 Minecraft 模组当前基于 **MultiLoader 1.21.1**(对应 Minecraft 1.21.1)。
|
||||
目标版本为 **26.1.2**(对应 Minecraft 26.1.2)。
|
||||
从 1.21.1 升级到 26.1.x,期间 API 发生了破坏性变更。
|
||||
|
||||
# 请只关注 common、fabric、neoforge文件下的src文件里的java部分
|
||||
其它以外的文件已经配置好了
|
||||
|
||||
## 核心变更参考
|
||||
请参考 项目里的中的迁移指南(Primers):[Doc](/primers-doc)
|
||||
|
||||
特别关注以下版本的变更(按从低到高依次应用):
|
||||
- 1.21 → 1.21.1
|
||||
- 1.21.1 → 1.21.2
|
||||
- 1.21.2 → 1.21.3
|
||||
- 依此类推,直到 26.1.2 对应的版本
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
plugins {
|
||||
id 'fabric-loom' version '1.9-SNAPSHOT' apply(false)
|
||||
id 'net.neoforged.moddev.legacyforge' version '2.0.103' apply(false)
|
||||
id 'net.fabricmc.fabric-loom' version '1.15.5' apply false
|
||||
id 'net.neoforged.moddev' version '2.0.141' apply false
|
||||
}
|
||||
|
|
@ -26,19 +26,6 @@ repositories {
|
|||
}
|
||||
filter { includeGroupAndSubgroups('org.spongepowered') }
|
||||
}
|
||||
exclusiveContent {
|
||||
forRepositories(
|
||||
maven {
|
||||
name = 'ParchmentMC'
|
||||
url = 'https://maven.parchmentmc.org/'
|
||||
},
|
||||
maven { url = "https://neoforged.forgecdn.net/releases" },
|
||||
maven { url = "https://neoforged.forgecdn.net/mojang-meta" }
|
||||
)
|
||||
filter { includeGroup('org.parchmentmc.data') }
|
||||
}
|
||||
maven { url = "https://libraries.minecraft.net/" }
|
||||
|
||||
|
||||
maven {
|
||||
url "https://cursemaven.com"
|
||||
|
|
@ -48,22 +35,13 @@ repositories {
|
|||
name = 'BlameJared'
|
||||
url = 'https://maven.blamejared.com'
|
||||
}
|
||||
}
|
||||
|
||||
// Declare capabilities on the outgoing configurations.
|
||||
// Read more about capabilities here: https://docs.gradle.org/current/userguide/component_capabilities.html#sec:declaring-additional-capabilities-for-a-local-component
|
||||
['apiElements', 'runtimeElements', 'sourcesElements', 'javadocElements'].each { variant ->
|
||||
configurations."$variant".outgoing {
|
||||
capability("$group:${project.name}:$version")
|
||||
capability("$group:${base.archivesName.get()}:$version")
|
||||
capability("$group:$mod_id-${project.name}-${minecraft_version}:$version")
|
||||
capability("$group:$mod_id:$version")
|
||||
maven {
|
||||
name = 'LTDNexus'
|
||||
url = 'https://nexus.bot.leisuretimedock.top/repository/maven-releases/'
|
||||
}
|
||||
publishing.publications.configureEach {
|
||||
suppressPomMetadataWarningsFor(variant)
|
||||
}
|
||||
}
|
||||
maven { url 'https://maven.covers1624.net/' }
|
||||
|
||||
}
|
||||
sourcesJar {
|
||||
from(rootProject.file('LICENSE')) {
|
||||
rename { "${it}_${mod_name}" }
|
||||
|
|
@ -101,8 +79,10 @@ processResources {
|
|||
'mod_id' : mod_id,
|
||||
'license' : license,
|
||||
'description' : project.description,
|
||||
"forge_version" : forge_version,
|
||||
"forge_loader_version_range" : forge_loader_version_range,
|
||||
'neoforge_version' : neoforge_version,
|
||||
'neoforge_loader_version_range': neoforge_loader_version_range,
|
||||
"neoforge_version": neoforge_version,
|
||||
"neoforge_loader_version_range": neoforge_loader_version_range,
|
||||
'credits' : credits,
|
||||
'java_version' : java_version
|
||||
]
|
||||
|
|
@ -111,7 +91,7 @@ processResources {
|
|||
key, value -> [(key): value instanceof String ? value.replace("\n", "\\\\n") : value]
|
||||
}
|
||||
|
||||
filesMatching(['META-INF/mods.toml']) {
|
||||
filesMatching(['META-INF/mods.toml', 'META-INF/neoforge.mods.toml']) {
|
||||
expand expandProps
|
||||
}
|
||||
|
||||
|
|
@ -130,19 +110,18 @@ publishing {
|
|||
pom {
|
||||
name = 'Lib39'
|
||||
description = 'Lib39 is a general-purpose dependency library for Minecraft mods.'
|
||||
url = 'https://github.com/3944Realms/lib39'
|
||||
url = 'https://gitea.bot.leisuretimedock.top/R3944Realms/Lib39'
|
||||
|
||||
properties = [
|
||||
'minecraft.version': project.minecraft_version,
|
||||
'mod.version': project.version,
|
||||
'forge.version': project.forge_version,
|
||||
'java.version': '17'
|
||||
'java.version': project.java_version
|
||||
]
|
||||
|
||||
licenses {
|
||||
license {
|
||||
name = 'MIT'
|
||||
url = 'https://raw.githubusercontent.com/3944Realms/lib39/refs/heads/main/LICENSE'
|
||||
url = 'https://gitea.bot.leisuretimedock.top/R3944Realms/Lib39/raw/branch/MultiLoader_26_1_2/LICENSE'
|
||||
distribution = 'repo'
|
||||
}
|
||||
}
|
||||
|
|
@ -156,15 +135,15 @@ publishing {
|
|||
}
|
||||
|
||||
scm {
|
||||
connection = 'scm:git:https://github.com/3944Realms/lib39.git'
|
||||
developerConnection = 'scm:git:ssh://git@github.com:3944Realms/lib39.git'
|
||||
url = 'https://github.com/3944Realms/lib39'
|
||||
connection = 'scm:git:git@bot.leisuretimedock.top:R3944Realms/Lib39.git'
|
||||
developerConnection = 'scm:git:ssh://git@bot.leisuretimedock.top:R3944Realms/Lib39.git'
|
||||
url = 'https://gitea.bot.leisuretimedock.top/R3944Realms/Lib39'
|
||||
tag = 'main'
|
||||
}
|
||||
|
||||
issueManagement {
|
||||
system = 'GitHub'
|
||||
url = 'https://github.com/3944Realms/lib39/issues'
|
||||
system = 'Gitea'
|
||||
url = 'https://gitea.bot.leisuretimedock.top/R3944Realms/Lib39/issues'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,8 +13,9 @@ configurations {
|
|||
|
||||
dependencies {
|
||||
compileOnly(project(':common')) {
|
||||
capabilities {
|
||||
requireCapability "$group:$mod_id"
|
||||
def loaderAttribute = Attribute.of('io.github.mcgradleconventions.loader', String)
|
||||
attributes {
|
||||
attribute(loaderAttribute, 'common')
|
||||
}
|
||||
}
|
||||
commonJava project(path: ':common', configuration: 'commonJava')
|
||||
|
|
@ -36,10 +37,11 @@ tasks.named('javadoc', Javadoc).configure {
|
|||
source(configurations.commonJava)
|
||||
options.encoding = 'UTF-8'
|
||||
options.charSet = 'UTF-8'
|
||||
options.links("https://docs.oracle.com/en/java/javase/17/docs/api/")
|
||||
options.links("https://docs.oracle.com/en/java/javase/25/docs/api/")
|
||||
options.memberLevel = JavadocMemberLevel.PUBLIC
|
||||
options.addBooleanOption('Xdoclint:none', true)
|
||||
options.addStringOption('doctitle', "${mod_id} ${minecraft_version} ${version} Javadoc")
|
||||
|
||||
}
|
||||
|
||||
tasks.named('sourcesJar', Jar) {
|
||||
|
|
|
|||
|
|
@ -1,26 +1,30 @@
|
|||
plugins {
|
||||
id 'multiloader-common'
|
||||
id 'net.neoforged.moddev.legacyforge'
|
||||
id 'net.neoforged.moddev'
|
||||
}
|
||||
|
||||
legacyForge {
|
||||
mcpVersion = minecraft_version
|
||||
if (file("src/main/resources/META-INF/accesstransformer.cfg").exists()) {
|
||||
accessTransformers = ["src/main/resources/META-INF/accesstransformer.cfg"]
|
||||
}
|
||||
parchment {
|
||||
minecraftVersion = parchment_minecraft
|
||||
mappingsVersion = parchment_version
|
||||
neoForge {
|
||||
neoFormVersion = neo_form_version
|
||||
// Automatically enable AccessTransformers if the file exists
|
||||
def at = file('src/main/resources/META-INF/accesstransformer.cfg')
|
||||
if (at.exists()) {
|
||||
accessTransformers.from(at.absolutePath)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
dependencies {
|
||||
compileOnly(group: 'org.spongepowered', name: 'mixin', version: '0.8.5')
|
||||
implementation(group: 'tschipp.carryon', name: 'carryon-common-1.20.1', version: '2.1.2') {
|
||||
compileOnly group: 'org.spongepowered', name: 'mixin', version: '0.8.5'
|
||||
// fabric and neoforge both bundle mixinextras, so it is safe to use it in common
|
||||
compileOnly group: 'io.github.llamalad7', name: 'mixinextras-common', version: '0.5.3'
|
||||
annotationProcessor group: 'io.github.llamalad7', name: 'mixinextras-common', version: '0.5.3'
|
||||
|
||||
implementation(group: 'tschipp.carryon', name: 'carryon-common-26.1.2', version: '3.0.1') {
|
||||
transitive = false
|
||||
}
|
||||
implementation(annotationProcessor("io.github.llamalad7:mixinextras-common:0.2.0"))
|
||||
implementation(group: 'com.google.code.findbugs', name: 'jsr305', version: '3.0.1')
|
||||
// fabric and neoforge both bundle mixinextras, so it is safe to use it in common
|
||||
compileOnly group: 'io.github.llamalad7', name: 'mixinextras-common', version: '0.5.3'
|
||||
annotationProcessor group: 'io.github.llamalad7', name: 'mixinextras-common', version: '0.5.3'
|
||||
}
|
||||
configurations {
|
||||
commonJava {
|
||||
|
|
@ -41,3 +45,21 @@ artifacts {
|
|||
clean {
|
||||
delete 'generated'
|
||||
}
|
||||
|
||||
def loaderAttribute = Attribute.of('io.github.mcgradleconventions.loader', String)
|
||||
['apiElements', 'runtimeElements', 'sourcesElements', 'javadocElements'].each { variant ->
|
||||
configurations.named("$variant") {
|
||||
attributes {
|
||||
attribute(loaderAttribute, 'common')
|
||||
}
|
||||
}
|
||||
}
|
||||
sourceSets.configureEach {
|
||||
[it.compileClasspathConfigurationName, it.runtimeClasspathConfigurationName].each { variant->
|
||||
configurations.named("$variant") {
|
||||
attributes {
|
||||
attribute(loaderAttribute, 'common')
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
package top.r3944realms.lib39;
|
||||
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.resources.Identifier;
|
||||
import org.jetbrains.annotations.Contract;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.slf4j.Logger;
|
||||
|
|
@ -48,8 +48,8 @@ public class Lib39 {
|
|||
* @return the resource location
|
||||
*/
|
||||
@Contract("_ -> new")
|
||||
public static @NotNull ResourceLocation rl(String path) {
|
||||
return new ResourceLocation(Lib39.MOD_ID, path);
|
||||
public static @NotNull Identifier rl(String path) {
|
||||
return Identifier.fromNamespaceAndPath(Lib39.MOD_ID, path);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -60,8 +60,8 @@ public class Lib39 {
|
|||
* @return the resource location
|
||||
*/
|
||||
@Contract("_, _ -> new")
|
||||
public static @NotNull ResourceLocation rl(String modId, String path) {
|
||||
return new ResourceLocation(modId, path);
|
||||
public static @NotNull Identifier rl(String modId, String path) {
|
||||
return Identifier.fromNamespaceAndPath(modId, path);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -71,8 +71,8 @@ public class Lib39 {
|
|||
* @return the resource location
|
||||
*/
|
||||
@Contract("_ -> new")
|
||||
public static @NotNull ResourceLocation mrl(String path) {
|
||||
return new ResourceLocation(path);
|
||||
public static @NotNull Identifier mrl(String path) {
|
||||
return Identifier.withDefaultNamespace(path);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
package top.r3944realms.lib39.base.command;
|
||||
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.resources.Identifier;
|
||||
import top.r3944realms.lib39.Lib39;
|
||||
import top.r3944realms.lib39.core.command.SimpleCommandHelpManager;
|
||||
|
||||
|
|
@ -18,7 +18,7 @@ public class Lib39CommandHelpManager extends SimpleCommandHelpManager {
|
|||
/**
|
||||
* 作为唯一标识符
|
||||
*/
|
||||
ResourceLocation ID = Lib39.rl("command_helper");
|
||||
Identifier ID = Lib39.rl("command_helper");
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
|
|
@ -31,7 +31,7 @@ public class Lib39CommandHelpManager extends SimpleCommandHelpManager {
|
|||
}
|
||||
|
||||
@Override
|
||||
public ResourceLocation getID() {
|
||||
public Identifier getID() {
|
||||
return ID;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ 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.resources.Identifier;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import top.r3944realms.lib39.Lib39;
|
||||
|
|
@ -19,6 +19,7 @@ import top.r3944realms.lib39.core.command.ICommandHelpManager;
|
|||
import top.r3944realms.lib39.core.command.SimpleHelpCommand;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
|
|
@ -92,7 +93,7 @@ public class Lib39HelpCommand extends SimpleHelpCommand {
|
|||
.executes(this::executeCalculate)))
|
||||
)
|
||||
.then(Commands.literal("teleport")
|
||||
.requires(source -> source.hasPermission(2)) // 需要OP權限
|
||||
.requires(Commands.hasPermission(Commands.LEVEL_GAMEMASTERS)) // 需要游戏管理员權限
|
||||
.then(Commands.argument("target", EntityArgument.player())
|
||||
.executes(this::executeTeleport))
|
||||
)
|
||||
|
|
@ -284,12 +285,14 @@ public class Lib39HelpCommand extends SimpleHelpCommand {
|
|||
|
||||
if (source.getEntity() instanceof ServerPlayer player) {
|
||||
player.teleportTo(
|
||||
target.serverLevel(),
|
||||
target.level(),
|
||||
target.getX(),
|
||||
target.getY(),
|
||||
target.getZ(),
|
||||
Set.of(),
|
||||
target.getYRot(),
|
||||
target.getXRot()
|
||||
target.getXRot(),
|
||||
true
|
||||
);
|
||||
|
||||
source.sendSuccess(() ->
|
||||
|
|
@ -304,7 +307,7 @@ public class Lib39HelpCommand extends SimpleHelpCommand {
|
|||
|
||||
private int executeInfo(CommandContext<CommandSourceStack> context) {
|
||||
CommandSourceStack source = context.getSource();
|
||||
ResourceLocation dimension = source.getLevel().dimension().location();
|
||||
Identifier dimension = source.getLevel().dimension().identifier();
|
||||
|
||||
source.sendSuccess(() ->
|
||||
Component.translatable("commands.lib39.info.message")
|
||||
|
|
|
|||
|
|
@ -1,16 +1,13 @@
|
|||
package top.r3944realms.lib39.base.datagen.provider;
|
||||
|
||||
import net.minecraft.core.HolderLookup;
|
||||
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.data.recipes.*;
|
||||
import net.minecraft.tags.ItemTags;
|
||||
import net.minecraft.world.item.Items;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import top.r3944realms.lib39.core.register.Lib39Items;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
/**
|
||||
* The type Lib 39 recipe provider.
|
||||
|
|
@ -19,18 +16,19 @@ public class Lib39RecipeProvider extends RecipeProvider {
|
|||
/**
|
||||
* Instantiates a new Lib 39 recipe provider.
|
||||
*
|
||||
* @param output the output
|
||||
* @param output the output
|
||||
* @param registries the registries
|
||||
*/
|
||||
public Lib39RecipeProvider(PackOutput output) {
|
||||
super(output);
|
||||
public Lib39RecipeProvider(HolderLookup.Provider output, RecipeOutput recipeOutput) {
|
||||
super(output, recipeOutput);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void buildRecipes(@NotNull Consumer<FinishedRecipe> consumer) {
|
||||
ShapelessRecipeBuilder.shapeless(RecipeCategory.MISC, Lib39Items.DOLL.get())
|
||||
protected void buildRecipes() {
|
||||
this.shapeless(RecipeCategory.MISC, Lib39Items.DOLL.get())
|
||||
.requires(ItemTags.WOOL)
|
||||
.requires(Items.ARMOR_STAND)
|
||||
.unlockedBy("has_armor_stand",has(Items.ARMOR_STAND))
|
||||
.save(consumer);
|
||||
.save(this.output);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@ 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;
|
||||
|
|
@ -12,23 +11,20 @@ import net.minecraft.client.renderer.ShaderInstance;
|
|||
import net.minecraft.network.chat.Component;
|
||||
import org.joml.Matrix4f;
|
||||
import org.joml.Vector2f;
|
||||
import org.jspecify.annotations.NonNull;
|
||||
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.
|
||||
|
|
@ -78,6 +74,7 @@ public class WheelWidget extends AbstractWidget {
|
|||
private Vector2f selectionEffectPos;
|
||||
private boolean animationStarted = false;
|
||||
|
||||
|
||||
/**
|
||||
* Sets closing animation started.
|
||||
*
|
||||
|
|
@ -384,16 +381,15 @@ public class WheelWidget extends AbstractWidget {
|
|||
return this.sections.size();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean mouseScrolled(double mouseX, double mouseY, double delta) {
|
||||
if (delta > 0) {
|
||||
public boolean mouseScrolled(double mouseX, double mouseY, double scrollX, double scrollY) {
|
||||
if (scrollY > 0) {
|
||||
if (this.currentSectionIndex == this.getSectionSize() - 1) {
|
||||
this.currentSectionIndex = 0;
|
||||
} else {
|
||||
this.currentSectionIndex++;
|
||||
}
|
||||
} else if (delta < 0) {
|
||||
} else if (scrollY < 0) {
|
||||
if (this.currentSectionIndex == 0) {
|
||||
this.currentSectionIndex = this.getSectionSize() - 1;
|
||||
} else {
|
||||
|
|
@ -451,13 +447,8 @@ public class WheelWidget extends AbstractWidget {
|
|||
}
|
||||
|
||||
@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) {
|
||||
protected void renderWidget(GuiGraphics guiGraphics, int mouseX, int mouseY, float partialTick) {
|
||||
checkMousePos(mouseX, mouseY);
|
||||
RenderSystem.enableDepthTest();
|
||||
RenderSystem.enableBlend();
|
||||
this.renderClosingAnimation(guiGraphics);
|
||||
|
|
@ -596,8 +587,8 @@ public class WheelWidget extends AbstractWidget {
|
|||
PoseStack poseStack = guiGraphics.pose();
|
||||
poseStack.pushPose();
|
||||
|
||||
setupRingShader(centerX, centerY, innerRadius, outerRadius);
|
||||
Tesselator tesselator = Tesselator.getInstance();
|
||||
BufferBuilder buffer = tesselator.getBuilder();
|
||||
|
||||
// 计算足够大的绘制区域来覆盖整个环形(基于外半径)
|
||||
float margin = outerRadius + 100f; // 使用半径计算边距
|
||||
|
|
@ -606,17 +597,16 @@ public class WheelWidget extends AbstractWidget {
|
|||
float x2 = centerX + margin;
|
||||
float y2 = centerY + margin;
|
||||
|
||||
buffer.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION_COLOR);
|
||||
BufferBuilder buffer = tesselator.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();
|
||||
buffer.addVertex(matrix, x1, y1, -300).setColor(color);
|
||||
buffer.addVertex(matrix, x1, y2, -300).setColor(color);
|
||||
buffer.addVertex(matrix, x2, y2, -300).setColor(color);
|
||||
buffer.addVertex(matrix, x2, y1, -300).setColor(color);
|
||||
|
||||
setupRingShader(centerX, centerY, innerRadius, outerRadius);
|
||||
|
||||
BufferUploader.drawWithShader(buffer.end());
|
||||
BufferUploader.drawWithShader(buffer.build());
|
||||
RenderSystem.setShader(() -> null);
|
||||
poseStack.popPose();
|
||||
}
|
||||
|
||||
|
|
@ -691,7 +681,7 @@ public class WheelWidget extends AbstractWidget {
|
|||
* @param radius the radius
|
||||
*/
|
||||
public static void renderSelectionEffect(
|
||||
GuiGraphics guiGraphics,
|
||||
@NonNull GuiGraphics guiGraphics,
|
||||
float centerX,
|
||||
float centerY,
|
||||
int color,
|
||||
|
|
@ -703,17 +693,16 @@ public class WheelWidget extends AbstractWidget {
|
|||
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);
|
||||
BufferBuilder buffer = tesselator.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();
|
||||
buffer.addVertex(matrix4f, x1, y1, -200).setColor(color);
|
||||
buffer.addVertex(matrix4f, x1, y2, -200).setColor(color);
|
||||
buffer.addVertex(matrix4f, x2, y2, -200).setColor(color);
|
||||
buffer.addVertex(matrix4f, x2, y1, -200).setColor(color);
|
||||
|
||||
Window window = Minecraft.getInstance().getWindow();
|
||||
float guiScale = (float) window.getGuiScale();
|
||||
|
|
@ -732,11 +721,8 @@ public class WheelWidget extends AbstractWidget {
|
|||
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()));
|
||||
BufferUploader.drawWithShader(Objects.requireNonNull(buffer.build()));
|
||||
RenderSystem.enableDepthTest();
|
||||
}
|
||||
|
||||
|
|
@ -756,8 +742,15 @@ public class WheelWidget extends AbstractWidget {
|
|||
protected void updateWidgetNarration(NarrationElementOutput narrationElementOutput) {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* The type Wheel section.
|
||||
* @param center 中心
|
||||
* @param angle 角度
|
||||
* @param angleStart 开始角度
|
||||
* @param angleEnd 结束角度
|
||||
* @param subTitle 副标题
|
||||
* @param renderer 渲染操作
|
||||
*/
|
||||
public record WheelSection(
|
||||
Vector2f center,
|
||||
|
|
|
|||
|
|
@ -5,10 +5,10 @@ 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 org.jetbrains.annotations.Nullable;
|
||||
import top.r3944realms.lib39.Lib39;
|
||||
|
||||
/**
|
||||
|
|
@ -31,13 +31,57 @@ public class DollModel extends Model {
|
|||
private final ModelPart rightArmSlim;
|
||||
private final ModelPart leftArmSlim;
|
||||
private final ModelPart leftLeg;
|
||||
@Nullable
|
||||
private IDollPose currentPose;
|
||||
|
||||
/**
|
||||
* Gets current pose.
|
||||
*
|
||||
* @return the current pose
|
||||
*/
|
||||
@Nullable
|
||||
public IDollPose getCurrentPose() {
|
||||
return currentPose;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets doll pose.
|
||||
*
|
||||
* @param dollPose the doll pose
|
||||
*/
|
||||
public void setDollPose(@NotNull IDollPose dollPose) {
|
||||
this.currentPose = dollPose;
|
||||
this.head.loadPose(dollPose.getHeadPose());
|
||||
this.body.loadPose(dollPose.getBodyPose());
|
||||
this.rightArm.loadPose(dollPose.getRightArmPose());
|
||||
this.leftArm.loadPose(dollPose.getLeftArmPose());
|
||||
this.rightArmSlim.loadPose(dollPose.getRightArmPose());
|
||||
this.leftArmSlim.loadPose(dollPose.getLeftArmPose());
|
||||
this.rightLeg.loadPose(dollPose.getRightLegPose());
|
||||
this.leftLeg.loadPose(dollPose.getLeftLegPose());
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset pose.
|
||||
*/
|
||||
public void resetPose() {
|
||||
this.currentPose = DollPoses.DEFAULT;
|
||||
this.head.resetPose();
|
||||
this.body.resetPose();
|
||||
this.rightArm.resetPose();
|
||||
this.leftArm.resetPose();
|
||||
this.rightArmSlim.resetPose();
|
||||
this.leftArmSlim.resetPose();
|
||||
this.rightLeg.resetPose();
|
||||
this.leftLeg.resetPose();
|
||||
}
|
||||
|
||||
/**
|
||||
* Instantiates a new Doll model.
|
||||
*
|
||||
* @param root the root
|
||||
*/
|
||||
public DollModel(ModelPart root) {
|
||||
public DollModel(@NotNull ModelPart root) {
|
||||
super(RenderType::entityTranslucent);
|
||||
this.head = root.getChild("head");
|
||||
this.body = root.getChild("body");
|
||||
|
|
@ -54,38 +98,118 @@ public class DollModel extends Model {
|
|||
*
|
||||
* @return the layer definition
|
||||
*/
|
||||
public static LayerDefinition createBodyLayer() {
|
||||
public static @NotNull LayerDefinition createBodyLayer() {
|
||||
return createBodyLayer(DollPoses.DEFAULT);
|
||||
}
|
||||
|
||||
private static @NotNull LayerDefinition createBodyLayer(@NotNull IDollPose dollPoses) {
|
||||
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));
|
||||
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)
|
||||
), dollPoses.getHeadPose()
|
||||
);
|
||||
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)
|
||||
), dollPoses.getBodyPose()
|
||||
);
|
||||
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)
|
||||
), dollPoses.getRightArmPose()
|
||||
);
|
||||
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)
|
||||
), dollPoses.getRightArmPose()
|
||||
);
|
||||
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)
|
||||
), dollPoses.getLeftArmPose()
|
||||
);
|
||||
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)
|
||||
), dollPoses.getLeftArmPose()
|
||||
);
|
||||
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)
|
||||
), dollPoses.getRightLegPose()
|
||||
);
|
||||
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)
|
||||
), dollPoses.getLeftLegPose()
|
||||
);
|
||||
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) {
|
||||
public void renderToBuffer(@NotNull PoseStack poseStack, VertexConsumer vertexConsumer, int packedLight, int packedOverlay, int color) {
|
||||
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);
|
||||
this.head.render(poseStack, vertexConsumer, packedLight, packedOverlay, color);
|
||||
this.body.render(poseStack, vertexConsumer, packedLight, packedOverlay, color);
|
||||
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);
|
||||
this.rightArmSlim.render(poseStack, vertexConsumer, packedLight, packedOverlay, color);
|
||||
this.leftArmSlim.render(poseStack, vertexConsumer, packedLight, packedOverlay, color);
|
||||
} else {
|
||||
this.rightArm.render(poseStack, vertexConsumer, packedLight, packedOverlay, red, green, blue, alpha);
|
||||
this.leftArm.render(poseStack, vertexConsumer, packedLight, packedOverlay, red, green, blue, alpha);
|
||||
this.rightArm.render(poseStack, vertexConsumer, packedLight, packedOverlay, color);
|
||||
this.leftArm.render(poseStack, vertexConsumer, packedLight, packedOverlay, color);
|
||||
}
|
||||
|
||||
this.rightLeg.render(poseStack, vertexConsumer, packedLight, packedOverlay, red, green, blue, alpha);
|
||||
this.leftLeg.render(poseStack, vertexConsumer, packedLight, packedOverlay, red, green, blue, alpha);
|
||||
this.rightLeg.render(poseStack, vertexConsumer, packedLight, packedOverlay, color);
|
||||
this.leftLeg.render(poseStack, vertexConsumer, packedLight, packedOverlay, color);
|
||||
poseStack.popPose();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,93 @@
|
|||
package top.r3944realms.lib39.client.model;
|
||||
|
||||
import net.minecraft.client.model.geom.PartPose;
|
||||
import net.minecraft.resources.Identifier;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import top.r3944realms.lib39.Lib39;
|
||||
|
||||
/**
|
||||
* The enum Doll poses.
|
||||
*/
|
||||
public enum DollPoses implements IDollPose{
|
||||
/**
|
||||
* Default doll poses.
|
||||
*/
|
||||
DEFAULT(
|
||||
"default",
|
||||
PartPose.offset(0.0F, 9.0F, 0.0F),
|
||||
PartPose.offset(0.0F, 9.0F, 0.0F),
|
||||
PartPose.offsetAndRotation(-5.0F, 11.0F, 0.0F, 0.0F, 0.0F, 0.3927F),
|
||||
PartPose.offsetAndRotation(5.0F, 11.0F, 0.0F, 0.0F, 0.0F, -0.3927F),
|
||||
PartPose.offsetAndRotation(-2.0F, 19.0F, -2.0F, -1.5708F, 0.3927F, 0.0F),
|
||||
PartPose.offsetAndRotation(2.0F, 19.0F, -2.0F, -1.5708F, -0.3927F, 0.0F)
|
||||
);
|
||||
// 注册全局?
|
||||
private final Identifier id;
|
||||
private final Vec3 offset;
|
||||
private final PartPose headPose;
|
||||
private final PartPose bodyPose;
|
||||
private final PartPose rightArmPose;
|
||||
private final PartPose leftArmPose;
|
||||
private final PartPose rightLegPose;
|
||||
private final PartPose leftLegPose;
|
||||
|
||||
DollPoses(String name, PartPose headPose, PartPose bodyPose,
|
||||
PartPose rightArmPose, PartPose leftArmPose,
|
||||
PartPose rightLegPose, PartPose leftLegPose) {
|
||||
this(name, Vec3.ZERO, headPose, bodyPose, rightArmPose, leftArmPose, rightLegPose, leftLegPose);
|
||||
}
|
||||
|
||||
DollPoses(String name, Vec3 offset, PartPose headPose, PartPose bodyPose,
|
||||
PartPose rightArmPose, PartPose leftArmPose,
|
||||
PartPose rightLegPose, PartPose leftLegPose) {
|
||||
this.id = Lib39.rl(name);
|
||||
this.offset = offset;
|
||||
this.headPose = headPose;
|
||||
this.bodyPose = bodyPose;
|
||||
this.rightArmPose = rightArmPose;
|
||||
this.leftArmPose = leftArmPose;
|
||||
this.rightLegPose = rightLegPose;
|
||||
this.leftLegPose = leftLegPose;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Identifier getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PartPose getHeadPose() {
|
||||
return headPose;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PartPose getBodyPose() {
|
||||
return bodyPose;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PartPose getRightArmPose() {
|
||||
return rightArmPose;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PartPose getLeftArmPose() {
|
||||
return leftArmPose;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PartPose getRightLegPose() {
|
||||
return rightLegPose;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PartPose getLeftLegPose() {
|
||||
return leftLegPose;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Vec3 getTotalOffset() {
|
||||
return offset;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,69 @@
|
|||
package top.r3944realms.lib39.client.model;
|
||||
|
||||
import net.minecraft.client.model.geom.PartPose;
|
||||
import net.minecraft.resources.Identifier;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* The interface Doll pose.
|
||||
*/
|
||||
public interface IDollPose {
|
||||
/**
|
||||
* Gets id.
|
||||
*
|
||||
* @return the id
|
||||
*/
|
||||
@NotNull Identifier getId();
|
||||
|
||||
/**
|
||||
* Gets total offset.
|
||||
*
|
||||
* @return the total offset
|
||||
*/
|
||||
@NotNull default Vec3 getTotalOffset() {
|
||||
return Vec3.ZERO;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets head pose.
|
||||
*
|
||||
* @return the head pose
|
||||
*/
|
||||
@NotNull PartPose getHeadPose();
|
||||
|
||||
/**
|
||||
* Gets body pose.
|
||||
*
|
||||
* @return the body pose
|
||||
*/
|
||||
@NotNull PartPose getBodyPose();
|
||||
|
||||
/**
|
||||
* Gets right arm pose.
|
||||
*
|
||||
* @return the right arm pose
|
||||
*/
|
||||
@NotNull PartPose getRightArmPose();
|
||||
|
||||
/**
|
||||
* Gets left arm pose.
|
||||
*
|
||||
* @return the left arm pose
|
||||
*/
|
||||
@NotNull PartPose getLeftArmPose();
|
||||
|
||||
/**
|
||||
* Gets right leg pose.
|
||||
*
|
||||
* @return the right leg pose
|
||||
*/
|
||||
@NotNull PartPose getRightLegPose();
|
||||
|
||||
/**
|
||||
* Gets left leg pose.
|
||||
*
|
||||
* @return the left leg pose
|
||||
*/
|
||||
@NotNull PartPose getLeftLegPose();
|
||||
}
|
||||
|
|
@ -254,8 +254,8 @@ public class RadialMenuRenderer<T> {
|
|||
*/
|
||||
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);
|
||||
Tesselator instance = Tesselator.getInstance();
|
||||
BufferBuilder buffer = instance.begin(VertexFormat.Mode.TRIANGLE_STRIP, DefaultVertexFormat.POSITION_COLOR);
|
||||
|
||||
Matrix4f matrix = guiGraphics.pose().last().pose();
|
||||
float segments = Math.max(8, this.segments * (angleSize / 360f));
|
||||
|
|
@ -269,14 +269,14 @@ public class RadialMenuRenderer<T> {
|
|||
float sin = Mth.sin(rad);
|
||||
|
||||
// 外圈顶点
|
||||
buffer.vertex(matrix, outerRadius * cos, outerRadius * sin, 0)
|
||||
.color(color[0], color[1], color[2], color[3]).endVertex();
|
||||
buffer.addVertex(matrix, outerRadius * cos, outerRadius * sin, 0)
|
||||
.setColor(color[0], color[1], color[2], color[3]);
|
||||
// 内圈顶点
|
||||
buffer.vertex(matrix, innerRadius * cos, innerRadius * sin, 0)
|
||||
.color(color[0], color[1], color[2], color[3] * 0.6f).endVertex();
|
||||
buffer.addVertex(matrix, innerRadius * cos, innerRadius * sin, 0)
|
||||
.setColor(color[0], color[1], color[2], color[3] * 0.6f);
|
||||
}
|
||||
|
||||
BufferUploader.drawWithShader(buffer.end());
|
||||
BufferUploader.drawWithShader(buffer.build());
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -4,25 +4,32 @@ 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.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.client.resources.DefaultPlayerSkin;
|
||||
import net.minecraft.client.resources.PlayerSkin;
|
||||
import net.minecraft.client.resources.SkinManager;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.resources.Identifier;
|
||||
import net.minecraft.world.item.component.ResolvableProfile;
|
||||
import net.minecraft.world.level.block.SkullBlock;
|
||||
import net.minecraft.world.level.block.WallSkullBlock;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.block.state.properties.RotationSegment;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import top.r3944realms.lib39.client.model.DollModel;
|
||||
import top.r3944realms.lib39.client.renderer.item.DollItemRenderer;
|
||||
import top.r3944realms.lib39.content.block.AbstractDollBlock;
|
||||
import top.r3944realms.lib39.content.block.WallDollBlock;
|
||||
import top.r3944realms.lib39.content.block.blockentity.DollBlockEntity;
|
||||
import top.r3944realms.lib39.util.lang.Pair;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* The type Doll block entity renderer.
|
||||
*/
|
||||
|
|
@ -45,16 +52,43 @@ public class DollBlockEntityRenderer implements BlockEntityRenderer<DollBlockEnt
|
|||
boolean isWall = dollBlock instanceof WallDollBlock;
|
||||
Direction direction = isWall ? blockState.getValue(WallSkullBlock.FACING) : null;
|
||||
float rotation = isWall ? direction.toYRot() : RotationSegment.convertToDegrees(blockState.getValue(SkullBlock.ROTATION));
|
||||
GameProfile profile = dollBlockEntity.getOwnerProfile();
|
||||
Pair<ResourceLocation, Boolean> resourceLocationBooleanPair = DollItemRenderer.loadSkin(profile);
|
||||
Pair<PlayerSkin.Model, RenderType> modelAndRenderTypePair = getModelAndRenderTypePair(dollBlockEntity.getOwnerProfile());
|
||||
poseStack.pushPose();
|
||||
poseStack.translate(0.5, 1.5, 0.5);
|
||||
poseStack.scale(1.0F, -1.0F, -1.0F);
|
||||
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);
|
||||
VertexConsumer vertexConsumer = buffer.getBuffer(modelAndRenderTypePair.second);
|
||||
this.dollModel.slim = modelAndRenderTypePair.first == PlayerSkin.Model.SLIM;
|
||||
this.dollModel.renderToBuffer(poseStack, vertexConsumer, packedLight, OverlayTexture.NO_OVERLAY,-1);
|
||||
poseStack.popPose();
|
||||
}
|
||||
}
|
||||
public static @NotNull Pair<PlayerSkin.Model, RenderType> getModelAndRenderTypePair(@Nullable ResolvableProfile profile) {
|
||||
SkinManager skinmanager = Minecraft.getInstance().getSkinManager();
|
||||
|
||||
if (profile == null) {
|
||||
return Pair.of(PlayerSkin.Model.SLIM,
|
||||
RenderType.entityTranslucent(DefaultPlayerSkin.getDefaultTexture()));
|
||||
}
|
||||
|
||||
GameProfile gameProfile = profile.gameProfile();
|
||||
|
||||
// 如果当前 Profile 没有纹理数据,尝试从 DollBlockEntity 缓存获取
|
||||
if (gameProfile != null && gameProfile.getProperties().isEmpty()
|
||||
&& gameProfile.getName() != null && !gameProfile.getName().isEmpty()) {
|
||||
Optional<GameProfile> cached = DollBlockEntity.fetchGameProfile(gameProfile.getName())
|
||||
.getNow(Optional.empty());
|
||||
if (cached.isPresent() && !cached.get().getProperties().isEmpty()) {
|
||||
gameProfile = cached.get();
|
||||
}
|
||||
}
|
||||
|
||||
if (gameProfile != null && !gameProfile.getProperties().isEmpty()) {
|
||||
PlayerSkin skin = skinmanager.getInsecureSkin(gameProfile);
|
||||
return Pair.of(skin.model(), RenderType.entityTranslucent(skin.texture()));
|
||||
}
|
||||
|
||||
return Pair.of(PlayerSkin.Model.SLIM,
|
||||
RenderType.entityTranslucent(DefaultPlayerSkin.getDefaultTexture()));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,10 +9,13 @@ 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.PlayerSkin;
|
||||
import net.minecraft.client.resources.SkinManager;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.core.component.DataComponents;
|
||||
import net.minecraft.resources.Identifier;
|
||||
import net.minecraft.world.item.ItemDisplayContext;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.item.component.ResolvableProfile;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import top.r3944realms.lib39.Lib39;
|
||||
import top.r3944realms.lib39.client.model.DollModel;
|
||||
|
|
@ -61,54 +64,44 @@ public class DollItemRenderer extends BlockEntityWithoutLevelRenderer {
|
|||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void renderByItem(@NotNull ItemStack stack, @NotNull ItemDisplayContext displayContext, @NotNull PoseStack poseStack, @NotNull MultiBufferSource buffer, int packedLight, int packedOverlay) {
|
||||
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;
|
||||
}
|
||||
lazyInit();
|
||||
GameProfile profile = GameProfileHelper.getProfileFromItemStack(stack);
|
||||
Pair<ResourceLocation, Boolean> resourceLocationBooleanPair = loadSkin(profile);
|
||||
ResourceLocation playerSkin = resourceLocationBooleanPair.first;
|
||||
boolean isSlim = resourceLocationBooleanPair.second;
|
||||
|
||||
// 直接从 DataComponents.PROFILE 获取 ResolvableProfile
|
||||
ResolvableProfile profile = stack.get(DataComponents.PROFILE);
|
||||
Pair<Identifier, PlayerSkin.Model> skinInfo = getSkinInfo(profile);
|
||||
|
||||
poseStack.pushPose();
|
||||
VertexConsumer vertexConsumer = buffer.getBuffer(
|
||||
RenderType.entityTranslucent(playerSkin)
|
||||
);
|
||||
VertexConsumer vertexConsumer = buffer.getBuffer(RenderType.entityTranslucent(skinInfo.first));
|
||||
|
||||
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
|
||||
);
|
||||
|
||||
this.dollModel.slim = skinInfo.second == PlayerSkin.Model.SLIM;
|
||||
this.dollModel.renderToBuffer(poseStack, vertexConsumer, packedLight, packedOverlay, -1);
|
||||
|
||||
poseStack.popPose();
|
||||
}
|
||||
|
||||
/**
|
||||
* Load skin pair.
|
||||
*
|
||||
* @param profile the profile
|
||||
* @return the pair
|
||||
* 获取皮肤纹理和模型类型(1.21+ 版本)
|
||||
*/
|
||||
public static @NotNull Pair<ResourceLocation,Boolean> loadSkin(GameProfile profile) {
|
||||
public static @NotNull Pair<Identifier, PlayerSkin.Model> getSkinInfo(@NotNull ResolvableProfile 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;
|
||||
|
||||
if (profile != null && profile.gameProfile() != null) {
|
||||
PlayerSkin skin = skinManager.getInsecureSkin(profile.gameProfile());
|
||||
return Pair.of(skin.texture(), skin.model());
|
||||
}
|
||||
return Pair.of(playerSkin, isSlim);
|
||||
|
||||
// 默认返回 Steve 皮肤
|
||||
return Pair.of(DefaultPlayerSkin.getDefaultTexture(), PlayerSkin.Model.SLIM);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,19 +1,24 @@
|
|||
package top.r3944realms.lib39.content.block;
|
||||
|
||||
import com.mojang.authlib.GameProfile;
|
||||
import com.mojang.serialization.MapCodec;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.core.component.DataComponents;
|
||||
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.LivingEntity;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.item.component.ResolvableProfile;
|
||||
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.LevelReader;
|
||||
import net.minecraft.world.level.block.*;
|
||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
|
|
@ -34,6 +39,7 @@ import net.minecraft.world.phys.shapes.Shapes;
|
|||
import net.minecraft.world.phys.shapes.VoxelShape;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import top.r3944realms.lib39.client.model.IDollPose;
|
||||
import top.r3944realms.lib39.content.block.blockentity.DollBlockEntity;
|
||||
import top.r3944realms.lib39.content.block.property.DollPose;
|
||||
import top.r3944realms.lib39.core.register.Lib39BlockEntities;
|
||||
|
|
@ -100,16 +106,16 @@ public abstract class AbstractDollBlock extends BaseEntityBlock implements Simpl
|
|||
}
|
||||
|
||||
@Override
|
||||
public @NotNull InteractionResult use(@NotNull BlockState blockState, @NotNull Level level, @NotNull BlockPos blockPos, @NotNull Player player,
|
||||
@NotNull InteractionHand hand, @NotNull BlockHitResult hitResult) {
|
||||
protected InteractionResult useWithoutItem(BlockState state, Level level, BlockPos pos, Player player, BlockHitResult hitResult) {
|
||||
if (level instanceof ServerLevel serverLevel) {
|
||||
// 播放粒子效果
|
||||
spawnNoteParticles(serverLevel, blockPos);
|
||||
spawnNoteParticles(serverLevel, pos);
|
||||
// 播放音效
|
||||
playDollSound(serverLevel, blockPos);
|
||||
playDollSound(serverLevel, pos);
|
||||
}
|
||||
return InteractionResult.SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* 在玩偶位置生成音符粒子效果
|
||||
*/
|
||||
|
|
@ -171,13 +177,16 @@ public abstract class AbstractDollBlock extends BaseEntityBlock implements Simpl
|
|||
}
|
||||
|
||||
@Override
|
||||
public @NotNull ItemStack getCloneItemStack(@NotNull BlockGetter level, @NotNull BlockPos pos, @NotNull BlockState state) {
|
||||
public ItemStack getCloneItemStack(LevelReader level, BlockPos pos, BlockState state) {
|
||||
ItemStack stack = super.getCloneItemStack(level, pos, state);
|
||||
BlockEntity blockEntity = level.getBlockEntity(pos);
|
||||
if (blockEntity instanceof DollBlockEntity doll) {
|
||||
GameProfile profile = doll.getOwnerProfile();
|
||||
if (profile != null) {
|
||||
GameProfileHelper.saveProfileToItemStack(stack, profile);
|
||||
ResolvableProfile profile;
|
||||
if (doll.getOwnerProfile() != null) {
|
||||
profile = doll.getOwnerProfile();
|
||||
if (profile != null) {
|
||||
GameProfileHelper.saveProfileToItemStack(stack, profile);
|
||||
}
|
||||
}
|
||||
}
|
||||
return stack;
|
||||
|
|
@ -204,22 +213,38 @@ public abstract class AbstractDollBlock extends BaseEntityBlock implements Simpl
|
|||
super.createBlockStateDefinition(builder);
|
||||
builder.add(WATERLOGGED, POSE);
|
||||
}
|
||||
@Override
|
||||
public void setPlacedBy(@NotNull Level level, @NotNull BlockPos pos, @NotNull BlockState state,
|
||||
@Nullable LivingEntity placer, @NotNull ItemStack stack) {
|
||||
super.setPlacedBy(level, pos, state, placer, stack);
|
||||
|
||||
BlockEntity blockEntity = level.getBlockEntity(pos);
|
||||
if (blockEntity instanceof DollBlockEntity dollEntity) {
|
||||
ResolvableProfile profile = GameProfileHelper.getProfileFromItemStack(stack);
|
||||
if (profile != null) {
|
||||
dollEntity.setOwner(profile);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成自定义掉落物
|
||||
*/
|
||||
@Nullable
|
||||
private List<ItemStack> getCustomDrops(DollBlockEntity dollEntity, LootParams.Builder params) {
|
||||
private List<ItemStack> getCustomDrops(DollBlockEntity dollEntity, LootParams.@NotNull 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);
|
||||
ResolvableProfile profile;
|
||||
if (dollEntity.getOwnerProfile() != null) {
|
||||
profile = dollEntity.getOwnerProfile();
|
||||
if (profile != null) {
|
||||
ItemStack instance = Lib39Items.DOLL.get().getDefaultInstance();
|
||||
GameProfileHelper.saveProfileToItemStack(instance, profile);
|
||||
return List.of(instance);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
package top.r3944realms.lib39.content.block;
|
||||
|
||||
import com.mojang.serialization.MapCodec;
|
||||
import net.minecraft.world.item.context.BlockPlaceContext;
|
||||
import net.minecraft.world.level.block.BaseEntityBlock;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.Mirror;
|
||||
import net.minecraft.world.level.block.Rotation;
|
||||
|
|
@ -17,7 +19,7 @@ import top.r3944realms.lib39.content.block.property.DollPose;
|
|||
* The type Doll block.
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
public class DollBlock extends AbstractDollBlock{
|
||||
public class DollBlock extends AbstractDollBlock {
|
||||
/**
|
||||
* The constant MAX.
|
||||
*/
|
||||
|
|
@ -42,6 +44,10 @@ public class DollBlock extends AbstractDollBlock{
|
|||
);
|
||||
}
|
||||
@Override
|
||||
protected MapCodec<? extends BaseEntityBlock> codec() {
|
||||
return simpleCodec(p -> new DollBlock());
|
||||
}
|
||||
@Override
|
||||
public @Nullable BlockState getStateForPlacement(@NotNull BlockPlaceContext context) {
|
||||
BlockState stateForPlacement = super.getStateForPlacement(context);
|
||||
return stateForPlacement != null ? stateForPlacement.setValue(ROTATION, RotationSegment.convertToSegment((context.getRotation()+180) % 360)) : null;
|
||||
|
|
|
|||
|
|
@ -1,11 +1,9 @@
|
|||
package top.r3944realms.lib39.content.block;
|
||||
|
||||
import com.mojang.serialization.MapCodec;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.world.item.context.BlockPlaceContext;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.HorizontalDirectionalBlock;
|
||||
import net.minecraft.world.level.block.Mirror;
|
||||
import net.minecraft.world.level.block.Rotation;
|
||||
import net.minecraft.world.level.block.*;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.block.state.StateDefinition;
|
||||
import net.minecraft.world.level.block.state.properties.DirectionProperty;
|
||||
|
|
@ -35,6 +33,12 @@ public class WallDollBlock extends AbstractDollBlock {
|
|||
.setValue(FACING, Direction.NORTH)
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected MapCodec<? extends BaseEntityBlock> codec() {
|
||||
return simpleCodec(p -> new WallDollBlock());
|
||||
}
|
||||
|
||||
public @NotNull BlockState rotate(@NotNull BlockState state, @NotNull Rotation rotation) {
|
||||
return state.setValue(FACING, rotation.rotate(state.getValue(FACING)));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,98 +1,196 @@
|
|||
package top.r3944realms.lib39.content.block.blockentity;
|
||||
|
||||
import com.google.common.cache.CacheBuilder;
|
||||
import com.google.common.cache.CacheLoader;
|
||||
import com.google.common.cache.LoadingCache;
|
||||
import com.mojang.authlib.GameProfile;
|
||||
import net.minecraft.Util;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.HolderLookup;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.nbt.NbtUtils;
|
||||
import net.minecraft.nbt.NbtOps;
|
||||
import net.minecraft.network.protocol.game.ClientboundBlockEntityDataPacket;
|
||||
import net.minecraft.server.Services;
|
||||
import net.minecraft.world.item.component.ResolvableProfile;
|
||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||
import net.minecraft.world.level.block.entity.SkullBlockEntity;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import top.r3944realms.lib39.core.register.Lib39BlockEntities;
|
||||
import top.r3944realms.lib39.util.GameProfileHelper;
|
||||
import top.r3944realms.lib39.util.nbt.NBTReader;
|
||||
import top.r3944realms.lib39.util.nbt.NBTWriter;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.time.Duration;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.function.BooleanSupplier;
|
||||
|
||||
/**
|
||||
* The type Doll block entity.
|
||||
* 参考 SkullBlockEntity 实现,添加缓存机制
|
||||
*/
|
||||
public class DollBlockEntity extends BlockEntity {
|
||||
|
||||
@Nullable
|
||||
private GameProfile owner;
|
||||
private static final String TAG_PROFILE = "profile";
|
||||
|
||||
// 静态缓存(与 SkullBlockEntity 共享或独立)
|
||||
@Nullable
|
||||
private static Executor mainThreadExecutor;
|
||||
@Nullable
|
||||
private static LoadingCache<String, CompletableFuture<Optional<GameProfile>>> profileCacheByName;
|
||||
@Nullable
|
||||
private static LoadingCache<UUID, CompletableFuture<Optional<GameProfile>>> profileCacheById;
|
||||
|
||||
public static final Executor CHECKED_MAIN_THREAD_EXECUTOR = (runnable) -> {
|
||||
Executor executor = mainThreadExecutor;
|
||||
if (executor != null) {
|
||||
executor.execute(runnable);
|
||||
}
|
||||
};
|
||||
|
||||
@Nullable
|
||||
private ResolvableProfile 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));
|
||||
/**
|
||||
* 初始化缓存(在 Mod 初始化或服务器启动时调用)
|
||||
*/
|
||||
public static void setup(final Services services, Executor executor) {
|
||||
mainThreadExecutor = executor;
|
||||
final BooleanSupplier cacheUninitialized = () -> profileCacheById == null;
|
||||
|
||||
profileCacheByName = CacheBuilder.newBuilder()
|
||||
.expireAfterAccess(Duration.ofMinutes(10L))
|
||||
.maximumSize(256L)
|
||||
.build(new CacheLoader<>() {
|
||||
@Override
|
||||
public CompletableFuture<Optional<GameProfile>> load(String username) {
|
||||
return fetchProfileByName(username, services);
|
||||
}
|
||||
});
|
||||
|
||||
profileCacheById = CacheBuilder.newBuilder()
|
||||
.expireAfterAccess(Duration.ofMinutes(10L))
|
||||
.maximumSize(256L)
|
||||
.build(new CacheLoader<>() {
|
||||
@Override
|
||||
public CompletableFuture<Optional<GameProfile>> load(UUID uuid) {
|
||||
return fetchProfileById(uuid, services, cacheUninitialized);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void load(@NotNull CompoundTag tag) {
|
||||
super.load(tag);
|
||||
NBTReader.of(tag)
|
||||
.compound(GameProfileHelper.TAG_OWN_PROFILE, compoundTag -> setOwner(NbtUtils.readGameProfile(compoundTag)));
|
||||
private static CompletableFuture<Optional<GameProfile>> fetchProfileByName(String name, Services services) {
|
||||
return services.profileCache().getAsync(name).thenCompose(optional -> {
|
||||
LoadingCache<UUID, CompletableFuture<Optional<GameProfile>>> cache = profileCacheById;
|
||||
if (cache != null && optional.isPresent()) {
|
||||
return cache.getUnchecked(optional.get().getId())
|
||||
.thenApply(fullProfile -> fullProfile.or(() -> optional));
|
||||
}
|
||||
return CompletableFuture.completedFuture(Optional.empty());
|
||||
});
|
||||
}
|
||||
|
||||
private static CompletableFuture<Optional<GameProfile>> fetchProfileById(UUID uuid, Services services, BooleanSupplier cacheUninitialized) {
|
||||
return CompletableFuture.supplyAsync(() -> {
|
||||
if (cacheUninitialized.getAsBoolean()) {
|
||||
return Optional.empty();
|
||||
}
|
||||
var result = services.sessionService().fetchProfile(uuid, true);
|
||||
return Optional.ofNullable(result).map(com.mojang.authlib.yggdrasil.ProfileResult::profile);
|
||||
}, Util.backgroundExecutor());
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets owner profile.
|
||||
*
|
||||
* @return the owner profile
|
||||
* 公开的静态方法:异步获取 GameProfile(复用 SkullBlockEntity 的缓存或使用自己的)
|
||||
*/
|
||||
public static CompletableFuture<Optional<GameProfile>> fetchGameProfile(String name) {
|
||||
if (profileCacheByName != null && name != null && !name.isEmpty()) {
|
||||
return profileCacheByName.getUnchecked(name);
|
||||
}
|
||||
// 回退到 SkullBlockEntity 的缓存
|
||||
return SkullBlockEntity.fetchGameProfile(name);
|
||||
}
|
||||
|
||||
public static CompletableFuture<Optional<GameProfile>> fetchGameProfile(UUID uuid) {
|
||||
if (profileCacheById != null && uuid != null) {
|
||||
return profileCacheById.getUnchecked(uuid);
|
||||
}
|
||||
return SkullBlockEntity.fetchGameProfile(uuid);
|
||||
}
|
||||
|
||||
public static void clearCache() {
|
||||
mainThreadExecutor = null;
|
||||
profileCacheByName = null;
|
||||
profileCacheById = null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public GameProfile getOwnerProfile() {
|
||||
public ResolvableProfile getOwnerProfile() {
|
||||
return this.owner;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public ClientboundBlockEntityDataPacket getUpdatePacket() {
|
||||
return ClientboundBlockEntityDataPacket.create(this);
|
||||
}
|
||||
|
||||
public @NotNull CompoundTag getUpdateTag() {
|
||||
return this.saveWithoutMetadata();
|
||||
@Override
|
||||
public CompoundTag getUpdateTag(HolderLookup.Provider registries) {
|
||||
CompoundTag tag = super.getUpdateTag(registries);
|
||||
saveAdditional(tag, registries);
|
||||
return tag;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets owner.
|
||||
*
|
||||
* @param owner the owner
|
||||
*/
|
||||
public void setOwner(@Nullable GameProfile owner) {
|
||||
public void setOwner(@Nullable ResolvableProfile 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));
|
||||
if (ownerName != null && !ownerName.isEmpty()) {
|
||||
setOwner(new ResolvableProfile(new GameProfile(Util.NIL_UUID, ownerName)));
|
||||
}
|
||||
}
|
||||
|
||||
private void updateOwnerProfile() {
|
||||
SkullBlockEntity.updateGameprofile(this.owner, gameProfile -> {
|
||||
this.owner = gameProfile;
|
||||
if (this.owner != null && !this.owner.isResolved()) {
|
||||
this.owner.resolve().thenAcceptAsync(resolved -> {
|
||||
this.owner = resolved;
|
||||
this.setChanged();
|
||||
// 通知客户端更新
|
||||
if (level != null && !level.isClientSide) {
|
||||
level.sendBlockUpdated(worldPosition, getBlockState(), getBlockState(), 3);
|
||||
}
|
||||
}, CHECKED_MAIN_THREAD_EXECUTOR);
|
||||
} else {
|
||||
this.setChanged();
|
||||
});
|
||||
if (level != null && !level.isClientSide && this.owner != null) {
|
||||
level.sendBlockUpdated(worldPosition, getBlockState(), getBlockState(), 3);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@Override
|
||||
protected void saveAdditional(CompoundTag tag, HolderLookup.Provider registries) {
|
||||
super.saveAdditional(tag, registries);
|
||||
if (this.owner != null) {
|
||||
tag.put(TAG_PROFILE, ResolvableProfile.CODEC.encodeStart(NbtOps.INSTANCE, this.owner).getOrThrow());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void loadAdditional(CompoundTag tag, HolderLookup.Provider registries) {
|
||||
super.loadAdditional(tag, registries);
|
||||
if (tag.contains(TAG_PROFILE)) {
|
||||
ResolvableProfile.CODEC.parse(NbtOps.INSTANCE, tag.get(TAG_PROFILE))
|
||||
.resultOrPartial(error -> {})
|
||||
.ifPresent(this::setOwner);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -8,6 +8,7 @@ import net.minecraft.world.item.Equipable;
|
|||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.item.StandingAndWallBlockItem;
|
||||
import net.minecraft.world.item.TooltipFlag;
|
||||
import net.minecraft.world.item.component.ResolvableProfile;
|
||||
import net.minecraft.world.level.Level;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
|
@ -29,16 +30,20 @@ public class DollItem extends StandingAndWallBlockItem implements Equipable {
|
|||
super(Lib39Blocks.DOLL.get(), Lib39Blocks.WALL_DOLL.get(), properties, Direction.DOWN);
|
||||
}
|
||||
|
||||
|
||||
@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()));
|
||||
public void appendHoverText(ItemStack stack, TooltipContext context, List<Component> tooltipComponents, TooltipFlag tooltipFlag) {
|
||||
super.appendHoverText(stack, context, tooltipComponents, tooltipFlag);
|
||||
ResolvableProfile profileFromItemStack = GameProfileHelper.getProfileFromItemStack(stack);
|
||||
if (profileFromItemStack != null) {
|
||||
GameProfile gameProfile = profileFromItemStack.gameProfile();
|
||||
if (gameProfile != null && gameProfile.getName() != null) {
|
||||
tooltipComponents.add(Component.translatable("tooltip.lib39.content.doll.hover.1", gameProfile.getName()));
|
||||
}
|
||||
}
|
||||
tooltip.add(Component.translatable("tooltip.lib39.content.doll.hover.2"));
|
||||
tooltipComponents.add(Component.translatable("tooltip.lib39.content.doll.hover.2"));
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public @NotNull EquipmentSlot getEquipmentSlot() {
|
||||
return EquipmentSlot.HEAD;
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ 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 net.minecraft.resources.Identifier;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import top.r3944realms.lib39.base.datagen.value.Lib39LangKey;
|
||||
|
|
@ -31,7 +31,7 @@ public interface ICommandHelpManager {
|
|||
*
|
||||
* @return the id
|
||||
*/
|
||||
ResourceLocation getID();
|
||||
Identifier getID();
|
||||
|
||||
/**
|
||||
* Gets head key.
|
||||
|
|
@ -291,12 +291,10 @@ public interface ICommandHelpManager {
|
|||
return Component.literal(rootCommand)
|
||||
.withStyle(ChatFormatting.AQUA)
|
||||
.withStyle(Style.EMPTY
|
||||
.withClickEvent(new ClickEvent(
|
||||
ClickEvent.Action.SUGGEST_COMMAND,
|
||||
.withClickEvent(new ClickEvent.SuggestCommand(
|
||||
rootCommand + " "
|
||||
))
|
||||
.withHoverEvent(new HoverEvent(
|
||||
HoverEvent.Action.SHOW_TEXT,
|
||||
.withHoverEvent(new HoverEvent.ShowText(
|
||||
Component.translatable(Lib39LangKey.Message.HELP_HOVER_COPY_TIP.getKey())
|
||||
))
|
||||
);
|
||||
|
|
@ -316,12 +314,10 @@ public interface ICommandHelpManager {
|
|||
MutableComponent commandName = Component.literal(node.getName())
|
||||
.withStyle(ChatFormatting.DARK_AQUA)
|
||||
.withStyle(Style.EMPTY
|
||||
.withClickEvent(new ClickEvent(
|
||||
ClickEvent.Action.SUGGEST_COMMAND,
|
||||
.withClickEvent(new ClickEvent.SuggestCommand(
|
||||
suggestedCommand
|
||||
))
|
||||
.withHoverEvent(new HoverEvent(
|
||||
HoverEvent.Action.SHOW_TEXT,
|
||||
.withHoverEvent(new HoverEvent.ShowText(
|
||||
Component.translatable(Lib39LangKey.Message.HELP_HOVER_COPY_TIP.getKey(), suggestedCommand)
|
||||
))
|
||||
);
|
||||
|
|
@ -370,12 +366,10 @@ public interface ICommandHelpManager {
|
|||
|
||||
// 为按钮添加点击事件
|
||||
toggleButton.withStyle(Style.EMPTY
|
||||
.withClickEvent(new ClickEvent(
|
||||
ClickEvent.Action.RUN_COMMAND,
|
||||
.withClickEvent(new ClickEvent.RunCommand(
|
||||
"/" + getCommandHead() + " help toggle " + node.hashCode()
|
||||
))
|
||||
.withHoverEvent(new HoverEvent(
|
||||
HoverEvent.Action.SHOW_TEXT,
|
||||
.withHoverEvent(new HoverEvent.ShowText(
|
||||
Component.translatable(Lib39LangKey.Message.HELP_CLICK_EXPAND.getKey())
|
||||
.withStyle(ChatFormatting.GRAY)
|
||||
))
|
||||
|
|
@ -467,11 +461,12 @@ public interface ICommandHelpManager {
|
|||
).withStyle(ChatFormatting.GRAY));
|
||||
|
||||
collapsedInfo.withStyle(Style.EMPTY
|
||||
.withClickEvent(new ClickEvent(
|
||||
ClickEvent.Action.RUN_COMMAND,
|
||||
.withClickEvent(new ClickEvent.RunCommand(
|
||||
"/" + getCommandHead() + " help toggle " + node.hashCode()
|
||||
))
|
||||
.withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, Component.translatable(Lib39LangKey.Message.HELP_CLICK_EXPAND.getKey())))
|
||||
.withHoverEvent(new HoverEvent.ShowText(
|
||||
Component.translatable(Lib39LangKey.Message.HELP_CLICK_EXPAND.getKey())
|
||||
))
|
||||
);
|
||||
|
||||
result.add(collapsedInfo.append(Component.literal(NEWLINE)));
|
||||
|
|
|
|||
|
|
@ -10,11 +10,10 @@ import net.minecraft.commands.Commands;
|
|||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.network.chat.MutableComponent;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import top.r3944realms.lib39.base.datagen.value.Lib39LangKey;
|
||||
import top.r3944realms.lib39.platform.Services;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* The interface Help command.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
package top.r3944realms.lib39.core.command;
|
||||
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.resources.Identifier;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import top.r3944realms.lib39.core.command.model.CommandNode;
|
||||
import top.r3944realms.lib39.core.command.model.Parameter;
|
||||
|
|
@ -28,7 +28,7 @@ public abstract class SimpleCommandHelpManager implements ICommandHelpManager {
|
|||
public void initialize() {
|
||||
if (root == null) {
|
||||
// 現在子類的字段已經初始化完成
|
||||
ResourceLocation id = getID();
|
||||
Identifier id = getID();
|
||||
if (id == null) {
|
||||
throw new IllegalStateException("getID() must return non-null");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1109,6 +1109,8 @@ public class CommandNode {
|
|||
|
||||
/**
|
||||
* 葉子節點配置記錄
|
||||
* @param description 介绍
|
||||
* @param parameters 参数列表
|
||||
*/
|
||||
public record LeafConfig(@NotNull MutableComponent description,
|
||||
@Nullable List<Parameter> parameters) {
|
||||
|
|
|
|||
|
|
@ -8,6 +8,8 @@ import java.util.List;
|
|||
|
||||
/**
|
||||
* The type Parameter.
|
||||
* @param name 参数名
|
||||
* @param required 是否必须
|
||||
*/
|
||||
public record Parameter(String name, boolean required) {
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
package top.r3944realms.lib39.core.compat;
|
||||
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.resources.Identifier;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
|
@ -11,15 +11,18 @@ import java.util.stream.Collectors;
|
|||
|
||||
/**
|
||||
* The type Compat manager.
|
||||
*
|
||||
* @param <C> the type parameter
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public abstract class CompatManager {
|
||||
public abstract class CompatManager<C extends ICompat> implements ICompatManager<C> {
|
||||
/**
|
||||
* Gets id.
|
||||
*
|
||||
* @return the id
|
||||
*/
|
||||
public ResourceLocation getId() {
|
||||
@Override
|
||||
public Identifier getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
|
|
@ -30,11 +33,8 @@ public abstract class CompatManager {
|
|||
/**
|
||||
* The Id.
|
||||
*/
|
||||
protected final ResourceLocation id;
|
||||
/**
|
||||
* The Compats.
|
||||
*/
|
||||
protected final Map<ResourceLocation, ICompat> compats = new HashMap<>();
|
||||
protected final Identifier id;
|
||||
|
||||
/**
|
||||
* The Initialized.
|
||||
*/
|
||||
|
|
@ -47,6 +47,7 @@ public abstract class CompatManager {
|
|||
/**
|
||||
* Initialize.
|
||||
*/
|
||||
@Override
|
||||
public void initialize() {
|
||||
initializeAllCompat();
|
||||
onLoadComplete();
|
||||
|
|
@ -57,7 +58,7 @@ public abstract class CompatManager {
|
|||
*
|
||||
* @param id the id
|
||||
*/
|
||||
public CompatManager(@NotNull ResourceLocation id) {
|
||||
public CompatManager(@NotNull Identifier id) {
|
||||
this.id = id;
|
||||
this.logger = LoggerFactory.getLogger(id.toString());
|
||||
}
|
||||
|
|
@ -68,7 +69,8 @@ public abstract class CompatManager {
|
|||
* @param id the id
|
||||
* @param compat the compat
|
||||
*/
|
||||
public void registerCompat(ResourceLocation id, ICompat compat) {
|
||||
@Override
|
||||
public void registerCompat(Identifier id, C compat) {
|
||||
if (initialized) {
|
||||
// 已初始化,直接注册
|
||||
doRegisterCompat(id, compat);
|
||||
|
|
@ -85,12 +87,12 @@ public abstract class CompatManager {
|
|||
* @param id the id
|
||||
* @param compat the compat
|
||||
*/
|
||||
protected void doRegisterCompat(ResourceLocation id, ICompat compat) {
|
||||
if (compats.containsKey(id)) {
|
||||
protected void doRegisterCompat(Identifier id, C compat) {
|
||||
if (getCompatMap().containsKey(id)) {
|
||||
logger.warn("Compat with id {} is already registered!", id);
|
||||
return;
|
||||
}
|
||||
compats.put(id, compat);
|
||||
getCompatMap().put(id, compat);
|
||||
logger.debug("Registered compat: {}", id);
|
||||
}
|
||||
|
||||
|
|
@ -101,7 +103,8 @@ public abstract class CompatManager {
|
|||
* @param path the path
|
||||
* @param compat the compat
|
||||
*/
|
||||
public void registerCompat(String namespace, String path, ICompat compat) {
|
||||
@Override
|
||||
public void registerCompat(String namespace, String path, C compat) {
|
||||
registerCompat(Lib39.rl(namespace, path), compat);
|
||||
}
|
||||
|
||||
|
|
@ -112,14 +115,14 @@ public abstract class CompatManager {
|
|||
* 初始化所有兼容模块并应用事件监听器
|
||||
*/
|
||||
protected synchronized void initializeAllCompat() {
|
||||
logger.info("Initializing {} compatibility modules", compats.size());
|
||||
logger.info("Initializing {} compatibility modules", getCompatMap().size());
|
||||
|
||||
// 先处理所有缓存的注册
|
||||
pendingTasks.forEach(Runnable::run);
|
||||
pendingTasks.clear();
|
||||
|
||||
// 初始化所有兼容模块
|
||||
for (Map.Entry<ResourceLocation, ICompat> entry : compats.entrySet()) {
|
||||
for (Map.Entry<Identifier, C> entry : getCompatMap().entrySet()) {
|
||||
if (!entry.getValue().isInitialized() && entry.getValue().isModLoaded()) {
|
||||
try {
|
||||
entry.getValue().initialize();
|
||||
|
|
@ -139,8 +142,9 @@ public abstract class CompatManager {
|
|||
* @param id the id
|
||||
* @return the compat
|
||||
*/
|
||||
public Optional<ICompat> getCompat(ResourceLocation id) {
|
||||
return Optional.ofNullable(compats.get(id));
|
||||
@Override
|
||||
public Optional<C> getCompat(Identifier id) {
|
||||
return Optional.ofNullable(getCompatMap().get(id));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -149,8 +153,9 @@ public abstract class CompatManager {
|
|||
* @param id the id
|
||||
* @return the boolean
|
||||
*/
|
||||
public boolean hasCompat(ResourceLocation id) {
|
||||
return compats.containsKey(id);
|
||||
@Override
|
||||
public boolean hasCompat(Identifier id) {
|
||||
return getCompatMap().containsKey(id);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -158,8 +163,9 @@ public abstract class CompatManager {
|
|||
*
|
||||
* @param id the id
|
||||
*/
|
||||
public void unregisterCompat(ResourceLocation id) {
|
||||
ICompat removed = compats.remove(id);
|
||||
@Override
|
||||
public void unregisterCompat(Identifier id) {
|
||||
C removed = getCompatMap().remove(id);
|
||||
if (removed != null) {
|
||||
logger.debug("Unregistered compat: {}", id);
|
||||
}
|
||||
|
|
@ -170,9 +176,9 @@ public abstract class CompatManager {
|
|||
*
|
||||
* @return the loaded compats
|
||||
*/
|
||||
public List<ICompat> getLoadedCompats() {
|
||||
return compats.values().stream()
|
||||
.filter(ICompat::isModLoaded)
|
||||
public List<C> getLoadedCompats() {
|
||||
return getCompatMap().values().stream()
|
||||
.filter(C::isModLoaded)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
|
|
@ -180,8 +186,8 @@ public abstract class CompatManager {
|
|||
* On load complete.
|
||||
*/
|
||||
public void onLoadComplete() {
|
||||
logger.info("Calling onLoadComplete for {} compatibility modules", compats.size());
|
||||
for (Map.Entry<ResourceLocation, ICompat> entry : compats.entrySet()) {
|
||||
logger.info("Calling onLoadComplete for {} compatibility modules", getCompatMap().size());
|
||||
for (Map.Entry<Identifier, C> entry : getCompatMap().entrySet()) {
|
||||
try {
|
||||
entry.getValue().onLoadComplete();
|
||||
} catch (Exception e) {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
package top.r3944realms.lib39.core.compat;
|
||||
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.resources.Identifier;
|
||||
|
||||
import java.util.concurrent.Callable;
|
||||
|
||||
|
|
@ -27,7 +27,7 @@ public interface ICompat {
|
|||
*
|
||||
* @return the resource location
|
||||
*/
|
||||
ResourceLocation id();
|
||||
Identifier id();
|
||||
|
||||
/**
|
||||
* Initialize.
|
||||
|
|
|
|||
|
|
@ -0,0 +1,72 @@
|
|||
package top.r3944realms.lib39.core.compat;
|
||||
|
||||
import net.minecraft.resources.Identifier;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* The interface Compat manager.
|
||||
*
|
||||
* @param <C> the type parameter
|
||||
*/
|
||||
public interface ICompatManager<C extends ICompat> {
|
||||
/**
|
||||
* Gets id.
|
||||
*
|
||||
* @return the id
|
||||
*/
|
||||
Identifier getId();
|
||||
|
||||
/**
|
||||
* Gets compat map.
|
||||
*
|
||||
* @return the compat map
|
||||
*/
|
||||
Map<Identifier, C> getCompatMap();
|
||||
|
||||
/**
|
||||
* Initialize.
|
||||
*/
|
||||
void initialize();
|
||||
|
||||
/**
|
||||
* Register compat.
|
||||
*
|
||||
* @param id the id
|
||||
* @param compat the compat
|
||||
*/
|
||||
void registerCompat(Identifier id, C compat);
|
||||
|
||||
/**
|
||||
* Register compat.
|
||||
*
|
||||
* @param namespace the namespace
|
||||
* @param path the path
|
||||
* @param compat the compat
|
||||
*/
|
||||
void registerCompat(String namespace, String path, C compat);
|
||||
|
||||
/**
|
||||
* Gets compat.
|
||||
*
|
||||
* @param id the id
|
||||
* @return the compat
|
||||
*/
|
||||
Optional<C> getCompat(Identifier id);
|
||||
|
||||
/**
|
||||
* Has compat boolean.
|
||||
*
|
||||
* @param id the id
|
||||
* @return the boolean
|
||||
*/
|
||||
boolean hasCompat(Identifier id);
|
||||
|
||||
/**
|
||||
* Unregister compat.
|
||||
*
|
||||
* @param id the id
|
||||
*/
|
||||
void unregisterCompat(Identifier id);
|
||||
}
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
package top.r3944realms.lib39.core.compat;
|
||||
|
||||
import net.minecraft.resources.Identifier;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* The type Simple compat manager.
|
||||
*/
|
||||
public class SimpleCompatManager extends CompatManager<ICompat> {
|
||||
/**
|
||||
* The Compats.
|
||||
*/
|
||||
Map<Identifier, ICompat> compats = new HashMap<>();
|
||||
|
||||
/**
|
||||
* Instantiates a new Compat manager.
|
||||
*
|
||||
* @param id the id
|
||||
*/
|
||||
public SimpleCompatManager(@NotNull Identifier id) {
|
||||
super(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<Identifier, ICompat> getCompatMap() {
|
||||
return compats;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
package top.r3944realms.lib39.core.register;
|
||||
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.resources.Identifier;
|
||||
import net.minecraft.sounds.SoundEvent;
|
||||
import top.r3944realms.lib39.Lib39;
|
||||
|
||||
|
|
@ -13,7 +13,7 @@ public class Lib39SoundEvents {
|
|||
/**
|
||||
* The constant RL_DUCK_TOY.
|
||||
*/
|
||||
public static final ResourceLocation RL_DUCK_TOY = Lib39.rl("duck_toy");
|
||||
public static final Identifier RL_DUCK_TOY = Lib39.rl("duck_toy");
|
||||
/**
|
||||
* The constant DUCK_TOY.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -3,8 +3,12 @@ package top.r3944realms.lib39.core.sync;
|
|||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.nbt.Tag;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.level.storage.ValueInput;
|
||||
import net.minecraft.world.level.storage.ValueOutput;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* The interface Lib 39 sync data holder.
|
||||
*/
|
||||
|
|
@ -26,24 +30,25 @@ public interface ILib39SyncDataHolder {
|
|||
/**
|
||||
* Lib 39 inject save sync data compound tag.
|
||||
*
|
||||
* @param tag the tag
|
||||
* @return the compound tag
|
||||
* @param output the tag
|
||||
*/
|
||||
default CompoundTag lib39$injectSaveSyncData(CompoundTag tag) {
|
||||
default void lib39$injectSaveSyncData(ValueOutput output) {
|
||||
if (lib39$getSyncData() != null && !lib39$getSyncData().isEmpty()) {
|
||||
tag.put("Lib39Data", lib39$getSyncData());
|
||||
output.store("Lib39Data", CompoundTag.CODEC, lib39$getSyncData());
|
||||
}
|
||||
return tag;
|
||||
}
|
||||
|
||||
/**
|
||||
* Lib 39 inject load sync data.
|
||||
*
|
||||
* @param tag the tag
|
||||
* @param input the input
|
||||
*/
|
||||
default void lib39$injectLoadSyncData(@NotNull CompoundTag tag) {
|
||||
if (tag.contains("Lib39Data", Tag.TAG_COMPOUND)) {
|
||||
lib39$setSyncData(tag.getCompound("Lib39Data"));
|
||||
default void lib39$injectLoadSyncData(@NotNull ValueInput input) {
|
||||
Optional<ValueInput> lib39DataOpt = input.child("Lib39Data");
|
||||
if (lib39DataOpt.isPresent()) {
|
||||
ValueInput valueInput = lib39DataOpt.get();
|
||||
Optional<CompoundTag> lib39Data = valueInput.read("Lib39Data", CompoundTag.CODEC);
|
||||
lib39$setSyncData(lib39Data.get());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -63,7 +68,10 @@ public interface ILib39SyncDataHolder {
|
|||
*/
|
||||
default void loadSyncData(NBTEntitySyncData syncData) {
|
||||
if (syncData != null && lib39$getSyncData().contains(syncData.id.toDebugFileName())) {
|
||||
syncData.deserializeNBT(lib39$getSyncData().getCompound(syncData.id.toDebugFileName()));
|
||||
Optional<CompoundTag> compound = lib39$getSyncData().getCompound(syncData.id.toDebugFileName());
|
||||
if (compound.isPresent()) {
|
||||
syncData.deserializeNBT(compound.get());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -7,7 +7,7 @@ import net.minecraft.nbt.Tag;
|
|||
*
|
||||
* @param <T> the type parameter
|
||||
*/
|
||||
public interface INBTSerializable <T extends Tag>{
|
||||
public interface INBTSerializable <T extends Tag> {
|
||||
/**
|
||||
* Serialize nbt t.
|
||||
*
|
||||
|
|
@ -18,7 +18,7 @@ public interface INBTSerializable <T extends Tag>{
|
|||
/**
|
||||
* Deserialize nbt.
|
||||
*
|
||||
* @param var1 the var 1
|
||||
* @param t the var
|
||||
*/
|
||||
void deserializeNBT(T var1);
|
||||
void deserializeNBT(T t);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
package top.r3944realms.lib39.core.sync;
|
||||
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.resources.Identifier;
|
||||
|
||||
/**
|
||||
* The interface Sync data.
|
||||
|
|
@ -13,7 +13,7 @@ public interface ISyncData<T> {
|
|||
*
|
||||
* @return the resource location
|
||||
*/
|
||||
ResourceLocation id();
|
||||
Identifier id();
|
||||
|
||||
/**
|
||||
* Is dirty boolean.
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
package top.r3944realms.lib39.core.sync;
|
||||
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.resources.Identifier;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
|
|
@ -15,19 +15,19 @@ public abstract class NBTEntitySyncData implements IEntity, ISyncData<NBTEntityS
|
|||
/**
|
||||
* The Id.
|
||||
*/
|
||||
protected final ResourceLocation id;
|
||||
protected final Identifier id;
|
||||
|
||||
/**
|
||||
* Instantiates a new Nbt sync data.
|
||||
*
|
||||
* @param id the id
|
||||
*/
|
||||
protected NBTEntitySyncData(ResourceLocation id) {
|
||||
protected NBTEntitySyncData(Identifier id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResourceLocation id() {
|
||||
public Identifier id() {
|
||||
return id;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
package top.r3944realms.lib39.core.sync;
|
||||
|
||||
import com.google.common.collect.Sets;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.resources.Identifier;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
|
@ -22,7 +22,7 @@ public abstract class SyncData2Manager<V extends SyncData2Manager.TypedSyncEntry
|
|||
*
|
||||
* @return the typed entries
|
||||
*/
|
||||
protected abstract Map<ResourceLocation, V> getTypedEntries();
|
||||
protected abstract Map<Identifier, V> getTypedEntries();
|
||||
|
||||
/**
|
||||
* 数据提供者接口 - 用于通过键获取数据
|
||||
|
|
@ -86,11 +86,11 @@ public abstract class SyncData2Manager<V extends SyncData2Manager.TypedSyncEntry
|
|||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public <K, T extends ISyncData<?>> void registerManagerWithProvider(
|
||||
ResourceLocation key,
|
||||
Identifier key,
|
||||
ISyncManager<K, T> manager,
|
||||
DataProvider<Entity, T> dataProvider
|
||||
) {
|
||||
Objects.requireNonNull(key, "ResourceLocation key cannot be null");
|
||||
Objects.requireNonNull(key, "Identifier key cannot be null");
|
||||
Objects.requireNonNull(manager, "Sync manager cannot be null");
|
||||
Objects.requireNonNull(dataProvider, "Data provider cannot be null");
|
||||
|
||||
|
|
@ -108,11 +108,11 @@ public abstract class SyncData2Manager<V extends SyncData2Manager.TypedSyncEntry
|
|||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public <K, T extends ISyncData<?>> void registerManager(
|
||||
ResourceLocation key,
|
||||
Identifier key,
|
||||
ISyncManager<K, T> manager,
|
||||
Function<Entity, Optional<T>> getter
|
||||
) {
|
||||
Objects.requireNonNull(key, "ResourceLocation key cannot be null");
|
||||
Objects.requireNonNull(key, "Identifier key cannot be null");
|
||||
Objects.requireNonNull(manager, "Sync manager cannot be null");
|
||||
Objects.requireNonNull(getter, "Data getter function cannot be null");
|
||||
|
||||
|
|
@ -126,8 +126,8 @@ public abstract class SyncData2Manager<V extends SyncData2Manager.TypedSyncEntry
|
|||
* @param manager the manager
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public void registerManager(ResourceLocation key, ISyncManager<?, ? extends ISyncData<?>> manager) {
|
||||
Objects.requireNonNull(key, "ResourceLocation key cannot be null");
|
||||
public void registerManager(Identifier key, ISyncManager<?, ? extends ISyncData<?>> manager) {
|
||||
Objects.requireNonNull(key, "Identifier key cannot be null");
|
||||
Objects.requireNonNull(manager, "Sync manager cannot be null");
|
||||
|
||||
// 创建一个没有数据提供者的 TypedSyncEntry
|
||||
|
|
@ -146,7 +146,7 @@ public abstract class SyncData2Manager<V extends SyncData2Manager.TypedSyncEntry
|
|||
* @return the manager
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public <K, T extends ISyncData<?>> Optional<ISyncManager<K, T>> getManager(ResourceLocation key) {
|
||||
public <K, T extends ISyncData<?>> Optional<ISyncManager<K, T>> getManager(Identifier key) {
|
||||
TypedSyncEntry<?,?> entry = getTypedEntries().get(key);
|
||||
return entry != null ? Optional.of((ISyncManager<K,T>) entry.manager) : Optional.empty();
|
||||
}
|
||||
|
|
@ -159,7 +159,7 @@ public abstract class SyncData2Manager<V extends SyncData2Manager.TypedSyncEntry
|
|||
* @return the data provider
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T extends ISyncData<?>> Optional<DataProvider<Entity, T>> getDataProvider(ResourceLocation key) {
|
||||
public <T extends ISyncData<?>> Optional<DataProvider<Entity, T>> getDataProvider(Identifier key) {
|
||||
TypedSyncEntry<?, ?> entry = getTypedEntries().get(key);
|
||||
if (entry != null && entry.dataProvider != null) {
|
||||
return Optional.of((DataProvider<Entity, T>) entry.dataProvider);
|
||||
|
|
@ -176,7 +176,7 @@ public abstract class SyncData2Manager<V extends SyncData2Manager.TypedSyncEntry
|
|||
* @return the entity data
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T extends ISyncData<?>> Optional<T> getEntityData(ResourceLocation key, Entity entity) {
|
||||
public <T extends ISyncData<?>> Optional<T> getEntityData(Identifier key, Entity entity) {
|
||||
return getDataProvider(key)
|
||||
.flatMap(provider -> {
|
||||
Optional<ISyncData<?>> result = provider.getData(entity);
|
||||
|
|
@ -190,8 +190,8 @@ public abstract class SyncData2Manager<V extends SyncData2Manager.TypedSyncEntry
|
|||
* @param key the key
|
||||
* @param classes the classes
|
||||
*/
|
||||
public final void allowEntityClass(ResourceLocation key, Class<?>... classes) {
|
||||
Objects.requireNonNull(key, "ResourceLocation key cannot be null");
|
||||
public final void allowEntityClass(Identifier key, Class<?>... classes) {
|
||||
Objects.requireNonNull(key, "Identifier key cannot be null");
|
||||
Objects.requireNonNull(classes, "Classes array cannot be null");
|
||||
|
||||
if (classes.length == 0) {
|
||||
|
|
@ -210,8 +210,8 @@ public abstract class SyncData2Manager<V extends SyncData2Manager.TypedSyncEntry
|
|||
* @param key the key
|
||||
* @param classes the classes
|
||||
*/
|
||||
public final void disallowEntityClass(ResourceLocation key, Class<?>... classes) {
|
||||
Objects.requireNonNull(key, "ResourceLocation key cannot be null");
|
||||
public final void disallowEntityClass(Identifier key, Class<?>... classes) {
|
||||
Objects.requireNonNull(key, "Identifier key cannot be null");
|
||||
Objects.requireNonNull(classes, "Classes array cannot be null");
|
||||
|
||||
TypedSyncEntry<?, ?> entry = getTypedEntries().get(key);
|
||||
|
|
@ -227,8 +227,8 @@ public abstract class SyncData2Manager<V extends SyncData2Manager.TypedSyncEntry
|
|||
* @param key the key
|
||||
* @param dataProvider the data provider
|
||||
*/
|
||||
public <T extends ISyncData<?>> void bindDataProvider(ResourceLocation key, DataProvider<Entity, T> dataProvider) {
|
||||
Objects.requireNonNull(key, "ResourceLocation key cannot be null");
|
||||
public <T extends ISyncData<?>> void bindDataProvider(Identifier key, DataProvider<Entity, T> dataProvider) {
|
||||
Objects.requireNonNull(key, "Identifier key cannot be null");
|
||||
Objects.requireNonNull(dataProvider, "Data provider cannot be null");
|
||||
|
||||
TypedSyncEntry<?, ?> entry = getTypedEntries().get(key);
|
||||
|
|
@ -247,7 +247,7 @@ public abstract class SyncData2Manager<V extends SyncData2Manager.TypedSyncEntry
|
|||
* @param key the key
|
||||
* @param getter the data getter function
|
||||
*/
|
||||
public <T extends ISyncData<?>> void bindDataGetter(ResourceLocation key, @NotNull Function<Entity, Optional<T>> getter) {
|
||||
public <T extends ISyncData<?>> void bindDataGetter(Identifier key, @NotNull Function<Entity, Optional<T>> getter) {
|
||||
bindDataProvider(key, getter::apply);
|
||||
}
|
||||
|
||||
|
|
@ -256,8 +256,8 @@ public abstract class SyncData2Manager<V extends SyncData2Manager.TypedSyncEntry
|
|||
*
|
||||
* @param key the key
|
||||
*/
|
||||
public void unbindDataProvider(ResourceLocation key) {
|
||||
Objects.requireNonNull(key, "ResourceLocation key cannot be null");
|
||||
public void unbindDataProvider(Identifier key) {
|
||||
Objects.requireNonNull(key, "Identifier key cannot be null");
|
||||
|
||||
TypedSyncEntry<?, ?> entry = getTypedEntries().get(key);
|
||||
if (entry != null) {
|
||||
|
|
@ -271,8 +271,8 @@ public abstract class SyncData2Manager<V extends SyncData2Manager.TypedSyncEntry
|
|||
*
|
||||
* @param key the key
|
||||
*/
|
||||
public void clearAllowedEntityClasses(ResourceLocation key) {
|
||||
Objects.requireNonNull(key, "ResourceLocation key cannot be null");
|
||||
public void clearAllowedEntityClasses(Identifier key) {
|
||||
Objects.requireNonNull(key, "Identifier key cannot be null");
|
||||
|
||||
TypedSyncEntry<?, ?> entry = getTypedEntries().get(key);
|
||||
if (entry != null) {
|
||||
|
|
@ -287,8 +287,8 @@ public abstract class SyncData2Manager<V extends SyncData2Manager.TypedSyncEntry
|
|||
* @param entityClass the entity class
|
||||
* @return the boolean
|
||||
*/
|
||||
public boolean isEntityClassAllowed(ResourceLocation key, Class<?> entityClass) {
|
||||
Objects.requireNonNull(key, "ResourceLocation key cannot be null");
|
||||
public boolean isEntityClassAllowed(Identifier key, Class<?> entityClass) {
|
||||
Objects.requireNonNull(key, "Identifier key cannot be null");
|
||||
Objects.requireNonNull(entityClass, "Entity class cannot be null");
|
||||
|
||||
TypedSyncEntry<?, ?> entry = getTypedEntries().get(key);
|
||||
|
|
@ -311,7 +311,7 @@ public abstract class SyncData2Manager<V extends SyncData2Manager.TypedSyncEntry
|
|||
* @param managerId the manager id
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public void trackEntityForManager(Entity entity, ResourceLocation managerId) {
|
||||
public void trackEntityForManager(Entity entity, Identifier managerId) {
|
||||
TypedSyncEntry<UUID, ?> entry = (TypedSyncEntry<UUID, ?>) getTypedEntries().get(managerId);
|
||||
if (entry != null) {
|
||||
trackEntityWithTypedEntry(entity, entry);
|
||||
|
|
@ -332,7 +332,7 @@ public abstract class SyncData2Manager<V extends SyncData2Manager.TypedSyncEntry
|
|||
* @param managerId the manager id
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public void untrackEntityForManager(Entity entity, ResourceLocation managerId) {
|
||||
public void untrackEntityForManager(Entity entity, Identifier managerId) {
|
||||
TypedSyncEntry<UUID, ?> entry = (TypedSyncEntry<UUID, ?>) getTypedEntries().get(managerId);
|
||||
if (entry != null) {
|
||||
untrackEntityWithTypedEntry(entity, entry);
|
||||
|
|
@ -352,7 +352,7 @@ public abstract class SyncData2Manager<V extends SyncData2Manager.TypedSyncEntry
|
|||
* @param entity the entity
|
||||
*/
|
||||
public void untrackEntityFromAllManagers(Entity entity) {
|
||||
for (ResourceLocation id : getRegisteredKeys()) {
|
||||
for (Identifier id : getRegisteredKeys()) {
|
||||
if (isEntityClassAllowed(id, entity.getClass())) {
|
||||
untrackEntityForManager(entity, id);
|
||||
}
|
||||
|
|
@ -365,7 +365,7 @@ public abstract class SyncData2Manager<V extends SyncData2Manager.TypedSyncEntry
|
|||
* @param entities the entities
|
||||
* @param managerId the manager id
|
||||
*/
|
||||
public void untrackEntitiesForManager(@NotNull Iterable<Entity> entities, ResourceLocation managerId) {
|
||||
public void untrackEntitiesForManager(@NotNull Iterable<Entity> entities, Identifier managerId) {
|
||||
for (Entity entity : entities) {
|
||||
untrackEntityForManager(entity, managerId);
|
||||
}
|
||||
|
|
@ -387,7 +387,7 @@ public abstract class SyncData2Manager<V extends SyncData2Manager.TypedSyncEntry
|
|||
*
|
||||
* @param managerId the manager id
|
||||
*/
|
||||
public void clearAllTrackedData(ResourceLocation managerId) {
|
||||
public void clearAllTrackedData(Identifier managerId) {
|
||||
TypedSyncEntry<?, ?> entry = getTypedEntries().get(managerId);
|
||||
if (entry != null) {
|
||||
clearTrackedDataForEntry(entry);
|
||||
|
|
@ -405,7 +405,7 @@ public abstract class SyncData2Manager<V extends SyncData2Manager.TypedSyncEntry
|
|||
* 清理所有管理器的跟踪数据
|
||||
*/
|
||||
public void clearAllTrackedData() {
|
||||
for (ResourceLocation id : getRegisteredKeys()) {
|
||||
for (Identifier id : getRegisteredKeys()) {
|
||||
clearAllTrackedData(id);
|
||||
}
|
||||
}
|
||||
|
|
@ -422,7 +422,7 @@ public abstract class SyncData2Manager<V extends SyncData2Manager.TypedSyncEntry
|
|||
// 辅助方法:更新条目的数据提供者
|
||||
@SuppressWarnings("unchecked")
|
||||
protected <K, T extends ISyncData<?>> void updateDataProviderInEntry(
|
||||
ResourceLocation id,
|
||||
Identifier id,
|
||||
TypedSyncEntry<?,?> entry,
|
||||
DataProvider<Entity, T> newDataProvider
|
||||
) {
|
||||
|
|
@ -441,7 +441,7 @@ public abstract class SyncData2Manager<V extends SyncData2Manager.TypedSyncEntry
|
|||
*
|
||||
* @return the registered keys
|
||||
*/
|
||||
public Set<ResourceLocation> getRegisteredKeys() {
|
||||
public Set<Identifier> getRegisteredKeys() {
|
||||
return Collections.unmodifiableSet(getTypedEntries().keySet());
|
||||
}
|
||||
|
||||
|
|
@ -450,7 +450,7 @@ public abstract class SyncData2Manager<V extends SyncData2Manager.TypedSyncEntry
|
|||
*
|
||||
* @param consumer the consumer
|
||||
*/
|
||||
public void forEach(BiConsumer<ResourceLocation, ISyncManager<?,?>> consumer) {
|
||||
public void forEach(BiConsumer<Identifier, ISyncManager<?,?>> consumer) {
|
||||
Objects.requireNonNull(consumer, "Consumer cannot be null");
|
||||
getTypedEntries().forEach((key, entry) -> consumer.accept(key, entry.manager));
|
||||
}
|
||||
|
|
@ -476,8 +476,8 @@ public abstract class SyncData2Manager<V extends SyncData2Manager.TypedSyncEntry
|
|||
*
|
||||
* @param key the key
|
||||
*/
|
||||
public void removeManager(ResourceLocation key) {
|
||||
Objects.requireNonNull(key, "ResourceLocation key cannot be null");
|
||||
public void removeManager(Identifier key) {
|
||||
Objects.requireNonNull(key, "Identifier key cannot be null");
|
||||
getTypedEntries().remove(key);
|
||||
}
|
||||
}
|
||||
|
|
@ -123,26 +123,6 @@ public abstract class LanguageProvider implements DataProvider {
|
|||
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.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
package top.r3944realms.lib39.example.content.data;
|
||||
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.resources.Identifier;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import top.r3944realms.lib39.core.sync.NBTEntitySyncData;
|
||||
|
||||
|
|
@ -36,7 +36,7 @@ public abstract class AbstractedTestSyncData extends NBTEntitySyncData {
|
|||
*
|
||||
* @param id the id
|
||||
*/
|
||||
protected AbstractedTestSyncData(ResourceLocation id) {
|
||||
protected AbstractedTestSyncData(Identifier id) {
|
||||
super(id);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ package top.r3944realms.lib39.example.content.item;
|
|||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.world.InteractionHand;
|
||||
import net.minecraft.world.InteractionResultHolder;
|
||||
import net.minecraft.world.InteractionResult;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.entity.LivingEntity;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
|
|
@ -11,16 +11,16 @@ import net.minecraft.world.entity.projectile.ProjectileUtil;
|
|||
import net.minecraft.world.item.Item;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.item.TooltipFlag;
|
||||
import net.minecraft.world.item.component.TooltipDisplay;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.phys.EntityHitResult;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import top.r3944realms.lib39.Lib39;
|
||||
import top.r3944realms.lib39.example.content.data.AbstractedTestSyncData;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
/**
|
||||
* 用于执行数据查询并检查同步状态的物品
|
||||
|
|
@ -39,7 +39,7 @@ public abstract class AbstractFabricItem extends Item {
|
|||
}
|
||||
|
||||
@Override
|
||||
public @NotNull InteractionResultHolder<ItemStack> use(@NotNull Level level, @NotNull Player player, @NotNull InteractionHand hand) {
|
||||
public InteractionResult use(@NotNull Level level, @NotNull Player player, @NotNull InteractionHand hand) {
|
||||
ItemStack itemStack = player.getItemInHand(hand);
|
||||
|
||||
if (level.isClientSide()) {
|
||||
|
|
@ -64,10 +64,10 @@ public abstract class AbstractFabricItem extends Item {
|
|||
}
|
||||
|
||||
// 添加冷却时间
|
||||
player.getCooldowns().addCooldown(this, 20); // 1秒冷却
|
||||
player.getCooldowns().addCooldown(itemStack, 20); // 1秒冷却
|
||||
}
|
||||
|
||||
return InteractionResultHolder.sidedSuccess(itemStack, level.isClientSide());
|
||||
return InteractionResult.SUCCESS.heldItemTransformedTo(itemStack);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -193,7 +193,7 @@ public abstract class AbstractFabricItem extends Item {
|
|||
Thread.sleep(3000);
|
||||
|
||||
// 在服务器线程中执行结果处理
|
||||
player.server.execute(() -> {
|
||||
player.level().getServer().execute(() -> {
|
||||
displayServerSingleEndResults(player, target);
|
||||
});
|
||||
|
||||
|
|
@ -203,7 +203,7 @@ public abstract class AbstractFabricItem extends Item {
|
|||
player.sendSystemMessage(Component.literal("§c数据查询被中断"));
|
||||
} catch (Exception e) {
|
||||
Lib39.LOGGER.error("[FabricItem] 数据查询出错", e);
|
||||
player.server.execute(() ->
|
||||
player.level().getServer().execute(() ->
|
||||
player.sendSystemMessage(Component.literal("§c数据查询出错: " + e.getMessage()))
|
||||
);
|
||||
}
|
||||
|
|
@ -530,29 +530,28 @@ public abstract class AbstractFabricItem extends Item {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void appendHoverText(@NotNull ItemStack stack, @Nullable Level level,
|
||||
@NotNull List<Component> tooltip, @NotNull TooltipFlag flag) {
|
||||
super.appendHoverText(stack, level, tooltip, flag);
|
||||
|
||||
tooltip.add(Component.literal("§7右键点击在 3 秒后执行"));
|
||||
tooltip.add(Component.literal("§7§e准星瞄准生物§7的数据查询"));
|
||||
tooltip.add(Component.literal("§7§oShift + 右键§7进行§e客户端-服务器双端同步检查§7"));
|
||||
tooltip.add(Component.literal(""));
|
||||
tooltip.add(Component.literal("§6查询延迟: §e3秒"));
|
||||
tooltip.add(Component.literal("§6瞄准距离: §e20格"));
|
||||
tooltip.add(Component.literal("§6冷却时间: §e1秒"));
|
||||
tooltip.add(Component.literal(""));
|
||||
tooltip.add(Component.literal("§a单端查询内容:"));
|
||||
tooltip.add(Component.literal("§7- 基础数据字段"));
|
||||
tooltip.add(Component.literal("§7- 自定义数据结构"));
|
||||
tooltip.add(Component.literal("§7- 数据验证状态"));
|
||||
tooltip.add(Component.literal("§7- 同步状态信息"));
|
||||
tooltip.add(Component.literal(""));
|
||||
tooltip.add(Component.literal("§e双端同步检查:"));
|
||||
tooltip.add(Component.literal("§7- 客户端和服务器同时查询"));
|
||||
tooltip.add(Component.literal("§7- 字段级同步状态对比"));
|
||||
tooltip.add(Component.literal("§7- 总体同步率计算"));
|
||||
tooltip.add(Component.literal("§7- 双端数据状态差异"));
|
||||
tooltip.add(Component.literal("§7- 同步建议"));
|
||||
public void appendHoverText(ItemStack itemStack, TooltipContext context, TooltipDisplay display, Consumer<Component> componentConsumer, TooltipFlag tooltipFlag) {
|
||||
super.appendHoverText(itemStack, context, display, componentConsumer, tooltipFlag);
|
||||
componentConsumer.accept(Component.literal("§7右键点击在 3 秒后执行"));
|
||||
componentConsumer.accept(Component.literal("§7§e准星瞄准生物§7的数据查询"));
|
||||
componentConsumer.accept(Component.literal("§7§oShift + 右键§7进行§e客户端-服务器双端同步检查§7"));
|
||||
componentConsumer.accept(Component.literal(""));
|
||||
componentConsumer.accept(Component.literal("§6查询延迟: §e3秒"));
|
||||
componentConsumer.accept(Component.literal("§6瞄准距离: §e20格"));
|
||||
componentConsumer.accept(Component.literal("§6冷却时间: §e1秒"));
|
||||
componentConsumer.accept(Component.literal(""));
|
||||
componentConsumer.accept(Component.literal("§a单端查询内容:"));
|
||||
componentConsumer.accept(Component.literal("§7- 基础数据字段"));
|
||||
componentConsumer.accept(Component.literal("§7- 自定义数据结构"));
|
||||
componentConsumer.accept(Component.literal("§7- 数据验证状态"));
|
||||
componentConsumer.accept(Component.literal("§7- 同步状态信息"));
|
||||
componentConsumer.accept(Component.literal(""));
|
||||
componentConsumer.accept(Component.literal("§e双端同步检查:"));
|
||||
componentConsumer.accept(Component.literal("§7- 客户端和服务器同时查询"));
|
||||
componentConsumer.accept(Component.literal("§7- 字段级同步状态对比"));
|
||||
componentConsumer.accept(Component.literal("§7- 总体同步率计算"));
|
||||
componentConsumer.accept(Component.literal("§7- 双端数据状态差异"));
|
||||
componentConsumer.accept(Component.literal("§7- 同步建议"));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -3,7 +3,7 @@ package top.r3944realms.lib39.example.content.item;
|
|||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.world.InteractionHand;
|
||||
import net.minecraft.world.InteractionResultHolder;
|
||||
import net.minecraft.world.InteractionResult;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.entity.LivingEntity;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
|
|
@ -11,16 +11,16 @@ import net.minecraft.world.entity.projectile.ProjectileUtil;
|
|||
import net.minecraft.world.item.Item;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.item.TooltipFlag;
|
||||
import net.minecraft.world.item.component.TooltipDisplay;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.phys.EntityHitResult;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import top.r3944realms.lib39.Lib39;
|
||||
import top.r3944realms.lib39.example.content.data.AbstractedTestSyncData;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
/**
|
||||
* 用于对准星生物触发 TestSyncData 随机变换的物品
|
||||
|
|
@ -40,7 +40,7 @@ public abstract class AbstractNeoForgeItem extends Item {
|
|||
}
|
||||
|
||||
@Override
|
||||
public @NotNull InteractionResultHolder<ItemStack> use(@NotNull Level level, @NotNull Player player, @NotNull InteractionHand hand) {
|
||||
public InteractionResult use(@NotNull Level level, @NotNull Player player, @NotNull InteractionHand hand) {
|
||||
ItemStack itemStack = player.getItemInHand(hand);
|
||||
|
||||
if (!level.isClientSide()) {
|
||||
|
|
@ -55,10 +55,10 @@ public abstract class AbstractNeoForgeItem extends Item {
|
|||
}
|
||||
|
||||
// 添加冷却时间
|
||||
player.getCooldowns().addCooldown(this, 20); // 1秒冷却
|
||||
player.getCooldowns().addCooldown(itemStack, 20); // 1秒冷却
|
||||
}
|
||||
|
||||
return InteractionResultHolder.sidedSuccess(itemStack, level.isClientSide());
|
||||
return InteractionResult.SUCCESS.heldItemTransformedTo(itemStack);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -268,27 +268,25 @@ public abstract class AbstractNeoForgeItem extends Item {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void appendHoverText(@NotNull ItemStack stack, @Nullable Level level,
|
||||
@NotNull List<Component> tooltip, @NotNull TooltipFlag flag) {
|
||||
super.appendHoverText(stack, level, tooltip, flag);
|
||||
|
||||
tooltip.add(Component.literal("§7右键点击触发§e准星瞄准生物§7的"));
|
||||
tooltip.add(Component.literal("§7测试数据随机变换"));
|
||||
tooltip.add(Component.literal("§7§oShift + 右键§7操作§e自身§7数据"));
|
||||
tooltip.add(Component.literal(""));
|
||||
tooltip.add(Component.literal("§6冷却时间: §e1秒"));
|
||||
tooltip.add(Component.literal("§6瞄准距离: §e20格"));
|
||||
tooltip.add(Component.literal(""));
|
||||
tooltip.add(Component.literal("§a变换类型:"));
|
||||
tooltip.add(Component.literal("§7- 完全随机数据"));
|
||||
tooltip.add(Component.literal("§7- 字符串+计数器"));
|
||||
tooltip.add(Component.literal("§7- 数值数据"));
|
||||
tooltip.add(Component.literal("§7- 自定义数据"));
|
||||
tooltip.add(Component.literal("§7- 重置默认值"));
|
||||
tooltip.add(Component.literal("§7- 玩家专属数据"));
|
||||
tooltip.add(Component.literal(""));
|
||||
tooltip.add(Component.literal("§e自身操作特性:"));
|
||||
tooltip.add(Component.literal("§7- 显示数据预览"));
|
||||
tooltip.add(Component.literal("§7- 玩家专属数据变换"));
|
||||
public void appendHoverText(ItemStack itemStack, TooltipContext context, TooltipDisplay display, Consumer<Component> componentConsumer, TooltipFlag tooltipFlag) {
|
||||
super.appendHoverText(itemStack, context, display, componentConsumer, tooltipFlag);
|
||||
componentConsumer.accept(Component.literal("§7右键点击触发§e准星瞄准生物§7的"));
|
||||
componentConsumer.accept(Component.literal("§7测试数据随机变换"));
|
||||
componentConsumer.accept(Component.literal("§7§oShift + 右键§7操作§e自身§7数据"));
|
||||
componentConsumer.accept(Component.literal(""));
|
||||
componentConsumer.accept(Component.literal("§6冷却时间: §e1秒"));
|
||||
componentConsumer.accept(Component.literal("§6瞄准距离: §e20格"));
|
||||
componentConsumer.accept(Component.literal(""));
|
||||
componentConsumer.accept(Component.literal("§a变换类型:"));
|
||||
componentConsumer.accept(Component.literal("§7- 完全随机数据"));
|
||||
componentConsumer.accept(Component.literal("§7- 字符串+计数器"));
|
||||
componentConsumer.accept(Component.literal("§7- 数值数据"));
|
||||
componentConsumer.accept(Component.literal("§7- 自定义数据"));
|
||||
componentConsumer.accept(Component.literal("§7- 重置默认值"));
|
||||
componentConsumer.accept(Component.literal("§7- 玩家专属数据"));
|
||||
componentConsumer.accept(Component.literal(""));
|
||||
componentConsumer.accept(Component.literal("§e自身操作特性:"));
|
||||
componentConsumer.accept(Component.literal("§7- 显示数据预览"));
|
||||
componentConsumer.accept(Component.literal("§7- 玩家专属数据变换"));
|
||||
}
|
||||
}
|
||||
|
|
@ -2,10 +2,10 @@ package top.r3944realms.lib39.example.content.item;
|
|||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.world.InteractionHand;
|
||||
import net.minecraft.world.InteractionResultHolder;
|
||||
|
||||
import net.minecraft.world.InteractionResult;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.item.Item;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.level.Level;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import top.r3944realms.lib39.example.client.screen.ForgeScreen;
|
||||
|
|
@ -25,7 +25,7 @@ public class ForgeItem extends Item {
|
|||
}
|
||||
|
||||
@Override
|
||||
public @NotNull InteractionResultHolder<ItemStack> use(@NotNull Level level, @NotNull Player player, @NotNull InteractionHand usedHand) {
|
||||
public @NotNull InteractionResult use(@NotNull Level level, @NotNull Player player, @NotNull InteractionHand usedHand) {
|
||||
if (level.isClientSide() && usedHand == InteractionHand.MAIN_HAND) {
|
||||
ClientOpt.clientUse(usedHand);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,48 +4,50 @@ import com.llamalad7.mixinextras.sugar.Local;
|
|||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.item.component.ResolvableProfile;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Pseudo;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.ModifyVariable;
|
||||
import top.r3944realms.lib39.content.item.DollItem;
|
||||
import top.r3944realms.lib39.util.GameProfileHelper;
|
||||
import top.r3944realms.lib39.util.storage.nbt.NBTReader;
|
||||
import tschipp.carryon.client.render.CarriedObjectRender;
|
||||
import tschipp.carryon.common.carry.CarryOnData;
|
||||
import tschipp.carryon.common.carry.CarryOnDataManager;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
/**
|
||||
* The type Mixin carried object render.
|
||||
*/
|
||||
@SuppressWarnings("DuplicatedCode")
|
||||
@Pseudo
|
||||
@Mixin(value = CarriedObjectRender.class, remap = false)
|
||||
public class MixinCarriedObjectRender {
|
||||
@ModifyVariable(
|
||||
method = "drawFirstPersonBlock",
|
||||
method = "drawBlock",
|
||||
at = @At(
|
||||
value = "LOAD",
|
||||
target = "Ltschipp/carryon/client/render/CarryRenderHelper;renderBakedModel(Lnet/minecraft/world/item/ItemStack;Lcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/MultiBufferSource;ILnet/minecraft/client/resources/model/BakedModel;)V"
|
||||
)
|
||||
value = "INVOKE",
|
||||
target = "Lnet/minecraft/client/renderer/item/ItemStackRenderState;submit(Lcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/SubmitNodeCollector;III)V",
|
||||
shift = At.Shift.BEFORE
|
||||
),
|
||||
ordinal = 0
|
||||
)
|
||||
private static ItemStack warpDollItem$1(ItemStack stack, @Local(ordinal = 0, argsOnly = true) Player player) {
|
||||
if (stack.getItem() instanceof DollItem) {
|
||||
CompoundTag compound = CarryOnDataManager.getCarryData(player).getNbt().getCompound("tile").getCompound(GameProfileHelper.TAG_OWN_PROFILE);
|
||||
stack.getOrCreateTag().put(GameProfileHelper.TAG_OWN_PROFILE, compound);
|
||||
private static ItemStack modifyRenderStack(ItemStack renderStack, @Local(argsOnly = true) Player player) {
|
||||
if (renderStack.getItem() instanceof DollItem) {
|
||||
CarryOnData carry = CarryOnDataManager.getCarryData(player);
|
||||
if (carry != null) {
|
||||
Optional<CompoundTag> compound = carry.getNbt().getCompound("tile");
|
||||
AtomicReference<ResolvableProfile> profileHolder = new AtomicReference<>();
|
||||
NBTReader.ofOpt(compound).gameProfile("profile", profileHolder::set);
|
||||
if (profileHolder.get() != null) {
|
||||
GameProfileHelper.saveProfileToItemStack(renderStack,profileHolder.get());
|
||||
}
|
||||
}
|
||||
}
|
||||
return stack;
|
||||
}
|
||||
@ModifyVariable(
|
||||
method = "drawThirdPerson",
|
||||
at = @At(
|
||||
value = "LOAD",
|
||||
target = "Ltschipp/carryon/client/render/CarryRenderHelper;renderBakedModel(Lnet/minecraft/world/item/ItemStack;Lcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/MultiBufferSource;ILnet/minecraft/client/resources/model/BakedModel;)V"
|
||||
)
|
||||
)
|
||||
private static ItemStack warpDollItem$2(ItemStack stack, @Local(ordinal = 0) Player player) {
|
||||
if (stack.getItem() instanceof DollItem) {
|
||||
CompoundTag compound = CarryOnDataManager.getCarryData(player).getNbt().getCompound("tile").getCompound(GameProfileHelper.TAG_OWN_PROFILE);
|
||||
stack.getOrCreateTag().put(GameProfileHelper.TAG_OWN_PROFILE, compound);
|
||||
}
|
||||
return stack;
|
||||
return renderStack;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,17 +1,19 @@
|
|||
package top.r3944realms.lib39.mixin;
|
||||
package top.r3944realms.lib39.mixin.minecraft;
|
||||
|
||||
import com.llamalad7.mixinextras.injector.wrapmethod.WrapMethod;
|
||||
import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.level.storage.ValueInput;
|
||||
import net.minecraft.world.level.storage.ValueOutput;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jspecify.annotations.NonNull;
|
||||
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.ILib39SyncDataHolder;
|
||||
import top.r3944realms.lib39.core.sync.ISyncData;
|
||||
import top.r3944realms.lib39.core.sync.NBTEntitySyncData;
|
||||
import top.r3944realms.lib39.core.sync.NBTEntitySyncData;import top.r3944realms.lib39.platform.Services;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
|
|
@ -44,19 +46,20 @@ public abstract class MixinEntity implements ILib39SyncDataHolder {
|
|||
}
|
||||
|
||||
@WrapMethod(method = "saveWithoutId")
|
||||
private CompoundTag wrapSave(CompoundTag compound, @NotNull Operation<CompoundTag> original) {
|
||||
FabricCommonEventHandler.getSyncData2Manager().forEach((id, manager) -> {
|
||||
private void wrapSave(ValueOutput output, @NonNull Operation<Void> original) {
|
||||
Services.PLATFORM.getUtilHelper().getSyncData2Manager().forEach((id, manager) -> {
|
||||
ISyncData<?> o = manager.getSyncMap().get(getUUID());
|
||||
if (o instanceof NBTEntitySyncData syncData) {
|
||||
saveSyncData(syncData);
|
||||
}
|
||||
});
|
||||
return lib39$injectSaveSyncData(original.call(compound));
|
||||
original.call(output);
|
||||
lib39$injectSaveSyncData(output);
|
||||
}
|
||||
|
||||
@WrapMethod(method = "load")
|
||||
private void warpLoad(CompoundTag compound, @NotNull Operation<Void> original) {
|
||||
original.call(compound);
|
||||
lib39$injectLoadSyncData(compound);
|
||||
private void warpLoad(ValueInput input, @NonNull Operation<Void> original) {
|
||||
original.call(input);
|
||||
lib39$injectLoadSyncData(input);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,5 +1,6 @@
|
|||
package top.r3944realms.lib39.platform.services;
|
||||
|
||||
import top.r3944realms.lib39.core.sync.SyncData2Manager;
|
||||
import top.r3944realms.lib39.util.block.BlockRegistryBuilder;
|
||||
|
||||
/**
|
||||
|
|
@ -12,4 +13,6 @@ public interface IUtilHelper {
|
|||
* @return the block registry builder
|
||||
*/
|
||||
BlockRegistryBuilder getBlockRegistryBuilder();
|
||||
|
||||
SyncData2Manager<?> getSyncData2Manager();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,27 +7,69 @@ import com.mojang.authlib.properties.Property;
|
|||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.multiplayer.PlayerInfo;
|
||||
import net.minecraft.client.player.AbstractClientPlayer;
|
||||
import net.minecraft.client.resources.DefaultPlayerSkin;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.nbt.NbtUtils;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.core.component.DataComponents;
|
||||
import net.minecraft.resources.Identifier;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.entity.player.PlayerModelType;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.item.component.ResolvableProfile;
|
||||
import net.minecraft.world.level.block.entity.SkullBlockEntity;
|
||||
import org.jetbrains.annotations.Contract;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import top.r3944realms.lib39.util.nbt.NBTReader;
|
||||
import top.r3944realms.lib39.util.nbt.NBTWriter;
|
||||
import org.jspecify.annotations.NonNull;
|
||||
import top.r3944realms.lib39.Lib39;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Base64;
|
||||
import java.util.Collection;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
/**
|
||||
* The type GameProfile helper.
|
||||
*/
|
||||
public class GameProfileHelper {
|
||||
/**
|
||||
* 获取 GameProfile(通过玩家名)
|
||||
*/
|
||||
@Contract("_ -> new")
|
||||
public static @NonNull ResolvableProfile fetchGameProfileByName(String name) {
|
||||
return ResolvableProfile.createUnresolved(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取 GameProfile(通过 UUID)
|
||||
* 直接复用 SkullBlockEntity 的实现
|
||||
*/
|
||||
@Contract("_ -> new")
|
||||
public static @NonNull ResolvableProfile fetchGameProfileByUUID(UUID uuid) {
|
||||
return ResolvableProfile.createUnresolved(uuid);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取 GameProfile(自动识别类型)
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <T> ResolvableProfile fetchGameProfile(T identifier) {
|
||||
if (identifier instanceof UUID uuid) {
|
||||
return fetchGameProfileByUUID(uuid);
|
||||
} else if (identifier instanceof String name) {
|
||||
return fetchGameProfileByName(name);
|
||||
} else if (identifier instanceof GameProfile gameProfile) {
|
||||
return ResolvableProfile.createResolved(gameProfile);
|
||||
}
|
||||
throw new IllegalArgumentException("Identifier type not supported: " + identifier.getClass());
|
||||
}
|
||||
|
||||
/**
|
||||
* 从 ItemStack 获取完整的 ResolvableProfile
|
||||
*/
|
||||
public static ResolvableProfile fetchProfileFromItemStack(@NotNull ItemStack stack) {
|
||||
ResolvableProfile resolvable = stack.get(DataComponents.PROFILE);
|
||||
if (resolvable == null) {
|
||||
return ResolvableProfile.Static.EMPTY;
|
||||
}
|
||||
return resolvable;
|
||||
}
|
||||
/**
|
||||
* Client Only Class
|
||||
*/
|
||||
|
|
@ -38,10 +80,10 @@ public class GameProfileHelper {
|
|||
* @param gameProfile the game profile
|
||||
* @return the resource location
|
||||
*/
|
||||
public static @NotNull ResourceLocation resolveSkinTexture(@NotNull GameProfile gameProfile) {
|
||||
public static @NotNull Identifier resolveSkinTexture(@NotNull GameProfile gameProfile) {
|
||||
return IClientOnly.check(() ->
|
||||
Minecraft.getInstance().getSkinManager()
|
||||
.getInsecureSkinLocation(gameProfile));
|
||||
.createLookup(gameProfile, true)).get().body().texturePath();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -50,10 +92,10 @@ public class GameProfileHelper {
|
|||
* @param gameProfile the game profile
|
||||
* @return the skin texture
|
||||
*/
|
||||
public static ResourceLocation getSkinTexture(@Nullable GameProfile gameProfile) {
|
||||
public static Identifier getSkinTexture(@Nullable GameProfile gameProfile) {
|
||||
return IClientOnly.check(() -> {
|
||||
if (gameProfile == null) {
|
||||
return DefaultPlayerSkin.getDefaultSkin();
|
||||
return Lib39.mrl("textures/entity/player/wide/steve.png");
|
||||
}
|
||||
return resolveSkinTexture(gameProfile);
|
||||
});
|
||||
|
|
@ -71,7 +113,7 @@ public class GameProfileHelper {
|
|||
PlayerInfo playerInfo = Objects.requireNonNull(Minecraft.getInstance()
|
||||
.getConnection())
|
||||
.getPlayerInfo(clientPlayer.getUUID());
|
||||
return playerInfo != null && "slim".equals(playerInfo.getModelName());
|
||||
return playerInfo != null && PlayerModelType.SLIM.equals(playerInfo.getSkin().model());
|
||||
}
|
||||
return false;
|
||||
});
|
||||
|
|
@ -85,21 +127,17 @@ public class GameProfileHelper {
|
|||
*/
|
||||
public static @NotNull String getSkinModelName(@NotNull Player player) {
|
||||
return IClientOnly.check(() -> {
|
||||
if (player.level().isClientSide && player instanceof AbstractClientPlayer) {
|
||||
if (player.level().isClientSide() && player instanceof AbstractClientPlayer) {
|
||||
PlayerInfo info = Objects.requireNonNull(Minecraft.getInstance().getConnection())
|
||||
.getPlayerInfo(player.getUUID());
|
||||
return info != null ? info.getModelName() : "default";
|
||||
return info != null ? info.getSkin().model().name() : PlayerModelType.WIDE.name();
|
||||
}
|
||||
return "default";
|
||||
return PlayerModelType.WIDE.name();
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* The constant TAG_BE.
|
||||
*/
|
||||
public static final String TAG_BE = "BlockEntityTag";
|
||||
/**
|
||||
* The constant TAG_OWN_PROFILE.
|
||||
*/
|
||||
|
|
@ -111,7 +149,7 @@ public class GameProfileHelper {
|
|||
* @param gameProfile the game profile
|
||||
* @return the skin texture
|
||||
*/
|
||||
public static ResourceLocation getSkinTexture(@Nullable GameProfile gameProfile) {
|
||||
public static Identifier getSkinTexture(@Nullable GameProfile gameProfile) {
|
||||
return ClientOpt.getSkinTexture(gameProfile);
|
||||
}
|
||||
|
||||
|
|
@ -122,7 +160,7 @@ public class GameProfileHelper {
|
|||
* @param gameProfile the game profile
|
||||
* @return the resource location
|
||||
*/
|
||||
public static @NotNull ResourceLocation resolveSkinTexture(@NotNull GameProfile gameProfile) {
|
||||
public static @NotNull Identifier resolveSkinTexture(@NotNull GameProfile gameProfile) {
|
||||
return ClientOpt.resolveSkinTexture(gameProfile);
|
||||
}
|
||||
|
||||
|
|
@ -133,7 +171,7 @@ public class GameProfileHelper {
|
|||
* @return the boolean
|
||||
*/
|
||||
public static boolean hasSlimArms(@NotNull Player player) {
|
||||
if (player.level().isClientSide) {
|
||||
if (player.level().isClientSide()) {
|
||||
return hasSlimArmsClient(player);
|
||||
} else {
|
||||
return hasSlimArmsServer(player);
|
||||
|
|
@ -148,9 +186,9 @@ public class GameProfileHelper {
|
|||
// 服务器端判断
|
||||
private static boolean hasSlimArmsServer(@NotNull Player player) {
|
||||
GameProfile profile = player.getGameProfile();
|
||||
for (Property property : profile.getProperties().get("textures")) {
|
||||
for (Property property : profile.properties().get("textures")) {
|
||||
try {
|
||||
String json = new String(Base64.getDecoder().decode(property.getValue()));
|
||||
String json = new String(Base64.getDecoder().decode(property.value()));
|
||||
JsonObject obj = JsonParser.parseString(json).getAsJsonObject();
|
||||
JsonObject textures = obj.getAsJsonObject("textures");
|
||||
JsonObject skin = textures.getAsJsonObject("SKIN");
|
||||
|
|
@ -190,14 +228,14 @@ public class GameProfileHelper {
|
|||
}
|
||||
|
||||
// 获取textures属性
|
||||
Collection<Property> textures = profile.getProperties().get("textures");
|
||||
Collection<Property> textures = profile.properties().get("textures");
|
||||
if (textures.isEmpty()) {
|
||||
return false; // 没有皮肤数据,使用默认
|
||||
}
|
||||
|
||||
// 获取第一个texture属性(通常是皮肤)
|
||||
Property textureProperty = textures.iterator().next();
|
||||
String value = textureProperty.getValue();
|
||||
String value = textureProperty.value();
|
||||
|
||||
try {
|
||||
return isSlimFromTextureData(value);
|
||||
|
|
@ -262,13 +300,13 @@ public class GameProfileHelper {
|
|||
return "default";
|
||||
}
|
||||
|
||||
Collection<Property> textures = profile.getProperties().get("textures");
|
||||
Collection<Property> textures = profile.properties().get("textures");
|
||||
if (textures.isEmpty()) {
|
||||
return "default";
|
||||
}
|
||||
|
||||
Property textureProperty = textures.iterator().next();
|
||||
String value = textureProperty.getValue();
|
||||
String value = textureProperty.value();
|
||||
|
||||
try {
|
||||
byte[] decodedBytes = Base64.getDecoder().decode(value);
|
||||
|
|
@ -291,64 +329,37 @@ public class GameProfileHelper {
|
|||
}
|
||||
|
||||
/**
|
||||
* 从ItemStack的NBT中读取GameProfile
|
||||
* 从ItemStack的组件中读取GameProfile
|
||||
*
|
||||
* @param stack the stack
|
||||
* @return the profile from item stack
|
||||
*/
|
||||
@Nullable
|
||||
public static GameProfile getProfileFromItemStack(ItemStack stack) {
|
||||
public static ResolvableProfile getProfileFromItemStack(@NotNull ItemStack stack) {
|
||||
if (stack.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
CompoundTag tag = stack.getTag();
|
||||
if (tag == null) {
|
||||
return null;
|
||||
}
|
||||
AtomicReference<GameProfile> profileRef = new AtomicReference<>();
|
||||
// 检查方块实体数据
|
||||
NBTReader.of(tag)
|
||||
.compound(TAG_BE, compoundTag ->
|
||||
NBTReader.of(compoundTag)
|
||||
.compound("OwnerProfile", ct -> profileRef.set(NbtUtils.readGameProfile(ct)))
|
||||
)
|
||||
.compound("OwnerProfile", ct -> {
|
||||
if (profileRef.get() == null) { //兼容写法
|
||||
profileRef.set(NbtUtils.readGameProfile(ct));
|
||||
}
|
||||
});
|
||||
return profileRef.get();
|
||||
if (stack.isEmpty()) return null;
|
||||
|
||||
ResolvableProfile profile = stack.get(DataComponents.PROFILE);
|
||||
return profile != null ? profile : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 将GameProfile保存到ItemStack的NBT
|
||||
* 将GameProfile保存到ItemStack的组件
|
||||
*
|
||||
* @param stack the stack
|
||||
* @param profile the profile
|
||||
*/
|
||||
public static void saveProfileToItemStack(@NotNull ItemStack stack, @Nullable GameProfile profile) {
|
||||
if (stack.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
CompoundTag tag = stack.getOrCreateTag();
|
||||
public static void saveProfileToItemStack(@NotNull ItemStack stack, @Nullable ResolvableProfile profile) {
|
||||
if (stack.isEmpty()) return;
|
||||
|
||||
if (profile == null) {
|
||||
// 移除现有数据
|
||||
NBTReader.of(tag)
|
||||
.compound(TAG_BE, ct -> tag.remove(TAG_OWN_PROFILE));
|
||||
tag.remove(TAG_BE);
|
||||
tag.remove(TAG_OWN_PROFILE);
|
||||
return;
|
||||
stack.remove(DataComponents.PROFILE);
|
||||
} else {
|
||||
stack.set(DataComponents.PROFILE, profile);
|
||||
}
|
||||
|
||||
// 创建方块实体数据
|
||||
NBTWriter.of(tag)
|
||||
.compound(TAG_BE, writer ->
|
||||
writer
|
||||
.compound(TAG_OWN_PROFILE, NbtUtils.writeGameProfile(new CompoundTag(), profile))
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -362,17 +373,7 @@ public class GameProfileHelper {
|
|||
return false;
|
||||
}
|
||||
|
||||
CompoundTag tag = stack.getTag();
|
||||
if (tag == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (tag.contains(TAG_BE)) {
|
||||
CompoundTag blockEntityTag = tag.getCompound(TAG_BE);
|
||||
return blockEntityTag.contains(TAG_OWN_PROFILE);
|
||||
}
|
||||
|
||||
return tag.contains(TAG_OWN_PROFILE);
|
||||
return !stack.isEmpty() && stack.has(DataComponents.PROFILE);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -145,7 +145,10 @@ public class MathUtil {
|
|||
* @return the direction
|
||||
*/
|
||||
public static Direction getDirection(BlockPos from, BlockPos to) {
|
||||
return Direction.fromDelta(from.getX() - to.getX(), from.getY() - to.getY(), from.getZ() - to.getZ());
|
||||
int dx = from.getX() - to.getX();
|
||||
int dy = from.getY() - to.getY();
|
||||
int dz = from.getZ() - to.getZ();
|
||||
return Direction.getNearest(dx, dy, dz, null);
|
||||
}
|
||||
|
||||
private static final Int2DoubleMap FACTORIAL_CACHE = new Int2DoubleOpenHashMap();
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
package top.r3944realms.lib39.util;
|
||||
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.resources.Identifier;
|
||||
import net.minecraft.util.StringRepresentable;
|
||||
import net.minecraft.world.item.Item;
|
||||
import net.minecraft.world.item.Items;
|
||||
|
|
@ -11,6 +11,7 @@ import top.r3944realms.lib39.Lib39;
|
|||
/**
|
||||
* The type Plant helper.
|
||||
*/
|
||||
//todo: 需添加26.1.2的新的Plant,部分条目可能需要重命名
|
||||
public class PlantHelper {
|
||||
/**
|
||||
* The enum Plant.
|
||||
|
|
@ -268,7 +269,7 @@ public class PlantHelper {
|
|||
* @return the texture rl
|
||||
*/
|
||||
@Contract("_ -> new")
|
||||
public static @NotNull ResourceLocation getTextureRL(@NotNull Plant plant) {
|
||||
public static @NotNull Identifier getTextureRL(@NotNull Plant plant) {
|
||||
return Lib39.mrl("block/" + plant.name);
|
||||
}
|
||||
|
||||
|
|
@ -279,7 +280,7 @@ public class PlantHelper {
|
|||
* @return the directly texture rl
|
||||
*/
|
||||
@Contract("_ -> new")
|
||||
public static @NotNull ResourceLocation getDirectlyTextureRL(@NotNull Plant plant) {
|
||||
public static @NotNull Identifier getDirectlyTextureRL(@NotNull Plant plant) {
|
||||
return Lib39.mrl("textures/block/" + plant.name + ".png");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
package top.r3944realms.lib39.util.resolve;
|
||||
|
||||
import net.minecraft.core.registries.Registries;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.resources.Identifier;
|
||||
import net.minecraft.tags.TagKey;
|
||||
import net.minecraft.world.entity.EntityType;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
|
@ -141,14 +141,14 @@ public abstract class EntityListResolve {
|
|||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
public boolean isEntityInList(EntityType<?> type) {
|
||||
String entityId = type.builtInRegistryHolder().key().location().toString();
|
||||
String entityId = type.builtInRegistryHolder().key().identifier().toString();
|
||||
String modId = entityId.split(":")[0];
|
||||
for (String rs : result.entityList) {
|
||||
if (rs.equals(entityId)) return true;
|
||||
}
|
||||
for(String rs : result.tagList) {
|
||||
String body = rs.substring(1);
|
||||
ResourceLocation tagId = Lib39.rl(body);
|
||||
Identifier tagId = Lib39.rl(body);
|
||||
TagKey<EntityType<?>> tag = TagKey.create(Registries.ENTITY_TYPE, tagId);
|
||||
if (type.builtInRegistryHolder().is(tag)) return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
package top.r3944realms.lib39.util.resolve;
|
||||
|
||||
import net.minecraft.core.registries.Registries;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.resources.Identifier;
|
||||
import net.minecraft.tags.TagKey;
|
||||
import net.minecraft.world.entity.EntityType;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
|
@ -153,7 +153,7 @@ public abstract class EntityMapResolve<T> {
|
|||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
private EntityMatchResult<T> findEntityMatch(EntityType<?> type) {
|
||||
String entityId = type.builtInRegistryHolder().key().location().toString();
|
||||
String entityId = type.builtInRegistryHolder().key().identifier().toString();
|
||||
String modId = entityId.split(":")[0];
|
||||
|
||||
// 检查实体ID匹配
|
||||
|
|
@ -166,7 +166,7 @@ public abstract class EntityMapResolve<T> {
|
|||
// 检查标签匹配
|
||||
for (String rs : result.tagMap.keySet()) {
|
||||
String body = rs.startsWith("#") ? rs.substring(1) : rs;
|
||||
ResourceLocation tagId = Lib39.rl(body);
|
||||
Identifier tagId = Lib39.rl(body);
|
||||
TagKey<EntityType<?>> tag = TagKey.create(Registries.ENTITY_TYPE, tagId);
|
||||
if (type.builtInRegistryHolder().is(tag)) {
|
||||
return new EntityMatchResult<>(EntityResolveResult.Type.TAG, rs, result.tagMap.get(rs));
|
||||
|
|
|
|||
|
|
@ -75,7 +75,7 @@ public class RidingApplier {
|
|||
if (RidingValidator.wouldCreateCycle(entity, vehicle)) {
|
||||
throw new RidingCycleException(entityId, vehicleId);
|
||||
}
|
||||
boolean success = entity.startRiding(vehicle, true);
|
||||
boolean success = entity.startRiding(vehicle, true, true);
|
||||
if (!success) {
|
||||
Lib39.LOGGER.error("Failed to mount entity {} to vehicle {}", entityId, vehicleId);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,15 +13,18 @@
|
|||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package top.r3944realms.lib39.util.nbt;
|
||||
package top.r3944realms.lib39.util.storage.nbt;
|
||||
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.nbt.ListTag;
|
||||
import net.minecraft.world.item.component.ResolvableProfile;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import org.jetbrains.annotations.Contract;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jspecify.annotations.NonNull;
|
||||
|
||||
import java.util.UUID;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
/**
|
||||
|
|
@ -45,24 +48,33 @@ public class NBTReader {
|
|||
public static NBTReader of(@NotNull CompoundTag nbt) {
|
||||
return new NBTReader(nbt);
|
||||
}
|
||||
|
||||
/**
|
||||
* String nbt reader.
|
||||
* 从CompoundTag创建读取器
|
||||
*
|
||||
* @param key the key
|
||||
* @param setter the setter
|
||||
* @param nbt the nbt opt
|
||||
* @return the nbt reader
|
||||
*/
|
||||
// 基本读取方法 - 直接赋值给成员变量
|
||||
public NBTReader string(String key, Consumer<String> setter) {
|
||||
if (nbt.contains(key)) {
|
||||
setter.accept(nbt.getString(key));
|
||||
@NotNull
|
||||
public static NBTReader ofOpt(@NotNull Optional<CompoundTag> nbt) {
|
||||
return new NBTReader(nbt.orElse(new CompoundTag()));
|
||||
}
|
||||
@Contract(pure = true)
|
||||
private static boolean checkOpt(@NonNull Optional<?> nbt) {
|
||||
return nbt.isPresent();
|
||||
}
|
||||
@Contract(pure = true)
|
||||
private static boolean checkOpt(Optional<?> @NonNull ... nbts) {
|
||||
for (Optional<?> nbt : nbts) {
|
||||
if (nbt.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return this;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* String nbt reader.
|
||||
* String nbt reader with default value.
|
||||
*
|
||||
* @param key the key
|
||||
* @param setter the setter
|
||||
|
|
@ -70,7 +82,14 @@ public class NBTReader {
|
|||
* @return the nbt reader
|
||||
*/
|
||||
public NBTReader string(String key, @NotNull Consumer<String> setter, String defaultValue) {
|
||||
setter.accept(nbt.contains(key) ? nbt.getString(key) : defaultValue);
|
||||
if (nbt.contains(key)) {
|
||||
Optional<String> value = nbt.getString(key);
|
||||
if (checkOpt(value)) {
|
||||
setter.accept(value.get());
|
||||
return this;
|
||||
}
|
||||
}
|
||||
setter.accept(defaultValue);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
|
@ -83,13 +102,14 @@ public class NBTReader {
|
|||
*/
|
||||
public NBTReader byteValue(String key, Consumer<Byte> setter) {
|
||||
if (nbt.contains(key)) {
|
||||
setter.accept(nbt.getByte(key));
|
||||
Optional<Byte> value = nbt.getByte(key);
|
||||
if (checkOpt(value)) setter.accept(value.get());
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Byte value nbt reader.
|
||||
* Byte value nbt reader with default value.
|
||||
*
|
||||
* @param key the key
|
||||
* @param setter the setter
|
||||
|
|
@ -97,7 +117,14 @@ public class NBTReader {
|
|||
* @return the nbt reader
|
||||
*/
|
||||
public NBTReader byteValue(String key, @NotNull Consumer<Byte> setter, byte defaultValue) {
|
||||
setter.accept(nbt.contains(key) ? nbt.getByte(key) : defaultValue);
|
||||
if (nbt.contains(key)) {
|
||||
Optional<Byte> value = nbt.getByte(key);
|
||||
if (checkOpt(value)) {
|
||||
setter.accept(value.get());
|
||||
return this;
|
||||
}
|
||||
}
|
||||
setter.accept(defaultValue);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
|
@ -110,13 +137,14 @@ public class NBTReader {
|
|||
*/
|
||||
public NBTReader shortValue(String key, Consumer<Short> setter) {
|
||||
if (nbt.contains(key)) {
|
||||
setter.accept(nbt.getShort(key));
|
||||
Optional<Short> value = nbt.getShort(key);
|
||||
if (checkOpt(value)) setter.accept(value.get());
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Short value nbt reader.
|
||||
* Short value nbt reader with default value.
|
||||
*
|
||||
* @param key the key
|
||||
* @param setter the setter
|
||||
|
|
@ -124,7 +152,14 @@ public class NBTReader {
|
|||
* @return the nbt reader
|
||||
*/
|
||||
public NBTReader shortValue(String key, @NotNull Consumer<Short> setter, short defaultValue) {
|
||||
setter.accept(nbt.contains(key) ? nbt.getShort(key) : defaultValue);
|
||||
if (nbt.contains(key)) {
|
||||
Optional<Short> value = nbt.getShort(key);
|
||||
if (checkOpt(value)) {
|
||||
setter.accept(value.get());
|
||||
return this;
|
||||
}
|
||||
}
|
||||
setter.accept(defaultValue);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
|
@ -137,13 +172,14 @@ public class NBTReader {
|
|||
*/
|
||||
public NBTReader intValue(String key, Consumer<Integer> setter) {
|
||||
if (nbt.contains(key)) {
|
||||
setter.accept(nbt.getInt(key));
|
||||
Optional<Integer> value = nbt.getInt(key);
|
||||
if (checkOpt(value)) setter.accept(value.get());
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Int value nbt reader.
|
||||
* Int value nbt reader with default value.
|
||||
*
|
||||
* @param key the key
|
||||
* @param setter the setter
|
||||
|
|
@ -151,7 +187,14 @@ public class NBTReader {
|
|||
* @return the nbt reader
|
||||
*/
|
||||
public NBTReader intValue(String key, @NotNull Consumer<Integer> setter, int defaultValue) {
|
||||
setter.accept(nbt.contains(key) ? nbt.getInt(key) : defaultValue);
|
||||
if (nbt.contains(key)) {
|
||||
Optional<Integer> value = nbt.getInt(key);
|
||||
if (checkOpt(value)) {
|
||||
setter.accept(value.get());
|
||||
return this;
|
||||
}
|
||||
}
|
||||
setter.accept(defaultValue);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
|
@ -164,13 +207,14 @@ public class NBTReader {
|
|||
*/
|
||||
public NBTReader longValue(String key, Consumer<Long> setter) {
|
||||
if (nbt.contains(key)) {
|
||||
setter.accept(nbt.getLong(key));
|
||||
Optional<Long> value = nbt.getLong(key);
|
||||
if (checkOpt(value)) setter.accept(value.get());
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Long value nbt reader.
|
||||
* Long value nbt reader with default value.
|
||||
*
|
||||
* @param key the key
|
||||
* @param setter the setter
|
||||
|
|
@ -178,7 +222,14 @@ public class NBTReader {
|
|||
* @return the nbt reader
|
||||
*/
|
||||
public NBTReader longValue(String key, @NotNull Consumer<Long> setter, long defaultValue) {
|
||||
setter.accept(nbt.contains(key) ? nbt.getLong(key) : defaultValue);
|
||||
if (nbt.contains(key)) {
|
||||
Optional<Long> value = nbt.getLong(key);
|
||||
if (checkOpt(value)) {
|
||||
setter.accept(value.get());
|
||||
return this;
|
||||
}
|
||||
}
|
||||
setter.accept(defaultValue);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
|
@ -191,13 +242,14 @@ public class NBTReader {
|
|||
*/
|
||||
public NBTReader floatValue(String key, Consumer<Float> setter) {
|
||||
if (nbt.contains(key)) {
|
||||
setter.accept(nbt.getFloat(key));
|
||||
Optional<Float> value = nbt.getFloat(key);
|
||||
if (checkOpt(value)) setter.accept(value.get());
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Float value nbt reader.
|
||||
* Float value nbt reader with default value.
|
||||
*
|
||||
* @param key the key
|
||||
* @param setter the setter
|
||||
|
|
@ -205,7 +257,14 @@ public class NBTReader {
|
|||
* @return the nbt reader
|
||||
*/
|
||||
public NBTReader floatValue(String key, @NotNull Consumer<Float> setter, float defaultValue) {
|
||||
setter.accept(nbt.contains(key) ? nbt.getFloat(key) : defaultValue);
|
||||
if (nbt.contains(key)) {
|
||||
Optional<Float> value = nbt.getFloat(key);
|
||||
if (checkOpt(value)) {
|
||||
setter.accept(value.get());
|
||||
return this;
|
||||
}
|
||||
}
|
||||
setter.accept(defaultValue);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
|
@ -218,13 +277,14 @@ public class NBTReader {
|
|||
*/
|
||||
public NBTReader doubleValue(String key, Consumer<Double> setter) {
|
||||
if (nbt.contains(key)) {
|
||||
setter.accept(nbt.getDouble(key));
|
||||
Optional<Double> value = nbt.getDouble(key);
|
||||
if (checkOpt(value)) setter.accept(value.get());
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Double value nbt reader.
|
||||
* Double value nbt reader with default value.
|
||||
*
|
||||
* @param key the key
|
||||
* @param setter the setter
|
||||
|
|
@ -232,7 +292,14 @@ public class NBTReader {
|
|||
* @return the nbt reader
|
||||
*/
|
||||
public NBTReader doubleValue(String key, @NotNull Consumer<Double> setter, double defaultValue) {
|
||||
setter.accept(nbt.contains(key) ? nbt.getDouble(key) : defaultValue);
|
||||
if (nbt.contains(key)) {
|
||||
Optional<Double> value = nbt.getDouble(key);
|
||||
if (checkOpt(value)) {
|
||||
setter.accept(value.get());
|
||||
return this;
|
||||
}
|
||||
}
|
||||
setter.accept(defaultValue);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
|
@ -245,13 +312,14 @@ public class NBTReader {
|
|||
*/
|
||||
public NBTReader booleanValue(String key, Consumer<Boolean> setter) {
|
||||
if (nbt.contains(key)) {
|
||||
setter.accept(nbt.getBoolean(key));
|
||||
Optional<Boolean> value = nbt.getBoolean(key);
|
||||
if (checkOpt(value)) setter.accept(value.get());
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Boolean value nbt reader.
|
||||
* Boolean value nbt reader with default value.
|
||||
*
|
||||
* @param key the key
|
||||
* @param setter the setter
|
||||
|
|
@ -259,7 +327,14 @@ public class NBTReader {
|
|||
* @return the nbt reader
|
||||
*/
|
||||
public NBTReader booleanValue(String key, @NotNull Consumer<Boolean> setter, boolean defaultValue) {
|
||||
setter.accept(nbt.contains(key) ? nbt.getBoolean(key) : defaultValue);
|
||||
if (nbt.contains(key)) {
|
||||
Optional<Boolean> value = nbt.getBoolean(key);
|
||||
if (checkOpt(value)) {
|
||||
setter.accept(value.get());
|
||||
return this;
|
||||
}
|
||||
}
|
||||
setter.accept(defaultValue);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
|
@ -270,10 +345,10 @@ public class NBTReader {
|
|||
* @param setter the setter
|
||||
* @return the nbt reader
|
||||
*/
|
||||
// 数组类型
|
||||
public NBTReader byteArray(String key, Consumer<byte[]> setter) {
|
||||
if (nbt.contains(key)) {
|
||||
setter.accept(nbt.getByteArray(key));
|
||||
Optional<byte[]> value = nbt.getByteArray(key);
|
||||
if (checkOpt(value)) setter.accept(value.get());
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
|
@ -287,7 +362,8 @@ public class NBTReader {
|
|||
*/
|
||||
public NBTReader intArray(String key, Consumer<int[]> setter) {
|
||||
if (nbt.contains(key)) {
|
||||
setter.accept(nbt.getIntArray(key));
|
||||
Optional<int[]> value = nbt.getIntArray(key);
|
||||
if (checkOpt(value)) setter.accept(value.get());
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
|
@ -301,39 +377,12 @@ public class NBTReader {
|
|||
*/
|
||||
public NBTReader longArray(String key, Consumer<long[]> setter) {
|
||||
if (nbt.contains(key)) {
|
||||
setter.accept(nbt.getLongArray(key));
|
||||
Optional<long[]> value = nbt.getLongArray(key);
|
||||
if (checkOpt(value)) setter.accept(value.get());
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Uuid nbt reader.
|
||||
*
|
||||
* @param key the key
|
||||
* @param setter the setter
|
||||
* @return the nbt reader
|
||||
*/
|
||||
// UUID
|
||||
public NBTReader uuid(String key, Consumer<UUID> setter) {
|
||||
if (nbt.hasUUID(key)) {
|
||||
setter.accept(nbt.getUUID(key));
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Uuid nbt reader.
|
||||
*
|
||||
* @param key the key
|
||||
* @param setter the setter
|
||||
* @param defaultValue the default value
|
||||
* @return the nbt reader
|
||||
*/
|
||||
public NBTReader uuid(String key, @NotNull Consumer<UUID> setter, UUID defaultValue) {
|
||||
setter.accept(nbt.hasUUID(key) ? nbt.getUUID(key) : defaultValue);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compound nbt reader.
|
||||
*
|
||||
|
|
@ -341,16 +390,16 @@ public class NBTReader {
|
|||
* @param setter the setter
|
||||
* @return the nbt reader
|
||||
*/
|
||||
// CompoundTag
|
||||
public NBTReader compound(String key, Consumer<CompoundTag> setter) {
|
||||
if (nbt.contains(key)) {
|
||||
setter.accept(nbt.getCompound(key));
|
||||
Optional<CompoundTag> value = nbt.getCompound(key);
|
||||
if (checkOpt(value)) setter.accept(value.get());
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compound nbt reader.
|
||||
* Compound nbt reader with default value.
|
||||
*
|
||||
* @param key the key
|
||||
* @param setter the setter
|
||||
|
|
@ -358,7 +407,14 @@ public class NBTReader {
|
|||
* @return the nbt reader
|
||||
*/
|
||||
public NBTReader compound(String key, @NotNull Consumer<CompoundTag> setter, CompoundTag defaultValue) {
|
||||
setter.accept(nbt.contains(key) ? nbt.getCompound(key) : defaultValue);
|
||||
if (nbt.contains(key)) {
|
||||
Optional<CompoundTag> value = nbt.getCompound(key);
|
||||
if (checkOpt(value)) {
|
||||
setter.accept(value.get());
|
||||
return this;
|
||||
}
|
||||
}
|
||||
setter.accept(defaultValue);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
|
@ -366,18 +422,45 @@ public class NBTReader {
|
|||
* List nbt reader.
|
||||
*
|
||||
* @param key the key
|
||||
* @param type the type
|
||||
* @param setter the setter
|
||||
* @return the nbt reader
|
||||
*/
|
||||
// ListTag
|
||||
public NBTReader list(String key, int type, Consumer<ListTag> setter) {
|
||||
public NBTReader list(String key, Consumer<ListTag> setter) {
|
||||
if (nbt.contains(key)) {
|
||||
setter.accept(nbt.getList(key, type));
|
||||
Optional<ListTag> value = nbt.getList(key);
|
||||
if (checkOpt(value)) setter.accept(value.get());
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public NBTReader gameProfile(String key, Consumer<ResolvableProfile> setter) {
|
||||
Optional<ResolvableProfile> read = nbt.read(key, ResolvableProfile.CODEC);
|
||||
if (read.isPresent()) {
|
||||
try {
|
||||
ResolvableProfile profile = read.get();
|
||||
setter.accept(profile);
|
||||
return this;
|
||||
} catch (IllegalArgumentException ignored) {
|
||||
|
||||
}
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public NBTReader gameProfile(String key, Consumer<ResolvableProfile> setter, ResolvableProfile defaultValue) {
|
||||
Optional<ResolvableProfile> read = nbt.read(key, ResolvableProfile.CODEC);
|
||||
if (read.isPresent()) {
|
||||
try {
|
||||
ResolvableProfile profile = read.get();
|
||||
setter.accept(profile);
|
||||
return this;
|
||||
} catch (IllegalArgumentException ignored) {
|
||||
|
||||
}
|
||||
}
|
||||
setter.accept(defaultValue);
|
||||
return this;
|
||||
}
|
||||
/**
|
||||
* Vec 3 nbt reader.
|
||||
*
|
||||
|
|
@ -385,23 +468,31 @@ public class NBTReader {
|
|||
* @param setter the setter
|
||||
* @return the nbt reader
|
||||
*/
|
||||
// Vec3支持
|
||||
public NBTReader vec3(String key, Consumer<Vec3> setter) {
|
||||
if (nbt.contains(key)) {
|
||||
CompoundTag vecTag = nbt.getCompound(key);
|
||||
if (vecTag.contains("X") && vecTag.contains("Y") && vecTag.contains("Z")) {
|
||||
setter.accept(new Vec3(
|
||||
vecTag.getDouble("X"),
|
||||
vecTag.getDouble("Y"),
|
||||
vecTag.getDouble("Z")
|
||||
));
|
||||
Optional<CompoundTag> vecTag = nbt.getCompound(key);
|
||||
if (checkOpt(vecTag)) {
|
||||
CompoundTag vec = vecTag.get();
|
||||
if (vec.contains("X") && vec.contains("Y") && vec.contains("Z")) {
|
||||
Optional<Double> x = vec.getDouble("X");
|
||||
Optional<Double> y = vec.getDouble("Y");
|
||||
Optional<Double> z = vec.getDouble("Z");
|
||||
if (checkOpt(x, y, z)) {
|
||||
Vec3 value = new Vec3(
|
||||
x.get(),
|
||||
y.get(),
|
||||
z.get()
|
||||
);
|
||||
setter.accept(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Vec 3 nbt reader.
|
||||
* Vec 3 nbt reader with default value.
|
||||
*
|
||||
* @param key the key
|
||||
* @param setter the setter
|
||||
|
|
@ -410,14 +501,23 @@ public class NBTReader {
|
|||
*/
|
||||
public NBTReader vec3(String key, Consumer<Vec3> setter, Vec3 defaultValue) {
|
||||
if (nbt.contains(key)) {
|
||||
CompoundTag vecTag = nbt.getCompound(key);
|
||||
if (vecTag.contains("X") && vecTag.contains("Y") && vecTag.contains("Z")) {
|
||||
setter.accept(new Vec3(
|
||||
vecTag.getDouble("X"),
|
||||
vecTag.getDouble("Y"),
|
||||
vecTag.getDouble("Z")
|
||||
));
|
||||
return this;
|
||||
Optional<CompoundTag> vecTag = nbt.getCompound(key);
|
||||
if (checkOpt(vecTag)) {
|
||||
CompoundTag vec = vecTag.get();
|
||||
if (vec.contains("X") && vec.contains("Y") && vec.contains("Z")) {
|
||||
Optional<Double> x = vec.getDouble("X");
|
||||
Optional<Double> y = vec.getDouble("Y");
|
||||
Optional<Double> z = vec.getDouble("Z");
|
||||
if (checkOpt(x, y, z)) {
|
||||
Vec3 value = new Vec3(
|
||||
x.get(),
|
||||
y.get(),
|
||||
z.get()
|
||||
);
|
||||
setter.accept(value);
|
||||
return this;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
setter.accept(defaultValue);
|
||||
|
|
@ -433,21 +533,24 @@ public class NBTReader {
|
|||
* @param setter the setter
|
||||
* @return the nbt reader
|
||||
*/
|
||||
// 枚举支持
|
||||
public <T extends Enum<T>> NBTReader enumValue(String key, Class<T> enumClass, Consumer<T> setter) {
|
||||
if (nbt.contains(key)) {
|
||||
String value = nbt.getString(key);
|
||||
try {
|
||||
setter.accept(Enum.valueOf(enumClass, value.toUpperCase()));
|
||||
} catch (IllegalArgumentException ignored) {
|
||||
// 保持setter的当前值
|
||||
Optional<String> value = nbt.getString(key);
|
||||
if(checkOpt(value)) {
|
||||
try {
|
||||
T enumValue = Enum.valueOf(enumClass, value.get().toUpperCase());
|
||||
setter.accept(enumValue);
|
||||
} catch (IllegalArgumentException ignored) {
|
||||
// 保持setter的当前值
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enum value nbt reader.
|
||||
* Enum value nbt reader with default value.
|
||||
*
|
||||
* @param <T> the type parameter
|
||||
* @param key the key
|
||||
|
|
@ -458,11 +561,15 @@ public class NBTReader {
|
|||
*/
|
||||
public <T extends Enum<T>> NBTReader enumValue(String key, Class<T> enumClass, Consumer<T> setter, T defaultValue) {
|
||||
if (nbt.contains(key)) {
|
||||
String value = nbt.getString(key);
|
||||
try {
|
||||
setter.accept(Enum.valueOf(enumClass, value.toUpperCase()));
|
||||
return this;
|
||||
} catch (IllegalArgumentException ignored) {
|
||||
Optional<String> value = nbt.getString(key);
|
||||
if (checkOpt(value)) {
|
||||
try {
|
||||
T enumValue = Enum.valueOf(enumClass, value.get().toUpperCase());
|
||||
setter.accept(enumValue);
|
||||
return this;
|
||||
} catch (IllegalArgumentException ignored) {
|
||||
// 保持setter的当前值
|
||||
}
|
||||
}
|
||||
}
|
||||
setter.accept(defaultValue);
|
||||
|
|
@ -476,16 +583,18 @@ public class NBTReader {
|
|||
* @param consumer the consumer
|
||||
* @return the nbt reader
|
||||
*/
|
||||
// 嵌套读取支持
|
||||
public NBTReader nested(String key, Consumer<NBTReader> consumer) {
|
||||
if (nbt.contains(key)) {
|
||||
consumer.accept(new NBTReader(nbt.getCompound(key)));
|
||||
Optional<CompoundTag> compound = nbt.getCompound(key);
|
||||
if (checkOpt(compound)) {
|
||||
consumer.accept(new NBTReader(compound.get()));
|
||||
}
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Nested nbt reader.
|
||||
* Nested nbt reader with orElse.
|
||||
*
|
||||
* @param key the key
|
||||
* @param consumer the consumer
|
||||
|
|
@ -494,7 +603,10 @@ public class NBTReader {
|
|||
*/
|
||||
public NBTReader nested(String key, Consumer<NBTReader> consumer, Runnable orElse) {
|
||||
if (nbt.contains(key)) {
|
||||
consumer.accept(new NBTReader(nbt.getCompound(key)));
|
||||
Optional<CompoundTag> compound = nbt.getCompound(key);
|
||||
if (checkOpt(compound)) {
|
||||
consumer.accept(new NBTReader(compound.get()));
|
||||
}
|
||||
} else {
|
||||
orElse.run();
|
||||
}
|
||||
|
|
@ -508,7 +620,6 @@ public class NBTReader {
|
|||
* @param action the action
|
||||
* @return the nbt reader
|
||||
*/
|
||||
// 条件读取
|
||||
public NBTReader ifPresent(String key, Runnable action) {
|
||||
if (nbt.contains(key)) {
|
||||
action.run();
|
||||
|
|
@ -535,7 +646,6 @@ public class NBTReader {
|
|||
*
|
||||
* @return the raw
|
||||
*/
|
||||
// 获取原始NBT
|
||||
@NotNull
|
||||
public CompoundTag getRaw() {
|
||||
return nbt;
|
||||
|
|
@ -547,14 +657,20 @@ public class NBTReader {
|
|||
* @param nbt the nbt
|
||||
* @return the vec 3
|
||||
*/
|
||||
// 便捷的静态方法(保持原有功能)
|
||||
@NotNull
|
||||
public static Vec3 readVec3(@NotNull CompoundTag nbt) {
|
||||
if (nbt.contains("X") && nbt.contains("Y") && nbt.contains("Z")) {
|
||||
return new Vec3(
|
||||
nbt.getDouble("X"),
|
||||
nbt.getDouble("Y"),
|
||||
nbt.getDouble("Z")
|
||||
Optional<Double> x = nbt.getDouble("X");
|
||||
Optional<Double> y = nbt.getDouble("Y");
|
||||
Optional<Double> z = nbt.getDouble("Z");
|
||||
if (checkOpt(x, y, z)) {
|
||||
return new Vec3(
|
||||
x.get(),
|
||||
y.get(),
|
||||
z.get()
|
||||
);
|
||||
} else throw new IllegalArgumentException(
|
||||
"XYZ is null."
|
||||
);
|
||||
} else {
|
||||
throw new IllegalArgumentException("NBT is missing X, Y, or Z value for Vec3");
|
||||
|
|
@ -570,11 +686,16 @@ public class NBTReader {
|
|||
@Nullable
|
||||
public static Vec3 readVec3Safe(@NotNull CompoundTag nbt) {
|
||||
if (nbt.contains("X") && nbt.contains("Y") && nbt.contains("Z")) {
|
||||
return new Vec3(
|
||||
nbt.getDouble("X"),
|
||||
nbt.getDouble("Y"),
|
||||
nbt.getDouble("Z")
|
||||
);
|
||||
Optional<Double> x = nbt.getDouble("X");
|
||||
Optional<Double> y = nbt.getDouble("Y");
|
||||
Optional<Double> z = nbt.getDouble("Z");
|
||||
if (checkOpt(x, y, z)) {
|
||||
return new Vec3(
|
||||
x.get(),
|
||||
y.get(),
|
||||
z.get()
|
||||
);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
|
@ -1,12 +1,14 @@
|
|||
package top.r3944realms.lib39.util.nbt;
|
||||
package top.r3944realms.lib39.util.storage.nbt;
|
||||
|
||||
import net.minecraft.nbt.*;
|
||||
import net.minecraft.world.item.component.ResolvableProfile;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import org.jetbrains.annotations.Contract;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jspecify.annotations.NonNull;
|
||||
|
||||
import java.util.UUID;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
|
|
@ -161,6 +163,17 @@ public class NBTWriter {
|
|||
}
|
||||
return this;
|
||||
}
|
||||
public NBTWriter gameProfile(String key, ResolvableProfile profile) {
|
||||
root.store(key, ResolvableProfile.CODEC, profile);
|
||||
return this;
|
||||
}
|
||||
|
||||
public NBTWriter gameProfile(String key, @NonNull Optional<ResolvableProfile> profile) {
|
||||
if (profile.isPresent()) {
|
||||
root.store(key, ResolvableProfile.CODEC, profile.get());
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
|
|
@ -394,47 +407,15 @@ public class NBTWriter {
|
|||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Uuid nbt writer.
|
||||
*
|
||||
* @param key the key
|
||||
* @param value the value
|
||||
* @return the nbt writer
|
||||
*/
|
||||
// UUID支持
|
||||
public NBTWriter uuid(String key, UUID value) {
|
||||
if (value != null) {
|
||||
root.putUUID(key, value);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Uuid nbt writer.
|
||||
*
|
||||
* @param key the key
|
||||
* @param value the value
|
||||
* @param defaultValue the default value
|
||||
* @return the nbt writer
|
||||
*/
|
||||
public NBTWriter uuid(String key, UUID value, UUID defaultValue) {
|
||||
if (value != null) {
|
||||
root.putUUID(key, value);
|
||||
} else if (defaultValue != null) {
|
||||
root.putUUID(key, defaultValue);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compound nbt writer.
|
||||
* 嵌套CompoundTag
|
||||
*
|
||||
* @param key the key
|
||||
* @param consumer the consumer
|
||||
* @return the nbt writer
|
||||
*/
|
||||
// 嵌套CompoundTag
|
||||
|
||||
public NBTWriter compound(String key, Consumer<NBTWriter> consumer) {
|
||||
if (consumer != null) {
|
||||
NBTWriter nestedBuilder = new NBTWriter();
|
||||
|
|
@ -493,12 +474,12 @@ public class NBTWriter {
|
|||
|
||||
/**
|
||||
* List nbt writer.
|
||||
* ListTag支持
|
||||
*
|
||||
* @param key the key
|
||||
* @param consumer the consumer
|
||||
* @return the nbt writer
|
||||
*/
|
||||
// ListTag支持
|
||||
public NBTWriter list(String key, Consumer<ListNBTBuilder> consumer) {
|
||||
if (consumer != null) {
|
||||
ListNBTBuilder listBuilder = new ListNBTBuilder();
|
||||
|
|
@ -562,7 +543,6 @@ public class NBTWriter {
|
|||
* @param tag the tag
|
||||
* @return the nbt writer
|
||||
*/
|
||||
// 直接操作Tag
|
||||
public NBTWriter tag(String key, Tag tag) {
|
||||
if (tag != null) {
|
||||
root.put(key, tag);
|
||||
|
|
@ -578,7 +558,6 @@ public class NBTWriter {
|
|||
* @param value the value
|
||||
* @return the nbt writer
|
||||
*/
|
||||
// 条件添加方法
|
||||
public NBTWriter stringIf(String key, boolean condition, Supplier<String> value) {
|
||||
if (condition && value != null) {
|
||||
root.putString(key, value.get());
|
||||
|
|
@ -616,21 +595,6 @@ public class NBTWriter {
|
|||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Uuid value if nbt writer.
|
||||
*
|
||||
* @param key the key
|
||||
* @param condition the condition
|
||||
* @param value the value
|
||||
* @return the nbt writer
|
||||
*/
|
||||
public NBTWriter uuidValueIf(String key, boolean condition, Supplier<UUID> value) {
|
||||
if (condition && value != null) {
|
||||
root.putUUID(key, value.get());
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Boolean value if nbt writer.
|
||||
*
|
||||
|
|
@ -1107,7 +1071,7 @@ public class NBTWriter {
|
|||
* @return the all keys
|
||||
*/
|
||||
public java.util.Set<String> getAllKeys() {
|
||||
return root.getAllKeys();
|
||||
return root.keySet();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -0,0 +1,557 @@
|
|||
package top.r3944realms.lib39.util.storage.vauleio;
|
||||
|
||||
|
||||
import com.mojang.serialization.Codec;
|
||||
import net.minecraft.world.item.component.ResolvableProfile;
|
||||
import net.minecraft.world.level.storage.ValueInput;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
/**
|
||||
* ValueInput Helper类
|
||||
* 提供链式操作和类型安全的ValueInput数据读取
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public class ValueInputWriter {
|
||||
private final ValueInput valueInput;
|
||||
|
||||
private ValueInputWriter(ValueInput valueInput) {
|
||||
this.valueInput = valueInput;
|
||||
}
|
||||
|
||||
/**
|
||||
* 从ValueInput创建读取器
|
||||
*
|
||||
* @param valueInput the value input
|
||||
* @return the value input reader
|
||||
*/
|
||||
@NotNull
|
||||
public static ValueInputWriter of(@NotNull ValueInput valueInput) {
|
||||
return new ValueInputWriter(valueInput);
|
||||
}
|
||||
|
||||
/**
|
||||
* String value input reader.
|
||||
*
|
||||
* @param key the key
|
||||
* @param setter the setter
|
||||
* @return the value input reader
|
||||
*/
|
||||
public ValueInputWriter string(String key, Consumer<String> setter) {
|
||||
valueInput.getString(key).ifPresent(setter);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* String value input reader.
|
||||
*
|
||||
* @param key the key
|
||||
* @param setter the setter
|
||||
* @param defaultValue the default value
|
||||
* @return the value input reader
|
||||
*/
|
||||
public ValueInputWriter string(String key, @NotNull Consumer<String> setter, String defaultValue) {
|
||||
setter.accept(valueInput.getStringOr(key, defaultValue));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Boolean value value input reader.
|
||||
*
|
||||
* @param key the key
|
||||
* @param setter the setter
|
||||
* @return the value input reader
|
||||
*/
|
||||
public ValueInputWriter booleanValue(String key, Consumer<Boolean> setter) {
|
||||
valueInput.read(key, Codec.BOOL).ifPresent(setter);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Boolean value value input reader.
|
||||
*
|
||||
* @param key the key
|
||||
* @param setter the setter
|
||||
* @param defaultValue the default value
|
||||
* @return the value input reader
|
||||
*/
|
||||
public ValueInputWriter booleanValue(String key, @NotNull Consumer<Boolean> setter, boolean defaultValue) {
|
||||
setter.accept(valueInput.getBooleanOr(key, defaultValue));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Byte value value input reader.
|
||||
*
|
||||
* @param key the key
|
||||
* @param setter the setter
|
||||
* @return the value input reader
|
||||
*/
|
||||
public ValueInputWriter byteValue(String key, Consumer<Byte> setter) {
|
||||
valueInput.read(key, Codec.BYTE).ifPresent(setter);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Byte value value input reader.
|
||||
*
|
||||
* @param key the key
|
||||
* @param setter the setter
|
||||
* @param defaultValue the default value
|
||||
* @return the value input reader
|
||||
*/
|
||||
public ValueInputWriter byteValue(String key, @NotNull Consumer<Byte> setter, byte defaultValue) {
|
||||
setter.accept(valueInput.getByteOr(key, defaultValue));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Short value value input reader.
|
||||
*
|
||||
* @param key the key
|
||||
* @param setter the setter
|
||||
* @return the value input reader
|
||||
*/
|
||||
public ValueInputWriter shortValue(String key, Consumer<Short> setter) {
|
||||
valueInput.read(key, Codec.SHORT).ifPresent(setter);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Short value value input reader.
|
||||
*
|
||||
* @param key the key
|
||||
* @param setter the setter
|
||||
* @param defaultValue the default value
|
||||
* @return the value input reader
|
||||
*/
|
||||
public ValueInputWriter shortValue(String key, @NotNull Consumer<Short> setter, short defaultValue) {
|
||||
setter.accept((short) valueInput.getShortOr(key, defaultValue));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Int value value input reader.
|
||||
*
|
||||
* @param key the key
|
||||
* @param setter the setter
|
||||
* @return the value input reader
|
||||
*/
|
||||
public ValueInputWriter intValue(String key, Consumer<Integer> setter) {
|
||||
valueInput.getInt(key).ifPresent(setter);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Int value value input reader.
|
||||
*
|
||||
* @param key the key
|
||||
* @param setter the setter
|
||||
* @param defaultValue the default value
|
||||
* @return the value input reader
|
||||
*/
|
||||
public ValueInputWriter intValue(String key, @NotNull Consumer<Integer> setter, int defaultValue) {
|
||||
setter.accept(valueInput.getIntOr(key, defaultValue));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Long value value input reader.
|
||||
*
|
||||
* @param key the key
|
||||
* @param setter the setter
|
||||
* @return the value input reader
|
||||
*/
|
||||
public ValueInputWriter longValue(String key, Consumer<Long> setter) {
|
||||
valueInput.getLong(key).ifPresent(setter);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Long value value input reader.
|
||||
*
|
||||
* @param key the key
|
||||
* @param setter the setter
|
||||
* @param defaultValue the default value
|
||||
* @return the value input reader
|
||||
*/
|
||||
public ValueInputWriter longValue(String key, @NotNull Consumer<Long> setter, long defaultValue) {
|
||||
setter.accept(valueInput.getLongOr(key, defaultValue));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Float value value input reader.
|
||||
*
|
||||
* @param key the key
|
||||
* @param setter the setter
|
||||
* @return the value input reader
|
||||
*/
|
||||
public ValueInputWriter floatValue(String key, Consumer<Float> setter) {
|
||||
valueInput.read(key, Codec.FLOAT).ifPresent(setter);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Float value value input reader.
|
||||
*
|
||||
* @param key the key
|
||||
* @param setter the setter
|
||||
* @param defaultValue the default value
|
||||
* @return the value input reader
|
||||
*/
|
||||
public ValueInputWriter floatValue(String key, @NotNull Consumer<Float> setter, float defaultValue) {
|
||||
setter.accept(valueInput.getFloatOr(key, defaultValue));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Double value value input reader.
|
||||
*
|
||||
* @param key the key
|
||||
* @param setter the setter
|
||||
* @return the value input reader
|
||||
*/
|
||||
public ValueInputWriter doubleValue(String key, Consumer<Double> setter) {
|
||||
valueInput.read(key, Codec.DOUBLE).ifPresent(setter);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Double value value input reader.
|
||||
*
|
||||
* @param key the key
|
||||
* @param setter the setter
|
||||
* @param defaultValue the default value
|
||||
* @return the value input reader
|
||||
*/
|
||||
public ValueInputWriter doubleValue(String key, @NotNull Consumer<Double> setter, double defaultValue) {
|
||||
setter.accept(valueInput.getDoubleOr(key, defaultValue));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Int array value input reader.
|
||||
*
|
||||
* @param key the key
|
||||
* @param setter the setter
|
||||
* @return the value input reader
|
||||
*/
|
||||
public ValueInputWriter intArray(String key, Consumer<int[]> setter) {
|
||||
valueInput.getIntArray(key).ifPresent(setter);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Int array value input reader.
|
||||
*
|
||||
* @param key the key
|
||||
* @param setter the setter
|
||||
* @param defaultValue the default value
|
||||
* @return the value input reader
|
||||
*/
|
||||
public ValueInputWriter intArray(String key, @NotNull Consumer<int[]> setter, int[] defaultValue) {
|
||||
setter.accept(valueInput.getIntArray(key).orElse(defaultValue));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Codec value value input reader.
|
||||
*
|
||||
* @param <T> the type parameter
|
||||
* @param key the key
|
||||
* @param codec the codec
|
||||
* @param setter the setter
|
||||
* @return the value input reader
|
||||
*/
|
||||
public <T> ValueInputWriter codecValue(String key, Codec<T> codec, Consumer<T> setter) {
|
||||
valueInput.read(key, codec).ifPresent(setter);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Codec value value input reader.
|
||||
*
|
||||
* @param <T> the type parameter
|
||||
* @param key the key
|
||||
* @param codec the codec
|
||||
* @param setter the setter
|
||||
* @param defaultValue the default value
|
||||
* @return the value input reader
|
||||
*/
|
||||
public <T> ValueInputWriter codecValue(String key, Codec<T> codec, @NotNull Consumer<T> setter, T defaultValue) {
|
||||
setter.accept(valueInput.read(key, codec).orElse(defaultValue));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Vec 3 value input reader.
|
||||
*
|
||||
* @param key the key
|
||||
* @param setter the setter
|
||||
* @return the value input reader
|
||||
*/
|
||||
public ValueInputWriter vec3(String key, Consumer<Vec3> setter) {
|
||||
valueInput.child(key).ifPresent(child -> {
|
||||
try {
|
||||
Vec3 vec = readVec3(child);
|
||||
setter.accept(vec);
|
||||
} catch (IllegalArgumentException ignored) {
|
||||
// 忽略解析错误
|
||||
}
|
||||
});
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Vec 3 value input reader.
|
||||
*
|
||||
* @param key the key
|
||||
* @param setter the setter
|
||||
* @param defaultValue the default value
|
||||
* @return the value input reader
|
||||
*/
|
||||
public ValueInputWriter vec3(String key, Consumer<Vec3> setter, Vec3 defaultValue) {
|
||||
Optional<ValueInput> child = valueInput.child(key);
|
||||
if (child.isPresent()) {
|
||||
try {
|
||||
Vec3 vec = readVec3(child.get());
|
||||
setter.accept(vec);
|
||||
return this;
|
||||
} catch (IllegalArgumentException ignored) {
|
||||
// 忽略解析错误,使用默认值
|
||||
}
|
||||
}
|
||||
setter.accept(defaultValue);
|
||||
return this;
|
||||
}
|
||||
|
||||
public ValueInputWriter gameProfile(String key, Consumer<ResolvableProfile> setter) {
|
||||
Optional<ResolvableProfile> read = valueInput.read(key, ResolvableProfile.CODEC);
|
||||
if (read.isPresent()) {
|
||||
try {
|
||||
ResolvableProfile profile = read.get();
|
||||
setter.accept(profile);
|
||||
return this;
|
||||
} catch (IllegalArgumentException ignored) {
|
||||
|
||||
}
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public ValueInputWriter gameProfile(String key, Consumer<ResolvableProfile> setter, ResolvableProfile defaultValue) {
|
||||
Optional<ResolvableProfile> read = valueInput.read(key, ResolvableProfile.CODEC);
|
||||
if (read.isPresent()) {
|
||||
try {
|
||||
ResolvableProfile profile = read.get();
|
||||
setter.accept(profile);
|
||||
return this;
|
||||
} catch (IllegalArgumentException ignored) {
|
||||
|
||||
}
|
||||
}
|
||||
setter.accept(defaultValue);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enum value value input reader.
|
||||
*
|
||||
* @param <T> the type parameter
|
||||
* @param key the key
|
||||
* @param enumClass the enum class
|
||||
* @param setter the setter
|
||||
* @return the value input reader
|
||||
*/
|
||||
public <T extends Enum<T>> ValueInputWriter enumValue(String key, Class<T> enumClass, Consumer<T> setter) {
|
||||
valueInput.getString(key).ifPresent(value -> {
|
||||
try {
|
||||
setter.accept(Enum.valueOf(enumClass, value.toUpperCase()));
|
||||
} catch (IllegalArgumentException ignored) {
|
||||
// 忽略枚举解析错误
|
||||
}
|
||||
});
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enum value value input reader.
|
||||
*
|
||||
* @param <T> the type parameter
|
||||
* @param key the key
|
||||
* @param enumClass the enum class
|
||||
* @param setter the setter
|
||||
* @param defaultValue the default value
|
||||
* @return the value input reader
|
||||
*/
|
||||
public <T extends Enum<T>> ValueInputWriter enumValue(String key, Class<T> enumClass, Consumer<T> setter, T defaultValue) {
|
||||
Optional<String> value = valueInput.getString(key);
|
||||
if (value.isPresent()) {
|
||||
try {
|
||||
setter.accept(Enum.valueOf(enumClass, value.get().toUpperCase()));
|
||||
return this;
|
||||
} catch (IllegalArgumentException ignored) {
|
||||
// 忽略枚举解析错误
|
||||
}
|
||||
}
|
||||
setter.accept(defaultValue);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Nested value input reader.
|
||||
*
|
||||
* @param key the key
|
||||
* @param consumer the consumer
|
||||
* @return the value input reader
|
||||
*/
|
||||
public ValueInputWriter nested(String key, Consumer<ValueInputWriter> consumer) {
|
||||
valueInput.child(key).ifPresent(child -> consumer.accept(new ValueInputWriter(child)));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Nested value input reader.
|
||||
*
|
||||
* @param key the key
|
||||
* @param consumer the consumer
|
||||
* @param orElse the or else
|
||||
* @return the value input reader
|
||||
*/
|
||||
public ValueInputWriter nested(String key, Consumer<ValueInputWriter> consumer, Runnable orElse) {
|
||||
Optional<ValueInput> child = valueInput.child(key);
|
||||
if (child.isPresent()) {
|
||||
consumer.accept(new ValueInputWriter(child.get()));
|
||||
} else {
|
||||
orElse.run();
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* List value input reader.
|
||||
*
|
||||
* @param <T> the type parameter
|
||||
* @param key the key
|
||||
* @param codec the codec
|
||||
* @param consumer the consumer
|
||||
* @return the value input reader
|
||||
*/
|
||||
public <T> ValueInputWriter list(String key, Codec<T> codec, Consumer<java.util.stream.Stream<T>> consumer) {
|
||||
valueInput.list(key, codec).ifPresent(list -> {
|
||||
if (!list.isEmpty()) {
|
||||
consumer.accept(list.stream());
|
||||
}
|
||||
});
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* List value input reader.
|
||||
*
|
||||
* @param <T> the type parameter
|
||||
* @param key the key
|
||||
* @param codec the codec
|
||||
* @param consumer the consumer
|
||||
* @param defaultValue the default value
|
||||
* @return the value input reader
|
||||
*/
|
||||
public <T> ValueInputWriter list(String key, Codec<T> codec, @NotNull Consumer<java.util.stream.Stream<T>> consumer, java.util.stream.Stream<T> defaultValue) {
|
||||
Optional<ValueInput.TypedInputList<T>> list = valueInput.list(key, codec);
|
||||
if (list.isPresent() && !list.get().isEmpty()) {
|
||||
consumer.accept(list.get().stream());
|
||||
} else {
|
||||
consumer.accept(defaultValue);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Children list value input reader.
|
||||
*
|
||||
* @param key the key
|
||||
* @param consumer the consumer
|
||||
* @return the value input reader
|
||||
*/
|
||||
public ValueInputWriter childrenList(String key, Consumer<java.util.stream.Stream<ValueInputWriter>> consumer) {
|
||||
valueInput.childrenList(key).ifPresent(list -> {
|
||||
if (!list.isEmpty()) {
|
||||
consumer.accept(list.stream().map(ValueInputWriter::new));
|
||||
}
|
||||
});
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* If present value input reader.
|
||||
*
|
||||
* @param key the key
|
||||
* @param action the action
|
||||
* @return the value input reader
|
||||
*/
|
||||
public ValueInputWriter ifPresent(String key, Runnable action) {
|
||||
if (valueInput.child(key).isPresent()) {
|
||||
action.run();
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* If absent value input reader.
|
||||
*
|
||||
* @param key the key
|
||||
* @param action the action
|
||||
* @return the value input reader
|
||||
*/
|
||||
public ValueInputWriter ifAbsent(String key, Runnable action) {
|
||||
if (valueInput.child(key).isEmpty()) {
|
||||
action.run();
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets raw.
|
||||
*
|
||||
* @return the raw
|
||||
*/
|
||||
@NotNull
|
||||
public ValueInput getRaw() {
|
||||
return valueInput;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read vec 3 vec 3.
|
||||
*
|
||||
* @param valueInput the value input
|
||||
* @return the vec 3
|
||||
*/
|
||||
@NotNull
|
||||
public static Vec3 readVec3(@NotNull ValueInput valueInput) {
|
||||
double x = valueInput.getDoubleOr("X", 0.0);
|
||||
double y = valueInput.getDoubleOr("Y", 0.0);
|
||||
double z = valueInput.getDoubleOr("Z", 0.0);
|
||||
return new Vec3(x, y, z);
|
||||
}
|
||||
|
||||
/**
|
||||
* Read vec 3 safe vec 3.
|
||||
*
|
||||
* @param valueInput the value input
|
||||
* @return the vec 3
|
||||
*/
|
||||
@Nullable
|
||||
public static Vec3 readVec3Safe(@NotNull ValueInput valueInput) {
|
||||
try {
|
||||
return readVec3(valueInput);
|
||||
} catch (Exception e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,648 @@
|
|||
package top.r3944realms.lib39.util.storage.vauleio;
|
||||
|
||||
import com.mojang.serialization.Codec;
|
||||
import net.minecraft.util.ProblemReporter;
|
||||
import net.minecraft.world.item.component.ResolvableProfile;
|
||||
import net.minecraft.world.level.storage.TagValueOutput;
|
||||
import net.minecraft.world.level.storage.ValueOutput;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import org.jetbrains.annotations.Contract;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jspecify.annotations.NonNull;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
/**
|
||||
* ValueOutput Helper类
|
||||
* 提供链式操作和类型安全的ValueOutput数据写入
|
||||
*/
|
||||
@SuppressWarnings({"unused", "OptionalUsedAsFieldOrParameterType", "UnusedReturnValue"})
|
||||
public class ValueOutputReader {
|
||||
private final ValueOutput valueOutput;
|
||||
private ValueOutputReader() {
|
||||
this.valueOutput = TagValueOutput.createWithoutContext(ProblemReporter.DISCARDING);
|
||||
}
|
||||
private ValueOutputReader(ValueOutput valueOutput) {
|
||||
this.valueOutput = valueOutput;
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建一个新的NBT构建器
|
||||
*
|
||||
* @return the nbt writer
|
||||
*/
|
||||
@Contract(value = " -> new", pure = true)
|
||||
public static @NotNull ValueOutputReader builder() {
|
||||
return new ValueOutputReader();
|
||||
}
|
||||
|
||||
/**
|
||||
* 从ValueOutput创建写入器
|
||||
*
|
||||
* @param valueOutput the value output
|
||||
* @return the value output writer
|
||||
*/
|
||||
@NotNull
|
||||
public static ValueOutputReader of(@NotNull ValueOutput valueOutput) {
|
||||
return new ValueOutputReader(valueOutput);
|
||||
}
|
||||
|
||||
/**
|
||||
* String value output writer.
|
||||
*
|
||||
* @param key the key
|
||||
* @param value the value
|
||||
* @return the value output writer
|
||||
*/
|
||||
// 基本写入方法
|
||||
public ValueOutputReader string(String key, String value) {
|
||||
if (value != null) {
|
||||
valueOutput.putString(key, value);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* String value output writer.
|
||||
*
|
||||
* @param key the key
|
||||
* @param value the value
|
||||
* @param defaultValue the default value
|
||||
* @return the value output writer
|
||||
*/
|
||||
public ValueOutputReader string(String key, @Nullable String value, String defaultValue) {
|
||||
valueOutput.putString(key, value != null ? value : defaultValue);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* String value output writer.
|
||||
*
|
||||
* @param key the key
|
||||
* @param value the value
|
||||
* @return the value output writer
|
||||
*/
|
||||
public ValueOutputReader string(String key, @NonNull Optional<String> value) {
|
||||
value.ifPresent(v -> valueOutput.putString(key, v));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Boolean value value output writer.
|
||||
*
|
||||
* @param key the key
|
||||
* @param value the value
|
||||
* @return the value output writer
|
||||
*/
|
||||
public ValueOutputReader booleanValue(String key, boolean value) {
|
||||
valueOutput.putBoolean(key, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Boolean value value output writer.
|
||||
*
|
||||
* @param key the key
|
||||
* @param value the value
|
||||
* @return the value output writer
|
||||
*/
|
||||
public ValueOutputReader booleanValue(String key, @NonNull Optional<Boolean> value) {
|
||||
value.ifPresent(v -> valueOutput.putBoolean(key, v));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Byte value value output writer.
|
||||
*
|
||||
* @param key the key
|
||||
* @param value the value
|
||||
* @return the value output writer
|
||||
*/
|
||||
public ValueOutputReader byteValue(String key, byte value) {
|
||||
valueOutput.putByte(key, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Byte value value output writer.
|
||||
*
|
||||
* @param key the key
|
||||
* @param value the value
|
||||
* @return the value output writer
|
||||
*/
|
||||
public ValueOutputReader byteValue(String key, @NonNull Optional<Byte> value) {
|
||||
value.ifPresent(v -> valueOutput.putByte(key, v));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Short value value output writer.
|
||||
*
|
||||
* @param key the key
|
||||
* @param value the value
|
||||
* @return the value output writer
|
||||
*/
|
||||
public ValueOutputReader shortValue(String key, short value) {
|
||||
valueOutput.putShort(key, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Short value value output writer.
|
||||
*
|
||||
* @param key the key
|
||||
* @param value the value
|
||||
* @return the value output writer
|
||||
*/
|
||||
public ValueOutputReader shortValue(String key, @NonNull Optional<Short> value) {
|
||||
value.ifPresent(v -> valueOutput.putShort(key, v));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Int value value output writer.
|
||||
*
|
||||
* @param key the key
|
||||
* @param value the value
|
||||
* @return the value output writer
|
||||
*/
|
||||
public ValueOutputReader intValue(String key, int value) {
|
||||
valueOutput.putInt(key, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Int value value output writer.
|
||||
*
|
||||
* @param key the key
|
||||
* @param value the value
|
||||
* @return the value output writer
|
||||
*/
|
||||
public ValueOutputReader intValue(String key, @NonNull Optional<Integer> value) {
|
||||
value.ifPresent(v -> valueOutput.putInt(key, v));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Long value value output writer.
|
||||
*
|
||||
* @param key the key
|
||||
* @param value the value
|
||||
* @return the value output writer
|
||||
*/
|
||||
public ValueOutputReader longValue(String key, long value) {
|
||||
valueOutput.putLong(key, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Long value value output writer.
|
||||
*
|
||||
* @param key the key
|
||||
* @param value the value
|
||||
* @return the value output writer
|
||||
*/
|
||||
public ValueOutputReader longValue(String key, @NonNull Optional<Long> value) {
|
||||
value.ifPresent(v -> valueOutput.putLong(key, v));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Float value value output writer.
|
||||
*
|
||||
* @param key the key
|
||||
* @param value the value
|
||||
* @return the value output writer
|
||||
*/
|
||||
public ValueOutputReader floatValue(String key, float value) {
|
||||
valueOutput.putFloat(key, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Float value value output writer.
|
||||
*
|
||||
* @param key the key
|
||||
* @param value the value
|
||||
* @return the value output writer
|
||||
*/
|
||||
public ValueOutputReader floatValue(String key, @NonNull Optional<Float> value) {
|
||||
value.ifPresent(v -> valueOutput.putFloat(key, v));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Double value value output writer.
|
||||
*
|
||||
* @param key the key
|
||||
* @param value the value
|
||||
* @return the value output writer
|
||||
*/
|
||||
public ValueOutputReader doubleValue(String key, double value) {
|
||||
valueOutput.putDouble(key, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Double value value output writer.
|
||||
*
|
||||
* @param key the key
|
||||
* @param value the value
|
||||
* @return the value output writer
|
||||
*/
|
||||
public ValueOutputReader doubleValue(String key, @NonNull Optional<Double> value) {
|
||||
value.ifPresent(v -> valueOutput.putDouble(key, v));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Int array value output writer.
|
||||
*
|
||||
* @param key the key
|
||||
* @param value the value
|
||||
* @return the value output writer
|
||||
*/
|
||||
public ValueOutputReader intArray(String key, int[] value) {
|
||||
if (value != null && value.length > 0) {
|
||||
valueOutput.putIntArray(key, value);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Int array value output writer.
|
||||
*
|
||||
* @param key the key
|
||||
* @param value the value
|
||||
* @return the value output writer
|
||||
*/
|
||||
public ValueOutputReader intArray(String key, @NonNull Optional<int[]> value) {
|
||||
value.ifPresent(v -> {
|
||||
if (v.length > 0) {
|
||||
valueOutput.putIntArray(key, v);
|
||||
}
|
||||
});
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Codec value value output writer.
|
||||
*
|
||||
* @param <T> the type parameter
|
||||
* @param key the key
|
||||
* @param codec the codec
|
||||
* @param value the value
|
||||
* @return the value output writer
|
||||
*/
|
||||
public <T> ValueOutputReader codecValue(String key, Codec<T> codec, T value) {
|
||||
if (value != null) {
|
||||
valueOutput.store(key, codec, value);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Codec value value output writer.
|
||||
*
|
||||
* @param <T> the type parameter
|
||||
* @param key the key
|
||||
* @param codec the codec
|
||||
* @param value the value
|
||||
* @return the value output writer
|
||||
*/
|
||||
public <T> ValueOutputReader codecValue(String key, Codec<T> codec, @NonNull Optional<T> value) {
|
||||
value.ifPresent(v -> valueOutput.store(key, codec, v));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Codec nullable value value output writer.
|
||||
*
|
||||
* @param <T> the type parameter
|
||||
* @param key the key
|
||||
* @param codec the codec
|
||||
* @param value the value
|
||||
* @return the value output writer
|
||||
*/
|
||||
public <T> ValueOutputReader codecNullable(String key, Codec<T> codec, @Nullable T value) {
|
||||
valueOutput.storeNullable(key, codec, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
public ValueOutputReader gameProfile(String key, ResolvableProfile profile) {
|
||||
valueOutput.store(key, ResolvableProfile.CODEC, profile);
|
||||
return this;
|
||||
}
|
||||
|
||||
public ValueOutputReader gameProfile(String key, @NonNull Optional<ResolvableProfile> profile) {
|
||||
if (profile.isPresent()) {
|
||||
valueOutput.store(key, ResolvableProfile.CODEC, profile.get());
|
||||
}
|
||||
return this;
|
||||
}
|
||||
/**
|
||||
* Vec 3 value output writer.
|
||||
*
|
||||
* @param key the key
|
||||
* @param vec the vec
|
||||
* @return the value output writer
|
||||
*/
|
||||
public ValueOutputReader vec3(String key, Vec3 vec) {
|
||||
if (vec != null) {
|
||||
ValueOutput child = valueOutput.child(key);
|
||||
writeVec3(child, vec);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Vec 3 value output writer.
|
||||
*
|
||||
* @param key the key
|
||||
* @param vec the vec
|
||||
* @return the value output writer
|
||||
*/
|
||||
public ValueOutputReader vec3(String key, @NonNull Optional<Vec3> vec) {
|
||||
vec.ifPresent(v -> vec3(key, v));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enum value value output writer.
|
||||
*
|
||||
* @param <T> the type parameter
|
||||
* @param key the key
|
||||
* @param value the value
|
||||
* @return the value output writer
|
||||
*/
|
||||
public <T extends Enum<T>> ValueOutputReader enumValue(String key, T value) {
|
||||
if (value != null) {
|
||||
valueOutput.putString(key, value.name().toLowerCase());
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enum value value output writer.
|
||||
*
|
||||
* @param <T> the type parameter
|
||||
* @param key the key
|
||||
* @param value the value
|
||||
* @return the value output writer
|
||||
*/
|
||||
public <T extends Enum<T>> ValueOutputReader enumValue(String key, @NonNull Optional<T> value) {
|
||||
value.ifPresent(v -> valueOutput.putString(key, v.name().toLowerCase()));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Nested value output writer.
|
||||
*
|
||||
* @param key the key
|
||||
* @param consumer the consumer
|
||||
* @return the value output writer
|
||||
*/
|
||||
public ValueOutputReader nested(String key, @NonNull Consumer<ValueOutputReader> consumer) {
|
||||
ValueOutput child = valueOutput.child(key);
|
||||
consumer.accept(new ValueOutputReader(child));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Nested if present value output writer.
|
||||
*
|
||||
* @param key the key
|
||||
* @param supplier the supplier
|
||||
* @param consumer the consumer
|
||||
* @return the value output writer
|
||||
*/
|
||||
public ValueOutputReader nestedIfPresent(String key, @NonNull Supplier<Boolean> supplier, Consumer<ValueOutputReader> consumer) {
|
||||
if (supplier.get()) {
|
||||
ValueOutput child = valueOutput.child(key);
|
||||
consumer.accept(new ValueOutputReader(child));
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* List value output writer.
|
||||
*
|
||||
* @param <T> the type parameter
|
||||
* @param key the key
|
||||
* @param elementCodec the element codec
|
||||
* @param elements the elements
|
||||
* @param consumer the consumer
|
||||
* @return the value output writer
|
||||
*/
|
||||
public <T> ValueOutputReader list(String key, Codec<T> elementCodec, Iterable<T> elements, Consumer<TypedListWriter<T>> consumer) {
|
||||
ValueOutput.TypedOutputList<T> list = valueOutput.list(key, elementCodec);
|
||||
if (!list.isEmpty()) {
|
||||
TypedListWriter<T> writer = new TypedListWriter<>(list);
|
||||
consumer.accept(writer);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* List value output writer.
|
||||
*
|
||||
* @param <T> the type parameter
|
||||
* @param key the key
|
||||
* @param elementCodec the element codec
|
||||
* @param elements the elements
|
||||
* @return the value output writer
|
||||
*/
|
||||
public <T> ValueOutputReader list(String key, Codec<T> elementCodec, @NonNull Iterable<T> elements) {
|
||||
ValueOutput.TypedOutputList<T> list = valueOutput.list(key, elementCodec);
|
||||
for (T element : elements) {
|
||||
if (element != null) {
|
||||
list.add(element);
|
||||
}
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Children list value output writer.
|
||||
*
|
||||
* @param key the key
|
||||
* @param consumer the consumer
|
||||
* @return the value output writer
|
||||
*/
|
||||
public ValueOutputReader childrenList(String key, Consumer<ChildrenListWriter> consumer) {
|
||||
ValueOutput.ValueOutputList list = valueOutput.childrenList(key);
|
||||
if (!list.isEmpty()) {
|
||||
ChildrenListWriter writer = new ChildrenListWriter(list);
|
||||
consumer.accept(writer);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* If present value output writer.
|
||||
*
|
||||
* @param condition the condition
|
||||
* @param action the action
|
||||
* @return the value output writer
|
||||
*/
|
||||
public ValueOutputReader ifPresent(boolean condition, Consumer<ValueOutputReader> action) {
|
||||
if (condition) {
|
||||
action.accept(this);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* If present value output writer.
|
||||
*
|
||||
* @param condition the condition
|
||||
* @param action the action
|
||||
* @return the value output writer
|
||||
*/
|
||||
public ValueOutputReader ifPresent(@NonNull Supplier<Boolean> condition, Consumer<ValueOutputReader> action) {
|
||||
if (condition.get()) {
|
||||
action.accept(this);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Discard value output writer.
|
||||
*
|
||||
* @param key the key
|
||||
* @return the value output writer
|
||||
*/
|
||||
public ValueOutputReader discard(String key) {
|
||||
valueOutput.discard(key);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets raw.
|
||||
*
|
||||
* @return the raw
|
||||
*/
|
||||
@NotNull
|
||||
public ValueOutput getRaw() {
|
||||
return valueOutput;
|
||||
}
|
||||
|
||||
/**
|
||||
* Write vec 3.
|
||||
*
|
||||
* @param valueOutput the value output
|
||||
* @param vec the vec
|
||||
*/
|
||||
public static void writeVec3(@NotNull ValueOutput valueOutput, @NotNull Vec3 vec) {
|
||||
valueOutput.putDouble("X", vec.x);
|
||||
valueOutput.putDouble("Y", vec.y);
|
||||
valueOutput.putDouble("Z", vec.z);
|
||||
}
|
||||
|
||||
/**
|
||||
* Write vec 3 safe.
|
||||
*
|
||||
* @param valueOutput the value output
|
||||
* @param vec the vec
|
||||
*/
|
||||
public static void writeVec3Safe(@NotNull ValueOutput valueOutput, @Nullable Vec3 vec) {
|
||||
if (vec != null) {
|
||||
writeVec3(valueOutput, vec);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The type Typed list writer.
|
||||
*
|
||||
* @param <T> the type parameter
|
||||
*/
|
||||
public static class TypedListWriter<T> {
|
||||
private final ValueOutput.TypedOutputList<T> list;
|
||||
|
||||
private TypedListWriter(ValueOutput.TypedOutputList<T> list) {
|
||||
this.list = list;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add typed list writer.
|
||||
*
|
||||
* @param element the element
|
||||
* @return the typed list writer
|
||||
*/
|
||||
public TypedListWriter<T> add(T element) {
|
||||
if (element != null) {
|
||||
list.add(element);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add all typed list writer.
|
||||
*
|
||||
* @param elements the elements
|
||||
* @return the typed list writer
|
||||
*/
|
||||
public TypedListWriter<T> addAll(@NonNull Iterable<T> elements) {
|
||||
for (T element : elements) {
|
||||
if (element != null) {
|
||||
list.add(element);
|
||||
}
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Is empty boolean.
|
||||
*
|
||||
* @return the boolean
|
||||
*/
|
||||
public boolean isEmpty() {
|
||||
return list.isEmpty();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The type Children list writer.
|
||||
*/
|
||||
public static class ChildrenListWriter {
|
||||
private final ValueOutput.ValueOutputList list;
|
||||
|
||||
private ChildrenListWriter(ValueOutput.ValueOutputList list) {
|
||||
this.list = list;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add child value output writer.
|
||||
*
|
||||
* @param consumer the consumer
|
||||
* @return the children list writer
|
||||
*/
|
||||
public ChildrenListWriter addChild(@NonNull Consumer<ValueOutputReader> consumer) {
|
||||
ValueOutput child = list.addChild();
|
||||
consumer.accept(new ValueOutputReader(child));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Discard last children list writer.
|
||||
*
|
||||
* @return the children list writer
|
||||
*/
|
||||
public ChildrenListWriter discardLast() {
|
||||
list.discardLast();
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Is empty boolean.
|
||||
*
|
||||
* @return the boolean
|
||||
*/
|
||||
public boolean isEmpty() {
|
||||
return list.isEmpty();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -2,29 +2,37 @@ package top.r3944realms.lib39.util.villager;
|
|||
|
||||
import com.google.common.collect.Lists;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Holder;
|
||||
import net.minecraft.core.Registry;
|
||||
import net.minecraft.core.component.DataComponents;
|
||||
import net.minecraft.core.registries.BuiltInRegistries;
|
||||
import net.minecraft.core.registries.Registries;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.tags.EnchantmentTags;
|
||||
import net.minecraft.tags.ItemTags;
|
||||
import net.minecraft.tags.TagKey;
|
||||
import net.minecraft.util.Mth;
|
||||
import net.minecraft.util.RandomSource;
|
||||
import net.minecraft.world.effect.MobEffect;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.entity.npc.VillagerDataHolder;
|
||||
import net.minecraft.world.entity.npc.VillagerTrades;
|
||||
import net.minecraft.world.entity.npc.VillagerType;
|
||||
import net.minecraft.world.entity.npc.villager.VillagerDataHolder;
|
||||
import net.minecraft.world.entity.npc.villager.VillagerTrades;
|
||||
import net.minecraft.world.entity.npc.villager.VillagerType;
|
||||
import net.minecraft.world.item.*;
|
||||
import net.minecraft.world.item.alchemy.Potion;
|
||||
import net.minecraft.world.item.alchemy.PotionBrewing;
|
||||
import net.minecraft.world.item.alchemy.PotionUtils;
|
||||
import net.minecraft.world.item.alchemy.PotionContents;
|
||||
import net.minecraft.world.item.component.DyedItemColor;
|
||||
import net.minecraft.world.item.component.SuspiciousStewEffects;
|
||||
import net.minecraft.world.item.enchantment.Enchantment;
|
||||
import net.minecraft.world.item.enchantment.EnchantmentHelper;
|
||||
import net.minecraft.world.item.enchantment.EnchantmentInstance;
|
||||
import net.minecraft.world.item.trading.ItemCost;
|
||||
import net.minecraft.world.item.trading.MerchantOffer;
|
||||
import net.minecraft.world.level.ItemLike;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.levelgen.structure.Structure;
|
||||
import net.minecraft.world.level.saveddata.maps.MapDecoration;
|
||||
import net.minecraft.world.level.saveddata.maps.MapDecorationType;
|
||||
import net.minecraft.world.level.saveddata.maps.MapItemSavedData;
|
||||
import org.jetbrains.annotations.Contract;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
|
@ -32,6 +40,7 @@ import org.jetbrains.annotations.Nullable;
|
|||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* 村民交易构建器
|
||||
|
|
@ -116,21 +125,22 @@ public class TradeBuilder {
|
|||
/**
|
||||
* 创建宝藏地图交易
|
||||
*
|
||||
* @param emeraldCost 绿宝石价格
|
||||
* @param destination the destination
|
||||
* @param displayName 显示名称
|
||||
* @param destinationTyp the destination typ
|
||||
* @param maxUses 最大使用次数
|
||||
* @param villagerXp 村民获得的经验
|
||||
* @param emeraldCost 绿宝石价格
|
||||
* @param destination the destination
|
||||
* @param displayName 显示名称
|
||||
* @param destinationType the destination type
|
||||
* @param maxUses 最大使用次数
|
||||
* @param villagerXp 村民获得的经验
|
||||
* @return 交易实例 treasure map for emeralds
|
||||
*/
|
||||
@Contract(pure = true)
|
||||
public static @NotNull TreasureMapForEmeralds createTreasureMapTrade(
|
||||
int emeraldCost, TagKey<Structure> destination, String displayName, MapDecoration.Type destinationTyp, int maxUses, int villagerXp) {
|
||||
|
||||
return new TreasureMapForEmeralds(emeraldCost, destination, displayName, destinationTyp, maxUses, villagerXp);
|
||||
int emeraldCost, TagKey<Structure> destination, String displayName,
|
||||
Holder<MapDecorationType> destinationType, int maxUses, int villagerXp) {
|
||||
return new TreasureMapForEmeralds(emeraldCost, destination, displayName, destinationType, maxUses, villagerXp);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 创建染色盔甲交易
|
||||
*
|
||||
|
|
@ -173,8 +183,8 @@ public class TradeBuilder {
|
|||
}
|
||||
|
||||
public MerchantOffer getOffer(@NotNull Entity trader, @NotNull RandomSource random) {
|
||||
ItemStack itemstack = new ItemStack(this.item, this.cost);
|
||||
return new MerchantOffer(itemstack, new ItemStack(Items.EMERALD), this.maxUses, this.villagerXp, this.priceMultiplier);
|
||||
ItemCost itemCost = new ItemCost(this.item, this.cost);
|
||||
return new MerchantOffer(itemCost, new ItemStack(Items.EMERALD), this.maxUses, this.villagerXp, this.priceMultiplier);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -260,7 +270,7 @@ public class TradeBuilder {
|
|||
}
|
||||
|
||||
public MerchantOffer getOffer(@NotNull Entity trader, @NotNull RandomSource random) {
|
||||
return new MerchantOffer(new ItemStack(Items.EMERALD, this.emeraldCost), new ItemStack(this.itemStack.getItem(), this.numberOfItems), this.maxUses, this.villagerXp, this.priceMultiplier);
|
||||
return new MerchantOffer(new ItemCost(Items.EMERALD, this.emeraldCost), new ItemStack(this.itemStack.getItem(), this.numberOfItems), this.maxUses, this.villagerXp, this.priceMultiplier);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -271,7 +281,7 @@ public class TradeBuilder {
|
|||
/**
|
||||
* The Effect.
|
||||
*/
|
||||
final MobEffect effect;
|
||||
private final Holder<MobEffect> effect;
|
||||
/**
|
||||
* The Duration.
|
||||
*/
|
||||
|
|
@ -289,7 +299,7 @@ public class TradeBuilder {
|
|||
* @param duration the duration
|
||||
* @param xp the xp
|
||||
*/
|
||||
public SuspiciousStewForEmerald(MobEffect effect, int duration, int xp) {
|
||||
public SuspiciousStewForEmerald(Holder<MobEffect> effect, int duration, int xp) {
|
||||
this.effect = effect;
|
||||
this.duration = duration;
|
||||
this.xp = xp;
|
||||
|
|
@ -299,8 +309,9 @@ public class TradeBuilder {
|
|||
@Nullable
|
||||
public MerchantOffer getOffer(@NotNull Entity trader, @NotNull RandomSource random) {
|
||||
ItemStack itemstack = new ItemStack(Items.SUSPICIOUS_STEW, 1);
|
||||
SuspiciousStewItem.saveMobEffect(itemstack, this.effect, this.duration);
|
||||
return new MerchantOffer(new ItemStack(Items.EMERALD, 1), itemstack, 12, this.xp, this.priceMultiplier);
|
||||
itemstack.set(DataComponents.SUSPICIOUS_STEW_EFFECTS,
|
||||
new SuspiciousStewEffects(List.of(new SuspiciousStewEffects.Entry(effect, this.duration))));
|
||||
return new MerchantOffer(new ItemCost(Items.EMERALD, 1), itemstack, 12, this.xp, this.priceMultiplier);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -355,7 +366,7 @@ public class TradeBuilder {
|
|||
|
||||
@Nullable
|
||||
public MerchantOffer getOffer(@NotNull Entity trader, @NotNull RandomSource random) {
|
||||
return new MerchantOffer(new ItemStack(Items.EMERALD, this.emeraldCost), new ItemStack(this.fromItem.getItem(), this.fromCount), new ItemStack(this.toItem.getItem(), this.toCount), this.maxUses, this.villagerXp, this.priceMultiplier);
|
||||
return new MerchantOffer(new ItemCost(Items.EMERALD, this.emeraldCost), Optional.of(new ItemCost(this.fromItem.getItem(), this.fromCount)), new ItemStack(this.toItem.getItem(), this.toCount), this.maxUses, this.villagerXp, this.priceMultiplier);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -400,9 +411,10 @@ public class TradeBuilder {
|
|||
|
||||
public MerchantOffer getOffer(@NotNull Entity trader, @NotNull RandomSource random) {
|
||||
int i = 5 + random.nextInt(15);
|
||||
ItemStack itemstack = EnchantmentHelper.enchantItem(random, new ItemStack(this.itemStack.getItem()), i, false);
|
||||
ItemStack itemstack = EnchantmentHelper.enchantItem(random, new ItemStack(this.itemStack.getItem()), i ,
|
||||
trader.level().registryAccess(), Optional.empty());
|
||||
int j = Math.min(this.baseEmeraldCost + i, 64);
|
||||
ItemStack itemstack1 = new ItemStack(Items.EMERALD, j);
|
||||
ItemCost itemstack1 = new ItemCost(Items.EMERALD, j);
|
||||
return new MerchantOffer(itemstack1, itemstack, this.maxUses, this.villagerXp, this.priceMultiplier);
|
||||
}
|
||||
}
|
||||
|
|
@ -439,8 +451,8 @@ public class TradeBuilder {
|
|||
@Nullable
|
||||
public MerchantOffer getOffer(@NotNull Entity trader, @NotNull RandomSource random) {
|
||||
if (trader instanceof VillagerDataHolder) {
|
||||
ItemStack itemstack = new ItemStack(this.trades.get(((VillagerDataHolder)trader).getVillagerData().getType()), this.cost);
|
||||
return new MerchantOffer(itemstack, new ItemStack(Items.EMERALD), this.maxUses, this.villagerXp, 0.05F);
|
||||
ItemCost itemCost = new ItemCost(this.trades.get(((VillagerDataHolder)trader).getVillagerData().getType()), this.cost);
|
||||
return new MerchantOffer(itemCost, new ItemStack(Items.EMERALD), this.maxUses, this.villagerXp, 0.05F);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
|
|
@ -484,11 +496,15 @@ public class TradeBuilder {
|
|||
}
|
||||
|
||||
public MerchantOffer getOffer(@NotNull Entity trader, @NotNull RandomSource random) {
|
||||
ItemStack itemstack = new ItemStack(Items.EMERALD, this.emeraldCost);
|
||||
List<Potion> list = BuiltInRegistries.POTION.stream().filter((effects) -> !effects.getEffects().isEmpty() && PotionBrewing.isBrewablePotion(effects)).toList();
|
||||
Potion potion = list.get(random.nextInt(list.size()));
|
||||
ItemStack itemstack1 = PotionUtils.setPotion(new ItemStack(this.toItem.getItem(), this.toCount), potion);
|
||||
return new MerchantOffer(itemstack, new ItemStack(this.fromItem, this.fromCount), itemstack1, this.maxUses, this.villagerXp, this.priceMultiplier);
|
||||
ItemCost itemcost = new ItemCost(Items.EMERALD, this.emeraldCost);
|
||||
List<? extends Holder<Potion>> brewablePotions = BuiltInRegistries.POTION.holders()
|
||||
.filter(potion -> !potion.value().getEffects().isEmpty())
|
||||
.filter(trader.level().potionBrewing()::isBrewablePotion)
|
||||
.toList();
|
||||
Holder<Potion> potion = brewablePotions.get(random.nextInt(brewablePotions.size()));
|
||||
ItemStack itemstack = new ItemStack(this.toItem.getItem(), this.toCount);
|
||||
itemstack.set(DataComponents.POTION_CONTENTS, new PotionContents(potion));
|
||||
return new MerchantOffer(itemcost, Optional.of(new ItemCost(this.fromItem, this.fromCount)), itemstack, this.maxUses, this.villagerXp, this.priceMultiplier);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -509,12 +525,17 @@ public class TradeBuilder {
|
|||
}
|
||||
|
||||
public MerchantOffer getOffer(@NotNull Entity trader, @NotNull RandomSource random) {
|
||||
List<Enchantment> list = BuiltInRegistries.ENCHANTMENT.stream().filter(Enchantment::isTradeable).toList();
|
||||
Enchantment enchantment = list.get(random.nextInt(list.size()));
|
||||
Registry<Enchantment> registry = trader.level().registryAccess().registryOrThrow(Registries.ENCHANTMENT);
|
||||
List<? extends Holder<Enchantment>> list = registry.holders()
|
||||
.filter(holder -> holder.is(EnchantmentTags.TRADEABLE))
|
||||
.toList();
|
||||
Holder<Enchantment> holder = list.get(random.nextInt(list.size()));
|
||||
Enchantment enchantment = holder.value();
|
||||
int i = Mth.nextInt(random, enchantment.getMinLevel(), enchantment.getMaxLevel());
|
||||
ItemStack itemstack = EnchantedBookItem.createForEnchantment(new EnchantmentInstance(enchantment, i));
|
||||
ItemStack itemstack = EnchantedBookItem.createForEnchantment(new EnchantmentInstance(holder, i));
|
||||
int j = 2 + random.nextInt(5 + i * 10) + 3 * i;
|
||||
if (enchantment.isTreasureOnly()) {
|
||||
|
||||
if (holder.is(EnchantmentTags.DOUBLE_TRADE_PRICE)) {
|
||||
j *= 2;
|
||||
}
|
||||
|
||||
|
|
@ -522,7 +543,7 @@ public class TradeBuilder {
|
|||
j = 64;
|
||||
}
|
||||
|
||||
return new MerchantOffer(new ItemStack(Items.EMERALD, j), new ItemStack(Items.BOOK), itemstack, 12, this.villagerXp, 0.2F);
|
||||
return new MerchantOffer(new ItemCost(Items.EMERALD, j), Optional.of(new ItemCost(Items.BOOK)), itemstack, 12, this.villagerXp, 0.2F);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -533,7 +554,7 @@ public class TradeBuilder {
|
|||
private final int emeraldCost;
|
||||
private final TagKey<Structure> destination;
|
||||
private final String displayName;
|
||||
private final MapDecoration.Type destinationType;
|
||||
private final Holder<MapDecorationType> destinationType;
|
||||
private final int maxUses;
|
||||
private final int villagerXp;
|
||||
|
||||
|
|
@ -547,7 +568,7 @@ public class TradeBuilder {
|
|||
* @param maxUses the max uses
|
||||
* @param villagerXp the villager xp
|
||||
*/
|
||||
public TreasureMapForEmeralds(int emeraldCost, TagKey<Structure> destination, String displayName, MapDecoration.Type destinationType, int maxUses, int villagerXp) {
|
||||
public TreasureMapForEmeralds(int emeraldCost, TagKey<Structure> destination, String displayName, Holder<MapDecorationType> destinationType, int maxUses, int villagerXp) {
|
||||
this.emeraldCost = emeraldCost;
|
||||
this.destination = destination;
|
||||
this.displayName = displayName;
|
||||
|
|
@ -566,8 +587,10 @@ public class TradeBuilder {
|
|||
ItemStack itemstack = MapItem.create(serverlevel, blockpos.getX(), blockpos.getZ(), (byte)2, true, true);
|
||||
MapItem.renderBiomePreviewMap(serverlevel, itemstack);
|
||||
MapItemSavedData.addTargetDecoration(itemstack, blockpos, "+", this.destinationType);
|
||||
itemstack.setHoverName(Component.translatable(this.displayName));
|
||||
return new MerchantOffer(new ItemStack(Items.EMERALD, this.emeraldCost), new ItemStack(Items.COMPASS), itemstack, this.maxUses, this.villagerXp, 0.2F);
|
||||
MapItemSavedData.addTargetDecoration(itemstack, blockpos, "+", this.destinationType);
|
||||
itemstack.set(DataComponents.ITEM_NAME, Component.translatable(this.displayName));
|
||||
return new MerchantOffer(new ItemCost(Items.EMERALD, this.emeraldCost),
|
||||
Optional.of(new ItemCost(Items.COMPASS)), itemstack, this.maxUses, this.villagerXp, 0.2F);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
|
|
@ -610,23 +633,23 @@ public class TradeBuilder {
|
|||
}
|
||||
|
||||
public MerchantOffer getOffer(@NotNull Entity trader, @NotNull RandomSource random) {
|
||||
ItemStack itemstack = new ItemStack(Items.EMERALD, this.value);
|
||||
ItemStack itemstack1 = new ItemStack(this.item);
|
||||
if (this.item instanceof DyeableArmorItem) {
|
||||
List<DyeItem> list = Lists.newArrayList();
|
||||
list.add(getRandomDye(random));
|
||||
ItemCost itemCost = new ItemCost(Items.EMERALD, this.value);
|
||||
ItemStack armorStack = new ItemStack(this.item);
|
||||
|
||||
if (armorStack.is(ItemTags.DYEABLE)) {
|
||||
List<DyeItem> dyes = Lists.newArrayList();
|
||||
dyes.add(getRandomDye(random));
|
||||
if (random.nextFloat() > 0.7F) {
|
||||
list.add(getRandomDye(random));
|
||||
dyes.add(getRandomDye(random));
|
||||
}
|
||||
|
||||
if (random.nextFloat() > 0.8F) {
|
||||
list.add(getRandomDye(random));
|
||||
dyes.add(getRandomDye(random));
|
||||
}
|
||||
|
||||
itemstack1 = DyeableLeatherItem.dyeArmor(itemstack1, list);
|
||||
// 1.21.1: 使用 DYED_COLOR 组件设置颜色
|
||||
armorStack = DyedItemColor.applyDyes(armorStack, dyes);
|
||||
}
|
||||
|
||||
return new MerchantOffer(itemstack, itemstack1, this.maxUses, this.villagerXp, 0.2F);
|
||||
return new MerchantOffer(itemCost, armorStack, this.maxUses, this.villagerXp, 0.2F);
|
||||
}
|
||||
|
||||
private static @NotNull DyeItem getRandomDye(@NotNull RandomSource random) {
|
||||
|
|
|
|||
|
|
@ -16,9 +16,7 @@ void main() {
|
|||
|
||||
// 确保内外半径合理
|
||||
if (OuterRadius <= InnerRadius) {
|
||||
vec4 color = vertexColor;
|
||||
color.a = 0;
|
||||
fragColor = color;
|
||||
discard; // ✅ 直接丢弃片段,不需要设置颜色
|
||||
}
|
||||
|
||||
// 计算环形 alpha
|
||||
|
|
@ -28,20 +26,20 @@ void main() {
|
|||
// 内边缘抗锯齿
|
||||
if (dist < InnerRadius + AntiAliasing) {
|
||||
float fade = (dist - InnerRadius) / AntiAliasing;
|
||||
alpha *= fade;
|
||||
alpha *= clamp(fade, 0.0, 1.0); // ✅ 确保值在 [0,1] 范围内
|
||||
}
|
||||
|
||||
// 外边缘抗锯齿
|
||||
if (dist > OuterRadius - AntiAliasing) {
|
||||
float fade = 1.0 - (dist - (OuterRadius - AntiAliasing)) / AntiAliasing;
|
||||
alpha *= fade;
|
||||
alpha *= clamp(fade, 0.0, 1.0); // ✅ 确保值在 [0,1] 范围内
|
||||
}
|
||||
}
|
||||
|
||||
vec4 color = vertexColor;
|
||||
color.a *= alpha;
|
||||
color.a = color.a * alpha; // ✅ 修正语法
|
||||
|
||||
if (alpha > 0.0) {
|
||||
if (color.a > 0.0) {
|
||||
fragColor = color * ColorModulator;
|
||||
} else {
|
||||
discard;
|
||||
|
|
|
|||
|
|
@ -6,7 +6,6 @@ uniform vec4 ColorModulator;
|
|||
uniform vec2 FramebufferSize;
|
||||
uniform vec2 Center;
|
||||
uniform float Radius;
|
||||
uniform float AntiAliasingRadius;
|
||||
|
||||
out vec4 fragColor;
|
||||
|
||||
|
|
|
|||
|
|
@ -32,14 +32,6 @@
|
|||
"values": [
|
||||
0.0
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "AntiAliasingRadius",
|
||||
"type": "float",
|
||||
"count": 1,
|
||||
"values": [
|
||||
1.5
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -1,2 +1 @@
|
|||
accessWidener v2 named
|
||||
# 不要用这个,太垃圾了,不支持parchment名
|
||||
classTweaker v1 official
|
||||
|
|
@ -3,9 +3,10 @@
|
|||
"minVersion": "0.8",
|
||||
"package": "top.r3944realms.lib39.mixin",
|
||||
"refmap": "${mod_id}.refmap.json",
|
||||
"compatibilityLevel": "JAVA_17",
|
||||
"compatibilityLevel": "JAVA_21",
|
||||
"mixins": [
|
||||
"carryon.MixinCarriedObjectRender",
|
||||
"minecraft.MixinEntity",
|
||||
"minecraft.CreativeModeTabsAccessor"
|
||||
],
|
||||
"client": [
|
||||
|
|
|
|||
|
|
@ -1,26 +1,13 @@
|
|||
import net.fabricmc.loom.task.RemapJarTask
|
||||
|
||||
plugins {
|
||||
id 'multiloader-loader'
|
||||
id 'fabric-loom'
|
||||
}
|
||||
repositories {
|
||||
maven { url 'https://maven.covers1624.net/' }
|
||||
id 'net.fabricmc.fabric-loom'
|
||||
}
|
||||
|
||||
dependencies {
|
||||
minecraft "com.mojang:minecraft:${minecraft_version}"
|
||||
mappings loom.layered {
|
||||
officialMojangMappings()
|
||||
parchment("org.parchmentmc.data:parchment-${parchment_minecraft}:${parchment_version}@zip")
|
||||
}
|
||||
modImplementation(group: 'tschipp.carryon', name: 'carryon-fabric-1.20.1', version: '2.1.2.7') {
|
||||
transitive = false
|
||||
}
|
||||
modImplementation "net.fabricmc:fabric-loader:${fabric_loader_version}"
|
||||
modImplementation "net.fabricmc.fabric-api:fabric-api:${fabric_version}"
|
||||
implementation group: 'com.google.code.findbugs', name: 'jsr305', version: '3.0.1'
|
||||
implementation project(":common")
|
||||
modImplementation "curse.maven:jade-324717:6291330"
|
||||
implementation "net.fabricmc:fabric-loader:${fabric_loader_version}"
|
||||
implementation "net.fabricmc.fabric-api:fabric-api:${fabric_version}"
|
||||
implementation "curse.maven:jade-324717:8048381"
|
||||
testImplementation "net.fabricmc:fabric-loader-junit:${fabric_loader_version}"
|
||||
localRuntime 'net.covers1624:DevLogin:0.1.0.5'
|
||||
}
|
||||
|
|
@ -36,7 +23,7 @@ loom {
|
|||
accessWidenerPath.set(project(":common").file("src/main/resources/${mod_id}.accesswidener"))
|
||||
}
|
||||
mixin {
|
||||
defaultRefmapName.set("${mod_id}.refmap.json")
|
||||
defaultRefmapName.set("${mod_id}.fabric.refmap.json")
|
||||
}
|
||||
runs {
|
||||
client {
|
||||
|
|
@ -102,7 +89,7 @@ tasks.named('javadoc', Javadoc) {
|
|||
classpath += project(':common').sourceSets.main.compileClasspath
|
||||
options.encoding = 'UTF-8'
|
||||
options.charSet = 'UTF-8'
|
||||
options.links("https://docs.oracle.com/en/java/javase/17/docs/api/")
|
||||
options.links("https://docs.oracle.com/en/java/javase/25/docs/api/")
|
||||
options.memberLevel = JavadocMemberLevel.PUBLIC
|
||||
options.addBooleanOption('Xdoclint:none', true)
|
||||
options.addStringOption('doctitle', "${mod_id} ${minecraft_version} ${version} Javadoc")
|
||||
|
|
@ -123,97 +110,20 @@ tasks.named('build') {
|
|||
dependsOn tasks.named('javadocJar')
|
||||
}
|
||||
|
||||
// 配置remap任务以包含sources和javadoc
|
||||
remapJar {
|
||||
dependsOn tasks.named('sourcesJar')
|
||||
dependsOn tasks.named('javadocJar')
|
||||
inputFile.set(tasks.named('jar').get().archiveFile)
|
||||
addNestedDependencies = false
|
||||
}
|
||||
|
||||
remapSourcesJar {
|
||||
dependsOn tasks.named('sourcesJar')
|
||||
inputFile.set(tasks.named('sourcesJar').get().archiveFile)
|
||||
}
|
||||
|
||||
// 为javadocJar创建remap任务
|
||||
tasks.register('remapJavadocJar', RemapJarTask) {
|
||||
dependsOn tasks.named('javadocJar')
|
||||
inputFile.set(tasks.named('javadocJar').get().archiveFile)
|
||||
archiveClassifier.set('javadoc')
|
||||
addNestedDependencies = false
|
||||
}
|
||||
|
||||
// 将remapped artifacts添加到发布配置
|
||||
publishing {
|
||||
publications {
|
||||
mavenJava(MavenPublication) {
|
||||
// 重置artifactsId
|
||||
artifactId = "${mod_id}-fabric-${minecraft_version}"
|
||||
artifacts.clear()
|
||||
// 手动添加需要的artifacts
|
||||
artifact(remapJar) {
|
||||
builtBy remapJar
|
||||
}
|
||||
artifact(remapSourcesJar) {
|
||||
builtBy remapSourcesJar
|
||||
classifier = 'sources'
|
||||
}
|
||||
artifact(remapJavadocJar) {
|
||||
builtBy remapJavadocJar
|
||||
classifier = 'javadoc'
|
||||
}
|
||||
pom {
|
||||
name = 'Lib39'
|
||||
description = 'Lib39 is a general-purpose dependency library for Minecraft mods.'
|
||||
url = 'https://github.com/3944Realms/lib39'
|
||||
|
||||
properties = [
|
||||
'minecraft.version': project.minecraft_version,
|
||||
'mod.version': project.version,
|
||||
'fabric.version': project.fabric_version,
|
||||
'java.version': '17'
|
||||
]
|
||||
|
||||
licenses {
|
||||
license {
|
||||
name = 'MIT'
|
||||
url = 'https://raw.githubusercontent.com/3944Realms/lib39/refs/heads/main/LICENSE'
|
||||
distribution = 'repo'
|
||||
}
|
||||
}
|
||||
|
||||
developers {
|
||||
developer {
|
||||
id = 'R3944Realms'
|
||||
name = "${mod_author}"
|
||||
email = 'f256198830@hotmail.com'
|
||||
}
|
||||
}
|
||||
|
||||
scm {
|
||||
connection = 'scm:git:https://github.com/3944Realms/lib39.git'
|
||||
developerConnection = 'scm:git:ssh://git@github.com:3944Realms/lib39.git'
|
||||
url = 'https://github.com/3944Realms/lib39'
|
||||
tag = 'main'
|
||||
}
|
||||
|
||||
issueManagement {
|
||||
system = 'GitHub'
|
||||
url = 'https://github.com/3944Realms/lib39/issues'
|
||||
}
|
||||
}
|
||||
def loaderAttribute = Attribute.of('io.github.mcgradleconventions.loader', String)
|
||||
['apiElements', 'runtimeElements', 'sourcesElements', 'javadocElements', 'includeInternal', 'modCompileClasspath'].each { variant ->
|
||||
configurations.named("$variant") {
|
||||
attributes {
|
||||
attribute(loaderAttribute, 'fabric')
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
test {
|
||||
useJUnitPlatform()
|
||||
}
|
||||
|
||||
tasks.named('generateMetadataFileForMavenJavaPublication') {
|
||||
dependsOn tasks.named('remapJavadocJar')
|
||||
dependsOn tasks.named('remapJar')
|
||||
dependsOn tasks.named('remapSourcesJar')
|
||||
}
|
||||
|
||||
sourceSets.configureEach {
|
||||
[it.compileClasspathConfigurationName, it.runtimeClasspathConfigurationName].each { variant->
|
||||
configurations.named("$variant") {
|
||||
attributes {
|
||||
attribute(loaderAttribute, 'fabric')
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -6,7 +6,7 @@ import net.fabricmc.fabric.api.event.EventFactory;
|
|||
import net.minecraft.commands.CommandBuildContext;
|
||||
import net.minecraft.commands.CommandSourceStack;
|
||||
import net.minecraft.network.chat.MutableComponent;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.resources.Identifier;
|
||||
import top.r3944realms.lib39.core.command.ICommandHelpManager;
|
||||
import top.r3944realms.lib39.core.command.model.CommandNode;
|
||||
import top.r3944realms.lib39.core.command.model.CommandPath;
|
||||
|
|
@ -50,7 +50,7 @@ public interface RegisterCommandHelpCallback {
|
|||
*
|
||||
* @return the id
|
||||
*/
|
||||
ResourceLocation getID();
|
||||
Identifier getID();
|
||||
|
||||
/**
|
||||
* Add child.
|
||||
|
|
@ -103,7 +103,7 @@ public interface RegisterCommandHelpCallback {
|
|||
*/
|
||||
record CommandHelpRegistrar(LiteralArgumentBuilder<CommandSourceStack> builder, ICommandHelpManager helpManager, CommandBuildContext context) implements Registrar {
|
||||
@Override
|
||||
public ResourceLocation getID() {
|
||||
public Identifier getID() {
|
||||
return helpManager.getID();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ package top.r3944realms.lib39.api.callback;
|
|||
import net.fabricmc.fabric.api.event.Event;
|
||||
import net.fabricmc.fabric.api.event.EventFactory;
|
||||
import net.fabricmc.fabric.api.lookup.v1.entity.EntityApiLookup;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.resources.Identifier;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import top.r3944realms.lib39.core.sync.ISyncData;
|
||||
|
|
@ -62,7 +62,7 @@ public interface SyncManagerRegisterCallback {
|
|||
* @param dataClass the data class
|
||||
*/
|
||||
<T extends ISyncData<?>> void register(
|
||||
ResourceLocation id,
|
||||
Identifier id,
|
||||
ISyncManager<Entity, T> syncManager,
|
||||
Class<T> dataClass
|
||||
);
|
||||
|
|
@ -73,7 +73,7 @@ public interface SyncManagerRegisterCallback {
|
|||
* @param id the id
|
||||
* @param entityClasses the entity classes
|
||||
*/
|
||||
void allowEntityClass(ResourceLocation id, Class<?>... entityClasses);
|
||||
void allowEntityClass(Identifier id, Class<?>... entityClasses);
|
||||
|
||||
/**
|
||||
* 移除允许的实体类
|
||||
|
|
@ -81,7 +81,7 @@ public interface SyncManagerRegisterCallback {
|
|||
* @param id the id
|
||||
* @param entityClasses the entity classes
|
||||
*/
|
||||
void disallowEntityClass(ResourceLocation id, Class<?>... entityClasses);
|
||||
void disallowEntityClass(Identifier id, Class<?>... entityClasses);
|
||||
|
||||
/**
|
||||
* 绑定 EntityApiLookup(用于分离注册的情况)
|
||||
|
|
@ -91,7 +91,7 @@ public interface SyncManagerRegisterCallback {
|
|||
* @param apiLookup the EntityApiLookup
|
||||
*/
|
||||
<T extends ISyncData<?>> void bindApiLookup(
|
||||
ResourceLocation id,
|
||||
Identifier id,
|
||||
net.fabricmc.fabric.api.lookup.v1.entity.EntityApiLookup<T, Void> apiLookup
|
||||
);
|
||||
|
||||
|
|
@ -100,7 +100,7 @@ public interface SyncManagerRegisterCallback {
|
|||
*
|
||||
* @param id the id
|
||||
*/
|
||||
void unbindApiLookup(ResourceLocation id);
|
||||
void unbindApiLookup(Identifier id);
|
||||
|
||||
/**
|
||||
* 完整的类型安全注册
|
||||
|
|
@ -112,7 +112,7 @@ public interface SyncManagerRegisterCallback {
|
|||
* @param allowedEntityClasses the allowed entity classes
|
||||
*/
|
||||
default <T extends ISyncData<?>> void registerComplete(
|
||||
ResourceLocation id,
|
||||
Identifier id,
|
||||
ISyncManager<Entity, T> syncManager,
|
||||
Class<T> dataClass,
|
||||
Class<?>... allowedEntityClasses
|
||||
|
|
@ -132,7 +132,7 @@ public interface SyncManagerRegisterCallback {
|
|||
|
||||
@Override
|
||||
public <T extends ISyncData<?>> void register(
|
||||
@NotNull ResourceLocation id,
|
||||
@NotNull Identifier id,
|
||||
@NotNull ISyncManager<Entity, T> syncManager,
|
||||
@NotNull Class<T> dataClass
|
||||
) {
|
||||
|
|
@ -140,25 +140,25 @@ public interface SyncManagerRegisterCallback {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void allowEntityClass(@NotNull ResourceLocation id, @NotNull Class<?>... entityClasses) {
|
||||
public void allowEntityClass(@NotNull Identifier id, @NotNull Class<?>... entityClasses) {
|
||||
manager.allowEntityClass(id, entityClasses);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void disallowEntityClass(@NotNull ResourceLocation id, @NotNull Class<?>... entityClasses) {
|
||||
public void disallowEntityClass(@NotNull Identifier id, @NotNull Class<?>... entityClasses) {
|
||||
manager.disallowEntityClass(id, entityClasses);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends ISyncData<?>> void bindApiLookup(
|
||||
@NotNull ResourceLocation id,
|
||||
@NotNull Identifier id,
|
||||
@NotNull EntityApiLookup<T, Void> apiLookup
|
||||
) {
|
||||
manager.bindApiLookup(id, apiLookup);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unbindApiLookup(@NotNull ResourceLocation id) {
|
||||
public void unbindApiLookup(@NotNull Identifier id) {
|
||||
manager.unbindApiLookup(id);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,11 +1,13 @@
|
|||
package top.r3944realms.lib39.base.compat.jade;
|
||||
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.resources.Identifier;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import snownee.jade.api.IWailaClientRegistration;
|
||||
import snownee.jade.api.IWailaPlugin;
|
||||
import snownee.jade.api.WailaPlugin;
|
||||
import top.r3944realms.lib39.Lib39;
|
||||
import top.r3944realms.lib39.base.compat.jade.provider.FabricDollComponentProvider;
|
||||
import top.r3944realms.lib39.content.block.AbstractDollBlock;
|
||||
import top.r3944realms.lib39.content.block.DollBlock;
|
||||
|
||||
/**
|
||||
|
|
@ -16,10 +18,10 @@ public class FabricJadePlugin implements IWailaPlugin {
|
|||
/**
|
||||
* The constant UID.
|
||||
*/
|
||||
public static final ResourceLocation UID = Lib39.rl("lib39");
|
||||
public static final Identifier UID = Lib39.rl("lib39");
|
||||
|
||||
@Override
|
||||
public void registerClient(IWailaClientRegistration registration) {
|
||||
registration.registerBlockComponent(new FabricDollComponentProvider(), DollBlock.class);
|
||||
public void registerClient(@NotNull IWailaClientRegistration registration) {
|
||||
registration.registerBlockComponent(new FabricDollComponentProvider(), AbstractDollBlock.class);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,8 @@ package top.r3944realms.lib39.base.compat.jade.provider;
|
|||
|
||||
import com.mojang.authlib.GameProfile;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.resources.Identifier;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import snownee.jade.api.BlockAccessor;
|
||||
import snownee.jade.api.IBlockComponentProvider;
|
||||
import snownee.jade.api.ITooltip;
|
||||
|
|
@ -15,17 +16,21 @@ import top.r3944realms.lib39.content.block.blockentity.DollBlockEntity;
|
|||
*/
|
||||
public class FabricDollComponentProvider implements IBlockComponentProvider {
|
||||
@Override
|
||||
public ResourceLocation getUid() {
|
||||
public Identifier getUid() {
|
||||
return FabricJadePlugin.UID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void appendTooltip(ITooltip iTooltip, BlockAccessor blockAccessor, IPluginConfig iPluginConfig) {
|
||||
public void appendTooltip(ITooltip iTooltip, @NotNull BlockAccessor blockAccessor, IPluginConfig iPluginConfig) {
|
||||
if (blockAccessor.getBlockEntity() instanceof DollBlockEntity doll) {
|
||||
GameProfile ownerProfile = doll.getOwnerProfile();
|
||||
if (ownerProfile != null) {
|
||||
iTooltip.add(Component.translatable("tooltip.lib39.content.doll.hover.1", ownerProfile.getName()));
|
||||
GameProfile ownerProfile;
|
||||
if (doll.getOwnerProfile() != null) {
|
||||
ownerProfile = doll.getOwnerProfile().gameProfile();
|
||||
if (ownerProfile != null) {
|
||||
iTooltip.add(Component.translatable("tooltip.lib39.content.doll.hover.1", ownerProfile.getName()));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,24 +9,30 @@ import net.fabricmc.fabric.api.itemgroup.v1.ItemGroupEvents;
|
|||
import net.fabricmc.fabric.api.lookup.v1.entity.EntityApiLookup;
|
||||
import net.minecraft.Util;
|
||||
import net.minecraft.client.multiplayer.ClientLevel;
|
||||
import net.minecraft.core.component.DataComponents;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.resources.ResourceKey;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.resources.Identifier;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.server.Services;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.item.CreativeModeTab;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.item.Items;
|
||||
import net.minecraft.world.item.component.ResolvableProfile;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.entity.SkullBlockEntity;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import top.r3944realms.lib39.Lib39;
|
||||
import top.r3944realms.lib39.api.callback.ActionResult;
|
||||
import top.r3944realms.lib39.api.callback.AnvilUpdateCallback;
|
||||
import top.r3944realms.lib39.api.callback.MinecraftSetUpServiceCallback;
|
||||
import top.r3944realms.lib39.api.callback.SyncManagerRegisterCallback;
|
||||
import top.r3944realms.lib39.api.callback.client.ClientWorldCallback;
|
||||
import top.r3944realms.lib39.base.command.Lib39HelpCommand;
|
||||
import top.r3944realms.lib39.content.block.blockentity.DollBlockEntity;
|
||||
import top.r3944realms.lib39.content.item.DollItem;
|
||||
import top.r3944realms.lib39.core.register.Lib39Items;
|
||||
import top.r3944realms.lib39.core.sync.ISyncData;
|
||||
|
|
@ -42,6 +48,7 @@ import java.util.ArrayList;
|
|||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
/**
|
||||
|
|
@ -115,8 +122,8 @@ public class FabricCommonEventHandler {
|
|||
public static void onServerTick(MinecraftServer server) {
|
||||
if (syncData2Manager == null) return;
|
||||
if (server.getTickCount() % 10 == 0)
|
||||
syncData2Manager.forEach(((resourceLocation, iSyncManager) -> iSyncManager.foreach(ISyncData::markDirty)));
|
||||
syncData2Manager.forEach(((resourceLocation, iSyncManager) -> iSyncManager.foreach(ISyncData::checkIfDirtyThenUpdate)));
|
||||
syncData2Manager.forEach(((Identifier, iSyncManager) -> iSyncManager.foreach(ISyncData::markDirty)));
|
||||
syncData2Manager.forEach(((Identifier, iSyncManager) -> iSyncManager.foreach(ISyncData::checkIfDirtyThenUpdate)));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -128,7 +135,7 @@ public class FabricCommonEventHandler {
|
|||
public static void onEntityJoinWorld(@NotNull Entity entity, ServerLevel level) {
|
||||
if (entity.level().isClientSide) return;
|
||||
|
||||
for (ResourceLocation id : syncData2Manager.getRegisteredKeys()) {
|
||||
for (Identifier id : syncData2Manager.getRegisteredKeys()) {
|
||||
if (syncData2Manager.isEntityClassAllowed(id, entity.getClass())) {
|
||||
syncData2Manager.trackEntityForManager(entity, id);
|
||||
}
|
||||
|
|
@ -144,7 +151,7 @@ public class FabricCommonEventHandler {
|
|||
public static void onEntityLeaveWorld(@NotNull Entity entity, ServerLevel level) {
|
||||
if (entity.level().isClientSide) return;
|
||||
|
||||
for (ResourceLocation id : syncData2Manager.getRegisteredKeys()) {
|
||||
for (Identifier id : syncData2Manager.getRegisteredKeys()) {
|
||||
if (syncData2Manager.isEntityClassAllowed(id, entity.getClass())) {
|
||||
syncData2Manager.untrackEntityForManager(entity, id);
|
||||
}
|
||||
|
|
@ -181,19 +188,35 @@ public class FabricCommonEventHandler {
|
|||
for (Map.Entry<ResourceKey<CreativeModeTab>, List<Supplier<Block>>> resourceKeyListEntry : tabToItemsMap.entrySet()) {
|
||||
ItemGroupEvents.modifyEntriesEvent(resourceKeyListEntry.getKey()).register(content -> resourceKeyListEntry.getValue().forEach(i -> content.accept(i.get())));
|
||||
}
|
||||
MinecraftSetUpServiceCallback.EVENT.register((services, mainThreadExecutor) -> {
|
||||
DollBlockEntity.setup(services, mainThreadExecutor);
|
||||
return ActionResult.SUCCESS;
|
||||
});
|
||||
AnvilUpdateCallback.EVENT.register((left, right, outputSlot, name, baseCost, player) -> {
|
||||
if (left.getItem() instanceof DollItem && name != null && name.length() < 15) {
|
||||
if (left.getItem() instanceof DollItem && name != null && !name.isEmpty() && name.length() <= 16) {
|
||||
ItemStack output = Lib39Items.DOLL.get().getDefaultInstance();
|
||||
output.setCount(left.getCount());
|
||||
|
||||
// 创建 ResolvableProfile
|
||||
GameProfile profile = new GameProfile(Util.NIL_UUID, name);
|
||||
ItemStack copied = Lib39Items.DOLL.get().getDefaultInstance();
|
||||
SkullBlockEntity.updateGameprofile(profile,
|
||||
profile1 -> GameProfileHelper.saveProfileToItemStack(copied, profile1)
|
||||
);
|
||||
copied.setCount(left.getCount());
|
||||
return AnvilUpdateCallback.AnvilUpdateResult.withOutput(copied, 1, 1);
|
||||
ResolvableProfile resolvableProfile = new ResolvableProfile(profile);
|
||||
output.set(DataComponents.PROFILE, resolvableProfile);
|
||||
|
||||
// 使用 DollBlockEntity 的缓存异步获取完整档案
|
||||
DollBlockEntity.fetchGameProfile(name).thenAcceptAsync(optional -> {
|
||||
optional.ifPresent(fullProfile -> {
|
||||
output.set(DataComponents.PROFILE, new ResolvableProfile(fullProfile));
|
||||
});
|
||||
}, SkullBlockEntity.CHECKED_MAIN_THREAD_EXECUTOR);
|
||||
|
||||
return AnvilUpdateCallback.AnvilUpdateResult.withOutput(output, 1, 1);
|
||||
} else if (name == null || name.isEmpty()) {
|
||||
return AnvilUpdateCallback.AnvilUpdateResult.withOutput(ItemStack.EMPTY, 0, 0);
|
||||
} else {
|
||||
ItemStack defaultInstance = Items.BARRIER.getDefaultInstance();
|
||||
defaultInstance.setHoverName(Component.translatable("invalid.player_name.too_long"));
|
||||
return AnvilUpdateCallback.AnvilUpdateResult.withOutput(defaultInstance, 0, 0);
|
||||
ItemStack errorOutput = Items.BARRIER.getDefaultInstance();
|
||||
errorOutput.set(DataComponents.CUSTOM_NAME,
|
||||
Component.translatable("invalid.player_name.too_long"));
|
||||
return AnvilUpdateCallback.AnvilUpdateResult.withOutput(errorOutput, 0, 0);
|
||||
}
|
||||
});
|
||||
EntityApiLookup.get(FabricTestSyncData.ID, AbstractedTestSyncData.class, Void.class)
|
||||
|
|
|
|||
|
|
@ -1,7 +1,8 @@
|
|||
package top.r3944realms.lib39.core.network;
|
||||
|
||||
import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking;
|
||||
import top.r3944realms.lib39.core.network.toClient.SyncNBTLookupDataEntityS2CPacket;
|
||||
import net.fabricmc.fabric.api.networking.v1.PayloadTypeRegistry;
|
||||
import top.r3944realms.lib39.core.network.toClient.SyncNBTLookupDataEntityS2CPayload;
|
||||
|
||||
/**
|
||||
* The type Fabric network handler.
|
||||
|
|
@ -12,10 +13,13 @@ public class FabricNetworkHandler {
|
|||
* 注册客户端接收的数据包
|
||||
*/
|
||||
public static void registerClientReceivers() {
|
||||
ClientPlayNetworking.registerGlobalReceiver(
|
||||
SyncNBTLookupDataEntityS2CPacket.TYPE,
|
||||
SyncNBTLookupDataEntityS2CPacket::receive
|
||||
PayloadTypeRegistry.playS2C().register(
|
||||
SyncNBTLookupDataEntityS2CPayload.TYPE,
|
||||
SyncNBTLookupDataEntityS2CPayload.STREAM_CODEC
|
||||
);
|
||||
ClientPlayNetworking.registerGlobalReceiver(
|
||||
SyncNBTLookupDataEntityS2CPayload.TYPE,
|
||||
SyncNBTLookupDataEntityS2CPayload::handle
|
||||
);
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,91 +0,0 @@
|
|||
package top.r3944realms.lib39.core.network.toClient;
|
||||
|
||||
import net.fabricmc.fabric.api.networking.v1.FabricPacket;
|
||||
import net.fabricmc.fabric.api.networking.v1.PacketSender;
|
||||
import net.fabricmc.fabric.api.networking.v1.PacketType;
|
||||
import net.minecraft.client.player.LocalPlayer;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.level.Level;
|
||||
import org.jetbrains.annotations.Contract;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import top.r3944realms.lib39.Lib39;
|
||||
import top.r3944realms.lib39.core.event.FabricCommonEventHandler;
|
||||
import top.r3944realms.lib39.core.sync.ISyncData;
|
||||
import top.r3944realms.lib39.core.sync.NBTEntitySyncData;
|
||||
import top.r3944realms.lib39.core.sync.SyncData2Manager;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* The type Sync nbt lookup data entity s 2 c packet.
|
||||
*/
|
||||
public record SyncNBTLookupDataEntityS2CPacket(int entityId, ResourceLocation id, CompoundTag data) implements FabricPacket {
|
||||
/**
|
||||
* The constant SYNC_NBT_LOOKUP_PACKET_ID.
|
||||
*/
|
||||
public static final ResourceLocation SYNC_NBT_LOOKUP_PACKET_ID =
|
||||
Lib39.rl("sync_nbt_lookup_data_entity");
|
||||
/**
|
||||
* The constant TYPE.
|
||||
*/
|
||||
public static final PacketType<SyncNBTLookupDataEntityS2CPacket> TYPE = PacketType.create(
|
||||
SYNC_NBT_LOOKUP_PACKET_ID,
|
||||
buf -> new SyncNBTLookupDataEntityS2CPacket(buf.readInt(), buf.readResourceLocation(), buf.readNbt())
|
||||
);
|
||||
|
||||
/**
|
||||
* Instantiates a new Sync nbt data s 2 c pack.
|
||||
*
|
||||
* @param entityId the entity id
|
||||
* @param data the data
|
||||
*/
|
||||
public SyncNBTLookupDataEntityS2CPacket(int entityId, @NotNull NBTEntitySyncData data) {
|
||||
this(entityId, data.id(), data.serializeNBT());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(@NotNull FriendlyByteBuf friendlyByteBuf) {
|
||||
friendlyByteBuf.writeInt(entityId);
|
||||
friendlyByteBuf.writeResourceLocation(id);
|
||||
friendlyByteBuf.writeNbt(data);
|
||||
}
|
||||
|
||||
@Contract(value = " -> new", pure = true)
|
||||
@Override
|
||||
public @NotNull PacketType<?> getType() {
|
||||
return TYPE;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Receive.
|
||||
*
|
||||
* @param packet the packet
|
||||
* @param localPlayer the local player
|
||||
* @param packetSender the packet sender
|
||||
*/
|
||||
public static void receive(@NotNull SyncNBTLookupDataEntityS2CPacket packet, @NotNull LocalPlayer localPlayer, PacketSender packetSender) {
|
||||
Level level = localPlayer.level();
|
||||
Entity entity = level.getEntity(packet.entityId);
|
||||
if (entity != null) {
|
||||
Optional<SyncData2Manager.DataProvider<Entity, ISyncData<?>>> lookupOpt =
|
||||
FabricCommonEventHandler
|
||||
.getSyncData2Manager()
|
||||
.getDataProvider(packet.id);
|
||||
lookupOpt.flatMap(dataProvider -> dataProvider.getData(entity))
|
||||
.ifPresent(lookup -> {
|
||||
if (lookup instanceof NBTEntitySyncData nbtLookup) {
|
||||
CompoundTag current = nbtLookup.serializeNBT();
|
||||
if (!current.equals(packet.data)) {
|
||||
nbtLookup.deserializeNBT(packet.data);
|
||||
}
|
||||
} else Lib39.LOGGER.debug("Unhandled sync data: {}", packet.data);
|
||||
}
|
||||
);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,109 @@
|
|||
package top.r3944realms.lib39.core.network.toClient;
|
||||
|
||||
import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking;
|
||||
import net.minecraft.client.player.LocalPlayer;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import net.minecraft.network.RegistryFriendlyByteBuf;
|
||||
import net.minecraft.network.codec.StreamCodec;
|
||||
import net.minecraft.network.protocol.common.custom.CustomPacketPayload;
|
||||
import net.minecraft.resources.Identifier;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.level.Level;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import top.r3944realms.lib39.Lib39;
|
||||
import top.r3944realms.lib39.core.event.FabricCommonEventHandler;
|
||||
import top.r3944realms.lib39.core.sync.ISyncData;
|
||||
import top.r3944realms.lib39.core.sync.NBTEntitySyncData;
|
||||
import top.r3944realms.lib39.core.sync.SyncData2Manager;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* The type Sync nbt lookup data entity s 2 c payload.
|
||||
*/
|
||||
public record SyncNBTLookupDataEntityS2CPayload(int entityId, Identifier id, CompoundTag data) implements CustomPacketPayload {
|
||||
/**
|
||||
* The constant SYNC_NBT_LOOKUP_PACKET_ID.
|
||||
*/
|
||||
public static final Identifier SYNC_NBT_LOOKUP_PACKET_ID =
|
||||
Lib39.rl("sync_nbt_lookup_data_entity");
|
||||
/**
|
||||
* The constant TYPE.
|
||||
*/
|
||||
public static final Type<SyncNBTLookupDataEntityS2CPayload> TYPE = new Type<>(SYNC_NBT_LOOKUP_PACKET_ID);
|
||||
|
||||
/**
|
||||
* Stream codec for serializing/deserializing the packet.
|
||||
*/
|
||||
public static final StreamCodec<RegistryFriendlyByteBuf, SyncNBTLookupDataEntityS2CPayload> STREAM_CODEC =
|
||||
StreamCodec.ofMember(SyncNBTLookupDataEntityS2CPayload::write, SyncNBTLookupDataEntityS2CPayload::new);
|
||||
|
||||
|
||||
/**
|
||||
* Instantiates a new Sync nbt data s 2 c pack.
|
||||
*
|
||||
* @param entityId the entity id
|
||||
* @param data the data
|
||||
*/
|
||||
public SyncNBTLookupDataEntityS2CPayload(int entityId, @NotNull NBTEntitySyncData data) {
|
||||
this(entityId, data.id(), data.serializeNBT());
|
||||
}
|
||||
|
||||
/**
|
||||
* Instantiates from buffer.
|
||||
*
|
||||
* @param buf the buffer
|
||||
*/
|
||||
public SyncNBTLookupDataEntityS2CPayload(RegistryFriendlyByteBuf buf) {
|
||||
this(buf.readInt(), buf.readIdentifier(), buf.readNbt());
|
||||
}
|
||||
|
||||
/**
|
||||
* Write.
|
||||
*
|
||||
* @param friendlyByteBuf the friendly byte buf
|
||||
*/
|
||||
public void write(@NotNull FriendlyByteBuf friendlyByteBuf) {
|
||||
friendlyByteBuf.writeInt(entityId);
|
||||
friendlyByteBuf.writeIdentifier(id);
|
||||
friendlyByteBuf.writeNbt(data);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Receive.
|
||||
*
|
||||
* @param payload the packet
|
||||
* @param context the context
|
||||
*/
|
||||
public static void handle(@NotNull SyncNBTLookupDataEntityS2CPayload payload, ClientPlayNetworking.Context context) {
|
||||
LocalPlayer localPlayer = context.player();
|
||||
Level level = localPlayer.level();
|
||||
Entity entity = level.getEntity(payload.entityId);
|
||||
|
||||
if (entity != null) {
|
||||
Optional<SyncData2Manager.DataProvider<Entity, ISyncData<?>>> lookupOpt =
|
||||
FabricCommonEventHandler
|
||||
.getSyncData2Manager()
|
||||
.getDataProvider(payload.id);
|
||||
|
||||
lookupOpt.flatMap(dataProvider -> dataProvider.getData(entity))
|
||||
.ifPresent(lookup -> {
|
||||
if (lookup instanceof NBTEntitySyncData nbtLookup) {
|
||||
CompoundTag current = nbtLookup.serializeNBT();
|
||||
if (!current.equals(payload.data)) {
|
||||
nbtLookup.deserializeNBT(payload.data);
|
||||
}
|
||||
} else {
|
||||
Lib39.LOGGER.debug("Unhandled sync data: {}", payload.data);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Type<? extends CustomPacketPayload> type() {
|
||||
return TYPE;
|
||||
}
|
||||
}
|
||||
|
|
@ -5,7 +5,7 @@ import net.minecraft.server.level.ServerLevel;
|
|||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.server.players.PlayerList;
|
||||
import top.r3944realms.lib39.core.event.FabricCommonEventHandler;
|
||||
import top.r3944realms.lib39.core.network.toClient.SyncNBTLookupDataEntityS2CPacket;
|
||||
import top.r3944realms.lib39.core.network.toClient.SyncNBTLookupDataEntityS2CPayload;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
|
|
@ -19,8 +19,8 @@ public interface IFabricUpdate extends IUpdate {
|
|||
PlayerList playerList = serverLevel.getServer().getPlayerList();
|
||||
List<ServerPlayer> players = playerList.getPlayers();
|
||||
for (ServerPlayer player : players) {
|
||||
if (ServerPlayNetworking.canSend(player, SyncNBTLookupDataEntityS2CPacket.TYPE)) {
|
||||
ServerPlayNetworking.send(player, new SyncNBTLookupDataEntityS2CPacket(getSyncData().entityId(), getSyncData()));
|
||||
if (ServerPlayNetworking.canSend(player, SyncNBTLookupDataEntityS2CPayload.TYPE)) {
|
||||
ServerPlayNetworking.send(player, new SyncNBTLookupDataEntityS2CPayload(getSyncData().entityId(), getSyncData()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ package top.r3944realms.lib39.core.sync;
|
|||
|
||||
import com.google.common.collect.Maps;
|
||||
import net.fabricmc.fabric.api.lookup.v1.entity.EntityApiLookup;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.resources.Identifier;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
|
|
@ -17,10 +17,10 @@ public class SyncData2LookupManager extends SyncData2Manager<SyncData2LookupMana
|
|||
/**
|
||||
* The Typed entries.
|
||||
*/
|
||||
protected final Map<ResourceLocation, TypedSyncEntry<?>> typedEntries = Maps.newConcurrentMap();
|
||||
protected final Map<Identifier, TypedSyncEntry<?>> typedEntries = Maps.newConcurrentMap();
|
||||
|
||||
@Override
|
||||
protected Map<ResourceLocation, TypedSyncEntry<?>> getTypedEntries() {
|
||||
protected Map<Identifier, TypedSyncEntry<?>> getTypedEntries() {
|
||||
return typedEntries;
|
||||
}
|
||||
|
||||
|
|
@ -57,11 +57,11 @@ public class SyncData2LookupManager extends SyncData2Manager<SyncData2LookupMana
|
|||
* @param dataClass the data class
|
||||
*/
|
||||
public <T extends ISyncData<?>> void registerManager(
|
||||
ResourceLocation key,
|
||||
Identifier key,
|
||||
ISyncManager<Entity, T> manager,
|
||||
Class<T> dataClass
|
||||
) {
|
||||
Objects.requireNonNull(key, "ResourceLocation key cannot be null");
|
||||
Objects.requireNonNull(key, "Identifier key cannot be null");
|
||||
Objects.requireNonNull(manager, "Sync manager cannot be null");
|
||||
Objects.requireNonNull(dataClass, "Data class cannot be null");
|
||||
|
||||
|
|
@ -77,8 +77,8 @@ public class SyncData2LookupManager extends SyncData2Manager<SyncData2LookupMana
|
|||
* @param key the key
|
||||
* @param apiLookup the EntityApiLookup
|
||||
*/
|
||||
public <T extends ISyncData<?>> void bindApiLookup(ResourceLocation key, EntityApiLookup<T, Void> apiLookup) {
|
||||
Objects.requireNonNull(key, "ResourceLocation key cannot be null");
|
||||
public <T extends ISyncData<?>> void bindApiLookup(Identifier key, EntityApiLookup<T, Void> apiLookup) {
|
||||
Objects.requireNonNull(key, "Identifier key cannot be null");
|
||||
Objects.requireNonNull(apiLookup, "EntityApiLookup cannot be null");
|
||||
|
||||
TypedSyncEntry<?> entry = typedEntries.get(key);
|
||||
|
|
@ -94,8 +94,8 @@ public class SyncData2LookupManager extends SyncData2Manager<SyncData2LookupMana
|
|||
*
|
||||
* @param key the key
|
||||
*/
|
||||
public void unbindApiLookup(ResourceLocation key) {
|
||||
Objects.requireNonNull(key, "ResourceLocation key cannot be null");
|
||||
public void unbindApiLookup(Identifier key) {
|
||||
Objects.requireNonNull(key, "Identifier key cannot be null");
|
||||
|
||||
TypedSyncEntry<?> entry = typedEntries.get(key);
|
||||
if (entry != null) {
|
||||
|
|
@ -112,7 +112,7 @@ public class SyncData2LookupManager extends SyncData2Manager<SyncData2LookupMana
|
|||
* @param newApiLookup the new api lookup
|
||||
*/
|
||||
protected <T extends ISyncData<?>> void updateApiLookupInEntry(
|
||||
ResourceLocation id,
|
||||
Identifier id,
|
||||
TypedSyncEntry<?> entry,
|
||||
EntityApiLookup<T, Void> newApiLookup
|
||||
) {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
package top.r3944realms.lib39.core.sync;
|
||||
|
||||
import net.fabricmc.fabric.api.lookup.v1.entity.EntityApiLookup;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.resources.Identifier;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import top.r3944realms.lib39.core.event.FabricCommonEventHandler;
|
||||
|
|
@ -25,7 +25,7 @@ public abstract class SyncLookupProvider<T extends NBTEntitySyncData> implements
|
|||
*
|
||||
* @return the id
|
||||
*/
|
||||
protected abstract ResourceLocation getId();
|
||||
protected abstract Identifier getId();
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public @Nullable T find(Entity entity, Void context) {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
package top.r3944realms.lib39.example;
|
||||
|
||||
import top.r3944realms.lib39.core.compat.CompatManager;
|
||||
import top.r3944realms.lib39.core.compat.ICompatManager;
|
||||
import top.r3944realms.lib39.example.core.compat.FabricLib39Compat;
|
||||
import top.r3944realms.lib39.example.core.event.FabricExCommonEventHandler;
|
||||
import top.r3944realms.lib39.example.core.network.FabricExNetworkHandler;
|
||||
|
|
@ -29,7 +29,7 @@ public class FabricLib39Example {
|
|||
FabricExCommonEventHandler.init();
|
||||
FabricExLib39Items.init();
|
||||
FabricExNetworkHandler.registerServerReceivers();
|
||||
CompatManager orCreateCompatManager = FabricExCommonEventHandler.getOrCreateCompatManager();
|
||||
ICompatManager orCreateCompatManager = FabricExCommonEventHandler.getOrCreateCompatManager();
|
||||
orCreateCompatManager.registerCompat(FabricLib39Compat.ID, FabricLib39Compat.INSTANCE);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2,14 +2,14 @@ package top.r3944realms.lib39.example.content.data;
|
|||
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.resources.Identifier;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import org.jetbrains.annotations.Contract;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import top.r3944realms.lib39.Lib39;
|
||||
import top.r3944realms.lib39.core.sync.IFabricUpdate;
|
||||
import top.r3944realms.lib39.util.nbt.NBTReader;
|
||||
import top.r3944realms.lib39.util.nbt.NBTWriter;
|
||||
import top.r3944realms.lib39.util.storage.nbt.NBTReader;
|
||||
import top.r3944realms.lib39.util.storage.nbt.NBTWriter;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
|
@ -23,7 +23,7 @@ public class FabricTestSyncData extends AbstractedTestSyncData implements IFabri
|
|||
/**
|
||||
* The constant ID.
|
||||
*/
|
||||
public static final ResourceLocation ID = Lib39.rl(Lib39.MOD_ID, "test_sync_data");
|
||||
public static final Identifier ID = Lib39.rl(Lib39.MOD_ID, "test_sync_data");
|
||||
|
||||
// NBT 键常量
|
||||
private static final String NBT_KEY_STRING = "test_string";
|
||||
|
|
@ -290,8 +290,8 @@ public class FabricTestSyncData extends AbstractedTestSyncData implements IFabri
|
|||
}
|
||||
|
||||
@Override
|
||||
public void deserializeNBT(CompoundTag nbt) {
|
||||
NBTReader.of(nbt)
|
||||
public void deserializeNBT(CompoundTag t) {
|
||||
NBTReader.of(t)
|
||||
.intValue(NBT_KEY_INT, integer -> testInt = integer)
|
||||
.string(NBT_KEY_STRING, string -> testString = string)
|
||||
.booleanValue(NBT_KEY_BOOLEAN, bool -> testBoolean = bool)
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
package top.r3944realms.lib39.example.content.data;
|
||||
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.resources.Identifier;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import top.r3944realms.lib39.core.sync.SyncLookupProvider;
|
||||
|
||||
|
|
@ -19,7 +19,7 @@ public class FabricTestSyncLookupProvider extends SyncLookupProvider<AbstractedT
|
|||
}
|
||||
|
||||
@Override
|
||||
protected ResourceLocation getId() {
|
||||
protected Identifier getId() {
|
||||
return FabricTestSyncData.ID;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
package top.r3944realms.lib39.example.core.compat;
|
||||
|
||||
import net.fabricmc.loader.api.FabricLoader;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.resources.Identifier;
|
||||
import top.r3944realms.lib39.Lib39;
|
||||
import top.r3944realms.lib39.core.compat.ICompat;
|
||||
|
||||
|
|
@ -20,7 +20,7 @@ public class FabricLib39Compat implements ICompat {
|
|||
/**
|
||||
* The constant ID.
|
||||
*/
|
||||
public static ResourceLocation ID = Lib39.rl("lib39");
|
||||
public static Identifier ID = Lib39.rl("lib39");
|
||||
|
||||
@Override
|
||||
public void setInitialize(boolean initialize) {
|
||||
|
|
@ -33,7 +33,7 @@ public class FabricLib39Compat implements ICompat {
|
|||
}
|
||||
|
||||
@Override
|
||||
public ResourceLocation id() {
|
||||
public Identifier id() {
|
||||
return ID;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,12 +1,19 @@
|
|||
package top.r3944realms.lib39.example.core.compat;
|
||||
|
||||
import net.minecraft.resources.Identifier;
|
||||
import top.r3944realms.lib39.Lib39;
|
||||
import top.r3944realms.lib39.core.compat.CompatManager;
|
||||
import top.r3944realms.lib39.core.compat.ICompat;
|
||||
import top.r3944realms.lib39.core.compat.SimpleCompatManager;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* The type Fabric lib 39 compat manager.
|
||||
*/
|
||||
public class FabricLib39CompatManager extends CompatManager {
|
||||
public class FabricLib39CompatManager extends SimpleCompatManager {
|
||||
|
||||
/**
|
||||
* Instantiates a new Compat manager.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import net.minecraft.world.entity.Entity;
|
|||
import net.minecraft.world.entity.LivingEntity;
|
||||
import top.r3944realms.lib39.api.callback.ActionResult;
|
||||
import top.r3944realms.lib39.api.callback.SyncManagerRegisterCallback;
|
||||
import top.r3944realms.lib39.core.compat.CompatManager;
|
||||
import top.r3944realms.lib39.core.compat.ICompatManager;
|
||||
import top.r3944realms.lib39.core.event.FabricCommonEventHandler;
|
||||
import top.r3944realms.lib39.core.sync.CachedSyncManager;
|
||||
import top.r3944realms.lib39.example.content.data.AbstractedTestSyncData;
|
||||
|
|
@ -23,7 +23,7 @@ public class FabricExCommonEventHandler {
|
|||
*
|
||||
* @return the compat manager
|
||||
*/
|
||||
public static CompatManager getOrCreateCompatManager() {
|
||||
public static ICompatManager getOrCreateCompatManager() {
|
||||
if (compatManager == null) {
|
||||
synchronized (FabricCommonEventHandler.class) {
|
||||
if (compatManager == null) {
|
||||
|
|
@ -37,7 +37,7 @@ public class FabricExCommonEventHandler {
|
|||
/**
|
||||
* The Compat manager.
|
||||
*/
|
||||
static volatile CompatManager compatManager;
|
||||
static volatile ICompatManager compatManager;
|
||||
|
||||
/**
|
||||
* Init.
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
package top.r3944realms.lib39.example.core.network;
|
||||
|
||||
import net.fabricmc.fabric.api.networking.v1.FabricPacket;
|
||||
import net.fabricmc.fabric.api.networking.v1.PacketSender;
|
||||
import net.fabricmc.fabric.api.networking.v1.PacketType;
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking;
|
||||
import net.minecraft.network.RegistryFriendlyByteBuf;
|
||||
import net.minecraft.network.codec.StreamCodec;
|
||||
import net.minecraft.network.protocol.common.custom.CustomPacketPayload;
|
||||
import net.minecraft.resources.Identifier;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import top.r3944realms.lib39.Lib39;
|
||||
|
|
@ -15,63 +15,59 @@ import top.r3944realms.lib39.example.content.item.FabricFabricItem;
|
|||
/**
|
||||
* The type Client data packet.
|
||||
*/
|
||||
public class FabricClientDataPacket implements FabricPacket {
|
||||
public record FabricClientDataPacket(AbstractedTestSyncData clientData, int targetEntityId) implements CustomPacketPayload {
|
||||
/**
|
||||
* The constant CLIENT_TEST_DATA.
|
||||
*/
|
||||
public static final ResourceLocation CLIENT_TEST_DATA =
|
||||
public static final Identifier CLIENT_TEST_DATA =
|
||||
Lib39.rl("client_test_data");
|
||||
|
||||
/**
|
||||
* The constant TYPE.
|
||||
*/
|
||||
public static final PacketType<FabricClientDataPacket> TYPE = PacketType.create(
|
||||
CLIENT_TEST_DATA,
|
||||
FabricClientDataPacket::new
|
||||
);
|
||||
private final AbstractedTestSyncData clientData;
|
||||
private final int targetEntityId;
|
||||
public static final CustomPacketPayload.Type<FabricClientDataPacket> TYPE =
|
||||
new CustomPacketPayload.Type<>(CLIENT_TEST_DATA);
|
||||
|
||||
/**
|
||||
* Instantiates a new Client data packet.
|
||||
*
|
||||
* @param clientData the client data
|
||||
* @param targetEntityId the target entity id
|
||||
* Stream codec for serializing/deserializing the packet.
|
||||
*/
|
||||
public FabricClientDataPacket(AbstractedTestSyncData clientData, int targetEntityId) {
|
||||
this.clientData = clientData;
|
||||
this.targetEntityId = targetEntityId;
|
||||
public static final StreamCodec<RegistryFriendlyByteBuf, FabricClientDataPacket> STREAM_CODEC =
|
||||
StreamCodec.ofMember(FabricClientDataPacket::write, FabricClientDataPacket::new);
|
||||
|
||||
/**
|
||||
* Instantiates a new Client data packet from buffer.
|
||||
*
|
||||
* @param buf the buffer
|
||||
*/
|
||||
public FabricClientDataPacket(RegistryFriendlyByteBuf buf) {
|
||||
this(FabricTestSyncData.staticFromBytes(buf), buf.readInt());
|
||||
}
|
||||
|
||||
/**
|
||||
* Instantiates a new Client data packet.
|
||||
* Write packet data to buffer.
|
||||
*
|
||||
* @param buf the buf
|
||||
* @param buf the buffer
|
||||
*/
|
||||
public FabricClientDataPacket(FriendlyByteBuf buf) {
|
||||
this.clientData = FabricTestSyncData.staticFromBytes(buf);
|
||||
this.targetEntityId = buf.readInt();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void write(FriendlyByteBuf buf) {
|
||||
public void write(RegistryFriendlyByteBuf buf) {
|
||||
clientData.toBytes(buf);
|
||||
buf.writeInt(targetEntityId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PacketType<?> getType() {
|
||||
public @NotNull Type<? extends CustomPacketPayload> type() {
|
||||
return TYPE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Receive.
|
||||
* Handle packet on server side.
|
||||
* Register this with ServerPlayNetworking.registerGlobalReceiver
|
||||
*
|
||||
* @param packet the packet
|
||||
* @param serverPlayer the server player
|
||||
* @param packetSender the packet sender
|
||||
* @param packet the packet
|
||||
* @param context the context
|
||||
*/
|
||||
public static void receive(@NotNull FabricClientDataPacket packet, @NotNull ServerPlayer serverPlayer, PacketSender packetSender) {
|
||||
public static void handle(FabricClientDataPacket packet, ServerPlayNetworking.Context context) {
|
||||
ServerPlayer serverPlayer = context.player();
|
||||
// PacketSender is no longer needed, use context.responseSender() if needed
|
||||
FabricFabricItem.handleClientDataFromPacket(serverPlayer, packet.clientData, packet.targetEntityId);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,5 +1,6 @@
|
|||
package top.r3944realms.lib39.example.core.network;
|
||||
|
||||
import net.fabricmc.fabric.api.networking.v1.PayloadTypeRegistry;
|
||||
import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking;
|
||||
|
||||
/**
|
||||
|
|
@ -10,9 +11,13 @@ public class FabricExNetworkHandler {
|
|||
* 注册服务器接收的数据包
|
||||
*/
|
||||
public static void registerServerReceivers() {
|
||||
PayloadTypeRegistry.playC2S().register(
|
||||
FabricClientDataPacket.TYPE,
|
||||
FabricClientDataPacket.STREAM_CODEC
|
||||
);
|
||||
ServerPlayNetworking.registerGlobalReceiver(
|
||||
FabricClientDataPacket.TYPE,
|
||||
FabricClientDataPacket::receive
|
||||
FabricClientDataPacket::handle
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,12 +5,15 @@ import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
|
|||
import com.llamalad7.mixinextras.sugar.Local;
|
||||
import com.mojang.blaze3d.platform.WindowEventHandler;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.screens.ReceivingLevelScreen;
|
||||
import net.minecraft.client.gui.screens.Screen;
|
||||
import net.minecraft.client.multiplayer.ClientLevel;
|
||||
import net.minecraft.server.Services;
|
||||
import net.minecraft.server.WorldStem;
|
||||
import net.minecraft.server.packs.repository.PackRepository;
|
||||
import net.minecraft.util.thread.ReentrantBlockableEventLoop;
|
||||
import net.minecraft.world.level.storage.LevelStorageSource;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
|
|
@ -19,8 +22,6 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
|||
import top.r3944realms.lib39.api.callback.MinecraftSetUpServiceCallback;
|
||||
import top.r3944realms.lib39.api.callback.client.ClientWorldCallback;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* The type Mixin minecraft.
|
||||
*/
|
||||
|
|
@ -29,7 +30,8 @@ public abstract class MixinMinecraft extends ReentrantBlockableEventLoop<Runnabl
|
|||
/**
|
||||
* The Level.
|
||||
*/
|
||||
@Shadow @Nullable public ClientLevel level;
|
||||
@Shadow @Nullable
|
||||
public ClientLevel level;
|
||||
|
||||
/**
|
||||
* Instantiates a new Mixin minecraft.
|
||||
|
|
@ -41,34 +43,37 @@ public abstract class MixinMinecraft extends ReentrantBlockableEventLoop<Runnabl
|
|||
}
|
||||
|
||||
/**
|
||||
* Set level callback.
|
||||
* Set clientLevel callback.
|
||||
*
|
||||
* @param levelClient the level client
|
||||
* @param clientLevel the clientLevel client
|
||||
* @param reason the reason
|
||||
* @param original the original
|
||||
*/
|
||||
@WrapMethod(method = "setLevel")
|
||||
public void setLevel$callback(ClientLevel levelClient, Operation<Void> original) {
|
||||
if (levelClient != null) ClientWorldCallback.UNLOAD.invoker().onWorldUnload(levelClient);
|
||||
original.call(levelClient);
|
||||
public void setLevel$callback(ClientLevel clientLevel, ReceivingLevelScreen.Reason reason, Operation<Void> original) {
|
||||
if (clientLevel != null) ClientWorldCallback.UNLOAD.invoker().onWorldUnload(clientLevel);
|
||||
original.call(clientLevel, reason);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear level callback.
|
||||
*
|
||||
* @param original the original
|
||||
* @param nextScreen the next screen
|
||||
* @param original the original
|
||||
*/
|
||||
@WrapMethod(method = "clearLevel()V")
|
||||
public void clearLevel$callback(Operation<Void> original) {
|
||||
@WrapMethod(method = "clearClientLevel")
|
||||
public void clearLevel$callback(Screen nextScreen, Operation<Void> original) {
|
||||
if (level != null) ClientWorldCallback.UNLOAD.invoker().onWorldUnload(level);
|
||||
original.call();
|
||||
original.call(nextScreen);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set level setup.
|
||||
*
|
||||
* @param levelClient the level client
|
||||
* @param ci the ci
|
||||
* @param services the services
|
||||
* @param level the level client
|
||||
* @param reason the reason
|
||||
* @param ci the ci
|
||||
* @param services the services
|
||||
*/
|
||||
@Inject(
|
||||
method = "setLevel",
|
||||
|
|
@ -78,16 +83,14 @@ public abstract class MixinMinecraft extends ReentrantBlockableEventLoop<Runnabl
|
|||
shift = At.Shift.AFTER
|
||||
)
|
||||
)
|
||||
public void setLevel$setup(ClientLevel levelClient, CallbackInfo ci,
|
||||
@Local(ordinal = 0) Services services) {
|
||||
public void setLevel$setup(ClientLevel level, ReceivingLevelScreen.Reason reason, CallbackInfo ci, @Local(ordinal = 0) Services services) {
|
||||
MinecraftSetUpServiceCallback.EVENT.invoker().load(services,this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Do world load setup.
|
||||
*
|
||||
* @param levelId the level id
|
||||
* @param level the level
|
||||
* @param levelStorage the level id
|
||||
* @param packRepository the pack repository
|
||||
* @param worldStem the world stem
|
||||
* @param newWorld the new world
|
||||
|
|
@ -102,8 +105,7 @@ public abstract class MixinMinecraft extends ReentrantBlockableEventLoop<Runnabl
|
|||
shift = At.Shift.AFTER
|
||||
)
|
||||
)
|
||||
public void doWorldLoad$setup(String levelId, LevelStorageSource.LevelStorageAccess level, PackRepository packRepository, WorldStem worldStem, boolean newWorld, CallbackInfo ci,
|
||||
@Local(ordinal = 0) Services services) {
|
||||
public void doWorldLoad$setup(LevelStorageSource.LevelStorageAccess levelStorage, PackRepository packRepository, WorldStem worldStem, boolean newWorld, CallbackInfo ci, @Local(ordinal = 0) Services services) {
|
||||
MinecraftSetUpServiceCallback.EVENT.invoker().load(services,this);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
package top.r3944realms.lib39.platform;
|
||||
|
||||
import top.r3944realms.lib39.core.event.FabricCommonEventHandler;
|
||||
import top.r3944realms.lib39.core.sync.SyncData2Manager;
|
||||
import top.r3944realms.lib39.platform.services.IUtilHelper;
|
||||
import top.r3944realms.lib39.util.FabricBlockRegistryBuilder;
|
||||
import top.r3944realms.lib39.util.block.BlockRegistryBuilder;
|
||||
|
|
@ -16,4 +18,9 @@ public enum FabricUtilHelper implements IUtilHelper {
|
|||
public BlockRegistryBuilder getBlockRegistryBuilder() {
|
||||
return new FabricBlockRegistryBuilder();
|
||||
}
|
||||
|
||||
@Override
|
||||
public SyncData2Manager<?> getSyncData2Manager() {
|
||||
return FabricCommonEventHandler.getSyncData2Manager();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,8 +8,8 @@
|
|||
"${mod_author}"
|
||||
],
|
||||
"contact": {
|
||||
"homepage": "https://github.com/3944Realms",
|
||||
"sources": "https://github.com/3944Realms/Lib39"
|
||||
"homepage": "https://gitea.bot.leisuretimedock.top/3944Realms",
|
||||
"sources": "https://gitea.bot.leisuretimedock.top/3944Realms/Lib39"
|
||||
},
|
||||
"license": "${license}",
|
||||
"icon": "lib39_logo.png",
|
||||
|
|
|
|||
|
|
@ -3,18 +3,17 @@
|
|||
"minVersion": "0.8",
|
||||
"package": "top.r3944realms.lib39.mixin",
|
||||
"refmap": "${mod_id}.fabric.refmap.json",
|
||||
"compatibilityLevel": "JAVA_17",
|
||||
"compatibilityLevel": "JAVA_18",
|
||||
"mixins": [
|
||||
"MixinApiLookUpImpl",
|
||||
"MixinEntity",
|
||||
"callback.MixinAnvilMenu",
|
||||
"callback.MixinDedicateServer"
|
||||
"callback.MixinAnvilMenu"
|
||||
],
|
||||
"client": [
|
||||
"callback.MixinMinecraft",
|
||||
"callback.client.MixinClientLevel"
|
||||
],
|
||||
"server": [
|
||||
"callback.MixinDedicateServer"
|
||||
],
|
||||
"injectors": {
|
||||
"defaultRequire": 1
|
||||
|
|
|
|||
|
|
@ -1,60 +0,0 @@
|
|||
package top.r3944realms.lib39;
|
||||
|
||||
import net.minecraftforge.eventbus.api.IEventBus;
|
||||
import net.minecraftforge.fml.common.Mod;
|
||||
import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;
|
||||
import top.r3944realms.lib39.core.network.NetworkHandler;
|
||||
import top.r3944realms.lib39.core.register.ForgeLib39BlockEntities;
|
||||
import top.r3944realms.lib39.core.register.ForgeLib39Blocks;
|
||||
import top.r3944realms.lib39.core.register.ForgeLib39Items;
|
||||
import top.r3944realms.lib39.core.register.ForgeLib39SoundEvents;
|
||||
import top.r3944realms.lib39.example.ForgeLib39Example;
|
||||
|
||||
/**
|
||||
* The type Lib 39.
|
||||
*/
|
||||
@Mod(Lib39.MOD_ID)
|
||||
public class Lib39Forge {
|
||||
/**
|
||||
* Instantiates a new Lib 39.
|
||||
*/
|
||||
public Lib39Forge() {
|
||||
Lib39.initialize();
|
||||
initialize();
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize.
|
||||
*/
|
||||
public static void initialize() {
|
||||
Lib39.LOGGER.info("[Lib39-Forge] Hello Forge");
|
||||
IEventBus modEventBus = FMLJavaModLoadingContext.get().getModEventBus();
|
||||
ForgeLib39Blocks.register(modEventBus);
|
||||
ForgeLib39Items.register(modEventBus);
|
||||
ForgeLib39BlockEntities.register(modEventBus);
|
||||
ForgeLib39SoundEvents.register(modEventBus);
|
||||
NetworkHandler.register();
|
||||
if (Lib39.shouldRegisterExamples()) {
|
||||
Lib39.LOGGER.info("[Lib39-Forge] Registering Examples");
|
||||
registerExamples();
|
||||
}
|
||||
Lib39.LOGGER.info("[Lib39-Forge] Finished Initializing.");
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Register examples.
|
||||
*/
|
||||
static void registerExamples() {
|
||||
Lib39.LOGGER.info("[Lib39-Forge] Starting example demonstrations");
|
||||
try {
|
||||
// 创建示例实例并演示功能
|
||||
ForgeLib39Example example = new ForgeLib39Example();
|
||||
example.demonstrateFeature();
|
||||
|
||||
Lib39.LOGGER.info("[Lib39-Forge] Example demonstrations completed successfully");
|
||||
} catch (Exception e) {
|
||||
Lib39.LOGGER.error("[Lib39-Forge] Failed to demonstrate examples", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,25 +0,0 @@
|
|||
package top.r3944realms.lib39.base.compat.jade;
|
||||
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import snownee.jade.api.IWailaClientRegistration;
|
||||
import snownee.jade.api.IWailaPlugin;
|
||||
import snownee.jade.api.WailaPlugin;
|
||||
import top.r3944realms.lib39.Lib39;
|
||||
import top.r3944realms.lib39.base.compat.jade.provider.ForgeDollComponentProvider;
|
||||
import top.r3944realms.lib39.content.block.DollBlock;
|
||||
|
||||
/**
|
||||
* The type Forge jade plugin.
|
||||
*/
|
||||
@WailaPlugin
|
||||
public class ForgeJadePlugin implements IWailaPlugin {
|
||||
/**
|
||||
* The constant UID.
|
||||
*/
|
||||
public static final ResourceLocation UID = Lib39.rl("lib39");
|
||||
|
||||
@Override
|
||||
public void registerClient(IWailaClientRegistration registration) {
|
||||
registration.registerBlockComponent(new ForgeDollComponentProvider(), DollBlock.class);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,32 +0,0 @@
|
|||
package top.r3944realms.lib39.base.compat.jade.provider;
|
||||
|
||||
import com.mojang.authlib.GameProfile;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import snownee.jade.api.BlockAccessor;
|
||||
import snownee.jade.api.IBlockComponentProvider;
|
||||
import snownee.jade.api.ITooltip;
|
||||
import snownee.jade.api.config.IPluginConfig;
|
||||
|
||||
import top.r3944realms.lib39.base.compat.jade.ForgeJadePlugin;
|
||||
import top.r3944realms.lib39.content.block.blockentity.DollBlockEntity;
|
||||
|
||||
/**
|
||||
* The type Forge doll component provider.
|
||||
*/
|
||||
public class ForgeDollComponentProvider implements IBlockComponentProvider {
|
||||
@Override
|
||||
public ResourceLocation getUid() {
|
||||
return ForgeJadePlugin.UID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void appendTooltip(ITooltip iTooltip, BlockAccessor blockAccessor, IPluginConfig iPluginConfig) {
|
||||
if (blockAccessor.getBlockEntity() instanceof DollBlockEntity doll) {
|
||||
GameProfile ownerProfile = doll.getOwnerProfile();
|
||||
if (ownerProfile != null) {
|
||||
iTooltip.add(Component.translatable("tooltip.lib39.content.doll.hover.1", ownerProfile.getName()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,32 +0,0 @@
|
|||
package top.r3944realms.lib39.content.item;
|
||||
|
||||
import net.minecraft.client.renderer.BlockEntityWithoutLevelRenderer;
|
||||
import net.minecraftforge.client.extensions.common.IClientItemExtensions;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import top.r3944realms.lib39.client.renderer.item.DollItemRenderer;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
|
||||
/**
|
||||
* The type Forge doll item.
|
||||
*/
|
||||
public class ForgeDollItem extends DollItem {
|
||||
/**
|
||||
* Instantiates a new Forge doll item.
|
||||
*
|
||||
* @param properties the properties
|
||||
*/
|
||||
public ForgeDollItem(Properties properties) {
|
||||
super(properties);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initializeClient(@NotNull Consumer<IClientItemExtensions> consumer) {
|
||||
consumer.accept(new IClientItemExtensions() {
|
||||
@Override
|
||||
public BlockEntityWithoutLevelRenderer getCustomRenderer() {
|
||||
return DollItemRenderer.getInstance();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -1,72 +0,0 @@
|
|||
package top.r3944realms.lib39.core.network;
|
||||
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraftforge.network.NetworkDirection;
|
||||
import net.minecraftforge.network.NetworkRegistry;
|
||||
import net.minecraftforge.network.PacketDistributor;
|
||||
import net.minecraftforge.network.simple.SimpleChannel;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import top.r3944realms.lib39.Lib39;
|
||||
import top.r3944realms.lib39.core.network.toClient.SyncNBTCapDataEntityS2CPacket;
|
||||
|
||||
/**
|
||||
* The type Network handler.
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public class NetworkHandler {
|
||||
private static int cid = 0;
|
||||
/**
|
||||
* The constant INSTANCE.
|
||||
*/
|
||||
public static final SimpleChannel INSTANCE = NetworkRegistry.newSimpleChannel(
|
||||
Lib39.rl(Lib39.MOD_ID, "main"),
|
||||
() -> Lib39.ModInfo.VERSION,
|
||||
Lib39.ModInfo.VERSION::equals,
|
||||
Lib39.ModInfo.VERSION::equals
|
||||
);
|
||||
|
||||
/**
|
||||
* Register.
|
||||
*/
|
||||
public static void register() {
|
||||
INSTANCE.messageBuilder(SyncNBTCapDataEntityS2CPacket.class, cid++, NetworkDirection.PLAY_TO_CLIENT)
|
||||
.encoder(SyncNBTCapDataEntityS2CPacket::encode)
|
||||
.decoder(SyncNBTCapDataEntityS2CPacket::decode)
|
||||
.consumerNetworkThread(SyncNBTCapDataEntityS2CPacket::handle)
|
||||
.add();
|
||||
}
|
||||
|
||||
/**
|
||||
* Send to player.
|
||||
*
|
||||
* @param <MSG> the type parameter
|
||||
* @param message the message
|
||||
* @param player the player
|
||||
*/
|
||||
public static <MSG> void sendToPlayer(MSG message, ServerPlayer player){
|
||||
INSTANCE.send(PacketDistributor.PLAYER.with(() -> player), message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send to player.
|
||||
*
|
||||
* @param <MSG> the type parameter
|
||||
* @param <T> the type parameter
|
||||
* @param message the message
|
||||
* @param entity the entity
|
||||
* @param packetDistributor the packet distributor
|
||||
*/
|
||||
public static <MSG, T> void sendToPlayer(MSG message, T entity, @NotNull PacketDistributor<T> packetDistributor){
|
||||
INSTANCE.send(packetDistributor.with(() -> entity), message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send to player.
|
||||
*
|
||||
* @param <MSG> the type parameter
|
||||
* @param message the message
|
||||
*/
|
||||
public static <MSG> void sendToAllPlayer(MSG message){
|
||||
INSTANCE.send(PacketDistributor.ALL.noArg(), message);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,13 +0,0 @@
|
|||
package top.r3944realms.lib39.core.sync;
|
||||
|
||||
import top.r3944realms.lib39.core.network.NetworkHandler;
|
||||
import top.r3944realms.lib39.core.network.toClient.SyncNBTCapDataEntityS2CPacket;
|
||||
|
||||
/**
|
||||
* The interface Forge update.
|
||||
*/
|
||||
public interface IForgeUpdate extends IUpdate {
|
||||
default void update() {
|
||||
NetworkHandler.sendToAllPlayer(new SyncNBTCapDataEntityS2CPacket(getSyncData().entityId(), getSyncData().id, getSyncData().serializeNBT()));
|
||||
}
|
||||
}
|
||||
|
|
@ -1,61 +0,0 @@
|
|||
package top.r3944realms.lib39.example;
|
||||
|
||||
import net.minecraftforge.common.MinecraftForge;
|
||||
import net.minecraftforge.eventbus.api.IEventBus;
|
||||
import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;
|
||||
import top.r3944realms.lib39.example.core.event.ExCommonEventHandler;
|
||||
import top.r3944realms.lib39.example.core.network.ExNetworkHandler;
|
||||
import top.r3944realms.lib39.example.core.register.ForgeExLib39Items;
|
||||
|
||||
/**
|
||||
* The type Forge lib 39 example.
|
||||
*/
|
||||
public class ForgeLib39Example {
|
||||
private static boolean registered = false;
|
||||
|
||||
/**
|
||||
* Instantiates a new Lib 39 example.
|
||||
*/
|
||||
public ForgeLib39Example() {
|
||||
if (!registered) {
|
||||
init();
|
||||
registerToEventBus();
|
||||
registered = true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Init.
|
||||
*/
|
||||
public void init() {
|
||||
IEventBus modEventBus = FMLJavaModLoadingContext.get().getModEventBus();
|
||||
ForgeExLib39Items.register(modEventBus);
|
||||
ExNetworkHandler.register();
|
||||
}
|
||||
|
||||
private void registerToEventBus() {
|
||||
IEventBus modBus = FMLJavaModLoadingContext.get().getModEventBus();
|
||||
IEventBus gameBus = MinecraftForge.EVENT_BUS;
|
||||
// DistExecutor.unsafeCallWhenOn(Dist.CLIENT, () -> {
|
||||
// modBus.register(ExClientEventHandler.Mod.class);
|
||||
// gameBus.register(ExClientEventHandler.Game.class);
|
||||
// return null;
|
||||
// });
|
||||
// DistExecutor.unsafeCallWhenOn(Dist.DEDICATED_SERVER, () -> {
|
||||
// modBus.register(ExServerEventHandler.Mod.class);
|
||||
// gameBus.register(ExServerEventHandler.Game.class);
|
||||
// return null;
|
||||
// });
|
||||
modBus.register(ExCommonEventHandler.Mod.class);
|
||||
gameBus.register(ExCommonEventHandler.Game.class);
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Demonstrate feature.
|
||||
*/
|
||||
public void demonstrateFeature() {
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -1,40 +0,0 @@
|
|||
package top.r3944realms.lib39.example.content.data;
|
||||
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraftforge.common.capabilities.Capability;
|
||||
import net.minecraftforge.common.capabilities.CapabilityManager;
|
||||
import net.minecraftforge.common.capabilities.CapabilityToken;
|
||||
import net.minecraftforge.common.capabilities.RegisterCapabilitiesEvent;
|
||||
import net.minecraftforge.event.AttachCapabilitiesEvent;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* The type Ex capability handler.
|
||||
*/
|
||||
public class ExCapabilityHandler {
|
||||
/**
|
||||
* The constant TEST_CAP.
|
||||
*/
|
||||
public static final Capability<AbstractedTestSyncData> TEST_CAP = CapabilityManager.get(new CapabilityToken<>() {});
|
||||
|
||||
/**
|
||||
* Register capability.
|
||||
*
|
||||
* @param event the event
|
||||
*/
|
||||
public static void registerCapability(@NotNull RegisterCapabilitiesEvent event) {
|
||||
event.register(AbstractedTestSyncData.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Attach capability.
|
||||
*
|
||||
* @param event the event
|
||||
*/
|
||||
public static void attachCapability(@NotNull AttachCapabilitiesEvent<?> event) {
|
||||
Object object = event.getObject();
|
||||
if(object instanceof Entity entity) {
|
||||
event.addCapability(TestSyncCapProvider.TEST_SYNC_REL, new TestSyncCapProvider(entity));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,49 +0,0 @@
|
|||
package top.r3944realms.lib39.example.content.data;
|
||||
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraftforge.common.capabilities.Capability;
|
||||
import net.minecraftforge.common.capabilities.ICapabilitySerializable;
|
||||
import net.minecraftforge.common.util.LazyOptional;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import top.r3944realms.lib39.Lib39;
|
||||
|
||||
/**
|
||||
* The type Test sync cap provider.
|
||||
*/
|
||||
public class TestSyncCapProvider implements ICapabilitySerializable<CompoundTag> {
|
||||
|
||||
/**
|
||||
* The constant TEST_SYNC_REL.
|
||||
*/
|
||||
public static final ResourceLocation TEST_SYNC_REL = Lib39.rl(Lib39.MOD_ID, "test_sync_data");
|
||||
private final AbstractedTestSyncData instance;
|
||||
private final LazyOptional<AbstractedTestSyncData> optional;
|
||||
|
||||
/**
|
||||
* Instantiates a new Test sync cap provider.
|
||||
*
|
||||
* @param entity the entity
|
||||
*/
|
||||
public TestSyncCapProvider(Entity entity) {
|
||||
this.instance = new TestSyncData(entity);
|
||||
this.optional = LazyOptional.of(() -> instance);
|
||||
}
|
||||
@Override
|
||||
public @NotNull <T> LazyOptional<T> getCapability(@NotNull Capability<T> cap, @Nullable Direction side) {
|
||||
return ExCapabilityHandler.TEST_CAP.orEmpty(cap, optional);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompoundTag serializeNBT() {
|
||||
return instance.serializeNBT();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deserializeNBT(CompoundTag nbt) {
|
||||
instance.deserializeNBT(nbt);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,70 +0,0 @@
|
|||
package top.r3944realms.lib39.example.core.network;
|
||||
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraftforge.network.NetworkEvent;
|
||||
import top.r3944realms.lib39.example.content.data.AbstractedTestSyncData;
|
||||
import top.r3944realms.lib39.example.content.data.TestSyncData;
|
||||
import top.r3944realms.lib39.example.content.item.ForgeFabricItem;
|
||||
|
||||
import java.util.function.Supplier;
|
||||
|
||||
/**
|
||||
* The type Client data packet.
|
||||
*/
|
||||
public class ClientDataPacket {
|
||||
private final AbstractedTestSyncData clientData;
|
||||
private final int targetEntityId;
|
||||
|
||||
/**
|
||||
* Instantiates a new Client data packet.
|
||||
*
|
||||
* @param clientData the client data
|
||||
* @param targetEntityId the target entity id
|
||||
*/
|
||||
public ClientDataPacket(AbstractedTestSyncData clientData, int targetEntityId) {
|
||||
this.clientData = clientData;
|
||||
this.targetEntityId = targetEntityId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Instantiates a new Client data packet.
|
||||
*
|
||||
* @param buf the buf
|
||||
*/
|
||||
public ClientDataPacket(FriendlyByteBuf buf) {
|
||||
this.clientData = TestSyncData.staticFromBytes(buf);
|
||||
this.targetEntityId = buf.readInt();
|
||||
}
|
||||
|
||||
/**
|
||||
* To bytes.
|
||||
*
|
||||
* @param buf the buf
|
||||
*/
|
||||
public void toBytes(FriendlyByteBuf buf) {
|
||||
clientData.toBytes(buf);
|
||||
buf.writeInt(targetEntityId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle.
|
||||
*
|
||||
* @param supplier the supplier
|
||||
*/
|
||||
public void handle(Supplier<NetworkEvent.Context> supplier) {
|
||||
NetworkEvent.Context context = supplier.get();
|
||||
context.enqueueWork(() -> {
|
||||
ServerPlayer player = context.getSender();
|
||||
if (player != null) {
|
||||
// 处理客户端发送的数据
|
||||
handleClientData(player, clientData, targetEntityId);
|
||||
}
|
||||
});
|
||||
context.setPacketHandled(true);
|
||||
}
|
||||
|
||||
private void handleClientData(ServerPlayer player, AbstractedTestSyncData clientData, int targetEntityId) {
|
||||
ForgeFabricItem.handleClientDataFromPacket(player, clientData, targetEntityId);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,36 +0,0 @@
|
|||
package top.r3944realms.lib39.example.core.network;
|
||||
|
||||
import net.minecraftforge.network.NetworkRegistry;
|
||||
import net.minecraftforge.network.simple.SimpleChannel;
|
||||
import top.r3944realms.lib39.Lib39;
|
||||
|
||||
/**
|
||||
* The type Ex network handler.
|
||||
*/
|
||||
public class ExNetworkHandler {
|
||||
/**
|
||||
* The constant INSTANCE.
|
||||
*/
|
||||
public static final SimpleChannel INSTANCE;
|
||||
private static int ID = 0;
|
||||
|
||||
static {
|
||||
INSTANCE = NetworkRegistry.newSimpleChannel(
|
||||
Lib39.rl(Lib39.MOD_ID, "test"),
|
||||
() -> "1.0",
|
||||
s -> true,
|
||||
s -> true
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register.
|
||||
*/
|
||||
public static void register() {
|
||||
// 注册数据包
|
||||
INSTANCE.registerMessage(ID++, ClientDataPacket.class,
|
||||
ClientDataPacket::toBytes,
|
||||
ClientDataPacket::new,
|
||||
ClientDataPacket::handle);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,19 +0,0 @@
|
|||
package top.r3944realms.lib39.platform;
|
||||
|
||||
import top.r3944realms.lib39.platform.services.IUtilHelper;
|
||||
import top.r3944realms.lib39.util.ForgeBlockRegistryBuilder;
|
||||
import top.r3944realms.lib39.util.block.BlockRegistryBuilder;
|
||||
|
||||
/**
|
||||
* The enum Forge util helper.
|
||||
*/
|
||||
public enum ForgeUtilHelper implements IUtilHelper {
|
||||
/**
|
||||
* Instance forge util helper.
|
||||
*/
|
||||
INSTANCE;
|
||||
@Override
|
||||
public BlockRegistryBuilder getBlockRegistryBuilder() {
|
||||
return new ForgeBlockRegistryBuilder();
|
||||
}
|
||||
}
|
||||
|
|
@ -1 +0,0 @@
|
|||
top.r3944realms.lib39.platform.ForgePlatformHelper
|
||||
|
|
@ -3,30 +3,28 @@
|
|||
# Every field you add must be added to buildSrc/src/main/groovy/multiloader-common.gradle expandProps map.
|
||||
|
||||
# Project
|
||||
version=0.5.5
|
||||
version=0.5.6
|
||||
group=top.r3944realms.lib39
|
||||
java_version=17
|
||||
java_version=25
|
||||
|
||||
# Common
|
||||
minecraft_version=1.20.1
|
||||
minecraft_version=26.1.2
|
||||
mod_name=3944Realms 's Lib Mod
|
||||
mod_author=R3944Realms
|
||||
mod_id=lib39
|
||||
license=MIT
|
||||
credits=Logo created by Shanyi43, edited by R3944Realms
|
||||
description=Lib39 is a general-purpose dependency library that provides utility methods and core functionality for other mods.
|
||||
minecraft_version_range=[1.20.1, 1.22)
|
||||
# The version of ParchmentMC that is used, see https://parchmentmc.org/docs/getting-started#choose-a-version for new versions
|
||||
parchment_minecraft=1.20.1
|
||||
parchment_version=2023.09.03
|
||||
minecraft_version_range=[26.1.2, 26.2)
|
||||
neo_form_version=26.1.2-1
|
||||
|
||||
# NeoForge
|
||||
neoforge_version=26.1.2.7-beta
|
||||
neoforge_loader_version_range=[4,)
|
||||
|
||||
# Fabric
|
||||
fabric_version=0.92.1+1.20.1
|
||||
fabric_loader_version=0.16.9
|
||||
|
||||
# Forge
|
||||
forge_version=47.2.30
|
||||
forge_loader_version_range=[47,)
|
||||
fabric_version=0.145.4+26.1.2
|
||||
fabric_loader_version=0.18.6
|
||||
|
||||
# Gradle
|
||||
org.gradle.jvmargs=-Xmx3G
|
||||
|
|
@ -40,9 +38,9 @@ publish_curseforge=true
|
|||
modrinth_id=n65Vs1Vk
|
||||
curseforge_id=1445917
|
||||
|
||||
java_versions=21 17
|
||||
java_versions=25
|
||||
|
||||
fabric_modrinth_dependencies=
|
||||
forge_modrinth_dependencies=
|
||||
neoforge_modrinth_dependencies=
|
||||
fabric_curseforge_dependencies=
|
||||
forge_curseforge_dependencies=
|
||||
neoforge_curseforge_dependencies=
|
||||
|
|
|
|||
35
gradlew
vendored
35
gradlew
vendored
|
|
@ -1,7 +1,7 @@
|
|||
#!/bin/sh
|
||||
|
||||
#
|
||||
# Copyright © 2015-2021 the original authors.
|
||||
# Copyright © 2015 the original authors.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
|
|
@ -15,6 +15,8 @@
|
|||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
|
||||
##############################################################################
|
||||
#
|
||||
|
|
@ -55,7 +57,7 @@
|
|||
# Darwin, MinGW, and NonStop.
|
||||
#
|
||||
# (3) This script is generated from the Groovy template
|
||||
# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
|
||||
# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
|
||||
# within the Gradle project.
|
||||
#
|
||||
# You can find Gradle at https://github.com/gradle/gradle/.
|
||||
|
|
@ -83,7 +85,8 @@ done
|
|||
# This is normally unused
|
||||
# shellcheck disable=SC2034
|
||||
APP_BASE_NAME=${0##*/}
|
||||
APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
|
||||
# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
|
||||
APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit
|
||||
|
||||
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||
MAX_FD=maximum
|
||||
|
|
@ -111,7 +114,6 @@ case "$( uname )" in #(
|
|||
NONSTOP* ) nonstop=true ;;
|
||||
esac
|
||||
|
||||
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
||||
|
||||
|
||||
# Determine the Java command to use to start the JVM.
|
||||
|
|
@ -130,10 +132,13 @@ location of your Java installation."
|
|||
fi
|
||||
else
|
||||
JAVACMD=java
|
||||
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
if ! command -v java >/dev/null 2>&1
|
||||
then
|
||||
die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
|
||||
Please set the JAVA_HOME variable in your environment to match the
|
||||
location of your Java installation."
|
||||
fi
|
||||
fi
|
||||
|
||||
# Increase the maximum file descriptors if we can.
|
||||
|
|
@ -141,7 +146,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
|
|||
case $MAX_FD in #(
|
||||
max*)
|
||||
# In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
|
||||
# shellcheck disable=SC3045
|
||||
# shellcheck disable=SC2039,SC3045
|
||||
MAX_FD=$( ulimit -H -n ) ||
|
||||
warn "Could not query maximum file descriptor limit"
|
||||
esac
|
||||
|
|
@ -149,7 +154,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
|
|||
'' | soft) :;; #(
|
||||
*)
|
||||
# In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
|
||||
# shellcheck disable=SC3045
|
||||
# shellcheck disable=SC2039,SC3045
|
||||
ulimit -n "$MAX_FD" ||
|
||||
warn "Could not set maximum file descriptor limit to $MAX_FD"
|
||||
esac
|
||||
|
|
@ -166,7 +171,6 @@ fi
|
|||
# For Cygwin or MSYS, switch paths to Windows format before running java
|
||||
if "$cygwin" || "$msys" ; then
|
||||
APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
|
||||
CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
|
||||
|
||||
JAVACMD=$( cygpath --unix "$JAVACMD" )
|
||||
|
||||
|
|
@ -198,16 +202,15 @@ fi
|
|||
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
|
||||
|
||||
# Collect all arguments for the java command;
|
||||
# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
|
||||
# shell script including quotes and variable substitutions, so put them in
|
||||
# double quotes to make sure that they get re-expanded; and
|
||||
# * put everything else in single quotes, so that it's not re-expanded.
|
||||
# Collect all arguments for the java command:
|
||||
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
|
||||
# and any embedded shellness will be escaped.
|
||||
# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
|
||||
# treated as '${Hostname}' itself on the command line.
|
||||
|
||||
set -- \
|
||||
"-Dorg.gradle.appname=$APP_BASE_NAME" \
|
||||
-classpath "$CLASSPATH" \
|
||||
org.gradle.wrapper.GradleWrapperMain \
|
||||
-jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \
|
||||
"$@"
|
||||
|
||||
# Stop when "xargs" is not available.
|
||||
|
|
@ -242,4 +245,4 @@ eval "set -- $(
|
|||
tr '\n' ' '
|
||||
)" '"$@"'
|
||||
|
||||
exec "$JAVACMD" "$@"
|
||||
exec "$JAVACMD" "$@"
|
||||
|
|
@ -1,13 +1,6 @@
|
|||
plugins {
|
||||
id 'multiloader-loader'
|
||||
id 'net.neoforged.moddev.legacyforge'
|
||||
}
|
||||
|
||||
mixin {
|
||||
add(sourceSets.main, "${mod_id}.refmap.json")
|
||||
|
||||
config("${mod_id}.mixins.json")
|
||||
config("${mod_id}.forge.mixins.json")
|
||||
id 'net.neoforged.moddev'
|
||||
}
|
||||
|
||||
def commonResources = project(':common').file('src/main/resources/').getAbsolutePath()
|
||||
|
|
@ -16,8 +9,8 @@ def forgeBuildResources = file('build/resources/main/').getAbsolutePath()
|
|||
def commonBuildResources = project(':common').file('build/resources/main/').getAbsolutePath()
|
||||
def generatedOutput = project(':common').file('src/generated/resources/').getAbsolutePath()
|
||||
|
||||
legacyForge {
|
||||
version = "${minecraft_version}-${forge_version}"
|
||||
neoForge {
|
||||
version = neoforge_version
|
||||
|
||||
validateAccessTransformers = true
|
||||
|
||||
|
|
@ -25,10 +18,6 @@ legacyForge {
|
|||
if (at.exists()) {
|
||||
accessTransformers = ["src/main/resources/META-INF/accesstransformer.cfg"]
|
||||
}
|
||||
parchment {
|
||||
minecraftVersion = parchment_minecraft
|
||||
mappingsVersion = parchment_version
|
||||
}
|
||||
runs {
|
||||
client {
|
||||
client()
|
||||
|
|
@ -43,7 +32,7 @@ legacyForge {
|
|||
)
|
||||
}
|
||||
data {
|
||||
data()
|
||||
clientData()
|
||||
|
||||
// 使用之前定义的变量
|
||||
programArguments.addAll(
|
||||
|
|
@ -71,21 +60,11 @@ legacyForge {
|
|||
sourceSets.main.resources.srcDir project(':common').file('src/generated/resources')
|
||||
|
||||
dependencies {
|
||||
compileOnly project(":common")
|
||||
annotationProcessor("org.spongepowered:mixin:0.8.5-SNAPSHOT:processor")
|
||||
implementation(annotationProcessor("io.github.llamalad7:mixinextras-common:0.2.0"))
|
||||
modImplementation(group: 'tschipp.carryon', name: 'carryon-forge-1.20.1', version: '2.1.2.7') {
|
||||
implementation(group: 'tschipp.carryon', name: 'carryon-neoforge-26.1.2', version: '3.0.1') {
|
||||
transitive = false
|
||||
}
|
||||
modImplementation ("curse.maven:jade-324717:6855440")
|
||||
implementation(jarJar("io.github.llamalad7:mixinextras-forge:0.2.0"))
|
||||
}
|
||||
implementation "curse.maven:jade-324717:8068368"
|
||||
|
||||
jar {
|
||||
finalizedBy('reobfJar')
|
||||
manifest.attributes([
|
||||
"MixinConfigs": "${mod_id}.mixins.json,${mod_id}.forge.mixins.json"
|
||||
])
|
||||
}
|
||||
|
||||
// 配置sourceJar任务
|
||||
|
|
@ -106,7 +85,7 @@ tasks.named('javadoc', Javadoc) {
|
|||
classpath += project(':common').sourceSets.main.compileClasspath
|
||||
options.encoding = 'UTF-8'
|
||||
options.charSet = 'UTF-8'
|
||||
options.links("https://docs.oracle.com/en/java/javase/17/docs/api/")
|
||||
options.links("https://docs.oracle.com/en/java/javase/21/docs/api/")
|
||||
options.memberLevel = JavadocMemberLevel.PUBLIC
|
||||
options.addBooleanOption('Xdoclint:none', true)
|
||||
options.addStringOption('doctitle', "${mod_id} ${minecraft_version} ${version} Javadoc")
|
||||
|
|
@ -129,72 +108,6 @@ tasks.named('build') {
|
|||
dependsOn tasks.named('javadocJar')
|
||||
}
|
||||
|
||||
// 处理reobf
|
||||
tasks.named('reobfJar') {
|
||||
dependsOn tasks.named('sourcesJar')
|
||||
dependsOn tasks.named('javadocJar')
|
||||
}
|
||||
|
||||
// 发布配置
|
||||
publishing {
|
||||
publications {
|
||||
mavenJava(MavenPublication) {
|
||||
artifactId = "${mod_id}-forge-${minecraft_version}"
|
||||
artifacts.clear()
|
||||
artifact(tasks.named('reobfJar').get()) {
|
||||
builtBy tasks.named('reobfJar')
|
||||
}
|
||||
artifact(tasks.named('sourcesJar').get()) {
|
||||
builtBy tasks.named('sourcesJar')
|
||||
classifier = 'sources'
|
||||
}
|
||||
artifact(tasks.named('javadocJar').get()) {
|
||||
builtBy tasks.named('javadocJar')
|
||||
classifier = 'javadoc'
|
||||
}
|
||||
pom {
|
||||
name = 'Lib39'
|
||||
description = 'Lib39 is a general-purpose dependency library for Minecraft mods.'
|
||||
url = 'https://github.com/3944Realms/lib39'
|
||||
|
||||
properties = [
|
||||
'minecraft.version': project.minecraft_version,
|
||||
'mod.version': project.version,
|
||||
'forge.version': project.forge_version,
|
||||
'java.version': '17'
|
||||
]
|
||||
|
||||
licenses {
|
||||
license {
|
||||
name = 'MIT'
|
||||
url = 'https://raw.githubusercontent.com/3944Realms/lib39/refs/heads/main/LICENSE'
|
||||
distribution = 'repo'
|
||||
}
|
||||
}
|
||||
|
||||
developers {
|
||||
developer {
|
||||
id = 'R3944Realms'
|
||||
name = "${mod_author}"
|
||||
email = 'f256198830@hotmail.com'
|
||||
}
|
||||
}
|
||||
|
||||
scm {
|
||||
connection = 'scm:git:https://github.com/3944Realms/lib39.git'
|
||||
developerConnection = 'scm:git:ssh://git@github.com:3944Realms/lib39.git'
|
||||
url = 'https://github.com/3944Realms/lib39'
|
||||
tag = 'main'
|
||||
}
|
||||
|
||||
issueManagement {
|
||||
system = 'GitHub'
|
||||
url = 'https://github.com/3944Realms/lib39/issues'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
test {
|
||||
useJUnitPlatform()
|
||||
}
|
||||
|
|
@ -205,21 +118,23 @@ processResources {
|
|||
|
||||
inputs.property "version", project.version
|
||||
inputs.property "minecraft_version", minecraft_version
|
||||
inputs.property "forge_version", forge_version
|
||||
inputs.property "neoforge_version", neoforge_version
|
||||
inputs.property "mod_id", mod_id
|
||||
inputs.property "mod_name", mod_name
|
||||
inputs.property "description", description
|
||||
inputs.property "mod_author", mod_author
|
||||
inputs.property "credits", credits
|
||||
|
||||
filesMatching(['META-INF/mods.toml', 'pack.mcmeta', "*.mixins.json"]) {
|
||||
expand([
|
||||
version: project.version,
|
||||
minecraft_version: minecraft_version,
|
||||
forge_version: forge_version,
|
||||
neoforge_version: neoforge_version,
|
||||
mod_id: mod_id,
|
||||
mod_name: mod_name,
|
||||
description: description,
|
||||
mod_author: mod_author
|
||||
mod_author: mod_author,
|
||||
"credits": credits
|
||||
])
|
||||
}
|
||||
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user