diff --git a/build.gradle b/build.gradle index 622081e..e851662 100644 --- a/build.gradle +++ b/build.gradle @@ -211,3 +211,7 @@ publishing { tasks.withType(JavaCompile).configureEach { options.encoding = 'UTF-8' // Use the UTF-8 charset for Java compilation } + +tasks.withType(ProcessResources).configureEach { + duplicatesStrategy = DuplicatesStrategy.INCLUDE +} diff --git a/src/main/java/net/fretux/ascend/AscendMod.java b/src/main/java/net/fretux/ascend/AscendMod.java index 6819cfc..d7acdb9 100644 --- a/src/main/java/net/fretux/ascend/AscendMod.java +++ b/src/main/java/net/fretux/ascend/AscendMod.java @@ -3,6 +3,7 @@ package net.fretux.ascend; import net.fretux.ascend.command.AscendCommand; import net.fretux.ascend.config.AscendConfig; import net.fretux.ascend.network.PacketHandler; +import net.fretux.ascend.registry.ModBlocks; import net.fretux.ascend.registry.ModItems; import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.eventbus.api.SubscribeEvent; @@ -24,6 +25,7 @@ public class AscendMod { System.out.println("[Ascend] Mod loaded! Side=" + FMLEnvironment.dist); net.minecraftforge.fml.ModLoadingContext.get().registerConfig(ModConfig.Type.COMMON, AscendConfig.COMMON_SPEC); ModItems.register(modBus); + ModBlocks.register(modBus); } private void onCommonSetup(final FMLCommonSetupEvent event) { diff --git a/src/main/java/net/fretux/ascend/block/ShrineOfRemembranceBlock.java b/src/main/java/net/fretux/ascend/block/ShrineOfRemembranceBlock.java new file mode 100644 index 0000000..9f7b31e --- /dev/null +++ b/src/main/java/net/fretux/ascend/block/ShrineOfRemembranceBlock.java @@ -0,0 +1,32 @@ +package net.fretux.ascend.block; + +import net.minecraft.core.BlockPos; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.InteractionResult; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.RenderShape; +import net.minecraft.world.level.block.state.BlockState; + +public class ShrineOfRemembranceBlock extends Block { + public ShrineOfRemembranceBlock(Properties props) { + super(props); + } + + @Override + public RenderShape getRenderShape(BlockState state) { + return RenderShape.MODEL; + } + + @Override + public InteractionResult use(BlockState state, Level level, BlockPos pos, + Player player, InteractionHand hand, + net.minecraft.world.phys.BlockHitResult hit) { + if (level.isClientSide) { + net.minecraft.client.Minecraft.getInstance().setScreen(new net.fretux.ascend.client.screen.ShrineScreen()); + return InteractionResult.SUCCESS; + } + return InteractionResult.CONSUME; + } +} diff --git a/src/main/java/net/fretux/ascend/client/screen/ShrineScreen.java b/src/main/java/net/fretux/ascend/client/screen/ShrineScreen.java new file mode 100644 index 0000000..457b8fc --- /dev/null +++ b/src/main/java/net/fretux/ascend/client/screen/ShrineScreen.java @@ -0,0 +1,65 @@ +package net.fretux.ascend.client.screen; + +import com.mojang.blaze3d.systems.RenderSystem; +import net.fretux.ascend.network.PacketHandler; +import net.fretux.ascend.network.ServerboundShrineChoicePacket; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.client.gui.components.Button; +import net.minecraft.client.gui.screens.Screen; +import net.minecraft.network.chat.Component; + +public class ShrineScreen extends Screen { + + private static final int WIDTH = 200; + private static final int HEIGHT = 120; + + private int leftPos; + private int topPos; + + public ShrineScreen() { + super(Component.literal("Shrine of Remembrance")); + } + + @Override + protected void init() { + super.init(); + this.leftPos = (this.width - WIDTH) / 2; + this.topPos = (this.height - HEIGHT) / 2; + + this.clearWidgets(); + + // Dialogue text + int buttonY = topPos + 60; + + Button forgetButton = Button.builder(Component.literal("I WISH TO FORGET"), (btn) -> { + PacketHandler.INSTANCE.sendToServer(new ServerboundShrineChoicePacket("forget")); + Minecraft.getInstance().setScreen(null); + }).bounds(leftPos + 20, buttonY, WIDTH - 40, 20).build(); + + Button cancelButton = Button.builder(Component.literal("LEAVE"), (btn) -> { + Minecraft.getInstance().setScreen(null); + }).bounds(leftPos + 20, buttonY + 25, WIDTH - 40, 20).build(); + + addRenderableWidget(forgetButton); + addRenderableWidget(cancelButton); + } + + @Override + public void render(GuiGraphics gui, int mouseX, int mouseY, float partialTicks) { + this.renderBackground(gui); + RenderSystem.enableBlend(); + gui.fill(leftPos - 6, topPos - 6, leftPos + WIDTH + 6, topPos + HEIGHT + 6, 0xAA000000); + RenderSystem.disableBlend(); + + gui.drawCenteredString(this.font, "SPEAK, LITTLE ONE.", this.width / 2, topPos + 10, 0xAA55FF); + gui.drawCenteredString(this.font, "WHAT IS IT YOU SEEK TO UNMAKE?", this.width / 2, topPos + 25, 0xAA55FF); + + super.render(gui, mouseX, mouseY, partialTicks); + } + + @Override + public boolean isPauseScreen() { + return false; + } +} diff --git a/src/main/java/net/fretux/ascend/config/AscendConfig.java b/src/main/java/net/fretux/ascend/config/AscendConfig.java index f66dc4f..46fc993 100644 --- a/src/main/java/net/fretux/ascend/config/AscendConfig.java +++ b/src/main/java/net/fretux/ascend/config/AscendConfig.java @@ -25,13 +25,13 @@ public class AscendConfig { builder.push("Ascend Progression"); xpPerMobKill = builder.comment("Ascend XP gained for killing a mob.") - .defineInRange("xpPerMobKill", 5, 0, 1000); + .defineInRange("xpPerMobKill", 10, 0, 1000); xpPerBlockBreak = builder.comment("Ascend XP gained for breaking a block (ore/stone/log).") .defineInRange("xpPerBlockBreak", 2, 0, 1000); xpPerCraft = builder.comment("Ascend XP gained for crafting items.") - .defineInRange("xpPerCraft", 3, 0, 1000); + .defineInRange("xpPerCraft", 1, 0, 1000); xpPerSmelt = builder.comment("Ascend XP gained for smelting items.") - .defineInRange("xpPerSmelt", 2, 0, 1000); + .defineInRange("xpPerSmelt", 1, 0, 1000); xpPerTrade = builder.comment("Ascend XP gained for trading with villagers.") .defineInRange("xpPerTrade", 5, 0, 1000); xpPerDamageTaken = builder.comment("Ascend XP gained for taking damage.") diff --git a/src/main/java/net/fretux/ascend/datagen/AscendDataGenerators.java b/src/main/java/net/fretux/ascend/datagen/AscendDataGenerators.java index 3ba2966..2589e9e 100644 --- a/src/main/java/net/fretux/ascend/datagen/AscendDataGenerators.java +++ b/src/main/java/net/fretux/ascend/datagen/AscendDataGenerators.java @@ -1,6 +1,9 @@ package net.fretux.ascend.datagen; import net.fretux.ascend.AscendMod; +import net.fretux.ascend.worldgen.ModWorldGenProvider; +import net.minecraft.data.DataGenerator; +import net.minecraft.data.PackOutput; import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; import net.minecraftforge.common.data.ExistingFileHelper; @@ -14,11 +17,13 @@ public class AscendDataGenerators { @OnlyIn(Dist.CLIENT) @SubscribeEvent public static void gatherData(GatherDataEvent event) { - var generator = event.getGenerator(); - ExistingFileHelper existingFileHelper = event.getExistingFileHelper(); + DataGenerator generator = event.getGenerator(); + PackOutput output = generator.getPackOutput(); + ExistingFileHelper helper = event.getExistingFileHelper(); - if (event.includeClient()) { - generator.addProvider(true, new AscendItemModelProvider(generator.getPackOutput(), existingFileHelper)); - } + generator.addProvider(event.includeClient(), new ModBlockStateProvider(output, helper)); + generator.addProvider(event.includeClient(), new AscendItemModelProvider(output, helper)); + generator.addProvider(event.includeServer(), new ModLootTableProvider(output)); + generator.addProvider(event.includeServer(), new ModWorldGenProvider(output, event.getLookupProvider())); } } \ No newline at end of file diff --git a/src/main/java/net/fretux/ascend/datagen/AscendItemModelProvider.java b/src/main/java/net/fretux/ascend/datagen/AscendItemModelProvider.java index be2d149..ad5d42e 100644 --- a/src/main/java/net/fretux/ascend/datagen/AscendItemModelProvider.java +++ b/src/main/java/net/fretux/ascend/datagen/AscendItemModelProvider.java @@ -1,6 +1,7 @@ package net.fretux.ascend.datagen; import net.fretux.ascend.AscendMod; +import net.fretux.ascend.registry.ModBlocks; import net.fretux.ascend.registry.ModItems; import net.minecraft.data.PackOutput; import net.minecraftforge.client.model.generators.ItemModelProvider; @@ -18,6 +19,8 @@ public class AscendItemModelProvider extends ItemModelProvider { protected void registerModels() { assert ModItems.MOONSEYE_TOME.getId() != null; basicItem(ModItems.MOONSEYE_TOME.getId().getPath()); + withExistingParent(ModBlocks.SHRINE_OF_REMEMBRANCE.getId().getPath(), + modLoc("block/" + ModBlocks.SHRINE_OF_REMEMBRANCE.getId().getPath())); } private void basicItem(String name) { diff --git a/src/main/java/net/fretux/ascend/datagen/ModBlockLootProvider.java b/src/main/java/net/fretux/ascend/datagen/ModBlockLootProvider.java new file mode 100644 index 0000000..e5f0fa0 --- /dev/null +++ b/src/main/java/net/fretux/ascend/datagen/ModBlockLootProvider.java @@ -0,0 +1,24 @@ +package net.fretux.ascend.datagen; + +import net.fretux.ascend.registry.ModBlocks; +import net.minecraft.data.loot.BlockLootSubProvider; +import net.minecraft.world.flag.FeatureFlags; + +import java.util.Set; + +public class ModBlockLootProvider extends BlockLootSubProvider { + + public ModBlockLootProvider() { + super(Set.of(), FeatureFlags.REGISTRY.allFlags()); + } + + @Override + protected void generate() { + + } + + @Override + protected Iterable getKnownBlocks() { + return Set.of(ModBlocks.SHRINE_OF_REMEMBRANCE.get()); + } +} \ No newline at end of file diff --git a/src/main/java/net/fretux/ascend/datagen/ModBlockStateProvider.java b/src/main/java/net/fretux/ascend/datagen/ModBlockStateProvider.java new file mode 100644 index 0000000..f000bc0 --- /dev/null +++ b/src/main/java/net/fretux/ascend/datagen/ModBlockStateProvider.java @@ -0,0 +1,21 @@ +package net.fretux.ascend.datagen; + +import net.fretux.ascend.AscendMod; +import net.fretux.ascend.registry.ModBlocks; +import net.minecraft.data.PackOutput; +import net.minecraftforge.client.model.generators.BlockStateProvider; +import net.minecraftforge.client.model.generators.ModelFile; +import net.minecraftforge.common.data.ExistingFileHelper; + +public class ModBlockStateProvider extends BlockStateProvider { + + public ModBlockStateProvider(PackOutput output, ExistingFileHelper exFileHelper) { + super(output, AscendMod.MODID, exFileHelper); + } + + @Override + protected void registerStatesAndModels() { + ModelFile shrineModel = models().getExistingFile(modLoc("block/shrine_of_remembrance")); + simpleBlockWithItem(ModBlocks.SHRINE_OF_REMEMBRANCE.get(), shrineModel); + } +} \ No newline at end of file diff --git a/src/main/java/net/fretux/ascend/datagen/ModLootTableProvider.java b/src/main/java/net/fretux/ascend/datagen/ModLootTableProvider.java new file mode 100644 index 0000000..83d7039 --- /dev/null +++ b/src/main/java/net/fretux/ascend/datagen/ModLootTableProvider.java @@ -0,0 +1,16 @@ +package net.fretux.ascend.datagen; + +import net.minecraft.data.PackOutput; +import net.minecraft.data.loot.LootTableProvider; +import net.minecraft.world.level.storage.loot.parameters.LootContextParamSets; + +import java.util.List; +import java.util.Set; + +public class ModLootTableProvider extends LootTableProvider { + public ModLootTableProvider(PackOutput output) { + super(output, Set.of(), List.of( + new SubProviderEntry(ModBlockLootProvider::new, LootContextParamSets.BLOCK) + )); + } +} diff --git a/src/main/java/net/fretux/ascend/network/PacketHandler.java b/src/main/java/net/fretux/ascend/network/PacketHandler.java index 89b5edd..a3900f4 100644 --- a/src/main/java/net/fretux/ascend/network/PacketHandler.java +++ b/src/main/java/net/fretux/ascend/network/PacketHandler.java @@ -30,5 +30,10 @@ public class PacketHandler { .decoder(ClientboundSyncStatsPacket::new) .consumerMainThread(ClientboundSyncStatsPacket::handle) .add(); + + INSTANCE.registerMessage(id++, ServerboundShrineChoicePacket.class, + ServerboundShrineChoicePacket::toBytes, + ServerboundShrineChoicePacket::new, + ServerboundShrineChoicePacket::handle); } } \ No newline at end of file diff --git a/src/main/java/net/fretux/ascend/network/ServerboundShrineChoicePacket.java b/src/main/java/net/fretux/ascend/network/ServerboundShrineChoicePacket.java new file mode 100644 index 0000000..439948a --- /dev/null +++ b/src/main/java/net/fretux/ascend/network/ServerboundShrineChoicePacket.java @@ -0,0 +1,48 @@ +package net.fretux.ascend.network; + +import net.fretux.ascend.player.PlayerStatsProvider; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.network.chat.Component; +import net.minecraft.server.level.ServerPlayer; +import net.minecraftforge.network.NetworkEvent; +import net.minecraftforge.network.PacketDistributor; + +import java.util.function.Supplier; + +public class ServerboundShrineChoicePacket { + private final String choice; + + public ServerboundShrineChoicePacket(String choice) { + this.choice = choice; + } + + public ServerboundShrineChoicePacket(FriendlyByteBuf buf) { + this.choice = buf.readUtf(); + } + + public void toBytes(FriendlyByteBuf buf) { + buf.writeUtf(choice); + } + + public void handle(Supplier ctx) { + ctx.get().enqueueWork(() -> { + ServerPlayer player = ctx.get().getSender(); + if (player == null) return; + + player.getCapability(PlayerStatsProvider.PLAYER_STATS).ifPresent(stats -> { + if ("forget".equals(choice)) { + if (stats.getKnowledge() >= 15) { + stats.addKnowledge(-15); + stats.refundAllPoints(); + player.sendSystemMessage(Component.literal("FOOLISH... YET HONEST.")); + } else { + player.sendSystemMessage(Component.literal("YOUR MIND IS TOO EMPTY TO BE WORTH MY TOUCH.")); + player.kill(); + } + PlayerStatsProvider.sync(player); + } + }); + }); + ctx.get().setPacketHandled(true); + } +} diff --git a/src/main/java/net/fretux/ascend/player/PlayerStats.java b/src/main/java/net/fretux/ascend/player/PlayerStats.java index 2627406..34694b0 100644 --- a/src/main/java/net/fretux/ascend/player/PlayerStats.java +++ b/src/main/java/net/fretux/ascend/player/PlayerStats.java @@ -109,6 +109,16 @@ public class PlayerStats { knowledge = Math.max(0, knowledge + amount); } + public void refundAllPoints() { + int totalSpent = 0; + for (String key : attributes.keySet()) { + int lvl = attributes.get(key); + totalSpent += lvl; + attributes.put(key, 0); + } + unspentPoints += totalSpent; + } + public boolean hasUsedMoonseye() { return hasUsedMoonseye; } diff --git a/src/main/java/net/fretux/ascend/registry/ModBlocks.java b/src/main/java/net/fretux/ascend/registry/ModBlocks.java new file mode 100644 index 0000000..72b4322 --- /dev/null +++ b/src/main/java/net/fretux/ascend/registry/ModBlocks.java @@ -0,0 +1,35 @@ +package net.fretux.ascend.registry; + +import net.fretux.ascend.AscendMod; +import net.fretux.ascend.block.ShrineOfRemembranceBlock; +import net.minecraft.world.item.BlockItem; +import net.minecraft.world.item.Item; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.state.BlockBehaviour; +import net.minecraft.world.level.material.MapColor; +import net.minecraftforge.eventbus.api.IEventBus; +import net.minecraftforge.registries.DeferredRegister; +import net.minecraftforge.registries.ForgeRegistries; +import net.minecraftforge.registries.RegistryObject; + +public class ModBlocks { + public static final DeferredRegister BLOCKS = + DeferredRegister.create(ForgeRegistries.BLOCKS, AscendMod.MODID); + + public static final RegistryObject SHRINE_OF_REMEMBRANCE = BLOCKS.register( + "shrine_of_remembrance", + () -> new ShrineOfRemembranceBlock( + BlockBehaviour.Properties.of() + .mapColor(MapColor.COLOR_PURPLE) + .strength(-1.0F, 3600000.0F) // unbreakable + .noLootTable() + .lightLevel(s -> 6) + .noOcclusion() + .requiresCorrectToolForDrops() + ) + ); + + public static void register(IEventBus bus) { + BLOCKS.register(bus); + } +} \ No newline at end of file diff --git a/src/main/java/net/fretux/ascend/worldgen/ModWorldGenProvider.java b/src/main/java/net/fretux/ascend/worldgen/ModWorldGenProvider.java new file mode 100644 index 0000000..fc59f56 --- /dev/null +++ b/src/main/java/net/fretux/ascend/worldgen/ModWorldGenProvider.java @@ -0,0 +1,55 @@ +package net.fretux.ascend.worldgen; + +import com.mojang.serialization.Codec; +import net.fretux.ascend.AscendMod; +import net.fretux.ascend.registry.ModBlocks; +import net.minecraft.core.HolderLookup; +import net.minecraft.core.RegistrySetBuilder; +import net.minecraft.core.registries.Registries; +import net.minecraft.data.PackOutput; +import net.minecraft.data.worldgen.BootstapContext; +import net.minecraft.data.worldgen.placement.PlacementUtils; +import net.minecraft.resources.ResourceKey; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.level.levelgen.GenerationStep; +import net.minecraft.world.level.levelgen.feature.ConfiguredFeature; +import net.minecraft.world.level.levelgen.feature.Feature; +import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConfiguration; +import net.minecraft.world.level.levelgen.placement.PlacedFeature; +import net.minecraft.world.level.levelgen.placement.RarityFilter; +import net.minecraftforge.common.data.DatapackBuiltinEntriesProvider; +import net.minecraftforge.registries.ForgeRegistries; + +import java.util.List; +import java.util.Set; +import java.util.concurrent.CompletableFuture; + +/** + * Generates structure and worldgen JSON entries for the Shrine of Remembrance. + */ +public class ModWorldGenProvider extends DatapackBuiltinEntriesProvider { + public static final ResourceKey> SHRINE_CONFIGURED = + ResourceKey.create(Registries.CONFIGURED_FEATURE, new ResourceLocation(AscendMod.MODID, "shrine_of_remembrance")); + public static final ResourceKey SHRINE_PLACED = + ResourceKey.create(Registries.PLACED_FEATURE, new ResourceLocation(AscendMod.MODID, "shrine_of_remembrance")); + + public ModWorldGenProvider(PackOutput output, CompletableFuture registries) { + super(output, registries, new RegistrySetBuilder() + .add(Registries.CONFIGURED_FEATURE, ModWorldGenProvider::bootstrapConfigured) + .add(Registries.PLACED_FEATURE, ModWorldGenProvider::bootstrapPlaced), + Set.of(AscendMod.MODID)); + } + + private static void bootstrapConfigured(BootstapContext> ctx) { + ctx.register(SHRINE_CONFIGURED, + new ConfiguredFeature<>(Feature.NO_OP, NoneFeatureConfiguration.INSTANCE)); + } + + private static void bootstrapPlaced(BootstapContext ctx) { + var configured = ctx.lookup(Registries.CONFIGURED_FEATURE).getOrThrow(SHRINE_CONFIGURED); + ctx.register(SHRINE_PLACED, + new PlacedFeature(configured, List.of( + RarityFilter.onAverageOnceEvery(400) // roughly like mineshafts + ))); + } +} diff --git a/src/main/resources/assets/ascend/models/block/shrine_of_remembrance.json b/src/main/resources/assets/ascend/models/block/shrine_of_remembrance.json new file mode 100644 index 0000000..69eeebe --- /dev/null +++ b/src/main/resources/assets/ascend/models/block/shrine_of_remembrance.json @@ -0,0 +1,376 @@ +{ + "format_version": "1.9.0", + "credit": "Made with Blockbench", + "textures": { + "0": "ascend:block/cavity", + "1": "ascend:block/eye", + "2": "ascend:block/luminous_abyss_rock", + "3": "ascend:block/orb", + "particle": "ascend:block/cavity" + }, + "elements": [ + { + "from": [-5, 1, 1], + "to": [-4, 15, 15], + "rotation": {"angle": -22.5, "axis": "z", "origin": [-6, 1, 0]}, + "faces": { + "north": {"uv": [14.85714, 0, 16, 2], "texture": "#2"}, + "east": {"uv": [0, 0, 16, 16], "texture": "#2"}, + "south": {"uv": [0, 0, 1.14286, 2], "texture": "#2"}, + "west": {"uv": [0, 0, 16, 16], "texture": "#2"}, + "up": {"uv": [0, 0, 1.14286, 16], "texture": "#2"}, + "down": {"uv": [0, 0, 1.14286, 16], "texture": "#2"} + } + }, + { + "from": [1, 0, 1], + "to": [15, 14, 15], + "faces": { + "north": {"uv": [16, 0.25, 0, 16], "texture": "#2"}, + "east": {"uv": [16, 0.25, 0, 16], "texture": "#2"}, + "south": {"uv": [16, 0.25, 0, 16], "texture": "#2"}, + "west": {"uv": [16, 0.25, 0, 16], "texture": "#2"}, + "up": {"uv": [16, 0.25, 0, 16], "texture": "#2"}, + "down": {"uv": [16, 0.25, 0, 16], "texture": "#2"} + } + }, + { + "from": [1, 0, 9], + "to": [15, 5, 23], + "rotation": {"angle": 0, "axis": "y", "origin": [0, -9, 8]}, + "faces": { + "north": {"uv": [16, 0.25, 0, 5.875], "texture": "#2"}, + "east": {"uv": [16, 0.25, 0, 5.875], "texture": "#2"}, + "south": {"uv": [16, 0.25, 0, 5.875], "texture": "#2"}, + "west": {"uv": [16, 0.25, 0, 5.875], "texture": "#2"}, + "up": {"uv": [16, 0.25, 0, 16], "texture": "#2"}, + "down": {"uv": [16, 0.25, 0, 16], "texture": "#2"} + } + }, + { + "from": [-5, -4, 15], + "to": [1, 10, 16], + "rotation": {"angle": -22.5, "axis": "z", "origin": [7, -2, 15]}, + "faces": { + "north": {"uv": [0, 0, 6, 14], "texture": "#2"}, + "east": {"uv": [0, 0, 6, 14], "texture": "#2"}, + "south": {"uv": [0, 0, 6, 14], "texture": "#2"}, + "west": {"uv": [0, 0, 6, 14], "texture": "#2"}, + "up": {"uv": [0, 0, 6, 14], "texture": "#2"}, + "down": {"uv": [0, 0, 6, 14], "texture": "#2"} + } + }, + { + "from": [-5, -4, 0], + "to": [1, 10, 1], + "rotation": {"angle": -22.5, "axis": "z", "origin": [7, -2, 0]}, + "faces": { + "north": {"uv": [8, 0, 14, 14], "texture": "#2"}, + "east": {"uv": [0, 0, 1, 14], "texture": "#2"}, + "south": {"uv": [0, 0, 6, 14], "texture": "#2"}, + "west": {"uv": [0, 0, 1, 14], "texture": "#2"}, + "up": {"uv": [0, 0, 6, 1], "texture": "#2"}, + "down": {"uv": [0, 0, 6, 1], "texture": "#2"} + } + }, + { + "from": [14, 2, 15], + "to": [20, 16, 16], + "rotation": {"angle": 22.5, "axis": "z", "origin": [26, 4, 15]}, + "faces": { + "north": {"uv": [0, 0, 6, 14], "texture": "#2"}, + "east": {"uv": [0, 0, 6, 14], "texture": "#2"}, + "south": {"uv": [0, 0, 6, 14], "texture": "#2"}, + "west": {"uv": [0, 0, 6, 14], "texture": "#2"}, + "up": {"uv": [0, 0, 6, 14], "texture": "#2"}, + "down": {"uv": [0, 0, 6, 14], "texture": "#2"} + } + }, + { + "from": [20, -1, 1], + "to": [21, 14, 15], + "rotation": {"angle": 22.5, "axis": "z", "origin": [20, 0, 1]}, + "faces": { + "north": {"uv": [0, 0, 14, 15], "texture": "#2"}, + "east": {"uv": [0, 0, 14, 15], "texture": "#2"}, + "south": {"uv": [0, 0, 15, 16], "texture": "#2"}, + "west": {"uv": [0, 0, 14, 15], "texture": "#2"}, + "up": {"uv": [0, 0, 14, 15], "texture": "#2"}, + "down": {"uv": [0, 0, 14, 15], "texture": "#2"} + } + }, + { + "from": [14, 2, 0], + "to": [20, 16, 1], + "rotation": {"angle": 22.5, "axis": "z", "origin": [26, 4, 0]}, + "faces": { + "north": {"uv": [8, 0, 14, 14], "texture": "#2"}, + "east": {"uv": [0, 0, 1, 14], "texture": "#2"}, + "south": {"uv": [0, 0, 6, 14], "texture": "#2"}, + "west": {"uv": [0, 0, 1, 14], "texture": "#2"}, + "up": {"uv": [0, 0, 6, 1], "texture": "#2"}, + "down": {"uv": [0, 0, 6, 1], "texture": "#2"} + } + }, + { + "from": [1, 14, 1], + "to": [15, 26, 8], + "rotation": {"angle": 0, "axis": "y", "origin": [1, 14, 1]}, + "faces": { + "north": {"uv": [0, 0, 14, 12], "texture": "#2"}, + "east": {"uv": [7, 0, 14, 12], "texture": "#2"}, + "south": {"uv": [0, 0, 14, 12], "texture": "#0"}, + "west": {"uv": [0, 0, 7, 12], "texture": "#2"}, + "up": {"uv": [0, 0, 14, 7], "texture": "#2"}, + "down": {"uv": [0, 7, 14, 14], "texture": "#2"} + } + }, + { + "from": [1, 14, 8], + "to": [10, 19, 15], + "rotation": {"angle": 0, "axis": "y", "origin": [1, 14, 1]}, + "faces": { + "north": {"uv": [7, 0, 16, 5], "texture": "#2"}, + "east": {"uv": [9, 10, 16, 15], "texture": "#2"}, + "south": {"uv": [7, 5, 16, 10], "texture": "#2"}, + "west": {"uv": [9, 11, 16, 16], "texture": "#2"}, + "up": {"uv": [9, 7, 0, 0], "texture": "#0"}, + "down": {"uv": [9, 7, 0, 14], "texture": "#2"} + } + }, + { + "from": [1, 19, 8], + "to": [3, 22, 15], + "rotation": {"angle": 0, "axis": "y", "origin": [1, 14, 1]}, + "faces": { + "north": {"uv": [12, 4, 14, 7], "texture": "#2"}, + "east": {"uv": [0, 4, 7, 7], "texture": "#0"}, + "south": {"uv": [0, 4, 2, 7], "texture": "#2"}, + "west": {"uv": [7, 4, 14, 7], "texture": "#2"}, + "up": {"uv": [0, 7, 2, 14], "texture": "#2"}, + "down": {"uv": [0, 0, 2, 7], "texture": "#2"} + } + }, + { + "from": [3, 19, 8], + "to": [7, 21, 15], + "rotation": {"angle": 0, "axis": "y", "origin": [1, 14, 1]}, + "faces": { + "north": {"uv": [8, 5, 12, 7], "texture": "#2"}, + "east": {"uv": [0, 5, 7, 7], "texture": "#0"}, + "south": {"uv": [2, 5, 6, 7], "texture": "#2"}, + "west": {"uv": [7, 5, 14, 7], "texture": "#2"}, + "up": {"uv": [2, 7, 6, 14], "texture": "#0"}, + "down": {"uv": [2, 0, 6, 7], "texture": "#2"} + } + }, + { + "from": [1, 22, 8], + "to": [3, 26, 15], + "rotation": {"angle": 0, "axis": "y", "origin": [1, 14, 1]}, + "faces": { + "north": {"uv": [12, 0, 14, 4], "texture": "#2"}, + "east": {"uv": [0, 0, 7, 4], "texture": "#0"}, + "south": {"uv": [0, 0, 2, 4], "texture": "#2"}, + "west": {"uv": [7, 0, 14, 4], "texture": "#2"}, + "up": {"uv": [0, 7, 2, 14], "texture": "#2"}, + "down": {"uv": [0, 0, 2, 7], "texture": "#2"} + } + }, + { + "from": [5, 22, 8], + "to": [10, 24, 15], + "rotation": {"angle": 0, "axis": "y", "origin": [1, 14, 1]}, + "faces": { + "north": {"uv": [5, 2, 10, 4], "texture": "#2"}, + "east": {"uv": [0, 2, 7, 4], "texture": "#2"}, + "south": {"uv": [4, 2, 9, 4], "texture": "#2"}, + "west": {"uv": [7, 2, 14, 4], "texture": "#0"}, + "up": {"uv": [4, 7, 9, 14], "texture": "#2"}, + "down": {"uv": [4, 0, 9, 7], "texture": "#0"} + } + }, + { + "from": [3, 24, 8], + "to": [10, 26, 15], + "rotation": {"angle": 0, "axis": "y", "origin": [1, 14, 1]}, + "faces": { + "north": {"uv": [5, 0, 12, 2], "texture": "#2"}, + "east": {"uv": [0, 0, 7, 2], "texture": "#2"}, + "south": {"uv": [2, 0, 9, 2], "texture": "#2"}, + "west": {"uv": [7, 0, 14, 2], "texture": "#2"}, + "up": {"uv": [2, 7, 9, 14], "texture": "#2"}, + "down": {"uv": [2, 0, 9, 7], "texture": "#0"} + } + }, + { + "from": [5, 21, 8], + "to": [7, 22, 15], + "rotation": {"angle": 0, "axis": "y", "origin": [1, 14, 1]}, + "faces": { + "north": {"uv": [8, 4, 10, 5], "texture": "#2"}, + "east": {"uv": [0, 4, 7, 5], "texture": "#0"}, + "south": {"uv": [4, 4, 6, 5], "texture": "#2"}, + "west": {"uv": [7, 4, 14, 5], "texture": "#0"}, + "up": {"uv": [4, 7, 6, 14], "texture": "#2"}, + "down": {"uv": [4, 0, 6, 7], "texture": "#2"} + } + }, + { + "from": [10, 22, 8], + "to": [15, 26, 15], + "rotation": {"angle": 0, "axis": "y", "origin": [1, 14, 1]}, + "faces": { + "north": {"uv": [0, 0, 5, 4], "texture": "#2"}, + "east": {"uv": [0, 0, 7, 4], "texture": "#2"}, + "south": {"uv": [9, 0, 14, 4], "texture": "#2"}, + "west": {"uv": [7, 0, 14, 4], "texture": "#2"}, + "up": {"uv": [9, 7, 14, 14], "texture": "#2"}, + "down": {"uv": [9, 0, 14, 7], "texture": "#2"} + } + }, + { + "from": [10, 14, 8], + "to": [11, 22, 15], + "rotation": {"angle": 0, "axis": "y", "origin": [1, 14, 1]}, + "faces": { + "north": {"uv": [9, 4, 10, 12], "texture": "#2"}, + "east": {"uv": [9, 4, 10, 12], "texture": "#0"}, + "south": {"uv": [9, 4, 10, 12], "texture": "#2"}, + "west": {"uv": [9, 4, 10, 12], "texture": "#0"}, + "up": {"uv": [9, 4, 10, 12], "texture": "#2"}, + "down": {"uv": [9, 4, 10, 12], "texture": "#2"} + } + }, + { + "from": [11, 14, 8], + "to": [14, 16, 15], + "rotation": {"angle": 0, "axis": "y", "origin": [1, 14, 1]}, + "faces": { + "north": {"uv": [1, 10, 4, 12], "texture": "#2"}, + "east": {"uv": [0, 10, 7, 12], "texture": "#2"}, + "south": {"uv": [10, 10, 13, 12], "texture": "#2"}, + "west": {"uv": [7, 10, 14, 12], "texture": "#2"}, + "up": {"uv": [10, 7, 13, 14], "texture": "#0"}, + "down": {"uv": [10, 0, 13, 7], "texture": "#2"} + } + }, + { + "from": [14, 14, 8], + "to": [15, 19, 15], + "rotation": {"angle": 0, "axis": "y", "origin": [1, 14, 1]}, + "faces": { + "north": {"uv": [0, 7, 1, 12], "texture": "#2"}, + "east": {"uv": [0, 7, 7, 12], "texture": "#2"}, + "south": {"uv": [13, 7, 14, 12], "texture": "#2"}, + "west": {"uv": [7, 7, 14, 12], "texture": "#0"}, + "up": {"uv": [13, 7, 14, 14], "texture": "#2"}, + "down": {"uv": [13, 0, 14, 7], "texture": "#2"} + } + }, + { + "from": [11, 19, 8], + "to": [15, 22, 15], + "rotation": {"angle": 0, "axis": "y", "origin": [1, 14, 1]}, + "faces": { + "north": {"uv": [0, 4, 4, 7], "texture": "#2"}, + "east": {"uv": [0, 4, 7, 7], "texture": "#2"}, + "south": {"uv": [10, 4, 14, 7], "texture": "#2"}, + "west": {"uv": [7, 4, 14, 7], "texture": "#2"}, + "up": {"uv": [10, 7, 14, 14], "texture": "#2"}, + "down": {"uv": [10, 0, 14, 7], "texture": "#0"} + } + }, + { + "from": [8, 20, 11], + "to": [9, 21, 12], + "rotation": {"angle": 0, "axis": "y", "origin": [8, 20, 11]}, + "faces": { + "north": {"uv": [2, 2, 0, 0], "texture": "#1"}, + "east": {"uv": [2, 2, 0, 0], "texture": "#1"}, + "south": {"uv": [2, 2, 0, 0], "texture": "#1"}, + "west": {"uv": [2, 2, 0, 0], "texture": "#1"}, + "up": {"uv": [2, 2, 0, 0], "texture": "#1"}, + "down": {"uv": [2, 2, 0, 0], "texture": "#1"} + } + }, + { + "from": [12, 17, 11], + "to": [13, 18, 12], + "rotation": {"angle": 0, "axis": "y", "origin": [12, 17, 11]}, + "faces": { + "north": {"uv": [0, 0, 2, 2], "texture": "#1"}, + "east": {"uv": [0, 0, 2, 2], "texture": "#1"}, + "south": {"uv": [0, 0, 2, 2], "texture": "#1"}, + "west": {"uv": [0, 0, 2, 2], "texture": "#1"}, + "up": {"uv": [0, 0, 2, 2], "texture": "#1"}, + "down": {"uv": [0, 0, 2, 2], "texture": "#1"} + } + }, + { + "from": [3, 22, 11], + "to": [4, 23, 12], + "rotation": {"angle": 0, "axis": "y", "origin": [3, 22, 11]}, + "faces": { + "north": {"uv": [0, 0, 2, 2], "texture": "#1"}, + "east": {"uv": [0, 0, 2, 2], "texture": "#1"}, + "south": {"uv": [0, 0, 2, 2], "texture": "#1"}, + "west": {"uv": [0, 0, 2, 2], "texture": "#1"}, + "up": {"uv": [0, 0, 2, 2], "texture": "#1"}, + "down": {"uv": [0, 0, 2, 2], "texture": "#1"} + } + }, + { + "from": [7, 10, 18], + "to": [9, 12, 20], + "rotation": {"angle": -45, "axis": "z", "origin": [7, 10, 18]}, + "faces": { + "north": {"uv": [0, 0, 2, 2], "texture": "#3"}, + "east": {"uv": [0, 2, 2, 4], "texture": "#3"}, + "south": {"uv": [2, 0, 4, 2], "texture": "#3"}, + "west": {"uv": [2, 2, 4, 4], "texture": "#3"}, + "up": {"uv": [2, 6, 0, 4], "texture": "#3"}, + "down": {"uv": [6, 0, 4, 2], "texture": "#3"} + } + } + ], + "display": { + "thirdperson_righthand": { + "rotation": [75, 45, 0], + "translation": [0, 2.5, 0], + "scale": [0.375, 0.375, 0.375] + }, + "thirdperson_lefthand": { + "rotation": [75, 45, 0], + "translation": [0, 2.5, 0], + "scale": [0.375, 0.375, 0.375] + }, + "firstperson_righthand": { + "rotation": [0, 45, 0], + "scale": [0.4, 0.4, 0.4] + }, + "firstperson_lefthand": { + "rotation": [0, -135, 0], + "scale": [0.4, 0.4, 0.4] + }, + "ground": { + "translation": [0, 3, 0], + "scale": [0.25, 0.25, 0.25] + }, + "gui": { + "rotation": [30, -135, 0], + "scale": [0.625, 0.625, 0.625] + }, + "fixed": { + "scale": [0.5, 0.5, 0.5] + } + }, + "groups": [ + { + "name": "group", + "origin": [-6, 1, 0], + "color": 0, + "children": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24] + } + ] +} \ No newline at end of file diff --git a/src/main/resources/assets/ascend/textures/block/cavity.png b/src/main/resources/assets/ascend/textures/block/cavity.png new file mode 100644 index 0000000..1e5dbb8 Binary files /dev/null and b/src/main/resources/assets/ascend/textures/block/cavity.png differ diff --git a/src/main/resources/assets/ascend/textures/block/eye.png b/src/main/resources/assets/ascend/textures/block/eye.png new file mode 100644 index 0000000..a54526e Binary files /dev/null and b/src/main/resources/assets/ascend/textures/block/eye.png differ diff --git a/src/main/resources/assets/ascend/textures/block/luminous_abyss_rock.png b/src/main/resources/assets/ascend/textures/block/luminous_abyss_rock.png new file mode 100644 index 0000000..a094eaa Binary files /dev/null and b/src/main/resources/assets/ascend/textures/block/luminous_abyss_rock.png differ diff --git a/src/main/resources/assets/ascend/textures/block/orb.png b/src/main/resources/assets/ascend/textures/block/orb.png new file mode 100644 index 0000000..569be13 Binary files /dev/null and b/src/main/resources/assets/ascend/textures/block/orb.png differ