backup2 -> still not functional

This commit is contained in:
Paula 2024-06-01 11:50:04 +02:00
parent 936c50e13c
commit 44992f0c07
53 changed files with 1813 additions and 150 deletions

View File

@ -1,25 +1,78 @@
package modchest;
import modchest.assets.OverlayAssetListener;
import modchest.assets.overlay.OffsetterRegistry;
import modchest.assets.overlay.ZeroOffsetter;
import modchest.block.custom.gridCodecs;
import modchest.block.custom.gridPreviewOutline;
import modchest.gui.gridScreen;
import modchest.networking.modNetworkingClient;
import modchest.transform.gridTransform;
import net.fabricmc.api.ClientModInitializer;
import net.fabricmc.fabric.api.client.model.ModelLoadingRegistry;
import net.fabricmc.fabric.api.client.rendering.v1.WorldRenderEvents;
import net.fabricmc.fabric.api.client.screenhandler.v1.ScreenRegistry;
import net.fabricmc.fabric.api.event.client.ClientSpriteRegistryCallback;
import net.fabricmc.fabric.api.object.builder.v1.client.model.FabricModelPredicateProviderRegistry;
import net.fabricmc.fabric.api.renderer.v1.render.RenderContext.QuadTransform;
import net.fabricmc.fabric.api.resource.ResourceManagerHelper;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.texture.SpriteAtlasTexture;
import net.minecraft.client.util.ModelIdentifier;
import net.minecraft.resource.ResourceType;
import net.minecraft.util.Identifier;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.mojang.serialization.Codec;
public class REServerModClient implements ClientModInitializer {
public static gridCodecs CODECS;
public static OverlayAssetListener CLIENT_OVERLAYS;
public static final Logger LOGGER = LoggerFactory.getLogger("modchest"); // Erster Error Logger
@SuppressWarnings("deprecation")
@Override
public void onInitializeClient() {
// This entrypoint is suitable for setting up client-specific logic, such as rendering.
final Identifier zeroId = REServerMod.META.id("zero");
OffsetterRegistry.register(zeroId, Codec.unit(new ZeroOffsetter(zeroId)));
REServerModClient.CODECS = new gridCodecs();
modNetworkingClient.registerC2SPackets(); //Identifier unter denen der Client zuhoert werden registriert
QuadTransformRegistry.INSTANCE.register(REServerMod.META.id("grid_transform"), gridTransform.SOURCE);
ScreenRegistry.register(REServerMod.META.GRID_SCREEN_HANDLER_TYPE, gridScreen.FACTORY);
ClientSpriteRegistryCallback.event(SpriteAtlasTexture.BLOCK_ATLAS_TEXTURE).register((atlas, registry) -> {
final int textureStart = "textures/".length();
final int pngLen = ".png".length();
for (final Identifier id : MinecraftClient.getInstance().getResourceManager().findResources("textures/grid",
s -> s.endsWith(".png"))) {
registry.register(new Identifier(id.getNamespace(),
id.getPath().substring(textureStart, id.getPath().length() - pngLen)));
}
});
CLIENT_OVERLAYS = new OverlayAssetListener();
ResourceManagerHelper.get(ResourceType.CLIENT_RESOURCES).registerReloadListener(CLIENT_OVERLAYS);
ModelLoadingRegistry.INSTANCE.registerModelProvider(
(resourceManager, out) -> out
.accept(new ModelIdentifier(REServerMod.META.id("hammer_none"), "inventory")));
FabricModelPredicateProviderRegistry.register(
REServerMod.ITEMS.HAMMER,
REServerMod.META.id("hammer_mode"),
(stack, world, entity) -> Optional.ofNullable(stack.getTag())
.map(t -> t.getString("mode"))
.flatMap(Hammer.CopyMode::fromString)
.orElse(Hammer.CopyMode.DEFAULT).id);
WorldRenderEvents.AFTER_ENTITIES.register(gridPreviewOutline::renderPreviewOutline);
// This entrypoint is suitable for setting up client-specific logic, such as rendering.
modNetworkingClient.registerC2SPackets(); // Identifier unter denen der Client zuhoert werden registriert
LOGGER.info("Modchest-Client successfully loaded!");
}

View File

@ -18,10 +18,11 @@ import com.google.gson.JsonElement;
import com.mojang.serialization.DataResult;
import com.mojang.serialization.JsonOps;
import modchest.REServerMod;
import modchest.assets.overlay.Overlay;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.fabricmc.fabric.api.resource.SimpleResourceReloadListener;
import net.minecraft.client.gui.screen.Overlay;
import net.minecraft.resource.ResourceManager;
import net.minecraft.util.Identifier;
import net.minecraft.util.Pair;
@ -41,10 +42,12 @@ public class OverlayAssetListener implements SimpleResourceReloadListener<Collec
Executor executor) {
return CompletableFuture.supplyAsync(() -> {
overlayInfoMap.clear();
return resourceManager.findResources("modchest/overlays", s -> s.endsWith(".json"));
return manager.findResources("modchest/overlays", s -> s.endsWith(".json"));
}, executor);
}
private DataResult<Unit> parseOverlayAndDependencies(final ResourceManager resourceManager,
final Identifier rootOverlayId) {
final Set<Identifier> loadedDependencies = new HashSet<>();
@ -60,8 +63,12 @@ public class OverlayAssetListener implements SimpleResourceReloadListener<Collec
final Set<Identifier> loadedDependencies, final Identifier overlayId) {
final JsonElement element;
try {
element = new Gson().fromJson(
new BufferedReader(new InputStreamReader(resourceManager.getResource(overlayId).getInputStream())),
element = new Gson().fromJson(new BufferedReader(new InputStreamReader(resourceManager.get(overlayId).getInputStream()), JsonElement.class);
)}
/*new BufferedReader(new InputStreamReader(resourceManager.getResource(overlayId).getInputStream())),
JsonElement.class);
} catch (final IOException e) {
return DataResult.error("Exception while loading an overlay:");
@ -83,20 +90,21 @@ public class OverlayAssetListener implements SimpleResourceReloadListener<Collec
overlayInfoMap.put(overlayId, pair.getFirst());
});
return result.map(p -> Unit.INSTANCE);
}
}*/
@Override
public CompletableFuture<Void> apply(Collection<Identifier> data, ResourceManager manager, Profiler profiler,
Executor executor) {
return CompletableFuture.runAsync(() -> {
for (final Identifier id : identifiers) {
for (final Identifier id : data) {
final DataResult<Unit> result = parseOverlayAndDependencies(manager, id);
result.get().ifRight(partial -> META.LOGGER
.warn("Error while parsing overlay \"" + id + "\": " + partial.message()));
result.get().ifRight(partial -> REServerMod.META.LOGGER.warning("Error while parsing overlay \"" + id + "\": " + partial.message()));
}
}, executor);
}
private final Identifier id = REServerMod.META.id("assets/overlay");
@Override
public Identifier getFabricId() {
return id;

View File

@ -4,7 +4,7 @@ import java.util.Optional;
import java.util.function.Function;
import java.util.function.Supplier;
import modchest.util.ToOptional;
import modchest.REServerMod;
import modchest.util.Float4;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
@ -16,7 +16,7 @@ public interface Offsetter extends ToOptional<Offsetter> {
public Identifier getId();
Identifier NONE_ID = META.id("none");
Identifier NONE_ID = REServerMod.META.id("none");
Offsetter NONE = new Offsetter() {
@Override

View File

@ -17,6 +17,7 @@ public class OffsetterRegistry {
private static final Map<Identifier, Identifiable<Codec<Offsetter>>> registeredOffsetters = new HashMap<>();
@SuppressWarnings("unused")
private static void register(final Identifier id, final Codec<Offsetter> codec) {
registeredOffsetters.put(id, new Identifiable<>(codec, id));
}

View File

@ -1,20 +1,19 @@
package modchest.assets.overlay;
import org.jetbrains.annotations.Nullable;
import java.util.Optional;
import com.mojang.serialization.Codec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import modchest.REServerModClient;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
@Environment(EnvType.CLIENT)
public class Offsetters {
public static final Codec<Offsetters> CODEC = RecordCodecBuilder.create(inst -> inst.group(
CODECS.OFFSETTER.optionalFieldOf("u").forGetter(o -> o.u.toOptional()),
CODECS.OFFSETTER.optionalFieldOf("v").forGetter(o -> o.v.toOptional())
REServerModClient.CODECS.OFFSETTER.optionalFieldOf("u").forGetter(o -> o.u.toOptional()),
REServerModClient.CODECS.OFFSETTER.optionalFieldOf("v").forGetter(o -> o.v.toOptional())
).apply(inst, Offsetters::new));
public static final Offsetters NONE = new Offsetters();

View File

@ -9,6 +9,7 @@ import org.jetbrains.annotations.Nullable;
import com.mojang.serialization.Codec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import modchest.REServerModClient;
import modchest.assets.Parent;
import modchest.assets.Parent.Some;
import modchest.transform.TransformResult;
@ -97,7 +98,7 @@ public abstract class Overlay implements ToOptional<Overlay> {
@Override
public TransformResult apply(MutableQuadView mqv, Float4 us, Float4 vs, Direction dir) {
final Float4 finalUs = sidedOffsetters().applyUs(us, dir);
float Float4 finalVs = sidedOffsetters().applyVs(vs, dir);
final Float4 finalVs = sidedOffsetters().applyVs(vs, dir);
return textureSource().apply(mqv, finalUs, finalVs, dir);
}
@ -106,7 +107,7 @@ public abstract class Overlay implements ToOptional<Overlay> {
if (textureSource != TextureSource.NONE) {
return textureSource;
} else {
return parent.run(parent -> CLIENT_OVERLAYS.getOverlayFor(parent).textureSource(), TextureSource.NONE);
return parent.run(parent -> REServerModClient.CLIENT_OVERLAYS.getOverlayFor(parent).textureSource(), TextureSource.NONE);
}
}
@ -115,7 +116,7 @@ public abstract class Overlay implements ToOptional<Overlay> {
if (coloredLike.isPresent()) {
return coloredLike;
} else {
return parent.run(parent -> CLIENT_OVERLAYS.getOverlayFor(parent).coloredLike(), Optional.empty());
return parent.run(parent -> REServerModClient.CLIENT_OVERLAYS.getOverlayFor(parent).coloredLike(), Optional.empty());
}
}
@ -124,7 +125,7 @@ public abstract class Overlay implements ToOptional<Overlay> {
if (sideOffsetters != SidedOffsetters.NONE) {
return sidedOffsetters;
} else {
return parent.run(parent -> CLIENT_OVERLAYS.getOverlayFor(parent).sidedOffsetters(),
return parent.run(parent -> REServerModClient.CLIENT_OVERLAYS.getOverlayFor(parent).sidedOffsetters(),
SidedOffsetters.NONE);
}
}

View File

@ -7,9 +7,9 @@ import java.util.function.Supplier;
import com.mojang.serialization.Codec;
import modchest.REServerModClient;
import modchest.util.Float4;
import modchest.util.ToOptional;
import modchest.util.initializer;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.util.math.Direction;
@ -21,26 +21,27 @@ public abstract class SidedOffsetters {
public static final Codec<SidedOffsetters.Base> CODEC = Some.CODEC.xmap(some -> some, base -> (Some) base);
public static final Base NONE = new Base() {
@Override
public Optional<Base> toOptional() {
return Optional.empty();
}
@Override
public Float4 applyUs(final Float4 origUs, Direction dir) {
return origUs;
}
@Override
public Float4 applyVs(final Float4 origVs, Direction dir) {
return origVs;
}
@Override
public <T, t> T match(Function<Base, t> some, Supplier<T> none) {
public <T> T match(Function<Base, T> some, Supplier<T> none) {
return none.get();
}
@Override
public Float4 applyUs(Float4 origUs, Direction dir) {
return origUs;
}
@Override
public Float4 applyVs(Float4 origVs, Direction dir) {
return origVs;
}
};
public interface Base extends ToOptional<Base> {
@ -50,7 +51,7 @@ public abstract class SidedOffsetters {
}
public static class Some implements Base, ToOptional.Some<Base> {
public static final Codec<SidedOffsetters.Some> CODEC = CODECS.sidedMapOf(Offsetters.CODEC)
public static final Codec<SidedOffsetters.Some> CODEC = REServerModClient.CODECS.sideMapOf(Offsetters.CODEC)
.xmap(SidedOffsetters.Some::new, so -> so.map);
private final Map<Direction, Offsetters> map;

View File

@ -9,8 +9,11 @@ import java.util.function.Supplier;
import org.spongepowered.asm.mixin.Final;
import com.mojang.serialization.Codec;
import com.mojang.serialization.DataResult;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import modchest.REServerMod;
import modchest.REServerModClient;
import modchest.transform.MaterialApplier;
import modchest.transform.SpriteApplier;
import modchest.transform.TransformResult;
@ -42,8 +45,7 @@ public abstract class TextureSource implements ToOptional<TextureSource> {
@SuppressWarnings("deprecation")
public Entry(Identifier texture, Optional<Identifier> materialSource) {
final Sprite sprite = MinecraftClient.getInstance().getSpriteAtlas(SpriteAtlasTexture.BLOCK_ATLAS_TEXTURE)
.apply(texture);
final Sprite sprite = MinecraftClient.getInstance().getSpriteAtlas(SpriteAtlasTexture.BLOCK_ATLAS_TEXTURE).apply(texture);
this.textureApplier = SpriteApplier.ofNullable(sprite);
final Optional<BlockState> materialSourceState = materialSource
.map(id -> Registry.BLOCK.get(id).getDefaultState());
@ -62,7 +64,7 @@ public abstract class TextureSource implements ToOptional<TextureSource> {
.apply(inst, i -> i));
case SIDED:
return RecordCodecBuilder.create(
inst -> inst.group(Sided.SIDED_CODEC.fieldOf("value").forGetter(i -> (Single) i))
inst -> inst.group(Sided.SIDED_CODEC.fieldOf("value").forGetter(i -> (Sided) i))
.apply(inst, i -> i));
default:
throw new IllegalStateException("Invalid TextureSourceKind:" + kind);
@ -110,7 +112,7 @@ public abstract class TextureSource implements ToOptional<TextureSource> {
Identifier.CODEC.optionalFieldOf("materialFrom").forGetter(e -> e.materialApplier.id()))
.apply(inst, Entry::new));
SIDED_CODEC = CODECS.sidedMapOf(sidedValueCodec).xmap(
SIDED_CODEC = REServerModClient.CODECS.sidedMapOf(sidedValueCodec).xmap(
map -> new Sided(new EnumMap<>(map)),
sided -> sided.entries);
}

View File

@ -4,17 +4,20 @@ import static net.minecraft.block.Block.field_31022;
import java.nio.ByteBuffer;
import java.nio.IntBuffer;
import java.util.List;
import java.util.Properties;
import org.lwjgl.system.MemoryStack;
import modchest.REServerMod;
import modchest.block.custom.grid.gridBlock;
import modchest.event.playerAfterRespawnEvent;
import modchest.grid.gridBlock;
import net.fabricmc.fabric.api.client.rendering.v1.WorldRenderContext;
import net.fabricmc.fabric.api.renderer.v1.model.ModelHelper;
import net.fabricmc.tinyremapper.extension.mixin.hard.util.CamelPrefixString;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks;
import net.minecraft.block.enums.DoubleBlockHalf;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.network.ClientPlayerEntity;
@ -84,7 +87,7 @@ public class gridPreviewOutline {
final BakedModel model = client.getBlockRenderManager().getModel(blockState);
final boolean valid;
if (block == Blocks.GRID_DOOR) {
if (block == REServerMod.BLOCKS.GRID_DOOR) {
final BlockPos upPos = pos.up();
final BlockState upState = blockState.with(Properties.DOUBLE_BLOCK_HALF, DoubleBlockHalf.UPPER);
final BakedModel upModel = client.getBlockRenderManager().getModel(upState);

View File

@ -1,4 +1,4 @@
package modchest.mixin.mc;
package modchest.mixin.client;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
@ -6,7 +6,7 @@ import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Redirect;
import modchest.util.initializer;
import modchest.REServerMod;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.client.render.item.ItemModels;
@ -16,7 +16,6 @@ import net.minecraft.client.util.ModelIdentifier;
import net.minecraft.client.world.ClientWorld;
import net.minecraft.entity.LivingEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.item.Items;
import net.minecraft.world.World;
@Environment(EnvType.CLIENT)
@ -31,8 +30,8 @@ public abstract class ItemRendererMixin {
@Redirect(method = "getHeldItemModel", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/render/item/ItemModels;getModel(Lnet/minecraft/item/ItemStack;)Lnet/minecraft/client/render/model/BakedModel;"))
BakedModel getModelProxy(final ItemModels itemModels, final ItemStack stack) {
if (stack.getItem() == ITEMS.HAMMER) {
return itemModels.getModelManager().getModel(new ModelIdentifier(META.id("hammer_none"), "inventory"));
if (stack.getItem() == REServerMod.ITEMS.HAMMER) {
return itemModels.getModelManager().getModel(new ModelIdentifier(REServerMod.META.id("hammer_none"), "inventory"));
}
return itemModels.getModel(stack);
}
@ -40,10 +39,10 @@ public abstract class ItemRendererMixin {
@Redirect(method = "innerRenderInGui", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/render/item/ItemRenderer;getHeldItemModel(Lnet/minecraft/item/ItemStack;Lnet/minecraft/world/World;Lnet/minecraft/entity/LivingEntity;)Lnet/minecraft/client/render/model/BakedModel;"))
BakedModel getHeldItemModelProxy(final ItemRenderer itemRenderer, final ItemStack stack, final World world,
final LivingEntity entity) {
if (stack.getItem() == ITEMS.HAMMER) {
if (stack.getItem() == REServerMod.ITEMS.HAMMER) {
final ClientWorld clientWorld = world instanceof ClientWorld ? (ClientWorld) world : null;
final BakedModel model = models.getModelManager()
.getModel(new ModelIdentifier(META.id("hammer"), "inventory"));
.getModel(new ModelIdentifier(REServerMod.META.id("hammer"), "inventory"));
final BakedModel model2 = model.getOverrides().apply(model, stack, clientWorld, entity, 0);
return model2 == null ? models.getModelManager().getMissingModel() : model2;
}

View File

@ -1,4 +1,4 @@
package modchest.mixin.mc;
package modchest.mixin.client;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Accessor;

View File

@ -1,7 +1,6 @@
package modchest.networking;
import modchest.REServerMod;
import modchest.networking.packet.gridRenderRequestS2CPacket;
import modchest.networking.packet.respawnRequestS2CPacket;
import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking;
import net.minecraft.util.Identifier;
@ -13,7 +12,6 @@ public class modNetworkingClient { //Identifier werden eingeführt
public static final Identifier grid_block_networking = new Identifier(REServerMod.MOD_ID, "grid_block_networking");
public static void registerC2SPackets() { //Identifier fuer packets werden registriert (Identifier die der Server aufruft um beim CLient was auszufuehren)
ClientPlayNetworking.registerGlobalReceiver(request_respawn, respawnRequestS2CPacket::receive); //was der Client dann machen soll steht in der receive Methode
ClientPlayNetworking.registerGlobalReceiver(grid_block_networking, gridRenderRequestS2CPacket::receive);
ClientPlayNetworking.registerGlobalReceiver(request_respawn, respawnRequestS2CPacket::receive); //was der Client dann machen soll steht in der receive Methode
}
}

View File

@ -1,40 +1,41 @@
package modchest.rendering;
import net.minecraft.client.texture.AbstractTexture;
import net.minecraft.client.texture.TextureManager;
import net.minecraft.resource.ResourceManager;
import net.minecraft.util.Identifier;
public class gridBlockTexture extends TextureManager{
public gridBlockTexture(ResourceManager resourceManager) {
super(resourceManager);
//TODO Auto-generated constructor stub
}
@Override
public AbstractTexture getTexture(Identifier id) {
return super.getTexture(id);
}
/*public static BlockColors getBlockColors(Block block, BlockRenderView world, BlockPos pos, BlockColors blockColors) {
BlockState state = block.getDefaultState();
// Verwende die Farbe für deine Zwecke
BlockColors colors = getBlockColors(block, world, pos, blockColors);
return colors;
}*/
/*public static Overlay getOverlayGrid(){
MinecraftClient minecraftClient = MinecraftClient.getInstance();
PlayerEntity player = minecraftClient.player;
ItemStack itemStackInHand = player.getMainHandStack();
Block blockInHand = getBlockFromItem(itemStackInHand.getItem());
BlockState stateInHand = blockInHand.getDefaultState();
RenderLayer inHandRenderLayer = ;*/
//stateInHand.getRenderingSeed
}
/*
* package modchest.rendering;
*
* import net.minecraft.client.texture.AbstractTexture;
* import net.minecraft.client.texture.TextureManager;
* import net.minecraft.resource.ResourceManager;
* import net.minecraft.util.Identifier;
*
* public class gridBlockTexture extends TextureManager{
*
* public gridBlockTexture(ResourceManager resourceManager) {
* super(resourceManager);
* //TODO Auto-generated constructor stub
* }
*
* @Override
* public AbstractTexture getTexture(Identifier id) {
* return super.getTexture(id);
* }
*
* public static BlockColors getBlockColors(Block block, BlockRenderView world,
* BlockPos pos, BlockColors blockColors) {
* BlockState state = block.getDefaultState();
* // Verwende die Farbe für deine Zwecke
* BlockColors colors = getBlockColors(block, world, pos, blockColors);
* return colors;
* }
*
* public static Overlay getOverlayGrid(){
* MinecraftClient minecraftClient = MinecraftClient.getInstance();
* PlayerEntity player = minecraftClient.player;
* ItemStack itemStackInHand = player.getMainHandStack();
* Block blockInHand = getBlockFromItem(itemStackInHand.getItem());
* BlockState stateInHand = blockInHand.getDefaultState();
* RenderLayer inHandRenderLayer = ;
*
*
* //stateInHand.getRenderingSeed
*
* }
*/

View File

@ -25,11 +25,11 @@ import net.minecraft.util.math.random.Random;
@Environment(EnvType.CLIENT)
public abstract class BaseApplier implements ToOptional<BaseApplier> {
public abstract TransformResult apply(MutableQuadView mqv, Direction dir, int index, Float4 vs, int color);
public abstract TransformResult apply(MutableQuadView mqv, Direction dir, int index, Float4 us,Float4 vs, int color);
public static final BaseApplier NONE = new BaseApplier() {
@Override
public TransformResult apply(MutableQuadView mqv, Direction dir, int index, Float4 vs, int color) {
public TransformResult apply(MutableQuadView mqv, Direction dir, int index, Float4 us,Float4 vs, int color) {
return TransformResult.NOTHING_TO_DO;
}
@ -57,8 +57,9 @@ public abstract class BaseApplier implements ToOptional<BaseApplier> {
final Direction dir = ModelHelper.faceFromIndex(i);
final List<BakedQuad> quads = model.getQuads(state, dir, r);
final int size = quads.size();
sizes.put(dir, size);
final SpriteApplier[] spriteAppliers = this.spriteAppliers.computeIfAbsent(dir, x -> new SpriteAppliers[size]);
final SpriteApplier[] spriteAppliers = this.spriteAppliers.computeIfAbsent(dir, x -> new SpriteApplier[size]);
final MaterialApplier[] materialAppliers = this.materialAppliers.computeIfAbsent(dir, x -> new MaterialApplier[size]);
final LazyColorApplier[] colorAppliers = this.colorAppliers.computeIfAbsent(dir, x -> new LazyColorApplier[size]);
@ -80,7 +81,7 @@ public abstract class BaseApplier implements ToOptional<BaseApplier> {
}
@Override
public TransformResult apply(MutableQuadView mqv, Direction dir, int quadIndex, Float4 vs, int color) {
public TransformResult apply(MutableQuadView mqv, Direction dir, int quadIndex, Float4 us, Float4 vs, int color) {
int size = sizes.getInt(dir);
if (size == 0) {
return TransformResult.failed(String.format("No %s quads in model for %s", dir, state));

View File

@ -6,6 +6,8 @@ import javax.swing.text.html.Option;
import org.jetbrains.annotations.NotNull;
import modchest.REServerMod;
import modchest.REServerModClient;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.fabricmc.fabric.api.renderer.v1.material.RenderMaterial;

View File

@ -0,0 +1,34 @@
package modchest.transform;
public interface MaterialMap {
/**
* Used by renderer to avoid overhead of sprite reverse lookup when not needed.
* @return true if map is sprite-sensitive, false if always returns same material
*/
boolean needsSprite();
/**
* Returns null if sprite is unmapped or if this is the default material map.
*/
@Nullable RenderMaterial getMapped(@Nullable Sprite sprite);
static MaterialMap get(BlockState state) {
return MaterialMapLoader.INSTANCE.get(state);
}
static MaterialMap get(FluidState fluidState) {
return MaterialMapLoader.INSTANCE.get(fluidState);
}
static MaterialMap getForParticle(ParticleType<?> particleType) {
return MaterialMapLoader.INSTANCE.get(particleType);
}
static MaterialMap defaultMaterialMap() {
return MaterialMapLoader.DEFAULT_MAP;
}
static MaterialMap get(ItemStack itemStack) {
return MaterialMapLoader.INSTANCE.get(itemStack);
}
}

View File

@ -0,0 +1,5 @@
package modchest.transform;
public class MaterialMapLoader {
}

View File

@ -22,7 +22,6 @@ public abstract class SpriteApplier {
}
public abstract TransformResult apply(MutableQuadView mqv, Float4 us, Float4 vs);
public abstract Identifier id();
public static final SpriteApplier NONE = new SpriteApplier() {
@ -40,7 +39,7 @@ public abstract class SpriteApplier {
public static class Some extends SpriteApplier {
private final Sprite toApply;
public Some(final Sprite toApply) {
public Some(Sprite toApply) {
this.toApply = toApply;
}

View File

@ -13,6 +13,7 @@ import modchest.grid.gridBlockEntityTypes;
import modchest.grid.gridBlocks;
import modchest.grid.gridItems;
import modchest.grid.gridMeta;
import modchest.grid.gridProperties;
import modchest.item.custom.SpecialItems;
import modchest.util.initializer;
@ -21,7 +22,7 @@ public class REServerMod implements ModInitializer {
public static final String MOD_ID = "modchest";
public static final Logger LOGGER = LoggerFactory.getLogger("modchest"); // Erster Error Logger
public static REServerModProperties PROPERTIES;
public static gridProperties PROPERTIES;
public static SpecialItems SPECIAL_ITEMS;
public static gridMeta META;
@ -38,10 +39,10 @@ public class REServerMod implements ModInitializer {
initializer.events();
initializer.networking();
PROPERTIES = new GridProperties();
PROPERTIES = new gridProperties();
SPECIAL_ITEMS = new SpecialItems();
META = new gridMeta()
META = new gridMeta();
BLOCKS = new gridBlocks();
ITEMS = new gridItems();
BLOCK_ENTITY_TYPES = new gridBlockEntityTypes();

View File

@ -4,6 +4,7 @@ import java.util.Properties;
import javax.swing.text.html.BlockView;
import modchest.REServerMod;
import modchest.block.entity.gridEntity;
import modchest.grid.data.Sections;
import net.minecraft.block.BlockEntityProvider;
@ -25,7 +26,7 @@ public class gridSlab extends SlabBlock implements gridSlotInfo, BlockEntityProv
@Override
public Sections sections() {
return META.GRID_SLAB_SECTIONS;
return REServerMod.META.GRID_SLAB_SECTIONS;
}
@Override
@ -74,8 +75,8 @@ public class gridSlab extends SlabBlock implements gridSlotInfo, BlockEntityProv
}
@Override
public BlockEntity createBlockEntity(final BlockView world) {
return new gridEntity(BLOCK_ENTITY_TYPES.GRID_SLAB, META.GRID_SLAB_SECTIONS);
public BlockEntity createBlockEntity(BlockView world) {
return new gridEntity(REServerMod.BLOCK_ENTITY_TYPES.GRID_SLAB, REServerMod.META.GRID_SLAB_SECTIONS);
}
@Override

View File

@ -15,6 +15,7 @@ import org.spongepowered.include.com.google.gson.JsonParseException;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import modchest.REServerMod;
import net.fabricmc.fabric.api.resource.SimpleResourceReloadListener;
import net.minecraft.item.ItemStack;
import net.minecraft.recipe.Ingredient;
@ -67,7 +68,7 @@ public class OverlayDataListener implements SimpleResourceReloadListener<Collect
}, executor);
}
private final Identifier id = META.id("data/overlay");
private final Identifier id = REServerMod.META.id("data/overlay");
@Override
public Identifier getFabricId() {

View File

@ -6,6 +6,8 @@ import java.util.stream.IntStream;
import org.spongepowered.asm.util.perf.Profiler.Section;
import modchest.REServerMod;
import modchest.util.nbt.ListTag;
import net.minecraft.block.BlockState;
import net.minecraft.item.ItemStack;
@ -37,7 +39,7 @@ public class Sections {
}
public Sections(final int partCount, final int... otherSizes) {
this(makSections(IntStream.concat(IntStream.of(partCount, partCount, SPECIAL_ITEMS.Map.size()), Arrays.stream(otherSizes))));
this(makSections(IntStream.concat(IntStream.of(partCount, partCount, REServerMod.SPECIAL_ITEMS.MAP.size()), Arrays.stream(otherSizes))));
}
public Section get(final int index) {

View File

@ -3,6 +3,7 @@ package modchest.grid.data;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.OptionalInt;
import java.util.stream.Collectors;
import javax.swing.text.html.Option;
@ -10,9 +11,14 @@ import javax.swing.text.html.Option;
import org.jetbrains.annotations.NotNull;
import com.google.common.collect.Streams;
import com.mojang.serialization.Dynamic;
import modchest.REServerMod;
import modchest.util.nbt.CompoundTag;
import modchest.util.nbt.ListTag;
import net.minecraft.block.BlockState;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NbtElement;
import net.minecraft.nbt.NbtOps;
import net.minecraft.util.Identifier;
import net.minecraft.util.Pair;
@ -31,7 +37,7 @@ public class gridData {
return items;
}
private static optional<BlockState>[] baseStatesFromTag(final Sections sections, final ListTag tag) {
private static Optional<BlockState>[] baseStatesFromTag(final Sections sections, final ListTag tag) {
final Optional<BlockState>[] baseStates = sections.makeBaseStates();
for (int i = 0, size = tag.size(); i < size; i++) {
@ -123,7 +129,7 @@ public class gridData {
}
public List<Pair<Optional<BlockState>, Optional<Identifier>>> toRenderAttachment() {
return Streams.zip(Arrays.stream(baseStates), overlayItems().stream().map(i -> i.flatMap(OVERLAYS::getOverlayId)), Pair::new).collect(Collectors.toList());
return Streams.zip(Arrays.stream(baseStates), overlayItems().stream().map(i -> i.flatMap(REServerMod.OVERLAYS::getOverlayId)), Pair::new).collect(Collectors.toList());
}
}

View File

@ -1,5 +1,6 @@
package modchest.grid;
import modchest.REServerMod;
import modchest.block.entity.gridEntity;
import net.minecraft.block.entity.BlockEntityType;
import net.minecraft.util.registry.Registry;
@ -11,26 +12,26 @@ public class gridBlockEntityTypes extends Registrar<BlockEntityType<?>> {
public final BlockEntityType<gridEntity> GRID = register(
BlockEntityType.Builder.create(
() -> new gridEntity(this.GRID, META.GRID_SECTIONS),
BLOCKS.GRID_BLOCK,
BLOCK.GRID_STAIRS,
BLOCK.GRID_FENCE,
BLOCK.GRID_FENCE_GATE,
BLOCKS.GRID_TRAPDOOR,
BLOCKS.GRID_DOOR,
BLOCKS.GRID_PATH,
BLOCKS.GRID_TORCH,
BLOCKS.GRID_WALL_TORCH,
BLOCKS.GRID_PRESSURE_PLATE,
BLOCKS.GRID_WALL,
BLOCKS.GRID_LAYER,
BLOCKS.GRID_CARPET,
BLOCKS.GRID_PANE).build(null),
META.id("frame"));
() -> new gridEntity(this.GRID, REServerMod.META.GRID_SECTIONS),
REServerMod.BLOCKS.GRID_BLOCK,
REServerMod.BLOCKS.GRID_STAIRS,
REServerMod.BLOCKS.GRID_FENCE,
REServerMod.BLOCKS.GRID_FENCE_GATE,
REServerMod.BLOCKS.GRID_TRAPDOOR,
REServerMod.BLOCKS.GRID_DOOR,
REServerMod.BLOCKS.GRID_PATH,
REServerMod.BLOCKS.GRID_TORCH,
REServerMod.BLOCKS.GRID_WALL_TORCH,
REServerMod.BLOCKS.GRID_PRESSURE_PLATE,
REServerMod.BLOCKS.GRID_WALL,
REServerMod.BLOCKS.GRID_LAYER,
REServerMod.BLOCKS.GRID_CARPET,
REServerMod.BLOCKS.GRID_PANE).build(null),
REServerMod.META.id("frame"));
public final BlockEntityType<gridEntity> GRID_SLAB = register(
BlockEntityType.Builder.create(
() -> new gridEntity(this.GRID_SLAB, META.GRID_SLAB_SECTIONS),
BLOCKS.GRID_SLAB).build(null),
META.id("grid_slab"));
() -> new gridEntity(this.GRID_SLAB, REServerMod.META.GRID_SLAB_SECTIONS),
REServerMod.BLOCKS.GRID_SLAB).build(null),
REServerMod.META.id("grid_slab"));
}

View File

@ -19,14 +19,13 @@ public class gridMeta {
public Identifier id(final String path) {
return new Identifier(NAMESPACE, path);
}
public final Logger LOGGER = LogManager.getLogger("grid");
public final Logger LOGGER = LogManager.getLogManager().getLogger("grid");
@SuppressWarnings("deprecation")
public final ScreenHandlerType<gridGuiDescription> GRID_SCREEN_HANDLER_TYPE = ScreenHandlerRegistry
.registerExtended(id("grid"),
(syncId, inventory, buf) -> new gridGuiDescription(syncId, inventory,
ScreenHandlerContext.create(inventory.player.world, buf.readBlockPos())));
public final ScreenHandlerType<gridGuiDescription> GRID_SCREEN_HANDLER_TYPE =
ScreenHandlerRegistry.registerExtended(
id("grid"),
(syncId, inventory, buf) -> new gridGuiDescription(syncId, inventory, ScreenHandlerContext.create(inventory.player.world, buf.readBlockPos())));
public final Sections GRID_SECTIONS = new Sections(1);
public final Sections GRID_SLAB_SECTIONS = new Sections(2);

View File

@ -2,6 +2,7 @@ package modchest.mixin.local;
import org.spongepowered.asm.mixin.Mixin;
import modchest.REServerMod;
import modchest.block.custom.grid.gridBlock;
import modchest.block.custom.grid.gridCarpet;
import modchest.block.custom.grid.gridDoor;
@ -48,7 +49,7 @@ public class SinglePartGridBlock implements gridSlotInfo {
@Override
public Sections sections() {
return META.GRID_SECTIONS;
return REServerMod.META.GRID_SECTIONS;
}
@Override

View File

@ -18,6 +18,7 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import com.mojang.datafixers.util.Function3;
import modchest.REServerMod;
import modchest.block.custom.grid.grid;
import modchest.block.custom.grid.gridBlock;
import modchest.block.custom.grid.gridCarpet;
@ -110,14 +111,14 @@ public abstract class gridBehaviour extends Block implements BlockEntityProvider
@SuppressWarnings("deprecation")
@Override
public boolean emitsRedstonePower(final BlockState state) {
return super.emitsRedstonePower(state) || state.get(PROPERTIES.HAS_REDSTONE);
return super.emitsRedstonePower(state) || state.get(REServerMod.PROPERTIES.HAS_REDSTONE);
}
@SuppressWarnings("deprecation")
@Override
public int getWeakRedstonePower(BlockState state, net.minecraft.world.BlockView world, BlockPos pos,
Direction direction) {
if (state.get(PROPERTIES.HAS_REDSTONE)) {
if (state.get(REServerMod.PROPERTIES.HAS_REDSTONE)) {
return 15 - super.getWeakRedstonePower(state, world, pos, direction)
} else {
return super.getWeakRedstonePower(state, world, pos, direction);
@ -187,7 +188,7 @@ public abstract class gridBehaviour extends Block implements BlockEntityProvider
final @Nullable PlayerEntity player = breaker;
if (player != null) {
if (player.getStackInHand(player.getActiveHand()).getItem() == ITEMS.GRID_HAMMER) {
if (player.getStackInHand(player.getActiveHand()).getItem() == REServerMod.ITEMS.HAMMER) {
onHammerRemoved(world, (gridEntity) blockEntity, oldState, player, false);
} else {
super.onStateReplaced(oldState, world, pos, newState, moved);
@ -196,7 +197,7 @@ public abstract class gridBehaviour extends Block implements BlockEntityProvider
if (blockEntity instanceof Inventory) {
ItemScatterer.spawn(world, pos, (Inventory) blockEntity);
}
super.onStateReplaced(state, world, pos, newState, moved);
super.onStateReplaced(oldState, world, pos, newState, moved);
}
}
@ -280,7 +281,7 @@ public abstract class gridBehaviour extends Block implements BlockEntityProvider
}
if (query.isValidForSpecial()) {
final SpecialItems.SpecialItem specialItem = SPECIAL_ITEM.Map.get(playerStack.getItem());
final SpecialItems.SpecialItem specialItem = REServerMod.SPECIAL_ITEMS.MAP.get(playerStack.getItem());
final int slot = grid.sections().special().makeAbsolute(specialItem.offset());
if (grid.getStack(slot).isEmpty()) {
@ -307,7 +308,7 @@ public abstract class gridBehaviour extends Block implements BlockEntityProvider
if (placer instanceof PlayerEntity) {
final PlayerEntity player = (PlayerEntity) placer;
if (player.getOffHandStack().getItem() != ITEMS.GRID_HAMMER || player.getOffHandStack().getTag() == null) {
if (player.getOffHandStack().getItem() != REServerMod.ITEMS.HAMMER || player.getOffHandStack().getTag() == null) {
tryCopy = false;
} else {
final BlockEntity blockEntity = world.getBlockEntity(pos);

View File

@ -3,6 +3,7 @@ package modchest.mixin.local;
import org.jetbrains.annotations.Nullable;
import org.spongepowered.asm.mixin.Mixin;
import modchest.REServerMod;
import modchest.block.custom.grid.gridBlock;
import modchest.block.custom.grid.gridCarpet;
import modchest.block.custom.grid.gridDoor;
@ -49,7 +50,7 @@ public class gridEntityProvider implements BlockEntityProvider {
@Override
public BlockEntity createBlockEntity(BlockPos pos, BlockState state) {
return new gridEntity(BLOCK_ENTITY_TYPES.GRID, META.FRAME_SECTIONS);
return new gridEntity(REServerMod.BLOCK_ENTITY_TYPES.GRID, REServerMod.META.GRID_SECTIONS);
}
}

View File

@ -47,8 +47,8 @@ public class WallBlockMixin extends Block {
throw new IllegalStateException("Shadow method should not run.");
}
@SuppressWarnings("DuplicatedCode")
@Override
@SuppressWarnings("unused")
private Map<BlockState, VoxelShape> getShapeMap(float f, float g, float h, float i, float j, float k) {
float l = 8.0F - f;
float m = 8.0F + f;

View File

@ -1,4 +1,4 @@
package modchest.networking.packet;
/*package modchest.networking.packet;
import net.minecraft.network.PacketByteBuf;
import net.minecraft.server.network.ServerPlayerEntity;
@ -12,4 +12,4 @@ public class gridBlockS2CPacket {
//PacketByteBuf gridBuffer = gridBlock.writeBuffer(hitResult);
//ServerPlayNetworking.send(serverPlayerEntity, modNetworkingServer.grid_block_networking, gridBuffer);
}
}
}*/

View File

@ -1,4 +1,4 @@
package modchest.util;
/*package modchest.util;
import org.intellij.lang.annotations.JdkConstants.HorizontalAlignment;
import org.spongepowered.asm.util.perf.Profiler.Section;
@ -26,4 +26,4 @@ public enum GuiUtil {
final Section section) {
return constructor.apply(inventory, section.start(), section.size(), 1, false);
}
}
}*/

View File

@ -3,6 +3,8 @@ package modchest.util;
import java.util.Optional;
import java.util.function.Function;
import modchest.REServerMod;
import modchest.block.custom.grid.grid;
import net.minecraft.block.BlockEntityProvider;
import net.minecraft.block.BlockRenderType;
import net.minecraft.block.BlockState;
@ -39,11 +41,11 @@ public class ValidQuery {
}
public boolean isValidForOverlay () {
return OVERLAYS.hasOverlay(stack);
return REServerMod.OVERLAYS.hasOverlay(stack);
}
public boolean isValidForSpecial() {
return SPECIAL_ITEMS.Map.containsKey(stack.getItem());
return REServerMod.SPECIAL_ITEMS.MAP.containsKey(stack.getItem());
}
}

View File

@ -0,0 +1,46 @@
package modchest.util.nbt;
import java.lang.reflect.Array;
/**
* ArrayTag is an abstract representation of any NBT array tag.
* For implementations see {@link ByteArrayTag}, {@link IntArrayTag}, {@link LongArrayTag}.
* @param <T> The array type.
* */
public abstract class ArrayTag<T> extends Tag<T> {
public ArrayTag(T value) {
super(value);
if (!value.getClass().isArray()) {
throw new UnsupportedOperationException("type of array tag must be an array");
}
}
public int length() {
return Array.getLength(getValue());
}
@Override
public T getValue() {
return super.getValue();
}
@Override
public void setValue(T value) {
super.setValue(value);
}
@Override
public String valueToString(int maxDepth) {
return arrayToString("", "");
}
protected String arrayToString(String prefix, String suffix) {
StringBuilder sb = new StringBuilder("[").append(prefix).append("".equals(prefix) ? "" : ";");
for (int i = 0; i < length(); i++) {
sb.append(i == 0 ? "" : ",").append(Array.get(getValue(), i)).append(suffix);
}
sb.append("]");
return sb.toString();
}
}

View File

@ -0,0 +1,42 @@
package modchest.util.nbt;
import java.util.Arrays;
public class ByteArrayTag extends ArrayTag<byte[]> implements Comparable<ByteArrayTag> {
public static final byte ID = 7;
public static final byte[] ZERO_VALUE = new byte[0];
public ByteArrayTag() {
super(ZERO_VALUE);
}
public ByteArrayTag(byte[] value) {
super(value);
}
@Override
public byte getID() {
return ID;
}
@Override
public boolean equals(Object other) {
return super.equals(other) && Arrays.equals(getValue(), ((ByteArrayTag) other).getValue());
}
@Override
public int hashCode() {
return Arrays.hashCode(getValue());
}
@Override
public int compareTo(ByteArrayTag other) {
return Integer.compare(length(), other.length());
}
@Override
public ByteArrayTag clone() {
return new ByteArrayTag(Arrays.copyOf(getValue(), length()));
}
}

View File

@ -0,0 +1,47 @@
package modchest.util.nbt;
public class ByteTag extends NumberTag<Byte> implements Comparable<ByteTag> {
public static final byte ID = 1;
public static final byte ZERO_VALUE = 0;
public ByteTag() {
super(ZERO_VALUE);
}
public ByteTag(byte value) {
super(value);
}
public ByteTag(boolean value) {
super((byte) (value ? 1 : 0));
}
@Override
public byte getID() {
return ID;
}
public boolean asBoolean() {
return getValue() > 0;
}
public void setValue(byte value) {
super.setValue(value);
}
@Override
public boolean equals(Object other) {
return super.equals(other) && asByte() == ((ByteTag) other).asByte();
}
@Override
public int compareTo(ByteTag other) {
return getValue().compareTo(other.getValue());
}
@Override
public ByteTag clone() {
return new ByteTag(getValue());
}
}

View File

@ -0,0 +1,299 @@
package modchest.util.nbt;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.function.BiConsumer;
import modchest.util.nbt.io.MaxDepthIO;
public class CompoundTag extends Tag<Map<String, Tag<?>>>
implements Iterable<Map.Entry<String, Tag<?>>>, Comparable<CompoundTag>, MaxDepthIO {
public static final byte ID = 10;
public CompoundTag() {
super(createEmptyValue());
}
public CompoundTag(int initialCapacity) {
super(new HashMap<>(initialCapacity));
}
@Override
public byte getID() {
return ID;
}
private static Map<String, Tag<?>> createEmptyValue() {
return new HashMap<>(8);
}
public int size() {
return getValue().size();
}
public Tag<?> remove(String key) {
return getValue().remove(key);
}
public void clear() {
getValue().clear();
}
public boolean containsKey(String key) {
return getValue().containsKey(key);
}
public boolean containsValue(Tag<?> value) {
return getValue().containsValue(value);
}
public Collection<Tag<?>> values() {
return getValue().values();
}
public Set<String> keySet() {
return getValue().keySet();
}
public Set<Map.Entry<String, Tag<?>>> entrySet() {
return new NonNullEntrySet<>(getValue().entrySet());
}
@Override
public Iterator<Map.Entry<String, Tag<?>>> iterator() {
return entrySet().iterator();
}
public void forEach(BiConsumer<String, Tag<?>> action) {
getValue().forEach(action);
}
public <C extends Tag<?>> C get(String key, Class<C> type) {
Tag<?> t = getValue().get(key);
if (t != null) {
return type.cast(t);
}
return null;
}
public Tag<?> get(String key) {
return getValue().get(key);
}
public NumberTag<?> getNumberTag(String key) {
return (NumberTag<?>) getValue().get(key);
}
public Number getNumber(String key) {
return getNumberTag(key).getValue();
}
public ByteTag getByteTag(String key) {
return get(key, ByteTag.class);
}
public ShortTag getShortTag(String key) {
return get(key, ShortTag.class);
}
public IntTag getIntTag(String key) {
return get(key, IntTag.class);
}
public LongTag getLongTag(String key) {
return get(key, LongTag.class);
}
public FloatTag getFloatTag(String key) {
return get(key, FloatTag.class);
}
public DoubleTag getDoubleTag(String key) {
return get(key, DoubleTag.class);
}
public StringTag getStringTag(String key) {
return get(key, StringTag.class);
}
public ByteArrayTag getByteArrayTag(String key) {
return get(key, ByteArrayTag.class);
}
public IntArrayTag getIntArrayTag(String key) {
return get(key, IntArrayTag.class);
}
public LongArrayTag getLongArrayTag(String key) {
return get(key, LongArrayTag.class);
}
public ListTag<?> getListTag(String key) {
return get(key, ListTag.class);
}
public CompoundTag getCompoundTag(String key) {
return get(key, CompoundTag.class);
}
public boolean getBoolean(String key) {
Tag<?> t = get(key);
return t instanceof ByteTag && ((ByteTag) t).asByte() > 0;
}
public byte getByte(String key) {
ByteTag t = getByteTag(key);
return t == null ? ByteTag.ZERO_VALUE : t.asByte();
}
public short getShort(String key) {
ShortTag t = getShortTag(key);
return t == null ? ShortTag.ZERO_VALUE : t.asShort();
}
public int getInt(String key) {
IntTag t = getIntTag(key);
return t == null ? IntTag.ZERO_VALUE : t.asInt();
}
public long getLong(String key) {
LongTag t = getLongTag(key);
return t == null ? LongTag.ZERO_VALUE : t.asLong();
}
public float getFloat(String key) {
FloatTag t = getFloatTag(key);
return t == null ? FloatTag.ZERO_VALUE : t.asFloat();
}
public double getDouble(String key) {
DoubleTag t = getDoubleTag(key);
return t == null ? DoubleTag.ZERO_VALUE : t.asDouble();
}
public String getString(String key) {
StringTag t = getStringTag(key);
return t == null ? StringTag.ZERO_VALUE : t.getValue();
}
public byte[] getByteArray(String key) {
ByteArrayTag t = getByteArrayTag(key);
return t == null ? ByteArrayTag.ZERO_VALUE : t.getValue();
}
public int[] getIntArray(String key) {
IntArrayTag t = getIntArrayTag(key);
return t == null ? IntArrayTag.ZERO_VALUE : t.getValue();
}
public long[] getLongArray(String key) {
LongArrayTag t = getLongArrayTag(key);
return t == null ? LongArrayTag.ZERO_VALUE : t.getValue();
}
public Tag<?> put(String key, Tag<?> tag) {
return getValue().put(Objects.requireNonNull(key), Objects.requireNonNull(tag));
}
public Tag<?> putIfNotNull(String key, Tag<?> tag) {
if (tag == null) {
return this;
}
return put(key, tag);
}
public Tag<?> putBoolean(String key, boolean value) {
return put(key, new ByteTag(value));
}
public Tag<?> putByte(String key, byte value) {
return put(key, new ByteTag(value));
}
public Tag<?> putShort(String key, short value) {
return put(key, new ShortTag(value));
}
public Tag<?> putInt(String key, int value) {
return put(key, new IntTag(value));
}
public Tag<?> putLong(String key, long value) {
return put(key, new LongTag(value));
}
public Tag<?> putFloat(String key, float value) {
return put(key, new FloatTag(value));
}
public Tag<?> putDouble(String key, double value) {
return put(key, new DoubleTag(value));
}
public Tag<?> putString(String key, String value) {
return put(key, new StringTag(value));
}
public Tag<?> putByteArray(String key, byte[] value) {
return put(key, new ByteArrayTag(value));
}
public Tag<?> putIntArray(String key, int[] value) {
return put(key, new IntArrayTag(value));
}
public Tag<?> putLongArray(String key, long[] value) {
return put(key, new LongArrayTag(value));
}
@Override
public String valueToString(int maxDepth) {
StringBuilder sb = new StringBuilder("{");
boolean first = true;
for (Map.Entry<String, Tag<?>> e : getValue().entrySet()) {
sb.append(first ? "" : ",")
.append(escapeString(e.getKey(), false)).append(":")
.append(e.getValue().toString(decrementMaxDepth(maxDepth)));
first = false;
}
sb.append("}");
return sb.toString();
}
@Override
public boolean equals(Object other) {
if (this == other) {
return true;
}
if (!super.equals(other) || size() != ((CompoundTag) other).size()) {
return false;
}
for (Map.Entry<String, Tag<?>> e : getValue().entrySet()) {
Tag<?> v;
if ((v = ((CompoundTag) other).get(e.getKey())) == null || !e.getValue().equals(v)) {
return false;
}
}
return true;
}
@Override
public int compareTo(CompoundTag o) {
return Integer.compare(size(), o.getValue().size());
}
@Override
public CompoundTag clone() {
// Choose initial capacity based on default load factor (0.75) so all entries fit in map without resizing
CompoundTag copy = new CompoundTag((int) Math.ceil(getValue().size() / 0.75f));
for (Map.Entry<String, Tag<?>> e : getValue().entrySet()) {
copy.put(e.getKey(), e.getValue().clone());
}
return copy;
}
}

View File

@ -0,0 +1,39 @@
package modchest.util.nbt;
public class DoubleTag extends NumberTag<Double> implements Comparable<DoubleTag> {
public static final byte ID = 6;
public static final double ZERO_VALUE = 0.0D;
public DoubleTag() {
super(ZERO_VALUE);
}
public DoubleTag(double value) {
super(value);
}
@Override
public byte getID() {
return ID;
}
public void setValue(double value) {
super.setValue(value);
}
@Override
public boolean equals(Object other) {
return super.equals(other) && getValue().equals(((DoubleTag) other).getValue());
}
@Override
public int compareTo(DoubleTag other) {
return getValue().compareTo(other.getValue());
}
@Override
public DoubleTag clone() {
return new DoubleTag(getValue());
}
}

View File

@ -0,0 +1,31 @@
package modchest.util.nbt;
public final class EndTag extends Tag<Void> {
public static final byte ID = 0;
public static final EndTag INSTANCE = new EndTag();
private EndTag() {
super(null);
}
@Override
public byte getID() {
return ID;
}
@Override
protected Void checkValue(Void value) {
return value;
}
@Override
public String valueToString(int maxDepth) {
return "\"end\"";
}
@Override
public EndTag clone() {
return INSTANCE;
}
}

View File

@ -0,0 +1,39 @@
package modchest.util.nbt;
public class FloatTag extends NumberTag<Float> implements Comparable<FloatTag> {
public static final byte ID = 5;
public static final float ZERO_VALUE = 0.0F;
public FloatTag() {
super(ZERO_VALUE);
}
public FloatTag(float value) {
super(value);
}
@Override
public byte getID() {
return ID;
}
public void setValue(float value) {
super.setValue(value);
}
@Override
public boolean equals(Object other) {
return super.equals(other) && getValue().equals(((FloatTag) other).getValue());
}
@Override
public int compareTo(FloatTag other) {
return getValue().compareTo(other.getValue());
}
@Override
public FloatTag clone() {
return new FloatTag(getValue());
}
}

View File

@ -0,0 +1,42 @@
package modchest.util.nbt;
import java.util.Arrays;
public class IntArrayTag extends ArrayTag<int[]> implements Comparable<IntArrayTag> {
public static final byte ID = 11;
public static final int[] ZERO_VALUE = new int[0];
public IntArrayTag() {
super(ZERO_VALUE);
}
public IntArrayTag(int[] value) {
super(value);
}
@Override
public byte getID() {
return ID;
}
@Override
public boolean equals(Object other) {
return super.equals(other) && Arrays.equals(getValue(), ((IntArrayTag) other).getValue());
}
@Override
public int hashCode() {
return Arrays.hashCode(getValue());
}
@Override
public int compareTo(IntArrayTag other) {
return Integer.compare(length(), other.length());
}
@Override
public IntArrayTag clone() {
return new IntArrayTag(Arrays.copyOf(getValue(), length()));
}
}

View File

@ -0,0 +1,39 @@
package modchest.util.nbt;
public class IntTag extends NumberTag<Integer> implements Comparable<IntTag> {
public static final byte ID = 3;
public static final int ZERO_VALUE = 0;
public IntTag() {
super(ZERO_VALUE);
}
public IntTag(int value) {
super(value);
}
@Override
public byte getID() {
return ID;
}
public void setValue(int value) {
super.setValue(value);
}
@Override
public boolean equals(Object other) {
return super.equals(other) && asInt() == ((IntTag) other).asInt();
}
@Override
public int compareTo(IntTag other) {
return getValue().compareTo(other.getValue());
}
@Override
public IntTag clone() {
return new IntTag(getValue());
}
}

View File

@ -0,0 +1,350 @@
package modchest.util.nbt;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import java.util.Objects;
import java.util.function.Consumer;
import modchest.util.nbt.io.MaxDepthIO;
/**
* ListTag represents a typed List in the nbt structure.
* An empty {@link ListTag} will be of type {@link EndTag} (unknown type).
* The type of an empty untyped {@link ListTag} can be set by using any of the {@code add()}
* methods or any of the {@code as...List()} methods.
*/
public class ListTag<T extends Tag<?>> extends Tag<List<T>> implements Iterable<T>, Comparable<ListTag<T>>, MaxDepthIO {
public static final byte ID = 9;
private Class<?> typeClass = null;
private ListTag(int initialCapacity) {
super(createEmptyValue(initialCapacity));
}
@Override
public byte getID() {
return ID;
}
/**
* <p>Creates a non-type-safe ListTag. Its element type will be set after the first
* element was added.</p>
*
* <p>This is an internal helper method for cases where the element type is not known
* at construction time. Use {@link #ListTag(Class)} when the type is known.</p>
*
* @return A new non-type-safe ListTag
*/
public static ListTag<?> createUnchecked(Class<?> typeClass) {
return createUnchecked(typeClass, 3);
}
/**
* <p>Creates a non-type-safe ListTag. Its element type will be set after the first
* element was added.</p>
*
* <p>This is an internal helper method for cases where the element type is not known
* at construction time. Use {@link #ListTag(Class)} when the type is known.</p>
*
* @return A new non-type-safe ListTag
*/
public static ListTag<?> createUnchecked(Class<?> typeClass, int initialCapacity) {
ListTag<?> list = new ListTag<>(initialCapacity);
list.typeClass = typeClass;
return list;
}
/**
* <p>Creates an empty mutable list to be used as empty value of ListTags.</p>
*
* @param <T> Type of the list elements
* @param initialCapacity The initial capacity of the returned List
* @return An instance of {@link java.util.List} with an initial capacity of 3
*/
private static <T> List<T> createEmptyValue(int initialCapacity) {
return new ArrayList<>(initialCapacity);
}
/**
* @param typeClass The exact class of the elements
* @throws IllegalArgumentException When {@code typeClass} is {@link EndTag}{@code .class}
* @throws NullPointerException When {@code typeClass} is {@code null}
*/
public ListTag(Class<? super T> typeClass) throws IllegalArgumentException, NullPointerException {
this(typeClass, 3);
}
/**
* @param typeClass The exact class of the elements
* @param initialCapacity Initial capacity of list
* @throws IllegalArgumentException When {@code typeClass} is {@link EndTag}{@code .class}
* @throws NullPointerException When {@code typeClass} is {@code null}
*/
public ListTag(Class<? super T> typeClass, int initialCapacity) throws IllegalArgumentException, NullPointerException {
super(createEmptyValue(initialCapacity));
if (typeClass == EndTag.class) {
throw new IllegalArgumentException("cannot create ListTag with EndTag elements");
}
this.typeClass = Objects.requireNonNull(typeClass);
}
public Class<?> getTypeClass() {
return typeClass == null ? EndTag.class : typeClass;
}
public int size() {
return getValue().size();
}
public T remove(int index) {
return getValue().remove(index);
}
public void clear() {
getValue().clear();
}
public boolean contains(T t) {
return getValue().contains(t);
}
public boolean containsAll(Collection<Tag<?>> tags) {
return getValue().containsAll(tags);
}
public void sort(Comparator<T> comparator) {
getValue().sort(comparator);
}
@Override
public Iterator<T> iterator() {
return getValue().iterator();
}
@Override
public void forEach(Consumer<? super T> action) {
getValue().forEach(action);
}
public T set(int index, T t) {
return getValue().set(index, Objects.requireNonNull(t));
}
/**
* Adds a Tag to this ListTag after the last index.
*
* @param t The element to be added.
*/
public void add(T t) {
add(size(), t);
}
public void add(int index, T t) {
Objects.requireNonNull(t);
if (getTypeClass() == EndTag.class) {
typeClass = t.getClass();
} else if (typeClass != t.getClass()) {
throw new ClassCastException(
String.format("cannot add %s to ListTag<%s>",
t.getClass().getSimpleName(),
typeClass.getSimpleName()));
}
getValue().add(index, t);
}
public void addAll(Collection<T> t) {
for (T tt : t) {
add(tt);
}
}
public void addAll(int index, Collection<T> t) {
int i = 0;
for (T tt : t) {
add(index + i, tt);
i++;
}
}
public void addBoolean(boolean value) {
addUnchecked(new ByteTag(value));
}
public void addByte(byte value) {
addUnchecked(new ByteTag(value));
}
public void addShort(short value) {
addUnchecked(new ShortTag(value));
}
public void addInt(int value) {
addUnchecked(new IntTag(value));
}
public void addLong(long value) {
addUnchecked(new LongTag(value));
}
public void addFloat(float value) {
addUnchecked(new FloatTag(value));
}
public void addDouble(double value) {
addUnchecked(new DoubleTag(value));
}
public void addString(String value) {
addUnchecked(new StringTag(value));
}
public void addByteArray(byte[] value) {
addUnchecked(new ByteArrayTag(value));
}
public void addIntArray(int[] value) {
addUnchecked(new IntArrayTag(value));
}
public void addLongArray(long[] value) {
addUnchecked(new LongArrayTag(value));
}
public T get(int index) {
return getValue().get(index);
}
public int indexOf(T t) {
return getValue().indexOf(t);
}
@SuppressWarnings("unchecked")
public <L extends Tag<?>> ListTag<L> asTypedList(Class<L> type) {
checkTypeClass(type);
return (ListTag<L>) this;
}
public ListTag<ByteTag> asByteTagList() {
return asTypedList(ByteTag.class);
}
public ListTag<ShortTag> asShortTagList() {
return asTypedList(ShortTag.class);
}
public ListTag<IntTag> asIntTagList() {
return asTypedList(IntTag.class);
}
public ListTag<LongTag> asLongTagList() {
return asTypedList(LongTag.class);
}
public ListTag<FloatTag> asFloatTagList() {
return asTypedList(FloatTag.class);
}
public ListTag<DoubleTag> asDoubleTagList() {
return asTypedList(DoubleTag.class);
}
public ListTag<StringTag> asStringTagList() {
return asTypedList(StringTag.class);
}
public ListTag<ByteArrayTag> asByteArrayTagList() {
return asTypedList(ByteArrayTag.class);
}
public ListTag<IntArrayTag> asIntArrayTagList() {
return asTypedList(IntArrayTag.class);
}
public ListTag<LongArrayTag> asLongArrayTagList() {
return asTypedList(LongArrayTag.class);
}
@SuppressWarnings("unchecked")
public ListTag<ListTag<?>> asListTagList() {
checkTypeClass(ListTag.class);
typeClass = ListTag.class;
return (ListTag<ListTag<?>>) this;
}
public ListTag<CompoundTag> asCompoundTagList() {
return asTypedList(CompoundTag.class);
}
@Override
public String valueToString(int maxDepth) {
StringBuilder sb = new StringBuilder("{\"type\":\"").append(getTypeClass().getSimpleName()).append("\",\"list\":[");
for (int i = 0; i < size(); i++) {
sb.append(i > 0 ? "," : "").append(get(i).valueToString(decrementMaxDepth(maxDepth)));
}
sb.append("]}");
return sb.toString();
}
@Override
public boolean equals(Object other) {
if (this == other) {
return true;
}
if (!super.equals(other) || size() != ((ListTag<?>) other).size() || getTypeClass() != ((ListTag<?>) other)
.getTypeClass()) {
return false;
}
for (int i = 0; i < size(); i++) {
if (!get(i).equals(((ListTag<?>) other).get(i))) {
return false;
}
}
return true;
}
@Override
public int hashCode() {
return Objects.hash(getTypeClass().hashCode(), getValue().hashCode());
}
@Override
public int compareTo(ListTag<T> o) {
return Integer.compare(size(), o.getValue().size());
}
@SuppressWarnings("unchecked")
@Override
public ListTag<T> clone() {
ListTag<T> copy = new ListTag<>(this.size());
// assure type safety for clone
copy.typeClass = typeClass;
for (T t : getValue()) {
copy.add((T) t.clone());
}
return copy;
}
//TODO: make private
@SuppressWarnings("unchecked")
public void addUnchecked(Tag<?> tag) {
if (getTypeClass() != EndTag.class && typeClass != tag.getClass()) {
throw new IllegalArgumentException(String.format(
"cannot add %s to ListTag<%s>",
tag.getClass().getSimpleName(), typeClass.getSimpleName()));
}
add(size(), (T) tag);
}
private void checkTypeClass(Class<?> clazz) {
if (getTypeClass() != EndTag.class && typeClass != clazz) {
throw new ClassCastException(String.format(
"cannot cast ListTag<%s> to ListTag<%s>",
typeClass.getSimpleName(), clazz.getSimpleName()));
}
}
}

View File

@ -0,0 +1,42 @@
package modchest.util.nbt;
import java.util.Arrays;
public class LongArrayTag extends ArrayTag<long[]> implements Comparable<LongArrayTag> {
public static final byte ID = 12;
public static final long[] ZERO_VALUE = new long[0];
public LongArrayTag() {
super(ZERO_VALUE);
}
public LongArrayTag(long[] value) {
super(value);
}
@Override
public byte getID() {
return ID;
}
@Override
public boolean equals(Object other) {
return super.equals(other) && Arrays.equals(getValue(), ((LongArrayTag) other).getValue());
}
@Override
public int hashCode() {
return Arrays.hashCode(getValue());
}
@Override
public int compareTo(LongArrayTag other) {
return Integer.compare(length(), other.length());
}
@Override
public LongArrayTag clone() {
return new LongArrayTag(Arrays.copyOf(getValue(), length()));
}
}

View File

@ -0,0 +1,39 @@
package modchest.util.nbt;
public class LongTag extends NumberTag<Long> implements Comparable<LongTag> {
public static final byte ID = 4;
public static final long ZERO_VALUE = 0L;
public LongTag() {
super(ZERO_VALUE);
}
public LongTag(long value) {
super(value);
}
@Override
public byte getID() {
return ID;
}
public void setValue(long value) {
super.setValue(value);
}
@Override
public boolean equals(Object other) {
return super.equals(other) && asLong() == ((LongTag) other).asLong();
}
@Override
public int compareTo(LongTag other) {
return getValue().compareTo(other.getValue());
}
@Override
public LongTag clone() {
return new LongTag(getValue());
}
}

View File

@ -0,0 +1,140 @@
package modchest.util.nbt;
import java.util.Collection;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
/**
* A decorator for the Set returned by CompoundTag#entrySet()
* that disallows setting null values.
* */
class NonNullEntrySet<K, V> implements Set<Map.Entry<K, V>> {
private Set<Map.Entry<K, V>> set;
NonNullEntrySet(Set<Map.Entry<K, V>> set) {
this.set = set;
}
@Override
public int size() {
return set.size();
}
@Override
public boolean isEmpty() {
return set.isEmpty();
}
@Override
public boolean contains(Object o) {
return set.contains(o);
}
@Override
public Iterator<Map.Entry<K, V>> iterator() {
return new NonNullEntrySetIterator(set.iterator());
}
@Override
public Object[] toArray() {
return set.toArray();
}
@Override
public <T> T[] toArray(T[] a) {
return set.toArray(a);
}
@Override
public boolean add(Map.Entry<K, V> kvEntry) {
return set.add(kvEntry);
}
@Override
public boolean remove(Object o) {
return set.remove(o);
}
@Override
public boolean containsAll(Collection<?> c) {
return set.containsAll(c);
}
@Override
public boolean addAll(Collection<? extends Map.Entry<K, V>> c) {
return set.addAll(c);
}
@Override
public boolean retainAll(Collection<?> c) {
return set.retainAll(c);
}
@Override
public boolean removeAll(Collection<?> c) {
return set.removeAll(c);
}
@Override
public void clear() {
set.clear();
}
class NonNullEntrySetIterator implements Iterator<Map.Entry<K, V>> {
private Iterator<Map.Entry<K, V>> iterator;
NonNullEntrySetIterator(Iterator<Map.Entry<K, V>> iterator) {
this.iterator = iterator;
}
@Override
public boolean hasNext() {
return iterator.hasNext();
}
@Override
public Map.Entry<K, V> next() {
return new NonNullEntry(iterator.next());
}
}
class NonNullEntry implements Map.Entry<K, V> {
private Map.Entry<K, V> entry;
NonNullEntry(Map.Entry<K, V> entry) {
this.entry = entry;
}
@Override
public K getKey() {
return entry.getKey();
}
@Override
public V getValue() {
return entry.getValue();
}
@Override
public V setValue(V value) {
if (value == null) {
throw new NullPointerException(getClass().getSimpleName() + " does not allow setting null");
}
return entry.setValue(value);
}
@Override
public boolean equals(Object o) {
return entry.equals(o);
}
@Override
public int hashCode() {
return entry.hashCode();
}
}
}

View File

@ -0,0 +1,37 @@
package modchest.util.nbt;
public abstract class NumberTag<T extends Number & Comparable<T>> extends Tag<T> {
public NumberTag(T value) {
super(value);
}
public byte asByte() {
return getValue().byteValue();
}
public short asShort() {
return getValue().shortValue();
}
public int asInt() {
return getValue().intValue();
}
public long asLong() {
return getValue().longValue();
}
public float asFloat() {
return getValue().floatValue();
}
public double asDouble() {
return getValue().doubleValue();
}
@Override
public String valueToString(int maxDepth) {
return getValue().toString();
}
}

View File

@ -0,0 +1,39 @@
package modchest.util.nbt;
public class ShortTag extends NumberTag<Short> implements Comparable<ShortTag> {
public static final byte ID = 2;
public static final short ZERO_VALUE = 0;
public ShortTag() {
super(ZERO_VALUE);
}
public ShortTag(short value) {
super(value);
}
@Override
public byte getID() {
return ID;
}
public void setValue(short value) {
super.setValue(value);
}
@Override
public boolean equals(Object other) {
return super.equals(other) && asShort() == ((ShortTag) other).asShort();
}
@Override
public int compareTo(ShortTag other) {
return getValue().compareTo(other.getValue());
}
@Override
public ShortTag clone() {
return new ShortTag(getValue());
}
}

View File

@ -0,0 +1,50 @@
package modchest.util.nbt;
public class StringTag extends Tag<String> implements Comparable<StringTag> {
public static final byte ID = 8;
public static final String ZERO_VALUE = "";
public StringTag() {
super(ZERO_VALUE);
}
public StringTag(String value) {
super(value);
}
@Override
public byte getID() {
return ID;
}
@Override
public String getValue() {
return super.getValue();
}
@Override
public void setValue(String value) {
super.setValue(value);
}
@Override
public String valueToString(int maxDepth) {
return escapeString(getValue(), false);
}
@Override
public boolean equals(Object other) {
return super.equals(other) && getValue().equals(((StringTag) other).getValue());
}
@Override
public int compareTo(StringTag o) {
return getValue().compareTo(o.getValue());
}
@Override
public StringTag clone() {
return new StringTag(getValue());
}
}

View File

@ -0,0 +1,162 @@
package modchest.util.nbt;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public abstract class Tag<T> implements Cloneable {
/**
* The default maximum depth of the NBT structure.
* */
public static final int DEFAULT_MAX_DEPTH = 512;
private static final Map<String, String> ESCAPE_CHARACTERS;
static {
final Map<String, String> temp = new HashMap<>();
temp.put("\\", "\\\\\\\\");
temp.put("\n", "\\\\n");
temp.put("\t", "\\\\t");
temp.put("\r", "\\\\r");
temp.put("\"", "\\\\\"");
ESCAPE_CHARACTERS = Collections.unmodifiableMap(temp);
}
private static final Pattern ESCAPE_PATTERN = Pattern.compile("[\\\\\n\t\r\"]");
private static final Pattern NON_QUOTE_PATTERN = Pattern.compile("[a-zA-Z0-9_\\-+]+");
private T value;
/**
* Initializes this Tag with some value. If the value is {@code null}, it will
* throw a {@code NullPointerException}
* @param value The value to be set for this Tag.
* */
public Tag(T value) {
setValue(value);
}
/**
* @return This Tag's ID, usually used for serialization and deserialization.
* */
public abstract byte getID();
/**
* @return The value of this Tag.
* */
protected T getValue() {
return value;
}
/**
* Sets the value for this Tag directly.
* @param value The value to be set.
* @throws NullPointerException If the value is null
* */
protected void setValue(T value) {
this.value = checkValue(value);
}
/**
* Checks if the value {@code value} is {@code null}.
* @param value The value to check
* @throws NullPointerException If {@code value} was {@code null}
* @return The parameter {@code value}
* */
protected T checkValue(T value) {
return Objects.requireNonNull(value);
}
/**
* Calls {@link Tag#toString(int)} with an initial depth of {@code 0}.
* @see Tag#toString(int)
* @throws MaxDepthReachedException If the maximum nesting depth is exceeded.
* */
@Override
public final String toString() {
return toString(DEFAULT_MAX_DEPTH);
}
/**
* Creates a string representation of this Tag in a valid JSON format.
* @param maxDepth The maximum nesting depth.
* @return The string representation of this Tag.
* @throws MaxDepthReachedException If the maximum nesting depth is exceeded.
* */
public String toString(int maxDepth) {
return "{\"type\":\""+ getClass().getSimpleName() + "\"," +
"\"value\":" + valueToString(maxDepth) + "}";
}
/**
* Calls {@link Tag#valueToString(int)} with {@link Tag#DEFAULT_MAX_DEPTH}.
* @return The string representation of the value of this Tag.
* @throws MaxDepthReachedException If the maximum nesting depth is exceeded.
* */
public String valueToString() {
return valueToString(DEFAULT_MAX_DEPTH);
}
/**
* Returns a JSON representation of the value of this Tag.
* @param maxDepth The maximum nesting depth.
* @return The string representation of the value of this Tag.
* @throws MaxDepthReachedException If the maximum nesting depth is exceeded.
* */
public abstract String valueToString(int maxDepth);
/**
* Returns whether this Tag and some other Tag are equal.
* They are equal if {@code other} is not {@code null} and they are of the same class.
* Custom Tag implementations should overwrite this but check the result
* of this {@code super}-method while comparing.
* @param other The Tag to compare to.
* @return {@code true} if they are equal based on the conditions mentioned above.
* */
@Override
public boolean equals(Object other) {
return other != null && getClass() == other.getClass();
}
/**
* Calculates the hash code of this Tag. Tags which are equal according to {@link Tag#equals(Object)}
* must return an equal hash code.
* @return The hash code of this Tag.
* */
@Override
public int hashCode() {
return value.hashCode();
}
/**
* Creates a clone of this Tag.
* @return A clone of this Tag.
* */
@SuppressWarnings("CloneDoesntDeclareCloneNotSupportedException")
public abstract Tag<T> clone();
/**
* Escapes a string to fit into a JSON-like string representation for Minecraft
* or to create the JSON string representation of a Tag returned from {@link Tag#toString()}
* @param s The string to be escaped.
* @param lenient {@code true} if it should force double quotes ({@code "}) at the start and
* the end of the string.
* @return The escaped string.
* */
protected static String escapeString(String s, boolean lenient) {
StringBuffer sb = new StringBuffer();
Matcher m = ESCAPE_PATTERN.matcher(s);
while (m.find()) {
m.appendReplacement(sb, ESCAPE_CHARACTERS.get(m.group()));
}
m.appendTail(sb);
m = NON_QUOTE_PATTERN.matcher(s);
if (!lenient || !m.matches()) {
sb.insert(0, "\"").append("\"");
}
return sb.toString();
}
}

View File

@ -0,0 +1,14 @@
package modchest.util.nbt.io;
public interface MaxDepthIO {
default int decrementMaxDepth(int maxDepth) {
if (maxDepth < 0) {
throw new IllegalArgumentException("negative maximum depth is not allowed");
} else if (maxDepth == 0) {
throw new MaxDepthReachedException("reached maximum depth of NBT structure");
}
return --maxDepth;
}
}

View File

@ -0,0 +1,12 @@
package modchest.util.nbt.io;
/**
* Exception indicating that the maximum (de-)serialization depth has been reached.
*/
@SuppressWarnings("serial")
public class MaxDepthReachedException extends RuntimeException {
public MaxDepthReachedException(String msg) {
super(msg);
}
}

View File

@ -0,0 +1,20 @@
{
"parent": "REServerMod:modchest/overlays/zero_sides.json",
"textureSource": {
"type": "sided",
"value": [
{
"sides": ["UP"],
"value": {
"texture": "minecraft:block/crimson_nylium"
}
},
{
"sides": ["north", "south", "east", "west"],
"value": {
"texture": "REServerMod:modchest/crimson_nylium_side_overlay"
}
}
]
}
}

View File

@ -4,7 +4,18 @@
"compatibilityLevel": "JAVA_17",
"mixins": [
"ServerPlayerEntityMixin",
"bedBlock"
"bedBlock",
"local.gridBehaviour",
"local.gridEntityProvider",
"local.SinglePartGridBlock",
"mc.BlockItemAccess",
"mc.GetItemBeforeEmpty",
"mc.WallBlockMixin"
],
"client": [
"mc.WorldRendererAccess",
"mc.BakedQuadAccess",
"mc.ItemRendererMixin"
],
"injectors": {
"defaultRequire": 1