Added weather vanes

This commit is contained in:
Sollace 2022-10-12 15:46:15 +02:00
parent c3032ded26
commit 6db30ff693
16 changed files with 348 additions and 8 deletions

View file

@ -18,8 +18,7 @@ import com.minelittlepony.unicopia.ability.magic.spell.trait.TraitLoader;
import com.minelittlepony.unicopia.advancement.UCriteria;
import com.minelittlepony.unicopia.block.UBlocks;
import com.minelittlepony.unicopia.block.UTreeGen;
import com.minelittlepony.unicopia.block.data.BlockDestructionManager;
import com.minelittlepony.unicopia.block.data.ZapAppleStageStore;
import com.minelittlepony.unicopia.block.data.*;
import com.minelittlepony.unicopia.block.state.StateMapLoader;
import com.minelittlepony.unicopia.command.Commands;
import com.minelittlepony.unicopia.container.SpellbookChapterLoader;
@ -63,6 +62,7 @@ public class Unicopia implements ModInitializer {
ServerTickEvents.END_WORLD_TICK.register(w -> {
((BlockDestructionManager.Source)w).getDestructionManager().tick();
ZapAppleStageStore.get(w).tick();
WeatherConditions.get(w).tick();
if (Debug.DEBUG_SPELLBOOK_CHAPTERS) {
SpellbookChapterLoader.INSTANCE.sendUpdate(w.getServer());
}

View file

@ -0,0 +1,16 @@
package com.minelittlepony.unicopia.block;
import net.minecraft.block.entity.BlockEntity;
import net.minecraft.block.entity.BlockEntityType;
import net.minecraft.block.entity.BlockEntityType.Builder;
import net.minecraft.util.registry.Registry;
public interface UBlockEntities {
BlockEntityType<WeatherVaneBlock.WeatherVane> WEATHER_VANE = create("weather_vane", BlockEntityType.Builder.create(WeatherVaneBlock.WeatherVane::new, UBlocks.WEATHER_VANE));
static <T extends BlockEntity> BlockEntityType<T> create(String id, Builder<T> builder) {
return Registry.register(Registry.BLOCK_ENTITY_TYPE, id, builder.build(null));
}
static void bootstrap() {}
}

View file

@ -42,6 +42,8 @@ public interface UBlocks {
Block ZAP_BULB = register("zap_bulb", new FruitBlock(FabricBlockSettings.of(Material.GOURD, MapColor.GRAY).strength(500, 1200).sounds(BlockSoundGroup.AZALEA_LEAVES), Direction.DOWN, ZAP_LEAVES, FruitBlock.DEFAULT_SHAPE, false));
Block ZAP_APPLE = register("zap_apple", new FruitBlock(FabricBlockSettings.of(Material.GOURD, MapColor.GRAY).sounds(BlockSoundGroup.AZALEA_LEAVES), Direction.DOWN, ZAP_LEAVES, FruitBlock.DEFAULT_SHAPE, false));
Block WEATHER_VANE = register("weather_vane", new WeatherVaneBlock(FabricBlockSettings.of(Material.METAL, MapColor.BLACK).requiresTool().strength(3.0f, 6.0f).sounds(BlockSoundGroup.METAL).nonOpaque()), ItemGroup.DECORATIONS);
Block GREEN_APPLE_LEAVES = register("green_apple_leaves", new FruitBearingBlock(FabricBlockSettings.copy(Blocks.OAK_LEAVES),
0xE5FFFF88,
() -> UBlocks.GREEN_APPLE,
@ -98,6 +100,9 @@ public interface UBlocks {
static void bootstrap() {
StrippableBlockRegistry.register(ZAP_LOG, STRIPPED_ZAP_LOG);
StrippableBlockRegistry.register(ZAP_WOOD, STRIPPED_ZAP_WOOD);
TRANSLUCENT_BLOCKS.add(WEATHER_VANE);
UBlockEntities.bootstrap();
}
static boolean never(BlockState state, BlockView world, BlockPos pos) {

View file

@ -0,0 +1,119 @@
package com.minelittlepony.unicopia.block;
import org.jetbrains.annotations.Nullable;
import com.minelittlepony.unicopia.USounds;
import com.minelittlepony.unicopia.block.data.WeatherConditions;
import net.minecraft.block.*;
import net.minecraft.block.entity.*;
import net.minecraft.nbt.NbtCompound;
import net.minecraft.network.Packet;
import net.minecraft.network.listener.ClientPlayPacketListener;
import net.minecraft.network.packet.s2c.play.BlockEntityUpdateS2CPacket;
import net.minecraft.server.world.ServerWorld;
import net.minecraft.sound.SoundCategory;
import net.minecraft.util.math.*;
import net.minecraft.util.shape.VoxelShape;
import net.minecraft.util.shape.VoxelShapes;
import net.minecraft.world.BlockView;
import net.minecraft.world.World;
public class WeatherVaneBlock extends BlockWithEntity {
/*private static final VoxelShape SHAPE = VoxelShapes.union(
Block.createCuboidShape(7.5F, 0, 7.5F, 8.5F, 14, 8.5F),
Block.createCuboidShape(7, 0, 7, 9, 1, 9)
);*/
protected WeatherVaneBlock(Settings settings) {
super(settings);
}
@Deprecated
@Override
public VoxelShape getOutlineShape(BlockState state, BlockView world, BlockPos pos, ShapeContext context) {
return VoxelShapes.union(
Block.createCuboidShape(7.5F, 0, 7.5F, 8.5F, 14, 8.5F),
Block.createCuboidShape(7, 0, 7, 9, 1, 9)
);
}
@Override
public BlockEntity createBlockEntity(BlockPos pos, BlockState state) {
return new WeatherVane(pos, state);
}
@Override
@Nullable
public <T extends BlockEntity> BlockEntityTicker<T> getTicker(World world, BlockState state, BlockEntityType<T> type) {
return BellBlock.checkType(type, UBlockEntities.WEATHER_VANE, world.isClient ? WeatherVane::clientTick : WeatherVane::serverTick);
}
public static class WeatherVane extends BlockEntity {
private float angle;
private float clientAngle;
private float prevAngle;
public WeatherVane(BlockPos pos, BlockState state) {
super(UBlockEntities.WEATHER_VANE, pos, state);
}
public float getAngle(float tickDelta) {
return MathHelper.lerp(tickDelta, prevAngle, clientAngle);
}
@Override
public void readNbt(NbtCompound nbt) {
angle = nbt.getFloat("angle");
}
@Override
protected void writeNbt(NbtCompound nbt) {
nbt.putFloat("angle", angle);
}
@Override
public Packet<ClientPlayPacketListener> toUpdatePacket() {
return BlockEntityUpdateS2CPacket.create(this);
}
@Override
public NbtCompound toInitialChunkDataNbt() {
return createNbt();
}
public static void serverTick(World world, BlockPos pos, BlockState state, WeatherVane entity) {
Vec3d airflow = WeatherConditions.get(world).getWindDirection();
float angle = (float)Math.atan2(airflow.x, airflow.z) + MathHelper.PI;
if (Math.signum(entity.angle) != Math.signum(angle)) {
angle = MathHelper.PI - angle;
}
angle %= MathHelper.PI;
if (angle != entity.angle) {
entity.angle = angle;
entity.markDirty();
if (world instanceof ServerWorld serverWorld) {
serverWorld.getChunkManager().markForUpdate(pos);
}
world.playSound(null, pos.getX(), pos.getY(), pos.getZ(), USounds.BLOCK_WEATHER_VANE_ROTATE, SoundCategory.BLOCKS, 1, 0.5F + (float)world.random.nextGaussian());
}
}
public static void clientTick(World world, BlockPos pos, BlockState state, WeatherVane entity) {
entity.prevAngle = entity.clientAngle;
float angle = entity.angle + (float)Math.sin(world.getTime() / 70F) * (world.isThundering() ? 30 : 1);
float step = (Math.abs(entity.clientAngle) - Math.abs(angle)) / 7F;
if (entity.clientAngle < angle) {
entity.clientAngle += step;
} else if (entity.clientAngle > angle) {
entity.clientAngle -= step;
}
}
}
}

View file

@ -1,13 +1,19 @@
package com.minelittlepony.unicopia.block.data;
import com.minelittlepony.unicopia.Unicopia;
import com.minelittlepony.unicopia.util.Tickable;
import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks;
import net.minecraft.nbt.NbtCompound;
import net.minecraft.tag.BlockTags;
import net.minecraft.util.Identifier;
import net.minecraft.util.math.*;
import net.minecraft.world.Heightmap.Type;
import net.minecraft.world.PersistentState;
import net.minecraft.world.World;
public class WeatherConditions {
public class WeatherConditions extends PersistentState implements Tickable {
public static final TwoDimensionalField HEIGHT_MAP_FIELD = (world, pos) -> {
return world.getTopY(Type.WORLD_SURFACE_WG, pos.getX(), pos.getZ());
};
@ -29,16 +35,87 @@ public class WeatherConditions {
public static final float MAX_UPDRAFT_HEIGHT = 20;
public static final float MAX_TERRAIN_HEIGHT = 50;
public static final float MAX_WIND_HEIGHT = 70;
private static final Identifier ID = Unicopia.id("weather_conditions");
public static WeatherConditions get(World world) {
return WorldOverlay.getPersistableStorage(world, ID, WeatherConditions::new, WeatherConditions::new);
}
private final World world;
private float windYaw;
private float prevWindYaw;
private int interpolation;
private int maxInterpolation = 100;
private boolean prevDayState;
private WeatherConditions(World world, NbtCompound compound) {
this(world);
windYaw = compound.getFloat("windYaw");
prevWindYaw = compound.getFloat("prevWindYaw");
prevDayState = compound.getBoolean("prevDayState");
interpolation = compound.getInt("interpolation");
maxInterpolation = compound.getInt("maxInterpolation");
}
private WeatherConditions(World world) {
this.world = world;
}
@Override
public void tick() {
if (interpolation < maxInterpolation) {
interpolation++;
markDirty();
}
boolean isDay = world.isDay();
if (isDay != prevDayState
|| world.random.nextInt(1200) == 0
|| (world.isRaining() && world.random.nextInt(120) == 0)
|| (world.isThundering() && world.random.nextInt(90) == 0)) {
prevDayState = isDay;
prevWindYaw = getWindYaw();
windYaw = world.random.nextFloat() * 360;
interpolation = 0;
maxInterpolation = world.isRaining() || world.isThundering() ? 50 : 100;
markDirty();
}
}
public float getWindYaw() {
return MathHelper.lerp(interpolation / (float)maxInterpolation, prevWindYaw, windYaw);
}
public Vec3d getWindDirection() {
return Vec3d.fromPolar(0, windYaw).normalize();
}
@Override
public NbtCompound writeNbt(NbtCompound compound) {
compound.putFloat("windYaw", windYaw);
compound.putFloat("prevWindYaw", prevWindYaw);
compound.putBoolean("prevDayState", prevDayState);
compound.putInt("interpolation", interpolation);
compound.putInt("maxInterpolation", maxInterpolation);
return compound;
}
public static Vec3d getAirflow(BlockPos pos, World world) {
BlockPos.Mutable probedPosition = new BlockPos.Mutable();
final float terrainFactor = Math.min(MAX_TERRAIN_HEIGHT, LOCAL_ALTITUDE_FIELD.getValue(world, probedPosition.set(pos))) / MAX_TERRAIN_HEIGHT;
final float localAltitude = LOCAL_ALTITUDE_FIELD.getValue(world, probedPosition.set(pos));
final float terrainFactor = Math.min(MAX_TERRAIN_HEIGHT, localAltitude) / MAX_TERRAIN_HEIGHT;
final float windFactor = Math.min(MAX_WIND_HEIGHT, localAltitude) / MAX_WIND_HEIGHT;
Vec3d terrainGradient = LOCAL_ALTITUDE_FIELD.computeAverage(world, pos, probedPosition).multiply(1 - terrainFactor);
Vec3d thermalGradient = THERMAL_FIELD.computeAverage(world, pos, probedPosition).multiply(terrainFactor);
Vec3d wind = get(world).getWindDirection().multiply(1 - windFactor);
return terrainGradient.add(thermalGradient).normalize().add(0, getUpdraft(probedPosition.set(pos), world), 0);
return terrainGradient.add(thermalGradient).add(wind).normalize().add(0, getUpdraft(probedPosition.set(pos), world), 0);
}
public static double getUpdraft(BlockPos.Mutable pos, World world) {

View file

@ -24,9 +24,7 @@ import com.minelittlepony.unicopia.particle.UParticles;
import net.fabricmc.fabric.api.blockrenderlayer.v1.BlockRenderLayerMap;
import net.fabricmc.fabric.api.client.particle.v1.ParticleFactoryRegistry;
import net.fabricmc.fabric.api.client.particle.v1.ParticleFactoryRegistry.PendingParticleFactory;
import net.fabricmc.fabric.api.client.rendering.v1.EntityRendererRegistry;
import net.fabricmc.fabric.api.client.rendering.v1.BuiltinItemRendererRegistry;
import net.fabricmc.fabric.api.client.rendering.v1.ColorProviderRegistry;
import net.fabricmc.fabric.api.client.rendering.v1.*;
import net.minecraft.block.Block;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.color.block.BlockColorProvider;
@ -77,6 +75,8 @@ public interface URenderers {
EntityRendererRegistry.register(UEntities.SPELLBOOK, SpellbookEntityRenderer::new);
EntityRendererRegistry.register(UEntities.AIR_BALLOON, AirBalloonEntityRenderer::new);
BlockEntityRendererRegistry.register(UBlockEntities.WEATHER_VANE, WeatherVaneBlockEntityRenderer::new);
ColorProviderRegistry.ITEM.register((stack, i) -> i > 0 ? -1 : ((DyeableItem)stack.getItem()).getColor(stack), UItems.FRIENDSHIP_BRACELET);
BuiltinItemRendererRegistry.INSTANCE.register(UItems.FILLED_JAR, (stack, mode, matrices, vertexConsumers, light, overlay) -> {

View file

@ -0,0 +1,58 @@
package com.minelittlepony.unicopia.client.render.entity;
import com.minelittlepony.unicopia.Unicopia;
import com.minelittlepony.unicopia.block.WeatherVaneBlock;
import com.minelittlepony.unicopia.block.WeatherVaneBlock.WeatherVane;
import com.minelittlepony.unicopia.client.render.RenderLayers;
import net.minecraft.client.model.*;
import net.minecraft.client.render.VertexConsumerProvider;
import net.minecraft.client.render.block.entity.BlockEntityRenderer;
import net.minecraft.client.render.block.entity.BlockEntityRendererFactory;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.util.Identifier;
public class WeatherVaneBlockEntityRenderer implements BlockEntityRenderer<WeatherVaneBlock.WeatherVane> {
private static final Identifier TEXTURE = Unicopia.id("textures/entity/weather_vane.png");
private final ModelPart root;
private final ModelPart pole;
public WeatherVaneBlockEntityRenderer(BlockEntityRendererFactory.Context ctx) {
root = getTexturedModelData().createModel();
pole = root.getChild("pole");
}
private static TexturedModelData getTexturedModelData() {
ModelData modelData = new ModelData();
ModelPartData root = modelData.getRoot();
root.addChild("base", ModelPartBuilder.create()
.uv(30, 14).mirrored().cuboid(-9, -1, 7, 2, 1, 2, Dilation.NONE), ModelTransform.pivot(8, 0, -8));
ModelPartData pole = root.addChild("pole", ModelPartBuilder.create(), ModelTransform.NONE);
pole.addChild("ew_arrow", ModelPartBuilder.create()
.uv(0, -16).cuboid(0, -12, -8, 0, 5, 16, Dilation.NONE), ModelTransform.rotation(0, 0.7854F, 0));
pole.addChild("apple", ModelPartBuilder.create()
.uv(0, 2).cuboid(0, -27, -7, 0, 15, 15, Dilation.NONE)
.uv(0, -11).cuboid(0, -9, -8, 0, 5, 16, Dilation.NONE)
.uv(32, 0).cuboid(-0.5F, -14, -0.5F, 1, 14, 1, Dilation.NONE), ModelTransform.NONE);
return TexturedModelData.of(modelData, 64, 32);
}
@Override
public void render(WeatherVane entity, float tickDelta, MatrixStack matrices, VertexConsumerProvider vertices, int light, int overlay) {
matrices.push();
matrices.scale(1, -1, -1);
matrices.translate(0.5F, 0, -0.5F);
pole.yaw = entity.getAngle(tickDelta);
root.render(matrices, vertices.getBuffer(RenderLayers.getEntityCutoutNoCull(TEXTURE, true)), light, overlay);
matrices.pop();
}
}

View file

@ -0,0 +1,5 @@
{
"variants": {
"": { "model": "unicopia:block/weather_vane" }
}
}

View file

@ -119,6 +119,7 @@
"block.unicopia.zap_apple": "Zap Apple",
"block.unicopia.zap_bulb": "Unripened Zap Apple",
"block.unicopia.apple_pie": "Apple Pie",
"block.unicopia.weather_vane": "Weather Vane",
"block.unicopia.green_apple_leaves": "Granny Smith Leaves",
"block.unicopia.green_apple_sapling": "Granny Smith Sapling",

View file

@ -0,0 +1,6 @@
{
"parent": "minecraft:block/cube_all",
"textures": {
"particle": "unicopia:item/weather_vane"
}
}

View file

@ -0,0 +1,6 @@
{
"parent": "item/generated",
"textures": {
"layer0": "unicopia:item/weather_vane"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 314 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

View file

@ -0,0 +1,30 @@
{
"parent": "minecraft:recipes/root",
"rewards": {
"recipes": [
"unicopia:weather_vane"
]
},
"criteria": {
"has_iron": {
"trigger": "minecraft:inventory_changed",
"conditions": {
"items": [
{ "items": [ "minecraft:iron_nugget", "minecraft:iron_ingot" ] }
]
}
},
"has_the_recipe": {
"trigger": "minecraft:recipe_unlocked",
"conditions": {
"recipe": "unicopia:weather_vane"
}
}
},
"requirements": [
[
"has_iron",
"has_the_recipe"
]
]
}

View file

@ -0,0 +1,16 @@
{
"type": "minecraft:crafting_shaped",
"pattern": [
" **",
"** ",
" * "
],
"key": {
"*": {
"item": "minecraft:iron_nugget"
}
},
"result": {
"item": "unicopia:weather_vane"
}
}

1
weather_vane.bbmodel Normal file
View file

@ -0,0 +1 @@
{"meta":{"format_version":"4.0","model_format":"modded_entity","box_uv":true},"name":"weather_vane","model_identifier":"weather_vane","modded_entity_version":"Fabric 1.17+","modded_entity_flip_y":true,"visible_box":[1,1,0],"variable_placeholders":"","variable_placeholder_buttons":[],"resolution":{"width":64,"height":32},"elements":[{"name":"apple","rescale":false,"locked":false,"from":[0,12,-7],"to":[0,27,8],"autouv":0,"color":7,"rotation":[0,8.110414437731967e-14,0],"origin":[0,0,0],"uv_offset":[0,2],"faces":{"north":{"uv":[15,17,15,32],"texture":0},"east":{"uv":[0,17,15,32],"texture":0},"south":{"uv":[30,17,30,32],"texture":0},"west":{"uv":[15,17,30,32],"texture":0},"up":{"uv":[15,17,15,2],"texture":0},"down":{"uv":[15,2,15,17],"texture":0}},"type":"cube","uuid":"cf1d6a48-071c-9144-ba90-50a7556f60e6"},{"name":"ns_arrow","rescale":false,"locked":false,"from":[0,4,-8],"to":[0,9,8],"autouv":0,"color":5,"rotation":[0,8.110414437731967e-14,0],"origin":[0,0,0],"uv_offset":[0,-11],"faces":{"north":{"uv":[16,5,16,10],"texture":0},"east":{"uv":[0,5,16,10],"texture":0},"south":{"uv":[32,5,32,10],"texture":0},"west":{"uv":[16,5,32,10],"texture":0},"up":{"uv":[16,5,16,-11],"texture":0},"down":{"uv":[16,-11,16,5],"texture":0}},"type":"cube","uuid":"9d8bbb1a-615f-7e29-0c45-d0ab4e454c68"},{"name":"pole","rescale":false,"locked":false,"from":[-0.5,0,-0.5],"to":[0.5,14,0.5],"autouv":0,"color":3,"rotation":[0,8.110414437731967e-14,0],"origin":[0,0,0],"uv_offset":[32,0],"faces":{"north":{"uv":[33,1,34,15],"texture":0},"east":{"uv":[32,1,33,15],"texture":0},"south":{"uv":[35,1,36,15],"texture":0},"west":{"uv":[34,1,35,15],"texture":0},"up":{"uv":[34,1,33,0],"texture":0},"down":{"uv":[35,0,34,1],"texture":0}},"type":"cube","uuid":"609b452e-a0c3-4214-c7ea-c46aee0927c2"},{"name":"base","rescale":false,"locked":false,"from":[-1,0,-1],"to":[1,1,1],"autouv":0,"color":5,"shade":false,"rotation":[0,8.110414437731967e-14,0],"origin":[-8,0,-8],"uv_offset":[30,14],"faces":{"north":{"uv":[34,16,32,17],"texture":0},"east":{"uv":[36,16,34,17],"texture":0},"south":{"uv":[38,16,36,17],"texture":0},"west":{"uv":[32,16,30,17],"texture":0},"up":{"uv":[32,16,34,14],"texture":0},"down":{"uv":[34,14,36,16],"texture":0}},"type":"cube","uuid":"8a648ab7-7658-12e0-233e-a97a4787e8b8"},{"name":"ew_arrow","rescale":false,"locked":false,"from":[0,7,-8],"to":[0,12,8],"autouv":0,"color":6,"rotation":[0,-44.99999999999998,0],"origin":[0,0,0],"uv_offset":[0,-16],"faces":{"north":{"uv":[16,0,16,5],"texture":0},"east":{"uv":[0,0,16,5],"texture":0},"south":{"uv":[32,0,32,5],"texture":0},"west":{"uv":[16,0,32,5],"texture":0},"up":{"uv":[16,0,16,-16],"texture":0},"down":{"uv":[16,-16,16,0],"texture":0}},"type":"cube","uuid":"ed31b929-d052-7393-a621-100c6adcbbfc"}],"outliner":[{"name":"root","origin":[0,0,0],"color":0,"uuid":"959db0ac-606f-c388-103d-475b7ea65a55","export":true,"isOpen":true,"locked":false,"visibility":true,"autouv":0,"children":["8a648ab7-7658-12e0-233e-a97a4787e8b8",{"name":"pole","origin":[0,0,0],"color":0,"uuid":"122cf60f-4817-d325-a071-47e7a5de8643","export":true,"isOpen":true,"locked":false,"visibility":true,"autouv":0,"children":["609b452e-a0c3-4214-c7ea-c46aee0927c2","9d8bbb1a-615f-7e29-0c45-d0ab4e454c68","ed31b929-d052-7393-a621-100c6adcbbfc","cf1d6a48-071c-9144-ba90-50a7556f60e6"]}]}],"textures":[{"path":"C:\\Users\\Chris Albers\\Documents\\GitRepos\\minecraft_mods\\Unicopia\\src\\main\\resources\\assets\\unicopia\\textures\\block\\weather_vane_arrows.png","name":"weather_vane_arrows.png","folder":"block","namespace":"unicopia","id":"arrows","particle":false,"render_mode":"default","visible":true,"mode":"bitmap","saved":true,"uuid":"62f348a9-1fd6-3c07-309c-0196f613de31","relative_path":"../../Documents/GitRepos/minecraft_mods/Unicopia/src/main/resources/assets/unicopia/textures/block/weather_vane_arrows.png","source":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAAAgCAYAAACinX6EAAAAAXNSR0IArs4c6QAAAUpJREFUaENjZCAD8FjO/v/leCojGVqxaflPwBxq2YPVGkaQZ0AypHiIHD14PDmwAQB1GCFHYHU/j+VskgIORyCg203TGEd3w2BMAfQNAHLyMY3LgMEfADEcHP+X/PhBLYcObBYAeQaUCkjxEDl6SCgEqRWwRCVumGVkFYIxHBwkBdygLATJiU1y9Az2FEBUcoEpGlZlAEk+p43igS0EaeMnkkwdDQC04BqQWoCkKKOy4tEUMJoCUENgxGQBQo0vugQEXSyhcplBVeNGA4CqwTkEDSM6BWycEA/Os/4FC4nWMxTCA6dnQB6GeXa4eh4UQUQHwHCLeVjqxJuch3PM4w2Ay6ys8Dr6XncUg1LpMrB63d+/h1X+x5oFkD2PrRAbboGAEaOjAYCU/EdkCgB5GlcqGG7JH2c1OOIDAFsqGI6xj7chNBSasdRwIwBGcoAhA5g2PwAAAABJRU5ErkJggg=="}],"fabricOptions":{"header":"package com.example.mod;","entity":"Entity","render":"","members":""}}