broken data stuff

This commit is contained in:
candle 2025-10-05 15:05:39 -04:00
parent 8266691770
commit b3b4e48071
18 changed files with 122 additions and 137 deletions

3
.gitignore vendored
View File

@ -1,7 +1,8 @@
build/
bin/
run/
.idea/
.c*
.gradle/
gradle/
.architectury-transformer/
.architectury-transformer/

View File

@ -3,18 +3,11 @@ package io.lampnet.betterlodestones;
import io.lampnet.betterlodestones.component.BetterLodestonesComponents;
import net.minecraft.core.BlockPos;
import net.minecraft.core.GlobalPos;
import net.minecraft.core.registries.Registries;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.ListTag;
import net.minecraft.nbt.NbtOps;
import net.minecraft.nbt.Tag;
import net.minecraft.resources.ResourceKey;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.core.component.DataComponents;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.CompassItem;
import net.minecraft.world.item.ItemStack;
import net.minecraft.core.component.DataComponents;
import net.minecraft.world.item.enchantment.EnchantmentHelper;
import net.minecraft.world.item.component.LodestoneTracker;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.Blocks;
@ -26,26 +19,30 @@ import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Consumer;
public class CompassDataHandler {
private static final String LODESTONES_KEY = "BetterLodestones";
private static final String CURRENT_INDEX_KEY = "CurrentLodestoneIndex";
private static final String POS_X_KEY = "PosX";
private static final String POS_Y_KEY = "PosY";
private static final String POS_Z_KEY = "PosZ";
private static final String DIMENSION_KEY = "Dimension";
private static final String BROKEN_LODESTONE_FLAG = "BrokenLodestone";
public static List<GlobalPos> getLodestones(ItemStack compass) {
return compass.get(BetterLodestonesComponents.LODESTONES);
List<GlobalPos> lodestones = compass.get(BetterLodestonesComponents.LODESTONES.get());
return lodestones != null ? lodestones : Collections.emptyList();
}
public static void syncVanillaLodestoneTracker(ItemStack compass) {
Optional<GlobalPos> currentLodestone = getCurrentLodestone(compass);
if (currentLodestone.isPresent()) {
boolean tracked = !hasBrokenLodestone(compass);
compass.set(DataComponents.LODESTONE_TRACKER, new LodestoneTracker(currentLodestone, tracked));
} else {
compass.remove(DataComponents.LODESTONE_TRACKER);
}
}
public static void addLodestone(ItemStack compass, GlobalPos lodestone) {
List<GlobalPos> lodestones = new ArrayList<>(getLodestones(compass));
if (!lodestones.contains(lodestone)) {
lodestones.add(lodestone);
compass.set(BetterLodestonesComponents.LODESTONES, lodestones);
compass.set(BetterLodestonesComponents.LODESTONES.get(), lodestones);
if (lodestones.size() == 1) {
compass.set(BetterLodestonesComponents.CURRENT_LODESTONE_INDEX, 0);
compass.set(BetterLodestonesComponents.CURRENT_LODESTONE_INDEX.get(), 0);
}
syncVanillaLodestoneTracker(compass);
}
}
@ -54,20 +51,21 @@ public class CompassDataHandler {
int currentIndex = getCurrentLodestoneIndex(compass);
if (lodestones.remove(lodestone)) {
if (lodestones.isEmpty()) {
compass.remove(BetterLodestonesComponents.LODESTONES);
compass.remove(BetterLodestonesComponents.CURRENT_LODESTONE_INDEX);
compass.remove(BetterLodestonesComponents.LODESTONES.get());
compass.remove(BetterLodestonesComponents.CURRENT_LODESTONE_INDEX.get());
} else {
if (currentIndex >= lodestones.size()) {
currentIndex = lodestones.size() - 1;
}
compass.set(BetterLodestonesComponents.LODESTONES, lodestones);
compass.set(BetterLodestonesComponents.CURRENT_LODESTONE_INDEX, Math.max(0, currentIndex));
compass.set(BetterLodestonesComponents.LODESTONES.get(), lodestones);
compass.set(BetterLodestonesComponents.CURRENT_LODESTONE_INDEX.get(), Math.max(0, currentIndex));
}
syncVanillaLodestoneTracker(compass);
}
}
public static int getCurrentLodestoneIndex(ItemStack compass) {
return compass.getOrDefault(BetterLodestonesComponents.CURRENT_LODESTONE_INDEX, 0);
return compass.getOrDefault(BetterLodestonesComponents.CURRENT_LODESTONE_INDEX.get(), 0);
}
public static Optional<GlobalPos> getCurrentLodestone(ItemStack compass) {
@ -90,7 +88,7 @@ public class CompassDataHandler {
}
int currentIndex = getCurrentLodestoneIndex(compass);
int nextIndex = (currentIndex + 1) % lodestones.size();
compass.set(BetterLodestonesComponents.CURRENT_LODESTONE_INDEX, nextIndex);
compass.set(BetterLodestonesComponents.CURRENT_LODESTONE_INDEX.get(), nextIndex);
GlobalPos newLodestone = lodestones.get(nextIndex);
if (isLodestoneValid(level, newLodestone)) {
@ -107,9 +105,10 @@ public class CompassDataHandler {
}
public static void clearAllLodestones(ItemStack compass) {
compass.remove(BetterLodestonesComponents.LODESTONES);
compass.remove(BetterLodestonesComponents.CURRENT_LODESTONE_INDEX);
compass.remove(BetterLodestonesComponents.BROKEN_LODESTONE);
compass.remove(BetterLodestonesComponents.LODESTONES.get());
compass.remove(BetterLodestonesComponents.CURRENT_LODESTONE_INDEX.get());
compass.remove(BetterLodestonesComponents.BROKEN_LODESTONE.get());
syncVanillaLodestoneTracker(compass);
}
public static void removeCurrentLodestone(ItemStack compass) {
@ -187,15 +186,17 @@ public class CompassDataHandler {
}
public static void markLodestoneAsBroken(ItemStack compass) {
compass.set(BetterLodestonesComponents.BROKEN_LODESTONE, true);
compass.set(BetterLodestonesComponents.BROKEN_LODESTONE.get(), true);
syncVanillaLodestoneTracker(compass);
}
public static boolean hasBrokenLodestone(ItemStack compass) {
return compass.getOrDefault(BetterLodestonesComponents.BROKEN_LODESTONE, false);
return compass.getOrDefault(BetterLodestonesComponents.BROKEN_LODESTONE.get(), false);
}
public static void clearBrokenLodestoneFlag(ItemStack compass) {
compass.remove(BetterLodestonesComponents.BROKEN_LODESTONE);
compass.remove(BetterLodestonesComponents.BROKEN_LODESTONE.get());
syncVanillaLodestoneTracker(compass);
}
public static void onLodestoneRemoved(Level level, BlockPos removedPos) {
@ -250,18 +251,6 @@ public class CompassDataHandler {
}
}
private static boolean isSameLodestone(CompoundTag tag, GlobalPos lodestone) {
int x = tag.getInt("PosX");
int y = tag.getInt("PosY");
int z = tag.getInt("PosZ");
String dimension = tag.getString("Dimension");
return x == lodestone.pos().getX() &&
y == lodestone.pos().getY() &&
z == lodestone.pos().getZ() &&
dimension.equals(lodestone.dimension().location().toString());
}
public static boolean convertVanillaLodestoneCompass(ItemStack compass) {
if (compass == null || !(compass.getItem() instanceof CompassItem)) {
return false;
@ -274,7 +263,6 @@ public class CompassDataHandler {
lodestoneTarget.target().ifPresent(globalPos -> {
addLodestone(compass, globalPos);
compass.remove(DataComponents.LODESTONE_TRACKER);
});
return true;

View File

@ -0,0 +1,6 @@
package io.lampnet.betterlodestones.client;
public class BetterLodestonesClient {
public static void initClient() {
}
}

View File

@ -1,30 +1,34 @@
package io.lampnet.betterlodestones.component;
import com.mojang.serialization.Codec;
import dev.architectury.registry.registries.DeferredRegister;
import dev.architectury.registry.registries.RegistrySupplier;
import io.lampnet.betterlodestones.BetterLodestones;
import net.minecraft.core.GlobalPos;
import net.minecraft.core.Registry;
import net.minecraft.core.component.DataComponentType;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.core.registries.Registries;
import java.util.List;
import java.util.function.UnaryOperator;
public class BetterLodestonesComponents {
public static final DataComponentType<List<GlobalPos>> LODESTONES = register("lodestones", builder -> builder.persistent(Codec.list(GlobalPos.CODEC)).cacheEncoding());
public static final DataComponentType<Integer> CURRENT_LODESTONE_INDEX = register("current_lodestone_index", builder -> builder.persistent(Codec.INT).cacheEncoding());
public static final DataComponentType<Boolean> BROKEN_LODESTONE = register("broken_lodestone", builder -> builder.persistent(Codec.BOOL).cacheEncoding());
public static final DeferredRegister<DataComponentType<?>> DATA_COMPONENTS =
DeferredRegister.create(BetterLodestones.MOD_ID, Registries.DATA_COMPONENT_TYPE);
private static <T> DataComponentType<T> register(String name, UnaryOperator<DataComponentType.Builder<T>> builder) {
return Registry.register(
BuiltInRegistries.DATA_COMPONENT_TYPE,
ResourceLocation.fromNamespaceAndPath(BetterLodestones.MOD_ID, name),
builder.apply(DataComponentType.builder()).build()
);
public static final RegistrySupplier<DataComponentType<List<GlobalPos>>> LODESTONES =
register("lodestones", builder -> builder.persistent(Codec.list(GlobalPos.CODEC)).cacheEncoding());
public static final RegistrySupplier<DataComponentType<Integer>> CURRENT_LODESTONE_INDEX =
register("current_lodestone_index", builder -> builder.persistent(Codec.INT).cacheEncoding());
public static final RegistrySupplier<DataComponentType<Boolean>> BROKEN_LODESTONE =
register("broken_lodestone", builder -> builder.persistent(Codec.BOOL).cacheEncoding());
private static <T> RegistrySupplier<DataComponentType<T>> register(String name, UnaryOperator<DataComponentType.Builder<T>> builder) {
return DATA_COMPONENTS.register(name, () -> builder.apply(DataComponentType.builder()).build());
}
public static void init() {
// This method is called to ensure the components are registered
DATA_COMPONENTS.register();
}
}

View File

@ -1,6 +1,7 @@
package io.lampnet.betterlodestones.mixin;
import io.lampnet.betterlodestones.CompassDataHandler;
import io.lampnet.betterlodestones.advancement.DimensionalCompassBindingTrigger;
import io.lampnet.betterlodestones.config.ConfigManager;
import io.lampnet.betterlodestones.registry.BetterLodestonesRegistry;
import net.minecraft.core.BlockPos;
@ -72,7 +73,7 @@ public class CompassItemMixin {
level.playSound(null, pos, SoundEvents.LODESTONE_COMPASS_LOCK, SoundSource.PLAYERS, 1.0F, 1.0F);
if (player instanceof ServerPlayer serverPlayer) {
BetterLodestonesRegistry.DIMENSIONAL_COMPASS_BINDING.trigger(serverPlayer, compass);
((DimensionalCompassBindingTrigger) BetterLodestonesRegistry.DIMENSIONAL_COMPASS_BINDING.get()).trigger(serverPlayer, compass);
}
if (player != null) {

View File

@ -1,38 +0,0 @@
package io.lampnet.betterlodestones.mixin;
import io.lampnet.betterlodestones.CompassDataHandler;
import io.lampnet.betterlodestones.component.BetterLodestonesComponents;
import net.minecraft.core.GlobalPos;
import net.minecraft.core.component.DataComponentType;
import net.minecraft.core.component.DataComponents;
import net.minecraft.world.item.CompassItem;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.component.LodestoneTracker;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Redirect;
import org.spongepowered.asm.mixin.injection.Slice;
import java.util.Optional;
@Mixin(CompassItem.class)
public class CompassItemMixinPointing {
@Redirect(method = "<clinit>", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/item/ItemStack;has(Lnet/minecraft/core/component/DataComponentType;)Z"),
slice = @Slice(from = @At(value = "CONSTANT", args = "stringValue=angle"), to = @At(value = "CONSTANT", args = "stringValue=lodestone_angle")))
private static boolean hasCustomLodestone(ItemStack itemStack, DataComponentType<?> dataComponentType) {
if (dataComponentType == DataComponents.LODESTONE_TRACKER) {
return itemStack.has(DataComponents.LODESTONE_TRACKER) || itemStack.has(BetterLodestonesComponents.LODESTONES);
}
return itemStack.has(dataComponentType);
}
@Redirect(method = "<clinit>", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/item/ItemStack;get(Lnet/minecraft/core/component/DataComponentType;)Ljava/lang/Object;"),
slice = @Slice(from = @At(value = "CONSTANT", args = "stringValue=lodestone_angle")))
private static Object getCustomLodestoneTarget(ItemStack itemStack, DataComponentType<?> dataComponentType) {
if (dataComponentType == DataComponents.LODESTONE_TRACKER && itemStack.has(BetterLodestonesComponents.LODESTONES)) {
Optional<GlobalPos> current = CompassDataHandler.getCurrentLodestone(itemStack);
return current.map(globalPos -> new LodestoneTracker(Optional.of(globalPos), true)).orElse(null);
}
return itemStack.get(dataComponentType);
}
}

View File

@ -1,18 +1,12 @@
package io.lampnet.betterlodestones.recipe;
import com.google.gson.JsonObject;
import com.mojang.serialization.Codec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import io.lampnet.betterlodestones.CompassDataHandler;
import io.lampnet.betterlodestones.component.BetterLodestonesComponents;
import net.minecraft.core.HolderLookup;
import net.minecraft.core.RegistryAccess;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.network.RegistryFriendlyByteBuf;
import net.minecraft.network.codec.StreamCodec;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.item.crafting.CraftingInput;
import net.minecraft.world.inventory.CraftingContainer;
import net.minecraft.world.item.CompassItem;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Items;
@ -45,7 +39,7 @@ public class CompassUnbindingRecipe extends CustomRecipe {
}
}
return !compass.isEmpty() && (compass.has(BetterLodestonesComponents.LODESTONES) || compass.has(net.minecraft.core.component.DataComponents.LODESTONE_TRACKER));
return !compass.isEmpty() && (compass.has(BetterLodestonesComponents.LODESTONES.get()) || compass.has(net.minecraft.core.component.DataComponents.LODESTONE_TRACKER));
}
@Override
@ -82,12 +76,12 @@ public class CompassUnbindingRecipe extends CustomRecipe {
@Override
public @NotNull RecipeSerializer<?> getSerializer() {
return CompassUnbindingRecipeSerializer.INSTANCE;
return io.lampnet.betterlodestones.registry.BetterLodestonesRegistry.COMPASS_UNBINDING.get();
}
public static class CompassUnbindingRecipeSerializer implements RecipeSerializer<CompassUnbindingRecipe> {
public static final CompassUnbindingRecipeSerializer INSTANCE = new CompassUnbindingRecipeSerializer();
private static final Codec<CompassUnbindingRecipe> CODEC = RecordCodecBuilder.create(instance ->
private static final com.mojang.serialization.MapCodec<CompassUnbindingRecipe> CODEC = RecordCodecBuilder.mapCodec(instance ->
instance.group(
CraftingBookCategory.CODEC.fieldOf("category").orElse(CraftingBookCategory.MISC).forGetter(CustomRecipe::category)
).apply(instance, CompassUnbindingRecipe::new)
@ -99,7 +93,7 @@ public class CompassUnbindingRecipe extends CustomRecipe {
@Override
public @NotNull com.mojang.serialization.MapCodec<CompassUnbindingRecipe> codec() {
return CODEC.fieldOf("recipe");
return CODEC;
}
@Override

View File

@ -1,14 +1,10 @@
package io.lampnet.betterlodestones.recipe;
import com.google.gson.JsonObject;
import com.mojang.serialization.Codec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import io.lampnet.betterlodestones.config.ConfigManager;
import net.minecraft.core.HolderLookup;
import net.minecraft.core.RegistryAccess;
import net.minecraft.network.RegistryFriendlyByteBuf;
import net.minecraft.network.codec.StreamCodec;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.item.crafting.CraftingInput;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack;
@ -58,12 +54,12 @@ public class ConfigurableLodestoneRecipe extends CustomRecipe {
@Override
public @NotNull RecipeSerializer<?> getSerializer() {
return Serializer.INSTANCE;
return io.lampnet.betterlodestones.registry.BetterLodestonesRegistry.CONFIGURABLE_LODESTONE.get();
}
public static class Serializer implements RecipeSerializer<ConfigurableLodestoneRecipe> {
public static final Serializer INSTANCE = new Serializer();
private static final Codec<ConfigurableLodestoneRecipe> CODEC = RecordCodecBuilder.create(instance ->
private static final com.mojang.serialization.MapCodec<ConfigurableLodestoneRecipe> CODEC = RecordCodecBuilder.mapCodec(instance ->
instance.group(
CraftingBookCategory.CODEC.fieldOf("category").orElse(CraftingBookCategory.MISC).forGetter(CustomRecipe::category)
).apply(instance, ConfigurableLodestoneRecipe::new)
@ -75,7 +71,7 @@ public class ConfigurableLodestoneRecipe extends CustomRecipe {
@Override
public @NotNull com.mojang.serialization.MapCodec<ConfigurableLodestoneRecipe> codec() {
return CODEC.fieldOf("recipe");
return CODEC;
}
@Override

View File

@ -6,7 +6,7 @@ import io.lampnet.betterlodestones.BetterLodestones;
import io.lampnet.betterlodestones.advancement.DimensionalCompassBindingTrigger;
import io.lampnet.betterlodestones.recipe.CompassUnbindingRecipe;
import io.lampnet.betterlodestones.recipe.ConfigurableLodestoneRecipe;
import net.minecraft.advancements.CriteriaTriggers;
import net.minecraft.advancements.CriterionTrigger;
import net.minecraft.core.registries.Registries;
import net.minecraft.world.item.crafting.RecipeSerializer;
@ -20,10 +20,14 @@ public final class BetterLodestonesRegistry {
public static final RegistrySupplier<RecipeSerializer<?>> COMPASS_UNBINDING =
RECIPE_SERIALIZERS.register("compass_unbinding", () -> CompassUnbindingRecipe.CompassUnbindingRecipeSerializer.INSTANCE);
public static final DimensionalCompassBindingTrigger DIMENSIONAL_COMPASS_BINDING =
CriteriaTriggers.register("dimensional_compass_binding", new DimensionalCompassBindingTrigger());
public static final DeferredRegister<CriterionTrigger<?>> CRITERION_TRIGGERS =
DeferredRegister.create(BetterLodestones.MOD_ID, Registries.TRIGGER_TYPE);
public static final RegistrySupplier<CriterionTrigger<DimensionalCompassBindingTrigger.TriggerInstance>> DIMENSIONAL_COMPASS_BINDING =
CRITERION_TRIGGERS.register("dimensional_compass_binding", DimensionalCompassBindingTrigger::new);
public static void init() {
RECIPE_SERIALIZERS.register();
CRITERION_TRIGGERS.register();
}
}

View File

@ -7,7 +7,6 @@
],
"mixins": [
"CompassItemMixin",
"CompassItemMixinPointing",
"CompassTooltipMixin",
"InventoryInteractionMixin",
"ItemPickupMixin",

View File

@ -1,9 +1,11 @@
{
"parent": "minecraft:nether/use_lodestone",
"parent": "minecraft:adventure/use_lodestone",
"display": {
"icon": {
"item": "minecraft:compass",
"nbt": "{CustomModelData:1}"
"id": "minecraft:compass",
"components": {
"minecraft:custom_model_data": 1
}
},
"title": {
"translate": "advancements.better_lodestones.dimensional_lodestone_master.title"

View File

@ -1,3 +1,4 @@
{
"type": "better_lodestones:compass_unbinding"
"type": "better_lodestones:compass_unbinding",
"category": "misc"
}

View File

@ -1,3 +1,4 @@
{
"type": "better_lodestones:configurable_lodestone"
"type": "better_lodestones:configurable_lodestone",
"category": "building"
}

View File

@ -2,7 +2,7 @@
"parent": "minecraft:adventure/root",
"display": {
"icon": {
"item": "minecraft:lodestone"
"id": "minecraft:lodestone"
},
"title": {
"translate": "advancements.nether.use_lodestone.title"
@ -19,22 +19,16 @@
"use_lodestone": {
"trigger": "minecraft:item_used_on_block",
"conditions": {
"location": [
{
"condition": "minecraft:match_tool",
"predicate": {
"items": [
"minecraft:compass"
]
}
}
],
"item": {
"items": [
"minecraft:compass"
]
},
"block": "minecraft:lodestone"
"location": {
"block": {
"blocks": "minecraft:lodestone"
}
}
}
}
}

View File

@ -1,3 +1,4 @@
{
"type": "better_lodestones:configurable_lodestone"
"type": "better_lodestones:configurable_lodestone",
"category": "building"
}

View File

@ -0,0 +1,11 @@
package io.lampnet.betterlodestones.fabric;
import io.lampnet.betterlodestones.client.BetterLodestonesClient;
import net.fabricmc.api.ClientModInitializer;
public final class BetterLodestonesFabricClient implements ClientModInitializer {
@Override
public void onInitializeClient() {
BetterLodestonesClient.initClient();
}
}

View File

@ -16,6 +16,9 @@
"entrypoints": {
"main": [
"io.lampnet.betterlodestones.fabric.BetterLodestonesFabric"
],
"client": [
"io.lampnet.betterlodestones.fabric.BetterLodestonesFabricClient"
]
},
"mixins": [

View File

@ -0,0 +1,17 @@
package io.lampnet.betterlodestones.neoforge;
import io.lampnet.betterlodestones.BetterLodestones;
import io.lampnet.betterlodestones.client.BetterLodestonesClient;
import net.neoforged.api.distmarker.Dist;
import net.neoforged.bus.api.SubscribeEvent;
import net.neoforged.fml.common.EventBusSubscriber;
import net.neoforged.fml.event.lifecycle.FMLClientSetupEvent;
@EventBusSubscriber(modid = BetterLodestones.MOD_ID, value = Dist.CLIENT)
public class BetterLodestonesNeoForgeClient {
@SubscribeEvent
public static void onClientSetup(FMLClientSetupEvent event) {
event.enqueueWork(BetterLodestonesClient::initClient);
}
}