Compare commits

..

10 Commits

Author SHA1 Message Date
b4e64f7f33 fix: Enchantment Description compatibility 2025-09-02 23:53:53 +08:00
lcy0x1
ea1d87e16d fix token sync 2025-07-28 14:06:49 +08:00
lcy0x1
adfadd5eb7 config fix 2025-03-02 15:44:45 +08:00
lcy0x1
a56299bf56 datagen fix 2025-01-01 15:42:19 +08:00
lcy0x1
d7af5ef4bb prepare for l2h 2024-10-23 09:01:11 +08:00
lcy0x1
21bff77a28 fix proxy 2024-10-05 01:27:25 +08:00
lcy0x1
294fadb7b5 bug fix 2024-09-27 14:14:09 +08:00
lcy0x1
b60e4492cf cuisine 2024-09-27 10:58:21 +08:00
lcy0x1
af889f4808 potion builder 2024-09-12 17:14:46 +08:00
lcy0x1
ca438aac32 force load default 2024-08-28 13:37:46 +08:00
60 changed files with 631 additions and 120 deletions

View File

@@ -1,13 +1,17 @@
plugins {
id 'java-library'
id 'eclipse'
id 'idea'
id 'maven-publish'
id 'net.neoforged.gradle.userdev' version '7.0.145'
id 'net.neoforged.moddev' version '2.0.80'
id 'net.darkhax.curseforgegradle' version '[1.1.24,)'
id "at.stnwtr.gradle-secrets-plugin" version "1.0.1"
id "com.modrinth.minotaur" version "2.+"
}
version = mod_version
group = 'dev.kxmc'
group = 'dev.xkmc'
repositories {
mavenLocal()
@@ -17,38 +21,53 @@ base {
archivesName = mod_id
}
java {
withSourcesJar()
}
java.toolchain.languageVersion = JavaLanguageVersion.of(21)
minecraft.accessTransformers.file rootProject.file('src/main/resources/META-INF/accesstransformer.cfg')
sourceSets {
client {}
server {}
data {}
common {}
}
neoForge {
// We currently only support NeoForge versions later than 21.0.x
// See https://projects.neoforged.net/neoforged/neoforge for the latest updates
version = "${neo_version}"
// Validate AT files and raise errors when they have invalid targets
// This option is false by default, but turning it on is recommended
//validateAccessTransformers = true
accessTransformers.from "./src/main/resources/META-INF/accesstransformer.cfg"
runs {
configureEach {
systemProperty 'forge.logging.markers', 'REGISTRIES'
systemProperty 'forge.logging.console.level', 'debug'
modSource project.sourceSets.main
}
client {
systemProperty 'forge.enabledGameTestNamespaces', project.mod_id
}
server {
systemProperty 'forge.enabledGameTestNamespaces', project.mod_id
programArgument '--nogui'
}
gameTestServer {
systemProperty 'forge.enabledGameTestNamespaces', project.mod_id
client()
}
data {
data()
programArguments.addAll '--mod', project.mod_id, '--all', '--output', file('src/generated/resources/').getAbsolutePath(), '--existing', file('src/main/resources/').getAbsolutePath()
}
server {
server()
}
}
mods {
"${mod_id}" {
sourceSet sourceSets.main
}
}
}
sourceSets.main.resources { srcDir 'src/generated/resources' }
dependencies {
implementation "net.neoforged:neoforge:${neo_version}"
}
tasks.withType(ProcessResources).configureEach {
var replaceProperties = [
minecraft_version : minecraft_version, minecraft_version_range: minecraft_version_range,
@@ -84,10 +103,6 @@ tasks.withType(JavaCompile).configureEach {
if (lljij.toBoolean()) jarJar.enable()
java {
withSourcesJar()
}
jar {
manifest {
attributes([
@@ -148,14 +163,22 @@ dependencies {
implementation "mezz.jei:jei-${jei_minecraft_version}:${jei_version}"
implementation "com.tterrag.registrate:Registrate:${registrate_version}"
implementation "dev.xkmc:l2serial:${l2serial_ver}"
implementation "vazkii.patchouli:Patchouli:${patchouli_ver}"
compileOnly "vazkii.patchouli:Patchouli:${patchouli_ver}"
runtimeOnly "dev.xkmc:l2damagetracker:3.0.2"
runtimeOnly "dev.xkmc:l2menustacker:3.0.9"
runtimeOnly "dev.xkmc:l2itemselector:3.0.7"
runtimeOnly "dev.xkmc:l2library:3.0.2"
runtimeOnly "dev.xkmc:l2complements:3.0.2+3"
//runtimeOnly "dev.xkmc:l2damagetracker:3.0.3+2"
//runtimeOnly "dev.xkmc:l2menustacker:3.0.9"
//runtimeOnly "dev.xkmc:l2itemselector:3.0.8"
//runtimeOnly "dev.xkmc:l2library:3.0.2+4"
//runtimeOnly "dev.xkmc:l2complements:3.0.2+7"
//runtimeOnly "dev.xkmc:l2archery:3.0.0+8"
//runtimeOnly "curse.maven:embeddium-908741:5630163"
//runtimeOnly "curse.maven:farmers-delight-398521:5566383"
//runtimeOnly "dev.xkmc:cuisinedelight:1.2.2"
//implementation "curse.maven:enchantment-descriptions-250419:5760047"
//implementation "curse.maven:bookshelf-228525:5757624"
//implementation "curse.maven:prickle-1023259:5757615"
runtimeOnly "curse.maven:embeddium-908741:5630163"
}

View File

@@ -8,9 +8,11 @@ org.gradle.debug=false
neogradle.subsystems.parchment.minecraftVersion=1.20.6
neogradle.subsystems.parchment.mappingsVersion=2024.06.02
org.gradle.configuration-cache=false
minecraft_version=1.21.1
minecraft_version_range=[1.21.1,1.22)
neo_version=21.1.4
neo_version=21.1.143
neo_version_range=[21.1.4,)
loader_version_range=[2,)
@@ -18,18 +20,18 @@ loader_version_range=[2,)
mod_id=l2core
mod_name=L2Core
mod_license=LGPL-2.1
mod_version=3.0.7+31
mod_version=3.0.8+15
mod_group_id=dev.xkmc
mod_authors=lcy0x1
mod_description=Core Library mod for all L2 mods
jei_minecraft_version = 1.21-neoforge
jei_version = 19.5.0.44
jei_minecraft_version = 1.21.1-neoforge
jei_version = 19.21.0.246
registrate_version = MC1.21-1.3.0+50
patchouli_ver = 1.21-87-NEOFORGE-SNAPSHOT
lljij = false
rootMod = false
l2serial_ver = 3.0.9
l2serial_ver = 3.0.9+4

View File

@@ -1,6 +1,6 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.10-bin.zip
networkTimeout=10000
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

Binary file not shown.

Binary file not shown.

BIN
libs/l2archery-3.0.0+8.jar Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -7,5 +7,5 @@ pluginManagement {
}
plugins {
id 'org.gradle.toolchains.foojay-resolver-convention' version '0.5.0'
id 'org.gradle.toolchains.foojay-resolver-convention' version '0.8.0'
}

View File

@@ -1,4 +1,4 @@
// 1.21 2024-07-25T11:38:15.636395 Registrate Provider for l2core [Registries, Data Maps, Recipes, Advancements, Loot Tables, Tags (blocks), Tags (items), Tags (fluids), Tags (entity_types), generic_server_provider, Blockstates, Item models, Lang (en_us/en_ud), generic_client_provider, Tags (mob_effect), Tags (attribute), Tags (enchantment)]
7fd8a37c6437c7cab27c53dbc0df73ececc1cd44 assets/l2core/lang/en_ud.json
18ae34417262501a3c00959390185e01ffb2ae7c assets/l2core/lang/en_us.json
// 1.21.1 2025-07-26T01:42:31.138209 Registrate Provider for l2core [Registries, Data Maps, Recipes, Advancements, Loot Tables, Tags (blocks), Tags (items), Tags (fluids), Tags (entity_types), generic_server_provider, Blockstates, Item models, Lang (en_us/en_ud), generic_client_provider, Tags (mob_effect), Tags (attribute), Tags (enchantment)]
72a986cabe624a799bdb74cc1b5e67dd6f80baed assets/l2core/lang/en_ud.json
9eab006827655c8a83941f5d9c71681a1244378c assets/l2core/lang/en_us.json
35133e95f1c8fdd7a1c21afcc231fc0bffefb9a8 data/l2core/tags/mob_effect/tracked_effects.json

View File

@@ -2,7 +2,9 @@
"l2core.configuration.addEnchantmentDescription": "suoıʇdıɹɔsǝᗡ ʇuǝɯʇuɐɥɔuƎ ppⱯ",
"l2core.configuration.addEnchantmentDescription.tooltip": "SʎⱯMꞀⱯ 'ʎꞀNO‾⟘ℲIHS 'ƎꞀᗺⱯSIᗡ :sǝnןɐΛ pǝʍoןןⱯ",
"l2core.configuration.overlayZVal": "ʎɐןɹǝʌo ɹǝʇɔɐɹɐɥɔ ɯǝʇı ɟo ʇɥbıǝɥ ǝɥ⟘",
"l2core.configuration.overlayZVal.tooltip": "000000Ɩ ~ 000000Ɩ- :ǝbuɐᴚ",
"l2core.configuration.overlayZVal.tooltip": "000000Ɩ ~ 000000Ɩ- :ǝbuɐᴚ \n0ϛᄅ :ʇןnɐɟǝᗡ ",
"l2core.configuration.renderOverlayIcons": "sǝıʇıʇuǝ uo suoɔı ʎɐןɹǝʌo ɹǝpuǝᴚ",
"l2core.configuration.renderOverlayIcons.tooltip": "",
"l2core.configuration.section.l2configs.l2core.client.toml": "uoıʇɐɹnbıɟuoƆ ʇuǝıןƆ ǝɹoƆᄅꞀ",
"l2core.configuration.section.l2configs.l2core.client.toml.title": "uoıʇɐɹnbıɟuoƆ ʇuǝıןƆ ǝɹoƆᄅꞀ",
"l2core.configuration.title": "uoıʇɐɹnbıɟuoƆ ǝɹoƆᄅꞀ",

View File

@@ -2,7 +2,9 @@
"l2core.configuration.addEnchantmentDescription": "Add Enchantment Descriptions",
"l2core.configuration.addEnchantmentDescription.tooltip": "Allowed Values: DISABLE, SHIFT_ONLY, ALWAYS",
"l2core.configuration.overlayZVal": "The height of item character overlay",
"l2core.configuration.overlayZVal.tooltip": "Range: -1000000 ~ 1000000",
"l2core.configuration.overlayZVal.tooltip": " Default: 250\n Range: -1000000 ~ 1000000",
"l2core.configuration.renderOverlayIcons": "Render overlay icons on entities",
"l2core.configuration.renderOverlayIcons.tooltip": "",
"l2core.configuration.section.l2configs.l2core.client.toml": "L2Core Client Configuration",
"l2core.configuration.section.l2configs.l2core.client.toml.title": "L2Core Client Configuration",
"l2core.configuration.title": "L2Core Configuration",

View File

@@ -3,22 +3,28 @@ package dev.xkmc.l2core.base.effects;
import dev.xkmc.l2core.base.effects.api.ForceEffect;
import net.minecraft.world.effect.MobEffectInstance;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.EntityType;
import net.minecraft.world.entity.LivingEntity;
import net.neoforged.neoforge.common.NeoForge;
import net.neoforged.neoforge.event.EventHooks;
import net.neoforged.neoforge.event.entity.living.MobEffectEvent;
import javax.annotation.Nullable;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import java.util.function.Predicate;
public class EffectUtil {
private static final Set<EntityType<?>> INVALID = new HashSet<>();
/**
* force add effect, make hard not override
* for icon use only, such as Arcane Mark on Wither and Ender Dragon
*/
private static void forceAddEffect(LivingEntity e, MobEffectInstance ins, @Nullable Entity source) {
private synchronized static void forceAddEffect(LivingEntity e, MobEffectInstance ins, @Nullable Entity source) {
if (INVALID.contains(e.getType())) return;
MobEffectInstance old = e.activeEffects.get(ins.getEffect());
var event = new ForceAddEffectEvent(e, ins);
NeoForge.EVENT_BUS.post(event);
@@ -27,7 +33,12 @@ public class EffectUtil {
}
NeoForge.EVENT_BUS.post(new MobEffectEvent.Added(e, old, ins, source));
if (old == null) {
try {
e.activeEffects.put(ins.getEffect(), ins);
} catch (Exception ignored) {
INVALID.add(e.getType());
return;
}
e.onEffectAdded(ins, source);
ins.onEffectAdded(e);
} else if (old.update(ins)) {

View File

@@ -0,0 +1,37 @@
package dev.xkmc.l2core.base.worldgen;
import com.mojang.serialization.MapCodec;
import dev.xkmc.l2core.init.L2LibReg;
import dev.xkmc.l2core.serial.configval.DoubleConfigValue;
import net.minecraft.core.BlockPos;
import net.minecraft.util.RandomSource;
import net.minecraft.world.level.levelgen.placement.PlacementModifierType;
import net.minecraft.world.level.levelgen.placement.RepeatingPlacement;
import java.util.function.DoubleSupplier;
public class ConfigChancePlacement extends RepeatingPlacement {
public static final MapCodec<ConfigChancePlacement> CODEC = DoubleConfigValue.CODEC.fieldOf("chance").xmap(ConfigChancePlacement::new, e -> e.chance);
private final DoubleSupplier chance;
private ConfigChancePlacement(DoubleSupplier chance) {
this.chance = chance;
}
public static ConfigChancePlacement of(DoubleSupplier count) {
return new ConfigChancePlacement(count);
}
@Override
protected int count(RandomSource random, BlockPos pos) {
double val = chance.getAsDouble();
int ans = (int) val;
return ans + (random.nextFloat() < val - ans ? 1 : 0);
}
@Override
public PlacementModifierType<?> type() {
return L2LibReg.PM_CHANCE.get();
}
}

View File

@@ -0,0 +1,39 @@
package dev.xkmc.l2core.base.worldgen;
import com.mojang.serialization.MapCodec;
import dev.xkmc.l2core.init.L2LibReg;
import dev.xkmc.l2core.serial.configval.DoubleConfigValue;
import net.minecraft.core.BlockPos;
import net.minecraft.util.RandomSource;
import net.minecraft.world.level.levelgen.placement.PlacementContext;
import net.minecraft.world.level.levelgen.placement.PlacementFilter;
import net.minecraft.world.level.levelgen.placement.PlacementModifierType;
import java.util.function.DoubleSupplier;
public class ConfigRarityFilter extends PlacementFilter {
public static final MapCodec<ConfigRarityFilter> CODEC =
DoubleConfigValue.CODEC.fieldOf("chance").xmap(ConfigRarityFilter::new, e -> e.chance);
private final DoubleSupplier chance;
private ConfigRarityFilter(DoubleSupplier chance) {
this.chance = chance;
}
public static ConfigRarityFilter of(DoubleSupplier chance) {
return new ConfigRarityFilter(chance);
}
@Override
protected boolean shouldPlace(PlacementContext context, RandomSource random, BlockPos pos) {
return random.nextFloat() < this.chance.getAsDouble();
}
@Override
public PlacementModifierType<?> type() {
return L2LibReg.PM_RARITY.get();
}
}

View File

@@ -0,0 +1,8 @@
@MethodsReturnNonnullByDefault
@ParametersAreNonnullByDefault
package dev.xkmc.l2core.base.worldgen;
import net.minecraft.MethodsReturnNonnullByDefault;
import javax.annotation.ParametersAreNonnullByDefault;

View File

@@ -2,14 +2,17 @@ package dev.xkmc.l2core.capability.conditionals;
import dev.xkmc.l2core.init.L2LibReg;
import dev.xkmc.l2core.util.Proxy;
import dev.xkmc.l2serial.serialization.codec.PacketCodec;
import dev.xkmc.l2serial.util.Wrappers;
import net.minecraft.world.entity.player.Player;
public class ClientDataHandler {
public static <T extends ConditionalToken> void handle(TokenKey<T> key, T token) {
public static <T extends ConditionalToken> void handle(TokenKey<T> key, byte[] data) {
Player player = Proxy.getClientPlayer();
if (player == null) return;
var buf = PacketCodec.decode(player.registryAccess(), data);
T token = Wrappers.cast(PacketCodec.from(buf, ConditionalToken.class, null));
ConditionalToken old = L2LibReg.CONDITIONAL.type().getOrCreate(player).data.put(key, token);
if (token instanceof NetworkSensitiveToken<?> t) {
t.onSync(Wrappers.cast(old), player);

View File

@@ -10,7 +10,7 @@ public interface NetworkSensitiveToken<T extends ConditionalToken> {
void onSync(@Nullable T old, Player player);
default void sync(TokenKey<T> key, T token, ServerPlayer sp) {
L2Core.PACKET_HANDLER.toClientPlayer(TokenToClient.of(key, token), sp);
L2Core.PACKET_HANDLER.toClientPlayer(TokenToClient.of(sp.registryAccess(), key, token), sp);
}
}

View File

@@ -1,20 +1,23 @@
package dev.xkmc.l2core.capability.conditionals;
import dev.xkmc.l2serial.network.SerialPacketBase;
import dev.xkmc.l2serial.serialization.codec.PacketCodec;
import net.minecraft.core.RegistryAccess;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.entity.player.Player;
import org.jetbrains.annotations.Nullable;
public record TokenToClient(ResourceLocation id, ConditionalToken token)
public record TokenToClient(ResourceLocation id, byte[] data)
implements SerialPacketBase<TokenToClient> {
public static <T extends ConditionalToken> TokenToClient of(TokenKey<T> key, T token) {
return new TokenToClient(key.asLocation(), token);
public static <T extends ConditionalToken> TokenToClient of(RegistryAccess access, TokenKey<T> key, T token) {
var data = PacketCodec.toBytes(access, token, ConditionalToken.class, e -> true);
return new TokenToClient(key.asLocation(), data);
}
@Override
public void handle(@Nullable Player player) {
ClientDataHandler.handle(TokenKey.of(id), token);
ClientDataHandler.handle(TokenKey.of(id), data);
}
}

View File

@@ -6,9 +6,14 @@ import mezz.jei.api.recipe.IFocusGroup;
import mezz.jei.api.recipe.RecipeType;
import mezz.jei.api.recipe.category.IRecipeCategory;
import net.minecraft.MethodsReturnNonnullByDefault;
import net.minecraft.client.Minecraft;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.item.crafting.Recipe;
import net.minecraft.world.item.crafting.RecipeHolder;
import net.minecraft.world.item.crafting.RecipeInput;
import javax.annotation.ParametersAreNonnullByDefault;
import java.util.List;
@ParametersAreNonnullByDefault
@MethodsReturnNonnullByDefault
@@ -27,6 +32,13 @@ public abstract class BaseRecipeCategory<T, C extends BaseRecipeCategory<T, C>>
this.type = new RecipeType<>(name, cls);
}
public <R extends Recipe<I>, I extends RecipeInput> List<R> getAll(net.minecraft.world.item.crafting.RecipeType<R> type) {
var level = Minecraft.getInstance().level;
if (level == null) return List.of();
return level.getRecipeManager().getAllRecipesFor(type)
.stream().map(RecipeHolder::value).toList();
}
@SuppressWarnings("unchecked")
public final C getThis() {
return (C) this;

View File

@@ -1,27 +1,23 @@
package dev.xkmc.l2core.events;
import dev.xkmc.l2core.capability.attachment.GeneralCapabilityHolder;
import dev.xkmc.l2core.capability.player.PlayerCapabilityHolder;
import dev.xkmc.l2core.init.L2Core;
import dev.xkmc.l2serial.util.Wrappers;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.entity.LivingEntity;
import net.neoforged.bus.api.EventPriority;
import net.neoforged.bus.api.SubscribeEvent;
import net.neoforged.fml.common.EventBusSubscriber;
import net.neoforged.neoforge.event.entity.EntityJoinLevelEvent;
import net.neoforged.neoforge.event.entity.player.PlayerEvent;
import net.neoforged.neoforge.event.tick.EntityTickEvent;
import net.neoforged.neoforge.event.tick.PlayerTickEvent;
@EventBusSubscriber(modid = L2Core.MODID, bus = EventBusSubscriber.Bus.GAME)
public class BaseCapabilityEvents {
@SubscribeEvent
public static void onLivingTick(EntityTickEvent.Post event) {
if (event.getEntity() instanceof LivingEntity le && le.isAlive()) {
for (GeneralCapabilityHolder<?, ?> holder : GeneralCapabilityHolder.INTERNAL_MAP.values()) {
if (holder.isFor(event.getEntity()))
holder.getOrCreate(Wrappers.cast(event.getEntity())).tick(Wrappers.cast(event.getEntity()));
}
public static void onPlayerTick(PlayerTickEvent.Post event) {
if (event.getEntity().isAlive())
for (PlayerCapabilityHolder<?> holder : PlayerCapabilityHolder.INTERNAL_MAP.values()) {
holder.getOrCreate(event.getEntity()).tick(event.getEntity());
}
}
@@ -30,6 +26,13 @@ public class BaseCapabilityEvents {
for (PlayerCapabilityHolder<?> holder : PlayerCapabilityHolder.INTERNAL_MAP.values()) {
ServerPlayer e = (ServerPlayer) event.getEntity();
holder.getOrCreate(e).onClone(e, event.isWasDeath());
}
}
@SubscribeEvent(priority = EventPriority.LOW)
public static void onPlayerJoinLevel(EntityJoinLevelEvent event) {
if (!(event.getEntity() instanceof ServerPlayer e)) return;
for (PlayerCapabilityHolder<?> holder : PlayerCapabilityHolder.INTERNAL_MAP.values()) {
holder.network.toClient(e);
holder.network.toTracking(e);
}

View File

@@ -9,6 +9,7 @@ import dev.xkmc.l2core.base.effects.ClientEffectCap;
import dev.xkmc.l2core.base.effects.EffectToClient;
import dev.xkmc.l2core.base.effects.api.*;
import dev.xkmc.l2core.init.L2Core;
import dev.xkmc.l2core.init.L2CoreConfig;
import dev.xkmc.l2core.init.L2LibReg;
import dev.xkmc.l2core.util.Proxy;
import net.minecraft.Util;
@@ -76,10 +77,18 @@ public class ClientEffectRenderEvents {
.createCompositeState(false)
));
public static RenderType get2DIcon(ResourceLocation id) {
return ICON_TYPE.apply(id);
}
@SubscribeEvent
public static void levelRenderLast(RenderLevelStageEvent event) {
if (event.getStage() != RenderLevelStageEvent.Stage.AFTER_WEATHER) return;
if (ICONS.isEmpty()) return;
if (!L2CoreConfig.CLIENT.renderOverlayIcons.get()) {
ICONS.clear();
return;
}
DUMMY.setupRenderState();
DUMMY.clearRenderState();
MultiBufferSource.BufferSource buffers = Minecraft.getInstance().renderBuffers().bufferSource();
@@ -123,6 +132,10 @@ public class ClientEffectRenderEvents {
}
}
if (entity == Minecraft.getInstance().getCameraEntity()) {
return;
}
int n = index;
int w = (int) Math.ceil(Math.sqrt(n));
int h = (int) Math.ceil(n * 1d / w);

View File

@@ -1,7 +1,6 @@
package dev.xkmc.l2core.events;
import com.mojang.datafixers.util.Either;
import dev.xkmc.l2core.init.L2Core;
import dev.xkmc.l2core.init.L2CoreConfig;
import dev.xkmc.l2core.init.L2LibReg;
import dev.xkmc.l2core.init.reg.ench.CustomDescEnchantment;
@@ -19,9 +18,9 @@ import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Items;
import net.minecraft.world.item.enchantment.EnchantmentHelper;
import net.neoforged.api.distmarker.Dist;
import net.neoforged.api.distmarker.OnlyIn;
import net.neoforged.bus.api.EventPriority;
import net.neoforged.bus.api.SubscribeEvent;
import net.neoforged.fml.common.EventBusSubscriber;
import net.neoforged.neoforge.event.entity.player.ItemTooltipEvent;
import java.util.ArrayList;
@@ -29,13 +28,13 @@ import java.util.Collection;
import java.util.List;
import java.util.stream.Stream;
@EventBusSubscriber(value = Dist.CLIENT, modid = L2Core.MODID, bus = EventBusSubscriber.Bus.GAME)
public class ClientEventHandler {
public enum EnchDesc {
DISABLE, SHIFT_ONLY, ALWAYS
}
@OnlyIn(Dist.CLIENT)
@SubscribeEvent(priority = EventPriority.LOW)
public static void modifyItemTooltip(ItemTooltipEvent event) {
var config = L2CoreConfig.CLIENT.addEnchantmentDescription.get();
@@ -61,7 +60,7 @@ public class ClientEventHandler {
for (int i = 0; i < n; i++) {
Component comp = list.get(i);
Component lit;
if (comp.getContents() instanceof PlainTextContents.LiteralContents txt && comp.getSiblings().size() == 1) {
if (comp.getContents() instanceof PlainTextContents txt && !comp.getSiblings().isEmpty()) {
comp = comp.getSiblings().getFirst();
lit = Component.literal(txt.text());
} else lit = Component.empty();

View File

@@ -3,13 +3,17 @@ package dev.xkmc.l2core.init;
import dev.xkmc.l2core.base.effects.EffectToClient;
import dev.xkmc.l2core.capability.conditionals.TokenToClient;
import dev.xkmc.l2core.capability.player.PlayerCapToClient;
import dev.xkmc.l2core.events.ClientEventHandler;
import dev.xkmc.l2core.init.reg.registrate.L2Registrate;
import dev.xkmc.l2core.serial.config.SyncPacket;
import dev.xkmc.l2serial.network.PacketHandler;
import dev.xkmc.l2serial.serialization.custom_handler.Handlers;
import net.minecraft.resources.ResourceLocation;
import net.neoforged.api.distmarker.Dist;
import net.neoforged.bus.api.IEventBus;
import net.neoforged.fml.ModList;
import net.neoforged.fml.common.Mod;
import net.neoforged.neoforge.common.NeoForge;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
@@ -31,11 +35,15 @@ public class L2Core {
e -> e.create(SyncPacket.class, PLAY_TO_CLIENT)
);
public L2Core(IEventBus bus) {
public L2Core(IEventBus bus, Dist currentDist) {
L2LibReg.register();
L2CoreConfig.init();
Handlers.register();
REGISTRATE.addDataGenerator(L2TagGen.EFF_TAGS, L2TagGen::onEffectTagGen);
if (!ModList.get().isLoaded("enchdesc") && currentDist == Dist.CLIENT) {
NeoForge.EVENT_BUS.register(ClientEventHandler.class);
}
}
public static ResourceLocation loc(String id) {

View File

@@ -10,6 +10,7 @@ public class L2CoreConfig {
public final ModConfigSpec.IntValue overlayZVal;
public final ModConfigSpec.EnumValue<ClientEventHandler.EnchDesc> addEnchantmentDescription;
public final ModConfigSpec.BooleanValue renderOverlayIcons;
Client(Builder builder) {
markL2();
@@ -17,6 +18,8 @@ public class L2CoreConfig {
.defineInRange("overlayZVal", 250, -1000000, 1000000);
addEnchantmentDescription = builder.text("Add Enchantment Descriptions")
.defineEnum("addEnchantmentDescription", ClientEventHandler.EnchDesc.ALWAYS);
renderOverlayIcons = builder.text("Render overlay icons on entities")
.define("renderOverlayIcons", true);
}
}

View File

@@ -2,6 +2,8 @@ package dev.xkmc.l2core.init;
import dev.xkmc.l2core.base.effects.ClientEffectCap;
import dev.xkmc.l2core.base.menu.base.MenuLayoutConfig;
import dev.xkmc.l2core.base.worldgen.ConfigChancePlacement;
import dev.xkmc.l2core.base.worldgen.ConfigRarityFilter;
import dev.xkmc.l2core.capability.conditionals.ConditionalData;
import dev.xkmc.l2core.capability.conditionals.PlayerFlagData;
import dev.xkmc.l2core.capability.player.PlayerCapabilityNetworkHandler;
@@ -21,6 +23,7 @@ import dev.xkmc.l2core.serial.loot.PlayerFlagCondition;
import dev.xkmc.l2serial.serialization.codec.MapCodecAdaptor;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.level.levelgen.placement.PlacementModifierType;
import net.minecraft.world.level.storage.loot.predicates.LootItemConditionType;
import net.neoforged.neoforge.common.conditions.ICondition;
import net.neoforged.neoforge.common.loot.IGlobalLootModifier;
@@ -73,6 +76,10 @@ public class L2LibReg {
public static final EECVal.Special<EnchColor> COLOR = ENCH_REG.special("color", EnchColor.CODEC);
public static final EECVal.Special<LegacyEnchantment> LEGACY = ENCH_REG.special("legacy", ENCH.reg().byNameCodec());
public static final SR<PlacementModifierType<?>> PM = SR.of(REG, BuiltInRegistries.PLACEMENT_MODIFIER_TYPE);
public static final Val<PlacementModifierType<ConfigRarityFilter>> PM_RARITY = PM.reg("rarity", () -> () -> ConfigRarityFilter.CODEC);
public static final Val<PlacementModifierType<ConfigChancePlacement>> PM_CHANCE = PM.reg("chance", () -> () -> ConfigChancePlacement.CODEC);
public static void register() {
}

View File

@@ -33,25 +33,34 @@ public interface EnchVal {
ResourceKey<Enchantment> id();
@DataGenOnly
Holder<Enchantment> datagenDirect(RegistrateProvider pvd);
Holder<Enchantment> datagenDirect();
@DataGenOnly
default Holder<Enchantment> datagenDirect(RegistrateProvider pvd) {
return datagenDirect();
}
default Optional<Holder<Enchantment>> safeHolder() {
return Optional.ofNullable(CommonHooks.resolveLookup(Registries.ENCHANTMENT)).flatMap(e -> e.get(id()));
}
default Holder<Enchantment> holder() {
return Optional.ofNullable(CommonHooks.resolveLookup(Registries.ENCHANTMENT)).orElseThrow().getOrThrow(id());
return safeHolder().orElseThrow();
}
default int getLv(ItemStack stack) {
return stack.getEnchantmentLevel(holder());
return safeHolder().map(stack::getEnchantmentLevel).orElse(0);
}
default int getLvIntrinsic(ItemStack stack) {
return stack.getOrDefault(DataComponents.ENCHANTMENTS, ItemEnchantments.EMPTY).getLevel(holder());
return safeHolder().map(e -> stack.getOrDefault(DataComponents.ENCHANTMENTS, ItemEnchantments.EMPTY).getLevel(e)).orElse(0);
}
interface Impl extends EnchVal {
Lazy<Builder> builder();
@Override
default Holder<Enchantment> datagenDirect(RegistrateProvider pvd) {
default Holder<Enchantment> datagenDirect() {
var val = builder().get().cache;
if (val == null) throw new IllegalStateException("Enchantment is not built yet");
return new DataGenHolder<>(id(), val);

View File

@@ -14,6 +14,7 @@ import dev.xkmc.l2core.init.L2Core;
import dev.xkmc.l2core.init.reg.simple.Val;
import dev.xkmc.l2core.util.ConfigInit;
import dev.xkmc.l2serial.serialization.custom_handler.CodecHandler;
import dev.xkmc.l2serial.serialization.custom_handler.Handlers;
import dev.xkmc.l2serial.util.ModContainerHack;
import dev.xkmc.l2serial.util.Wrappers;
import net.minecraft.client.particle.ParticleEngine;
@@ -21,7 +22,6 @@ import net.minecraft.client.particle.ParticleProvider;
import net.minecraft.core.Registry;
import net.minecraft.core.particles.ParticleOptions;
import net.minecraft.core.particles.ParticleType;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.core.registries.Registries;
import net.minecraft.network.chat.Component;
import net.minecraft.network.codec.ByteBufCodecs;
@@ -101,6 +101,10 @@ public class L2Registrate extends AbstractRegistrate<L2Registrate> {
}
public <T extends Potion> SimpleEntry<Potion> potion(String name, NonNullSupplier<T> sup) {
return potion(name, RegistrateLangProvider.toEnglishName(name), sup);
}
public <T extends Potion> SimpleEntry<Potion> potion(String name, String desc, NonNullSupplier<T> sup) {
RegistryEntry<Potion, T> ans = entry(name, (cb) -> new NoConfigBuilder<>(this, this, name, cb,
Registries.POTION, sup)).register();
if (doDataGen.get()) {
@@ -111,7 +115,7 @@ public class L2Registrate extends AbstractRegistrate<L2Registrate> {
String str = item.getDescriptionId() + ".effect." + name;
String pref_name = RegistrateLangProvider.toEnglishName(prefs[prefs.length - 1]);
if (item == Items.TIPPED_ARROW) pref_name = "Arrow";
addRawLang(str, pref_name + " of " + RegistrateLangProvider.toEnglishName(name));
addRawLang(str, pref_name + " of " + desc);
}
}
return new SimpleEntry<>(ans);
@@ -142,6 +146,7 @@ public class L2Registrate extends AbstractRegistrate<L2Registrate> {
cons.accept(ans);
var reg = ans.create();
new CodecHandler<>(Wrappers.cast(cls), reg.byNameCodec(), ByteBufCodecs.fromCodecWithRegistries(reg.byNameCodec()));
Handlers.registerReg(Wrappers.cast(cls), key);
OneTimeEventReceiver.addModListener(this, NewRegistryEvent.class, (e) -> e.register(reg));
return new RegistryInstance<>(reg, key);
}
@@ -242,13 +247,6 @@ public class L2Registrate extends AbstractRegistrate<L2Registrate> {
before = e.id;
}
}
for (var e : BuiltInRegistries.CREATIVE_MODE_TAB.entrySet()) {
var id = e.getKey().location();
if (known(id) || known(e.getValue())) {
continue;
}
b.withTabsAfter(id);
}
}
private static boolean known(ResourceLocation id) {

View File

@@ -1,6 +1,7 @@
package dev.xkmc.l2core.init.reg.registrate;
import dev.xkmc.l2serial.util.Wrappers;
import net.minecraft.core.Holder;
import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.MutableComponent;
import net.minecraft.resources.ResourceLocation;
@@ -46,4 +47,8 @@ public class NamedEntry<T extends NamedEntry<T>> {
return Wrappers.cast(this);
}
public Holder<T> holder() {
return registry.get().wrapAsHolder(getThis());
}
}

View File

@@ -0,0 +1,141 @@
package dev.xkmc.l2core.init.reg.registrate;
import com.google.common.collect.ListMultimap;
import com.google.common.collect.Multimaps;
import com.tterrag.registrate.providers.RegistrateLangProvider;
import net.minecraft.core.Holder;
import net.minecraft.resources.ResourceKey;
import net.minecraft.world.effect.MobEffect;
import net.minecraft.world.effect.MobEffectInstance;
import net.minecraft.world.item.CreativeModeTab;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.Items;
import net.minecraft.world.item.alchemy.Potion;
import net.minecraft.world.item.alchemy.PotionBrewing;
import net.minecraft.world.item.alchemy.PotionContents;
import net.minecraft.world.item.alchemy.Potions;
import net.minecraft.world.level.ItemLike;
import net.neoforged.neoforge.common.NeoForge;
import net.neoforged.neoforge.event.brewing.RegisterBrewingRecipesEvent;
import javax.annotation.Nullable;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.TreeSet;
import java.util.function.Consumer;
import java.util.stream.Stream;
public class PotionBuilder {
public static class TabHolder {
private final ListMultimap<String, Holder<Potion>> potions;
private final String modid;
public TabHolder(String modid) {
potions = Multimaps.newListMultimap(new LinkedHashMap<>(), ArrayList::new);
this.modid = modid;
}
public Stream<Holder<Potion>> stream() {
List<String> ans = new ArrayList<>();
ans.add(modid);
var set = new TreeSet<>(potions.keySet());
set.remove(modid);
ans.addAll(set);
return ans.stream().flatMap(e -> potions.get(e).stream());
}
public synchronized void add(String modid, SimpleEntry<Potion> ans) {
potions.put(modid, ans);
}
}
private final List<Consumer<PotionBrewing.Builder>> recipes = new ArrayList<>();
private final TabHolder tab;
private final L2Registrate reg;
private PotionBuilder(L2Registrate reg, TabHolder tab) {
this.reg = reg;
this.tab = tab;
NeoForge.EVENT_BUS.addListener(this::registerBrewingRecipe);
}
public PotionBuilder(L2Registrate reg, PotionBuilder parent) {
this(reg, parent.tab);
}
public PotionBuilder(L2Registrate reg) {
this(reg, new TabHolder(reg.getModid()));
}
private void registerBrewingRecipe(RegisterBrewingRecipesEvent event) {
var builder = event.getBuilder();
recipes.forEach(e -> e.accept(builder));
}
public void addMix(Holder<Potion> source, ItemLike item, Holder<Potion> potion) {
recipes.add(e -> e.addMix(source, item.asItem(), potion));
}
public Holder<Potion> regPotion(String id, String name, Holder<MobEffect> sup, int dur, int amp) {
var ans = reg.potion(id, RegistrateLangProvider.toEnglishName(name), () -> new Potion(new MobEffectInstance(sup, dur, amp)));
tab.add(reg.getModid(), ans);
return ans;
}
public Holder<Potion> regPotion(String id, String nameId, Holder<MobEffect> sup, Holder<Potion> source, ItemLike item, int dur, int amp) {
var potion = regPotion(id, nameId, sup, dur, amp);
addMix(source, item, potion);
return potion;
}
public void regPotion2(String id, Holder<MobEffect> sup, ItemLike item, int dur, int durLong) {
var potion = regPotion(id, id, sup, Potions.AWKWARD, item, dur, 0);
regPotion("long_" + id, id, sup, potion, Items.REDSTONE, durLong, 0);
}
public void regPotion3(String id, Holder<MobEffect> sup, ItemLike item, int durStrong, int dur, int durLong, int amp, int ampStrong) {
var potion = regPotion(id, id, sup, Potions.AWKWARD, item, dur, amp);
regPotion("long_" + id, id, sup, potion, Items.REDSTONE, durLong, amp);
regPotion("strong_" + id, id, sup, potion, Items.GLOWSTONE_DUST, durStrong, ampStrong);
}
public void regPotion3(String id, Holder<MobEffect> sup, ItemLike item, int durStrong, int dur, int durLong, int amp, int ampStrong, ItemLike longItem, ItemLike strongItem) {
var potion = regPotion(id, id, sup, Potions.AWKWARD, item, dur, amp);
regPotion("long_" + id, id, sup, potion, longItem, durLong, amp);
regPotion("strong_" + id, id, sup, potion, strongItem, durStrong, ampStrong);
}
public void interleave(String id, Holder<MobEffect> sup, int durStrong, int dur, int durLong, int amp, int ampStrong,
ItemLike a, Holder<Potion> ap, @Nullable Holder<Potion> lap, @Nullable Holder<Potion> sap,
ItemLike b, Holder<Potion> bp, @Nullable Holder<Potion> lbp, @Nullable Holder<Potion> sbp) {
var potion = regPotion(id, id, sup, dur, amp);
var longPotion = regPotion("long_" + id, id, sup, potion, Items.REDSTONE, durLong, amp);
var strongPotion = regPotion("strong_" + id, id, sup, potion, Items.GLOWSTONE_DUST, durStrong, ampStrong);
addMix(ap, a, potion);
addMix(bp, b, potion);
if (lap != null) addMix(lap, a, longPotion);
if (lbp != null) addMix(lbp, b, longPotion);
if (sap != null) addMix(sap, a, strongPotion);
if (sbp != null) addMix(sbp, b, strongPotion);
}
public void regTab(ResourceKey<CreativeModeTab> key) {
regTab(key, Items.POTION);
regTab(key, Items.SPLASH_POTION);
regTab(key, Items.LINGERING_POTION);
}
private void regTab(ResourceKey<CreativeModeTab> key, Item potion) {
reg.modifyCreativeModeTab(key, m -> tab.stream().forEach(e ->
m.accept(PotionContents.createItemStack(potion, e),
CreativeModeTab.TabVisibility.PARENT_TAB_ONLY)));
}
}

View File

@@ -8,6 +8,7 @@ import dev.xkmc.l2core.capability.player.PlayerCapabilityTemplate;
import net.minecraft.resources.ResourceLocation;
import net.neoforged.neoforge.attachment.AttachmentHolder;
import net.neoforged.neoforge.attachment.AttachmentType;
import net.neoforged.neoforge.attachment.IAttachmentHolder;
import net.neoforged.neoforge.registries.DeferredHolder;
import net.neoforged.neoforge.registries.DeferredRegister;
import net.neoforged.neoforge.registries.NeoForgeRegistries;
@@ -32,7 +33,7 @@ public record AttReg(DeferredRegister<AttachmentType<?>> att) {
return reg(id, type);
}
public <E extends GeneralCapabilityTemplate<H, E>, H extends AttachmentHolder> AttVal.CapVal<H, E>
public <E extends GeneralCapabilityTemplate<H, E>, H extends IAttachmentHolder> AttVal.CapVal<H, E>
entity(String id, Class<E> holder_class, Supplier<E> sup, Class<H> entity_class, Predicate<H> pred) {
ResourceLocation rl = ResourceLocation.fromNamespaceAndPath(att.getNamespace(), id);
var type = new GeneralCapabilityHolder<>(rl, holder_class, sup, entity_class, pred);
@@ -62,7 +63,7 @@ public record AttReg(DeferredRegister<AttachmentType<?>> att) {
}
private record CapValImpl<E extends AttachmentHolder, T extends GeneralCapabilityTemplate<E, T>>(
private record CapValImpl<E extends IAttachmentHolder, T extends GeneralCapabilityTemplate<E, T>>(
DeferredHolder<AttachmentType<?>, AttachmentType<T>> val, GeneralCapabilityHolder<E, T> type
) implements AttVal.CapVal<E, T> {

View File

@@ -7,12 +7,13 @@ import dev.xkmc.l2core.capability.player.PlayerCapabilityHolder;
import dev.xkmc.l2core.capability.player.PlayerCapabilityTemplate;
import net.neoforged.neoforge.attachment.AttachmentHolder;
import net.neoforged.neoforge.attachment.AttachmentType;
import net.neoforged.neoforge.attachment.IAttachmentHolder;
public interface AttVal<T, H extends AttachmentDef<T>> extends Val<AttachmentType<T>> {
H type();
interface CapVal<E extends AttachmentHolder, T extends GeneralCapabilityTemplate<E, T>>
interface CapVal<E extends IAttachmentHolder, T extends GeneralCapabilityTemplate<E, T>>
extends AttVal<T, GeneralCapabilityHolder<E, T>> {
}

View File

@@ -3,9 +3,10 @@ package dev.xkmc.l2core.init.reg.varitem;
import com.tterrag.registrate.util.entry.ItemEntry;
import net.minecraft.world.item.Item;
import net.minecraft.world.level.ItemLike;
import org.jetbrains.annotations.Nullable;
public class VarHolder<T extends Item> implements VarEntry<T>, ItemLike {
import java.util.function.Supplier;
public class VarHolder<T extends Item> implements VarEntry<T>, ItemLike, Supplier<T> {
private final String str;
private final VarBuilder<T> builder;
@@ -25,6 +26,11 @@ public class VarHolder<T extends Item> implements VarEntry<T>, ItemLike {
return item.asItem();
}
@Override
public T get() {
return item.get();
}
@Override
public String id() {
return str;

View File

@@ -2,7 +2,6 @@ package dev.xkmc.l2core.init.reg.varitem;
import com.google.gson.*;
import com.mojang.datafixers.util.Pair;
import com.tterrag.registrate.util.OneTimeEventReceiver;
import com.tterrag.registrate.util.entry.ItemEntry;
import dev.xkmc.l2core.init.L2Core;
import dev.xkmc.l2core.init.reg.registrate.L2Registrate;
@@ -14,12 +13,10 @@ import net.neoforged.fml.loading.FMLPaths;
import net.neoforged.neoforge.registries.RegisterEvent;
import org.apache.logging.log4j.Level;
import javax.annotation.Nullable;
import java.io.FileReader;
import java.io.FileWriter;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.function.Function;
@@ -41,7 +38,7 @@ public class VarItemInit<T extends Item> {
private final Function<ResourceLocation, T> func;
private final VarBuilder<T> builder;
private final Map<String, VarEntry<T>> defaults = new LinkedHashMap<>();
private final List<String> registered = new ArrayList<>();
private final Set<String> registered = new LinkedHashSet<>();
private final Map<String, ItemEntry<T>> results = new ConcurrentHashMap<>();
private VarItemInit(L2Registrate reg, ResourceLocation id, Function<ResourceLocation, T> func, VarBuilder<T> builder) {
@@ -61,6 +58,11 @@ public class VarItemInit<T extends Item> {
return e;
}
@Nullable
public ItemEntry<T> get(String str) {
return results.get(str);
}
private synchronized void init(RegisterEvent event) {
if (event.getRegistry() != BuiltInRegistries.ITEM) return;
load();
@@ -119,17 +121,24 @@ public class VarItemInit<T extends Item> {
private Pair<Boolean, List<String>> parseFile(JsonElement elem) {
if (!elem.isJsonArray()) return Pair.of(true, List.of());
List<String> ans = new ArrayList<>();
Set<String> ans = new LinkedHashSet<>(defaults.keySet());
Set<String> checker = new HashSet<>();
boolean err = false;
for (var e : elem.getAsJsonArray()) {
var rl = e.getAsString();
if (ResourceLocation.isValidPath(rl)) ans.add(rl);
else {
if (ResourceLocation.isValidPath(rl)) {
ans.add(rl);
checker.add(rl);
} else {
L2Core.LOGGER.error("Item ID {} for varitem type {} is invalid. Skipped", rl, id);
err = true;
}
}
return Pair.of(err, ans);
if (checker.size() != ans.size()) {
L2Core.LOGGER.error("Found missing default items for varitem type {}. Filling", id);
err = true;
}
return Pair.of(err, new ArrayList<>(ans));
}
private record SimpleVarEntry<T extends Item>(String id) implements VarEntry<T> {

View File

@@ -0,0 +1,17 @@
package dev.xkmc.l2core.mixin;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.world.item.CreativeModeTab;
import org.spongepowered.asm.mixin.Mixin;
@Mixin(CreativeModeTab.class)
public class CreativeModeTabMixin {
@Override
public String toString() {
CreativeModeTab tab = (CreativeModeTab) (Object) this;
var key = BuiltInRegistries.CREATIVE_MODE_TAB.getKey(tab);
return key == null ? "[Unregistered]" : key.toString();
}
}

View File

@@ -12,6 +12,7 @@ public class BaseConfigType<T extends BaseConfig> {
public final PacketHandlerWithConfig parent;
final Map<ResourceLocation, T> configs = new HashMap<>();
final Map<ResourceLocation, T> clientConfigs = new HashMap<>();
protected BaseConfigType(PacketHandlerWithConfig parent, String id, Class<T> cls) {
this.parent = parent;
@@ -26,4 +27,11 @@ public class BaseConfigType<T extends BaseConfig> {
public void afterReload() {
}
public void clientBeforeReload() {
clientConfigs.clear();
}
public void clientAfterReload() {
}
}

View File

@@ -1,6 +1,7 @@
package dev.xkmc.l2core.serial.config;
import com.google.gson.JsonElement;
import com.tterrag.registrate.providers.ProviderType;
import dev.xkmc.l2serial.serialization.codec.JsonCodec;
import net.minecraft.core.HolderLookup;
import net.minecraft.data.CachedOutput;

View File

@@ -1,16 +1,23 @@
package dev.xkmc.l2core.serial.config;
import dev.xkmc.l2core.util.ServerProxy;
import net.minecraft.resources.ResourceLocation;
public class MergedConfigType<T extends BaseConfig> extends BaseConfigType<T> {
private T result;
private T result, clientResult;
MergedConfigType(PacketHandlerWithConfig parent, String id, Class<T> cls) {
super(parent, id, cls);
}
T load() {
if (ServerProxy.isOnClient())
return loadClient();
return loadServer();
}
T loadServer() {
if (result != null) {
return result;
}
@@ -19,11 +26,28 @@ public class MergedConfigType<T extends BaseConfig> extends BaseConfigType<T> {
return result;
}
T loadClient() {
if (clientResult != null) {
return clientResult;
}
clientResult = new ConfigMerger<>(cls).apply(clientConfigs.values());
clientResult.id = ResourceLocation.fromNamespaceAndPath(parent.modid, id);
return clientResult;
}
@Override
public void afterReload() {
result = null;
if (cls.isAnnotationPresent(ConfigLoadOnStart.class)) {
load();
loadServer();
}
}
@Override
public void clientAfterReload() {
clientResult = null;
if (cls.isAnnotationPresent(ConfigLoadOnStart.class)) {
loadClient();
}
}

View File

@@ -114,25 +114,30 @@ public class PacketHandlerWithConfig extends PacketHandler {
private <T extends BaseConfig> void addJson(BaseConfigType<T> type, ResourceLocation k, JsonElement v) {
T config = new JsonCodec(getRegistryLookup()).from(v, type.cls, null);
if (config != null) {
addConfig(type, k, config);
addServerConfig(type, k, config);
}
}
private <T extends BaseConfig> void addConfig(BaseConfigType<T> type, ResourceLocation k, T config) {
private <T extends BaseConfig> void addServerConfig(BaseConfigType<T> type, ResourceLocation k, T config) {
config.id = k;
type.configs.put(k, config);
configs.add(new ConfigInstance(type.id, k, config));
}
private <T extends BaseConfig> void addClientConfig(BaseConfigType<T> type, ResourceLocation k, T config) {
config.id = k;
type.clientConfigs.put(k, config);
}
/**
* Called on client side only
*/
public void apply(ArrayList<ConfigInstance> list) {
listener_before.forEach(Runnable::run);
types.values().forEach(BaseConfigType::clientBeforeReload);
for (var e : list) {
addConfig(types.get(e.name), e.id(), Wrappers.cast(e.config));
addClientConfig(types.get(e.name), e.id(), Wrappers.cast(e.config));
}
listener_after.forEach(Runnable::run);
types.values().forEach(BaseConfigType::clientAfterReload);
}
}

View File

@@ -0,0 +1,53 @@
package dev.xkmc.l2core.serial.config;
import com.tterrag.registrate.AbstractRegistrate;
import com.tterrag.registrate.providers.ProviderType;
import com.tterrag.registrate.providers.RegistrateProvider;
import net.minecraft.core.HolderLookup;
import net.minecraft.data.CachedOutput;
import net.minecraft.data.DataGenerator;
import net.minecraft.data.DataProvider;
import net.neoforged.fml.LogicalSide;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.function.BiFunction;
public class RegistrateNestedProvider implements RegistrateProvider {
public static final ProviderType<RegistrateNestedProvider> TYPE = ProviderType.registerProvider("l2_custom", RegistrateNestedProvider::new);
private final List<DataProvider> list = new ArrayList<>();
private final AbstractRegistrate<?> reg;
private final DataGenerator gen;
private final CompletableFuture<HolderLookup.Provider> pvd;
public RegistrateNestedProvider(ProviderType.Context<RegistrateNestedProvider> ctx) {
this.reg = ctx.parent();
this.gen = ctx.event().getGenerator();
this.pvd = ctx.provider();
}
@Override
public LogicalSide getSide() {
return LogicalSide.SERVER;
}
public RegistrateNestedProvider add(BiFunction<DataGenerator, CompletableFuture<HolderLookup.Provider>, DataProvider> factory) {
list.add(factory.apply(gen, pvd));
return this;
}
@Override
public CompletableFuture<?> run(CachedOutput cachedOutput) {
reg.genData(TYPE, this);
return CompletableFuture.allOf(list.stream().map(e -> e.run(cachedOutput)).toArray(CompletableFuture[]::new));
}
@Override
public String getName() {
return "Custom Registrate Provider";
}
}

View File

@@ -5,6 +5,7 @@ import net.minecraft.MethodsReturnNonnullByDefault;
import net.minecraft.network.RegistryFriendlyByteBuf;
import net.minecraft.network.codec.StreamCodec;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Items;
import net.minecraft.world.item.crafting.Ingredient;
import net.minecraft.world.item.crafting.SmithingTransformRecipe;
@@ -14,7 +15,7 @@ import javax.annotation.ParametersAreNonnullByDefault;
@MethodsReturnNonnullByDefault
public abstract class AbstractSmithingRecipe<T extends AbstractSmithingRecipe<T>> extends SmithingTransformRecipe {
public static final Ingredient TEMPLATE_PLACEHOLDER = Ingredient.EMPTY;
public static final Ingredient TEMPLATE_PLACEHOLDER = Ingredient.of(Items.PAPER);
public AbstractSmithingRecipe(Ingredient template, Ingredient base, Ingredient addition, ItemStack result) {
super(template, base, addition, result);

View File

@@ -63,7 +63,7 @@ public class BaseRecipeBuilder<
.rewards(AdvancementRewards.Builder.recipe(id))
.requirements(AdvancementRequirements.Strategy.OR);
this.criteria.forEach(builder::addCriterion);
id = ResourceLocation.fromNamespaceAndPath(id.getNamespace(), "recipes/" +
id = ResourceLocation.fromNamespaceAndPath(id.getNamespace(),
BuiltInRegistries.RECIPE_SERIALIZER.getKey(type).getPath() + "/" + id.getPath());
pvd.accept(id, recipe, builder.build(id));
}

View File

@@ -5,8 +5,15 @@ import mezz.jei.api.gui.drawable.IDrawable;
import mezz.jei.api.recipe.IFocusGroup;
import mezz.jei.api.recipe.RecipeType;
import mezz.jei.api.recipe.category.IRecipeCategory;
import net.minecraft.client.Minecraft;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.item.crafting.Recipe;
import net.minecraft.world.item.crafting.RecipeHolder;
import net.minecraft.world.item.crafting.RecipeInput;
import java.util.List;
@Deprecated(forRemoval = true)
public abstract class BaseRecipeCategory<T, C extends BaseRecipeCategory<T, C>> implements IRecipeCategory<T> {
@SuppressWarnings("unchecked")

View File

@@ -1,9 +1,10 @@
package dev.xkmc.l2core.util;
import com.mojang.blaze3d.systems.RenderSystem;
import net.minecraft.client.Minecraft;
import net.minecraft.client.player.LocalPlayer;
import net.minecraft.core.RegistryAccess;
import net.minecraft.server.MinecraftServer;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.level.Level;
import net.neoforged.api.distmarker.Dist;
import net.neoforged.fml.loading.FMLEnvironment;
@@ -11,16 +12,15 @@ import net.neoforged.neoforge.server.ServerLifecycleHooks;
import javax.annotation.Nullable;
import java.util.Optional;
import java.util.function.BiConsumer;
public class Proxy {
@Deprecated
public static RegistryAccess getRegistryAccess() {
@Nullable
public static Player getPlayer() {
if (FMLEnvironment.dist == Dist.CLIENT) {
return Minecraft.getInstance().level.registryAccess();
return Minecraft.getInstance().player;
}
return ServerLifecycleHooks.getCurrentServer().registryAccess();
return null;
}
@Nullable
@@ -28,9 +28,14 @@ public class Proxy {
if (FMLEnvironment.dist == Dist.CLIENT) {
return Minecraft.getInstance().level;
}
return ServerLifecycleHooks.getCurrentServer().overworld();
var server = ServerLifecycleHooks.getCurrentServer();
if (server != null) {
return server.overworld();
}
return null;
}
@Deprecated
public static Optional<MinecraftServer> getServer() {
return Optional.ofNullable(ServerLifecycleHooks.getCurrentServer());
}
@@ -40,4 +45,7 @@ public class Proxy {
return Minecraft.getInstance().player;
}
static boolean isOnClient() {
return getServer().isEmpty() || RenderSystem.isOnRenderThread();
}
}

View File

@@ -0,0 +1,39 @@
package dev.xkmc.l2core.util;
import net.minecraft.core.RegistryAccess;
import net.minecraft.server.MinecraftServer;
import net.minecraft.world.level.Level;
import net.neoforged.api.distmarker.Dist;
import net.neoforged.fml.loading.FMLEnvironment;
import net.neoforged.neoforge.server.ServerLifecycleHooks;
import javax.annotation.Nullable;
import java.util.Optional;
public class ServerProxy {
@Nullable
public static RegistryAccess getRegistryAccess() {
if (FMLEnvironment.dist == Dist.CLIENT) {
Level level = Proxy.getLevel();
if (level != null) {
return level.registryAccess();
}
}
var server = ServerLifecycleHooks.getCurrentServer();
if (server != null) {
return server.registryAccess();
}
return null;
}
public static Optional<MinecraftServer> getServer() {
return Optional.ofNullable(ServerLifecycleHooks.getCurrentServer());
}
public static boolean isOnClient() {
if (FMLEnvironment.dist == Dist.DEDICATED_SERVER) return false;
return Proxy.isOnClient();
}
}

View File

@@ -6,5 +6,7 @@
"l2core.configuration.overlayZVal.tooltip": "默认值250",
"l2core.configuration.section.l2configs.l2core.client.toml": "莱特兰核心 - 客户端配置",
"l2core.configuration.section.l2configs.l2core.client.toml.title": "莱特兰核心 - 客户端配置",
"l2core.configuration.title": "莱特兰核心 - 配置"
"l2core.configuration.title": "莱特兰核心 - 配置",
"l2core.configuration.renderOverlayIcons": "实体图标显示",
"l2core.configuration.renderOverlayIcons.tooltip": ""
}

View File

@@ -4,6 +4,7 @@
"package": "dev.xkmc.l2core.mixin",
"compatibilityLevel": "JAVA_21",
"mixins": [
"CreativeModeTabMixin"
],
"client": [
],