diff --git a/src/main/java/com/minelittlepony/unicopia/Unicopia.java b/src/main/java/com/minelittlepony/unicopia/Unicopia.java index e968fc3a..58c39dd3 100644 --- a/src/main/java/com/minelittlepony/unicopia/Unicopia.java +++ b/src/main/java/com/minelittlepony/unicopia/Unicopia.java @@ -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()); } diff --git a/src/main/java/com/minelittlepony/unicopia/block/UBlockEntities.java b/src/main/java/com/minelittlepony/unicopia/block/UBlockEntities.java new file mode 100644 index 00000000..dad1d265 --- /dev/null +++ b/src/main/java/com/minelittlepony/unicopia/block/UBlockEntities.java @@ -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 WEATHER_VANE = create("weather_vane", BlockEntityType.Builder.create(WeatherVaneBlock.WeatherVane::new, UBlocks.WEATHER_VANE)); + + static BlockEntityType create(String id, Builder builder) { + return Registry.register(Registry.BLOCK_ENTITY_TYPE, id, builder.build(null)); + } + + static void bootstrap() {} +} diff --git a/src/main/java/com/minelittlepony/unicopia/block/UBlocks.java b/src/main/java/com/minelittlepony/unicopia/block/UBlocks.java index 8ef9805a..8b568b5a 100644 --- a/src/main/java/com/minelittlepony/unicopia/block/UBlocks.java +++ b/src/main/java/com/minelittlepony/unicopia/block/UBlocks.java @@ -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) { diff --git a/src/main/java/com/minelittlepony/unicopia/block/WeatherVaneBlock.java b/src/main/java/com/minelittlepony/unicopia/block/WeatherVaneBlock.java new file mode 100644 index 00000000..068fb951 --- /dev/null +++ b/src/main/java/com/minelittlepony/unicopia/block/WeatherVaneBlock.java @@ -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 BlockEntityTicker getTicker(World world, BlockState state, BlockEntityType 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 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; + } + } + } +} diff --git a/src/main/java/com/minelittlepony/unicopia/block/data/WeatherConditions.java b/src/main/java/com/minelittlepony/unicopia/block/data/WeatherConditions.java index dcae7ed2..c3b15ad3 100644 --- a/src/main/java/com/minelittlepony/unicopia/block/data/WeatherConditions.java +++ b/src/main/java/com/minelittlepony/unicopia/block/data/WeatherConditions.java @@ -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) { diff --git a/src/main/java/com/minelittlepony/unicopia/client/URenderers.java b/src/main/java/com/minelittlepony/unicopia/client/URenderers.java index 903b8ad3..3e108f08 100644 --- a/src/main/java/com/minelittlepony/unicopia/client/URenderers.java +++ b/src/main/java/com/minelittlepony/unicopia/client/URenderers.java @@ -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) -> { diff --git a/src/main/java/com/minelittlepony/unicopia/client/render/entity/WeatherVaneBlockEntityRenderer.java b/src/main/java/com/minelittlepony/unicopia/client/render/entity/WeatherVaneBlockEntityRenderer.java new file mode 100644 index 00000000..24ad2bc7 --- /dev/null +++ b/src/main/java/com/minelittlepony/unicopia/client/render/entity/WeatherVaneBlockEntityRenderer.java @@ -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 { + 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(); + } +} diff --git a/src/main/resources/assets/unicopia/blockstates/weather_vane.json b/src/main/resources/assets/unicopia/blockstates/weather_vane.json new file mode 100644 index 00000000..e4a9f4e3 --- /dev/null +++ b/src/main/resources/assets/unicopia/blockstates/weather_vane.json @@ -0,0 +1,5 @@ +{ + "variants": { + "": { "model": "unicopia:block/weather_vane" } + } +} diff --git a/src/main/resources/assets/unicopia/lang/en_us.json b/src/main/resources/assets/unicopia/lang/en_us.json index 04e7cfae..831b7e95 100644 --- a/src/main/resources/assets/unicopia/lang/en_us.json +++ b/src/main/resources/assets/unicopia/lang/en_us.json @@ -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", diff --git a/src/main/resources/assets/unicopia/models/block/weather_vane.json b/src/main/resources/assets/unicopia/models/block/weather_vane.json new file mode 100644 index 00000000..824dcce2 --- /dev/null +++ b/src/main/resources/assets/unicopia/models/block/weather_vane.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:block/cube_all", + "textures": { + "particle": "unicopia:item/weather_vane" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/unicopia/models/item/weather_vane.json b/src/main/resources/assets/unicopia/models/item/weather_vane.json new file mode 100644 index 00000000..0c105c42 --- /dev/null +++ b/src/main/resources/assets/unicopia/models/item/weather_vane.json @@ -0,0 +1,6 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "unicopia:item/weather_vane" + } +} diff --git a/src/main/resources/assets/unicopia/textures/entity/weather_vane.png b/src/main/resources/assets/unicopia/textures/entity/weather_vane.png new file mode 100644 index 00000000..7aa6fdd7 Binary files /dev/null and b/src/main/resources/assets/unicopia/textures/entity/weather_vane.png differ diff --git a/src/main/resources/assets/unicopia/textures/item/weather_vane.png b/src/main/resources/assets/unicopia/textures/item/weather_vane.png new file mode 100644 index 00000000..1e79431f Binary files /dev/null and b/src/main/resources/assets/unicopia/textures/item/weather_vane.png differ diff --git a/src/main/resources/data/unicopia/advancements/recipes/weather_vane.json b/src/main/resources/data/unicopia/advancements/recipes/weather_vane.json new file mode 100644 index 00000000..3b6f199a --- /dev/null +++ b/src/main/resources/data/unicopia/advancements/recipes/weather_vane.json @@ -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" + ] + ] +} \ No newline at end of file diff --git a/src/main/resources/data/unicopia/recipes/weather_vane.json b/src/main/resources/data/unicopia/recipes/weather_vane.json new file mode 100644 index 00000000..4818dbcc --- /dev/null +++ b/src/main/resources/data/unicopia/recipes/weather_vane.json @@ -0,0 +1,16 @@ +{ + "type": "minecraft:crafting_shaped", + "pattern": [ + " **", + "** ", + " * " + ], + "key": { + "*": { + "item": "minecraft:iron_nugget" + } + }, + "result": { + "item": "unicopia:weather_vane" + } +} \ No newline at end of file diff --git a/weather_vane.bbmodel b/weather_vane.bbmodel new file mode 100644 index 00000000..758da9b0 --- /dev/null +++ b/weather_vane.bbmodel @@ -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":""}} \ No newline at end of file