From 4955ed0e1b8a244fb230ebfe693e60cd0177832e Mon Sep 17 00:00:00 2001 From: stellanera Date: Thu, 19 Jun 2025 23:31:10 +0200 Subject: [PATCH 1/8] altar now cuts tanks down to their capacity when it shrinks but gives you a 5s grace period from the moment it knows that the capacity is smaller than the main tank contents. also initial transfer node/filter stuff --- gradle.properties | 4 +- notes.txt | 7 +- .../common/blockentity/BloodAltarTile.java | 22 ++- .../common/blockentity/FilterNodeTile.java | 105 +++++++++++ .../common/blockentity/MasterNodeTile.java | 73 ++++++++ .../common/blockentity/RoutingNodeTile.java | 167 ++++++++++++++++++ .../bloodmagic/common/menu/TrainerMenu.java | 2 +- .../common/routing/IFluidFilter.java | 6 + .../common/routing/IItemFilter.java | 6 + .../common/routing/IResourceMatcher.java | 16 ++ .../common/routing/IRoutingFilter.java | 21 +++ 11 files changed, 420 insertions(+), 9 deletions(-) create mode 100644 src/main/java/wayoftime/bloodmagic/common/blockentity/FilterNodeTile.java create mode 100644 src/main/java/wayoftime/bloodmagic/common/blockentity/MasterNodeTile.java create mode 100644 src/main/java/wayoftime/bloodmagic/common/blockentity/RoutingNodeTile.java create mode 100644 src/main/java/wayoftime/bloodmagic/common/routing/IFluidFilter.java create mode 100644 src/main/java/wayoftime/bloodmagic/common/routing/IItemFilter.java create mode 100644 src/main/java/wayoftime/bloodmagic/common/routing/IResourceMatcher.java create mode 100644 src/main/java/wayoftime/bloodmagic/common/routing/IRoutingFilter.java diff --git a/gradle.properties b/gradle.properties index 7d017dcf9a..c9fdf27987 100644 --- a/gradle.properties +++ b/gradle.properties @@ -18,8 +18,8 @@ minecraft_version=1.21.1 # as they do not follow standard versioning conventions. minecraft_version_range=[1.21.1, 1.22) # The Neo version must agree with the Minecraft version to get a valid artifact -neo_version=21.1.179 -mdg_version=2.0.93 +neo_version=21.1.180 +mdg_version=2.0.95 # The Neo version range can use any version of Neo as bounds neo_version_range=[21.1.0,) # The loader version range can only use the major version of FML as bounds diff --git a/notes.txt b/notes.txt index 69444737db..413a10b9d6 100644 --- a/notes.txt +++ b/notes.txt @@ -9,7 +9,8 @@ Altar - datapackable structure, by default looking at tags (bloodmagic:altar/runes, bloodmagic:altar/tN_capstones, bloodmagic:altar/pillars) with the pillars tag being special in that when its empty it just requires solid blocks - should be working exactly like the old one from user perspective - the blocks to enable redstone pulse on crafting and reading the soul network instead of the altar fill level are based on the block tags bloodmagic:altar/pulse_on_crafting and bloodmagic:altar/soul_network_comparator -- now has its 2 in/out put tanks visible for jade +- now has its 2 in/out put tanks visible for jade (as well as the main tank) +- there is a 5 second grace period when swapping altar structure before the tanks get capped at current max capacity instead of it happening immediately Blood Tank - stores any fluid (emits the same light level the inserted fluid does) @@ -51,4 +52,6 @@ Tartaric gems Training Bracelet - will allow at most the minimum exp required for the selected level for each of the set tomes - in deny others mode all "unknown" upgrades (the ones not set) will return the limit of 0 meaning nothing else can be trained - - in allow others mode all "unknown" upgrades will return the limit of -1 signifying that there is no limit set and can be trained as normal \ No newline at end of file + - in allow others mode all "unknown" upgrades will return the limit of -1 signifying that there is no limit set and can be trained as normal + +Transfer Nodes diff --git a/src/main/java/wayoftime/bloodmagic/common/blockentity/BloodAltarTile.java b/src/main/java/wayoftime/bloodmagic/common/blockentity/BloodAltarTile.java index fb2536f7e2..442072b78b 100644 --- a/src/main/java/wayoftime/bloodmagic/common/blockentity/BloodAltarTile.java +++ b/src/main/java/wayoftime/bloodmagic/common/blockentity/BloodAltarTile.java @@ -90,6 +90,7 @@ public void calculateStats(Map upgrades) { efficiencyMod = (float) Math.pow(0.85, upgrades.getOrDefault(EnumRuneType.EFFICIENCY, 0)); } + private int changingGrace = 0; public static void tick(Level level, BlockPos pos, BlockState state, BloodAltarTile tile) { if (level.isClientSide) { return; @@ -110,26 +111,39 @@ public static void tick(Level level, BlockPos pos, BlockState state, BloodAltarT } } + if (tile.mainTank > tile.getMainCapacity()) { + tile.changingGrace++; + } else { + tile.changingGrace = 0; + } + + if (tile.changingGrace >= 20 * 5) { + tile.mainTank = Math.min(tile.mainTank, tile.getMainCapacity()); + tile.inputTank = Math.min(tile.inputTank, tile.getIOCapacity()); + tile.outputTank = Math.min(tile.inputTank, tile.getIOCapacity()); + } + if (tile.ticks % Math.max(tile.tickRate, 1) == 0) { float ioAmount = 20F * tile.dislocationMod; int input = (int) Math.min(tile.inputTank, ioAmount); - input = (int) Math.min(input, tile.getMainCapacity() - tile.mainTank); + input = Math.clamp(input, 0, tile.getMainCapacity() - tile.mainTank); tile.inputTank -= input; tile.mainTank += input; int output = (int) Math.min(tile.mainTank, ioAmount); - output = (int) Math.min(output, tile.getIOCapacity() - tile.outputTank); + output = Math.clamp(output, 0, tile.getIOCapacity() - tile.outputTank); tile.mainTank -= output; tile.outputTank += output; if (!tile.isActive) { tile.progress = 0; int charge = (int) Math.min(tile.mainTank, tile.chargeAmountMod); - charge = (int) Math.min(charge, tile.getChargingCapacity() - tile.chargingTank); + charge = Math.clamp(charge, 0, tile.getChargingCapacity() - tile.chargingTank); tile.mainTank -= charge; tile.chargingTank += charge; } } + tile.setChanged(); if (!tile.isActive && tile.cooldownAfterCrafting > 0) { tile.cooldownAfterCrafting--; @@ -212,7 +226,7 @@ public static void tick(Level level, BlockPos pos, BlockState state, BloodAltarT } public void sacrificialDaggerCall(int lpAdded, boolean isSacrifice) { - mainTank = mainTank + Math.min((getMainCapacity() - mainTank), (int) ((isSacrifice ? 1 + sacrificeMod : 1 + selfSacMod) * lpAdded)); + mainTank = mainTank + Math.clamp((int) ((isSacrifice ? 1f + sacrificeMod : 1f + selfSacMod) * (float) lpAdded), 0, getMainCapacity() - mainTank); setChanged(); } diff --git a/src/main/java/wayoftime/bloodmagic/common/blockentity/FilterNodeTile.java b/src/main/java/wayoftime/bloodmagic/common/blockentity/FilterNodeTile.java new file mode 100644 index 0000000000..eb7e321e7d --- /dev/null +++ b/src/main/java/wayoftime/bloodmagic/common/blockentity/FilterNodeTile.java @@ -0,0 +1,105 @@ +package wayoftime.bloodmagic.common.blockentity; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.network.chat.Component; +import net.minecraft.world.MenuProvider; +import net.minecraft.world.entity.player.Inventory; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.inventory.AbstractContainerMenu; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.state.BlockState; +import net.neoforged.neoforge.items.ItemStackHandler; +import org.jetbrains.annotations.Nullable; +import wayoftime.bloodmagic.common.datacomponent.BMDataComponents; +import wayoftime.bloodmagic.common.routing.IFluidFilter; +import wayoftime.bloodmagic.common.routing.IItemFilter; + +import java.util.EnumMap; + +public class FilterNodeTile extends RoutingNodeTile implements MenuProvider { + + private final boolean isOutput; + public FilterNodeTile(BlockPos pos, BlockState blockState, boolean isOutput) { + super(BMTiles.FILTER_NODE.get(), pos, blockState); + this.isOutput = isOutput; + } + + public final ItemStackHandler filterInv = new ItemStackHandler(6) { + @Override + public int getSlotLimit(int slot) { + return 1; + } + + @Override + public boolean isItemValid(int slot, ItemStack stack) { + return stack.has(BMDataComponents.filter_data); + } + + @Override + protected void onContentsChanged(int slot) { + setChanged(); + level.sendBlockUpdated(getBlockPos(), getBlockState(), getBlockState(), Block.UPDATE_ALL); + sendFilterInfo(); + } + }; + + @Override + public void masterCheckinRequest() { + super.masterCheckinRequest(); + sendFilterInfo(); + } + + @Override + public void setActive(boolean newState) { + if (isActive != newState) { + BlockEntity be = level.getBlockEntity(masterPos); + if (be instanceof MasterNodeTile master) { + if (newState) { + sendFilterInfo(); + } else { + master.removeNodeInfo(getBlockPos()); + } + } + } + super.setActive(newState); + } + + @Override + public void setMasterPos(BlockPos masterPos) { + super.setMasterPos(masterPos); + sendFilterInfo(); + } + + protected void sendFilterInfo() { + BlockEntity be = level.getBlockEntity(masterPos); + if (be instanceof MasterNodeTile master) { + master.addPriorityInfo(getBlockPos(), getPriorityMap()); + if (isOutput) { + master.addItemOutputFilterInfo(getBlockPos(), getItemFilters()); + master.addFluidOutputFilterInfo(getBlockPos(), getFluidFilters()); + } else { + master.addItemInputFilterInfo(getBlockPos(), getItemFilters()); + master.addFluidInputFilterInfo(getBlockPos(), getFluidFilters()); + } + } + } + + protected EnumMap getPriorityMap() { + + } + + protected EnumMap getItemFilters() {} + + protected EnumMap getFluidFilters() {} + + @Override + public Component getDisplayName() { + } + + @Override + public @Nullable AbstractContainerMenu createMenu(int containerId, Inventory playerInventory, Player player) { + } +} diff --git a/src/main/java/wayoftime/bloodmagic/common/blockentity/MasterNodeTile.java b/src/main/java/wayoftime/bloodmagic/common/blockentity/MasterNodeTile.java new file mode 100644 index 0000000000..957863ef00 --- /dev/null +++ b/src/main/java/wayoftime/bloodmagic/common/blockentity/MasterNodeTile.java @@ -0,0 +1,73 @@ +package wayoftime.bloodmagic.common.blockentity; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.network.chat.Component; +import net.minecraft.world.MenuProvider; +import net.minecraft.world.entity.player.Inventory; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.inventory.AbstractContainerMenu; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.state.BlockState; +import org.jetbrains.annotations.Nullable; +import wayoftime.bloodmagic.common.routing.IFluidFilter; +import wayoftime.bloodmagic.common.routing.IItemFilter; + +import java.util.EnumMap; +import java.util.HashMap; +import java.util.Map; + +public class MasterNodeTile extends RoutingNodeTile implements MenuProvider { + + public MasterNodeTile(BlockPos pos, BlockState blockState) { + super(BMTiles.MASTER_NODE.get(), pos, blockState); + } + + public static void tick(Level level, BlockPos pos, BlockState state, MasterNodeTile node) { + + } + + private Map> inputItemFilterMap = new HashMap<>(); + private Map> outputItemFilterMap = new HashMap<>(); + public void addItemInputFilterInfo(BlockPos pos, EnumMap filters) { + inputItemFilterMap.put(pos, filters); + setChanged(); + } + + public void addItemOutputFilterInfo(BlockPos pos, EnumMap filters) { + outputItemFilterMap.put(pos, filters); + setChanged(); + } + + private Map> inputFluidFilterMap = new HashMap<>(); + private Map> outputFluidFilterMap = new HashMap<>(); + public void addFluidInputFilterInfo(BlockPos pos, EnumMap filters) { + inputFluidFilterMap.put(pos, filters); + setChanged(); + } + + public void addFluidOutputFilterInfo(BlockPos pos, EnumMap filters) { + outputFluidFilterMap.put(pos, filters); + setChanged(); + } + + private Map> priorityMap = new HashMap<>(); + public void addPriorityInfo(BlockPos pos, EnumMap priority) { + priorityMap.put(pos, priority); + } + + public void removeNodeInfo(BlockPos pos) { + inputItemFilterMap.remove(pos); + outputItemFilterMap.remove(pos); + inputFluidFilterMap.remove(pos); + outputFluidFilterMap.remove(pos); + } + + @Override + public Component getDisplayName() { + } + + @Override + public @Nullable AbstractContainerMenu createMenu(int containerId, Inventory playerInventory, Player player) { + } +} diff --git a/src/main/java/wayoftime/bloodmagic/common/blockentity/RoutingNodeTile.java b/src/main/java/wayoftime/bloodmagic/common/blockentity/RoutingNodeTile.java new file mode 100644 index 0000000000..c4e5f4aea3 --- /dev/null +++ b/src/main/java/wayoftime/bloodmagic/common/blockentity/RoutingNodeTile.java @@ -0,0 +1,167 @@ +package wayoftime.bloodmagic.common.blockentity; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.HolderLookup; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.ListTag; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; + +import java.util.HashSet; +import java.util.Set; + +public class RoutingNodeTile extends BaseTile { + + public RoutingNodeTile(BlockEntityType type, BlockPos pos, BlockState blockState) { + super(type, pos, blockState); + } + + protected BlockPos masterPos = BlockPos.ZERO; // TODO 0, 0, 0 is NOT an invalid coordinate (at least not in every DIM) and putting a master node there WILL make it NOT work + protected BlockPos parentPos = BlockPos.ZERO; // same thing here + protected Set children = new HashSet<>(); + protected boolean isActive = true; + + public static void tick(Level level, BlockPos pos, BlockState state, T node) { + // TODO might want to do something to prevent fast clocks from permanently dis- and re-enabling half the network. not that you *should* have one next to your network but it might cause some lag + int signal = level.getBestNeighborSignal(pos); + node.setActive(signal == 0); + + if (node.parentPos != BlockPos.ZERO) { + BlockEntity be = node.level.getBlockEntity(node.parentPos); + if (!(be instanceof RoutingNodeTile)) { + node.removeFromNetwork(); + } + } + } + + // when master node wants to (re)evaluate the network. + // general nodes dont need to do anything here except pass it on, filter nodes will have to resend their filter config + public void masterCheckinRequest() { + children.forEach(child -> { + BlockEntity be = this.level.getBlockEntity(child); + if (be instanceof RoutingNodeTile node) { + node.masterCheckinRequest(); + } else { // you in da wrong neighbourhood dawg + children.remove(child); + } + }); + } + + public void setActive(boolean newState) { + if (this.isActive == newState) { + return; // no change, done + } + this.isActive = newState; + this.setChanged(); + this.level.sendBlockUpdated(getBlockPos(), getBlockState(), getBlockState(), Block.UPDATE_ALL); // send block update for sync so client knows and can render lines appropriately + + children.forEach(child -> { + BlockEntity be = this.level.getBlockEntity(child); + if (be instanceof RoutingNodeTile node) { + node.setActive(newState); + } + }); + // TODO filter nodes should update the master node with their filter info from here + } + + public boolean isActive() { + return isActive; + } + + public void setParent(BlockPos parent) { + this.parentPos = parent; + this.setChanged(); + this.level.sendBlockUpdated(getBlockPos(), getBlockState(), getBlockState(), Block.UPDATE_ALL); // send block update for sync so client knows and can render lines appropriately + } + + public boolean hasParent() { + return this.parentPos != BlockPos.ZERO; + } + + public BlockPos getParentPos() { + return this.parentPos; + } + + public void addConnection(BlockPos child) { + children.add(child); + this.setChanged(); + this.level.sendBlockUpdated(getBlockPos(), getBlockState(), getBlockState(), Block.UPDATE_ALL); // send block update for sync so client knows and can render lines appropriately + } + + public void removeConnection(BlockPos child) { + children.remove(child); + BlockEntity be = this.level.getBlockEntity(child); + if (be instanceof RoutingNodeTile node) { + node.removeFromNetwork(); + } + this.setChanged(); + this.level.sendBlockUpdated(getBlockPos(), getBlockState(), getBlockState(), Block.UPDATE_ALL); // send block update for sync so client knows and can render lines appropriately + } + + public void removeFromNetwork() { + this.parentPos = BlockPos.ZERO; + this.masterPos = BlockPos.ZERO; + + // TODO filtering nodes should remove their info from master here + children.forEach(child -> { + BlockEntity be = this.level.getBlockEntity(child); + if (be instanceof RoutingNodeTile node) { + node.removeFromNetwork(); + } else { // you in da wrong neighbourhood dawg + children.remove(child); + } + }); + } + + public boolean hasMaster() { + return this.masterPos != BlockPos.ZERO; + } + + public BlockPos getMasterPos() { + return this.masterPos; + } + + public void setMasterPos(BlockPos masterPos) { + this.masterPos = masterPos; + this.setChanged(); + this.level.sendBlockUpdated(getBlockPos(), getBlockState(), getBlockState(), Block.UPDATE_ALL); // send block update for sync so client knows and can render lines appropriately + } + + @Override + protected void saveAdditional(CompoundTag tag, HolderLookup.Provider registries) { + super.saveAdditional(tag, registries); + CompoundTag nodeInfo = new CompoundTag(); + nodeInfo.putBoolean("active", isActive); + nodeInfo.put("master", posToTag(masterPos)); + ListTag childTag = new ListTag(); + children.forEach(pos -> childTag.add(posToTag(pos))); + nodeInfo.put("children", childTag); + tag.put("node_info", nodeInfo); + } + + @Override + protected void loadAdditional(CompoundTag tag, HolderLookup.Provider registries) { + super.loadAdditional(tag, registries); + CompoundTag nodeInfo = tag.getCompound("node_info"); + this.isActive = nodeInfo.getBoolean("active"); + masterPos = tagToPos(tag.getCompound("master")); + ListTag childrenTag = nodeInfo.getList("children", ListTag.TAG_COMPOUND); + children.clear(); // just to be sure theres no weird overflow happening + childrenTag.forEach(childTag -> children.add(tagToPos((CompoundTag) childTag))); // cast should be fine since we tell .getList its a list of TC's. I *think* + } + + protected CompoundTag posToTag(BlockPos pos) { + CompoundTag tag = new CompoundTag(); + tag.putInt("x", pos.getX()); + tag.putInt("y", pos.getY()); + tag.putInt("z", pos.getZ()); + return tag; + } + + protected BlockPos tagToPos(CompoundTag tag) { + return new BlockPos(tag.getInt("x"), tag.getInt("y"), tag.getInt("z")); + } +} diff --git a/src/main/java/wayoftime/bloodmagic/common/menu/TrainerMenu.java b/src/main/java/wayoftime/bloodmagic/common/menu/TrainerMenu.java index 23060a4725..baecc3d6bb 100644 --- a/src/main/java/wayoftime/bloodmagic/common/menu/TrainerMenu.java +++ b/src/main/java/wayoftime/bloodmagic/common/menu/TrainerMenu.java @@ -14,7 +14,7 @@ public class TrainerMenu extends AbstractGhostMenu { // CLIENT constructor public TrainerMenu(int containerId, Inventory playerInv, RegistryFriendlyByteBuf buf) { - // buf -> int heldSlot + // buf -> int heldSlot super(BMMenus.TRAINER.get(), containerId, playerInv, 3 + 16, 4, 4, 89, 15, 105, buf.readInt()); } diff --git a/src/main/java/wayoftime/bloodmagic/common/routing/IFluidFilter.java b/src/main/java/wayoftime/bloodmagic/common/routing/IFluidFilter.java new file mode 100644 index 0000000000..5a1553ff2e --- /dev/null +++ b/src/main/java/wayoftime/bloodmagic/common/routing/IFluidFilter.java @@ -0,0 +1,6 @@ +package wayoftime.bloodmagic.common.routing; + +import net.neoforged.neoforge.fluids.FluidStack; + +public interface IFluidFilter extends IRoutingFilter { +} diff --git a/src/main/java/wayoftime/bloodmagic/common/routing/IItemFilter.java b/src/main/java/wayoftime/bloodmagic/common/routing/IItemFilter.java new file mode 100644 index 0000000000..043d678230 --- /dev/null +++ b/src/main/java/wayoftime/bloodmagic/common/routing/IItemFilter.java @@ -0,0 +1,6 @@ +package wayoftime.bloodmagic.common.routing; + +import net.minecraft.world.item.ItemStack; + +public interface IItemFilter extends IRoutingFilter { +} diff --git a/src/main/java/wayoftime/bloodmagic/common/routing/IResourceMatcher.java b/src/main/java/wayoftime/bloodmagic/common/routing/IResourceMatcher.java new file mode 100644 index 0000000000..ec4e0d9c0f --- /dev/null +++ b/src/main/java/wayoftime/bloodmagic/common/routing/IResourceMatcher.java @@ -0,0 +1,16 @@ +package wayoftime.bloodmagic.common.routing; + +public interface IResourceMatcher { + + boolean doesResourceMatch(T resource); + + int getCount(); + + void setCount(int count); + + void grow(int amount); + + void shrink(int amount); + + boolean isEmpty(); +} diff --git a/src/main/java/wayoftime/bloodmagic/common/routing/IRoutingFilter.java b/src/main/java/wayoftime/bloodmagic/common/routing/IRoutingFilter.java new file mode 100644 index 0000000000..08a0cc9bb7 --- /dev/null +++ b/src/main/java/wayoftime/bloodmagic/common/routing/IRoutingFilter.java @@ -0,0 +1,21 @@ +package wayoftime.bloodmagic.common.routing; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; + +import java.util.List; + +public interface IRoutingFilter { + + void initializeFilter(List> matchList, BlockPos target, Direction interactionSide, boolean isOutput); + + T transferThroughOutputFilter(T resource); + + int transferThroughInputFilter(IRoutingFilter outputFilter, int maxTransfer); + + boolean doesResourcePassFilter(T resource); + + boolean doesResourceMatch(IResourceMatcher matcher, T resource); + + List> getMatchList(); +} From 4682291465f6159b56438a91afa208291510c46f Mon Sep 17 00:00:00 2001 From: stellanera Date: Fri, 7 Nov 2025 10:59:56 +0100 Subject: [PATCH 2/8] gotta go --- gradle.properties | 4 +- .../provider/BMBlockstateProvider.java | 28 + .../bloodmagic/blockstates/routing_node.json | 64 ++ .../blockstates/routing_node_input.json | 64 ++ .../blockstates/routing_node_master.json | 64 ++ .../blockstates/routing_node_output.json | 64 ++ .../bloodmagic/models/item/node_router.json | 6 + .../living_upgrades/exp/arrow_protect.json | 8 +- .../wayoftime/bloodmagic/ServerConfig.java | 29 +- .../client/event/ClientModEventHandler.java | 2 +- .../render/blockentity/NodeRenderer.java | 166 ++++ .../bloodmagic/common/block/BMBlocks.java | 11 + .../common/block/FilterNodeBlock.java | 21 + .../common/block/MasterNodeBlock.java | 18 + .../common/block/RoutingNodeBlock.java | 128 +++ .../common/blockentity/BMTiles.java | 13 + .../common/blockentity/FilterNodeTile.java | 84 +- .../common/blockentity/MasterNodeTile.java | 96 ++- .../common/blockentity/RoutingNodeTile.java | 80 +- .../bloodmagic/common/capability/BMCaps.java | 15 + .../datacomponent/BMDataComponents.java | 2 + .../common/event/CommonEventHandler.java | 1 - .../bloodmagic/common/item/BMItems.java | 2 + .../common/item/LivingArmourItem.java | 2 +- .../common/item/NodeRouterItem.java | 21 + .../common/routing/IFluidFilter.java | 6 - .../common/routing/IItemFilter.java | 6 - .../common/routing/IRoutingFilter.java | 9 +- .../common/routing/NodeContext.java | 15 + .../bloodmagic/util/helper/RenderHelper.java | 22 +- .../bloodmagic/blockstates/doubt_block.json | 2 +- .../blockstates/life_essence_block.json | 2 +- .../bloodmagic/models/block/doubt_block.json | 4 +- .../models/block/life_essence_block.json | 4 +- .../routing/modelmasterroutingnodebase.mtl | 11 + .../routing/modelmasterroutingnodebase.obj | 360 +++++++++ .../modelmasterroutingnodecombined.mtl | 24 + .../modelmasterroutingnodecombined.obj | 637 +++++++++++++++ .../routing/modelmasterroutingnodecore.mtl | 11 + .../routing/modelmasterroutingnodecore.obj | 66 ++ .../block/routing/modelroutingnodebase.mtl | 11 + .../block/routing/modelroutingnodebase.obj | 444 ++++++++++ .../routing/modelroutingnodecombined.mtl | 24 + .../routing/modelroutingnodecombined.obj | 757 ++++++++++++++++++ .../block/routing/modelroutingnodecore.mtl | 11 + .../block/routing/modelroutingnodecore.obj | 66 ++ .../models/block/routing_node_base.json | 10 + .../models/block/routing_node_base_input.json | 6 + .../block/routing_node_base_master.json | 10 + .../block/routing_node_base_output.json | 6 + .../models/block/routing_node_core.json | 11 + .../models/block/routing_node_core_input.json | 6 + .../block/routing_node_core_master.json | 11 + .../block/routing_node_core_output.json | 6 + .../bloodmagic/models/item/routing_node.json | 11 + .../models/item/routing_node_input.json | 7 + .../models/item/routing_node_master.json | 11 + .../models/item/routing_node_output.json | 7 + .../textures/block/crystal_corrosive.png | Bin 0 -> 748 bytes .../textures/block/crystal_default.png | Bin 0 -> 740 bytes .../textures/block/crystal_destructive.png | Bin 0 -> 748 bytes .../textures/block/crystal_steadfast.png | Bin 0 -> 734 bytes .../textures/block/crystal_vengeful.png | Bin 0 -> 737 bytes .../textures/block/hellforged_corrosive.png | Bin 0 -> 699 bytes ...orged_block.png => hellforged_default.png} | Bin .../textures/block/hellforged_destructive.png | Bin 0 -> 698 bytes .../textures/block/hellforged_steadfast.png | Bin 0 -> 738 bytes .../textures/block/hellforged_vengeful.png | Bin 0 -> 692 bytes .../textures/block/routing_node.png | Bin 0 -> 1798 bytes .../textures/block/routing_node_input.png | Bin 0 -> 8922 bytes .../textures/block/routing_node_master.png | Bin 0 -> 2898 bytes .../textures/block/routing_node_output.png | Bin 0 -> 8919 bytes .../bloodmagic/textures/item/node_router.png | Bin 0 -> 492 bytes 73 files changed, 3397 insertions(+), 190 deletions(-) create mode 100644 src/generated/resources/assets/bloodmagic/blockstates/routing_node.json create mode 100644 src/generated/resources/assets/bloodmagic/blockstates/routing_node_input.json create mode 100644 src/generated/resources/assets/bloodmagic/blockstates/routing_node_master.json create mode 100644 src/generated/resources/assets/bloodmagic/blockstates/routing_node_output.json create mode 100644 src/generated/resources/assets/bloodmagic/models/item/node_router.json create mode 100644 src/main/java/wayoftime/bloodmagic/client/render/blockentity/NodeRenderer.java create mode 100644 src/main/java/wayoftime/bloodmagic/common/block/FilterNodeBlock.java create mode 100644 src/main/java/wayoftime/bloodmagic/common/block/MasterNodeBlock.java create mode 100644 src/main/java/wayoftime/bloodmagic/common/block/RoutingNodeBlock.java create mode 100644 src/main/java/wayoftime/bloodmagic/common/capability/BMCaps.java create mode 100644 src/main/java/wayoftime/bloodmagic/common/item/NodeRouterItem.java delete mode 100644 src/main/java/wayoftime/bloodmagic/common/routing/IFluidFilter.java delete mode 100644 src/main/java/wayoftime/bloodmagic/common/routing/IItemFilter.java create mode 100644 src/main/java/wayoftime/bloodmagic/common/routing/NodeContext.java create mode 100755 src/main/resources/assets/bloodmagic/models/block/routing/modelmasterroutingnodebase.mtl create mode 100755 src/main/resources/assets/bloodmagic/models/block/routing/modelmasterroutingnodebase.obj create mode 100755 src/main/resources/assets/bloodmagic/models/block/routing/modelmasterroutingnodecombined.mtl create mode 100755 src/main/resources/assets/bloodmagic/models/block/routing/modelmasterroutingnodecombined.obj create mode 100755 src/main/resources/assets/bloodmagic/models/block/routing/modelmasterroutingnodecore.mtl create mode 100755 src/main/resources/assets/bloodmagic/models/block/routing/modelmasterroutingnodecore.obj create mode 100755 src/main/resources/assets/bloodmagic/models/block/routing/modelroutingnodebase.mtl create mode 100755 src/main/resources/assets/bloodmagic/models/block/routing/modelroutingnodebase.obj create mode 100755 src/main/resources/assets/bloodmagic/models/block/routing/modelroutingnodecombined.mtl create mode 100755 src/main/resources/assets/bloodmagic/models/block/routing/modelroutingnodecombined.obj create mode 100755 src/main/resources/assets/bloodmagic/models/block/routing/modelroutingnodecore.mtl create mode 100755 src/main/resources/assets/bloodmagic/models/block/routing/modelroutingnodecore.obj create mode 100755 src/main/resources/assets/bloodmagic/models/block/routing_node_base.json create mode 100644 src/main/resources/assets/bloodmagic/models/block/routing_node_base_input.json create mode 100755 src/main/resources/assets/bloodmagic/models/block/routing_node_base_master.json create mode 100644 src/main/resources/assets/bloodmagic/models/block/routing_node_base_output.json create mode 100755 src/main/resources/assets/bloodmagic/models/block/routing_node_core.json create mode 100644 src/main/resources/assets/bloodmagic/models/block/routing_node_core_input.json create mode 100755 src/main/resources/assets/bloodmagic/models/block/routing_node_core_master.json create mode 100644 src/main/resources/assets/bloodmagic/models/block/routing_node_core_output.json create mode 100755 src/main/resources/assets/bloodmagic/models/item/routing_node.json create mode 100644 src/main/resources/assets/bloodmagic/models/item/routing_node_input.json create mode 100755 src/main/resources/assets/bloodmagic/models/item/routing_node_master.json create mode 100644 src/main/resources/assets/bloodmagic/models/item/routing_node_output.json create mode 100755 src/main/resources/assets/bloodmagic/textures/block/crystal_corrosive.png create mode 100755 src/main/resources/assets/bloodmagic/textures/block/crystal_default.png create mode 100755 src/main/resources/assets/bloodmagic/textures/block/crystal_destructive.png create mode 100755 src/main/resources/assets/bloodmagic/textures/block/crystal_steadfast.png create mode 100755 src/main/resources/assets/bloodmagic/textures/block/crystal_vengeful.png create mode 100755 src/main/resources/assets/bloodmagic/textures/block/hellforged_corrosive.png rename src/main/resources/assets/bloodmagic/textures/block/{hellforged_block.png => hellforged_default.png} (100%) mode change 100644 => 100755 create mode 100755 src/main/resources/assets/bloodmagic/textures/block/hellforged_destructive.png create mode 100755 src/main/resources/assets/bloodmagic/textures/block/hellforged_steadfast.png create mode 100755 src/main/resources/assets/bloodmagic/textures/block/hellforged_vengeful.png create mode 100755 src/main/resources/assets/bloodmagic/textures/block/routing_node.png create mode 100755 src/main/resources/assets/bloodmagic/textures/block/routing_node_input.png create mode 100755 src/main/resources/assets/bloodmagic/textures/block/routing_node_master.png create mode 100755 src/main/resources/assets/bloodmagic/textures/block/routing_node_output.png create mode 100755 src/main/resources/assets/bloodmagic/textures/item/node_router.png diff --git a/gradle.properties b/gradle.properties index c9fdf27987..44686c633d 100644 --- a/gradle.properties +++ b/gradle.properties @@ -18,8 +18,8 @@ minecraft_version=1.21.1 # as they do not follow standard versioning conventions. minecraft_version_range=[1.21.1, 1.22) # The Neo version must agree with the Minecraft version to get a valid artifact -neo_version=21.1.180 -mdg_version=2.0.95 +neo_version=21.1.213 +mdg_version=2.0.115 # The Neo version range can use any version of Neo as bounds neo_version_range=[21.1.0,) # The loader version range can only use the major version of FML as bounds diff --git a/src/datagen/java/wayoftime/bloodmagic/datagen/provider/BMBlockstateProvider.java b/src/datagen/java/wayoftime/bloodmagic/datagen/provider/BMBlockstateProvider.java index 3fdd68512a..2320b51ac9 100644 --- a/src/datagen/java/wayoftime/bloodmagic/datagen/provider/BMBlockstateProvider.java +++ b/src/datagen/java/wayoftime/bloodmagic/datagen/provider/BMBlockstateProvider.java @@ -3,13 +3,16 @@ import net.minecraft.core.Direction; import net.minecraft.data.PackOutput; import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.level.block.Block; import net.neoforged.neoforge.client.model.generators.BlockStateProvider; import net.neoforged.neoforge.client.model.generators.ModelFile; +import net.neoforged.neoforge.client.model.generators.MultiPartBlockStateBuilder; import net.neoforged.neoforge.client.model.generators.VariantBlockStateBuilder; import net.neoforged.neoforge.common.data.ExistingFileHelper; import wayoftime.bloodmagic.BloodMagic; import wayoftime.bloodmagic.common.block.ARCBlock; import wayoftime.bloodmagic.common.block.BMBlocks; +import wayoftime.bloodmagic.common.block.RoutingNodeBlock; import wayoftime.bloodmagic.common.datacomponent.EnumWillType; public class BMBlockstateProvider extends BlockStateProvider { @@ -23,6 +26,31 @@ protected void registerStatesAndModels() { simpleBlockWithItem(block.get(), cubeAll(block.get())); }); + buildArc(); + + buildRoutingNode(BMBlocks.ROUTING_NODE.block().get(), ""); + buildRoutingNode(BMBlocks.MASTER_NODE.block().get(), "_master"); + buildRoutingNode(BMBlocks.INPUT_ROUTING_NODE.block().get(), "_input"); + buildRoutingNode(BMBlocks.OUTPUT_ROUTING_NODE.block().get(), "_output"); + } + + private void buildRoutingNode(Block node, String type) { + MultiPartBlockStateBuilder builder = getMultipartBuilder(node); + + ModelFile base = models().getExistingFile(bm("block/routing_node_base" + type)); + ModelFile core = models().getExistingFile(bm("block/routing_node_core" + type)); + + builder.part().modelFile(core).addModel().end(); + + builder.part().modelFile(base).addModel().condition(RoutingNodeBlock.DOWN, true).end(); + builder.part().modelFile(base).rotationX(180).addModel().condition(RoutingNodeBlock.UP, true).end(); + builder.part().modelFile(base).rotationX(270).addModel().condition(RoutingNodeBlock.NORTH, true).end(); + builder.part().modelFile(base).rotationX(90).addModel().condition(RoutingNodeBlock.SOUTH, true).end(); + builder.part().modelFile(base).rotationY(90).rotationX(90).addModel().condition(RoutingNodeBlock.WEST, true).end(); + builder.part().modelFile(base).rotationY(90).rotationX(270).addModel().condition(RoutingNodeBlock.EAST, true).end(); + } + + private void buildArc() { VariantBlockStateBuilder builder = getVariantBuilder(BMBlocks.ARC_BLOCK.block().get()); String bottom = "block/arc_bottom"; String lit = "_lit"; diff --git a/src/generated/resources/assets/bloodmagic/blockstates/routing_node.json b/src/generated/resources/assets/bloodmagic/blockstates/routing_node.json new file mode 100644 index 0000000000..f03a84c340 --- /dev/null +++ b/src/generated/resources/assets/bloodmagic/blockstates/routing_node.json @@ -0,0 +1,64 @@ +{ + "multipart": [ + { + "apply": { + "model": "bloodmagic:block/routing_node_core" + } + }, + { + "apply": { + "model": "bloodmagic:block/routing_node_base" + }, + "when": { + "down": "true" + } + }, + { + "apply": { + "model": "bloodmagic:block/routing_node_base", + "x": 180 + }, + "when": { + "up": "true" + } + }, + { + "apply": { + "model": "bloodmagic:block/routing_node_base", + "x": 270 + }, + "when": { + "north": "true" + } + }, + { + "apply": { + "model": "bloodmagic:block/routing_node_base", + "x": 90 + }, + "when": { + "south": "true" + } + }, + { + "apply": { + "model": "bloodmagic:block/routing_node_base", + "x": 90, + "y": 90 + }, + "when": { + "west": "true" + } + }, + { + "apply": { + "model": "bloodmagic:block/routing_node_base", + "x": 270, + "y": 90 + }, + "when": { + "east": "true" + } + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/assets/bloodmagic/blockstates/routing_node_input.json b/src/generated/resources/assets/bloodmagic/blockstates/routing_node_input.json new file mode 100644 index 0000000000..b0b650492e --- /dev/null +++ b/src/generated/resources/assets/bloodmagic/blockstates/routing_node_input.json @@ -0,0 +1,64 @@ +{ + "multipart": [ + { + "apply": { + "model": "bloodmagic:block/routing_node_core_input" + } + }, + { + "apply": { + "model": "bloodmagic:block/routing_node_base_input" + }, + "when": { + "down": "true" + } + }, + { + "apply": { + "model": "bloodmagic:block/routing_node_base_input", + "x": 180 + }, + "when": { + "up": "true" + } + }, + { + "apply": { + "model": "bloodmagic:block/routing_node_base_input", + "x": 270 + }, + "when": { + "north": "true" + } + }, + { + "apply": { + "model": "bloodmagic:block/routing_node_base_input", + "x": 90 + }, + "when": { + "south": "true" + } + }, + { + "apply": { + "model": "bloodmagic:block/routing_node_base_input", + "x": 90, + "y": 90 + }, + "when": { + "west": "true" + } + }, + { + "apply": { + "model": "bloodmagic:block/routing_node_base_input", + "x": 270, + "y": 90 + }, + "when": { + "east": "true" + } + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/assets/bloodmagic/blockstates/routing_node_master.json b/src/generated/resources/assets/bloodmagic/blockstates/routing_node_master.json new file mode 100644 index 0000000000..3ffae37e61 --- /dev/null +++ b/src/generated/resources/assets/bloodmagic/blockstates/routing_node_master.json @@ -0,0 +1,64 @@ +{ + "multipart": [ + { + "apply": { + "model": "bloodmagic:block/routing_node_core_master" + } + }, + { + "apply": { + "model": "bloodmagic:block/routing_node_base_master" + }, + "when": { + "down": "true" + } + }, + { + "apply": { + "model": "bloodmagic:block/routing_node_base_master", + "x": 180 + }, + "when": { + "up": "true" + } + }, + { + "apply": { + "model": "bloodmagic:block/routing_node_base_master", + "x": 270 + }, + "when": { + "north": "true" + } + }, + { + "apply": { + "model": "bloodmagic:block/routing_node_base_master", + "x": 90 + }, + "when": { + "south": "true" + } + }, + { + "apply": { + "model": "bloodmagic:block/routing_node_base_master", + "x": 90, + "y": 90 + }, + "when": { + "west": "true" + } + }, + { + "apply": { + "model": "bloodmagic:block/routing_node_base_master", + "x": 270, + "y": 90 + }, + "when": { + "east": "true" + } + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/assets/bloodmagic/blockstates/routing_node_output.json b/src/generated/resources/assets/bloodmagic/blockstates/routing_node_output.json new file mode 100644 index 0000000000..88cfee2a15 --- /dev/null +++ b/src/generated/resources/assets/bloodmagic/blockstates/routing_node_output.json @@ -0,0 +1,64 @@ +{ + "multipart": [ + { + "apply": { + "model": "bloodmagic:block/routing_node_core_output" + } + }, + { + "apply": { + "model": "bloodmagic:block/routing_node_base_output" + }, + "when": { + "down": "true" + } + }, + { + "apply": { + "model": "bloodmagic:block/routing_node_base_output", + "x": 180 + }, + "when": { + "up": "true" + } + }, + { + "apply": { + "model": "bloodmagic:block/routing_node_base_output", + "x": 270 + }, + "when": { + "north": "true" + } + }, + { + "apply": { + "model": "bloodmagic:block/routing_node_base_output", + "x": 90 + }, + "when": { + "south": "true" + } + }, + { + "apply": { + "model": "bloodmagic:block/routing_node_base_output", + "x": 90, + "y": 90 + }, + "when": { + "west": "true" + } + }, + { + "apply": { + "model": "bloodmagic:block/routing_node_base_output", + "x": 270, + "y": 90 + }, + "when": { + "east": "true" + } + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/assets/bloodmagic/models/item/node_router.json b/src/generated/resources/assets/bloodmagic/models/item/node_router.json new file mode 100644 index 0000000000..d15ee8f177 --- /dev/null +++ b/src/generated/resources/assets/bloodmagic/models/item/node_router.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "bloodmagic:item/node_router" + } +} \ No newline at end of file diff --git a/src/generated/resources/data/bloodmagic/bloodmagic/living_upgrades/exp/arrow_protect.json b/src/generated/resources/data/bloodmagic/bloodmagic/living_upgrades/exp/arrow_protect.json index 3fc7b04a7a..a67f2773de 100644 --- a/src/generated/resources/data/bloodmagic/bloodmagic/living_upgrades/exp/arrow_protect.json +++ b/src/generated/resources/data/bloodmagic/bloodmagic/living_upgrades/exp/arrow_protect.json @@ -26,11 +26,7 @@ ] }, "levels": { - "exp_to_level": { - "1": 1 - }, - "level_to_cost": { - "1": 0 - } + "exp_to_level": {}, + "level_to_cost": {} } } \ No newline at end of file diff --git a/src/main/java/wayoftime/bloodmagic/ServerConfig.java b/src/main/java/wayoftime/bloodmagic/ServerConfig.java index a71fbd71a9..d32ccfa2a8 100644 --- a/src/main/java/wayoftime/bloodmagic/ServerConfig.java +++ b/src/main/java/wayoftime/bloodmagic/ServerConfig.java @@ -5,12 +5,33 @@ public class ServerConfig { public final ModConfigSpec.ConfigValue SELF_SACRIFICE_CONVERSION; + public final ModConfigSpec.ConfigValue SACRIFICE_CONVERSION; public final ModConfigSpec.ConfigValue DEFAULT_UPGRADE_POINTS; - public final ModConfigSpec.ConfigValue EVOLUTION_UPGRADE_POINTS; // might as well put that here already + public final ModConfigSpec.ConfigValue EVOLUTION_UPGRADE_POINTS; + + public final ModConfigSpec.ConfigValue BASE_ITEM_TRANSFER; + public final ModConfigSpec.ConfigValue UPGRADE_ITEM_TRANSFER; + + public final ModConfigSpec.ConfigValue BASE_FLUID_TRANSFER; + public final ModConfigSpec.ConfigValue UPGRADE_FLUID_TRANSFER; + + public final ModConfigSpec.ConfigValue MAX_AMOUNT_UPGRADES; + public final ModConfigSpec.ConfigValue MAX_SPEED_UPGRADES; protected ServerConfig(ModConfigSpec.Builder builder) { - SELF_SACRIFICE_CONVERSION = builder.define("self_sacrifice_conversion", 100); - DEFAULT_UPGRADE_POINTS = builder.define("default_upgrade_points", 100); - EVOLUTION_UPGRADE_POINTS = builder.define("evolution_upgrade_points", 300); + builder.comment("Range: > 0 means between " + Integer.MAX_VALUE + " and 0 inclusive"); + SELF_SACRIFICE_CONVERSION = builder.defineInRange("self_sacrifice_conversion", 100, 0, Integer.MAX_VALUE); + SACRIFICE_CONVERSION = builder.defineInRange("sacrifice_conversion", 25, 0, Integer.MAX_VALUE); + DEFAULT_UPGRADE_POINTS = builder.defineInRange("default_upgrade_points", 100, 0, Integer.MAX_VALUE); + EVOLUTION_UPGRADE_POINTS = builder.defineInRange("evolution_upgrade_points", 300, 0, Integer.MAX_VALUE); + + BASE_ITEM_TRANSFER = builder.defineInRange("base_item_transfer", 16, 0, Integer.MAX_VALUE); + UPGRADE_ITEM_TRANSFER = builder.defineInRange("upgrade_item_transfer", 16, 0, Integer.MAX_VALUE); + + BASE_FLUID_TRANSFER = builder.defineInRange("base_fluid_transfer", 4000, 0, Integer.MAX_VALUE); + UPGRADE_FLUID_TRANSFER = builder.defineInRange("upgrade_fluid_transfer", 4000, 0, Integer.MAX_VALUE); + + MAX_AMOUNT_UPGRADES = builder.defineInRange("max_amount_upgrades", 9, 0, 64); + MAX_SPEED_UPGRADES = builder.defineInRange("max_speed_upgrades", 9, 0, 19); } } diff --git a/src/main/java/wayoftime/bloodmagic/client/event/ClientModEventHandler.java b/src/main/java/wayoftime/bloodmagic/client/event/ClientModEventHandler.java index ac9b77dd23..08e0044e3e 100644 --- a/src/main/java/wayoftime/bloodmagic/client/event/ClientModEventHandler.java +++ b/src/main/java/wayoftime/bloodmagic/client/event/ClientModEventHandler.java @@ -19,7 +19,7 @@ import wayoftime.bloodmagic.common.datacomponent.EnumWillType; import wayoftime.bloodmagic.common.item.BMItems; -@EventBusSubscriber(value = Dist.CLIENT, modid = BloodMagic.MODID, bus = EventBusSubscriber.Bus.MOD) +@EventBusSubscriber(value = Dist.CLIENT, modid = BloodMagic.MODID) public class ClientModEventHandler { @SubscribeEvent diff --git a/src/main/java/wayoftime/bloodmagic/client/render/blockentity/NodeRenderer.java b/src/main/java/wayoftime/bloodmagic/client/render/blockentity/NodeRenderer.java new file mode 100644 index 0000000000..02d135aab2 --- /dev/null +++ b/src/main/java/wayoftime/bloodmagic/client/render/blockentity/NodeRenderer.java @@ -0,0 +1,166 @@ +package wayoftime.bloodmagic.client.render.blockentity; + +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.blaze3d.vertex.VertexConsumer; +import com.mojang.math.Axis; +import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.client.renderer.RenderType; +import net.minecraft.client.renderer.blockentity.BlockEntityRenderer; +import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider; +import net.minecraft.client.renderer.texture.OverlayTexture; +import net.minecraft.core.BlockPos; +import net.minecraft.resources.ResourceLocation; +import wayoftime.bloodmagic.BloodMagic; +import wayoftime.bloodmagic.common.blockentity.RoutingNodeTile; + +public class NodeRenderer implements BlockEntityRenderer { + + public static final ResourceLocation DEFAULT = BloodMagic.rl("textures/block/crystal_default.png"); + public static final ResourceLocation CORROSIVE = BloodMagic.rl("textures/block/crystal_corrosive.png"); + public static final ResourceLocation DESTRUCTIVE = BloodMagic.rl("textures/block/crystal_destructive.png"); + public static final ResourceLocation STEADFAST = BloodMagic.rl("textures/block/crystal_steadfast.png"); + public static final ResourceLocation VENGEFUL = BloodMagic.rl("textures/block/crystal_vengeful.png"); + public NodeRenderer(BlockEntityRendererProvider.Context context) { + } + + public void render(RoutingNodeTile node, float partialTick, PoseStack poseStack, MultiBufferSource bufferSource, int packedLight, int packedOverlay) { + BlockPos parentPos = node.getParentPos(); + if (parentPos == BlockPos.ZERO) { + return; + } + + long gameTime = node.getLevel().getGameTime(); + float time = (float)Math.floorMod(gameTime, 40) + partialTick; + + BlockPos offsetPos = parentPos.subtract(node.getBlockPos()); + int xd = offsetPos.getX(); + int yd = offsetPos.getY(); + int zd = offsetPos.getZ(); + + double distance = Math.sqrt(xd * xd + yd * yd + zd * zd); + double subLength = Math.sqrt(xd * xd + zd * zd); + float rotYaw = -((float) (Math.atan2(xd, zd) * 180.0D / Math.PI)); + float rotPitch = ((float) (Math.atan2(yd, subLength) * 180.0D / Math.PI)); + + poseStack.pushPose(); + poseStack.translate(0.5f, 0.5f, 0.5f); + poseStack.mulPose(Axis.YP.rotationDegrees(-rotYaw)); + poseStack.mulPose(Axis.XN.rotationDegrees(rotPitch - 90)); + + renderBeaconBeam(poseStack, bufferSource, DEFAULT, time, (float) distance, 0.06f, 0.1f, node.hasMaster()); + } + + public static void renderBeaconBeam( + PoseStack poseStack, + MultiBufferSource bufferSource, + ResourceLocation beamLocation, + float time, + float height, + float beamRadius, + float glowRadius, + boolean isConnected + ) { + poseStack.pushPose(); + poseStack.translate(0.5, 0.5, 0.5); + poseStack.pushPose(); + poseStack.mulPose(Axis.YP.rotationDegrees(time * 2.25F - 45.0F)); + renderPart( + poseStack, + bufferSource.getBuffer(RenderType.beaconBeam(beamLocation, false)), + 0, + height, + 0.0F, + beamRadius, + beamRadius, + 0.0F, + -beamRadius, + 0.0F, + 0.0F, + -beamRadius, + isConnected + ); + poseStack.popPose(); + renderPart( + poseStack, + bufferSource.getBuffer(RenderType.beaconBeam(beamLocation, true)), + 0, + height, + -glowRadius, + -glowRadius, + glowRadius, + -glowRadius, + -glowRadius, + glowRadius, + glowRadius, + glowRadius, + isConnected + ); + poseStack.popPose(); + } + private static void renderPart( + PoseStack poseStack, + VertexConsumer consumer, + int minY, + float maxY, + float x1, + float z1, + float x2, + float z2, + float x3, + float z3, + float x4, + float z4, + boolean isConnected + ) { + PoseStack.Pose posestack$pose = poseStack.last(); + renderQuad( + posestack$pose, consumer, minY, maxY, x1, z1, x2, z2, isConnected + ); + renderQuad( + posestack$pose, consumer, minY, maxY, x4, z4, x3, z3, isConnected + ); + renderQuad( + posestack$pose, consumer, minY, maxY, x2, z2, x4, z4, isConnected + ); + renderQuad( + posestack$pose, consumer, minY, maxY, x3, z3, x1, z1, isConnected + ); + } + + private static void renderQuad( + PoseStack.Pose pose, + VertexConsumer consumer, + int minY, + float maxY, + float minX, + float minZ, + float maxX, + float maxZ, + boolean isConnected + ) { + float minU = 1/16.0f; + float maxU = 15/16.0f; + float minV = 1/16.0f; + float maxV = 15/16.0f; + addVertex(pose, consumer, maxY, minX, minZ, maxU, minV, isConnected); + addVertex(pose, consumer, minY, minX, minZ, maxU, maxV, isConnected); + addVertex(pose, consumer, minY, maxX, maxZ, minU, maxV, isConnected); + addVertex(pose, consumer, maxY, maxX, maxZ, minU, minV, isConnected); + } + + private static void addVertex( + PoseStack.Pose pose, VertexConsumer consumer, float y, float x, float z, float u, float v, boolean isConnected + ) { + consumer.addVertex(pose, x, y, z) + .setColor(isConnected ? 0xFFFFFF : 0x666666) + .setUv(u, v) + .setOverlay(OverlayTexture.NO_OVERLAY) + .setLight(15728880) + .setNormal(pose, 0.0F, 1.0F, 0.0F); + } + + @Override + public boolean shouldRenderOffScreen(RoutingNodeTile blockEntity) { + return true; + } +} diff --git a/src/main/java/wayoftime/bloodmagic/common/block/BMBlocks.java b/src/main/java/wayoftime/bloodmagic/common/block/BMBlocks.java index 4adced0806..210b91d1ee 100644 --- a/src/main/java/wayoftime/bloodmagic/common/block/BMBlocks.java +++ b/src/main/java/wayoftime/bloodmagic/common/block/BMBlocks.java @@ -1,6 +1,7 @@ package wayoftime.bloodmagic.common.block; import net.minecraft.ChatFormatting; +import net.minecraft.core.BlockPos; import net.minecraft.core.component.DataComponentType; import net.minecraft.core.component.DataComponents; import net.minecraft.world.item.BlockItem; @@ -8,10 +9,15 @@ import net.minecraft.world.item.component.ItemLore; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.SoundType; +import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.state.BlockBehaviour; +import net.minecraft.world.level.block.state.BlockState; import net.neoforged.bus.api.IEventBus; import net.neoforged.neoforge.registries.DeferredRegister; +import org.jetbrains.annotations.Nullable; import wayoftime.bloodmagic.BloodMagic; +import wayoftime.bloodmagic.common.blockentity.BMTiles; +import wayoftime.bloodmagic.common.blockentity.FilterNodeTile; import wayoftime.bloodmagic.common.datacomponent.BMDataComponents; import wayoftime.bloodmagic.util.helper.BlockEntityHelper; import wayoftime.bloodmagic.util.helper.BlockWithItemHolder; @@ -34,6 +40,11 @@ public class BMBlocks { public static final BlockWithItemHolder HELLFIRE_FORGE = BLOCK_REG.register("hellfire_forge", HellfireForgeBlock::new); public static final BlockWithItemHolder ARC_BLOCK = BLOCK_REG.register("arc", ARCBlock::new); + public static final BlockWithItemHolder MASTER_NODE = BLOCK_REG.register("routing_node_master", MasterNodeBlock::new); + public static final BlockWithItemHolder ROUTING_NODE = BLOCK_REG.register("routing_node", RoutingNodeBlock::new); + public static final BlockWithItemHolder INPUT_ROUTING_NODE = BLOCK_REG.register("routing_node_input", () -> new FilterNodeBlock(false)); + public static final BlockWithItemHolder OUTPUT_ROUTING_NODE = BLOCK_REG.register("routing_node_output", () -> new FilterNodeBlock(true)); + // TODO add model/textures for this and change registry to BASIC_REG public static final BlockWithItemHolder LIVING_STATION = BLOCK_REG.register("living_station", LivingStationBlock::new); diff --git a/src/main/java/wayoftime/bloodmagic/common/block/FilterNodeBlock.java b/src/main/java/wayoftime/bloodmagic/common/block/FilterNodeBlock.java new file mode 100644 index 0000000000..40ef3b3e70 --- /dev/null +++ b/src/main/java/wayoftime/bloodmagic/common/block/FilterNodeBlock.java @@ -0,0 +1,21 @@ +package wayoftime.bloodmagic.common.block; + +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.state.BlockState; +import org.jetbrains.annotations.Nullable; +import wayoftime.bloodmagic.common.blockentity.FilterNodeTile; + +public class FilterNodeBlock extends RoutingNodeBlock { + + private final boolean isOutput; + public FilterNodeBlock(boolean isOutput) { + super(); + this.isOutput = isOutput; + } + + @Override + public @Nullable BlockEntity newBlockEntity(BlockPos pos, BlockState state) { + return new FilterNodeTile(pos, state, isOutput); + } +} diff --git a/src/main/java/wayoftime/bloodmagic/common/block/MasterNodeBlock.java b/src/main/java/wayoftime/bloodmagic/common/block/MasterNodeBlock.java new file mode 100644 index 0000000000..564738ac1d --- /dev/null +++ b/src/main/java/wayoftime/bloodmagic/common/block/MasterNodeBlock.java @@ -0,0 +1,18 @@ +package wayoftime.bloodmagic.common.block; + +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.state.BlockState; +import org.jetbrains.annotations.Nullable; +import wayoftime.bloodmagic.common.blockentity.MasterNodeTile; + +public class MasterNodeBlock extends RoutingNodeBlock { + public MasterNodeBlock() { + super(); + } + + @Override + public @Nullable BlockEntity newBlockEntity(BlockPos pos, BlockState state) { + return new MasterNodeTile(pos, state); + } +} diff --git a/src/main/java/wayoftime/bloodmagic/common/block/RoutingNodeBlock.java b/src/main/java/wayoftime/bloodmagic/common/block/RoutingNodeBlock.java new file mode 100644 index 0000000000..14dd234d0b --- /dev/null +++ b/src/main/java/wayoftime/bloodmagic/common/block/RoutingNodeBlock.java @@ -0,0 +1,128 @@ +package wayoftime.bloodmagic.common.block; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.world.item.context.BlockPlaceContext; +import net.minecraft.world.level.BlockGetter; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.LevelAccessor; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.EntityBlock; +import net.minecraft.world.level.block.RenderShape; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.block.state.StateDefinition; +import net.minecraft.world.level.block.state.properties.BlockStateProperties; +import net.minecraft.world.level.block.state.properties.BooleanProperty; +import net.minecraft.world.level.material.PushReaction; +import net.minecraft.world.phys.shapes.CollisionContext; +import net.minecraft.world.phys.shapes.VoxelShape; +import org.jetbrains.annotations.Nullable; +import wayoftime.bloodmagic.common.blockentity.BMTiles; +import wayoftime.bloodmagic.common.blockentity.RoutingNodeTile; + +public class RoutingNodeBlock extends Block implements EntityBlock { + public static final BooleanProperty ENABLED = BlockStateProperties.ENABLED; + public static final BooleanProperty DOWN = BlockStateProperties.DOWN; + public static final BooleanProperty UP = BlockStateProperties.UP; + public static final BooleanProperty NORTH = BlockStateProperties.NORTH; + public static final BooleanProperty SOUTH = BlockStateProperties.SOUTH; + public static final BooleanProperty WEST = BlockStateProperties.WEST; + public static final BooleanProperty EAST = BlockStateProperties.EAST; + + public static final VoxelShape SHAPE = Block.box(6, 6, 6, 10, 10, 10); + + public RoutingNodeBlock() { + super( + Properties.of() + .strength(2, 5) + .requiresCorrectToolForDrops() + .forceSolidOn() // not washed away by water + .dynamicShape() // not sure needed, but it should update its connections + .noOcclusion() // dont cull blocks + .pushReaction(PushReaction.BLOCK) // dont move, even if moving BEs is allowed + ); + + this.registerDefaultState( + this.getStateDefinition().any() + .setValue(ENABLED, true) + .setValue(DOWN, false) + .setValue(UP, false) + .setValue(NORTH, false) + .setValue(SOUTH, false) + .setValue(WEST, false) + .setValue(EAST, false) + ); + } + + @Override + protected void neighborChanged(BlockState state, Level level, BlockPos pos, Block neighborBlock, BlockPos neighborPos, boolean movedByPiston) { + // adapted from HopperBlock + boolean enabled = !level.hasNeighborSignal(pos); + if (enabled != state.getValue(ENABLED)) { + level.setBlock(pos, state.setValue(ENABLED, enabled), 2); + } + } + + @Override + public @Nullable BlockState getStateForPlacement(BlockPlaceContext context) { + Level level = context.getLevel(); + BlockPos blockpos = context.getClickedPos(); + BlockState returnState = defaultBlockState(); + returnState = returnState.setValue(ENABLED, !level.hasNeighborSignal(blockpos)); + + for (Direction dir : Direction.values()) + { + BlockPos attachedPos = blockpos.relative(dir); + BlockState attachedState = level.getBlockState(attachedPos); + BooleanProperty prop = switch (dir) { + case DOWN -> DOWN; + case EAST -> EAST; + case NORTH -> NORTH; + case SOUTH -> SOUTH; + case UP -> UP; + case WEST -> WEST; + }; + returnState = returnState.setValue(prop, attachedState.isFaceSturdy(level, attachedPos, dir.getOpposite())); + } + + return returnState; + } + + @Override + protected BlockState updateShape(BlockState state, Direction dir, BlockState neighborState, LevelAccessor level, BlockPos pos, BlockPos neighborPos) { + BlockPos attachedPos = pos.relative(dir); + BlockState attachedState = level.getBlockState(attachedPos); + BooleanProperty prop = switch (dir) { + case DOWN -> DOWN; + case EAST -> EAST; + case NORTH -> NORTH; + case SOUTH -> SOUTH; + case UP -> UP; + case WEST -> WEST; + }; + state = state.setValue(prop, attachedState.isFaceSturdy(level, attachedPos, dir.getOpposite())); + + return state; + } + + @Override + protected RenderShape getRenderShape(BlockState state) { + return RenderShape.MODEL; + } + + @Override + protected VoxelShape getShape(BlockState state, BlockGetter level, BlockPos pos, CollisionContext context) { + return SHAPE; + } + + @Override + protected void createBlockStateDefinition(StateDefinition.Builder builder) { + builder.add(ENABLED, DOWN, UP, NORTH, SOUTH, WEST, EAST); + } + + @Override + public @Nullable BlockEntity newBlockEntity(BlockPos pos, BlockState state) { + return new RoutingNodeTile(BMTiles.ROUTING_NODE.get(), pos, state); + } +} diff --git a/src/main/java/wayoftime/bloodmagic/common/blockentity/BMTiles.java b/src/main/java/wayoftime/bloodmagic/common/blockentity/BMTiles.java index 3e2e8ed8fc..56b87c3098 100644 --- a/src/main/java/wayoftime/bloodmagic/common/blockentity/BMTiles.java +++ b/src/main/java/wayoftime/bloodmagic/common/blockentity/BMTiles.java @@ -2,6 +2,7 @@ import net.minecraft.core.Direction; import net.minecraft.core.registries.BuiltInRegistries; +import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.entity.BlockEntityType; import net.neoforged.bus.api.IEventBus; import net.neoforged.neoforge.capabilities.Capabilities; @@ -14,6 +15,7 @@ import wayoftime.bloodmagic.client.render.blockentity.BloodAltarRenderer; import wayoftime.bloodmagic.client.render.blockentity.BloodTankRenderer; import wayoftime.bloodmagic.client.render.blockentity.HellfireForgeRenderer; +import wayoftime.bloodmagic.client.render.blockentity.NodeRenderer; import wayoftime.bloodmagic.common.block.BMBlocks; import java.util.Set; @@ -36,6 +38,15 @@ public class BMTiles { public static final DeferredHolder, BlockEntityType> LIVING_STATION_TYPE = TILES.register("living_station", () -> new BlockEntityType<>(LivingStationTile::new, Set.of(BMBlocks.LIVING_STATION.block().get()), null)); + public static final DeferredHolder, BlockEntityType> ROUTING_NODE = TILES.register("routing_node", + () -> new BlockEntityType<>(RoutingNodeTile::new, Set.of(BMBlocks.ROUTING_NODE.block().get()), null)); + + public static final DeferredHolder, BlockEntityType> FILTER_ROUTING_NODE = TILES.register("filter_routing_node", + () -> new BlockEntityType<>(FilterNodeTile::new, Set.of(BMBlocks.INPUT_ROUTING_NODE.block().get(), BMBlocks.OUTPUT_ROUTING_NODE.block().get()), null)); + + public static final DeferredHolder, BlockEntityType> MASTER_ROUTING_NODE = TILES.register("master_routing_node", + () -> new BlockEntityType<>(MasterNodeTile::new, Set.of(BMBlocks.MASTER_NODE.block().get()), null)); + private static void registerTileCapabilities(RegisterCapabilitiesEvent event) { event.registerBlockEntity( Capabilities.ItemHandler.BLOCK, @@ -86,6 +97,8 @@ private static void registerBlockEntityRenderer(EntityRenderersEvent.RegisterRen event.registerBlockEntityRenderer(HELLFIRE_FORGE_TYPE.get(), HellfireForgeRenderer::new); event.registerBlockEntityRenderer(BLOOD_ALTAR_TYPE.get(), BloodAltarRenderer::new); event.registerBlockEntityRenderer(BLOOD_TANK_TYPE.get(), BloodTankRenderer::new); + event.registerBlockEntityRenderer(ROUTING_NODE.get(), NodeRenderer::new); + event.registerBlockEntityRenderer(FILTER_ROUTING_NODE.get(), NodeRenderer::new); } public static void register(IEventBus modBus) { diff --git a/src/main/java/wayoftime/bloodmagic/common/blockentity/FilterNodeTile.java b/src/main/java/wayoftime/bloodmagic/common/blockentity/FilterNodeTile.java index eb7e321e7d..a0df73a1b1 100644 --- a/src/main/java/wayoftime/bloodmagic/common/blockentity/FilterNodeTile.java +++ b/src/main/java/wayoftime/bloodmagic/common/blockentity/FilterNodeTile.java @@ -3,30 +3,50 @@ import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.network.chat.Component; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.server.level.ServerLevel; import net.minecraft.world.MenuProvider; import net.minecraft.world.entity.player.Inventory; import net.minecraft.world.entity.player.Player; import net.minecraft.world.inventory.AbstractContainerMenu; +import net.minecraft.world.inventory.SimpleContainerData; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.state.BlockState; +import net.neoforged.neoforge.capabilities.BlockCapabilityCache; +import net.neoforged.neoforge.capabilities.Capabilities; +import net.neoforged.neoforge.fluids.capability.IFluidHandler; +import net.neoforged.neoforge.items.IItemHandler; import net.neoforged.neoforge.items.ItemStackHandler; import org.jetbrains.annotations.Nullable; -import wayoftime.bloodmagic.common.datacomponent.BMDataComponents; -import wayoftime.bloodmagic.common.routing.IFluidFilter; -import wayoftime.bloodmagic.common.routing.IItemFilter; +import wayoftime.bloodmagic.BloodMagic; +import wayoftime.bloodmagic.common.block.RoutingNodeBlock; +import wayoftime.bloodmagic.common.capability.BMCaps; +import wayoftime.bloodmagic.common.routing.IRoutingFilter; +import wayoftime.bloodmagic.common.routing.NodeContext; -import java.util.EnumMap; +import java.util.*; +import java.util.function.BiConsumer; public class FilterNodeTile extends RoutingNodeTile implements MenuProvider { + public static final int MAX_PRIO = 10; private final boolean isOutput; public FilterNodeTile(BlockPos pos, BlockState blockState, boolean isOutput) { - super(BMTiles.FILTER_NODE.get(), pos, blockState); + super(BMTiles.FILTER_ROUTING_NODE.get(), pos, blockState); this.isOutput = isOutput; } + public FilterNodeTile(BlockPos pos, BlockState state) { + this(pos, state, false); + } + + private Map> itemCapCache = new HashMap<>(); + private Map> fluidCapCache = new HashMap<>(); + + public final SimpleContainerData priorities = new SimpleContainerData(6); + public final ItemStackHandler filterInv = new ItemStackHandler(6) { @Override public int getSlotLimit(int slot) { @@ -35,71 +55,39 @@ public int getSlotLimit(int slot) { @Override public boolean isItemValid(int slot, ItemStack stack) { - return stack.has(BMDataComponents.filter_data); + return stack.getCapability(BMCaps.ROUTING_FILTER_PROVIDER, NodeContext.EMPTY) != null; } @Override protected void onContentsChanged(int slot) { setChanged(); level.sendBlockUpdated(getBlockPos(), getBlockState(), getBlockState(), Block.UPDATE_ALL); - sendFilterInfo(); } }; - @Override - public void masterCheckinRequest() { - super.masterCheckinRequest(); - sendFilterInfo(); - } - @Override - public void setActive(boolean newState) { - if (isActive != newState) { - BlockEntity be = level.getBlockEntity(masterPos); - if (be instanceof MasterNodeTile master) { - if (newState) { - sendFilterInfo(); - } else { - master.removeNodeInfo(getBlockPos()); - } - } + public void propagateNetwork(BiConsumer> collector, boolean requireEnabled) { + if (requireEnabled && !getBlockState().getValue(RoutingNodeBlock.ENABLED)) { + return; } - super.setActive(newState); - } - @Override - public void setMasterPos(BlockPos masterPos) { - super.setMasterPos(masterPos); - sendFilterInfo(); - } + collector.accept(getBlockPos(), Optional.of(isOutput)); - protected void sendFilterInfo() { - BlockEntity be = level.getBlockEntity(masterPos); - if (be instanceof MasterNodeTile master) { - master.addPriorityInfo(getBlockPos(), getPriorityMap()); - if (isOutput) { - master.addItemOutputFilterInfo(getBlockPos(), getItemFilters()); - master.addFluidOutputFilterInfo(getBlockPos(), getFluidFilters()); - } else { - master.addItemInputFilterInfo(getBlockPos(), getItemFilters()); - master.addFluidInputFilterInfo(getBlockPos(), getFluidFilters()); + for (BlockPos pos : children) { + if (level.getBlockEntity(pos) instanceof RoutingNodeTile node) { + node.propagateNetwork(collector, requireEnabled); } } } - protected EnumMap getPriorityMap() { - - } - - protected EnumMap getItemFilters() {} - - protected EnumMap getFluidFilters() {} - + // TODO not return null for both below @Override public Component getDisplayName() { + return null; } @Override public @Nullable AbstractContainerMenu createMenu(int containerId, Inventory playerInventory, Player player) { + return null; } } diff --git a/src/main/java/wayoftime/bloodmagic/common/blockentity/MasterNodeTile.java b/src/main/java/wayoftime/bloodmagic/common/blockentity/MasterNodeTile.java index 957863ef00..5047ecff09 100644 --- a/src/main/java/wayoftime/bloodmagic/common/blockentity/MasterNodeTile.java +++ b/src/main/java/wayoftime/bloodmagic/common/blockentity/MasterNodeTile.java @@ -1,73 +1,103 @@ package wayoftime.bloodmagic.common.blockentity; +import com.mojang.datafixers.util.Pair; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; +import net.minecraft.core.HolderLookup; +import net.minecraft.nbt.CompoundTag; import net.minecraft.network.chat.Component; +import net.minecraft.resources.ResourceLocation; import net.minecraft.world.MenuProvider; import net.minecraft.world.entity.player.Inventory; import net.minecraft.world.entity.player.Player; import net.minecraft.world.inventory.AbstractContainerMenu; +import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.state.BlockState; +import net.neoforged.neoforge.items.ItemStackHandler; import org.jetbrains.annotations.Nullable; -import wayoftime.bloodmagic.common.routing.IFluidFilter; -import wayoftime.bloodmagic.common.routing.IItemFilter; +import wayoftime.bloodmagic.BloodMagic; +import wayoftime.bloodmagic.common.block.BMBlocks; +import wayoftime.bloodmagic.common.routing.IRoutingFilter; -import java.util.EnumMap; -import java.util.HashMap; -import java.util.Map; +import java.util.*; public class MasterNodeTile extends RoutingNodeTile implements MenuProvider { public MasterNodeTile(BlockPos pos, BlockState blockState) { - super(BMTiles.MASTER_NODE.get(), pos, blockState); + super(BMTiles.MASTER_ROUTING_NODE.get(), pos, blockState); } + public ItemStackHandler upgradeInv = new ItemStackHandler(2) { + @Override + public int getSlotLimit(int slot) { + return switch (slot) { + case 0 -> BloodMagic.SERVER_CONFIG.MAX_AMOUNT_UPGRADES.get(); + case 1 -> BloodMagic.SERVER_CONFIG.MAX_SPEED_UPGRADES.get(); + default -> 0; + }; + } + + @Override + public boolean isItemValid(int slot, ItemStack stack) { + return switch (slot) { + // TODO replace with the actual upgrades after adding them + case 0 -> stack.is(BMBlocks.RUNE_CAPACITY.item()); + case 1 -> stack.is(BMBlocks.RUNE_ACCELERATION.item()); + default -> false; + }; + } + + @Override + protected void onContentsChanged(int slot) { + setChanged(); + level.sendBlockUpdated(getBlockPos(), getBlockState(), getBlockState(), Block.UPDATE_ALL); + } + }; + + public int ticks = 0; + private Set outputNodes; + private Set inputNodes; public static void tick(Level level, BlockPos pos, BlockState state, MasterNodeTile node) { + if (level.isClientSide) { + return; + } - } + if (node.inputNodes == null || node.outputNodes == null) { - private Map> inputItemFilterMap = new HashMap<>(); - private Map> outputItemFilterMap = new HashMap<>(); - public void addItemInputFilterInfo(BlockPos pos, EnumMap filters) { - inputItemFilterMap.put(pos, filters); - setChanged(); - } + } - public void addItemOutputFilterInfo(BlockPos pos, EnumMap filters) { - outputItemFilterMap.put(pos, filters); - setChanged(); - } + if (node.ticks % Math.min(1, 20 - node.upgradeInv.getStackInSlot(1).getCount()) != 0) { + return; + } - private Map> inputFluidFilterMap = new HashMap<>(); - private Map> outputFluidFilterMap = new HashMap<>(); - public void addFluidInputFilterInfo(BlockPos pos, EnumMap filters) { - inputFluidFilterMap.put(pos, filters); - setChanged(); } - public void addFluidOutputFilterInfo(BlockPos pos, EnumMap filters) { - outputFluidFilterMap.put(pos, filters); - setChanged(); + public void markNodeDirty(BlockPos nodePos) { + } - private Map> priorityMap = new HashMap<>(); - public void addPriorityInfo(BlockPos pos, EnumMap priority) { - priorityMap.put(pos, priority); + @Override + protected void loadAdditional(CompoundTag tag, HolderLookup.Provider registries) { + super.loadAdditional(tag, registries); + ticks = tag.getInt("ticks"); } - public void removeNodeInfo(BlockPos pos) { - inputItemFilterMap.remove(pos); - outputItemFilterMap.remove(pos); - inputFluidFilterMap.remove(pos); - outputFluidFilterMap.remove(pos); + @Override + protected void saveAdditional(CompoundTag tag, HolderLookup.Provider registries) { + super.saveAdditional(tag, registries); + tag.putInt("ticks", ticks % 20); } + // TODO fix these two @Override public Component getDisplayName() { + return null; } @Override public @Nullable AbstractContainerMenu createMenu(int containerId, Inventory playerInventory, Player player) { + return null; } } diff --git a/src/main/java/wayoftime/bloodmagic/common/blockentity/RoutingNodeTile.java b/src/main/java/wayoftime/bloodmagic/common/blockentity/RoutingNodeTile.java index c4e5f4aea3..09a5e3b889 100644 --- a/src/main/java/wayoftime/bloodmagic/common/blockentity/RoutingNodeTile.java +++ b/src/main/java/wayoftime/bloodmagic/common/blockentity/RoutingNodeTile.java @@ -9,66 +9,41 @@ import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.entity.BlockEntityType; import net.minecraft.world.level.block.state.BlockState; +import wayoftime.bloodmagic.common.block.RoutingNodeBlock; import java.util.HashSet; +import java.util.Optional; import java.util.Set; +import java.util.function.BiConsumer; +import java.util.function.Consumer; public class RoutingNodeTile extends BaseTile { + // somebody please think of the children public RoutingNodeTile(BlockEntityType type, BlockPos pos, BlockState blockState) { super(type, pos, blockState); } - protected BlockPos masterPos = BlockPos.ZERO; // TODO 0, 0, 0 is NOT an invalid coordinate (at least not in every DIM) and putting a master node there WILL make it NOT work - protected BlockPos parentPos = BlockPos.ZERO; // same thing here - protected Set children = new HashSet<>(); - protected boolean isActive = true; - - public static void tick(Level level, BlockPos pos, BlockState state, T node) { - // TODO might want to do something to prevent fast clocks from permanently dis- and re-enabling half the network. not that you *should* have one next to your network but it might cause some lag - int signal = level.getBestNeighborSignal(pos); - node.setActive(signal == 0); - - if (node.parentPos != BlockPos.ZERO) { - BlockEntity be = node.level.getBlockEntity(node.parentPos); - if (!(be instanceof RoutingNodeTile)) { - node.removeFromNetwork(); - } - } + public RoutingNodeTile(BlockPos pos, BlockState state) { + super(BMTiles.ROUTING_NODE.get(), pos, state); } - // when master node wants to (re)evaluate the network. - // general nodes dont need to do anything here except pass it on, filter nodes will have to resend their filter config - public void masterCheckinRequest() { - children.forEach(child -> { - BlockEntity be = this.level.getBlockEntity(child); - if (be instanceof RoutingNodeTile node) { - node.masterCheckinRequest(); - } else { // you in da wrong neighbourhood dawg - children.remove(child); - } - }); - } + protected BlockPos masterPos = BlockPos.ZERO; + protected BlockPos parentPos = BlockPos.ZERO; + protected Set children = new HashSet<>(); - public void setActive(boolean newState) { - if (this.isActive == newState) { - return; // no change, done + public void propagateNetwork(BiConsumer> collector, boolean requireEnabled) { + if (requireEnabled && !getBlockState().getValue(RoutingNodeBlock.ENABLED)) { + return; } - this.isActive = newState; - this.setChanged(); - this.level.sendBlockUpdated(getBlockPos(), getBlockState(), getBlockState(), Block.UPDATE_ALL); // send block update for sync so client knows and can render lines appropriately - children.forEach(child -> { - BlockEntity be = this.level.getBlockEntity(child); - if (be instanceof RoutingNodeTile node) { - node.setActive(newState); - } - }); - // TODO filter nodes should update the master node with their filter info from here - } + collector.accept(getBlockPos(), Optional.empty()); - public boolean isActive() { - return isActive; + for (BlockPos pos : children) { + if (level.getBlockEntity(pos) instanceof RoutingNodeTile node) { + node.propagateNetwork(collector, requireEnabled); + } + } } public void setParent(BlockPos parent) { @@ -92,6 +67,7 @@ public void addConnection(BlockPos child) { } public void removeConnection(BlockPos child) { + this.parentPos = BlockPos.ZERO; children.remove(child); BlockEntity be = this.level.getBlockEntity(child); if (be instanceof RoutingNodeTile node) { @@ -102,7 +78,6 @@ public void removeConnection(BlockPos child) { } public void removeFromNetwork() { - this.parentPos = BlockPos.ZERO; this.masterPos = BlockPos.ZERO; // TODO filtering nodes should remove their info from master here @@ -134,7 +109,6 @@ public void setMasterPos(BlockPos masterPos) { protected void saveAdditional(CompoundTag tag, HolderLookup.Provider registries) { super.saveAdditional(tag, registries); CompoundTag nodeInfo = new CompoundTag(); - nodeInfo.putBoolean("active", isActive); nodeInfo.put("master", posToTag(masterPos)); ListTag childTag = new ListTag(); children.forEach(pos -> childTag.add(posToTag(pos))); @@ -146,7 +120,6 @@ protected void saveAdditional(CompoundTag tag, HolderLookup.Provider registries) protected void loadAdditional(CompoundTag tag, HolderLookup.Provider registries) { super.loadAdditional(tag, registries); CompoundTag nodeInfo = tag.getCompound("node_info"); - this.isActive = nodeInfo.getBoolean("active"); masterPos = tagToPos(tag.getCompound("master")); ListTag childrenTag = nodeInfo.getList("children", ListTag.TAG_COMPOUND); children.clear(); // just to be sure theres no weird overflow happening @@ -155,13 +128,18 @@ protected void loadAdditional(CompoundTag tag, HolderLookup.Provider registries) protected CompoundTag posToTag(BlockPos pos) { CompoundTag tag = new CompoundTag(); - tag.putInt("x", pos.getX()); - tag.putInt("y", pos.getY()); - tag.putInt("z", pos.getZ()); + if (pos != BlockPos.ZERO) { + tag.putInt("x", pos.getX()); + tag.putInt("y", pos.getY()); + tag.putInt("z", pos.getZ()); + } return tag; } protected BlockPos tagToPos(CompoundTag tag) { - return new BlockPos(tag.getInt("x"), tag.getInt("y"), tag.getInt("z")); + if (tag.contains("x") && tag.contains("y") && tag.contains("z")) { + return new BlockPos(tag.getInt("x"), tag.getInt("y"), tag.getInt("z")); + } + return BlockPos.ZERO; } } diff --git a/src/main/java/wayoftime/bloodmagic/common/capability/BMCaps.java b/src/main/java/wayoftime/bloodmagic/common/capability/BMCaps.java new file mode 100644 index 0000000000..e5b83a19ec --- /dev/null +++ b/src/main/java/wayoftime/bloodmagic/common/capability/BMCaps.java @@ -0,0 +1,15 @@ +package wayoftime.bloodmagic.common.capability; + +import net.neoforged.neoforge.capabilities.ItemCapability; +import wayoftime.bloodmagic.BloodMagic; +import wayoftime.bloodmagic.common.routing.IRoutingFilter; +import wayoftime.bloodmagic.common.routing.NodeContext; + +public class BMCaps { + // TODO does it matter that its IRF instead of IRF here? like both permit any (afaik) but specifying it makes IC#create complain + public static final ItemCapability ROUTING_FILTER_PROVIDER = ItemCapability.create( + BloodMagic.rl("routing_filter_provider"), + IRoutingFilter.class, + NodeContext.class + ); +} diff --git a/src/main/java/wayoftime/bloodmagic/common/datacomponent/BMDataComponents.java b/src/main/java/wayoftime/bloodmagic/common/datacomponent/BMDataComponents.java index 9ea3d68560..4bf9583d05 100644 --- a/src/main/java/wayoftime/bloodmagic/common/datacomponent/BMDataComponents.java +++ b/src/main/java/wayoftime/bloodmagic/common/datacomponent/BMDataComponents.java @@ -32,6 +32,8 @@ public class BMDataComponents { public static final DeferredHolder, DataComponentType> ARC_CHANCE = DATA_COMPONENTS.registerComponentType("arc_chance", builder -> builder.persistent(Codec.DOUBLE)); public static final DeferredHolder, DataComponentType> ARC_SPEED = DATA_COMPONENTS.registerComponentType("arc_speed", builder -> builder.persistent(Codec.DOUBLE)); + public static final DeferredHolder, DataComponentType> + public static final DeferredHolder, DataComponentType> CONTAINER_TIER = DATA_COMPONENTS.registerComponentType("container_tier", builder -> builder.persistent(Codec.INT).networkSynchronized(ByteBufCodecs.INT)); public static final DeferredHolder, DataComponentType> FLUID_CONTENT = DATA_COMPONENTS.registerComponentType("fluid_content", builder -> builder.persistent(SimpleFluidContent.CODEC).networkSynchronized(SimpleFluidContent.STREAM_CODEC)); public static final DeferredHolder, DataComponentType> ENERGY_CONTENT = DATA_COMPONENTS.registerComponentType("energy_content", builder -> builder.persistent(Codec.INT).networkSynchronized(ByteBufCodecs.INT)); diff --git a/src/main/java/wayoftime/bloodmagic/common/event/CommonEventHandler.java b/src/main/java/wayoftime/bloodmagic/common/event/CommonEventHandler.java index 8d6ce02de9..b0de99fbf2 100644 --- a/src/main/java/wayoftime/bloodmagic/common/event/CommonEventHandler.java +++ b/src/main/java/wayoftime/bloodmagic/common/event/CommonEventHandler.java @@ -32,7 +32,6 @@ public static void onInteract(PlayerInteractEvent.RightClickItem event) { Binding binding = held.get(BMDataComponents.BINDING); if (binding == null) { - BloodMagic.LOGGER.info("binding was null"); return; } BloodMagic.LOGGER.info("binding: {}:{}", binding.name(), binding.uuid()); diff --git a/src/main/java/wayoftime/bloodmagic/common/item/BMItems.java b/src/main/java/wayoftime/bloodmagic/common/item/BMItems.java index 3ccf4b7d86..99410eec10 100644 --- a/src/main/java/wayoftime/bloodmagic/common/item/BMItems.java +++ b/src/main/java/wayoftime/bloodmagic/common/item/BMItems.java @@ -35,6 +35,8 @@ public class BMItems { public static final DeferredHolder ORB_ARCHMAGE = BASIC_ITEMS.register("blood_orb_archmage", BloodOrbItem::new); public static final DeferredHolder ORB_TRANSCENDENT = BASIC_ITEMS.register("blood_orb_transcendent", BloodOrbItem::new); + public static final DeferredHolder NODE_ROUTER = BASIC_ITEMS.register("node_router", NodeRouterItem::new); + private static Supplier makeLivingArmour(ArmorItem.Type type) { return () -> new ArmorItem(BMMaterialsAndTiers.LIVING_ARMOUR_MATERIAL, type, new Item.Properties().durability(type.getDurability(33))); } diff --git a/src/main/java/wayoftime/bloodmagic/common/item/LivingArmourItem.java b/src/main/java/wayoftime/bloodmagic/common/item/LivingArmourItem.java index c94b0d19b0..4aeba1fd71 100644 --- a/src/main/java/wayoftime/bloodmagic/common/item/LivingArmourItem.java +++ b/src/main/java/wayoftime/bloodmagic/common/item/LivingArmourItem.java @@ -14,6 +14,6 @@ public LivingArmourItem() { .durability(Type.CHESTPLATE.getDurability(33)) .component(BMDataComponents.REQUIRED_SET, BMTags.Items.LIVING_SET) .component(BMDataComponents.CURRENT_UPGRADE_POINTS, 0) - ); + ); } } diff --git a/src/main/java/wayoftime/bloodmagic/common/item/NodeRouterItem.java b/src/main/java/wayoftime/bloodmagic/common/item/NodeRouterItem.java new file mode 100644 index 0000000000..65dd1cbef8 --- /dev/null +++ b/src/main/java/wayoftime/bloodmagic/common/item/NodeRouterItem.java @@ -0,0 +1,21 @@ +package wayoftime.bloodmagic.common.item; + +import net.minecraft.world.InteractionResult; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.context.UseOnContext; +import wayoftime.bloodmagic.common.datacomponent.BMDataComponents; + +public class NodeRouterItem extends Item { + + public NodeRouterItem() { + super( + new Properties().stacksTo(1) + .component(BMDataComponents.) + ); + } + + @Override + public InteractionResult useOn(UseOnContext context) { + + } +} diff --git a/src/main/java/wayoftime/bloodmagic/common/routing/IFluidFilter.java b/src/main/java/wayoftime/bloodmagic/common/routing/IFluidFilter.java deleted file mode 100644 index 5a1553ff2e..0000000000 --- a/src/main/java/wayoftime/bloodmagic/common/routing/IFluidFilter.java +++ /dev/null @@ -1,6 +0,0 @@ -package wayoftime.bloodmagic.common.routing; - -import net.neoforged.neoforge.fluids.FluidStack; - -public interface IFluidFilter extends IRoutingFilter { -} diff --git a/src/main/java/wayoftime/bloodmagic/common/routing/IItemFilter.java b/src/main/java/wayoftime/bloodmagic/common/routing/IItemFilter.java deleted file mode 100644 index 043d678230..0000000000 --- a/src/main/java/wayoftime/bloodmagic/common/routing/IItemFilter.java +++ /dev/null @@ -1,6 +0,0 @@ -package wayoftime.bloodmagic.common.routing; - -import net.minecraft.world.item.ItemStack; - -public interface IItemFilter extends IRoutingFilter { -} diff --git a/src/main/java/wayoftime/bloodmagic/common/routing/IRoutingFilter.java b/src/main/java/wayoftime/bloodmagic/common/routing/IRoutingFilter.java index 08a0cc9bb7..606ef0b2db 100644 --- a/src/main/java/wayoftime/bloodmagic/common/routing/IRoutingFilter.java +++ b/src/main/java/wayoftime/bloodmagic/common/routing/IRoutingFilter.java @@ -2,6 +2,7 @@ import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; +import net.minecraft.resources.ResourceLocation; import java.util.List; @@ -9,13 +10,9 @@ public interface IRoutingFilter { void initializeFilter(List> matchList, BlockPos target, Direction interactionSide, boolean isOutput); + ResourceLocation getTransferType(); + T transferThroughOutputFilter(T resource); int transferThroughInputFilter(IRoutingFilter outputFilter, int maxTransfer); - - boolean doesResourcePassFilter(T resource); - - boolean doesResourceMatch(IResourceMatcher matcher, T resource); - - List> getMatchList(); } diff --git a/src/main/java/wayoftime/bloodmagic/common/routing/NodeContext.java b/src/main/java/wayoftime/bloodmagic/common/routing/NodeContext.java new file mode 100644 index 0000000000..75dd176052 --- /dev/null +++ b/src/main/java/wayoftime/bloodmagic/common/routing/NodeContext.java @@ -0,0 +1,15 @@ +package wayoftime.bloodmagic.common.routing; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; + +public record NodeContext(BlockPos targetPos, Direction accessSide, FilterOperation op) { + + public static final NodeContext EMPTY = new NodeContext(BlockPos.ZERO, Direction.DOWN, FilterOperation.CAP_TEST); + + public enum FilterOperation { + INPUT, + OUTPUT, + CAP_TEST + } +} diff --git a/src/main/java/wayoftime/bloodmagic/util/helper/RenderHelper.java b/src/main/java/wayoftime/bloodmagic/util/helper/RenderHelper.java index ef6b6a596c..ba55893254 100644 --- a/src/main/java/wayoftime/bloodmagic/util/helper/RenderHelper.java +++ b/src/main/java/wayoftime/bloodmagic/util/helper/RenderHelper.java @@ -26,7 +26,7 @@ public static void addVertex ( VertexConsumer buf, Matrix4f matrix, float x, float y, float z, float u, float v, int colour, int light, int overlay, Vector3f norm ){ buf.addVertex(matrix, x, y, z) - .setColor(red(colour), green(colour), blue(colour), alpha(colour)) + .setColor(colour) .setUv(u, v) .setOverlay(overlay) .setLight(light) @@ -88,24 +88,4 @@ public static void addCubeAll( addVertex(buf, matrix, x0, y1, z1, u1, v1, tintColour, light, overlay, norm); addVertex(buf, matrix, x0, y0, z1, u1, v0, tintColour, light, overlay, norm); } - - public static int alpha(int colour) { - return colour >> 24 & 0xFF; - } - - public static int red(int colour) { - return colour >> 16 & 0xFF; - } - - public static int green(int colour) { - return colour >> 8 & 0xFF; - } - - public static int blue(int colour) { - return colour & 0xFF; - } - - public static int argb(int alpha, int red, int green, int blue) { - return alpha << 24 + red << 16 + green << 8 + blue; - } } diff --git a/src/main/resources/assets/bloodmagic/blockstates/doubt_block.json b/src/main/resources/assets/bloodmagic/blockstates/doubt_block.json index 1795b4324c..ce7b1e066a 100644 --- a/src/main/resources/assets/bloodmagic/blockstates/doubt_block.json +++ b/src/main/resources/assets/bloodmagic/blockstates/doubt_block.json @@ -1,5 +1,5 @@ { "variants": { - "": "block/doubt_block" + "": "bloodmagic:block/doubt_block" } } \ No newline at end of file diff --git a/src/main/resources/assets/bloodmagic/blockstates/life_essence_block.json b/src/main/resources/assets/bloodmagic/blockstates/life_essence_block.json index 4648893829..5d6cfd1626 100644 --- a/src/main/resources/assets/bloodmagic/blockstates/life_essence_block.json +++ b/src/main/resources/assets/bloodmagic/blockstates/life_essence_block.json @@ -1,5 +1,5 @@ { "variants": { - "": "block/life_essence_block" + "": "bloodmagic:block/life_essence_block" } } \ No newline at end of file diff --git a/src/main/resources/assets/bloodmagic/models/block/doubt_block.json b/src/main/resources/assets/bloodmagic/models/block/doubt_block.json index 319fe5298a..e5f9a18ccd 100644 --- a/src/main/resources/assets/bloodmagic/models/block/doubt_block.json +++ b/src/main/resources/assets/bloodmagic/models/block/doubt_block.json @@ -1,3 +1,5 @@ { - "render_type": "minecraft:solid" + "textures": { + "particle": "bloodmagic:liquid_doubt_still" + } } diff --git a/src/main/resources/assets/bloodmagic/models/block/life_essence_block.json b/src/main/resources/assets/bloodmagic/models/block/life_essence_block.json index 319fe5298a..c2e90126e0 100644 --- a/src/main/resources/assets/bloodmagic/models/block/life_essence_block.json +++ b/src/main/resources/assets/bloodmagic/models/block/life_essence_block.json @@ -1,3 +1,5 @@ { - "render_type": "minecraft:solid" + "textures": { + "particle": "bloodmagic:block/life_essence_still" + } } diff --git a/src/main/resources/assets/bloodmagic/models/block/routing/modelmasterroutingnodebase.mtl b/src/main/resources/assets/bloodmagic/models/block/routing/modelmasterroutingnodebase.mtl new file mode 100755 index 0000000000..1bb26d8754 --- /dev/null +++ b/src/main/resources/assets/bloodmagic/models/block/routing/modelmasterroutingnodebase.mtl @@ -0,0 +1,11 @@ +# Blender MTL File: 'None' +# Material Count: 1 + +newmtl None +#Ns 0 +Ka 0.000000 0.000000 0.000000 +Kd 0.8 0.8 0.8 +#Ks 0.8 0.8 0.8 +d 1 +#illum 2 +map_Kd #base \ No newline at end of file diff --git a/src/main/resources/assets/bloodmagic/models/block/routing/modelmasterroutingnodebase.obj b/src/main/resources/assets/bloodmagic/models/block/routing/modelmasterroutingnodebase.obj new file mode 100755 index 0000000000..d0ca172f3e --- /dev/null +++ b/src/main/resources/assets/bloodmagic/models/block/routing/modelmasterroutingnodebase.obj @@ -0,0 +1,360 @@ +# Blender v2.76 (sub 0) OBJ File: '' +# www.blender.org +mtllib modelmasterroutingnodebase.mtl +o ModelMasterRoutingNodeBase +v 0.250000 0.062500 0.750000 +v 0.250000 -0.000000 0.750000 +v 0.750000 -0.000000 0.750000 +v 0.750000 0.062500 0.750000 +v 0.750000 0.062500 0.250000 +v 0.750000 0.000000 0.250000 +v 0.250000 0.000000 0.250000 +v 0.250000 0.062500 0.250000 +v 0.362465 0.389996 0.531250 +v 0.278129 0.024602 0.531250 +v 0.339027 0.010546 0.531250 +v 0.423364 0.375940 0.531250 +v 0.423364 0.375940 0.468750 +v 0.339027 0.010546 0.468750 +v 0.278129 0.024602 0.468750 +v 0.362465 0.389996 0.468750 +v 0.468750 0.375964 0.423360 +v 0.468750 0.010578 0.339023 +v 0.531250 0.010578 0.339023 +v 0.531250 0.375964 0.423360 +v 0.531250 0.390020 0.362462 +v 0.531250 0.024634 0.278126 +v 0.468750 0.024634 0.278126 +v 0.468750 0.390020 0.362462 +v 0.468750 0.389996 0.637535 +v 0.468750 0.024602 0.721871 +v 0.531250 0.024602 0.721871 +v 0.531250 0.389996 0.637535 +v 0.531250 0.375940 0.576636 +v 0.531250 0.010546 0.660972 +v 0.468750 0.010546 0.660972 +v 0.468750 0.375940 0.576636 +v 0.576640 0.375964 0.531250 +v 0.660976 0.010578 0.531250 +v 0.721874 0.024634 0.531250 +v 0.637538 0.390020 0.531250 +v 0.637538 0.390020 0.468750 +v 0.721874 0.024634 0.468750 +v 0.660976 0.010578 0.468750 +v 0.576640 0.375964 0.468750 +v 0.375000 0.156250 0.625000 +v 0.375000 0.031250 0.625000 +v 0.625000 0.031250 0.625000 +v 0.625000 0.156250 0.625000 +v 0.625000 0.156250 0.375000 +v 0.625000 0.031250 0.375000 +v 0.375000 0.031250 0.375000 +v 0.375000 0.156250 0.375000 +v 0.437500 0.250000 0.562500 +v 0.437500 0.125000 0.562500 +v 0.562500 0.125000 0.562500 +v 0.562500 0.250000 0.562500 +v 0.562500 0.250000 0.437500 +v 0.562500 0.125000 0.437500 +v 0.437500 0.125000 0.437500 +v 0.437500 0.250000 0.437500 +v 0.468750 0.343750 0.531250 +v 0.468750 0.218750 0.531250 +v 0.531250 0.218750 0.531250 +v 0.531250 0.343750 0.531250 +v 0.531250 0.343750 0.468750 +v 0.531250 0.218750 0.468750 +v 0.468750 0.218750 0.468750 +v 0.468750 0.343750 0.468750 +v 0.362465 0.389996 0.531250 +v 0.278129 0.024602 0.531250 +v 0.339027 0.010546 0.531250 +v 0.423364 0.375940 0.531250 +v 0.423364 0.375940 0.468750 +v 0.339027 0.010546 0.468750 +v 0.278129 0.024602 0.468750 +v 0.362465 0.389996 0.468750 +v 0.468750 0.375964 0.423360 +v 0.468750 0.010578 0.339023 +v 0.531250 0.010578 0.339023 +v 0.531250 0.375964 0.423360 +v 0.531250 0.390020 0.362462 +v 0.531250 0.024634 0.278126 +v 0.468750 0.024634 0.278126 +v 0.468750 0.390020 0.362462 +v 0.468750 0.389996 0.637535 +v 0.468750 0.024602 0.721871 +v 0.531250 0.024602 0.721871 +v 0.531250 0.389996 0.637535 +v 0.531250 0.375940 0.576636 +v 0.531250 0.010546 0.660972 +v 0.468750 0.010546 0.660972 +v 0.468750 0.375940 0.576636 +v 0.576640 0.375964 0.531250 +v 0.660976 0.010578 0.531250 +v 0.721874 0.024634 0.531250 +v 0.637538 0.390020 0.531250 +v 0.637538 0.390020 0.468750 +v 0.721874 0.024634 0.468750 +v 0.660976 0.010578 0.468750 +v 0.576640 0.375964 0.468750 +v 0.375000 0.156250 0.625000 +v 0.375000 0.031250 0.625000 +v 0.625000 0.031250 0.625000 +v 0.625000 0.156250 0.625000 +v 0.625000 0.156250 0.375000 +v 0.625000 0.031250 0.375000 +v 0.375000 0.031250 0.375000 +v 0.375000 0.156250 0.375000 +v 0.437500 0.250000 0.562500 +v 0.437500 0.125000 0.562500 +v 0.562500 0.125000 0.562500 +v 0.562500 0.250000 0.562500 +v 0.562500 0.250000 0.437500 +v 0.562500 0.125000 0.437500 +v 0.437500 0.125000 0.437500 +v 0.437500 0.250000 0.437500 +v 0.468750 0.343750 0.531250 +v 0.468750 0.218750 0.531250 +v 0.531250 0.218750 0.531250 +v 0.531250 0.343750 0.531250 +v 0.531250 0.343750 0.468750 +v 0.531250 0.218750 0.468750 +v 0.468750 0.218750 0.468750 +v 0.468750 0.343750 0.468750 +v 0.437500 0.250000 0.562500 +v 0.437500 0.125000 0.562500 +v 0.562500 0.125000 0.562500 +v 0.562500 0.250000 0.562500 +v 0.562500 0.250000 0.437500 +v 0.562500 0.125000 0.437500 +v 0.437500 0.125000 0.437500 +v 0.437500 0.250000 0.437500 +v 0.468750 0.343750 0.531250 +v 0.468750 0.218750 0.531250 +v 0.531250 0.218750 0.531250 +v 0.531250 0.343750 0.531250 +v 0.531250 0.343750 0.468750 +v 0.531250 0.218750 0.468750 +v 0.468750 0.218750 0.468750 +v 0.468750 0.343750 0.468750 +v 0.468750 0.343750 0.531250 +v 0.468750 0.218750 0.531250 +v 0.531250 0.218750 0.531250 +v 0.531250 0.343750 0.531250 +v 0.531250 0.343750 0.468750 +v 0.531250 0.218750 0.468750 +v 0.468750 0.218750 0.468750 +v 0.468750 0.343750 0.468750 +vt 0.140625 0.515625 +vt 0.140625 0.500000 +vt 0.265625 0.500000 +vt 0.265625 0.515625 +vt 0.390625 0.515625 +vt 0.390625 0.500000 +vt 0.515625 0.500000 +vt 0.515625 0.515625 +vt 0.140625 0.640625 +vt 0.265625 0.640625 +vt 0.390625 0.640625 +vt 0.015625 0.515625 +vt 0.015625 0.500000 +vt 0.093750 0.625000 +vt 0.093750 0.531250 +vt 0.109375 0.531250 +vt 0.109375 0.625000 +vt 0.125000 0.625000 +vt 0.125000 0.531250 +vt 0.140625 0.531250 +vt 0.140625 0.625000 +vt 0.093750 0.640625 +vt 0.109375 0.640625 +vt 0.125000 0.640625 +vt 0.078125 0.625000 +vt 0.078125 0.531250 +vt 0.046875 0.625000 +vt 0.046875 0.531250 +vt 0.062500 0.531250 +vt 0.062500 0.625000 +vt 0.046875 0.640625 +vt 0.062500 0.640625 +vt 0.078125 0.640625 +vt 0.031250 0.625000 +vt 0.031250 0.531250 +vt 0.015625 0.625000 +vt 0.015625 0.531250 +vt 0.015625 0.640625 +vt 0.031250 0.640625 +vt 0.000000 0.625000 +vt 0.000000 0.531250 +vt 0.593750 0.531250 +vt 0.593750 0.500000 +vt 0.656250 0.500000 +vt 0.656250 0.531250 +vt 0.718750 0.531250 +vt 0.718750 0.500000 +vt 0.781250 0.500000 +vt 0.781250 0.531250 +vt 0.593750 0.593750 +vt 0.656250 0.593750 +vt 0.718750 0.593750 +vt 0.531250 0.531250 +vt 0.531250 0.500000 +vt 0.828125 0.531250 +vt 0.828125 0.500000 +vt 0.859375 0.500000 +vt 0.859375 0.531250 +vt 0.890625 0.531250 +vt 0.890625 0.500000 +vt 0.921875 0.500000 +vt 0.921875 0.531250 +vt 0.828125 0.562500 +vt 0.859375 0.562500 +vt 0.890625 0.562500 +vt 0.796875 0.531250 +vt 0.796875 0.500000 +vt 0.953125 0.531250 +vt 0.953125 0.500000 +vt 0.968750 0.500000 +vt 0.968750 0.531250 +vt 0.984375 0.531250 +vt 0.984375 0.500000 +vt 1.000000 0.500000 +vt 1.000000 0.531250 +vt 0.953125 0.546875 +vt 0.968750 0.546875 +vt 0.984375 0.546875 +vt 0.937500 0.531250 +vt 0.937500 0.500000 +vn 0.000000 0.000000 1.000000 +vn 0.000000 0.000000 -1.000000 +vn 0.000000 1.000000 0.000000 +vn 0.000000 -1.000000 -0.000000 +vn 1.000000 0.000000 0.000000 +vn -1.000000 0.000000 0.000000 +vn 0.224900 0.974400 0.000000 +vn -0.224900 -0.974400 -0.000000 +vn 0.974400 -0.224900 0.000000 +vn -0.974400 0.224900 0.000000 +vn 0.000000 -0.224900 0.974400 +vn 0.000000 0.224900 -0.974400 +vn 0.000000 0.974400 0.224900 +vn 0.000000 -0.974400 -0.224900 +vn 0.000000 0.224900 0.974400 +vn 0.000000 -0.224900 -0.974400 +vn 0.000000 0.974400 -0.224900 +vn 0.000000 -0.974400 0.224900 +vn -0.224900 0.974400 0.000000 +vn 0.224900 -0.974400 -0.000000 +vn 0.974400 0.224900 0.000000 +vn -0.974400 -0.224900 0.000000 +usemtl None +#s 1 +f 1/1/1 2/2/1 3/3/1 4/4/1 +f 5/5/2 6/6/2 7/7/2 8/8/2 +f 8/9/3 1/1/3 4/4/3 5/10/3 +f 2/5/4 7/11/4 6/10/4 3/4/4 +f 5/5/5 4/4/5 3/3/5 6/6/5 +f 8/12/6 7/13/6 2/2/6 1/1/6 +f 9/14/1 10/15/1 11/16/1 12/17/1 +f 13/18/2 14/19/2 15/20/2 16/21/2 +f 16/22/7 9/14/7 12/17/7 13/23/7 +f 10/18/8 15/24/8 14/23/8 11/17/8 +f 13/18/9 12/17/9 11/16/9 14/19/9 +f 16/25/10 15/26/10 10/15/10 9/14/10 +f 17/27/11 18/28/11 19/29/11 20/30/11 +f 21/25/12 22/26/12 23/15/12 24/14/12 +f 24/31/13 17/27/13 20/30/13 21/32/13 +f 18/25/14 23/33/14 22/32/14 19/30/14 +f 21/25/5 20/30/5 19/29/5 22/26/5 +f 24/34/6 23/35/6 18/28/6 17/27/6 +f 25/36/15 26/37/15 27/35/15 28/34/15 +f 29/27/16 30/28/16 31/29/16 32/30/16 +f 32/38/17 25/36/17 28/34/17 29/39/17 +f 26/27/18 31/31/18 30/39/18 27/34/18 +f 29/27/5 28/34/5 27/35/5 30/28/5 +f 32/40/6 31/41/6 26/37/6 25/36/6 +f 33/30/1 34/29/1 35/26/1 36/25/1 +f 37/14/2 38/15/2 39/16/2 40/17/2 +f 40/32/19 33/30/19 36/25/19 37/33/19 +f 34/14/20 39/22/20 38/33/20 35/25/20 +f 37/14/21 36/25/21 35/26/21 38/15/21 +f 40/27/22 39/28/22 34/29/22 33/30/22 +f 41/42/1 42/43/1 43/44/1 44/45/1 +f 45/46/2 46/47/2 47/48/2 48/49/2 +f 48/50/3 41/42/3 44/45/3 45/51/3 +f 42/46/4 47/52/4 46/51/4 43/45/4 +f 45/46/5 44/45/5 43/44/5 46/47/5 +f 48/53/6 47/54/6 42/43/6 41/42/6 +f 49/55/1 50/56/1 51/57/1 52/58/1 +f 53/59/2 54/60/2 55/61/2 56/62/2 +f 56/63/3 49/55/3 52/58/3 53/64/3 +f 50/59/4 55/65/4 54/64/4 51/58/4 +f 53/59/5 52/58/5 51/57/5 54/60/5 +f 56/66/6 55/67/6 50/56/6 49/55/6 +f 57/68/1 58/69/1 59/70/1 60/71/1 +f 61/72/2 62/73/2 63/74/2 64/75/2 +f 64/76/3 57/68/3 60/71/3 61/77/3 +f 58/72/4 63/78/4 62/77/4 59/71/4 +f 61/72/5 60/71/5 59/70/5 62/73/5 +f 64/79/6 63/80/6 58/69/6 57/68/6 +f 65/14/1 66/15/1 67/16/1 68/17/1 +f 69/18/2 70/19/2 71/20/2 72/21/2 +f 72/22/7 65/14/7 68/17/7 69/23/7 +f 66/18/8 71/24/8 70/23/8 67/17/8 +f 69/18/9 68/17/9 67/16/9 70/19/9 +f 72/25/10 71/26/10 66/15/10 65/14/10 +f 73/27/11 74/28/11 75/29/11 76/30/11 +f 77/25/12 78/26/12 79/15/12 80/14/12 +f 80/31/13 73/27/13 76/30/13 77/32/13 +f 74/25/14 79/33/14 78/32/14 75/30/14 +f 77/25/5 76/30/5 75/29/5 78/26/5 +f 80/34/6 79/35/6 74/28/6 73/27/6 +f 81/36/15 82/37/15 83/35/15 84/34/15 +f 85/27/16 86/28/16 87/29/16 88/30/16 +f 88/38/17 81/36/17 84/34/17 85/39/17 +f 82/27/18 87/31/18 86/39/18 83/34/18 +f 85/27/5 84/34/5 83/35/5 86/28/5 +f 88/40/6 87/41/6 82/37/6 81/36/6 +f 89/30/1 90/29/1 91/26/1 92/25/1 +f 93/14/2 94/15/2 95/16/2 96/17/2 +f 96/32/19 89/30/19 92/25/19 93/33/19 +f 90/14/20 95/22/20 94/33/20 91/25/20 +f 93/14/21 92/25/21 91/26/21 94/15/21 +f 96/27/22 95/28/22 90/29/22 89/30/22 +f 97/42/1 98/43/1 99/44/1 100/45/1 +f 101/46/2 102/47/2 103/48/2 104/49/2 +f 104/50/3 97/42/3 100/45/3 101/51/3 +f 98/46/4 103/52/4 102/51/4 99/45/4 +f 101/46/5 100/45/5 99/44/5 102/47/5 +f 104/53/6 103/54/6 98/43/6 97/42/6 +f 105/55/1 106/56/1 107/57/1 108/58/1 +f 109/59/2 110/60/2 111/61/2 112/62/2 +f 112/63/3 105/55/3 108/58/3 109/64/3 +f 106/59/4 111/65/4 110/64/4 107/58/4 +f 109/59/5 108/58/5 107/57/5 110/60/5 +f 112/66/6 111/67/6 106/56/6 105/55/6 +f 113/68/1 114/69/1 115/70/1 116/71/1 +f 117/72/2 118/73/2 119/74/2 120/75/2 +f 120/76/3 113/68/3 116/71/3 117/77/3 +f 114/72/4 119/78/4 118/77/4 115/71/4 +f 117/72/5 116/71/5 115/70/5 118/73/5 +f 120/79/6 119/80/6 114/69/6 113/68/6 +f 121/55/1 122/56/1 123/57/1 124/58/1 +f 125/59/2 126/60/2 127/61/2 128/62/2 +f 128/63/3 121/55/3 124/58/3 125/64/3 +f 122/59/4 127/65/4 126/64/4 123/58/4 +f 125/59/5 124/58/5 123/57/5 126/60/5 +f 128/66/6 127/67/6 122/56/6 121/55/6 +f 129/68/1 130/69/1 131/70/1 132/71/1 +f 133/72/2 134/73/2 135/74/2 136/75/2 +f 136/76/3 129/68/3 132/71/3 133/77/3 +f 130/72/4 135/78/4 134/77/4 131/71/4 +f 133/72/5 132/71/5 131/70/5 134/73/5 +f 136/79/6 135/80/6 130/69/6 129/68/6 +f 137/68/1 138/69/1 139/70/1 140/71/1 +f 141/72/2 142/73/2 143/74/2 144/75/2 +f 144/76/3 137/68/3 140/71/3 141/77/3 +f 138/72/4 143/78/4 142/77/4 139/71/4 +f 141/72/5 140/71/5 139/70/5 142/73/5 +f 144/79/6 143/80/6 138/69/6 137/68/6 diff --git a/src/main/resources/assets/bloodmagic/models/block/routing/modelmasterroutingnodecombined.mtl b/src/main/resources/assets/bloodmagic/models/block/routing/modelmasterroutingnodecombined.mtl new file mode 100755 index 0000000000..c851cf27d6 --- /dev/null +++ b/src/main/resources/assets/bloodmagic/models/block/routing/modelmasterroutingnodecombined.mtl @@ -0,0 +1,24 @@ +# Blender MTL File: 'None' +# Material Count: 2 + +newmtl None +Ns 0.000000 +Ka 1.000000 1.000000 1.000000 +Kd 0.800000 0.800000 0.800000 +Ks 0.000000 0.000000 0.000000 +Ke 0.000000 0.000000 0.000000 +Ni 1.450000 +d 1.000000 +illum 1 +map_Kd #base + +newmtl None.001 +Ns 0.000000 +Ka 1.000000 1.000000 1.000000 +Kd 0.800000 0.800000 0.800000 +Ks 0.000000 0.000000 0.000000 +Ke 0.000000 0.000000 0.000000 +Ni 1.450000 +d 1.000000 +illum 1 +map_Kd #core diff --git a/src/main/resources/assets/bloodmagic/models/block/routing/modelmasterroutingnodecombined.obj b/src/main/resources/assets/bloodmagic/models/block/routing/modelmasterroutingnodecombined.obj new file mode 100755 index 0000000000..5f6f824e58 --- /dev/null +++ b/src/main/resources/assets/bloodmagic/models/block/routing/modelmasterroutingnodecombined.obj @@ -0,0 +1,637 @@ +# Blender v2.93.1 OBJ File: '' +# www.blender.org +mtllib modelmasterroutingnodecombined.mtl +o ModelMasterRoutingNodeBase +v 0.250000 0.062500 0.750000 +v 0.250000 -0.000000 0.750000 +v 0.750000 -0.000000 0.750000 +v 0.750000 0.062500 0.750000 +v 0.750000 0.062500 0.250000 +v 0.750000 -0.000000 0.250000 +v 0.250000 -0.000000 0.250000 +v 0.250000 0.062500 0.250000 +v 0.362465 0.389996 0.531250 +v 0.278129 0.024602 0.531250 +v 0.339027 0.010546 0.531250 +v 0.423364 0.375940 0.531250 +v 0.423364 0.375940 0.468750 +v 0.339027 0.010546 0.468750 +v 0.278129 0.024602 0.468750 +v 0.362465 0.389996 0.468750 +v 0.468750 0.375964 0.423360 +v 0.468750 0.010578 0.339023 +v 0.531250 0.010578 0.339023 +v 0.531250 0.375964 0.423360 +v 0.531250 0.390020 0.362462 +v 0.531250 0.024634 0.278126 +v 0.468750 0.024634 0.278126 +v 0.468750 0.390020 0.362462 +v 0.468750 0.389996 0.637535 +v 0.468750 0.024602 0.721871 +v 0.531250 0.024602 0.721871 +v 0.531250 0.389996 0.637535 +v 0.531250 0.375940 0.576636 +v 0.531250 0.010546 0.660972 +v 0.468750 0.010546 0.660972 +v 0.468750 0.375940 0.576636 +v 0.576640 0.375964 0.531250 +v 0.660976 0.010578 0.531250 +v 0.721874 0.024634 0.531250 +v 0.637538 0.390020 0.531250 +v 0.637538 0.390020 0.468750 +v 0.721874 0.024634 0.468750 +v 0.660976 0.010578 0.468750 +v 0.576640 0.375964 0.468750 +v 0.375000 0.156250 0.625000 +v 0.375000 0.031250 0.625000 +v 0.625000 0.031250 0.625000 +v 0.625000 0.156250 0.625000 +v 0.625000 0.156250 0.375000 +v 0.625000 0.031250 0.375000 +v 0.375000 0.031250 0.375000 +v 0.375000 0.156250 0.375000 +v 0.437500 0.250000 0.562500 +v 0.437500 0.125000 0.562500 +v 0.562500 0.125000 0.562500 +v 0.562500 0.250000 0.562500 +v 0.562500 0.250000 0.437500 +v 0.562500 0.125000 0.437500 +v 0.437500 0.125000 0.437500 +v 0.437500 0.250000 0.437500 +v 0.468750 0.343750 0.531250 +v 0.468750 0.218750 0.531250 +v 0.531250 0.218750 0.531250 +v 0.531250 0.343750 0.531250 +v 0.531250 0.343750 0.468750 +v 0.531250 0.218750 0.468750 +v 0.468750 0.218750 0.468750 +v 0.468750 0.343750 0.468750 +v 0.362465 0.389996 0.531250 +v 0.278129 0.024602 0.531250 +v 0.339027 0.010546 0.531250 +v 0.423364 0.375940 0.531250 +v 0.423364 0.375940 0.468750 +v 0.339027 0.010546 0.468750 +v 0.278129 0.024602 0.468750 +v 0.362465 0.389996 0.468750 +v 0.468750 0.375964 0.423360 +v 0.468750 0.010578 0.339023 +v 0.531250 0.010578 0.339023 +v 0.531250 0.375964 0.423360 +v 0.531250 0.390020 0.362462 +v 0.531250 0.024634 0.278126 +v 0.468750 0.024634 0.278126 +v 0.468750 0.390020 0.362462 +v 0.468750 0.389996 0.637535 +v 0.468750 0.024602 0.721871 +v 0.531250 0.024602 0.721871 +v 0.531250 0.389996 0.637535 +v 0.531250 0.375940 0.576636 +v 0.531250 0.010546 0.660972 +v 0.468750 0.010546 0.660972 +v 0.468750 0.375940 0.576636 +v 0.576640 0.375964 0.531250 +v 0.660976 0.010578 0.531250 +v 0.721874 0.024634 0.531250 +v 0.637538 0.390020 0.531250 +v 0.637538 0.390020 0.468750 +v 0.721874 0.024634 0.468750 +v 0.660976 0.010578 0.468750 +v 0.576640 0.375964 0.468750 +v 0.375000 0.156250 0.625000 +v 0.375000 0.031250 0.625000 +v 0.625000 0.031250 0.625000 +v 0.625000 0.156250 0.625000 +v 0.625000 0.156250 0.375000 +v 0.625000 0.031250 0.375000 +v 0.375000 0.031250 0.375000 +v 0.375000 0.156250 0.375000 +v 0.437500 0.250000 0.562500 +v 0.437500 0.125000 0.562500 +v 0.562500 0.125000 0.562500 +v 0.562500 0.250000 0.562500 +v 0.562500 0.250000 0.437500 +v 0.562500 0.125000 0.437500 +v 0.437500 0.125000 0.437500 +v 0.437500 0.250000 0.437500 +v 0.468750 0.343750 0.531250 +v 0.468750 0.218750 0.531250 +v 0.531250 0.218750 0.531250 +v 0.531250 0.343750 0.531250 +v 0.531250 0.343750 0.468750 +v 0.531250 0.218750 0.468750 +v 0.468750 0.218750 0.468750 +v 0.468750 0.343750 0.468750 +v 0.437500 0.250000 0.562500 +v 0.437500 0.125000 0.562500 +v 0.562500 0.125000 0.562500 +v 0.562500 0.250000 0.562500 +v 0.562500 0.250000 0.437500 +v 0.562500 0.125000 0.437500 +v 0.437500 0.125000 0.437500 +v 0.437500 0.250000 0.437500 +v 0.468750 0.343750 0.531250 +v 0.468750 0.218750 0.531250 +v 0.531250 0.218750 0.531250 +v 0.531250 0.343750 0.531250 +v 0.531250 0.343750 0.468750 +v 0.531250 0.218750 0.468750 +v 0.468750 0.218750 0.468750 +v 0.468750 0.343750 0.468750 +v 0.468750 0.343750 0.531250 +v 0.468750 0.218750 0.531250 +v 0.531250 0.218750 0.531250 +v 0.531250 0.343750 0.531250 +v 0.531250 0.343750 0.468750 +v 0.531250 0.218750 0.468750 +v 0.468750 0.218750 0.468750 +v 0.468750 0.343750 0.468750 +vt 0.140625 0.515625 +vt 0.140625 0.500000 +vt 0.265625 0.500000 +vt 0.265625 0.515625 +vt 0.390625 0.515625 +vt 0.390625 0.500000 +vt 0.515625 0.500000 +vt 0.515625 0.515625 +vt 0.140625 0.640625 +vt 0.265625 0.640625 +vt 0.390625 0.515625 +vt 0.390625 0.640625 +vt 0.265625 0.640625 +vt 0.265625 0.515625 +vt 0.015625 0.515625 +vt 0.015625 0.500000 +vt 0.093750 0.625000 +vt 0.093750 0.531250 +vt 0.109375 0.531250 +vt 0.109375 0.625000 +vt 0.125000 0.625000 +vt 0.125000 0.531250 +vt 0.140625 0.531250 +vt 0.140625 0.625000 +vt 0.093750 0.640625 +vt 0.109375 0.640625 +vt 0.125000 0.625000 +vt 0.125000 0.640625 +vt 0.109375 0.640625 +vt 0.109375 0.625000 +vt 0.078125 0.625000 +vt 0.078125 0.531250 +vt 0.046875 0.625000 +vt 0.046875 0.531250 +vt 0.062500 0.531250 +vt 0.062500 0.625000 +vt 0.078125 0.625000 +vt 0.078125 0.531250 +vt 0.093750 0.531250 +vt 0.093750 0.625000 +vt 0.046875 0.640625 +vt 0.062500 0.640625 +vt 0.078125 0.625000 +vt 0.078125 0.640625 +vt 0.062500 0.640625 +vt 0.062500 0.625000 +vt 0.031250 0.625000 +vt 0.031250 0.531250 +vt 0.015625 0.625000 +vt 0.015625 0.531250 +vt 0.031250 0.531250 +vt 0.031250 0.625000 +vt 0.046875 0.625000 +vt 0.046875 0.531250 +vt 0.062500 0.531250 +vt 0.062500 0.625000 +vt 0.015625 0.640625 +vt 0.031250 0.640625 +vt 0.046875 0.625000 +vt 0.046875 0.640625 +vt 0.031250 0.640625 +vt 0.031250 0.625000 +vt 0.000000 0.625000 +vt 0.000000 0.531250 +vt 0.062500 0.625000 +vt 0.062500 0.531250 +vt 0.078125 0.531250 +vt 0.078125 0.625000 +vt 0.093750 0.625000 +vt 0.093750 0.531250 +vt 0.109375 0.531250 +vt 0.109375 0.625000 +vt 0.062500 0.640625 +vt 0.078125 0.640625 +vt 0.093750 0.625000 +vt 0.093750 0.640625 +vt 0.078125 0.640625 +vt 0.078125 0.625000 +vt 0.046875 0.625000 +vt 0.046875 0.531250 +vt 0.593750 0.531250 +vt 0.593750 0.500000 +vt 0.656250 0.500000 +vt 0.656250 0.531250 +vt 0.718750 0.531250 +vt 0.718750 0.500000 +vt 0.781250 0.500000 +vt 0.781250 0.531250 +vt 0.593750 0.593750 +vt 0.656250 0.593750 +vt 0.718750 0.531250 +vt 0.718750 0.593750 +vt 0.656250 0.593750 +vt 0.656250 0.531250 +vt 0.531250 0.531250 +vt 0.531250 0.500000 +vt 0.828125 0.531250 +vt 0.828125 0.500000 +vt 0.859375 0.500000 +vt 0.859375 0.531250 +vt 0.890625 0.531250 +vt 0.890625 0.500000 +vt 0.921875 0.500000 +vt 0.921875 0.531250 +vt 0.828125 0.562500 +vt 0.859375 0.562500 +vt 0.890625 0.531250 +vt 0.890625 0.562500 +vt 0.859375 0.562500 +vt 0.859375 0.531250 +vt 0.796875 0.531250 +vt 0.796875 0.500000 +vt 0.953125 0.531250 +vt 0.953125 0.500000 +vt 0.968750 0.500000 +vt 0.968750 0.531250 +vt 0.984375 0.531250 +vt 0.984375 0.500000 +vt 1.000000 0.500000 +vt 1.000000 0.531250 +vt 0.953125 0.546875 +vt 0.968750 0.546875 +vt 0.984375 0.531250 +vt 0.984375 0.546875 +vt 0.968750 0.546875 +vt 0.968750 0.531250 +vt 0.937500 0.531250 +vt 0.937500 0.500000 +vt 0.093750 0.625000 +vt 0.093750 0.531250 +vt 0.109375 0.531250 +vt 0.109375 0.625000 +vt 0.125000 0.625000 +vt 0.125000 0.531250 +vt 0.140625 0.531250 +vt 0.140625 0.625000 +vt 0.093750 0.640625 +vt 0.109375 0.640625 +vt 0.125000 0.625000 +vt 0.125000 0.640625 +vt 0.109375 0.640625 +vt 0.109375 0.625000 +vt 0.078125 0.625000 +vt 0.078125 0.531250 +vt 0.046875 0.625000 +vt 0.046875 0.531250 +vt 0.062500 0.531250 +vt 0.062500 0.625000 +vt 0.078125 0.625000 +vt 0.078125 0.531250 +vt 0.093750 0.531250 +vt 0.093750 0.625000 +vt 0.046875 0.640625 +vt 0.062500 0.640625 +vt 0.078125 0.625000 +vt 0.078125 0.640625 +vt 0.062500 0.640625 +vt 0.062500 0.625000 +vt 0.031250 0.625000 +vt 0.031250 0.531250 +vt 0.015625 0.625000 +vt 0.015625 0.531250 +vt 0.031250 0.531250 +vt 0.031250 0.625000 +vt 0.046875 0.625000 +vt 0.046875 0.531250 +vt 0.062500 0.531250 +vt 0.062500 0.625000 +vt 0.015625 0.640625 +vt 0.031250 0.640625 +vt 0.046875 0.625000 +vt 0.046875 0.640625 +vt 0.031250 0.640625 +vt 0.031250 0.625000 +vt 0.000000 0.625000 +vt 0.000000 0.531250 +vt 0.062500 0.625000 +vt 0.062500 0.531250 +vt 0.078125 0.531250 +vt 0.078125 0.625000 +vt 0.093750 0.625000 +vt 0.093750 0.531250 +vt 0.109375 0.531250 +vt 0.109375 0.625000 +vt 0.062500 0.640625 +vt 0.078125 0.640625 +vt 0.093750 0.625000 +vt 0.093750 0.640625 +vt 0.078125 0.640625 +vt 0.078125 0.625000 +vt 0.046875 0.625000 +vt 0.046875 0.531250 +vt 0.593750 0.531250 +vt 0.593750 0.500000 +vt 0.656250 0.500000 +vt 0.656250 0.531250 +vt 0.718750 0.531250 +vt 0.718750 0.500000 +vt 0.781250 0.500000 +vt 0.781250 0.531250 +vt 0.593750 0.593750 +vt 0.656250 0.593750 +vt 0.718750 0.531250 +vt 0.718750 0.593750 +vt 0.656250 0.593750 +vt 0.656250 0.531250 +vt 0.531250 0.531250 +vt 0.531250 0.500000 +vt 0.828125 0.531250 +vt 0.828125 0.500000 +vt 0.859375 0.500000 +vt 0.859375 0.531250 +vt 0.890625 0.531250 +vt 0.890625 0.500000 +vt 0.921875 0.500000 +vt 0.921875 0.531250 +vt 0.828125 0.562500 +vt 0.859375 0.562500 +vt 0.890625 0.531250 +vt 0.890625 0.562500 +vt 0.859375 0.562500 +vt 0.859375 0.531250 +vt 0.796875 0.531250 +vt 0.796875 0.500000 +vt 0.953125 0.531250 +vt 0.953125 0.500000 +vt 0.968750 0.500000 +vt 0.968750 0.531250 +vt 0.984375 0.531250 +vt 0.984375 0.500000 +vt 1.000000 0.500000 +vt 1.000000 0.531250 +vt 0.953125 0.546875 +vt 0.968750 0.546875 +vt 0.984375 0.531250 +vt 0.984375 0.546875 +vt 0.968750 0.546875 +vt 0.968750 0.531250 +vt 0.937500 0.531250 +vt 0.937500 0.500000 +vt 0.828125 0.531250 +vt 0.828125 0.500000 +vt 0.859375 0.500000 +vt 0.859375 0.531250 +vt 0.890625 0.531250 +vt 0.890625 0.500000 +vt 0.921875 0.500000 +vt 0.921875 0.531250 +vt 0.828125 0.562500 +vt 0.859375 0.562500 +vt 0.890625 0.531250 +vt 0.890625 0.562500 +vt 0.859375 0.562500 +vt 0.859375 0.531250 +vt 0.796875 0.531250 +vt 0.796875 0.500000 +vt 0.953125 0.531250 +vt 0.953125 0.500000 +vt 0.968750 0.500000 +vt 0.968750 0.531250 +vt 0.984375 0.531250 +vt 0.984375 0.500000 +vt 1.000000 0.500000 +vt 1.000000 0.531250 +vt 0.953125 0.546875 +vt 0.968750 0.546875 +vt 0.984375 0.531250 +vt 0.984375 0.546875 +vt 0.968750 0.546875 +vt 0.968750 0.531250 +vt 0.937500 0.531250 +vt 0.937500 0.500000 +vt 0.953125 0.531250 +vt 0.953125 0.500000 +vt 0.968750 0.500000 +vt 0.968750 0.531250 +vt 0.984375 0.531250 +vt 0.984375 0.500000 +vt 1.000000 0.500000 +vt 1.000000 0.531250 +vt 0.953125 0.546875 +vt 0.968750 0.546875 +vt 0.984375 0.531250 +vt 0.984375 0.546875 +vt 0.968750 0.546875 +vt 0.968750 0.531250 +vt 0.937500 0.531250 +vt 0.937500 0.500000 +vn 0.0000 0.0000 1.0000 +vn 0.0000 0.0000 -1.0000 +vn 0.0000 1.0000 0.0000 +vn 0.0000 -1.0000 -0.0000 +vn 1.0000 0.0000 0.0000 +vn -1.0000 0.0000 0.0000 +vn 0.2249 0.9744 0.0000 +vn -0.2249 -0.9744 -0.0000 +vn 0.9744 -0.2249 0.0000 +vn -0.9744 0.2249 0.0000 +vn 0.0000 -0.2249 0.9744 +vn 0.0000 0.2249 -0.9744 +vn 0.0000 0.9744 0.2249 +vn 0.0000 -0.9744 -0.2249 +vn 0.0000 0.2249 0.9744 +vn 0.0000 -0.2249 -0.9744 +vn 0.0000 0.9744 -0.2249 +vn 0.0000 -0.9744 0.2249 +vn -0.2249 0.9744 0.0000 +vn 0.2249 -0.9744 -0.0000 +vn 0.9744 0.2249 0.0000 +vn -0.9744 -0.2249 0.0000 +usemtl None +s 1 +f 1/1/1 2/2/1 3/3/1 4/4/1 +f 5/5/2 6/6/2 7/7/2 8/8/2 +f 8/9/3 1/1/3 4/4/3 5/10/3 +f 2/11/4 7/12/4 6/13/4 3/14/4 +f 5/5/5 4/4/5 3/3/5 6/6/5 +f 8/15/6 7/16/6 2/2/6 1/1/6 +f 9/17/1 10/18/1 11/19/1 12/20/1 +f 13/21/2 14/22/2 15/23/2 16/24/2 +f 16/25/7 9/17/7 12/20/7 13/26/7 +f 10/27/8 15/28/8 14/29/8 11/30/8 +f 13/21/9 12/20/9 11/19/9 14/22/9 +f 16/31/10 15/32/10 10/18/10 9/17/10 +f 17/33/11 18/34/11 19/35/11 20/36/11 +f 21/37/12 22/38/12 23/39/12 24/40/12 +f 24/41/13 17/33/13 20/36/13 21/42/13 +f 18/43/14 23/44/14 22/45/14 19/46/14 +f 21/37/5 20/36/5 19/35/5 22/38/5 +f 24/47/6 23/48/6 18/34/6 17/33/6 +f 25/49/15 26/50/15 27/51/15 28/52/15 +f 29/53/16 30/54/16 31/55/16 32/56/16 +f 32/57/17 25/49/17 28/52/17 29/58/17 +f 26/59/18 31/60/18 30/61/18 27/62/18 +f 29/53/5 28/52/5 27/51/5 30/54/5 +f 32/63/6 31/64/6 26/50/6 25/49/6 +f 33/65/1 34/66/1 35/67/1 36/68/1 +f 37/69/2 38/70/2 39/71/2 40/72/2 +f 40/73/19 33/65/19 36/68/19 37/74/19 +f 34/75/20 39/76/20 38/77/20 35/78/20 +f 37/69/21 36/68/21 35/67/21 38/70/21 +f 40/79/22 39/80/22 34/66/22 33/65/22 +f 41/81/1 42/82/1 43/83/1 44/84/1 +f 45/85/2 46/86/2 47/87/2 48/88/2 +f 48/89/3 41/81/3 44/84/3 45/90/3 +f 42/91/4 47/92/4 46/93/4 43/94/4 +f 45/85/5 44/84/5 43/83/5 46/86/5 +f 48/95/6 47/96/6 42/82/6 41/81/6 +f 49/97/1 50/98/1 51/99/1 52/100/1 +f 53/101/2 54/102/2 55/103/2 56/104/2 +f 56/105/3 49/97/3 52/100/3 53/106/3 +f 50/107/4 55/108/4 54/109/4 51/110/4 +f 53/101/5 52/100/5 51/99/5 54/102/5 +f 56/111/6 55/112/6 50/98/6 49/97/6 +f 57/113/1 58/114/1 59/115/1 60/116/1 +f 61/117/2 62/118/2 63/119/2 64/120/2 +f 64/121/3 57/113/3 60/116/3 61/122/3 +f 58/123/4 63/124/4 62/125/4 59/126/4 +f 61/117/5 60/116/5 59/115/5 62/118/5 +f 64/127/6 63/128/6 58/114/6 57/113/6 +f 65/129/1 66/130/1 67/131/1 68/132/1 +f 69/133/2 70/134/2 71/135/2 72/136/2 +f 72/137/7 65/129/7 68/132/7 69/138/7 +f 66/139/8 71/140/8 70/141/8 67/142/8 +f 69/133/9 68/132/9 67/131/9 70/134/9 +f 72/143/10 71/144/10 66/130/10 65/129/10 +f 73/145/11 74/146/11 75/147/11 76/148/11 +f 77/149/12 78/150/12 79/151/12 80/152/12 +f 80/153/13 73/145/13 76/148/13 77/154/13 +f 74/155/14 79/156/14 78/157/14 75/158/14 +f 77/149/5 76/148/5 75/147/5 78/150/5 +f 80/159/6 79/160/6 74/146/6 73/145/6 +f 81/161/15 82/162/15 83/163/15 84/164/15 +f 85/165/16 86/166/16 87/167/16 88/168/16 +f 88/169/17 81/161/17 84/164/17 85/170/17 +f 82/171/18 87/172/18 86/173/18 83/174/18 +f 85/165/5 84/164/5 83/163/5 86/166/5 +f 88/175/6 87/176/6 82/162/6 81/161/6 +f 89/177/1 90/178/1 91/179/1 92/180/1 +f 93/181/2 94/182/2 95/183/2 96/184/2 +f 96/185/19 89/177/19 92/180/19 93/186/19 +f 90/187/20 95/188/20 94/189/20 91/190/20 +f 93/181/21 92/180/21 91/179/21 94/182/21 +f 96/191/22 95/192/22 90/178/22 89/177/22 +f 97/193/1 98/194/1 99/195/1 100/196/1 +f 101/197/2 102/198/2 103/199/2 104/200/2 +f 104/201/3 97/193/3 100/196/3 101/202/3 +f 98/203/4 103/204/4 102/205/4 99/206/4 +f 101/197/5 100/196/5 99/195/5 102/198/5 +f 104/207/6 103/208/6 98/194/6 97/193/6 +f 105/209/1 106/210/1 107/211/1 108/212/1 +f 109/213/2 110/214/2 111/215/2 112/216/2 +f 112/217/3 105/209/3 108/212/3 109/218/3 +f 106/219/4 111/220/4 110/221/4 107/222/4 +f 109/213/5 108/212/5 107/211/5 110/214/5 +f 112/223/6 111/224/6 106/210/6 105/209/6 +f 113/225/1 114/226/1 115/227/1 116/228/1 +f 117/229/2 118/230/2 119/231/2 120/232/2 +f 120/233/3 113/225/3 116/228/3 117/234/3 +f 114/235/4 119/236/4 118/237/4 115/238/4 +f 117/229/5 116/228/5 115/227/5 118/230/5 +f 120/239/6 119/240/6 114/226/6 113/225/6 +f 121/241/1 122/242/1 123/243/1 124/244/1 +f 125/245/2 126/246/2 127/247/2 128/248/2 +f 128/249/3 121/241/3 124/244/3 125/250/3 +f 122/251/4 127/252/4 126/253/4 123/254/4 +f 125/245/5 124/244/5 123/243/5 126/246/5 +f 128/255/6 127/256/6 122/242/6 121/241/6 +f 129/257/1 130/258/1 131/259/1 132/260/1 +f 133/261/2 134/262/2 135/263/2 136/264/2 +f 136/265/3 129/257/3 132/260/3 133/266/3 +f 130/267/4 135/268/4 134/269/4 131/270/4 +f 133/261/5 132/260/5 131/259/5 134/262/5 +f 136/271/6 135/272/6 130/258/6 129/257/6 +f 137/273/1 138/274/1 139/275/1 140/276/1 +f 141/277/2 142/278/2 143/279/2 144/280/2 +f 144/281/3 137/273/3 140/276/3 141/282/3 +f 138/283/4 143/284/4 142/285/4 139/286/4 +f 141/277/5 140/276/5 139/275/5 142/278/5 +f 144/287/6 143/288/6 138/274/6 137/273/6 +o ModelMasterRoutingNodeCore +v 0.343750 0.656250 0.656250 +v 0.343750 0.343750 0.656250 +v 0.656250 0.343750 0.656250 +v 0.656250 0.656250 0.656250 +v 0.656250 0.656250 0.343750 +v 0.656250 0.343750 0.343750 +v 0.343750 0.343750 0.343750 +v 0.343750 0.656250 0.343750 +v 0.406250 0.593750 0.593750 +v 0.406250 0.406250 0.593750 +v 0.593750 0.406250 0.593750 +v 0.593750 0.593750 0.593750 +v 0.593750 0.593750 0.406250 +v 0.593750 0.406250 0.406250 +v 0.406250 0.406250 0.406250 +v 0.406250 0.593750 0.406250 +vt 0.078125 0.921875 +vt 0.078125 0.843750 +vt 0.156250 0.843750 +vt 0.156250 0.921875 +vt 0.234375 0.921875 +vt 0.234375 0.843750 +vt 0.312500 0.843750 +vt 0.312500 0.921875 +vt 0.078125 1.000000 +vt 0.156250 1.000000 +vt 0.234375 0.921875 +vt 0.234375 1.000000 +vt 0.156250 1.000000 +vt 0.156250 0.921875 +vt 0.000000 0.921875 +vt 0.000000 0.843750 +vt 0.046875 0.781250 +vt 0.046875 0.734375 +vt 0.093750 0.734375 +vt 0.093750 0.781250 +vt 0.140625 0.781250 +vt 0.140625 0.734375 +vt 0.187500 0.734375 +vt 0.187500 0.781250 +vt 0.046875 0.828125 +vt 0.093750 0.828125 +vt 0.140625 0.781250 +vt 0.140625 0.828125 +vt 0.093750 0.828125 +vt 0.093750 0.781250 +vt 0.000000 0.781250 +vt 0.000000 0.734375 +vn 0.0000 -0.0000 1.0000 +vn 0.0000 0.0000 -1.0000 +vn 0.0000 1.0000 0.0000 +vn 0.0000 -1.0000 -0.0000 +vn 1.0000 0.0000 0.0000 +vn -1.0000 0.0000 0.0000 +usemtl None.001 +s 1 +f 145/289/23 146/290/23 147/291/23 148/292/23 +f 149/293/24 150/294/24 151/295/24 152/296/24 +f 152/297/25 145/289/25 148/292/25 149/298/25 +f 146/299/26 151/300/26 150/301/26 147/302/26 +f 149/293/27 148/292/27 147/291/27 150/294/27 +f 152/303/28 151/304/28 146/290/28 145/289/28 +f 153/305/23 154/306/23 155/307/23 156/308/23 +f 157/309/24 158/310/24 159/311/24 160/312/24 +f 160/313/25 153/305/25 156/308/25 157/314/25 +f 154/315/26 159/316/26 158/317/26 155/318/26 +f 157/309/27 156/308/27 155/307/27 158/310/27 +f 160/319/28 159/320/28 154/306/28 153/305/28 diff --git a/src/main/resources/assets/bloodmagic/models/block/routing/modelmasterroutingnodecore.mtl b/src/main/resources/assets/bloodmagic/models/block/routing/modelmasterroutingnodecore.mtl new file mode 100755 index 0000000000..26d04038de --- /dev/null +++ b/src/main/resources/assets/bloodmagic/models/block/routing/modelmasterroutingnodecore.mtl @@ -0,0 +1,11 @@ +# Blender MTL File: 'None' +# Material Count: 1 + +newmtl None +#Ns 0 +Ka 0.000000 0.000000 0.000000 +Kd 0.8 0.8 0.8 +#Ks 0.8 0.8 0.8 +d 1 +#illum 2 +map_Kd #core \ No newline at end of file diff --git a/src/main/resources/assets/bloodmagic/models/block/routing/modelmasterroutingnodecore.obj b/src/main/resources/assets/bloodmagic/models/block/routing/modelmasterroutingnodecore.obj new file mode 100755 index 0000000000..4529d98a79 --- /dev/null +++ b/src/main/resources/assets/bloodmagic/models/block/routing/modelmasterroutingnodecore.obj @@ -0,0 +1,66 @@ +# Blender v2.76 (sub 0) OBJ File: '' +# www.blender.org +mtllib modelmasterroutingnodecore.mtl +o ModelMasterRoutingNodeCore +v 0.343750 0.656250 0.656250 +v 0.343750 0.343750 0.656250 +v 0.656250 0.343750 0.656250 +v 0.656250 0.656250 0.656250 +v 0.656250 0.656250 0.343750 +v 0.656250 0.343750 0.343750 +v 0.343750 0.343750 0.343750 +v 0.343750 0.656250 0.343750 +v 0.406250 0.593750 0.593750 +v 0.406250 0.406250 0.593750 +v 0.593750 0.406250 0.593750 +v 0.593750 0.593750 0.593750 +v 0.593750 0.593750 0.406250 +v 0.593750 0.406250 0.406250 +v 0.406250 0.406250 0.406250 +v 0.406250 0.593750 0.406250 +vt 0.078125 0.921875 +vt 0.078125 0.843750 +vt 0.156250 0.843750 +vt 0.156250 0.921875 +vt 0.234375 0.921875 +vt 0.234375 0.843750 +vt 0.312500 0.843750 +vt 0.312500 0.921875 +vt 0.078125 1.000000 +vt 0.156250 1.000000 +vt 0.234375 1.000000 +vt 0.000000 0.921875 +vt 0.000000 0.843750 +vt 0.046875 0.781250 +vt 0.046875 0.734375 +vt 0.093750 0.734375 +vt 0.093750 0.781250 +vt 0.140625 0.781250 +vt 0.140625 0.734375 +vt 0.187500 0.734375 +vt 0.187500 0.781250 +vt 0.046875 0.828125 +vt 0.093750 0.828125 +vt 0.140625 0.828125 +vt 0.000000 0.781250 +vt 0.000000 0.734375 +vn 0.000000 -0.000000 1.000000 +vn 0.000000 0.000000 -1.000000 +vn 0.000000 1.000000 0.000000 +vn 0.000000 -1.000000 -0.000000 +vn 1.000000 0.000000 0.000000 +vn -1.000000 0.000000 0.000000 +usemtl None +#s 1 +f 1/1/1 2/2/1 3/3/1 4/4/1 +f 5/5/2 6/6/2 7/7/2 8/8/2 +f 8/9/3 1/1/3 4/4/3 5/10/3 +f 2/5/4 7/11/4 6/10/4 3/4/4 +f 5/5/5 4/4/5 3/3/5 6/6/5 +f 8/12/6 7/13/6 2/2/6 1/1/6 +f 9/14/1 10/15/1 11/16/1 12/17/1 +f 13/18/2 14/19/2 15/20/2 16/21/2 +f 16/22/3 9/14/3 12/17/3 13/23/3 +f 10/18/4 15/24/4 14/23/4 11/17/4 +f 13/18/5 12/17/5 11/16/5 14/19/5 +f 16/25/6 15/26/6 10/15/6 9/14/6 diff --git a/src/main/resources/assets/bloodmagic/models/block/routing/modelroutingnodebase.mtl b/src/main/resources/assets/bloodmagic/models/block/routing/modelroutingnodebase.mtl new file mode 100755 index 0000000000..1bb26d8754 --- /dev/null +++ b/src/main/resources/assets/bloodmagic/models/block/routing/modelroutingnodebase.mtl @@ -0,0 +1,11 @@ +# Blender MTL File: 'None' +# Material Count: 1 + +newmtl None +#Ns 0 +Ka 0.000000 0.000000 0.000000 +Kd 0.8 0.8 0.8 +#Ks 0.8 0.8 0.8 +d 1 +#illum 2 +map_Kd #base \ No newline at end of file diff --git a/src/main/resources/assets/bloodmagic/models/block/routing/modelroutingnodebase.obj b/src/main/resources/assets/bloodmagic/models/block/routing/modelroutingnodebase.obj new file mode 100755 index 0000000000..52ce964321 --- /dev/null +++ b/src/main/resources/assets/bloodmagic/models/block/routing/modelroutingnodebase.obj @@ -0,0 +1,444 @@ +# Blender v2.76 (sub 0) OBJ File: '' +# www.blender.org +mtllib modelroutingnodebase.mtl +o ModelRoutingNode +v 0.312500 0.062500 0.687500 +v 0.312500 -0.000000 0.687500 +v 0.687500 -0.000000 0.687500 +v 0.687500 0.062500 0.687500 +v 0.687500 0.062500 0.312500 +v 0.687500 0.000000 0.312500 +v 0.312500 0.000000 0.312500 +v 0.312500 0.062500 0.312500 +v 0.389168 0.422318 0.531250 +v 0.304832 0.056925 0.531250 +v 0.365731 0.042869 0.531250 +v 0.450067 0.408262 0.531250 +v 0.450067 0.408262 0.468750 +v 0.365731 0.042869 0.468750 +v 0.304832 0.056925 0.468750 +v 0.389168 0.422318 0.468750 +v 0.468750 0.408285 0.450063 +v 0.468750 0.042900 0.365726 +v 0.531250 0.042900 0.365726 +v 0.531250 0.408285 0.450063 +v 0.531250 0.422341 0.389165 +v 0.531250 0.056956 0.304829 +v 0.468750 0.056956 0.304829 +v 0.468750 0.422341 0.389165 +v 0.468750 0.422318 0.610832 +v 0.468750 0.056925 0.695168 +v 0.531250 0.056925 0.695168 +v 0.531250 0.422318 0.610832 +v 0.531250 0.408262 0.549933 +v 0.531250 0.042869 0.634269 +v 0.468750 0.042869 0.634269 +v 0.468750 0.408262 0.549933 +v 0.549937 0.408285 0.531250 +v 0.634273 0.042900 0.531250 +v 0.695171 0.056956 0.531250 +v 0.610835 0.422341 0.531250 +v 0.610835 0.422341 0.468750 +v 0.695171 0.056956 0.468750 +v 0.634273 0.042900 0.468750 +v 0.549937 0.408285 0.468750 +v 0.437500 0.125000 0.562500 +v 0.437500 0.062500 0.562500 +v 0.562500 0.062500 0.562500 +v 0.562500 0.125000 0.562500 +v 0.562500 0.125000 0.437500 +v 0.562500 0.062500 0.437500 +v 0.437500 0.062500 0.437500 +v 0.437500 0.125000 0.437500 +v 0.468750 0.187500 0.531250 +v 0.468750 0.125000 0.531250 +v 0.531250 0.125000 0.531250 +v 0.531250 0.187500 0.531250 +v 0.531250 0.187500 0.468750 +v 0.531250 0.125000 0.468750 +v 0.468750 0.125000 0.468750 +v 0.468750 0.187500 0.468750 +v 0.437500 0.062500 0.312500 +v 0.437500 0.000000 0.312500 +v 0.562500 0.000000 0.312500 +v 0.562500 0.062500 0.312500 +v 0.562500 0.062500 0.250000 +v 0.562500 0.000000 0.250000 +v 0.437500 0.000000 0.250000 +v 0.437500 0.062500 0.250000 +v 0.687500 0.062500 0.562500 +v 0.687500 -0.000000 0.562500 +v 0.750000 -0.000000 0.562500 +v 0.750000 0.062500 0.562500 +v 0.750000 0.062500 0.437500 +v 0.750000 0.000000 0.437500 +v 0.687500 0.000000 0.437500 +v 0.687500 0.062500 0.437500 +v 0.437500 0.062500 0.750000 +v 0.437500 -0.000000 0.750000 +v 0.562500 -0.000000 0.750000 +v 0.562500 0.062500 0.750000 +v 0.562500 0.062500 0.687500 +v 0.562500 -0.000000 0.687500 +v 0.437500 -0.000000 0.687500 +v 0.437500 0.062500 0.687500 +v 0.250000 0.062500 0.562500 +v 0.250000 -0.000000 0.562500 +v 0.312500 -0.000000 0.562500 +v 0.312500 0.062500 0.562500 +v 0.312500 0.062500 0.437500 +v 0.312500 0.000000 0.437500 +v 0.250000 0.000000 0.437500 +v 0.250000 0.062500 0.437500 +v 0.389168 0.422318 0.531250 +v 0.304832 0.056925 0.531250 +v 0.365731 0.042869 0.531250 +v 0.450067 0.408262 0.531250 +v 0.450067 0.408262 0.468750 +v 0.365731 0.042869 0.468750 +v 0.304832 0.056925 0.468750 +v 0.389168 0.422318 0.468750 +v 0.468750 0.408285 0.450063 +v 0.468750 0.042900 0.365726 +v 0.531250 0.042900 0.365726 +v 0.531250 0.408285 0.450063 +v 0.531250 0.422341 0.389165 +v 0.531250 0.056956 0.304829 +v 0.468750 0.056956 0.304829 +v 0.468750 0.422341 0.389165 +v 0.468750 0.422318 0.610832 +v 0.468750 0.056925 0.695168 +v 0.531250 0.056925 0.695168 +v 0.531250 0.422318 0.610832 +v 0.531250 0.408262 0.549933 +v 0.531250 0.042869 0.634269 +v 0.468750 0.042869 0.634269 +v 0.468750 0.408262 0.549933 +v 0.549937 0.408285 0.531250 +v 0.634273 0.042900 0.531250 +v 0.695171 0.056956 0.531250 +v 0.610835 0.422341 0.531250 +v 0.610835 0.422341 0.468750 +v 0.695171 0.056956 0.468750 +v 0.634273 0.042900 0.468750 +v 0.549937 0.408285 0.468750 +v 0.437500 0.125000 0.562500 +v 0.437500 0.062500 0.562500 +v 0.562500 0.062500 0.562500 +v 0.562500 0.125000 0.562500 +v 0.562500 0.125000 0.437500 +v 0.562500 0.062500 0.437500 +v 0.437500 0.062500 0.437500 +v 0.437500 0.125000 0.437500 +v 0.468750 0.187500 0.531250 +v 0.468750 0.125000 0.531250 +v 0.531250 0.125000 0.531250 +v 0.531250 0.187500 0.531250 +v 0.531250 0.187500 0.468750 +v 0.531250 0.125000 0.468750 +v 0.468750 0.125000 0.468750 +v 0.468750 0.187500 0.468750 +v 0.437500 0.062500 0.312500 +v 0.437500 0.000000 0.312500 +v 0.562500 0.000000 0.312500 +v 0.562500 0.062500 0.312500 +v 0.562500 0.062500 0.250000 +v 0.562500 0.000000 0.250000 +v 0.437500 0.000000 0.250000 +v 0.437500 0.062500 0.250000 +v 0.687500 0.062500 0.562500 +v 0.687500 -0.000000 0.562500 +v 0.750000 -0.000000 0.562500 +v 0.750000 0.062500 0.562500 +v 0.750000 0.062500 0.437500 +v 0.750000 0.000000 0.437500 +v 0.687500 0.000000 0.437500 +v 0.687500 0.062500 0.437500 +v 0.437500 0.062500 0.750000 +v 0.437500 -0.000000 0.750000 +v 0.562500 -0.000000 0.750000 +v 0.562500 0.062500 0.750000 +v 0.562500 0.062500 0.687500 +v 0.562500 -0.000000 0.687500 +v 0.437500 -0.000000 0.687500 +v 0.437500 0.062500 0.687500 +v 0.250000 0.062500 0.562500 +v 0.250000 -0.000000 0.562500 +v 0.312500 -0.000000 0.562500 +v 0.312500 0.062500 0.562500 +v 0.312500 0.062500 0.437500 +v 0.312500 0.000000 0.437500 +v 0.250000 0.000000 0.437500 +v 0.250000 0.062500 0.437500 +v 0.468750 0.187500 0.531250 +v 0.468750 0.125000 0.531250 +v 0.531250 0.125000 0.531250 +v 0.531250 0.187500 0.531250 +v 0.531250 0.187500 0.468750 +v 0.531250 0.125000 0.468750 +v 0.468750 0.125000 0.468750 +v 0.468750 0.187500 0.468750 +vt 0.093750 0.515625 +vt 0.093750 0.500000 +vt 0.187500 0.500000 +vt 0.187500 0.515625 +vt 0.281250 0.515625 +vt 0.281250 0.500000 +vt 0.375000 0.500000 +vt 0.375000 0.515625 +vt 0.093750 0.609375 +vt 0.187500 0.609375 +vt 0.281250 0.609375 +vt 0.000000 0.515625 +vt 0.000000 0.500000 +vt 0.015625 0.625000 +vt 0.015625 0.531250 +vt 0.031250 0.531250 +vt 0.031250 0.625000 +vt 0.046875 0.625000 +vt 0.046875 0.531250 +vt 0.062500 0.531250 +vt 0.062500 0.625000 +vt 0.015625 0.640625 +vt 0.031250 0.640625 +vt 0.046875 0.640625 +vt 0.000000 0.625000 +vt 0.000000 0.531250 +vt 0.421875 0.515625 +vt 0.421875 0.500000 +vt 0.453125 0.500000 +vt 0.453125 0.515625 +vt 0.484375 0.515625 +vt 0.484375 0.500000 +vt 0.515625 0.500000 +vt 0.515625 0.515625 +vt 0.421875 0.546875 +vt 0.453125 0.546875 +vt 0.484375 0.546875 +vt 0.390625 0.515625 +vt 0.390625 0.500000 +vt 0.546875 0.515625 +vt 0.546875 0.500000 +vt 0.562500 0.500000 +vt 0.562500 0.515625 +vt 0.578125 0.515625 +vt 0.578125 0.500000 +vt 0.593750 0.500000 +vt 0.593750 0.515625 +vt 0.546875 0.531250 +vt 0.562500 0.531250 +vt 0.578125 0.531250 +vt 0.531250 0.515625 +vt 0.531250 0.500000 +vt 0.625000 0.515625 +vt 0.625000 0.500000 +vt 0.656250 0.500000 +vt 0.656250 0.515625 +vt 0.671875 0.515625 +vt 0.671875 0.500000 +vt 0.703125 0.500000 +vt 0.703125 0.515625 +vt 0.625000 0.531250 +vt 0.656250 0.531250 +vt 0.687500 0.515625 +vt 0.687500 0.531250 +vt 0.609375 0.515625 +vt 0.609375 0.500000 +vt 0.750000 0.515625 +vt 0.750000 0.500000 +vt 0.765625 0.500000 +vt 0.765625 0.515625 +vt 0.796875 0.515625 +vt 0.796875 0.500000 +vt 0.812500 0.500000 +vt 0.812500 0.515625 +vt 0.750000 0.546875 +vt 0.765625 0.546875 +vt 0.781250 0.515625 +vt 0.781250 0.546875 +vt 0.718750 0.515625 +vt 0.718750 0.500000 +vt 0.625000 0.562500 +vt 0.625000 0.546875 +vt 0.656250 0.546875 +vt 0.656250 0.562500 +vt 0.671875 0.562500 +vt 0.671875 0.546875 +vt 0.703125 0.546875 +vt 0.703125 0.562500 +vt 0.625000 0.578125 +vt 0.656250 0.578125 +vt 0.687500 0.562500 +vt 0.687500 0.578125 +vt 0.609375 0.562500 +vt 0.609375 0.546875 +vt 0.750000 0.578125 +vt 0.750000 0.562500 +vt 0.765625 0.562500 +vt 0.765625 0.578125 +vt 0.796875 0.578125 +vt 0.796875 0.562500 +vt 0.812500 0.562500 +vt 0.812500 0.578125 +vt 0.750000 0.609375 +vt 0.765625 0.609375 +vt 0.781250 0.578125 +vt 0.781250 0.609375 +vt 0.718750 0.578125 +vt 0.718750 0.562500 +vn 0.000000 0.000000 1.000000 +vn 0.000000 0.000000 -1.000000 +vn 0.000000 1.000000 0.000000 +vn 0.000000 -1.000000 -0.000000 +vn 1.000000 0.000000 0.000000 +vn -1.000000 0.000000 0.000000 +vn 0.224900 0.974400 0.000000 +vn -0.224900 -0.974400 -0.000000 +vn 0.974400 -0.224900 0.000000 +vn -0.974400 0.224900 0.000000 +vn 0.000000 -0.224900 0.974400 +vn 0.000000 0.224900 -0.974400 +vn 0.000000 0.974400 0.224900 +vn 0.000000 -0.974400 -0.224900 +vn 0.000000 0.224900 0.974400 +vn 0.000000 -0.224900 -0.974400 +vn 0.000000 0.974400 -0.224900 +vn 0.000000 -0.974400 0.224900 +vn -0.224900 0.974400 0.000000 +vn 0.224900 -0.974400 -0.000000 +vn 0.974400 0.224900 0.000000 +vn -0.974400 -0.224900 0.000000 +usemtl None +#s 1 +f 1/1/1 2/2/1 3/3/1 4/4/1 +f 5/5/2 6/6/2 7/7/2 8/8/2 +f 8/9/3 1/1/3 4/4/3 5/10/3 +f 2/5/4 7/11/4 6/10/4 3/4/4 +f 5/5/5 4/4/5 3/3/5 6/6/5 +f 8/12/6 7/13/6 2/2/6 1/1/6 +f 9/14/1 10/15/1 11/16/1 12/17/1 +f 13/18/2 14/19/2 15/20/2 16/21/2 +f 16/22/7 9/14/7 12/17/7 13/23/7 +f 10/18/8 15/24/8 14/23/8 11/17/8 +f 13/18/9 12/17/9 11/16/9 14/19/9 +f 16/25/10 15/26/10 10/15/10 9/14/10 +f 17/14/11 18/15/11 19/16/11 20/17/11 +f 21/18/12 22/19/12 23/20/12 24/21/12 +f 24/22/13 17/14/13 20/17/13 21/23/13 +f 18/18/14 23/24/14 22/23/14 19/17/14 +f 21/18/5 20/17/5 19/16/5 22/19/5 +f 24/25/6 23/26/6 18/15/6 17/14/6 +f 25/14/15 26/15/15 27/16/15 28/17/15 +f 29/18/16 30/19/16 31/20/16 32/21/16 +f 32/22/17 25/14/17 28/17/17 29/23/17 +f 26/18/18 31/24/18 30/23/18 27/17/18 +f 29/18/5 28/17/5 27/16/5 30/19/5 +f 32/25/6 31/26/6 26/15/6 25/14/6 +f 33/14/1 34/15/1 35/16/1 36/17/1 +f 37/18/2 38/19/2 39/20/2 40/21/2 +f 40/22/19 33/14/19 36/17/19 37/23/19 +f 34/18/20 39/24/20 38/23/20 35/17/20 +f 37/18/21 36/17/21 35/16/21 38/19/21 +f 40/25/22 39/26/22 34/15/22 33/14/22 +f 41/27/1 42/28/1 43/29/1 44/30/1 +f 45/31/2 46/32/2 47/33/2 48/34/2 +f 48/35/3 41/27/3 44/30/3 45/36/3 +f 42/31/4 47/37/4 46/36/4 43/30/4 +f 45/31/5 44/30/5 43/29/5 46/32/5 +f 48/38/6 47/39/6 42/28/6 41/27/6 +f 49/40/1 50/41/1 51/42/1 52/43/1 +f 53/44/2 54/45/2 55/46/2 56/47/2 +f 56/48/3 49/40/3 52/43/3 53/49/3 +f 50/44/4 55/50/4 54/49/4 51/43/4 +f 53/44/5 52/43/5 51/42/5 54/45/5 +f 56/51/6 55/52/6 50/41/6 49/40/6 +f 57/53/1 58/54/1 59/55/1 60/56/1 +f 61/57/2 62/58/2 63/59/2 64/60/2 +f 64/61/3 57/53/3 60/56/3 61/62/3 +f 58/63/4 63/64/4 62/62/4 59/56/4 +f 61/57/5 60/56/5 59/55/5 62/58/5 +f 64/65/6 63/66/6 58/54/6 57/53/6 +f 65/67/1 66/68/1 67/69/1 68/70/1 +f 69/71/2 70/72/2 71/73/2 72/74/2 +f 72/75/3 65/67/3 68/70/3 69/76/3 +f 66/77/4 71/78/4 70/76/4 67/70/4 +f 69/71/5 68/70/5 67/69/5 70/72/5 +f 72/79/6 71/80/6 66/68/6 65/67/6 +f 73/81/1 74/82/1 75/83/1 76/84/1 +f 77/85/2 78/86/2 79/87/2 80/88/2 +f 80/89/3 73/81/3 76/84/3 77/90/3 +f 74/91/4 79/92/4 78/90/4 75/84/4 +f 77/85/5 76/84/5 75/83/5 78/86/5 +f 80/93/6 79/94/6 74/82/6 73/81/6 +f 81/95/1 82/96/1 83/97/1 84/98/1 +f 85/99/2 86/100/2 87/101/2 88/102/2 +f 88/103/3 81/95/3 84/98/3 85/104/3 +f 82/105/4 87/106/4 86/104/4 83/98/4 +f 85/99/5 84/98/5 83/97/5 86/100/5 +f 88/107/6 87/108/6 82/96/6 81/95/6 +f 89/14/1 90/15/1 91/16/1 92/17/1 +f 93/18/2 94/19/2 95/20/2 96/21/2 +f 96/22/7 89/14/7 92/17/7 93/23/7 +f 90/18/8 95/24/8 94/23/8 91/17/8 +f 93/18/9 92/17/9 91/16/9 94/19/9 +f 96/25/10 95/26/10 90/15/10 89/14/10 +f 97/14/11 98/15/11 99/16/11 100/17/11 +f 101/18/12 102/19/12 103/20/12 104/21/12 +f 104/22/13 97/14/13 100/17/13 101/23/13 +f 98/18/14 103/24/14 102/23/14 99/17/14 +f 101/18/5 100/17/5 99/16/5 102/19/5 +f 104/25/6 103/26/6 98/15/6 97/14/6 +f 105/14/15 106/15/15 107/16/15 108/17/15 +f 109/18/16 110/19/16 111/20/16 112/21/16 +f 112/22/17 105/14/17 108/17/17 109/23/17 +f 106/18/18 111/24/18 110/23/18 107/17/18 +f 109/18/5 108/17/5 107/16/5 110/19/5 +f 112/25/6 111/26/6 106/15/6 105/14/6 +f 113/14/1 114/15/1 115/16/1 116/17/1 +f 117/18/2 118/19/2 119/20/2 120/21/2 +f 120/22/19 113/14/19 116/17/19 117/23/19 +f 114/18/20 119/24/20 118/23/20 115/17/20 +f 117/18/21 116/17/21 115/16/21 118/19/21 +f 120/25/22 119/26/22 114/15/22 113/14/22 +f 121/27/1 122/28/1 123/29/1 124/30/1 +f 125/31/2 126/32/2 127/33/2 128/34/2 +f 128/35/3 121/27/3 124/30/3 125/36/3 +f 122/31/4 127/37/4 126/36/4 123/30/4 +f 125/31/5 124/30/5 123/29/5 126/32/5 +f 128/38/6 127/39/6 122/28/6 121/27/6 +f 129/40/1 130/41/1 131/42/1 132/43/1 +f 133/44/2 134/45/2 135/46/2 136/47/2 +f 136/48/3 129/40/3 132/43/3 133/49/3 +f 130/44/4 135/50/4 134/49/4 131/43/4 +f 133/44/5 132/43/5 131/42/5 134/45/5 +f 136/51/6 135/52/6 130/41/6 129/40/6 +f 137/53/1 138/54/1 139/55/1 140/56/1 +f 141/57/2 142/58/2 143/59/2 144/60/2 +f 144/61/3 137/53/3 140/56/3 141/62/3 +f 138/63/4 143/64/4 142/62/4 139/56/4 +f 141/57/5 140/56/5 139/55/5 142/58/5 +f 144/65/6 143/66/6 138/54/6 137/53/6 +f 145/67/1 146/68/1 147/69/1 148/70/1 +f 149/71/2 150/72/2 151/73/2 152/74/2 +f 152/75/3 145/67/3 148/70/3 149/76/3 +f 146/77/4 151/78/4 150/76/4 147/70/4 +f 149/71/5 148/70/5 147/69/5 150/72/5 +f 152/79/6 151/80/6 146/68/6 145/67/6 +f 153/81/1 154/82/1 155/83/1 156/84/1 +f 157/85/2 158/86/2 159/87/2 160/88/2 +f 160/89/3 153/81/3 156/84/3 157/90/3 +f 154/91/4 159/92/4 158/90/4 155/84/4 +f 157/85/5 156/84/5 155/83/5 158/86/5 +f 160/93/6 159/94/6 154/82/6 153/81/6 +f 161/95/1 162/96/1 163/97/1 164/98/1 +f 165/99/2 166/100/2 167/101/2 168/102/2 +f 168/103/3 161/95/3 164/98/3 165/104/3 +f 162/105/4 167/106/4 166/104/4 163/98/4 +f 165/99/5 164/98/5 163/97/5 166/100/5 +f 168/107/6 167/108/6 162/96/6 161/95/6 +f 169/40/1 170/41/1 171/42/1 172/43/1 +f 173/44/2 174/45/2 175/46/2 176/47/2 +f 176/48/3 169/40/3 172/43/3 173/49/3 +f 170/44/4 175/50/4 174/49/4 171/43/4 +f 173/44/5 172/43/5 171/42/5 174/45/5 +f 176/51/6 175/52/6 170/41/6 169/40/6 diff --git a/src/main/resources/assets/bloodmagic/models/block/routing/modelroutingnodecombined.mtl b/src/main/resources/assets/bloodmagic/models/block/routing/modelroutingnodecombined.mtl new file mode 100755 index 0000000000..f366012a04 --- /dev/null +++ b/src/main/resources/assets/bloodmagic/models/block/routing/modelroutingnodecombined.mtl @@ -0,0 +1,24 @@ +# Blender MTL File: 'None' +# Material Count: 2 + +newmtl None.001 +Ns 0.000000 +Ka 1.000000 1.000000 1.000000 +Kd 0.800000 0.800000 0.800000 +Ks 0.000000 0.000000 0.000000 +Ke 0.000000 0.000000 0.000000 +Ni 1.450000 +d 1.000000 +illum 1 +map_Kd #base + +newmtl None.002 +Ns 0.000000 +Ka 1.000000 1.000000 1.000000 +Kd 0.800000 0.800000 0.800000 +Ks 0.000000 0.000000 0.000000 +Ke 0.000000 0.000000 0.000000 +Ni 1.450000 +d 1.000000 +illum 1 +map_Kd #base diff --git a/src/main/resources/assets/bloodmagic/models/block/routing/modelroutingnodecombined.obj b/src/main/resources/assets/bloodmagic/models/block/routing/modelroutingnodecombined.obj new file mode 100755 index 0000000000..0984b22dc1 --- /dev/null +++ b/src/main/resources/assets/bloodmagic/models/block/routing/modelroutingnodecombined.obj @@ -0,0 +1,757 @@ +# Blender v2.93.1 OBJ File: '' +# www.blender.org +mtllib modelroutingnodecombined.mtl +o ModelRoutingNode +v 0.312500 0.062500 0.687500 +v 0.312500 -0.000000 0.687500 +v 0.687500 -0.000000 0.687500 +v 0.687500 0.062500 0.687500 +v 0.687500 0.062500 0.312500 +v 0.687500 -0.000000 0.312500 +v 0.312500 -0.000000 0.312500 +v 0.312500 0.062500 0.312500 +v 0.389168 0.422318 0.531250 +v 0.304832 0.056925 0.531250 +v 0.365731 0.042869 0.531250 +v 0.450067 0.408262 0.531250 +v 0.450067 0.408262 0.468750 +v 0.365731 0.042869 0.468750 +v 0.304832 0.056925 0.468750 +v 0.389168 0.422318 0.468750 +v 0.468750 0.408285 0.450063 +v 0.468750 0.042900 0.365726 +v 0.531250 0.042900 0.365726 +v 0.531250 0.408285 0.450063 +v 0.531250 0.422341 0.389165 +v 0.531250 0.056956 0.304829 +v 0.468750 0.056956 0.304829 +v 0.468750 0.422341 0.389165 +v 0.468750 0.422318 0.610832 +v 0.468750 0.056925 0.695168 +v 0.531250 0.056925 0.695168 +v 0.531250 0.422318 0.610832 +v 0.531250 0.408262 0.549933 +v 0.531250 0.042869 0.634269 +v 0.468750 0.042869 0.634269 +v 0.468750 0.408262 0.549933 +v 0.549937 0.408285 0.531250 +v 0.634273 0.042900 0.531250 +v 0.695171 0.056956 0.531250 +v 0.610835 0.422341 0.531250 +v 0.610835 0.422341 0.468750 +v 0.695171 0.056956 0.468750 +v 0.634273 0.042900 0.468750 +v 0.549937 0.408285 0.468750 +v 0.437500 0.125000 0.562500 +v 0.437500 0.062500 0.562500 +v 0.562500 0.062500 0.562500 +v 0.562500 0.125000 0.562500 +v 0.562500 0.125000 0.437500 +v 0.562500 0.062500 0.437500 +v 0.437500 0.062500 0.437500 +v 0.437500 0.125000 0.437500 +v 0.468750 0.187500 0.531250 +v 0.468750 0.125000 0.531250 +v 0.531250 0.125000 0.531250 +v 0.531250 0.187500 0.531250 +v 0.531250 0.187500 0.468750 +v 0.531250 0.125000 0.468750 +v 0.468750 0.125000 0.468750 +v 0.468750 0.187500 0.468750 +v 0.437500 0.062500 0.312500 +v 0.437500 -0.000000 0.312500 +v 0.562500 -0.000000 0.312500 +v 0.562500 0.062500 0.312500 +v 0.562500 0.062500 0.250000 +v 0.562500 -0.000000 0.250000 +v 0.437500 -0.000000 0.250000 +v 0.437500 0.062500 0.250000 +v 0.687500 0.062500 0.562500 +v 0.687500 -0.000000 0.562500 +v 0.750000 -0.000000 0.562500 +v 0.750000 0.062500 0.562500 +v 0.750000 0.062500 0.437500 +v 0.750000 -0.000000 0.437500 +v 0.687500 -0.000000 0.437500 +v 0.687500 0.062500 0.437500 +v 0.437500 0.062500 0.750000 +v 0.437500 -0.000000 0.750000 +v 0.562500 -0.000000 0.750000 +v 0.562500 0.062500 0.750000 +v 0.562500 0.062500 0.687500 +v 0.562500 -0.000000 0.687500 +v 0.437500 -0.000000 0.687500 +v 0.437500 0.062500 0.687500 +v 0.250000 0.062500 0.562500 +v 0.250000 -0.000000 0.562500 +v 0.312500 -0.000000 0.562500 +v 0.312500 0.062500 0.562500 +v 0.312500 0.062500 0.437500 +v 0.312500 -0.000000 0.437500 +v 0.250000 -0.000000 0.437500 +v 0.250000 0.062500 0.437500 +v 0.389168 0.422318 0.531250 +v 0.304832 0.056925 0.531250 +v 0.365731 0.042869 0.531250 +v 0.450067 0.408262 0.531250 +v 0.450067 0.408262 0.468750 +v 0.365731 0.042869 0.468750 +v 0.304832 0.056925 0.468750 +v 0.389168 0.422318 0.468750 +v 0.468750 0.408285 0.450063 +v 0.468750 0.042900 0.365726 +v 0.531250 0.042900 0.365726 +v 0.531250 0.408285 0.450063 +v 0.531250 0.422341 0.389165 +v 0.531250 0.056956 0.304829 +v 0.468750 0.056956 0.304829 +v 0.468750 0.422341 0.389165 +v 0.468750 0.422318 0.610832 +v 0.468750 0.056925 0.695168 +v 0.531250 0.056925 0.695168 +v 0.531250 0.422318 0.610832 +v 0.531250 0.408262 0.549933 +v 0.531250 0.042869 0.634269 +v 0.468750 0.042869 0.634269 +v 0.468750 0.408262 0.549933 +v 0.549937 0.408285 0.531250 +v 0.634273 0.042900 0.531250 +v 0.695171 0.056956 0.531250 +v 0.610835 0.422341 0.531250 +v 0.610835 0.422341 0.468750 +v 0.695171 0.056956 0.468750 +v 0.634273 0.042900 0.468750 +v 0.549937 0.408285 0.468750 +v 0.437500 0.125000 0.562500 +v 0.437500 0.062500 0.562500 +v 0.562500 0.062500 0.562500 +v 0.562500 0.125000 0.562500 +v 0.562500 0.125000 0.437500 +v 0.562500 0.062500 0.437500 +v 0.437500 0.062500 0.437500 +v 0.437500 0.125000 0.437500 +v 0.468750 0.187500 0.531250 +v 0.468750 0.125000 0.531250 +v 0.531250 0.125000 0.531250 +v 0.531250 0.187500 0.531250 +v 0.531250 0.187500 0.468750 +v 0.531250 0.125000 0.468750 +v 0.468750 0.125000 0.468750 +v 0.468750 0.187500 0.468750 +v 0.437500 0.062500 0.312500 +v 0.437500 -0.000000 0.312500 +v 0.562500 -0.000000 0.312500 +v 0.562500 0.062500 0.312500 +v 0.562500 0.062500 0.250000 +v 0.562500 -0.000000 0.250000 +v 0.437500 -0.000000 0.250000 +v 0.437500 0.062500 0.250000 +v 0.687500 0.062500 0.562500 +v 0.687500 -0.000000 0.562500 +v 0.750000 -0.000000 0.562500 +v 0.750000 0.062500 0.562500 +v 0.750000 0.062500 0.437500 +v 0.750000 -0.000000 0.437500 +v 0.687500 -0.000000 0.437500 +v 0.687500 0.062500 0.437500 +v 0.437500 0.062500 0.750000 +v 0.437500 -0.000000 0.750000 +v 0.562500 -0.000000 0.750000 +v 0.562500 0.062500 0.750000 +v 0.562500 0.062500 0.687500 +v 0.562500 -0.000000 0.687500 +v 0.437500 -0.000000 0.687500 +v 0.437500 0.062500 0.687500 +v 0.250000 0.062500 0.562500 +v 0.250000 -0.000000 0.562500 +v 0.312500 -0.000000 0.562500 +v 0.312500 0.062500 0.562500 +v 0.312500 0.062500 0.437500 +v 0.312500 -0.000000 0.437500 +v 0.250000 -0.000000 0.437500 +v 0.250000 0.062500 0.437500 +v 0.468750 0.187500 0.531250 +v 0.468750 0.125000 0.531250 +v 0.531250 0.125000 0.531250 +v 0.531250 0.187500 0.531250 +v 0.531250 0.187500 0.468750 +v 0.531250 0.125000 0.468750 +v 0.468750 0.125000 0.468750 +v 0.468750 0.187500 0.468750 +vt 0.093750 0.515625 +vt 0.093750 0.500000 +vt 0.187500 0.500000 +vt 0.187500 0.515625 +vt 0.281250 0.515625 +vt 0.281250 0.500000 +vt 0.375000 0.500000 +vt 0.375000 0.515625 +vt 0.093750 0.609375 +vt 0.187500 0.609375 +vt 0.281250 0.515625 +vt 0.281250 0.609375 +vt 0.187500 0.609375 +vt 0.187500 0.515625 +vt 0.000000 0.515625 +vt 0.000000 0.500000 +vt 0.015625 0.625000 +vt 0.015625 0.531250 +vt 0.031250 0.531250 +vt 0.031250 0.625000 +vt 0.046875 0.625000 +vt 0.046875 0.531250 +vt 0.062500 0.531250 +vt 0.062500 0.625000 +vt 0.015625 0.640625 +vt 0.031250 0.640625 +vt 0.046875 0.625000 +vt 0.046875 0.640625 +vt 0.031250 0.640625 +vt 0.031250 0.625000 +vt 0.000000 0.625000 +vt 0.000000 0.531250 +vt 0.015625 0.625000 +vt 0.015625 0.531250 +vt 0.031250 0.531250 +vt 0.031250 0.625000 +vt 0.046875 0.625000 +vt 0.046875 0.531250 +vt 0.062500 0.531250 +vt 0.062500 0.625000 +vt 0.015625 0.640625 +vt 0.031250 0.640625 +vt 0.046875 0.625000 +vt 0.046875 0.640625 +vt 0.031250 0.640625 +vt 0.031250 0.625000 +vt 0.000000 0.625000 +vt 0.000000 0.531250 +vt 0.015625 0.625000 +vt 0.015625 0.531250 +vt 0.031250 0.531250 +vt 0.031250 0.625000 +vt 0.046875 0.625000 +vt 0.046875 0.531250 +vt 0.062500 0.531250 +vt 0.062500 0.625000 +vt 0.015625 0.640625 +vt 0.031250 0.640625 +vt 0.046875 0.625000 +vt 0.046875 0.640625 +vt 0.031250 0.640625 +vt 0.031250 0.625000 +vt 0.000000 0.625000 +vt 0.000000 0.531250 +vt 0.015625 0.625000 +vt 0.015625 0.531250 +vt 0.031250 0.531250 +vt 0.031250 0.625000 +vt 0.046875 0.625000 +vt 0.046875 0.531250 +vt 0.062500 0.531250 +vt 0.062500 0.625000 +vt 0.015625 0.640625 +vt 0.031250 0.640625 +vt 0.046875 0.625000 +vt 0.046875 0.640625 +vt 0.031250 0.640625 +vt 0.031250 0.625000 +vt 0.000000 0.625000 +vt 0.000000 0.531250 +vt 0.421875 0.515625 +vt 0.421875 0.500000 +vt 0.453125 0.500000 +vt 0.453125 0.515625 +vt 0.484375 0.515625 +vt 0.484375 0.500000 +vt 0.515625 0.500000 +vt 0.515625 0.515625 +vt 0.421875 0.546875 +vt 0.453125 0.546875 +vt 0.484375 0.515625 +vt 0.484375 0.546875 +vt 0.453125 0.546875 +vt 0.453125 0.515625 +vt 0.390625 0.515625 +vt 0.390625 0.500000 +vt 0.546875 0.515625 +vt 0.546875 0.500000 +vt 0.562500 0.500000 +vt 0.562500 0.515625 +vt 0.578125 0.515625 +vt 0.578125 0.500000 +vt 0.593750 0.500000 +vt 0.593750 0.515625 +vt 0.546875 0.531250 +vt 0.562500 0.531250 +vt 0.578125 0.515625 +vt 0.578125 0.531250 +vt 0.562500 0.531250 +vt 0.562500 0.515625 +vt 0.531250 0.515625 +vt 0.531250 0.500000 +vt 0.625000 0.515625 +vt 0.625000 0.500000 +vt 0.656250 0.500000 +vt 0.656250 0.515625 +vt 0.671875 0.515625 +vt 0.671875 0.500000 +vt 0.703125 0.500000 +vt 0.703125 0.515625 +vt 0.625000 0.531250 +vt 0.656250 0.531250 +vt 0.687500 0.515625 +vt 0.687500 0.531250 +vt 0.656250 0.531250 +vt 0.656250 0.515625 +vt 0.609375 0.515625 +vt 0.609375 0.500000 +vt 0.750000 0.515625 +vt 0.750000 0.500000 +vt 0.765625 0.500000 +vt 0.765625 0.515625 +vt 0.796875 0.515625 +vt 0.796875 0.500000 +vt 0.812500 0.500000 +vt 0.812500 0.515625 +vt 0.750000 0.546875 +vt 0.765625 0.546875 +vt 0.781250 0.515625 +vt 0.781250 0.546875 +vt 0.765625 0.546875 +vt 0.765625 0.515625 +vt 0.718750 0.515625 +vt 0.718750 0.500000 +vt 0.625000 0.562500 +vt 0.625000 0.546875 +vt 0.656250 0.546875 +vt 0.656250 0.562500 +vt 0.671875 0.562500 +vt 0.671875 0.546875 +vt 0.703125 0.546875 +vt 0.703125 0.562500 +vt 0.625000 0.578125 +vt 0.656250 0.578125 +vt 0.687500 0.562500 +vt 0.687500 0.578125 +vt 0.656250 0.578125 +vt 0.656250 0.562500 +vt 0.609375 0.562500 +vt 0.609375 0.546875 +vt 0.750000 0.578125 +vt 0.750000 0.562500 +vt 0.765625 0.562500 +vt 0.765625 0.578125 +vt 0.796875 0.578125 +vt 0.796875 0.562500 +vt 0.812500 0.562500 +vt 0.812500 0.578125 +vt 0.750000 0.609375 +vt 0.765625 0.609375 +vt 0.781250 0.578125 +vt 0.781250 0.609375 +vt 0.765625 0.609375 +vt 0.765625 0.578125 +vt 0.718750 0.578125 +vt 0.718750 0.562500 +vt 0.015625 0.625000 +vt 0.015625 0.531250 +vt 0.031250 0.531250 +vt 0.031250 0.625000 +vt 0.046875 0.625000 +vt 0.046875 0.531250 +vt 0.062500 0.531250 +vt 0.062500 0.625000 +vt 0.015625 0.640625 +vt 0.031250 0.640625 +vt 0.046875 0.625000 +vt 0.046875 0.640625 +vt 0.031250 0.640625 +vt 0.031250 0.625000 +vt 0.000000 0.625000 +vt 0.000000 0.531250 +vt 0.015625 0.625000 +vt 0.015625 0.531250 +vt 0.031250 0.531250 +vt 0.031250 0.625000 +vt 0.046875 0.625000 +vt 0.046875 0.531250 +vt 0.062500 0.531250 +vt 0.062500 0.625000 +vt 0.015625 0.640625 +vt 0.031250 0.640625 +vt 0.046875 0.625000 +vt 0.046875 0.640625 +vt 0.031250 0.640625 +vt 0.031250 0.625000 +vt 0.000000 0.625000 +vt 0.000000 0.531250 +vt 0.015625 0.625000 +vt 0.015625 0.531250 +vt 0.031250 0.531250 +vt 0.031250 0.625000 +vt 0.046875 0.625000 +vt 0.046875 0.531250 +vt 0.062500 0.531250 +vt 0.062500 0.625000 +vt 0.015625 0.640625 +vt 0.031250 0.640625 +vt 0.046875 0.625000 +vt 0.046875 0.640625 +vt 0.031250 0.640625 +vt 0.031250 0.625000 +vt 0.000000 0.625000 +vt 0.000000 0.531250 +vt 0.015625 0.625000 +vt 0.015625 0.531250 +vt 0.031250 0.531250 +vt 0.031250 0.625000 +vt 0.046875 0.625000 +vt 0.046875 0.531250 +vt 0.062500 0.531250 +vt 0.062500 0.625000 +vt 0.015625 0.640625 +vt 0.031250 0.640625 +vt 0.046875 0.625000 +vt 0.046875 0.640625 +vt 0.031250 0.640625 +vt 0.031250 0.625000 +vt 0.000000 0.625000 +vt 0.000000 0.531250 +vt 0.421875 0.515625 +vt 0.421875 0.500000 +vt 0.453125 0.500000 +vt 0.453125 0.515625 +vt 0.484375 0.515625 +vt 0.484375 0.500000 +vt 0.515625 0.500000 +vt 0.515625 0.515625 +vt 0.421875 0.546875 +vt 0.453125 0.546875 +vt 0.484375 0.515625 +vt 0.484375 0.546875 +vt 0.453125 0.546875 +vt 0.453125 0.515625 +vt 0.390625 0.515625 +vt 0.390625 0.500000 +vt 0.546875 0.515625 +vt 0.546875 0.500000 +vt 0.562500 0.500000 +vt 0.562500 0.515625 +vt 0.578125 0.515625 +vt 0.578125 0.500000 +vt 0.593750 0.500000 +vt 0.593750 0.515625 +vt 0.546875 0.531250 +vt 0.562500 0.531250 +vt 0.578125 0.515625 +vt 0.578125 0.531250 +vt 0.562500 0.531250 +vt 0.562500 0.515625 +vt 0.531250 0.515625 +vt 0.531250 0.500000 +vt 0.625000 0.515625 +vt 0.625000 0.500000 +vt 0.656250 0.500000 +vt 0.656250 0.515625 +vt 0.671875 0.515625 +vt 0.671875 0.500000 +vt 0.703125 0.500000 +vt 0.703125 0.515625 +vt 0.625000 0.531250 +vt 0.656250 0.531250 +vt 0.687500 0.515625 +vt 0.687500 0.531250 +vt 0.656250 0.531250 +vt 0.656250 0.515625 +vt 0.609375 0.515625 +vt 0.609375 0.500000 +vt 0.750000 0.515625 +vt 0.750000 0.500000 +vt 0.765625 0.500000 +vt 0.765625 0.515625 +vt 0.796875 0.515625 +vt 0.796875 0.500000 +vt 0.812500 0.500000 +vt 0.812500 0.515625 +vt 0.750000 0.546875 +vt 0.765625 0.546875 +vt 0.781250 0.515625 +vt 0.781250 0.546875 +vt 0.765625 0.546875 +vt 0.765625 0.515625 +vt 0.718750 0.515625 +vt 0.718750 0.500000 +vt 0.625000 0.562500 +vt 0.625000 0.546875 +vt 0.656250 0.546875 +vt 0.656250 0.562500 +vt 0.671875 0.562500 +vt 0.671875 0.546875 +vt 0.703125 0.546875 +vt 0.703125 0.562500 +vt 0.625000 0.578125 +vt 0.656250 0.578125 +vt 0.687500 0.562500 +vt 0.687500 0.578125 +vt 0.656250 0.578125 +vt 0.656250 0.562500 +vt 0.609375 0.562500 +vt 0.609375 0.546875 +vt 0.750000 0.578125 +vt 0.750000 0.562500 +vt 0.765625 0.562500 +vt 0.765625 0.578125 +vt 0.796875 0.578125 +vt 0.796875 0.562500 +vt 0.812500 0.562500 +vt 0.812500 0.578125 +vt 0.750000 0.609375 +vt 0.765625 0.609375 +vt 0.781250 0.578125 +vt 0.781250 0.609375 +vt 0.765625 0.609375 +vt 0.765625 0.578125 +vt 0.718750 0.578125 +vt 0.718750 0.562500 +vt 0.546875 0.515625 +vt 0.546875 0.500000 +vt 0.562500 0.500000 +vt 0.562500 0.515625 +vt 0.578125 0.515625 +vt 0.578125 0.500000 +vt 0.593750 0.500000 +vt 0.593750 0.515625 +vt 0.546875 0.531250 +vt 0.562500 0.531250 +vt 0.578125 0.515625 +vt 0.578125 0.531250 +vt 0.562500 0.531250 +vt 0.562500 0.515625 +vt 0.531250 0.515625 +vt 0.531250 0.500000 +vn 0.0000 0.0000 1.0000 +vn 0.0000 0.0000 -1.0000 +vn 0.0000 1.0000 0.0000 +vn 0.0000 -1.0000 -0.0000 +vn 1.0000 0.0000 0.0000 +vn -1.0000 0.0000 0.0000 +vn 0.2249 0.9744 0.0000 +vn -0.2249 -0.9744 -0.0000 +vn 0.9744 -0.2249 0.0000 +vn -0.9744 0.2249 0.0000 +vn 0.0000 -0.2249 0.9744 +vn 0.0000 0.2249 -0.9744 +vn 0.0000 0.9744 0.2249 +vn 0.0000 -0.9744 -0.2249 +vn 0.0000 0.2249 0.9744 +vn 0.0000 -0.2249 -0.9744 +vn 0.0000 0.9744 -0.2249 +vn 0.0000 -0.9744 0.2249 +vn -0.2249 0.9744 0.0000 +vn 0.2249 -0.9744 -0.0000 +vn 0.9744 0.2249 0.0000 +vn -0.9744 -0.2249 0.0000 +usemtl None.001 +s 1 +f 1/1/1 2/2/1 3/3/1 4/4/1 +f 5/5/2 6/6/2 7/7/2 8/8/2 +f 8/9/3 1/1/3 4/4/3 5/10/3 +f 2/11/4 7/12/4 6/13/4 3/14/4 +f 5/5/5 4/4/5 3/3/5 6/6/5 +f 8/15/6 7/16/6 2/2/6 1/1/6 +f 9/17/1 10/18/1 11/19/1 12/20/1 +f 13/21/2 14/22/2 15/23/2 16/24/2 +f 16/25/7 9/17/7 12/20/7 13/26/7 +f 10/27/8 15/28/8 14/29/8 11/30/8 +f 13/21/9 12/20/9 11/19/9 14/22/9 +f 16/31/10 15/32/10 10/18/10 9/17/10 +f 17/33/11 18/34/11 19/35/11 20/36/11 +f 21/37/12 22/38/12 23/39/12 24/40/12 +f 24/41/13 17/33/13 20/36/13 21/42/13 +f 18/43/14 23/44/14 22/45/14 19/46/14 +f 21/37/5 20/36/5 19/35/5 22/38/5 +f 24/47/6 23/48/6 18/34/6 17/33/6 +f 25/49/15 26/50/15 27/51/15 28/52/15 +f 29/53/16 30/54/16 31/55/16 32/56/16 +f 32/57/17 25/49/17 28/52/17 29/58/17 +f 26/59/18 31/60/18 30/61/18 27/62/18 +f 29/53/5 28/52/5 27/51/5 30/54/5 +f 32/63/6 31/64/6 26/50/6 25/49/6 +f 33/65/1 34/66/1 35/67/1 36/68/1 +f 37/69/2 38/70/2 39/71/2 40/72/2 +f 40/73/19 33/65/19 36/68/19 37/74/19 +f 34/75/20 39/76/20 38/77/20 35/78/20 +f 37/69/21 36/68/21 35/67/21 38/70/21 +f 40/79/22 39/80/22 34/66/22 33/65/22 +f 41/81/1 42/82/1 43/83/1 44/84/1 +f 45/85/2 46/86/2 47/87/2 48/88/2 +f 48/89/3 41/81/3 44/84/3 45/90/3 +f 42/91/4 47/92/4 46/93/4 43/94/4 +f 45/85/5 44/84/5 43/83/5 46/86/5 +f 48/95/6 47/96/6 42/82/6 41/81/6 +f 49/97/1 50/98/1 51/99/1 52/100/1 +f 53/101/2 54/102/2 55/103/2 56/104/2 +f 56/105/3 49/97/3 52/100/3 53/106/3 +f 50/107/4 55/108/4 54/109/4 51/110/4 +f 53/101/5 52/100/5 51/99/5 54/102/5 +f 56/111/6 55/112/6 50/98/6 49/97/6 +f 57/113/1 58/114/1 59/115/1 60/116/1 +f 61/117/2 62/118/2 63/119/2 64/120/2 +f 64/121/3 57/113/3 60/116/3 61/122/3 +f 58/123/4 63/124/4 62/125/4 59/126/4 +f 61/117/5 60/116/5 59/115/5 62/118/5 +f 64/127/6 63/128/6 58/114/6 57/113/6 +f 65/129/1 66/130/1 67/131/1 68/132/1 +f 69/133/2 70/134/2 71/135/2 72/136/2 +f 72/137/3 65/129/3 68/132/3 69/138/3 +f 66/139/4 71/140/4 70/141/4 67/142/4 +f 69/133/5 68/132/5 67/131/5 70/134/5 +f 72/143/6 71/144/6 66/130/6 65/129/6 +f 73/145/1 74/146/1 75/147/1 76/148/1 +f 77/149/2 78/150/2 79/151/2 80/152/2 +f 80/153/3 73/145/3 76/148/3 77/154/3 +f 74/155/4 79/156/4 78/157/4 75/158/4 +f 77/149/5 76/148/5 75/147/5 78/150/5 +f 80/159/6 79/160/6 74/146/6 73/145/6 +f 81/161/1 82/162/1 83/163/1 84/164/1 +f 85/165/2 86/166/2 87/167/2 88/168/2 +f 88/169/3 81/161/3 84/164/3 85/170/3 +f 82/171/4 87/172/4 86/173/4 83/174/4 +f 85/165/5 84/164/5 83/163/5 86/166/5 +f 88/175/6 87/176/6 82/162/6 81/161/6 +f 89/177/1 90/178/1 91/179/1 92/180/1 +f 93/181/2 94/182/2 95/183/2 96/184/2 +f 96/185/7 89/177/7 92/180/7 93/186/7 +f 90/187/8 95/188/8 94/189/8 91/190/8 +f 93/181/9 92/180/9 91/179/9 94/182/9 +f 96/191/10 95/192/10 90/178/10 89/177/10 +f 97/193/11 98/194/11 99/195/11 100/196/11 +f 101/197/12 102/198/12 103/199/12 104/200/12 +f 104/201/13 97/193/13 100/196/13 101/202/13 +f 98/203/14 103/204/14 102/205/14 99/206/14 +f 101/197/5 100/196/5 99/195/5 102/198/5 +f 104/207/6 103/208/6 98/194/6 97/193/6 +f 105/209/15 106/210/15 107/211/15 108/212/15 +f 109/213/16 110/214/16 111/215/16 112/216/16 +f 112/217/17 105/209/17 108/212/17 109/218/17 +f 106/219/18 111/220/18 110/221/18 107/222/18 +f 109/213/5 108/212/5 107/211/5 110/214/5 +f 112/223/6 111/224/6 106/210/6 105/209/6 +f 113/225/1 114/226/1 115/227/1 116/228/1 +f 117/229/2 118/230/2 119/231/2 120/232/2 +f 120/233/19 113/225/19 116/228/19 117/234/19 +f 114/235/20 119/236/20 118/237/20 115/238/20 +f 117/229/21 116/228/21 115/227/21 118/230/21 +f 120/239/22 119/240/22 114/226/22 113/225/22 +f 121/241/1 122/242/1 123/243/1 124/244/1 +f 125/245/2 126/246/2 127/247/2 128/248/2 +f 128/249/3 121/241/3 124/244/3 125/250/3 +f 122/251/4 127/252/4 126/253/4 123/254/4 +f 125/245/5 124/244/5 123/243/5 126/246/5 +f 128/255/6 127/256/6 122/242/6 121/241/6 +f 129/257/1 130/258/1 131/259/1 132/260/1 +f 133/261/2 134/262/2 135/263/2 136/264/2 +f 136/265/3 129/257/3 132/260/3 133/266/3 +f 130/267/4 135/268/4 134/269/4 131/270/4 +f 133/261/5 132/260/5 131/259/5 134/262/5 +f 136/271/6 135/272/6 130/258/6 129/257/6 +f 137/273/1 138/274/1 139/275/1 140/276/1 +f 141/277/2 142/278/2 143/279/2 144/280/2 +f 144/281/3 137/273/3 140/276/3 141/282/3 +f 138/283/4 143/284/4 142/285/4 139/286/4 +f 141/277/5 140/276/5 139/275/5 142/278/5 +f 144/287/6 143/288/6 138/274/6 137/273/6 +f 145/289/1 146/290/1 147/291/1 148/292/1 +f 149/293/2 150/294/2 151/295/2 152/296/2 +f 152/297/3 145/289/3 148/292/3 149/298/3 +f 146/299/4 151/300/4 150/301/4 147/302/4 +f 149/293/5 148/292/5 147/291/5 150/294/5 +f 152/303/6 151/304/6 146/290/6 145/289/6 +f 153/305/1 154/306/1 155/307/1 156/308/1 +f 157/309/2 158/310/2 159/311/2 160/312/2 +f 160/313/3 153/305/3 156/308/3 157/314/3 +f 154/315/4 159/316/4 158/317/4 155/318/4 +f 157/309/5 156/308/5 155/307/5 158/310/5 +f 160/319/6 159/320/6 154/306/6 153/305/6 +f 161/321/1 162/322/1 163/323/1 164/324/1 +f 165/325/2 166/326/2 167/327/2 168/328/2 +f 168/329/3 161/321/3 164/324/3 165/330/3 +f 162/331/4 167/332/4 166/333/4 163/334/4 +f 165/325/5 164/324/5 163/323/5 166/326/5 +f 168/335/6 167/336/6 162/322/6 161/321/6 +f 169/337/1 170/338/1 171/339/1 172/340/1 +f 173/341/2 174/342/2 175/343/2 176/344/2 +f 176/345/3 169/337/3 172/340/3 173/346/3 +f 170/347/4 175/348/4 174/349/4 171/350/4 +f 173/341/5 172/340/5 171/339/5 174/342/5 +f 176/351/6 175/352/6 170/338/6 169/337/6 +o ModelRoutingNodeCore +v 0.375000 0.625000 0.625000 +v 0.375000 0.375000 0.625000 +v 0.625000 0.375000 0.625000 +v 0.625000 0.625000 0.625000 +v 0.625000 0.625000 0.375000 +v 0.625000 0.375000 0.375000 +v 0.375000 0.375000 0.375000 +v 0.375000 0.625000 0.375000 +v 0.437500 0.562500 0.562500 +v 0.437500 0.437500 0.562500 +v 0.562500 0.437500 0.562500 +v 0.562500 0.562500 0.562500 +v 0.562500 0.562500 0.437500 +v 0.562500 0.437500 0.437500 +v 0.437500 0.437500 0.437500 +v 0.437500 0.562500 0.437500 +vt 0.062500 0.937500 +vt 0.062500 0.875000 +vt 0.125000 0.875000 +vt 0.125000 0.937500 +vt 0.187500 0.937500 +vt 0.187500 0.875000 +vt 0.250000 0.875000 +vt 0.250000 0.937500 +vt 0.062500 1.000000 +vt 0.125000 1.000000 +vt 0.187500 0.937500 +vt 0.187500 1.000000 +vt 0.125000 1.000000 +vt 0.125000 0.937500 +vt 0.000000 0.937500 +vt 0.000000 0.875000 +vt 0.031250 0.796875 +vt 0.031250 0.765625 +vt 0.062500 0.765625 +vt 0.062500 0.796875 +vt 0.093750 0.796875 +vt 0.093750 0.765625 +vt 0.125000 0.765625 +vt 0.125000 0.796875 +vt 0.031250 0.828125 +vt 0.062500 0.828125 +vt 0.093750 0.796875 +vt 0.093750 0.828125 +vt 0.062500 0.828125 +vt 0.062500 0.796875 +vt 0.000000 0.796875 +vt 0.000000 0.765625 +vn 0.0000 -0.0000 1.0000 +vn 0.0000 0.0000 -1.0000 +vn 0.0000 1.0000 0.0000 +vn 0.0000 -1.0000 -0.0000 +vn 1.0000 0.0000 0.0000 +vn -1.0000 0.0000 0.0000 +usemtl None.002 +s 1 +f 177/353/23 178/354/23 179/355/23 180/356/23 +f 181/357/24 182/358/24 183/359/24 184/360/24 +f 184/361/25 177/353/25 180/356/25 181/362/25 +f 178/363/26 183/364/26 182/365/26 179/366/26 +f 181/357/27 180/356/27 179/355/27 182/358/27 +f 184/367/28 183/368/28 178/354/28 177/353/28 +f 185/369/23 186/370/23 187/371/23 188/372/23 +f 189/373/24 190/374/24 191/375/24 192/376/24 +f 192/377/25 185/369/25 188/372/25 189/378/25 +f 186/379/26 191/380/26 190/381/26 187/382/26 +f 189/373/27 188/372/27 187/371/27 190/374/27 +f 192/383/28 191/384/28 186/370/28 185/369/28 diff --git a/src/main/resources/assets/bloodmagic/models/block/routing/modelroutingnodecore.mtl b/src/main/resources/assets/bloodmagic/models/block/routing/modelroutingnodecore.mtl new file mode 100755 index 0000000000..26d04038de --- /dev/null +++ b/src/main/resources/assets/bloodmagic/models/block/routing/modelroutingnodecore.mtl @@ -0,0 +1,11 @@ +# Blender MTL File: 'None' +# Material Count: 1 + +newmtl None +#Ns 0 +Ka 0.000000 0.000000 0.000000 +Kd 0.8 0.8 0.8 +#Ks 0.8 0.8 0.8 +d 1 +#illum 2 +map_Kd #core \ No newline at end of file diff --git a/src/main/resources/assets/bloodmagic/models/block/routing/modelroutingnodecore.obj b/src/main/resources/assets/bloodmagic/models/block/routing/modelroutingnodecore.obj new file mode 100755 index 0000000000..4484ec38a7 --- /dev/null +++ b/src/main/resources/assets/bloodmagic/models/block/routing/modelroutingnodecore.obj @@ -0,0 +1,66 @@ +# Blender v2.76 (sub 0) OBJ File: '' +# www.blender.org +mtllib modelroutingnodecore.mtl +o ModelRoutingNodeCore +v 0.375000 0.625000 0.625000 +v 0.375000 0.375000 0.625000 +v 0.625000 0.375000 0.625000 +v 0.625000 0.625000 0.625000 +v 0.625000 0.625000 0.375000 +v 0.625000 0.375000 0.375000 +v 0.375000 0.375000 0.375000 +v 0.375000 0.625000 0.375000 +v 0.437500 0.562500 0.562500 +v 0.437500 0.437500 0.562500 +v 0.562500 0.437500 0.562500 +v 0.562500 0.562500 0.562500 +v 0.562500 0.562500 0.437500 +v 0.562500 0.437500 0.437500 +v 0.437500 0.437500 0.437500 +v 0.437500 0.562500 0.437500 +vt 0.062500 0.937500 +vt 0.062500 0.875000 +vt 0.125000 0.875000 +vt 0.125000 0.937500 +vt 0.187500 0.937500 +vt 0.187500 0.875000 +vt 0.250000 0.875000 +vt 0.250000 0.937500 +vt 0.062500 1.000000 +vt 0.125000 1.000000 +vt 0.187500 1.000000 +vt 0.000000 0.937500 +vt 0.000000 0.875000 +vt 0.031250 0.796875 +vt 0.031250 0.765625 +vt 0.062500 0.765625 +vt 0.062500 0.796875 +vt 0.093750 0.796875 +vt 0.093750 0.765625 +vt 0.125000 0.765625 +vt 0.125000 0.796875 +vt 0.031250 0.828125 +vt 0.062500 0.828125 +vt 0.093750 0.828125 +vt 0.000000 0.796875 +vt 0.000000 0.765625 +vn 0.000000 -0.000000 1.000000 +vn 0.000000 0.000000 -1.000000 +vn 0.000000 1.000000 0.000000 +vn 0.000000 -1.000000 -0.000000 +vn 1.000000 0.000000 0.000000 +vn -1.000000 0.000000 0.000000 +usemtl None +#s 1 +f 1/1/1 2/2/1 3/3/1 4/4/1 +f 5/5/2 6/6/2 7/7/2 8/8/2 +f 8/9/3 1/1/3 4/4/3 5/10/3 +f 2/5/4 7/11/4 6/10/4 3/4/4 +f 5/5/5 4/4/5 3/3/5 6/6/5 +f 8/12/6 7/13/6 2/2/6 1/1/6 +f 9/14/1 10/15/1 11/16/1 12/17/1 +f 13/18/2 14/19/2 15/20/2 16/21/2 +f 16/22/3 9/14/3 12/17/3 13/23/3 +f 10/18/4 15/24/4 14/23/4 11/17/4 +f 13/18/5 12/17/5 11/16/5 14/19/5 +f 16/25/6 15/26/6 10/15/6 9/14/6 diff --git a/src/main/resources/assets/bloodmagic/models/block/routing_node_base.json b/src/main/resources/assets/bloodmagic/models/block/routing_node_base.json new file mode 100755 index 0000000000..7e856e14c5 --- /dev/null +++ b/src/main/resources/assets/bloodmagic/models/block/routing_node_base.json @@ -0,0 +1,10 @@ +{ + "parent": "block/block", + "loader": "neoforge:obj", + "flip_v": true, + "model": "bloodmagic:models/block/routing/modelroutingnodebase.obj", + "textures": { + "base": "bloodmagic:block/routing_node", + "particle": "#base" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/bloodmagic/models/block/routing_node_base_input.json b/src/main/resources/assets/bloodmagic/models/block/routing_node_base_input.json new file mode 100644 index 0000000000..f395756933 --- /dev/null +++ b/src/main/resources/assets/bloodmagic/models/block/routing_node_base_input.json @@ -0,0 +1,6 @@ +{ + "parent": "bloodmagic:block/routing_node_base", + "textures": { + "base": "bloodmagic:block/routing_node_input" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/bloodmagic/models/block/routing_node_base_master.json b/src/main/resources/assets/bloodmagic/models/block/routing_node_base_master.json new file mode 100755 index 0000000000..5efb673e7a --- /dev/null +++ b/src/main/resources/assets/bloodmagic/models/block/routing_node_base_master.json @@ -0,0 +1,10 @@ +{ + "parent": "block/block", + "loader": "neoforge:obj", + "flip_v": true, + "model": "bloodmagic:models/block/routing/modelmasterroutingnodebase.obj", + "textures": { + "base": "bloodmagic:block/routing_node_master", + "particle": "#base" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/bloodmagic/models/block/routing_node_base_output.json b/src/main/resources/assets/bloodmagic/models/block/routing_node_base_output.json new file mode 100644 index 0000000000..d5bc5847cd --- /dev/null +++ b/src/main/resources/assets/bloodmagic/models/block/routing_node_base_output.json @@ -0,0 +1,6 @@ +{ + "parent": "bloodmagic:block/routing_node_base", + "textures": { + "base": "bloodmagic:block/routing_node_output" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/bloodmagic/models/block/routing_node_core.json b/src/main/resources/assets/bloodmagic/models/block/routing_node_core.json new file mode 100755 index 0000000000..fbd7a2735f --- /dev/null +++ b/src/main/resources/assets/bloodmagic/models/block/routing_node_core.json @@ -0,0 +1,11 @@ +{ + "parent": "block/block", + "render_type": "minecraft:translucent", + "loader": "neoforge:obj", + "flip_v": true, + "model": "bloodmagic:models/block/routing/modelroutingnodecore.obj", + "textures": { + "core": "bloodmagic:block/routing_node", + "particle": "#core" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/bloodmagic/models/block/routing_node_core_input.json b/src/main/resources/assets/bloodmagic/models/block/routing_node_core_input.json new file mode 100644 index 0000000000..5d9b20f08a --- /dev/null +++ b/src/main/resources/assets/bloodmagic/models/block/routing_node_core_input.json @@ -0,0 +1,6 @@ +{ + "parent": "bloodmagic:block/routing_node_core", + "textures": { + "core": "bloodmagic:block/routing_node_input" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/bloodmagic/models/block/routing_node_core_master.json b/src/main/resources/assets/bloodmagic/models/block/routing_node_core_master.json new file mode 100755 index 0000000000..46b2962a83 --- /dev/null +++ b/src/main/resources/assets/bloodmagic/models/block/routing_node_core_master.json @@ -0,0 +1,11 @@ +{ + "parent": "block/block", + "render_type": "minecraft:translucent", + "loader": "neoforge:obj", + "flip_v": true, + "model": "bloodmagic:models/block/routing/modelmasterroutingnodecore.obj", + "textures": { + "core": "bloodmagic:block/routing_node_master", + "particle": "#core" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/bloodmagic/models/block/routing_node_core_output.json b/src/main/resources/assets/bloodmagic/models/block/routing_node_core_output.json new file mode 100644 index 0000000000..e6d0973f8d --- /dev/null +++ b/src/main/resources/assets/bloodmagic/models/block/routing_node_core_output.json @@ -0,0 +1,6 @@ +{ + "parent": "bloodmagic:block/routing_node_core", + "textures": { + "core": "bloodmagic:block/routing_node_output" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/bloodmagic/models/item/routing_node.json b/src/main/resources/assets/bloodmagic/models/item/routing_node.json new file mode 100755 index 0000000000..b955503307 --- /dev/null +++ b/src/main/resources/assets/bloodmagic/models/item/routing_node.json @@ -0,0 +1,11 @@ +{ + "parent": "block/block", + "loader": "neoforge:obj", + "flip_v": true, + "model": "bloodmagic:models/block/routing/modelroutingnodecombined.obj", + "textures": { + "core": "bloodmagic:block/routing_node", + "base": "bloodmagic:block/routing_node", + "particle": "#core" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/bloodmagic/models/item/routing_node_input.json b/src/main/resources/assets/bloodmagic/models/item/routing_node_input.json new file mode 100644 index 0000000000..ab727ff1e2 --- /dev/null +++ b/src/main/resources/assets/bloodmagic/models/item/routing_node_input.json @@ -0,0 +1,7 @@ +{ + "parent": "bloodmagic:item/routing_node", + "textures": { + "core": "bloodmagic:block/routing_node_input", + "base": "bloodmagic:block/routing_node_input" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/bloodmagic/models/item/routing_node_master.json b/src/main/resources/assets/bloodmagic/models/item/routing_node_master.json new file mode 100755 index 0000000000..67598ea114 --- /dev/null +++ b/src/main/resources/assets/bloodmagic/models/item/routing_node_master.json @@ -0,0 +1,11 @@ +{ + "parent": "block/block", + "loader": "neoforge:obj", + "flip_v": true, + "model": "bloodmagic:models/block/routing/modelmasterroutingnodecombined.obj", + "textures": { + "core": "bloodmagic:block/routing_node_master", + "base": "bloodmagic:block/routing_node_master", + "particle": "#core" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/bloodmagic/models/item/routing_node_output.json b/src/main/resources/assets/bloodmagic/models/item/routing_node_output.json new file mode 100644 index 0000000000..b32a47d1c8 --- /dev/null +++ b/src/main/resources/assets/bloodmagic/models/item/routing_node_output.json @@ -0,0 +1,7 @@ +{ + "parent": "bloodmagic:item/routing_node", + "textures": { + "core": "bloodmagic:block/routing_node_output", + "base": "bloodmagic:block/routing_node_output" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/bloodmagic/textures/block/crystal_corrosive.png b/src/main/resources/assets/bloodmagic/textures/block/crystal_corrosive.png new file mode 100755 index 0000000000000000000000000000000000000000..27f6c52b86d51794c857c727b40ad2d344dd317a GIT binary patch literal 748 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 Q4gdfE07*qoM6N<$f}gia_y7O^ literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/bloodmagic/textures/block/crystal_vengeful.png b/src/main/resources/assets/bloodmagic/textures/block/crystal_vengeful.png new file mode 100755 index 0000000000000000000000000000000000000000..5f70782552f9056a8c51ecc3290a56823d0fb971 GIT binary patch literal 737 zcmV<70v`Q|P)D+r9>D>_X;f1H000McNliru-~${E9U6~so4Ei00&Yn} zK~y-)J&{Y2BSjPhJ%5!|s*xF5a@J>VN{CEa}bV?a0=ZH#ky<(zB4Tg`PL>b&6gstzT2B~bFunh8R$o5BG(k!qJx$nU=K9ay zNXSf=6WFU8GbZ8()Nlj2>E@cM*00JLLL_t(I%axN$ZyQMr zgg>%-JdPY-;~ewzbII8VlKh+v5FkJvvaEUZJi1BlL4tf<-UAboP9CT+V_`HJpa{xfM?4IPMA>G_HuCfMFQ1;CF0}u5 z*u2rD9zoFnvh+8SJr;;S$Sgjf(vkI^c^lbmX19fPFErn2*2pSK^GcSU#a~b|S?@Ww zzgSdMI>vpV)HAq32!SIa;p?3v8Wi1 zMUW$cPTw-wkwbc<*hsMv$N9DVz-mRK!@UBKQlhq>?a4DB}- zhSO-i^CmqaD5ak1^MNEC@9sWO?8M$yy42ImP{%2DrqWn^pll-#`kvJmhUJK=q6%H= znd^zQ&bMolCbFWK8HF=$fkb9&g>(5ylAee3NZ?HM#M&nMe86dxWk!UHks<;!qqd!9 zmGg3>*2x`Kp zDr5xKy0L9Dd)@FVs3iJ)U?|VbZ9pQ(dPj{)62aYHW&Ql+GoPM5q9V5td-x5T+r>bt h1c3*rKzI-V{{gFxrY%u;D}Mk0002ovPDHLkV1kO-D!Tvx literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/bloodmagic/textures/block/hellforged_block.png b/src/main/resources/assets/bloodmagic/textures/block/hellforged_default.png old mode 100644 new mode 100755 similarity index 100% rename from src/main/resources/assets/bloodmagic/textures/block/hellforged_block.png rename to src/main/resources/assets/bloodmagic/textures/block/hellforged_default.png diff --git a/src/main/resources/assets/bloodmagic/textures/block/hellforged_destructive.png b/src/main/resources/assets/bloodmagic/textures/block/hellforged_destructive.png new file mode 100755 index 0000000000000000000000000000000000000000..6ca45881b3eaa45704ee69d0f9ec08122e979eeb GIT binary patch literal 698 zcmV;r0!96aP)WFU8GbZ8()Nlj2>E@cM*00JIKL_t(I%axPMuGByb zM33E_WbOdsu|eYVVa?(S0iOdB2q9o5uSqgVx7#c-TvjaTjnxa6%T;ArKYw*X;GeIQ zy{hij9YnyLj~_k|2?2`Z(-nDiz^4_r3^{`esA8uRZjOh*I*qL3%<0o7?(g5Cz<)QF zoCwVURCWMq>KjOdFIU_P#6THFq^i(E%{mU)v|!7^HqVr8!*V8y3MD0^sVUt6QPIPJ z{OgRTgj9iT7)kv|QNaZ$jtGPhQ5@{l;we!sGt$&p+u_R<3D##7pL z^MblN`uK>QTEg>Zl*@#TGj56H%NMrGgjW@%WB@`C+zbf{2ob=|(8ov0b)j@4W#}LI$m)1UBvw3jGJLU&$uOu3OQ$p5ff)^`#l5M(8DftzOIB2b^vm^ zfh5RI*%IOTGf*M*1Mzr=R2B8BmsmUO%}tG2MkxjBd&r40%&g;pzIci)3(KiPRZ*1C z)TFi}P19dCArMi;tU$l-?J<()EAzMSNK@}jijmr$e3^*HJIKZ|O$fIjxr13DZwX6@ z<#Z;cgdXnpVcoC?%#1Wnx6@F}?B;?S5b!E;?Rvb5R8OBEO(YKkYuh0r5BHU(88bsg zhytW_W1S|_x{(AV1mf|)eD27@xZ71%c*=+frIZI-01L3IG5A literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/bloodmagic/textures/block/hellforged_steadfast.png b/src/main/resources/assets/bloodmagic/textures/block/hellforged_steadfast.png new file mode 100755 index 0000000000000000000000000000000000000000..d6d52598bb6ab3b868d99334d23a52862c910ede GIT binary patch literal 738 zcmV<80v-K{P)WFU8GbZ8()Nlj2>E@cM*00KryL_t(I%Y~D>k`zY} zMNd{$KZYHo)nefA_XHtB9t8V0l0k$J5X?+>b$9ivvQkFxf;^>{#=Q}FPhR=_=f#}& zhzQSPWnYKEA_&uulIK=l>O#QfS(Mh~UhOs;O9~o%XI`P8(JVz7ob^!dF7o22xy@)55xJ zq-kc`GFg@2yreM}B!Ylj6eAPvkB0&!=ysG2w$F z>p=tO&|C=KBR~My_nr1!lTsq~1F;(^rl=~2;k-NW7HHal4~}U}7~lY|Uyc)Q-y$U! zaGo*U? zYhqnjnx-P>9aoAHZv$DCp`RFH;%AdUDPbU>qj)E%WmJ3_yRI z*rpv-Wg9lyQ-c#ZauN|t4fTptMt_~~mFIl_g1Yg)uyGF+Dz~#fi-;1Z1Vx<5OKD__H+qb_X@Uy~ZKX!etvpoI6&(Z_%FMFh> UcP-b?v;Y7A07*qoM6N<$g4JeENdN!< literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/bloodmagic/textures/block/hellforged_vengeful.png b/src/main/resources/assets/bloodmagic/textures/block/hellforged_vengeful.png new file mode 100755 index 0000000000000000000000000000000000000000..774c0e21baf690114678df7d518d25982632dccb GIT binary patch literal 692 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 D&y8#< literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/bloodmagic/textures/block/routing_node_input.png b/src/main/resources/assets/bloodmagic/textures/block/routing_node_input.png new file mode 100755 index 0000000000000000000000000000000000000000..12b9ffccb9ae5f26b78270247c575689c357e034 GIT binary patch literal 8922 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 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/bloodmagic/textures/block/routing_node_master.png b/src/main/resources/assets/bloodmagic/textures/block/routing_node_master.png new file mode 100755 index 0000000000000000000000000000000000000000..b861ffade9c01f4a1fa0895fa290b5cc8367e5bb GIT binary patch literal 2898 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 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/bloodmagic/textures/block/routing_node_output.png b/src/main/resources/assets/bloodmagic/textures/block/routing_node_output.png new file mode 100755 index 0000000000000000000000000000000000000000..9b6184711a3928fb388bce36bb8c99afb7eac92d GIT binary patch literal 8919 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 iCh5IW0f1k@f1(en0H}!4E&qN10000 Date: Fri, 7 Nov 2025 12:12:54 +0100 Subject: [PATCH 3/8] ill be back --- .../client/event/ClientEventHandler.java | 16 ++++++++++++++ .../datacomponent/BMDataComponents.java | 3 ++- .../common/item/NodeRouterItem.java | 22 ++++++++++++++++++- 3 files changed, 39 insertions(+), 2 deletions(-) diff --git a/src/main/java/wayoftime/bloodmagic/client/event/ClientEventHandler.java b/src/main/java/wayoftime/bloodmagic/client/event/ClientEventHandler.java index 35db49aae0..2eaff94df4 100644 --- a/src/main/java/wayoftime/bloodmagic/client/event/ClientEventHandler.java +++ b/src/main/java/wayoftime/bloodmagic/client/event/ClientEventHandler.java @@ -1,12 +1,16 @@ package wayoftime.bloodmagic.client.event; import net.minecraft.ChatFormatting; +import net.minecraft.core.BlockPos; +import net.minecraft.core.GlobalPos; import net.minecraft.core.component.DataComponentType; import net.minecraft.network.chat.Component; +import net.minecraft.resources.ResourceKey; import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.TooltipFlag; import net.minecraft.world.item.component.TooltipProvider; +import net.minecraft.world.level.Level; import net.neoforged.api.distmarker.Dist; import net.neoforged.bus.api.SubscribeEvent; import net.neoforged.fml.common.EventBusSubscriber; @@ -38,10 +42,22 @@ public static void onHoverText(ItemTooltipEvent event) { } addToTooltip(BMDataComponents.UPGRADES.get(), context, toAdd::add, flags, stack); + if (stack.has(BMDataComponents.STORED_POSITION)) { + GlobalPos storedPos = stack.get(BMDataComponents.STORED_POSITION); + toAdd.add(Component.translatable("tooltip.bloodmagic.stored_position", posString(storedPos.pos()), dimensionString(storedPos.dimension())).withStyle(ChatFormatting.GRAY)); + } + // add after name. idgaf tooltip.addAll(1, toAdd); } + private static String posString(BlockPos pos) { + return "%d, %d, %d".formatted(pos.getX(), pos.getY(), pos.getZ()); + } + + private static String dimensionString(ResourceKey dim) { + return "%s:%s".formatted(dim.location().getNamespace(), dim.location().getPath()); + } public static void addToTooltip( DataComponentType component, Item.TooltipContext context, Consumer tooltipAdder, TooltipFlag tooltipFlag, ItemStack stack diff --git a/src/main/java/wayoftime/bloodmagic/common/datacomponent/BMDataComponents.java b/src/main/java/wayoftime/bloodmagic/common/datacomponent/BMDataComponents.java index 4bf9583d05..64332ad90e 100644 --- a/src/main/java/wayoftime/bloodmagic/common/datacomponent/BMDataComponents.java +++ b/src/main/java/wayoftime/bloodmagic/common/datacomponent/BMDataComponents.java @@ -2,6 +2,7 @@ import com.mojang.serialization.Codec; import it.unimi.dsi.fastutil.objects.Object2FloatOpenHashMap; +import net.minecraft.core.GlobalPos; import net.minecraft.core.Holder; import net.minecraft.core.component.DataComponentType; import net.minecraft.core.registries.Registries; @@ -32,7 +33,7 @@ public class BMDataComponents { public static final DeferredHolder, DataComponentType> ARC_CHANCE = DATA_COMPONENTS.registerComponentType("arc_chance", builder -> builder.persistent(Codec.DOUBLE)); public static final DeferredHolder, DataComponentType> ARC_SPEED = DATA_COMPONENTS.registerComponentType("arc_speed", builder -> builder.persistent(Codec.DOUBLE)); - public static final DeferredHolder, DataComponentType> + public static final DeferredHolder, DataComponentType> STORED_POSITION = DATA_COMPONENTS.registerComponentType("stored_position", builder -> builder.persistent(GlobalPos.CODEC).networkSynchronized(GlobalPos.STREAM_CODEC)); public static final DeferredHolder, DataComponentType> CONTAINER_TIER = DATA_COMPONENTS.registerComponentType("container_tier", builder -> builder.persistent(Codec.INT).networkSynchronized(ByteBufCodecs.INT)); public static final DeferredHolder, DataComponentType> FLUID_CONTENT = DATA_COMPONENTS.registerComponentType("fluid_content", builder -> builder.persistent(SimpleFluidContent.CODEC).networkSynchronized(SimpleFluidContent.STREAM_CODEC)); diff --git a/src/main/java/wayoftime/bloodmagic/common/item/NodeRouterItem.java b/src/main/java/wayoftime/bloodmagic/common/item/NodeRouterItem.java index 65dd1cbef8..16e228d657 100644 --- a/src/main/java/wayoftime/bloodmagic/common/item/NodeRouterItem.java +++ b/src/main/java/wayoftime/bloodmagic/common/item/NodeRouterItem.java @@ -1,21 +1,41 @@ package wayoftime.bloodmagic.common.item; +import net.minecraft.core.GlobalPos; +import net.minecraft.network.chat.Component; +import net.minecraft.world.InteractionHand; import net.minecraft.world.InteractionResult; import net.minecraft.world.item.Item; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.TooltipFlag; import net.minecraft.world.item.context.UseOnContext; import wayoftime.bloodmagic.common.datacomponent.BMDataComponents; +import java.util.List; + public class NodeRouterItem extends Item { public NodeRouterItem() { super( new Properties().stacksTo(1) - .component(BMDataComponents.) ); } @Override public InteractionResult useOn(UseOnContext context) { + if (context.getHand() == InteractionHand.OFF_HAND) { + return InteractionResult.PASS; + } + ItemStack routerStack = context.getItemInHand(); + if (context.isSecondaryUseActive()) { + routerStack.remove(BMDataComponents.STORED_POSITION); + } else { + if (!routerStack.has(BMDataComponents.STORED_POSITION)) { + // first node, this is the parent + } else { + // second node, this is the child + } + } + return InteractionResult.PASS; } } From c5b40bb76c9294881b960cf651b8794c12a47e9d Mon Sep 17 00:00:00 2001 From: stellanera Date: Fri, 7 Nov 2025 17:13:40 +0100 Subject: [PATCH 4/8] node routing seems to work --- .../java/wayoftime/bloodmagic/Datagen.java | 2 +- .../datagen/provider/BMItemTagProvider.java | 7 ++ .../datagen/provider/BMLanguageProvider.java | 17 +++++ .../blockstates/hellforged_block.json | 7 -- .../blockstates/hellforged_block_default.json | 7 ++ .../assets/bloodmagic/lang/en_us.json | 15 +++- ...ock.json => hellforged_block_default.json} | 2 +- .../models/item/hellforged_block.json | 3 - .../models/item/hellforged_block_default.json | 3 + ...ock.json => hellforged_block_default.json} | 4 +- .../tags/block/altar/t5_capstones.json | 2 +- .../data/bloodmagic/tags/item/soul_gems.json | 9 +++ .../tags/block/storage_blocks/hellforged.json | 2 +- .../tags/item/storage_blocks/hellforged.json | 2 +- .../tags/block/beacon_base_blocks.json | 2 +- .../tags/block/mineable/pickaxe.json | 2 +- .../minecraft/tags/block/needs_iron_tool.json | 2 +- .../java/wayoftime/bloodmagic/BloodMagic.java | 14 +++- .../wayoftime/bloodmagic/ClientConfig.java | 12 +++ .../client/event/ClientEventHandler.java | 11 +-- .../render/blockentity/NodeRenderer.java | 29 +++++++- .../bloodmagic/common/block/BMBlocks.java | 5 +- .../common/block/BloodTankBlock.java | 7 +- .../common/block/MasterNodeBlock.java | 10 +++ .../common/block/RoutingNodeBlock.java | 51 ++++++++++++- .../common/blockentity/MasterNodeTile.java | 5 ++ .../common/blockentity/RoutingNodeTile.java | 66 +++++++++++------ .../common/datacomponent/Binding.java | 5 +- .../common/item/NodeRouterItem.java | 69 ++++++++++++++++-- .../wayoftime/bloodmagic/util/ChatUtil.java | 28 +++++++ .../util/helper/BlockEntityHelper.java | 8 -- ...ive.png => hellforged_block_corrosive.png} | Bin ...fault.png => hellforged_block_default.png} | Bin ...e.png => hellforged_block_destructive.png} | Bin ...ast.png => hellforged_block_steadfast.png} | Bin ...eful.png => hellforged_block_vengeful.png} | Bin 36 files changed, 328 insertions(+), 80 deletions(-) delete mode 100644 src/generated/resources/assets/bloodmagic/blockstates/hellforged_block.json create mode 100644 src/generated/resources/assets/bloodmagic/blockstates/hellforged_block_default.json rename src/generated/resources/assets/bloodmagic/models/block/{hellforged_block.json => hellforged_block_default.json} (53%) delete mode 100644 src/generated/resources/assets/bloodmagic/models/item/hellforged_block.json create mode 100644 src/generated/resources/assets/bloodmagic/models/item/hellforged_block_default.json rename src/generated/resources/data/bloodmagic/loot_table/blocks/{hellforged_block.json => hellforged_block_default.json} (70%) create mode 100644 src/generated/resources/data/bloodmagic/tags/item/soul_gems.json create mode 100644 src/main/java/wayoftime/bloodmagic/ClientConfig.java rename src/main/resources/assets/bloodmagic/textures/block/{hellforged_corrosive.png => hellforged_block_corrosive.png} (100%) rename src/main/resources/assets/bloodmagic/textures/block/{hellforged_default.png => hellforged_block_default.png} (100%) rename src/main/resources/assets/bloodmagic/textures/block/{hellforged_destructive.png => hellforged_block_destructive.png} (100%) rename src/main/resources/assets/bloodmagic/textures/block/{hellforged_steadfast.png => hellforged_block_steadfast.png} (100%) rename src/main/resources/assets/bloodmagic/textures/block/{hellforged_vengeful.png => hellforged_block_vengeful.png} (100%) diff --git a/src/datagen/java/wayoftime/bloodmagic/Datagen.java b/src/datagen/java/wayoftime/bloodmagic/Datagen.java index d1900f85ac..19dc578cb7 100644 --- a/src/datagen/java/wayoftime/bloodmagic/Datagen.java +++ b/src/datagen/java/wayoftime/bloodmagic/Datagen.java @@ -15,7 +15,7 @@ import wayoftime.bloodmagic.datagen.content.LivingUpgrades; import wayoftime.bloodmagic.datagen.provider.*; -@EventBusSubscriber(bus = EventBusSubscriber.Bus.MOD) +@EventBusSubscriber public class Datagen { @SubscribeEvent diff --git a/src/datagen/java/wayoftime/bloodmagic/datagen/provider/BMItemTagProvider.java b/src/datagen/java/wayoftime/bloodmagic/datagen/provider/BMItemTagProvider.java index 21c9939e83..9d2a04d277 100644 --- a/src/datagen/java/wayoftime/bloodmagic/datagen/provider/BMItemTagProvider.java +++ b/src/datagen/java/wayoftime/bloodmagic/datagen/provider/BMItemTagProvider.java @@ -48,5 +48,12 @@ protected void addTags(HolderLookup.Provider provider) { .addTag(BMTags.Items.CUTTING_FLUIDS) .addTag(BMTags.Items.HYDRATION) .addTag(BMTags.Items.ARC_FURNACE); + + tag(BMTags.Items.SOUL_GEM) + .add(BMItems.SOUL_GEM_PETTY.get()) + .add(BMItems.SOUL_GEM_LESSER.get()) + .add(BMItems.SOUL_GEM_COMMON.get()) + .add(BMItems.SOUL_GEM_GREATER.get()) + .add(BMItems.SOUL_GEM_GRAND.get()); } } diff --git a/src/datagen/java/wayoftime/bloodmagic/datagen/provider/BMLanguageProvider.java b/src/datagen/java/wayoftime/bloodmagic/datagen/provider/BMLanguageProvider.java index 414876dece..4dc14d316f 100644 --- a/src/datagen/java/wayoftime/bloodmagic/datagen/provider/BMLanguageProvider.java +++ b/src/datagen/java/wayoftime/bloodmagic/datagen/provider/BMLanguageProvider.java @@ -139,6 +139,23 @@ protected void addTranslations() { add("chat.bloodmagic.living_upgrade.level_up", "%s has levelled up to %s!"); LivingUpgrades.translations(this::add); + + addTooltip("stored_position", "Stored: %s in %s"); + + add(BMBlocks.ROUTING_NODE, "Routing Node"); + add(BMBlocks.MASTER_NODE, "Master Routing Node"); + add(BMBlocks.INPUT_ROUTING_NODE, "Input Routing Node"); + add(BMBlocks.OUTPUT_ROUTING_NODE, "Output Routing Node"); + add(BMItems.NODE_ROUTER.get(), "Node Router"); + + addTooltip("router.connected", "Successfully connected nodes!"); + addTooltip("router.pos_cleared", "Cleared stored position!"); + addTooltip("router.pos_set", "Stored %s!"); + + addTooltip("router.master_child", "Cannot add Master as a child node!"); + addTooltip("router.no_node", "Block at %s is not a Routing Node!"); + addTooltip("router.distance", "Nodes are too far apart, max 16 blocks"); + addTooltip("router.same", "Cannot link node to itself!"); } public void addCommand(String key, String value) { diff --git a/src/generated/resources/assets/bloodmagic/blockstates/hellforged_block.json b/src/generated/resources/assets/bloodmagic/blockstates/hellforged_block.json deleted file mode 100644 index 724de93110..0000000000 --- a/src/generated/resources/assets/bloodmagic/blockstates/hellforged_block.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "variants": { - "": { - "model": "bloodmagic:block/hellforged_block" - } - } -} \ No newline at end of file diff --git a/src/generated/resources/assets/bloodmagic/blockstates/hellforged_block_default.json b/src/generated/resources/assets/bloodmagic/blockstates/hellforged_block_default.json new file mode 100644 index 0000000000..edae94248b --- /dev/null +++ b/src/generated/resources/assets/bloodmagic/blockstates/hellforged_block_default.json @@ -0,0 +1,7 @@ +{ + "variants": { + "": { + "model": "bloodmagic:block/hellforged_block_default" + } + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/bloodmagic/lang/en_us.json b/src/generated/resources/assets/bloodmagic/lang/en_us.json index de191142c0..5ecf0134e8 100644 --- a/src/generated/resources/assets/bloodmagic/lang/en_us.json +++ b/src/generated/resources/assets/bloodmagic/lang/en_us.json @@ -8,9 +8,13 @@ "block.bloodmagic.crystal_cluster_brick": "Crystal Cluster Brick", "block.bloodmagic.doubt_block": "Liquid Doubt", "block.bloodmagic.hellfire_forge": "Hellfire Forge", - "block.bloodmagic.hellforged_block": "Hellforged Block", + "block.bloodmagic.hellforged_block_default": "Hellforged Block", "block.bloodmagic.life_essence_block": "Life Essence", "block.bloodmagic.living_station": "Living Upgrade Station", + "block.bloodmagic.routing_node": "Routing Node", + "block.bloodmagic.routing_node_input": "Input Routing Node", + "block.bloodmagic.routing_node_master": "Master Routing Node", + "block.bloodmagic.routing_node_output": "Output Routing Node", "block.bloodmagic.rune_2_acceleration": "Reinforced Acceleration Rune", "block.bloodmagic.rune_2_capacity": "Reinforced Capacity Rune", "block.bloodmagic.rune_2_capacity_augmented": "Reinforced Augmented Capacity Rune", @@ -57,6 +61,7 @@ "item.bloodmagic.living_leggings": "Living Leggings", "item.bloodmagic.living_plate": "Living Plate", "item.bloodmagic.living_plate.dead": "Formerly Living Plate", + "item.bloodmagic.node_router": "Node Router", "item.bloodmagic.raw_will": "Raw Will", "item.bloodmagic.sacrificial_dagger": "Sacrificial Dagger", "item.bloodmagic.soul_gem_common": "Common Tartaric Gem", @@ -139,6 +144,13 @@ "tooltip.bloodmagic.fluid_content_empty": "Empty", "tooltip.bloodmagic.has_living_stats": "Theres some kind of notes, but you cant decipher them", "tooltip.bloodmagic.no_owner": "Not bound yet", + "tooltip.bloodmagic.router.connected": "Successfully connected nodes!", + "tooltip.bloodmagic.router.distance": "Nodes are too far apart, max 16 blocks", + "tooltip.bloodmagic.router.master_child": "Cannot add Master as a child node!", + "tooltip.bloodmagic.router.no_node": "Block at %s is not a Routing Node!", + "tooltip.bloodmagic.router.pos_cleared": "Cleared stored position!", + "tooltip.bloodmagic.router.pos_set": "Stored %s!", + "tooltip.bloodmagic.router.same": "Cannot link node to itself!", "tooltip.bloodmagic.save_for_decoration": "Save for Decoration", "tooltip.bloodmagic.scrap": "Contained Upgrade Points: %s", "tooltip.bloodmagic.soul_gem.soul_gem_common": "A gem used to contain more will.", @@ -146,6 +158,7 @@ "tooltip.bloodmagic.soul_gem.soul_gem_greater": "A gem used to contain a greater amount of will.", "tooltip.bloodmagic.soul_gem.soul_gem_lesser": "A gem used to contain some will.", "tooltip.bloodmagic.soul_gem.soul_gem_petty": "A gem used to contain a little will.", + "tooltip.bloodmagic.stored_position": "Stored: %s in %s", "tooltip.bloodmagic.upgrade_points": "Upgrade Points: %s/%s", "tooltip.bloodmagic.will": "Will Quality: %s", "trainer.bloodmagic.allow_others": "Allow Others", diff --git a/src/generated/resources/assets/bloodmagic/models/block/hellforged_block.json b/src/generated/resources/assets/bloodmagic/models/block/hellforged_block_default.json similarity index 53% rename from src/generated/resources/assets/bloodmagic/models/block/hellforged_block.json rename to src/generated/resources/assets/bloodmagic/models/block/hellforged_block_default.json index 1a385e60e6..f6cb9ed7ad 100644 --- a/src/generated/resources/assets/bloodmagic/models/block/hellforged_block.json +++ b/src/generated/resources/assets/bloodmagic/models/block/hellforged_block_default.json @@ -1,6 +1,6 @@ { "parent": "minecraft:block/cube_all", "textures": { - "all": "bloodmagic:block/hellforged_block" + "all": "bloodmagic:block/hellforged_block_default" } } \ No newline at end of file diff --git a/src/generated/resources/assets/bloodmagic/models/item/hellforged_block.json b/src/generated/resources/assets/bloodmagic/models/item/hellforged_block.json deleted file mode 100644 index d323830c9c..0000000000 --- a/src/generated/resources/assets/bloodmagic/models/item/hellforged_block.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "parent": "bloodmagic:block/hellforged_block" -} \ No newline at end of file diff --git a/src/generated/resources/assets/bloodmagic/models/item/hellforged_block_default.json b/src/generated/resources/assets/bloodmagic/models/item/hellforged_block_default.json new file mode 100644 index 0000000000..e08fa33ce9 --- /dev/null +++ b/src/generated/resources/assets/bloodmagic/models/item/hellforged_block_default.json @@ -0,0 +1,3 @@ +{ + "parent": "bloodmagic:block/hellforged_block_default" +} \ No newline at end of file diff --git a/src/generated/resources/data/bloodmagic/loot_table/blocks/hellforged_block.json b/src/generated/resources/data/bloodmagic/loot_table/blocks/hellforged_block_default.json similarity index 70% rename from src/generated/resources/data/bloodmagic/loot_table/blocks/hellforged_block.json rename to src/generated/resources/data/bloodmagic/loot_table/blocks/hellforged_block_default.json index 19c00defe9..d5050389fa 100644 --- a/src/generated/resources/data/bloodmagic/loot_table/blocks/hellforged_block.json +++ b/src/generated/resources/data/bloodmagic/loot_table/blocks/hellforged_block_default.json @@ -11,11 +11,11 @@ "entries": [ { "type": "minecraft:item", - "name": "bloodmagic:hellforged_block" + "name": "bloodmagic:hellforged_block_default" } ], "rolls": 1.0 } ], - "random_sequence": "bloodmagic:blocks/hellforged_block" + "random_sequence": "bloodmagic:blocks/hellforged_block_default" } \ No newline at end of file diff --git a/src/generated/resources/data/bloodmagic/tags/block/altar/t5_capstones.json b/src/generated/resources/data/bloodmagic/tags/block/altar/t5_capstones.json index a936971747..81e804e270 100644 --- a/src/generated/resources/data/bloodmagic/tags/block/altar/t5_capstones.json +++ b/src/generated/resources/data/bloodmagic/tags/block/altar/t5_capstones.json @@ -1,5 +1,5 @@ { "values": [ - "bloodmagic:hellforged_block" + "bloodmagic:hellforged_block_default" ] } \ No newline at end of file diff --git a/src/generated/resources/data/bloodmagic/tags/item/soul_gems.json b/src/generated/resources/data/bloodmagic/tags/item/soul_gems.json new file mode 100644 index 0000000000..01db0b4797 --- /dev/null +++ b/src/generated/resources/data/bloodmagic/tags/item/soul_gems.json @@ -0,0 +1,9 @@ +{ + "values": [ + "bloodmagic:soul_gem_petty", + "bloodmagic:soul_gem_lesser", + "bloodmagic:soul_gem_common", + "bloodmagic:soul_gem_greater", + "bloodmagic:soul_gem_grand" + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/c/tags/block/storage_blocks/hellforged.json b/src/generated/resources/data/c/tags/block/storage_blocks/hellforged.json index a936971747..81e804e270 100644 --- a/src/generated/resources/data/c/tags/block/storage_blocks/hellforged.json +++ b/src/generated/resources/data/c/tags/block/storage_blocks/hellforged.json @@ -1,5 +1,5 @@ { "values": [ - "bloodmagic:hellforged_block" + "bloodmagic:hellforged_block_default" ] } \ No newline at end of file diff --git a/src/generated/resources/data/c/tags/item/storage_blocks/hellforged.json b/src/generated/resources/data/c/tags/item/storage_blocks/hellforged.json index a936971747..81e804e270 100644 --- a/src/generated/resources/data/c/tags/item/storage_blocks/hellforged.json +++ b/src/generated/resources/data/c/tags/item/storage_blocks/hellforged.json @@ -1,5 +1,5 @@ { "values": [ - "bloodmagic:hellforged_block" + "bloodmagic:hellforged_block_default" ] } \ No newline at end of file diff --git a/src/generated/resources/data/minecraft/tags/block/beacon_base_blocks.json b/src/generated/resources/data/minecraft/tags/block/beacon_base_blocks.json index a936971747..81e804e270 100644 --- a/src/generated/resources/data/minecraft/tags/block/beacon_base_blocks.json +++ b/src/generated/resources/data/minecraft/tags/block/beacon_base_blocks.json @@ -1,5 +1,5 @@ { "values": [ - "bloodmagic:hellforged_block" + "bloodmagic:hellforged_block_default" ] } \ No newline at end of file diff --git a/src/generated/resources/data/minecraft/tags/block/mineable/pickaxe.json b/src/generated/resources/data/minecraft/tags/block/mineable/pickaxe.json index 00086dd83d..5d11f5b997 100644 --- a/src/generated/resources/data/minecraft/tags/block/mineable/pickaxe.json +++ b/src/generated/resources/data/minecraft/tags/block/mineable/pickaxe.json @@ -4,7 +4,7 @@ "bloodmagic:blood_tank", "bloodmagic:bloodstone", "bloodmagic:bloodstone_brick", - "bloodmagic:hellforged_block", + "bloodmagic:hellforged_block_default", "bloodmagic:crystal_cluster", "bloodmagic:crystal_cluster_brick", "bloodmagic:rune_blank", diff --git a/src/generated/resources/data/minecraft/tags/block/needs_iron_tool.json b/src/generated/resources/data/minecraft/tags/block/needs_iron_tool.json index a936971747..81e804e270 100644 --- a/src/generated/resources/data/minecraft/tags/block/needs_iron_tool.json +++ b/src/generated/resources/data/minecraft/tags/block/needs_iron_tool.json @@ -1,5 +1,5 @@ { "values": [ - "bloodmagic:hellforged_block" + "bloodmagic:hellforged_block_default" ] } \ No newline at end of file diff --git a/src/main/java/wayoftime/bloodmagic/BloodMagic.java b/src/main/java/wayoftime/bloodmagic/BloodMagic.java index cd6a0d2788..5d36afd55e 100644 --- a/src/main/java/wayoftime/bloodmagic/BloodMagic.java +++ b/src/main/java/wayoftime/bloodmagic/BloodMagic.java @@ -37,10 +37,17 @@ public class BloodMagic { public static final ServerConfig SERVER_CONFIG; private static final ModConfigSpec SERVER_CONFIG_SPEC; + public static final ClientConfig CLIENT_CONFIG; + private static final ModConfigSpec CLIENT_CONFIG_SPEC; + static { - Pair pair = new ModConfigSpec.Builder().configure(ServerConfig::new); - SERVER_CONFIG = pair.getLeft(); - SERVER_CONFIG_SPEC = pair.getRight(); + Pair serverConf = new ModConfigSpec.Builder().configure(ServerConfig::new); + SERVER_CONFIG = serverConf.getLeft(); + SERVER_CONFIG_SPEC = serverConf.getRight(); + + Pair clientConf = new ModConfigSpec.Builder().configure(ClientConfig::new); + CLIENT_CONFIG = clientConf.getLeft(); + CLIENT_CONFIG_SPEC = clientConf.getRight(); } public BloodMagic(IEventBus modBus, ModContainer container) { @@ -60,6 +67,7 @@ public BloodMagic(IEventBus modBus, ModContainer container) { BMTabs.register(modBus); container.registerConfig(ModConfig.Type.SERVER, SERVER_CONFIG_SPEC); + container.registerConfig(ModConfig.Type.CLIENT, CLIENT_CONFIG_SPEC); NeoForge.EVENT_BUS.addListener(BMCommands::register); } diff --git a/src/main/java/wayoftime/bloodmagic/ClientConfig.java b/src/main/java/wayoftime/bloodmagic/ClientConfig.java new file mode 100644 index 0000000000..d2ba6e8ea2 --- /dev/null +++ b/src/main/java/wayoftime/bloodmagic/ClientConfig.java @@ -0,0 +1,12 @@ +package wayoftime.bloodmagic; + +import net.neoforged.neoforge.common.ModConfigSpec; + +public class ClientConfig { + + public final ModConfigSpec.BooleanValue ALWAYS_RENDER_NODE_LINES; + + protected ClientConfig(ModConfigSpec.Builder builder) { + ALWAYS_RENDER_NODE_LINES = builder.define("always_render_lines", false); + } +} diff --git a/src/main/java/wayoftime/bloodmagic/client/event/ClientEventHandler.java b/src/main/java/wayoftime/bloodmagic/client/event/ClientEventHandler.java index 2eaff94df4..00096db6b6 100644 --- a/src/main/java/wayoftime/bloodmagic/client/event/ClientEventHandler.java +++ b/src/main/java/wayoftime/bloodmagic/client/event/ClientEventHandler.java @@ -17,6 +17,7 @@ import net.neoforged.neoforge.event.entity.player.ItemTooltipEvent; import wayoftime.bloodmagic.BloodMagic; import wayoftime.bloodmagic.common.datacomponent.BMDataComponents; +import wayoftime.bloodmagic.util.ChatUtil; import java.util.ArrayList; import java.util.List; @@ -44,21 +45,13 @@ public static void onHoverText(ItemTooltipEvent event) { if (stack.has(BMDataComponents.STORED_POSITION)) { GlobalPos storedPos = stack.get(BMDataComponents.STORED_POSITION); - toAdd.add(Component.translatable("tooltip.bloodmagic.stored_position", posString(storedPos.pos()), dimensionString(storedPos.dimension())).withStyle(ChatFormatting.GRAY)); + toAdd.add(Component.translatable("tooltip.bloodmagic.stored_position", ChatUtil.posString(storedPos.pos()), ChatUtil.dimensionString(storedPos.dimension())).withStyle(ChatFormatting.GRAY)); } // add after name. idgaf tooltip.addAll(1, toAdd); } - private static String posString(BlockPos pos) { - return "%d, %d, %d".formatted(pos.getX(), pos.getY(), pos.getZ()); - } - - private static String dimensionString(ResourceKey dim) { - return "%s:%s".formatted(dim.location().getNamespace(), dim.location().getPath()); - } - public static void addToTooltip( DataComponentType component, Item.TooltipContext context, Consumer tooltipAdder, TooltipFlag tooltipFlag, ItemStack stack ) { diff --git a/src/main/java/wayoftime/bloodmagic/client/render/blockentity/NodeRenderer.java b/src/main/java/wayoftime/bloodmagic/client/render/blockentity/NodeRenderer.java index 02d135aab2..cf1546290e 100644 --- a/src/main/java/wayoftime/bloodmagic/client/render/blockentity/NodeRenderer.java +++ b/src/main/java/wayoftime/bloodmagic/client/render/blockentity/NodeRenderer.java @@ -3,6 +3,8 @@ import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.VertexConsumer; import com.mojang.math.Axis; +import net.minecraft.client.Minecraft; +import net.minecraft.client.player.LocalPlayer; import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.client.renderer.RenderType; import net.minecraft.client.renderer.blockentity.BlockEntityRenderer; @@ -11,7 +13,9 @@ import net.minecraft.core.BlockPos; import net.minecraft.resources.ResourceLocation; import wayoftime.bloodmagic.BloodMagic; +import wayoftime.bloodmagic.common.block.RoutingNodeBlock; import wayoftime.bloodmagic.common.blockentity.RoutingNodeTile; +import wayoftime.bloodmagic.common.item.BMItems; public class NodeRenderer implements BlockEntityRenderer { @@ -29,6 +33,19 @@ public void render(RoutingNodeTile node, float partialTick, PoseStack poseStack, return; } + LocalPlayer player = Minecraft.getInstance().player; + if (player == null) { // what are we even doing lmao + return; + } + boolean shouldRenderLine = BloodMagic.CLIENT_CONFIG.ALWAYS_RENDER_NODE_LINES.get() // config override + || node.getBlockState().getValue(RoutingNodeBlock.RENDER_LINE) // node override + || player.getMainHandItem().is(BMItems.NODE_ROUTER) // has router in mainhand -> maybe should be a tag and also check curio? routing glasses, anyone? + || player.getOffhandItem().is(BMItems.NODE_ROUTER); // has router in offhand + + if (!shouldRenderLine) { + return; + } + long gameTime = node.getLevel().getGameTime(); float time = (float)Math.floorMod(gameTime, 40) + partialTick; @@ -47,7 +64,16 @@ public void render(RoutingNodeTile node, float partialTick, PoseStack poseStack, poseStack.mulPose(Axis.YP.rotationDegrees(-rotYaw)); poseStack.mulPose(Axis.XN.rotationDegrees(rotPitch - 90)); - renderBeaconBeam(poseStack, bufferSource, DEFAULT, time, (float) distance, 0.06f, 0.1f, node.hasMaster()); + ResourceLocation kind = switch (node.getBlockState().getValue(RoutingNodeBlock.WILL)) { + case DEFAULT -> DEFAULT; + case CORROSIVE -> CORROSIVE; + case DESTRUCTIVE -> DESTRUCTIVE; + case STEADFAST -> STEADFAST; + case VENGEFUL -> VENGEFUL; + }; + + renderBeaconBeam(poseStack, bufferSource, kind, time, (float) distance, 0.06f, 0.1f, node.getBlockState().getValue(RoutingNodeBlock.ENABLED)); + poseStack.popPose(); } public static void renderBeaconBeam( @@ -61,7 +87,6 @@ public static void renderBeaconBeam( boolean isConnected ) { poseStack.pushPose(); - poseStack.translate(0.5, 0.5, 0.5); poseStack.pushPose(); poseStack.mulPose(Axis.YP.rotationDegrees(time * 2.25F - 45.0F)); renderPart( diff --git a/src/main/java/wayoftime/bloodmagic/common/block/BMBlocks.java b/src/main/java/wayoftime/bloodmagic/common/block/BMBlocks.java index 210b91d1ee..1e6b8fe672 100644 --- a/src/main/java/wayoftime/bloodmagic/common/block/BMBlocks.java +++ b/src/main/java/wayoftime/bloodmagic/common/block/BMBlocks.java @@ -19,6 +19,7 @@ import wayoftime.bloodmagic.common.blockentity.BMTiles; import wayoftime.bloodmagic.common.blockentity.FilterNodeTile; import wayoftime.bloodmagic.common.datacomponent.BMDataComponents; +import wayoftime.bloodmagic.util.ChatUtil; import wayoftime.bloodmagic.util.helper.BlockEntityHelper; import wayoftime.bloodmagic.util.helper.BlockWithItemHolder; import wayoftime.bloodmagic.util.helper.BlockWithItemRegister; @@ -49,7 +50,7 @@ public class BMBlocks { public static final BlockWithItemHolder LIVING_STATION = BLOCK_REG.register("living_station", LivingStationBlock::new); private static final BlockBehaviour.Properties rune_properties = BlockBehaviour.Properties.of().strength(2.0F, 5.0F).sound(SoundType.STONE).requiresCorrectToolForDrops(); - private static final ItemLore save_decoration = new ItemLore(List.of(BlockEntityHelper.translatableHover("tooltip.bloodmagic.save_for_decoration").withStyle(ChatFormatting.ITALIC))); + private static final ItemLore save_decoration = new ItemLore(List.of(ChatUtil.translatableHover("tooltip.bloodmagic.save_for_decoration").withStyle(ChatFormatting.ITALIC))); private static final Item.Properties decoration_item_properties = new Item.Properties().component(DataComponents.LORE, save_decoration); public static final BlockWithItemHolder RUNE_BLANK = BASIC_REG.register("rune_blank", rune_properties, decoration_item_properties); @@ -79,7 +80,7 @@ public class BMBlocks { public static final BlockWithItemHolder BLOODSTONE = BASIC_REG.register("bloodstone", rune_properties, decoration_item_properties); public static final BlockWithItemHolder BLOODSTONE_BRICK = BASIC_REG.register("bloodstone_brick", rune_properties, decoration_item_properties); - public static final BlockWithItemHolder HELLFORGED_BLOCK = BASIC_REG.register("hellforged_block", BlockBehaviour.Properties.of().strength(5, 6).sound(SoundType.METAL).requiresCorrectToolForDrops(), new Item.Properties()); + public static final BlockWithItemHolder HELLFORGED_BLOCK = BASIC_REG.register("hellforged_block_default", BlockBehaviour.Properties.of().strength(5, 6).sound(SoundType.METAL).requiresCorrectToolForDrops(), new Item.Properties()); public static final BlockWithItemHolder CRYSTAL_CLUSTER = BASIC_REG.register("crystal_cluster", rune_properties, decoration_item_properties); public static final BlockWithItemHolder CRYSTAL_CLUSTER_BRICK = BASIC_REG.register("crystal_cluster_brick", rune_properties, decoration_item_properties); diff --git a/src/main/java/wayoftime/bloodmagic/common/block/BloodTankBlock.java b/src/main/java/wayoftime/bloodmagic/common/block/BloodTankBlock.java index 5a6f9c4de8..3db91ec1f8 100644 --- a/src/main/java/wayoftime/bloodmagic/common/block/BloodTankBlock.java +++ b/src/main/java/wayoftime/bloodmagic/common/block/BloodTankBlock.java @@ -28,6 +28,7 @@ import org.jetbrains.annotations.Nullable; import wayoftime.bloodmagic.common.blockentity.BloodTankTile; import wayoftime.bloodmagic.common.datacomponent.BMDataComponents; +import wayoftime.bloodmagic.util.ChatUtil; import wayoftime.bloodmagic.util.helper.BlockEntityHelper; import java.util.List; @@ -67,14 +68,14 @@ public void appendHoverText(ItemStack stack, Item.TooltipContext context, List BlockEntityTicker getTicker(Level level, BlockState state, BlockEntityType blockEntityType) { + return BlockEntityHelper.getTicker(blockEntityType, BMTiles.MASTER_ROUTING_NODE.get(), MasterNodeTile::tick); + } + @Override public @Nullable BlockEntity newBlockEntity(BlockPos pos, BlockState state) { return new MasterNodeTile(pos, state); diff --git a/src/main/java/wayoftime/bloodmagic/common/block/RoutingNodeBlock.java b/src/main/java/wayoftime/bloodmagic/common/block/RoutingNodeBlock.java index 14dd234d0b..f3306fc4f9 100644 --- a/src/main/java/wayoftime/bloodmagic/common/block/RoutingNodeBlock.java +++ b/src/main/java/wayoftime/bloodmagic/common/block/RoutingNodeBlock.java @@ -2,6 +2,13 @@ import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.util.RandomSource; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.InteractionResult; +import net.minecraft.world.ItemInteractionResult; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.context.BlockPlaceContext; import net.minecraft.world.level.BlockGetter; import net.minecraft.world.level.Level; @@ -10,16 +17,24 @@ import net.minecraft.world.level.block.EntityBlock; import net.minecraft.world.level.block.RenderShape; import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.entity.BlockEntityTicker; +import net.minecraft.world.level.block.entity.BlockEntityType; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.StateDefinition; import net.minecraft.world.level.block.state.properties.BlockStateProperties; import net.minecraft.world.level.block.state.properties.BooleanProperty; +import net.minecraft.world.level.block.state.properties.EnumProperty; import net.minecraft.world.level.material.PushReaction; +import net.minecraft.world.phys.BlockHitResult; import net.minecraft.world.phys.shapes.CollisionContext; import net.minecraft.world.phys.shapes.VoxelShape; import org.jetbrains.annotations.Nullable; import wayoftime.bloodmagic.common.blockentity.BMTiles; import wayoftime.bloodmagic.common.blockentity.RoutingNodeTile; +import wayoftime.bloodmagic.common.datacomponent.BMDataComponents; +import wayoftime.bloodmagic.common.datacomponent.EnumWillType; +import wayoftime.bloodmagic.common.tag.BMTags; +import wayoftime.bloodmagic.util.helper.BlockEntityHelper; public class RoutingNodeBlock extends Block implements EntityBlock { public static final BooleanProperty ENABLED = BlockStateProperties.ENABLED; @@ -29,9 +44,10 @@ public class RoutingNodeBlock extends Block implements EntityBlock { public static final BooleanProperty SOUTH = BlockStateProperties.SOUTH; public static final BooleanProperty WEST = BlockStateProperties.WEST; public static final BooleanProperty EAST = BlockStateProperties.EAST; + public static final EnumProperty WILL = EnumProperty.create("will_type", EnumWillType.class); + public static final BooleanProperty RENDER_LINE = BooleanProperty.create("render_line"); public static final VoxelShape SHAPE = Block.box(6, 6, 6, 10, 10, 10); - public RoutingNodeBlock() { super( Properties.of() @@ -52,9 +68,40 @@ public RoutingNodeBlock() { .setValue(SOUTH, false) .setValue(WEST, false) .setValue(EAST, false) + .setValue(WILL, EnumWillType.DEFAULT) + .setValue(RENDER_LINE, false) ); } + @Override + public @Nullable BlockEntityTicker getTicker(Level level, BlockState state, BlockEntityType blockEntityType) { + return BlockEntityHelper.getTicker(blockEntityType, BMTiles.ROUTING_NODE.get(), RoutingNodeTile::tick); + } + + @Override + protected InteractionResult useWithoutItem(BlockState state, Level level, BlockPos pos, Player player, BlockHitResult hitResult) { + if (player.isShiftKeyDown()) { + level.setBlock(pos, state.setValue(RENDER_LINE, true), UPDATE_ALL); + level.scheduleTick(pos, state.getBlock(), 20 * 5); + } + return super.useWithoutItem(state, level, pos, player, hitResult); + } + + @Override + protected void tick(BlockState state, ServerLevel level, BlockPos pos, RandomSource random) { + level.setBlock(pos, state.setValue(RENDER_LINE, false), UPDATE_ALL); + } + + @Override + protected ItemInteractionResult useItemOn(ItemStack stack, BlockState state, Level level, BlockPos pos, Player player, InteractionHand hand, BlockHitResult hitResult) { + if (stack.is(BMTags.Items.SOUL_GEM)) { + level.setBlock(pos, state.setValue(WILL, stack.getOrDefault(BMDataComponents.DEMON_WILL_TYPE, EnumWillType.DEFAULT)), UPDATE_ALL); + return ItemInteractionResult.sidedSuccess(level.isClientSide); + } + + return super.useItemOn(stack, state, level, pos, player, hand, hitResult); + } + @Override protected void neighborChanged(BlockState state, Level level, BlockPos pos, Block neighborBlock, BlockPos neighborPos, boolean movedByPiston) { // adapted from HopperBlock @@ -118,7 +165,7 @@ protected VoxelShape getShape(BlockState state, BlockGetter level, BlockPos pos, @Override protected void createBlockStateDefinition(StateDefinition.Builder builder) { - builder.add(ENABLED, DOWN, UP, NORTH, SOUTH, WEST, EAST); + builder.add(ENABLED, DOWN, UP, NORTH, SOUTH, WEST, EAST, WILL, RENDER_LINE); } @Override diff --git a/src/main/java/wayoftime/bloodmagic/common/blockentity/MasterNodeTile.java b/src/main/java/wayoftime/bloodmagic/common/blockentity/MasterNodeTile.java index 5047ecff09..14fb6a3f6c 100644 --- a/src/main/java/wayoftime/bloodmagic/common/blockentity/MasterNodeTile.java +++ b/src/main/java/wayoftime/bloodmagic/common/blockentity/MasterNodeTile.java @@ -78,6 +78,11 @@ public void markNodeDirty(BlockPos nodePos) { } + @Override + public boolean addToNetwork(BlockPos parent) { + return false; + } + @Override protected void loadAdditional(CompoundTag tag, HolderLookup.Provider registries) { super.loadAdditional(tag, registries); diff --git a/src/main/java/wayoftime/bloodmagic/common/blockentity/RoutingNodeTile.java b/src/main/java/wayoftime/bloodmagic/common/blockentity/RoutingNodeTile.java index 09a5e3b889..889de09c0b 100644 --- a/src/main/java/wayoftime/bloodmagic/common/blockentity/RoutingNodeTile.java +++ b/src/main/java/wayoftime/bloodmagic/common/blockentity/RoutingNodeTile.java @@ -9,6 +9,7 @@ import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.entity.BlockEntityType; import net.minecraft.world.level.block.state.BlockState; +import wayoftime.bloodmagic.BloodMagic; import wayoftime.bloodmagic.common.block.RoutingNodeBlock; import java.util.HashSet; @@ -28,6 +29,20 @@ public RoutingNodeTile(BlockPos pos, BlockState state) { super(BMTiles.ROUTING_NODE.get(), pos, state); } + public static void tick(Level level, BlockPos blockPos, BlockState blockState, RoutingNodeTile node) { + if (!(level.getGameTime() % 20 == 0)) { + return; + } + + if (!node.hasMaster() && node.hasParent()) { + if (level.getBlockEntity(node.parentPos) instanceof RoutingNodeTile parent) { + if (parent.hasMaster()) { + node.masterPos = parent.masterPos; + } + } + } + } + protected BlockPos masterPos = BlockPos.ZERO; protected BlockPos parentPos = BlockPos.ZERO; protected Set children = new HashSet<>(); @@ -48,8 +63,6 @@ public void propagateNetwork(BiConsumer> collector, public void setParent(BlockPos parent) { this.parentPos = parent; - this.setChanged(); - this.level.sendBlockUpdated(getBlockPos(), getBlockState(), getBlockState(), Block.UPDATE_ALL); // send block update for sync so client knows and can render lines appropriately } public boolean hasParent() { @@ -60,21 +73,33 @@ public BlockPos getParentPos() { return this.parentPos; } - public void addConnection(BlockPos child) { - children.add(child); - this.setChanged(); - this.level.sendBlockUpdated(getBlockPos(), getBlockState(), getBlockState(), Block.UPDATE_ALL); // send block update for sync so client knows and can render lines appropriately - } + public boolean addToNetwork(BlockPos parent) { + if (!(level.getBlockEntity(parent) instanceof RoutingNodeTile parentNode)) { + return false; + } + if (masterPos != BlockPos.ZERO && parentNode.masterPos != BlockPos.ZERO) { + return false; + } - public void removeConnection(BlockPos child) { - this.parentPos = BlockPos.ZERO; - children.remove(child); - BlockEntity be = this.level.getBlockEntity(child); - if (be instanceof RoutingNodeTile node) { - node.removeFromNetwork(); + parentPos = parent; + if (masterPos == BlockPos.ZERO && parentNode.masterPos != BlockPos.ZERO) { + masterPos = parentNode.masterPos; + } else if (masterPos != BlockPos.ZERO && parentNode.masterPos == BlockPos.ZERO) { + parentNode.masterPos = masterPos; } + + parentNode.addChild(getBlockPos()); + parentNode.setChanged(); + level.sendBlockUpdated(parentPos, parentNode.getBlockState(), parentNode.getBlockState(), Block.UPDATE_CLIENTS); + this.setChanged(); - this.level.sendBlockUpdated(getBlockPos(), getBlockState(), getBlockState(), Block.UPDATE_ALL); // send block update for sync so client knows and can render lines appropriately + level.sendBlockUpdated(getBlockPos(), getBlockState(), getBlockState(), Block.UPDATE_CLIENTS); + + return true; + } + + public void addChild(BlockPos child) { + this.children.add(child); } public void removeFromNetwork() { @@ -82,8 +107,7 @@ public void removeFromNetwork() { // TODO filtering nodes should remove their info from master here children.forEach(child -> { - BlockEntity be = this.level.getBlockEntity(child); - if (be instanceof RoutingNodeTile node) { + if (level.getBlockEntity(child) instanceof RoutingNodeTile node) { node.removeFromNetwork(); } else { // you in da wrong neighbourhood dawg children.remove(child); @@ -99,17 +123,12 @@ public BlockPos getMasterPos() { return this.masterPos; } - public void setMasterPos(BlockPos masterPos) { - this.masterPos = masterPos; - this.setChanged(); - this.level.sendBlockUpdated(getBlockPos(), getBlockState(), getBlockState(), Block.UPDATE_ALL); // send block update for sync so client knows and can render lines appropriately - } - @Override protected void saveAdditional(CompoundTag tag, HolderLookup.Provider registries) { super.saveAdditional(tag, registries); CompoundTag nodeInfo = new CompoundTag(); nodeInfo.put("master", posToTag(masterPos)); + nodeInfo.put("parent", posToTag(parentPos)); ListTag childTag = new ListTag(); children.forEach(pos -> childTag.add(posToTag(pos))); nodeInfo.put("children", childTag); @@ -120,7 +139,8 @@ protected void saveAdditional(CompoundTag tag, HolderLookup.Provider registries) protected void loadAdditional(CompoundTag tag, HolderLookup.Provider registries) { super.loadAdditional(tag, registries); CompoundTag nodeInfo = tag.getCompound("node_info"); - masterPos = tagToPos(tag.getCompound("master")); + masterPos = tagToPos(nodeInfo.getCompound("master")); + parentPos = tagToPos(nodeInfo.getCompound("parent")); ListTag childrenTag = nodeInfo.getList("children", ListTag.TAG_COMPOUND); children.clear(); // just to be sure theres no weird overflow happening childrenTag.forEach(childTag -> children.add(tagToPos((CompoundTag) childTag))); // cast should be fine since we tell .getList its a list of TC's. I *think* diff --git a/src/main/java/wayoftime/bloodmagic/common/datacomponent/Binding.java b/src/main/java/wayoftime/bloodmagic/common/datacomponent/Binding.java index e91c1ccf6c..d4ee0870ff 100644 --- a/src/main/java/wayoftime/bloodmagic/common/datacomponent/Binding.java +++ b/src/main/java/wayoftime/bloodmagic/common/datacomponent/Binding.java @@ -11,6 +11,7 @@ import net.minecraft.world.item.Item; import net.minecraft.world.item.TooltipFlag; import net.minecraft.world.item.component.TooltipProvider; +import wayoftime.bloodmagic.util.ChatUtil; import wayoftime.bloodmagic.util.helper.BlockEntityHelper; import java.nio.charset.StandardCharsets; @@ -41,9 +42,9 @@ public boolean isEmpty() { @Override public void addToTooltip(Item.TooltipContext context, Consumer tooltip, TooltipFlag tooltipFlag) { if (this.isEmpty()) { - tooltip.accept(BlockEntityHelper.translatableHover("tooltip.bloodmagic.no_owner")); + tooltip.accept(ChatUtil.translatableHover("tooltip.bloodmagic.no_owner")); } else { - tooltip.accept(BlockEntityHelper.translatableHover("tooltip.bloodmagic.current_owner", this.name)); + tooltip.accept(ChatUtil.translatableHover("tooltip.bloodmagic.current_owner", this.name)); } } } diff --git a/src/main/java/wayoftime/bloodmagic/common/item/NodeRouterItem.java b/src/main/java/wayoftime/bloodmagic/common/item/NodeRouterItem.java index 16e228d657..1ba2ab51b5 100644 --- a/src/main/java/wayoftime/bloodmagic/common/item/NodeRouterItem.java +++ b/src/main/java/wayoftime/bloodmagic/common/item/NodeRouterItem.java @@ -1,16 +1,18 @@ package wayoftime.bloodmagic.common.item; +import net.minecraft.core.BlockPos; import net.minecraft.core.GlobalPos; import net.minecraft.network.chat.Component; import net.minecraft.world.InteractionHand; import net.minecraft.world.InteractionResult; import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.TooltipFlag; import net.minecraft.world.item.context.UseOnContext; +import net.minecraft.world.level.Level; +import wayoftime.bloodmagic.common.blockentity.MasterNodeTile; +import wayoftime.bloodmagic.common.blockentity.RoutingNodeTile; import wayoftime.bloodmagic.common.datacomponent.BMDataComponents; - -import java.util.List; +import wayoftime.bloodmagic.util.ChatUtil; public class NodeRouterItem extends Item { @@ -28,14 +30,71 @@ public InteractionResult useOn(UseOnContext context) { ItemStack routerStack = context.getItemInHand(); if (context.isSecondaryUseActive()) { routerStack.remove(BMDataComponents.STORED_POSITION); + if (context.getLevel().isClientSide) { + ChatUtil.sendChat(context.getPlayer(), ChatUtil.translatableHover("tooltip.bloodmagic.router.pos_cleared")); + } + return InteractionResult.sidedSuccess(context.getLevel().isClientSide); } else { + BlockPos clickedPos = context.getClickedPos(); + Level level = context.getLevel(); + if (!(level.getBlockEntity(clickedPos) instanceof RoutingNodeTile clickedNode)) { + if (level.isClientSide) { + ChatUtil.sendChat(context.getPlayer(), ChatUtil.translatableHover("tooltip.bloodmagic.router.no_node", ChatUtil.posString(clickedPos))); + } + return InteractionResult.FAIL; + } if (!routerStack.has(BMDataComponents.STORED_POSITION)) { // first node, this is the parent + routerStack.set(BMDataComponents.STORED_POSITION, new GlobalPos(context.getLevel().dimension(), clickedPos)); + if (level.isClientSide) { + ChatUtil.sendChat(context.getPlayer(), ChatUtil.translatableHover("tooltip.bloodmagic.router.pos_set", ChatUtil.posString(clickedPos))); + } } else { // second node, this is the child + if (clickedNode instanceof MasterNodeTile) { + if (level.isClientSide) { + ChatUtil.sendChat(context.getPlayer(), Component.translatable("tooltip.bloodmagic.router.master_child")); + } + return InteractionResult.FAIL; + } + + GlobalPos storedPos = routerStack.get(BMDataComponents.STORED_POSITION); + if (clickedPos.distSqr(storedPos.pos()) > 16 * 16) { + if (level.isClientSide) { + ChatUtil.sendChat(context.getPlayer(), Component.translatable("tooltip.bloodmagic.router.distance")); + } + return InteractionResult.FAIL; + } + + if (clickedPos.equals(storedPos.pos())) { + if (level.isClientSide) { + ChatUtil.sendChat(context.getPlayer(), Component.translatable("tooltip.bloodmagic.router.same")); + } + return InteractionResult.FAIL; + } + + if (!(level.getBlockEntity(storedPos.pos()) instanceof RoutingNodeTile)) { + if (level.isClientSide) { + ChatUtil.sendChat(context.getPlayer(), Component.translatable("tooltip.bloodmagic.router.no_node", ChatUtil.posString(storedPos.pos()))); + } + return InteractionResult.FAIL; + } + + if (!clickedNode.addToNetwork(storedPos.pos())) { + return InteractionResult.FAIL; + } + // if chaining nodes together for long distance, having this active is good + // if connecting x nodes to the same parent having this active is annoying + // perhaps client config? is client config available on server? probably gonna need to send a packet from client + // TODO decide how to handle this + routerStack.remove(BMDataComponents.STORED_POSITION); + if (level.isClientSide) { + ChatUtil.sendChat(context.getPlayer(), Component.translatable("tooltip.bloodmagic.router.connected")); + ChatUtil.sendChat(context.getPlayer(), Component.translatable("tooltip.bloodmagic.router.pos_cleared")); + } } - } - return InteractionResult.PASS; + return InteractionResult.sidedSuccess(level.isClientSide); + } } } diff --git a/src/main/java/wayoftime/bloodmagic/util/ChatUtil.java b/src/main/java/wayoftime/bloodmagic/util/ChatUtil.java index 5ccbd58b18..49191354e5 100644 --- a/src/main/java/wayoftime/bloodmagic/util/ChatUtil.java +++ b/src/main/java/wayoftime/bloodmagic/util/ChatUtil.java @@ -1,8 +1,36 @@ package wayoftime.bloodmagic.util; +import net.minecraft.ChatFormatting; +import net.minecraft.core.BlockPos; +import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.MutableComponent; +import net.minecraft.resources.ResourceKey; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.level.Level; + import java.text.DecimalFormat; public class ChatUtil { + + public static void sendChat(Player player, Component text) { + player.sendSystemMessage(text); + } + + public static String posString(BlockPos pos) { + return "%d, %d, %d".formatted(pos.getX(), pos.getY(), pos.getZ()); + } + + public static String dimensionString(ResourceKey dim) { + return "%s:%s".formatted(dim.location().getNamespace(), dim.location().getPath()); + } + + public static MutableComponent translatableHover(String key, Object... args) { + return Component.translatable(key, args).withStyle(ChatFormatting.GRAY); + } + + public static MutableComponent translatableHover(String key) { + return Component.translatable(key).withStyle(ChatFormatting.GRAY); + } public static final DecimalFormat DECIMAL_FORMAT = new DecimalFormat("###,###,###.##"); private static final char[] ones = new char[]{'I', 'X', 'C', 'M'}; diff --git a/src/main/java/wayoftime/bloodmagic/util/helper/BlockEntityHelper.java b/src/main/java/wayoftime/bloodmagic/util/helper/BlockEntityHelper.java index fe94c12569..3203d4fbed 100644 --- a/src/main/java/wayoftime/bloodmagic/util/helper/BlockEntityHelper.java +++ b/src/main/java/wayoftime/bloodmagic/util/helper/BlockEntityHelper.java @@ -16,14 +16,6 @@ public static BlockEntityTicker) ticker : null; } - public static MutableComponent translatableHover(String key, Object... args) { - return Component.translatable(key, args).withStyle(ChatFormatting.GRAY); - } - - public static MutableComponent translatableHover(String key) { - return Component.translatable(key).withStyle(ChatFormatting.GRAY); - } - public static void dropContents(Level level, BlockPos pos, IItemHandler handler) { for (int i = 0; i < handler.getSlots(); i++) { Containers.dropItemStack(level, pos.getX(), pos.getY(), pos.getZ(), handler.getStackInSlot(i)); diff --git a/src/main/resources/assets/bloodmagic/textures/block/hellforged_corrosive.png b/src/main/resources/assets/bloodmagic/textures/block/hellforged_block_corrosive.png similarity index 100% rename from src/main/resources/assets/bloodmagic/textures/block/hellforged_corrosive.png rename to src/main/resources/assets/bloodmagic/textures/block/hellforged_block_corrosive.png diff --git a/src/main/resources/assets/bloodmagic/textures/block/hellforged_default.png b/src/main/resources/assets/bloodmagic/textures/block/hellforged_block_default.png similarity index 100% rename from src/main/resources/assets/bloodmagic/textures/block/hellforged_default.png rename to src/main/resources/assets/bloodmagic/textures/block/hellforged_block_default.png diff --git a/src/main/resources/assets/bloodmagic/textures/block/hellforged_destructive.png b/src/main/resources/assets/bloodmagic/textures/block/hellforged_block_destructive.png similarity index 100% rename from src/main/resources/assets/bloodmagic/textures/block/hellforged_destructive.png rename to src/main/resources/assets/bloodmagic/textures/block/hellforged_block_destructive.png diff --git a/src/main/resources/assets/bloodmagic/textures/block/hellforged_steadfast.png b/src/main/resources/assets/bloodmagic/textures/block/hellforged_block_steadfast.png similarity index 100% rename from src/main/resources/assets/bloodmagic/textures/block/hellforged_steadfast.png rename to src/main/resources/assets/bloodmagic/textures/block/hellforged_block_steadfast.png diff --git a/src/main/resources/assets/bloodmagic/textures/block/hellforged_vengeful.png b/src/main/resources/assets/bloodmagic/textures/block/hellforged_block_vengeful.png similarity index 100% rename from src/main/resources/assets/bloodmagic/textures/block/hellforged_vengeful.png rename to src/main/resources/assets/bloodmagic/textures/block/hellforged_block_vengeful.png From 94993c580a57cf09fa25cc293125ff7e5f04a304 Mon Sep 17 00:00:00 2001 From: stellanera Date: Sat, 8 Nov 2025 15:22:07 +0100 Subject: [PATCH 5/8] node beams work now --- .../datagen/provider/BMItemTagProvider.java | 6 ++ .../datagen/provider/BMLanguageProvider.java | 7 ++ .../assets/bloodmagic/lang/en_us.json | 5 ++ .../models/item/node_upgrade_amount.json | 6 ++ .../models/item/node_upgrade_speed.json | 6 ++ .../bloodmagic/tags/item/node_debugger.json | 10 +++ .../client/event/ClientModEventHandler.java | 6 +- .../render/blockentity/NodeRenderer.java | 82 ++++++++--------- .../client/screen/NodeFilterScreen.java | 41 +++++++++ .../client/screen/NodeMasterScreen.java | 40 +++++++++ .../common/block/MasterNodeBlock.java | 23 +++++ .../common/block/RoutingNodeBlock.java | 12 ++- .../common/blockentity/FilterNodeTile.java | 9 +- .../common/blockentity/MasterNodeTile.java | 12 ++- .../bloodmagic/common/item/BMItems.java | 2 + .../bloodmagic/common/menu/BMMenus.java | 3 + .../common/menu/LivingStationMenu.java | 2 +- .../common/menu/NodeFilterMenu.java | 35 ++++++++ .../common/menu/NodeMasterMenu.java | 83 ++++++++++++++++++ .../bloodmagic/common/tag/BMTags.java | 2 + .../textures/gui/container/filter_item.png | Bin 0 -> 17389 bytes .../textures/gui/container/node_filter.png | Bin 0 -> 1590 bytes .../textures/gui/container/node_master.png | Bin 0 -> 942 bytes .../textures/item/node_upgrade_amount.png | Bin 0 -> 927 bytes .../textures/item/node_upgrade_speed.png | Bin 0 -> 586 bytes 25 files changed, 334 insertions(+), 58 deletions(-) create mode 100644 src/generated/resources/assets/bloodmagic/models/item/node_upgrade_amount.json create mode 100644 src/generated/resources/assets/bloodmagic/models/item/node_upgrade_speed.json create mode 100644 src/generated/resources/data/bloodmagic/tags/item/node_debugger.json create mode 100644 src/main/java/wayoftime/bloodmagic/client/screen/NodeFilterScreen.java create mode 100644 src/main/java/wayoftime/bloodmagic/client/screen/NodeMasterScreen.java create mode 100644 src/main/java/wayoftime/bloodmagic/common/menu/NodeFilterMenu.java create mode 100644 src/main/java/wayoftime/bloodmagic/common/menu/NodeMasterMenu.java create mode 100644 src/main/resources/assets/bloodmagic/textures/gui/container/filter_item.png create mode 100644 src/main/resources/assets/bloodmagic/textures/gui/container/node_filter.png create mode 100644 src/main/resources/assets/bloodmagic/textures/gui/container/node_master.png create mode 100644 src/main/resources/assets/bloodmagic/textures/item/node_upgrade_amount.png create mode 100644 src/main/resources/assets/bloodmagic/textures/item/node_upgrade_speed.png diff --git a/src/datagen/java/wayoftime/bloodmagic/datagen/provider/BMItemTagProvider.java b/src/datagen/java/wayoftime/bloodmagic/datagen/provider/BMItemTagProvider.java index 9d2a04d277..20f2270c65 100644 --- a/src/datagen/java/wayoftime/bloodmagic/datagen/provider/BMItemTagProvider.java +++ b/src/datagen/java/wayoftime/bloodmagic/datagen/provider/BMItemTagProvider.java @@ -6,6 +6,7 @@ import net.minecraft.world.level.block.Block; import net.neoforged.neoforge.common.data.ExistingFileHelper; import wayoftime.bloodmagic.BloodMagic; +import wayoftime.bloodmagic.common.block.BMBlocks; import wayoftime.bloodmagic.common.item.BMItems; import wayoftime.bloodmagic.common.tag.BMTags; @@ -55,5 +56,10 @@ protected void addTags(HolderLookup.Provider provider) { .add(BMItems.SOUL_GEM_COMMON.get()) .add(BMItems.SOUL_GEM_GREATER.get()) .add(BMItems.SOUL_GEM_GRAND.get()); + + tag(BMTags.Items.NODE_DEBUGGER) + .add(BMItems.NODE_ROUTER.get()) + .add(BMBlocks.MASTER_NODE.asItem(), BMBlocks.ROUTING_NODE.asItem(), BMBlocks.INPUT_ROUTING_NODE.asItem(), BMBlocks.OUTPUT_ROUTING_NODE.asItem()) + .addTag(BMTags.Items.SOUL_GEM); } } diff --git a/src/datagen/java/wayoftime/bloodmagic/datagen/provider/BMLanguageProvider.java b/src/datagen/java/wayoftime/bloodmagic/datagen/provider/BMLanguageProvider.java index 4dc14d316f..73eb563b50 100644 --- a/src/datagen/java/wayoftime/bloodmagic/datagen/provider/BMLanguageProvider.java +++ b/src/datagen/java/wayoftime/bloodmagic/datagen/provider/BMLanguageProvider.java @@ -148,6 +148,13 @@ protected void addTranslations() { add(BMBlocks.OUTPUT_ROUTING_NODE, "Output Routing Node"); add(BMItems.NODE_ROUTER.get(), "Node Router"); + add(BMItems.NODE_AMOUNT_UPGRADE.get(), "Basic Routing Logic Upgrade"); + add(BMItems.NODE_SPEED_UPGRADE.get(), "Basic Routing Speed Upgrade"); + + add("gui.bloodmagic.node.master", "Master Routing Node"); + add("gui.bloodmagic.node.input", "Input Routing Node"); + add("gui.bloodmagic.node.output", "Output Routing Node"); + addTooltip("router.connected", "Successfully connected nodes!"); addTooltip("router.pos_cleared", "Cleared stored position!"); addTooltip("router.pos_set", "Stored %s!"); diff --git a/src/generated/resources/assets/bloodmagic/lang/en_us.json b/src/generated/resources/assets/bloodmagic/lang/en_us.json index 5ecf0134e8..0e2ba7f1d5 100644 --- a/src/generated/resources/assets/bloodmagic/lang/en_us.json +++ b/src/generated/resources/assets/bloodmagic/lang/en_us.json @@ -48,6 +48,9 @@ "commands.bloodmagic.upgrade.set": "Set %s to %s exp for %s", "fluid.bloodmagic.doubt_fluid": "Liquid Doubt", "fluid.bloodmagic.life_essence_fluid": "Life Essence", + "gui.bloodmagic.node.input": "Input Routing Node", + "gui.bloodmagic.node.master": "Master Routing Node", + "gui.bloodmagic.node.output": "Output Routing Node", "item.bloodmagic.blood_orb_apprentice": "Apprentice Blood Orb", "item.bloodmagic.blood_orb_archmage": "Archmage Blood Orb", "item.bloodmagic.blood_orb_magician": "Magician Blood Orb", @@ -62,6 +65,8 @@ "item.bloodmagic.living_plate": "Living Plate", "item.bloodmagic.living_plate.dead": "Formerly Living Plate", "item.bloodmagic.node_router": "Node Router", + "item.bloodmagic.node_upgrade_amount": "Basic Routing Logic Upgrade", + "item.bloodmagic.node_upgrade_speed": "Basic Routing Speed Upgrade", "item.bloodmagic.raw_will": "Raw Will", "item.bloodmagic.sacrificial_dagger": "Sacrificial Dagger", "item.bloodmagic.soul_gem_common": "Common Tartaric Gem", diff --git a/src/generated/resources/assets/bloodmagic/models/item/node_upgrade_amount.json b/src/generated/resources/assets/bloodmagic/models/item/node_upgrade_amount.json new file mode 100644 index 0000000000..15bf6c90f1 --- /dev/null +++ b/src/generated/resources/assets/bloodmagic/models/item/node_upgrade_amount.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "bloodmagic:item/node_upgrade_amount" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/bloodmagic/models/item/node_upgrade_speed.json b/src/generated/resources/assets/bloodmagic/models/item/node_upgrade_speed.json new file mode 100644 index 0000000000..3f7fcb757a --- /dev/null +++ b/src/generated/resources/assets/bloodmagic/models/item/node_upgrade_speed.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "bloodmagic:item/node_upgrade_speed" + } +} \ No newline at end of file diff --git a/src/generated/resources/data/bloodmagic/tags/item/node_debugger.json b/src/generated/resources/data/bloodmagic/tags/item/node_debugger.json new file mode 100644 index 0000000000..f4c1010004 --- /dev/null +++ b/src/generated/resources/data/bloodmagic/tags/item/node_debugger.json @@ -0,0 +1,10 @@ +{ + "values": [ + "bloodmagic:node_router", + "bloodmagic:routing_node_master", + "bloodmagic:routing_node", + "bloodmagic:routing_node_input", + "bloodmagic:routing_node_output", + "#bloodmagic:soul_gems" + ] +} \ No newline at end of file diff --git a/src/main/java/wayoftime/bloodmagic/client/event/ClientModEventHandler.java b/src/main/java/wayoftime/bloodmagic/client/event/ClientModEventHandler.java index 08e0044e3e..5c1221b924 100644 --- a/src/main/java/wayoftime/bloodmagic/client/event/ClientModEventHandler.java +++ b/src/main/java/wayoftime/bloodmagic/client/event/ClientModEventHandler.java @@ -10,11 +10,9 @@ import net.neoforged.neoforge.client.event.EntityRenderersEvent; import net.neoforged.neoforge.client.event.RegisterMenuScreensEvent; import wayoftime.bloodmagic.BloodMagic; -import wayoftime.bloodmagic.client.screen.TrainerScreen; +import wayoftime.bloodmagic.client.screen.*; import wayoftime.bloodmagic.common.menu.BMMenus; import wayoftime.bloodmagic.client.render.entity.layer.LivingElytraLayer; -import wayoftime.bloodmagic.client.screen.ARCScreen; -import wayoftime.bloodmagic.client.screen.LivingStationScreen; import wayoftime.bloodmagic.common.datacomponent.BMDataComponents; import wayoftime.bloodmagic.common.datacomponent.EnumWillType; import wayoftime.bloodmagic.common.item.BMItems; @@ -47,5 +45,7 @@ public static void registerScreens(RegisterMenuScreensEvent event) { event.register(BMMenus.ARC.get(), ARCScreen::new); event.register(BMMenus.LIVING_STATION.get(), LivingStationScreen::new); event.register(BMMenus.TRAINER.get(), TrainerScreen::new); + event.register(BMMenus.MASTER_NODE.get(), NodeMasterScreen::new); + event.register(BMMenus.FILTERED_NODE.get(), NodeFilterScreen::new); } } \ No newline at end of file diff --git a/src/main/java/wayoftime/bloodmagic/client/render/blockentity/NodeRenderer.java b/src/main/java/wayoftime/bloodmagic/client/render/blockentity/NodeRenderer.java index cf1546290e..c0164c4422 100644 --- a/src/main/java/wayoftime/bloodmagic/client/render/blockentity/NodeRenderer.java +++ b/src/main/java/wayoftime/bloodmagic/client/render/blockentity/NodeRenderer.java @@ -12,18 +12,20 @@ import net.minecraft.client.renderer.texture.OverlayTexture; import net.minecraft.core.BlockPos; import net.minecraft.resources.ResourceLocation; +import net.minecraft.util.Mth; import wayoftime.bloodmagic.BloodMagic; import wayoftime.bloodmagic.common.block.RoutingNodeBlock; import wayoftime.bloodmagic.common.blockentity.RoutingNodeTile; -import wayoftime.bloodmagic.common.item.BMItems; +import wayoftime.bloodmagic.common.tag.BMTags; public class NodeRenderer implements BlockEntityRenderer { - public static final ResourceLocation DEFAULT = BloodMagic.rl("textures/block/crystal_default.png"); - public static final ResourceLocation CORROSIVE = BloodMagic.rl("textures/block/crystal_corrosive.png"); - public static final ResourceLocation DESTRUCTIVE = BloodMagic.rl("textures/block/crystal_destructive.png"); - public static final ResourceLocation STEADFAST = BloodMagic.rl("textures/block/crystal_steadfast.png"); - public static final ResourceLocation VENGEFUL = BloodMagic.rl("textures/block/crystal_vengeful.png"); + public static final ResourceLocation BEAM = ResourceLocation.withDefaultNamespace("textures/entity/beacon_beam.png"); + public static final int DEFAULT = 0x91CCC6; + public static final int CORROSIVE = 0xA7CE90; + public static final int DESTRUCTIVE = 0xD9BFA2; + public static final int STEADFAST = 0x9794CD; + public static final int VENGEFUL = 0xCFB98F; public NodeRenderer(BlockEntityRendererProvider.Context context) { } @@ -39,8 +41,8 @@ public void render(RoutingNodeTile node, float partialTick, PoseStack poseStack, } boolean shouldRenderLine = BloodMagic.CLIENT_CONFIG.ALWAYS_RENDER_NODE_LINES.get() // config override || node.getBlockState().getValue(RoutingNodeBlock.RENDER_LINE) // node override - || player.getMainHandItem().is(BMItems.NODE_ROUTER) // has router in mainhand -> maybe should be a tag and also check curio? routing glasses, anyone? - || player.getOffhandItem().is(BMItems.NODE_ROUTER); // has router in offhand + || player.getMainHandItem().is(BMTags.Items.NODE_DEBUGGER) + || player.getOffhandItem().is(BMTags.Items.NODE_DEBUGGER); if (!shouldRenderLine) { return; @@ -49,7 +51,7 @@ public void render(RoutingNodeTile node, float partialTick, PoseStack poseStack, long gameTime = node.getLevel().getGameTime(); float time = (float)Math.floorMod(gameTime, 40) + partialTick; - BlockPos offsetPos = parentPos.subtract(node.getBlockPos()); + BlockPos offsetPos = node.getBlockPos().subtract(parentPos); int xd = offsetPos.getX(); int yd = offsetPos.getY(); int zd = offsetPos.getZ(); @@ -63,8 +65,9 @@ public void render(RoutingNodeTile node, float partialTick, PoseStack poseStack, poseStack.translate(0.5f, 0.5f, 0.5f); poseStack.mulPose(Axis.YP.rotationDegrees(-rotYaw)); poseStack.mulPose(Axis.XN.rotationDegrees(rotPitch - 90)); + poseStack.translate(0, -distance, 0); - ResourceLocation kind = switch (node.getBlockState().getValue(RoutingNodeBlock.WILL)) { + int colour = switch (node.getBlockState().getValue(RoutingNodeBlock.WILL)) { case DEFAULT -> DEFAULT; case CORROSIVE -> CORROSIVE; case DESTRUCTIVE -> DESTRUCTIVE; @@ -72,7 +75,7 @@ public void render(RoutingNodeTile node, float partialTick, PoseStack poseStack, case VENGEFUL -> VENGEFUL; }; - renderBeaconBeam(poseStack, bufferSource, kind, time, (float) distance, 0.06f, 0.1f, node.getBlockState().getValue(RoutingNodeBlock.ENABLED)); + renderBeaconBeam(poseStack, bufferSource, BEAM, colour, time, (float) distance, 0.06f, node.getBlockState().getValue(RoutingNodeBlock.ENABLED)); poseStack.popPose(); } @@ -80,18 +83,23 @@ public static void renderBeaconBeam( PoseStack poseStack, MultiBufferSource bufferSource, ResourceLocation beamLocation, + int colour, float time, float height, float beamRadius, - float glowRadius, boolean isConnected ) { - poseStack.pushPose(); + float f1 = height < 0 ? time : -time; + float f2 = Mth.frac(f1 * 0.2F - (float)Mth.floor(f1 * 0.1F)); + float v1 = -1 + f2; + float v0 = height * (0.5F / beamRadius) + v1; + poseStack.pushPose(); poseStack.mulPose(Axis.YP.rotationDegrees(time * 2.25F - 45.0F)); renderPart( poseStack, bufferSource.getBuffer(RenderType.beaconBeam(beamLocation, false)), + colour, 0, height, 0.0F, @@ -102,22 +110,8 @@ public static void renderBeaconBeam( 0.0F, 0.0F, -beamRadius, - isConnected - ); - poseStack.popPose(); - renderPart( - poseStack, - bufferSource.getBuffer(RenderType.beaconBeam(beamLocation, true)), - 0, - height, - -glowRadius, - -glowRadius, - glowRadius, - -glowRadius, - -glowRadius, - glowRadius, - glowRadius, - glowRadius, + v0, + v1, isConnected ); poseStack.popPose(); @@ -125,6 +119,7 @@ public static void renderBeaconBeam( private static void renderPart( PoseStack poseStack, VertexConsumer consumer, + int colour, int minY, float maxY, float x1, @@ -135,49 +130,50 @@ private static void renderPart( float z3, float x4, float z4, + float v0, + float v1, boolean isConnected ) { PoseStack.Pose posestack$pose = poseStack.last(); renderQuad( - posestack$pose, consumer, minY, maxY, x1, z1, x2, z2, isConnected + posestack$pose, consumer, colour, minY, maxY, x1, z1, x2, z2, v0, v1, isConnected ); renderQuad( - posestack$pose, consumer, minY, maxY, x4, z4, x3, z3, isConnected + posestack$pose, consumer, colour, minY, maxY, x4, z4, x3, z3, v0, v1, isConnected ); renderQuad( - posestack$pose, consumer, minY, maxY, x2, z2, x4, z4, isConnected + posestack$pose, consumer, colour, minY, maxY, x2, z2, x4, z4, v0, v1, isConnected ); renderQuad( - posestack$pose, consumer, minY, maxY, x3, z3, x1, z1, isConnected + posestack$pose, consumer, colour, minY, maxY, x3, z3, x1, z1, v0, v1, isConnected ); } private static void renderQuad( PoseStack.Pose pose, VertexConsumer consumer, + int colour, int minY, float maxY, float minX, float minZ, float maxX, float maxZ, + float v0, + float v1, boolean isConnected ) { - float minU = 1/16.0f; - float maxU = 15/16.0f; - float minV = 1/16.0f; - float maxV = 15/16.0f; - addVertex(pose, consumer, maxY, minX, minZ, maxU, minV, isConnected); - addVertex(pose, consumer, minY, minX, minZ, maxU, maxV, isConnected); - addVertex(pose, consumer, minY, maxX, maxZ, minU, maxV, isConnected); - addVertex(pose, consumer, maxY, maxX, maxZ, minU, minV, isConnected); + addVertex(pose, consumer, colour, maxY, minX, minZ, 1, v0, isConnected); + addVertex(pose, consumer, colour, minY, minX, minZ, 1, v1, isConnected); + addVertex(pose, consumer, colour, minY, maxX, maxZ, 0, v1, isConnected); + addVertex(pose, consumer, colour, maxY, maxX, maxZ, 0, v0, isConnected); } private static void addVertex( - PoseStack.Pose pose, VertexConsumer consumer, float y, float x, float z, float u, float v, boolean isConnected + PoseStack.Pose pose, VertexConsumer consumer, int colour, float y, float x, float z, float u, float v, boolean isConnected ) { consumer.addVertex(pose, x, y, z) - .setColor(isConnected ? 0xFFFFFF : 0x666666) + .setColor((isConnected ? colour : 0x666666)) .setUv(u, v) .setOverlay(OverlayTexture.NO_OVERLAY) .setLight(15728880) diff --git a/src/main/java/wayoftime/bloodmagic/client/screen/NodeFilterScreen.java b/src/main/java/wayoftime/bloodmagic/client/screen/NodeFilterScreen.java new file mode 100644 index 0000000000..df9f4bd8b4 --- /dev/null +++ b/src/main/java/wayoftime/bloodmagic/client/screen/NodeFilterScreen.java @@ -0,0 +1,41 @@ +package wayoftime.bloodmagic.client.screen; + +import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.client.gui.components.Button; +import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen; +import net.minecraft.network.chat.Component; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.entity.player.Inventory; +import wayoftime.bloodmagic.BloodMagic; +import wayoftime.bloodmagic.common.menu.NodeFilterMenu; + +public class NodeFilterScreen extends AbstractContainerScreen { + + private static final ResourceLocation background = BloodMagic.rl("textures/gui/container/node_filer.png"); + public NodeFilterScreen(NodeFilterMenu menu, Inventory playerInventory, Component title) { + super(menu, playerInventory, title); + } + + @Override + protected void init() { + addRenderableWidget(Button.builder(Component.literal("<"), button -> sendButtonClick(1)) + .pos(leftPos + 16, topPos + 34) + .size(8, 20) + .build() + ); + addRenderableWidget(Button.builder(Component.literal(">"), button -> sendButtonClick(2)) + .pos(leftPos + 44, topPos + 34) + .size(8, 20) + .build() + ); + } + + @Override + protected void renderBg(GuiGraphics guiGraphics, float partialTick, int mouseX, int mouseY) { + guiGraphics.blit(background, leftPos, topPos, 0, 0, imageWidth, imageHeight); + } + + private void sendButtonClick(int id) { + this.minecraft.gameMode.handleInventoryButtonClick(this.menu.containerId, id); + } +} diff --git a/src/main/java/wayoftime/bloodmagic/client/screen/NodeMasterScreen.java b/src/main/java/wayoftime/bloodmagic/client/screen/NodeMasterScreen.java new file mode 100644 index 0000000000..6f0791a776 --- /dev/null +++ b/src/main/java/wayoftime/bloodmagic/client/screen/NodeMasterScreen.java @@ -0,0 +1,40 @@ +package wayoftime.bloodmagic.client.screen; + +import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen; +import net.minecraft.network.chat.Component; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.entity.player.Inventory; +import wayoftime.bloodmagic.BloodMagic; +import wayoftime.bloodmagic.common.menu.NodeMasterMenu; + +public class NodeMasterScreen extends AbstractContainerScreen { + + private final ResourceLocation background = ResourceLocation.fromNamespaceAndPath(BloodMagic.MODID, "textures/gui/container/node_master.png"); + public NodeMasterScreen(NodeMasterMenu menu, Inventory playerInventory, Component title) { + super(menu, playerInventory, title); + this.imageWidth = 176; + this.imageHeight = 125; + + this.inventoryLabelY = 28; + } + + @Override + public void init() + { + super.init(); + this.leftPos = (this.width - this.imageWidth) / 2; + this.topPos = (this.height - this.imageHeight) / 2; + } + + @Override + public void render(GuiGraphics guiGraphics, int mouseX, int mouseY, float partialTick) { + super.render(guiGraphics, mouseX, mouseY, partialTick); + this.renderTooltip(guiGraphics, mouseX, mouseY); + } + + @Override + protected void renderBg(GuiGraphics guiGraphics, float partialTick, int mouseX, int mouseY) { + guiGraphics.blit(background, leftPos, topPos, 0, 0, imageWidth, imageHeight); + } +} diff --git a/src/main/java/wayoftime/bloodmagic/common/block/MasterNodeBlock.java b/src/main/java/wayoftime/bloodmagic/common/block/MasterNodeBlock.java index 5edc01e868..ca261311ae 100644 --- a/src/main/java/wayoftime/bloodmagic/common/block/MasterNodeBlock.java +++ b/src/main/java/wayoftime/bloodmagic/common/block/MasterNodeBlock.java @@ -1,11 +1,16 @@ package wayoftime.bloodmagic.common.block; import net.minecraft.core.BlockPos; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.InteractionResult; +import net.minecraft.world.MenuProvider; +import net.minecraft.world.entity.player.Player; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.entity.BlockEntityTicker; import net.minecraft.world.level.block.entity.BlockEntityType; import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.BlockHitResult; import org.jetbrains.annotations.Nullable; import wayoftime.bloodmagic.common.blockentity.BMTiles; import wayoftime.bloodmagic.common.blockentity.MasterNodeTile; @@ -16,6 +21,24 @@ public MasterNodeBlock() { super(); } + @Override + protected InteractionResult useWithoutItem(BlockState state, Level level, BlockPos pos, Player player, BlockHitResult hitResult) { + if (!level.isClientSide && player instanceof ServerPlayer serverPlayer) { + serverPlayer.openMenu(state.getMenuProvider(level, pos)); + } + return InteractionResult.sidedSuccess(level.isClientSide); + } + + @Nullable + @Override + protected MenuProvider getMenuProvider(BlockState state, Level level, BlockPos pos) { + BlockEntity BE = level.getBlockEntity(pos); + if (!(BE instanceof MasterNodeTile tile)) { + return null; + } + return tile; + } + @Override public @Nullable BlockEntityTicker getTicker(Level level, BlockState state, BlockEntityType blockEntityType) { return BlockEntityHelper.getTicker(blockEntityType, BMTiles.MASTER_ROUTING_NODE.get(), MasterNodeTile::tick); diff --git a/src/main/java/wayoftime/bloodmagic/common/block/RoutingNodeBlock.java b/src/main/java/wayoftime/bloodmagic/common/block/RoutingNodeBlock.java index f3306fc4f9..adb37e57ea 100644 --- a/src/main/java/wayoftime/bloodmagic/common/block/RoutingNodeBlock.java +++ b/src/main/java/wayoftime/bloodmagic/common/block/RoutingNodeBlock.java @@ -2,6 +2,7 @@ import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; +import net.minecraft.core.particles.DustParticleOptions; import net.minecraft.server.level.ServerLevel; import net.minecraft.util.RandomSource; import net.minecraft.world.InteractionHand; @@ -87,6 +88,13 @@ protected InteractionResult useWithoutItem(BlockState state, Level level, BlockP return super.useWithoutItem(state, level, pos, player, hitResult); } + @Override + public void animateTick(BlockState state, Level level, BlockPos pos, RandomSource random) { + if (!state.getValue(ENABLED) && random.nextFloat() < 0.3) { + level.addParticle(new DustParticleOptions(DustParticleOptions.REDSTONE_PARTICLE_COLOR, 1.1f), pos.getX() + 0.5, pos.getY() + 0.5, pos.getZ() + 0.5f, 0.0, 0.0, 0.0); + } + } + @Override protected void tick(BlockState state, ServerLevel level, BlockPos pos, RandomSource random) { level.setBlock(pos, state.setValue(RENDER_LINE, false), UPDATE_ALL); @@ -95,7 +103,9 @@ protected void tick(BlockState state, ServerLevel level, BlockPos pos, RandomSou @Override protected ItemInteractionResult useItemOn(ItemStack stack, BlockState state, Level level, BlockPos pos, Player player, InteractionHand hand, BlockHitResult hitResult) { if (stack.is(BMTags.Items.SOUL_GEM)) { - level.setBlock(pos, state.setValue(WILL, stack.getOrDefault(BMDataComponents.DEMON_WILL_TYPE, EnumWillType.DEFAULT)), UPDATE_ALL); + EnumWillType gemType = stack.getOrDefault(BMDataComponents.DEMON_WILL_TYPE, EnumWillType.DEFAULT); + EnumWillType setType = state.getValue(WILL) == gemType ? EnumWillType.DEFAULT : gemType; + level.setBlock(pos, state.setValue(WILL, setType), UPDATE_ALL); return ItemInteractionResult.sidedSuccess(level.isClientSide); } diff --git a/src/main/java/wayoftime/bloodmagic/common/blockentity/FilterNodeTile.java b/src/main/java/wayoftime/bloodmagic/common/blockentity/FilterNodeTile.java index a0df73a1b1..287c088ac0 100644 --- a/src/main/java/wayoftime/bloodmagic/common/blockentity/FilterNodeTile.java +++ b/src/main/java/wayoftime/bloodmagic/common/blockentity/FilterNodeTile.java @@ -23,6 +23,7 @@ import wayoftime.bloodmagic.BloodMagic; import wayoftime.bloodmagic.common.block.RoutingNodeBlock; import wayoftime.bloodmagic.common.capability.BMCaps; +import wayoftime.bloodmagic.common.menu.NodeFilterMenu; import wayoftime.bloodmagic.common.routing.IRoutingFilter; import wayoftime.bloodmagic.common.routing.NodeContext; @@ -42,9 +43,6 @@ public FilterNodeTile(BlockPos pos, BlockState state) { this(pos, state, false); } - private Map> itemCapCache = new HashMap<>(); - private Map> fluidCapCache = new HashMap<>(); - public final SimpleContainerData priorities = new SimpleContainerData(6); public final ItemStackHandler filterInv = new ItemStackHandler(6) { @@ -80,14 +78,13 @@ public void propagateNetwork(BiConsumer> collector, } } - // TODO not return null for both below @Override public Component getDisplayName() { - return null; + return Component.translatable("gui.bloodmagic.node." + (isOutput ? "output" : "input")); } @Override public @Nullable AbstractContainerMenu createMenu(int containerId, Inventory playerInventory, Player player) { - return null; + return new NodeFilterMenu(containerId, playerInventory, filterInv, priorities); } } diff --git a/src/main/java/wayoftime/bloodmagic/common/blockentity/MasterNodeTile.java b/src/main/java/wayoftime/bloodmagic/common/blockentity/MasterNodeTile.java index 14fb6a3f6c..25cc46d9ed 100644 --- a/src/main/java/wayoftime/bloodmagic/common/blockentity/MasterNodeTile.java +++ b/src/main/java/wayoftime/bloodmagic/common/blockentity/MasterNodeTile.java @@ -19,6 +19,8 @@ import org.jetbrains.annotations.Nullable; import wayoftime.bloodmagic.BloodMagic; import wayoftime.bloodmagic.common.block.BMBlocks; +import wayoftime.bloodmagic.common.item.BMItems; +import wayoftime.bloodmagic.common.menu.NodeMasterMenu; import wayoftime.bloodmagic.common.routing.IRoutingFilter; import java.util.*; @@ -43,8 +45,8 @@ public int getSlotLimit(int slot) { public boolean isItemValid(int slot, ItemStack stack) { return switch (slot) { // TODO replace with the actual upgrades after adding them - case 0 -> stack.is(BMBlocks.RUNE_CAPACITY.item()); - case 1 -> stack.is(BMBlocks.RUNE_ACCELERATION.item()); + case 0 -> stack.is(BMItems.NODE_AMOUNT_UPGRADE.get()); + case 1 -> stack.is(BMItems.NODE_SPEED_UPGRADE.get()); default -> false; }; } @@ -87,22 +89,24 @@ public boolean addToNetwork(BlockPos parent) { protected void loadAdditional(CompoundTag tag, HolderLookup.Provider registries) { super.loadAdditional(tag, registries); ticks = tag.getInt("ticks"); + upgradeInv.deserializeNBT(registries, tag.getCompound("upgrades")); } @Override protected void saveAdditional(CompoundTag tag, HolderLookup.Provider registries) { super.saveAdditional(tag, registries); tag.putInt("ticks", ticks % 20); + tag.put("upgrades", upgradeInv.serializeNBT(registries)); } // TODO fix these two @Override public Component getDisplayName() { - return null; + return Component.translatable("gui.bloodmagic.node.master"); } @Override public @Nullable AbstractContainerMenu createMenu(int containerId, Inventory playerInventory, Player player) { - return null; + return new NodeMasterMenu(containerId, playerInventory, this.upgradeInv); } } diff --git a/src/main/java/wayoftime/bloodmagic/common/item/BMItems.java b/src/main/java/wayoftime/bloodmagic/common/item/BMItems.java index 99410eec10..59a502fee5 100644 --- a/src/main/java/wayoftime/bloodmagic/common/item/BMItems.java +++ b/src/main/java/wayoftime/bloodmagic/common/item/BMItems.java @@ -36,6 +36,8 @@ public class BMItems { public static final DeferredHolder ORB_TRANSCENDENT = BASIC_ITEMS.register("blood_orb_transcendent", BloodOrbItem::new); public static final DeferredHolder NODE_ROUTER = BASIC_ITEMS.register("node_router", NodeRouterItem::new); + public static final DeferredHolder NODE_AMOUNT_UPGRADE = BASIC_ITEMS.register("node_upgrade_amount", () -> new Item(new Item.Properties())); + public static final DeferredHolder NODE_SPEED_UPGRADE = BASIC_ITEMS.register("node_upgrade_speed", () -> new Item(new Item.Properties().stacksTo(19))); private static Supplier makeLivingArmour(ArmorItem.Type type) { return () -> new ArmorItem(BMMaterialsAndTiers.LIVING_ARMOUR_MATERIAL, type, new Item.Properties().durability(type.getDurability(33))); diff --git a/src/main/java/wayoftime/bloodmagic/common/menu/BMMenus.java b/src/main/java/wayoftime/bloodmagic/common/menu/BMMenus.java index 514a78a8ee..fd801e841e 100644 --- a/src/main/java/wayoftime/bloodmagic/common/menu/BMMenus.java +++ b/src/main/java/wayoftime/bloodmagic/common/menu/BMMenus.java @@ -18,6 +18,9 @@ public class BMMenus { public static final DeferredHolder, MenuType> TRAINER = MENUS.register("trainer", () -> IMenuTypeExtension.create(TrainerMenu::new)); + public static final DeferredHolder, MenuType> MASTER_NODE = MENUS.register("node_master", () -> new MenuType<>(NodeMasterMenu::new, FeatureFlags.DEFAULT_FLAGS)); + public static final DeferredHolder, MenuType> FILTERED_NODE = MENUS.register("node_filtered", () -> new MenuType<>(NodeFilterMenu::new, FeatureFlags.DEFAULT_FLAGS)); + public static void register(IEventBus modbus) { MENUS.register(modbus); } diff --git a/src/main/java/wayoftime/bloodmagic/common/menu/LivingStationMenu.java b/src/main/java/wayoftime/bloodmagic/common/menu/LivingStationMenu.java index 0bf25492de..473fbe348b 100644 --- a/src/main/java/wayoftime/bloodmagic/common/menu/LivingStationMenu.java +++ b/src/main/java/wayoftime/bloodmagic/common/menu/LivingStationMenu.java @@ -34,7 +34,7 @@ public LivingStationMenu(int containerId, Inventory playerInventory, IItemHandle playerInvStart = inv.getSlots(); playerInvEnd = playerInvStart + 27; hotbarStart = playerInvEnd + 1; - hotbarEnd = hotbarStart + 8; + hotbarEnd = hotbarStart + 9; // TODO whether or not something can go into a given slot is essentially duplicated between here and the actual inventory... this.addSlot(new SlotItemHandler(inv, 0, 12, 22) { diff --git a/src/main/java/wayoftime/bloodmagic/common/menu/NodeFilterMenu.java b/src/main/java/wayoftime/bloodmagic/common/menu/NodeFilterMenu.java new file mode 100644 index 0000000000..1668ccd2b0 --- /dev/null +++ b/src/main/java/wayoftime/bloodmagic/common/menu/NodeFilterMenu.java @@ -0,0 +1,35 @@ +package wayoftime.bloodmagic.common.menu; + +import net.minecraft.world.entity.player.Inventory; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.inventory.AbstractContainerMenu; +import net.minecraft.world.inventory.ContainerData; +import net.minecraft.world.inventory.ContainerLevelAccess; +import net.minecraft.world.inventory.SimpleContainerData; +import net.minecraft.world.item.ItemStack; +import net.neoforged.neoforge.items.IItemHandler; +import net.neoforged.neoforge.items.ItemStackHandler; +import wayoftime.bloodmagic.common.block.BMBlocks; + +public class NodeFilterMenu extends AbstractContainerMenu { + public NodeFilterMenu(int containerId, Inventory playerInv) { + this(containerId, playerInv, new ItemStackHandler(6), new SimpleContainerData(6)); + } + + public NodeFilterMenu(int containerId, Inventory playerInv, IItemHandler filterInv, ContainerData priorities) { + super(BMMenus.FILTERED_NODE.get(), containerId); + } + + @Override + public ItemStack quickMoveStack(Player player, int index) { + // TODO at least implement shift-clicking filters out maybe + return ItemStack.EMPTY; + } + + @Override + public boolean stillValid(Player player) { + // TODO add buffer to menu creation and send isOutput so this can be checked properly + return AbstractContainerMenu.stillValid(ContainerLevelAccess.NULL, player, BMBlocks.INPUT_ROUTING_NODE.block().get()) + || AbstractContainerMenu.stillValid(ContainerLevelAccess.NULL, player, BMBlocks.OUTPUT_ROUTING_NODE.block().get()); + } +} diff --git a/src/main/java/wayoftime/bloodmagic/common/menu/NodeMasterMenu.java b/src/main/java/wayoftime/bloodmagic/common/menu/NodeMasterMenu.java new file mode 100644 index 0000000000..70ba140ec6 --- /dev/null +++ b/src/main/java/wayoftime/bloodmagic/common/menu/NodeMasterMenu.java @@ -0,0 +1,83 @@ +package wayoftime.bloodmagic.common.menu; + + +import net.minecraft.world.entity.player.Inventory; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.inventory.AbstractContainerMenu; +import net.minecraft.world.inventory.ContainerLevelAccess; +import net.minecraft.world.inventory.Slot; +import net.minecraft.world.item.ItemStack; +import net.neoforged.neoforge.items.IItemHandler; +import net.neoforged.neoforge.items.ItemStackHandler; +import net.neoforged.neoforge.items.SlotItemHandler; +import wayoftime.bloodmagic.common.block.BMBlocks; + +public class NodeMasterMenu extends AbstractContainerMenu { + + public NodeMasterMenu(int containerId, Inventory playerInv) { + this(containerId, playerInv, new ItemStackHandler(2)); + } + + private int playerInvStart; + private int playerInvEnd; + private int hotbarStart; + private int hotbarEnd; + public NodeMasterMenu(int containerId, Inventory playerInv, IItemHandler inv) { + super(BMMenus.MASTER_NODE.get(), containerId); + playerInvStart = inv.getSlots(); + playerInvEnd = playerInvStart + 27; + hotbarStart = playerInvEnd + 1; + hotbarEnd = hotbarStart + 9; + + this.addSlot(new SlotItemHandler(inv, 0, 62, 20)); + this.addSlot(new SlotItemHandler(inv, 1, 98, 20)); + + // player inv + for (int i = 0; i < 3; i++) { + for (int j = 0; j < 9; j++) { + this.addSlot(new Slot(playerInv, j + i * 9 + 9, 8 + j * 18, 44 + i * 18)); + } + } + + // player hotbar + for (int i = 0; i < 9; i++) { + this.addSlot(new Slot(playerInv, i, 8 + i * 18, 102)); + } + } + + @Override + public ItemStack quickMoveStack(Player player, int index) { + ItemStack movedStack = ItemStack.EMPTY; + Slot movedSlot = this.slots.get(index); + + if (movedSlot.hasItem()) { + ItemStack rawStack = movedSlot.getItem(); + movedStack = rawStack.copy(); + + if (index <= playerInvStart) { + if (!this.moveItemStackTo(rawStack, playerInvStart, hotbarEnd, false)) { + return ItemStack.EMPTY; + } + } + + if (index > playerInvStart) { + if (!this.moveItemStackTo(rawStack, 0, playerInvStart, false)) { + return ItemStack.EMPTY; + } + } + + if (rawStack.isEmpty()) { + movedSlot.set(ItemStack.EMPTY); + } else { + movedSlot.setChanged(); + } + } + + return movedStack; + } + + @Override + public boolean stillValid(Player player) { + return AbstractContainerMenu.stillValid(ContainerLevelAccess.NULL, player, BMBlocks.MASTER_NODE.block().get()); + } +} diff --git a/src/main/java/wayoftime/bloodmagic/common/tag/BMTags.java b/src/main/java/wayoftime/bloodmagic/common/tag/BMTags.java index 6d574c13dd..42754ba32a 100644 --- a/src/main/java/wayoftime/bloodmagic/common/tag/BMTags.java +++ b/src/main/java/wayoftime/bloodmagic/common/tag/BMTags.java @@ -16,6 +16,8 @@ public class BMTags { public static class Items { public static final TagKey SOUL_GEM = tag(bm("soul_gems")); + public static final TagKey NODE_DEBUGGER = tag(bm("node_debugger")); + public static final TagKey STORAGE_BLOCKS_HELLFORGED = fromBlock(Blocks.STORAGE_BLOCKS_HELLFORGED); public static final TagKey ARC_TOOL = tag(bm("arc_tool")); diff --git a/src/main/resources/assets/bloodmagic/textures/gui/container/filter_item.png b/src/main/resources/assets/bloodmagic/textures/gui/container/filter_item.png new file mode 100644 index 0000000000000000000000000000000000000000..804db55592806642265c8cc2ad7da2ff56c1fb59 GIT binary patch literal 17389 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 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/bloodmagic/textures/gui/container/node_filter.png b/src/main/resources/assets/bloodmagic/textures/gui/container/node_filter.png new file mode 100644 index 0000000000000000000000000000000000000000..a92dff1bc86ddd4c0289f4a07e1ca9a3feecd33b GIT binary patch literal 1590 zcmeAS@N?(olHy`uVBq!ia0y~yU<5K5893O0R7}x|G$5xn)7d$|)7e>}peR2rGbfdS zL1SX=L|c!;0V1vb!Aq4y*}J@zM+ShB-{YaJ_l zz1V6#y>q*)c5pR4;P03{d-9_0DHZWS8G?_SPye=fKlgC$cSfhZXF@h7GXmJ7xL_CMGemi(R?M~ClL;;S}Mo+|FQ2+&wjRC?e3BUkry=^-}VbCY~VJ@+V;0L=XS5~f&V-)nY#5$ z`Oef$ip$P?sJx(DddH5u%ujL!JDGXxUQSZ9oHXC-#Pi1Q#=n;7Tqx%*S--P5d*0(O zj2@TQOv`U*c23yhaPzg?`*&IMZ|^Uk_4zmBa*d)rCs&-e1;z_olDE4HkOqRE&b#Y@ z6lZ})WHAE+-yslY6xHx*01C2~c>21sKjmN%;}?oN>gUA3z+&X-;uunK>+Ri(xwow( z8Uk0H@MBwKI>V7CptwSym@i%D>(Z=Panr5|t2{r>S^mK8&)x}Z*DsOT9Q-4d_dkQTZ?)CjYZA#9_e=?zQO6^D*4*5F@6Nk< zVQZ%DvHjP6{=9#9>#|tA=^s9R6kKpoGT4Ai&@NV(>jZtNNhEE_}9V zGS6q5-7Ac1JFNA3>*v>B={L$M)epjnG(aH&EU30=X6LjL`H$( zz{H;-4To12hWvQ;!o7`~p*`gDZr;Z?Wr)TG!H_tzNerNGH-}A-C7BK9|$$WG6^u$UI4yFV9Z++YT{r9t3)o}t1 zZTbJ+Du(xb+& zXwduVx}g5UcJ=@D(Xt9={yOgD_QTzI4FgvbLl^_|uKEkl z7s>+}cH9+r_#y-q7?^ec{xwqo27%~-!2ip>2MRG6tf-tf+xE=jvN=)n+Zi?_&-rE{ zyy2NmIuq9c?FIJmL=a&N4{SKY>f!AMe~TMTj1m#2moqi$ zG9<7%L`Ta;t1~7%SlhRDvMvKS;6P!Ijp3l{zn`zhZhrUw28rYoma~)3O@Dso^Bccf zSB7ok3tYT3pUgRH`22M79Nh$N97cd+mg#{IkY=u`l5+q>Zr6W-;xh|{QuShY9red4zW#vFYIPW5{;f~}5sI?Q84#59J38yI%5 z0Mkgr9F7#f&&4P(K^Km#FOJ22g*mg7Z8LUGiL&lOq*|1}wIa|aw+x&7Ica~}(CiNVr2Jm`@a zEC*D9Ie_g6Q1h($hwJ8W`IOJ$%7GZmv;EKVzU=~sOnfg_?YR?uy_Cd-BKlo qnGaaW=|6Zi>B7ruaR!=zzE{>v7dr$Ryk7Ky%=dKlb6Mw<&;$Ve=SWBZ literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/bloodmagic/textures/gui/container/node_master.png b/src/main/resources/assets/bloodmagic/textures/gui/container/node_master.png new file mode 100644 index 0000000000000000000000000000000000000000..fbdf21f8d6c45fb906cf20b0a98ab3139b57792d GIT binary patch literal 942 zcmeAS@N?(olHy`uVBq!ia0y~yU<5K5893O0R7}x|G!U;i$lZzY=1HA;AcrO0(btiI zVPik{pF~z5Um@8e$d`ekN{xY`p@o6r7f`6-1p`B=0RzLU1O^7H84L{K1#@-<+5jck zlDyqr82*Fcg1yTp14TFsJR*x382Ao>Fr%o3R|8Oxy~NYkmHj0*yO6Q9Z0$&^qan zAM|GxbdU4*bpFyV< z{uZvPw%x&sRU?v_4;HuGVV_Xk7u0pVnW5*0xBulUS3mXKi{sB@gxlJn|MAOu2KTqC z_`ht82E%XZ3yY=*z1}q|`P}K^Kb==}859_RfyTtZfrY`*pbRvQ?MsRL zfxzFd&KkDcE$vvb^;$>JOZt_+1TKUn6j#moyhC)xf02g2ycvnF*IKSE zwwY7Ljn%)EX>4Tx04R}tkv&MmP!xqvTeVdx4rUN>$WWauh>AE$6^me@v=v%)FnQ@8G-*gu zTpR`0f`dPcRRZ7c=mzuY2mGx{LBG@4i2)U&)&c@QK88OgAjz4dR(i zOXs{#EU=QK5T6r|8+1Y9N3P2*zi}=)?B|(+kx9)H3&divgXIopB|{~iCXOhoM*04% z%L?Z$&T6H`TKD8H4Cl3#G}md3AdV#@kc0>sHIz|-g(&SBDJD{M9`o=IJN_iOWO9|k z$gzMbR7j2={11N5)+|g-x=G;}(EVcDAEQ8U7iiXP`}^3onl~*KK!#?ud;=UD z0%JwWUiWx+sB>=r_O#~r1N|X#c%kg92LJ#724YJ`L;!vO=m6}o?8=$|000SaNLh0L z01m~>o^PKj*Rwc0AA5#d}b;z>XxgqM(NsZx#+vV1^S17I7+8qMW8;vnWSo6B9 zsxHQu-71;9aI3VHM4lem!oF@Se6CAJjnpqo4z0~ za?H$i-1WOs@u(`0KD57;9sc|MF{|o z=VJ1L)6Ot{ literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/bloodmagic/textures/item/node_upgrade_speed.png b/src/main/resources/assets/bloodmagic/textures/item/node_upgrade_speed.png new file mode 100644 index 0000000000000000000000000000000000000000..e4422fb52c35e54e021bb3a991ed52f52ad4643a GIT binary patch literal 586 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`jKx9jPK-BC>eK@{Ea{HEjtmSN z`?>!lvI6-E$sR$z3=CCj3=9n|3=F@3LJcn%7)lKo7+xhXFj&oCU=S~uvn$XBD8ZKG z?e4l+bn}!$WMS8?b)rHmSEqUU z|3zSIk93M-}gD6e-_on>{t{zo%L6u##;OS zT@$rh*Uhjl=!t8iAzQTOH@UlUjFGt?UsQOVFZP@)BAc^8e#hKXcRjB-ZoT&A-tMc8 zYwUm5{xwwc+!s8v>-%g){>7~Go(Fat?Ad?v*3K`71JXQ|=RX56fHt~cUT^fTMlIiO ze@T9!qS4Q^C*_XIOI@T&9u)t`bBn#sBcD^s?Z8{dP)qT)6;aDg+NSS2{GzRY zsmS8TnhcL4TMQ3rzx{Bi$l%x-_8sd^Z(hUn;KQp z$D4T=Zf|2e(XCpN{;_%2%D`8TG)s6{8(TM-Z(y0XOf)r8k2&;cTv*@~)yi2-*H$-F z%0!p5F*90JRC^Vyb)O`{P;u+{72fC1HP5%-uD8v-HMRD~)=QIJFRuN#zh;^CZGT Date: Thu, 13 Nov 2025 21:23:09 +0100 Subject: [PATCH 6/8] filter node displays neighbours and swaps (at least priority) correctly, cant test filters as they dont exist yet --- .../client/screen/NodeFilterScreen.java | 138 +++++++++++++++++- .../common/block/FilterNodeBlock.java | 30 ++++ .../common/blockentity/FilterNodeTile.java | 41 +++++- .../bloodmagic/common/item/FilterItem.java | 38 +++++ .../bloodmagic/common/item/TrainerItem.java | 5 +- .../bloodmagic/common/menu/ARCMenu.java | 1 + .../common/menu/AbstractGhostMenu.java | 2 +- .../bloodmagic/common/menu/BMMenus.java | 4 +- .../common/menu/NodeFilterMenu.java | 121 +++++++++++++-- .../bloodmagic/common/menu/TrainerMenu.java | 8 +- .../textures/gui/container/node_filter.png | Bin 1590 -> 1156 bytes 11 files changed, 358 insertions(+), 30 deletions(-) create mode 100644 src/main/java/wayoftime/bloodmagic/common/item/FilterItem.java diff --git a/src/main/java/wayoftime/bloodmagic/client/screen/NodeFilterScreen.java b/src/main/java/wayoftime/bloodmagic/client/screen/NodeFilterScreen.java index df9f4bd8b4..16e38cbac5 100644 --- a/src/main/java/wayoftime/bloodmagic/client/screen/NodeFilterScreen.java +++ b/src/main/java/wayoftime/bloodmagic/client/screen/NodeFilterScreen.java @@ -1,41 +1,163 @@ package wayoftime.bloodmagic.client.screen; +import com.mojang.datafixers.util.Pair; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.Font; import net.minecraft.client.gui.GuiGraphics; import net.minecraft.client.gui.components.Button; import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen; +import net.minecraft.core.Direction; import net.minecraft.network.chat.Component; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.entity.player.Inventory; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.Vec3; import wayoftime.bloodmagic.BloodMagic; import wayoftime.bloodmagic.common.menu.NodeFilterMenu; public class NodeFilterScreen extends AbstractContainerScreen { - private static final ResourceLocation background = BloodMagic.rl("textures/gui/container/node_filer.png"); - public NodeFilterScreen(NodeFilterMenu menu, Inventory playerInventory, Component title) { - super(menu, playerInventory, title); + private static final ResourceLocation background = BloodMagic.rl("textures/gui/container/node_filter.png"); + private static final ResourceLocation selected = BloodMagic.rl("container/ghost_selected"); + // TODO name these better. up means leftmost or topmost... + private static final int upLeft = 109 + 1; + private static final int upTop = 11 + 1; + private static final int midLeft = upLeft + 20; + private static final int midTop = upTop + 20; + private static final int bottomLeft = midLeft + 20; + private static final int bottomTop = midTop + 20; + private final Direction down; + private final Pair downLocation = Pair.of(midLeft, bottomTop); + private final Direction up; + private final Pair upLocation = Pair.of(midLeft, upTop); + private final Direction front; + private final Pair frontLocation = Pair.of(midLeft, midTop); + private final Direction back; + private final Pair backLocation = Pair.of(bottomLeft, bottomTop); + private final Direction left; + private final Pair leftLocation = Pair.of(upLeft, midTop); + private final Direction right; + private final Pair rightLocation = Pair.of(bottomLeft, midTop); + + public NodeFilterScreen(NodeFilterMenu menu, Inventory playerInv, Component title) { + super(menu, playerInv, title); + imageWidth = 176; + imageHeight = 187; + + Vec3 rot = Vec3.directionFromRotation(playerInv.player.getRotationVector()); + Direction playerFacing = Direction.getNearest(rot.x, rot.y, rot.z); + Direction horizontalFacing = playerInv.player.getDirection(); + back = playerFacing; + front = playerFacing.getOpposite(); + left = horizontalFacing.getCounterClockWise(); + right = horizontalFacing.getClockWise(); + if (playerFacing.getAxis().isVertical()) { + up = playerFacing == Direction.DOWN ? horizontalFacing : horizontalFacing.getOpposite(); + down = playerFacing == Direction.DOWN ? horizontalFacing.getOpposite() : horizontalFacing; + } else { + up = Direction.UP; + down = Direction.DOWN; + } + sendButtonClick(front.get3DDataValue()); } @Override protected void init() { - addRenderableWidget(Button.builder(Component.literal("<"), button -> sendButtonClick(1)) - .pos(leftPos + 16, topPos + 34) + super.init(); + + addRenderableWidget(directionButton(down, downLocation)); + addRenderableWidget(directionButton(up, upLocation)); + addRenderableWidget(directionButton(front, frontLocation)); + addRenderableWidget(directionButton(back, backLocation)); + addRenderableWidget(directionButton(left, leftLocation)); + addRenderableWidget(directionButton(right, rightLocation)); + + addRenderableWidget(Button.builder(Component.literal("<"), button -> sendButtonClick(NodeFilterMenu.BUTTON_PRIO_DOWN)) + .pos(leftPos + 61, topPos + 50) .size(8, 20) .build() ); - addRenderableWidget(Button.builder(Component.literal(">"), button -> sendButtonClick(2)) - .pos(leftPos + 44, topPos + 34) + addRenderableWidget(Button.builder(Component.literal(">"), button -> sendButtonClick(NodeFilterMenu.BUTTON_PRIO_UP)) + .pos(leftPos + 89, topPos + 50) .size(8, 20) .build() ); } + private Button directionButton(Direction dir, Pair pos) { + return Button.builder(Component.empty(), getPress(dir)) + .pos(leftPos + pos.getFirst(), topPos + pos.getSecond()) + .size(18, 18) + .build(); + } + + private Button.OnPress getPress(Direction dir) { + return button -> { + if(!(menu.getData(6) == dir.get3DDataValue())) { + sendButtonClick(dir.get3DDataValue()); + } + }; + } + @Override protected void renderBg(GuiGraphics guiGraphics, float partialTick, int mouseX, int mouseY) { guiGraphics.blit(background, leftPos, topPos, 0, 0, imageWidth, imageHeight); } + @Override + protected void renderLabels(GuiGraphics guiGraphics, int mouseX, int mouseY) { + super.renderLabels(guiGraphics, mouseX, mouseY); + // TODO figure out why its 71 + 5 and 51 + 5 instead of 76 and 56 + guiGraphics.drawString(this.font, Component.literal("" + menu.getData(menu.getData(6))), 71 + 5, 51 + 5, 0xFFFFFF, false); + + drawBlock(guiGraphics, up, upLocation.getFirst(), upLocation.getSecond()); + drawBlock(guiGraphics, down, downLocation.getFirst(), downLocation.getSecond()); + drawBlock(guiGraphics, left, leftLocation.getFirst(), leftLocation.getSecond()); + drawBlock(guiGraphics, right, rightLocation.getFirst(), rightLocation.getSecond()); + drawBlock(guiGraphics, front, frontLocation.getFirst(), frontLocation.getSecond()); + drawBlock(guiGraphics, back, backLocation.getFirst(), backLocation.getSecond()); + + Pair activePos = getPosForDir(Direction.from3DDataValue(menu.getData(6))); + guiGraphics.blitSprite(selected, activePos.getFirst() - 3, activePos.getSecond() - 3, 24, 24); + } + + private Pair getPosForDir(Direction dir) { + if (dir == up) { + return upLocation; + } + if (dir == down) { + return downLocation; + } + if (dir == front) { + return frontLocation; + } + if (dir == back) { + return backLocation; + } + if (dir == left) { + return leftLocation; + } + if (dir == right) { + return rightLocation; + } + + return Pair.of(0, 0); + } + + private void drawBlock(GuiGraphics guiGraphics, Direction dir, int x, int y) { + BlockState blockState = this.menu.player.level().getBlockState(this.menu.nodePos.relative(dir)); + Block block = blockState.getBlock(); + ItemStack stack = new ItemStack(block); + guiGraphics.pose().pushPose(); + guiGraphics.pose().translate(x + 3, y + 3, 0); + guiGraphics.pose().scale(0.75f, 0.75f, 0.75f); + guiGraphics.renderItem(stack, 0, 0); + guiGraphics.pose().popPose(); + } + private void sendButtonClick(int id) { - this.minecraft.gameMode.handleInventoryButtonClick(this.menu.containerId, id); + Minecraft.getInstance().gameMode.handleInventoryButtonClick(this.menu.containerId, id); } } diff --git a/src/main/java/wayoftime/bloodmagic/common/block/FilterNodeBlock.java b/src/main/java/wayoftime/bloodmagic/common/block/FilterNodeBlock.java index 40ef3b3e70..d799c062ad 100644 --- a/src/main/java/wayoftime/bloodmagic/common/block/FilterNodeBlock.java +++ b/src/main/java/wayoftime/bloodmagic/common/block/FilterNodeBlock.java @@ -1,10 +1,17 @@ package wayoftime.bloodmagic.common.block; import net.minecraft.core.BlockPos; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.InteractionResult; +import net.minecraft.world.MenuProvider; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.level.Level; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.BlockHitResult; import org.jetbrains.annotations.Nullable; import wayoftime.bloodmagic.common.blockentity.FilterNodeTile; +import wayoftime.bloodmagic.common.blockentity.MasterNodeTile; public class FilterNodeBlock extends RoutingNodeBlock { @@ -14,6 +21,29 @@ public FilterNodeBlock(boolean isOutput) { this.isOutput = isOutput; } + @Override + protected InteractionResult useWithoutItem(BlockState state, Level level, BlockPos pos, Player player, BlockHitResult hitResult) { + if (player.isShiftKeyDown()) { + level.setBlock(pos, state.setValue(RENDER_LINE, true), UPDATE_ALL); + level.scheduleTick(pos, state.getBlock(), 20 * 5); + } + + if (!level.isClientSide && player instanceof ServerPlayer serverPlayer) { + serverPlayer.openMenu(state.getMenuProvider(level, pos), buf -> buf.writeBlockPos(pos).writeBoolean(isOutput)); + } + return InteractionResult.sidedSuccess(level.isClientSide); + } + + @Nullable + @Override + protected MenuProvider getMenuProvider(BlockState state, Level level, BlockPos pos) { + BlockEntity BE = level.getBlockEntity(pos); + if (!(BE instanceof FilterNodeTile tile)) { + return null; + } + return tile; + } + @Override public @Nullable BlockEntity newBlockEntity(BlockPos pos, BlockState state) { return new FilterNodeTile(pos, state, isOutput); diff --git a/src/main/java/wayoftime/bloodmagic/common/blockentity/FilterNodeTile.java b/src/main/java/wayoftime/bloodmagic/common/blockentity/FilterNodeTile.java index 287c088ac0..0d965e4700 100644 --- a/src/main/java/wayoftime/bloodmagic/common/blockentity/FilterNodeTile.java +++ b/src/main/java/wayoftime/bloodmagic/common/blockentity/FilterNodeTile.java @@ -2,6 +2,8 @@ import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; +import net.minecraft.core.HolderLookup; +import net.minecraft.nbt.*; import net.minecraft.network.chat.Component; import net.minecraft.resources.ResourceLocation; import net.minecraft.server.level.ServerLevel; @@ -43,7 +45,7 @@ public FilterNodeTile(BlockPos pos, BlockState state) { this(pos, state, false); } - public final SimpleContainerData priorities = new SimpleContainerData(6); + public int[] priorities = new int[] {0, 0, 0, 0, 0, 0}; public final ItemStackHandler filterInv = new ItemStackHandler(6) { @Override @@ -63,6 +65,21 @@ protected void onContentsChanged(int slot) { } }; + @Override + protected void saveAdditional(CompoundTag tag, HolderLookup.Provider registries) { + super.saveAdditional(tag, registries); + CompoundTag invTag = filterInv.serializeNBT(registries); + tag.put("filter_inv", invTag); + IntArrayTag prioTag = new IntArrayTag(priorities); + tag.put("priorities", prioTag); + } + + @Override + protected void loadAdditional(CompoundTag tag, HolderLookup.Provider registries) { + super.loadAdditional(tag, registries); + filterInv.deserializeNBT(registries, tag.getCompound("filter_inv")); + priorities = tag.getIntArray("priorities"); + } public void propagateNetwork(BiConsumer> collector, boolean requireEnabled) { if (requireEnabled && !getBlockState().getValue(RoutingNodeBlock.ENABLED)) { @@ -85,6 +102,26 @@ public Component getDisplayName() { @Override public @Nullable AbstractContainerMenu createMenu(int containerId, Inventory playerInventory, Player player) { - return new NodeFilterMenu(containerId, playerInventory, filterInv, priorities); + return new NodeFilterMenu(containerId, playerInventory, filterInv, new SimpleContainerData(7) { + private int side; + @Override + public int get(int index) { + if (index < 6) { + return FilterNodeTile.this.priorities[index]; + } else { + return side; + } + } + + @Override + public void set(int index, int value) { + if (index < 6) { + FilterNodeTile.this.priorities[index] = value; + FilterNodeTile.this.setChanged(); + } else { + side = value; + } + } + }, getBlockPos(), isOutput); } } diff --git a/src/main/java/wayoftime/bloodmagic/common/item/FilterItem.java b/src/main/java/wayoftime/bloodmagic/common/item/FilterItem.java new file mode 100644 index 0000000000..50083cb88d --- /dev/null +++ b/src/main/java/wayoftime/bloodmagic/common/item/FilterItem.java @@ -0,0 +1,38 @@ +package wayoftime.bloodmagic.common.item; + +import net.minecraft.network.chat.Component; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.InteractionResultHolder; +import net.minecraft.world.SimpleMenuProvider; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.Level; +import wayoftime.bloodmagic.common.datacomponent.BMDataComponents; + +public class FilterItem extends Item { + + private final String name; + public FilterItem(Properties properties, String name) { + super(properties); + this.name = name; + } + + @Override + public InteractionResultHolder use(Level level, Player player, InteractionHand usedHand) { + ItemStack stack = player.getItemInHand(usedHand); + if (!(stack.getItem() instanceof FilterItem)) { + return InteractionResultHolder.pass(stack); + } + + if (!level.isClientSide) { + /* + player.openMenu(new SimpleMenuProvider( + (containerId, playerInventory, player1) -> new FilterMenu(containerId, playerInventory, stack.get(BMDataComponents.FILTER_INVENTORY)), + Component.translatable("gui.bloodmagic.filter." + name)) + ); + */ + } + return InteractionResultHolder.sidedSuccess(stack, level.isClientSide); + } +} diff --git a/src/main/java/wayoftime/bloodmagic/common/item/TrainerItem.java b/src/main/java/wayoftime/bloodmagic/common/item/TrainerItem.java index 07eaef1356..d417735c46 100644 --- a/src/main/java/wayoftime/bloodmagic/common/item/TrainerItem.java +++ b/src/main/java/wayoftime/bloodmagic/common/item/TrainerItem.java @@ -77,10 +77,9 @@ public void set(int index, int value) { serverPlayer.openMenu( new SimpleMenuProvider( - (id, inv, playerIn) -> new TrainerMenu(id, inv, handler, data, playerIn.getInventory().selected), + (id, inv, playerIn) -> new TrainerMenu(id, inv, handler, data), Component.translatable(getDescriptionId()) - ), - buf -> buf.writeInt(serverPlayer.getInventory().selected) + ) ); } diff --git a/src/main/java/wayoftime/bloodmagic/common/menu/ARCMenu.java b/src/main/java/wayoftime/bloodmagic/common/menu/ARCMenu.java index 456163964a..697c5c63c2 100644 --- a/src/main/java/wayoftime/bloodmagic/common/menu/ARCMenu.java +++ b/src/main/java/wayoftime/bloodmagic/common/menu/ARCMenu.java @@ -52,6 +52,7 @@ public void onTake(Player player, ItemStack stack) { } public ARCMenu(int containerId, Inventory playerInventory, FriendlyByteBuf buf) { + // TODO nonono, bad! just pass the tanks & inv sis this(containerId, playerInventory, (ARCTile) playerInventory.player.level().getBlockEntity(buf.readBlockPos())); } diff --git a/src/main/java/wayoftime/bloodmagic/common/menu/AbstractGhostMenu.java b/src/main/java/wayoftime/bloodmagic/common/menu/AbstractGhostMenu.java index 39c7d157b9..fef2662e6f 100644 --- a/src/main/java/wayoftime/bloodmagic/common/menu/AbstractGhostMenu.java +++ b/src/main/java/wayoftime/bloodmagic/common/menu/AbstractGhostMenu.java @@ -63,7 +63,7 @@ public void clicked(int slotId, int button, ClickType clickType, Player player) // I clicked on the slot with an empty hand. Selecting! updateGhostSelection(tracker.get(0), slotId); BloodMagic.LOGGER.info("selected ghost slot {} index {}", slotId, slot.getSlotIndex()); - tracker.set(0, slot.getSlotIndex()); + setData(0, slot.getSlotIndex()); // Return here to not save the server-side inventory return; } else if (!heldStack.isEmpty() && slotStack.isEmpty() && ghostSlot.isValid(heldStack)) { diff --git a/src/main/java/wayoftime/bloodmagic/common/menu/BMMenus.java b/src/main/java/wayoftime/bloodmagic/common/menu/BMMenus.java index fd801e841e..d4e8510bff 100644 --- a/src/main/java/wayoftime/bloodmagic/common/menu/BMMenus.java +++ b/src/main/java/wayoftime/bloodmagic/common/menu/BMMenus.java @@ -16,10 +16,10 @@ public class BMMenus { public static final DeferredHolder, MenuType> ARC = MENUS.register("arc_menu", () -> IMenuTypeExtension.create(ARCMenu::new)); public static final DeferredHolder, MenuType> LIVING_STATION = MENUS.register("living_station", () -> IMenuTypeExtension.create(LivingStationMenu::new)); - public static final DeferredHolder, MenuType> TRAINER = MENUS.register("trainer", () -> IMenuTypeExtension.create(TrainerMenu::new)); + public static final DeferredHolder, MenuType> TRAINER = MENUS.register("trainer", () -> new MenuType<>(TrainerMenu::new, FeatureFlags.DEFAULT_FLAGS)); public static final DeferredHolder, MenuType> MASTER_NODE = MENUS.register("node_master", () -> new MenuType<>(NodeMasterMenu::new, FeatureFlags.DEFAULT_FLAGS)); - public static final DeferredHolder, MenuType> FILTERED_NODE = MENUS.register("node_filtered", () -> new MenuType<>(NodeFilterMenu::new, FeatureFlags.DEFAULT_FLAGS)); + public static final DeferredHolder, MenuType> FILTERED_NODE = MENUS.register("node_filtered", () -> IMenuTypeExtension.create(NodeFilterMenu::new)); public static void register(IEventBus modbus) { MENUS.register(modbus); diff --git a/src/main/java/wayoftime/bloodmagic/common/menu/NodeFilterMenu.java b/src/main/java/wayoftime/bloodmagic/common/menu/NodeFilterMenu.java index 1668ccd2b0..3cdf119d41 100644 --- a/src/main/java/wayoftime/bloodmagic/common/menu/NodeFilterMenu.java +++ b/src/main/java/wayoftime/bloodmagic/common/menu/NodeFilterMenu.java @@ -1,23 +1,125 @@ package wayoftime.bloodmagic.common.menu; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.network.RegistryFriendlyByteBuf; import net.minecraft.world.entity.player.Inventory; import net.minecraft.world.entity.player.Player; -import net.minecraft.world.inventory.AbstractContainerMenu; -import net.minecraft.world.inventory.ContainerData; -import net.minecraft.world.inventory.ContainerLevelAccess; -import net.minecraft.world.inventory.SimpleContainerData; +import net.minecraft.world.inventory.*; import net.minecraft.world.item.ItemStack; import net.neoforged.neoforge.items.IItemHandler; +import net.neoforged.neoforge.items.IItemHandlerModifiable; import net.neoforged.neoforge.items.ItemStackHandler; +import net.neoforged.neoforge.items.SlotItemHandler; import wayoftime.bloodmagic.common.block.BMBlocks; +import wayoftime.bloodmagic.common.blockentity.BMTiles; +import wayoftime.bloodmagic.common.blockentity.FilterNodeTile; public class NodeFilterMenu extends AbstractContainerMenu { - public NodeFilterMenu(int containerId, Inventory playerInv) { - this(containerId, playerInv, new ItemStackHandler(6), new SimpleContainerData(6)); + + // I'd get the IDs directly from Direction but switch wants a "constant expression" + public static final int DATA_DOWN = 0; + public static final int DATA_UP = 1; + public static final int DATA_NORTH = 2; + public static final int DATA_SOUTH = 3; + public static final int DATA_WEST = 4; + public static final int DATA_EAST = 5; + public static final int DATA_SIDE = 6; + + public static final int BUTTON_PRIO_DOWN = 6; + public static final int BUTTON_PRIO_UP = 7; + public static final int BUTTON_EDIT = 8; + + public NodeFilterMenu(int containerId, Inventory playerInv, RegistryFriendlyByteBuf buf) { + this(containerId, playerInv, new ItemStackHandler(6), new SimpleContainerData(7), buf.readBlockPos(), buf.readBoolean()); } - public NodeFilterMenu(int containerId, Inventory playerInv, IItemHandler filterInv, ContainerData priorities) { + private final ContainerData priorities; + public final BlockPos nodePos; + public final Player player; + public final boolean isOutput; + public NodeFilterMenu(int containerId, Inventory playerInv, IItemHandler filterInv, ContainerData priorities, BlockPos nodePos, boolean isOutput) { super(BMMenus.FILTERED_NODE.get(), containerId); + addDataSlots(priorities); + this.priorities = priorities; + this.nodePos = nodePos; + this.player = playerInv.player; + this.isOutput = isOutput; + + // TODO extract into separate class so this is more sightly + this.addSlot(new SlotItemHandler(filterInv, 0, 71, 33) { + @Override + public boolean mayPlace(ItemStack stack) { + if (stack.isEmpty()) + return false; + return getItemHandler().isItemValid(priorities.get(DATA_SIDE), stack); + } + + @Override + public ItemStack getItem() { + return getItemHandler().getStackInSlot(priorities.get(DATA_SIDE)); + } + + @Override + public void set(ItemStack stack) { + ((IItemHandlerModifiable) this.getItemHandler()).setStackInSlot(priorities.get(DATA_SIDE), stack); + this.setChanged(); + } + + public void initialize(ItemStack stack) { + ((IItemHandlerModifiable) this.getItemHandler()).setStackInSlot(priorities.get(DATA_SIDE), stack); + this.setChanged(); + } + + @Override + public boolean mayPickup(Player playerIn) { + return !this.getItemHandler().extractItem(priorities.get(DATA_SIDE), 1, true).isEmpty(); + } + + @Override + public ItemStack remove(int amount) { + return this.getItemHandler().extractItem(priorities.get(DATA_SIDE), amount, false); + } + }); + + // player inv + for (int i = 0; i < 3; i++) { + for (int j = 0; j < 9; j++) { + this.addSlot(new Slot(playerInv, j + i * 9 + 9, 8 + j * 18, 87 + i * 18)); + } + } + + // player hotbar + for (int i = 0; i < 9; i++) { + this.addSlot(new Slot(playerInv, i, 8 + i * 18, 145)); + } + } + + @Override + public boolean clickMenuButton(Player player, int id) { + return switch (id) { + case BUTTON_PRIO_DOWN, BUTTON_PRIO_UP -> { + int side = priorities.get(DATA_SIDE); + int prio = priorities.get(side); + int newPrio = Math.clamp(prio + (id == BUTTON_PRIO_UP ? 1 : -1), 0, FilterNodeTile.MAX_PRIO); + priorities.set(side, newPrio); + broadcastChanges(); + yield true; + } + case BUTTON_EDIT -> { + yield false; + } + case DATA_DOWN, DATA_UP, DATA_NORTH, DATA_SOUTH, DATA_WEST, DATA_EAST -> { + priorities.set(DATA_SIDE, id); + broadcastChanges(); + yield true; + } + default -> false; + }; + } + + public int getData(int index) { + return priorities.get(index); } @Override @@ -28,8 +130,7 @@ public ItemStack quickMoveStack(Player player, int index) { @Override public boolean stillValid(Player player) { - // TODO add buffer to menu creation and send isOutput so this can be checked properly - return AbstractContainerMenu.stillValid(ContainerLevelAccess.NULL, player, BMBlocks.INPUT_ROUTING_NODE.block().get()) - || AbstractContainerMenu.stillValid(ContainerLevelAccess.NULL, player, BMBlocks.OUTPUT_ROUTING_NODE.block().get()); + return AbstractContainerMenu.stillValid(ContainerLevelAccess.create(this.player.level(), this.nodePos), player, isOutput ? + BMBlocks.OUTPUT_ROUTING_NODE.block().get() : BMBlocks.INPUT_ROUTING_NODE.block().get()); } } diff --git a/src/main/java/wayoftime/bloodmagic/common/menu/TrainerMenu.java b/src/main/java/wayoftime/bloodmagic/common/menu/TrainerMenu.java index baecc3d6bb..ca5c5be6a8 100644 --- a/src/main/java/wayoftime/bloodmagic/common/menu/TrainerMenu.java +++ b/src/main/java/wayoftime/bloodmagic/common/menu/TrainerMenu.java @@ -13,14 +13,14 @@ public class TrainerMenu extends AbstractGhostMenu { // CLIENT constructor - public TrainerMenu(int containerId, Inventory playerInv, RegistryFriendlyByteBuf buf) { + public TrainerMenu(int containerId, Inventory playerInv) { // buf -> int heldSlot - super(BMMenus.TRAINER.get(), containerId, playerInv, 3 + 16, 4, 4, 89, 15, 105, buf.readInt()); + super(BMMenus.TRAINER.get(), containerId, playerInv, 3 + 16, 4, 4, 89, 15, 105, playerInv.selected); } // SERVER constructor - public TrainerMenu(int containerId, Inventory playerInv, GhostItemHandler handler, ContainerData trainerData, int heldSlot) { - super(BMMenus.TRAINER.get(), containerId, playerInv, trainerData, handler, 4, 4, 89, 15, 105, heldSlot); + public TrainerMenu(int containerId, Inventory playerInv, GhostItemHandler handler, ContainerData trainerData) { + super(BMMenus.TRAINER.get(), containerId, playerInv, trainerData, handler, 4, 4, 89, 15, 105, playerInv.selected); } @Override diff --git a/src/main/resources/assets/bloodmagic/textures/gui/container/node_filter.png b/src/main/resources/assets/bloodmagic/textures/gui/container/node_filter.png index a92dff1bc86ddd4c0289f4a07e1ca9a3feecd33b..6610e324401421f412fe245e482f6ffb1e89d42a 100644 GIT binary patch literal 1156 zcmeAS@N?(olHy`uVBq!ia0y~yU<5K5893O0R7}x|G!U;i$lZzY=1HA;AcrO0(btiI zVPik{pF~z5Um@8e$d`ekN{xY`p@o6r7f`6-1p`B=0RzLU1O^7H84L{K1#@-<+5jck zlDyqr82*Fcg1yTp14TFsJR*x382Ao>Fr%o3R|8Oxy~NYkmHj0*FPElb?ObM81_tI6 zo-U3d6}R5rJy{~Z+#KaIIr1V*xg68C+NBhTs9tmAHrsH&e4~ElOvh{Q zTW{#c{t0C2TUg9_ZSRDoBJb<@KDpj5RoXBq{@x#%vo`1b)@aXT_{VkN_wU`S53S=p zEFdWO*usi)O##z~XY7m&EDQn+4xpd_F&@a=i(yhy%G-Wht9ae@)!i>y7&sUd7=W&2 z!pGQi$W1}%kea+Y!vW5Q`@i-x%82GBBKE%p1X1w`P|NrOTi}!OG zm@ZtHU2n7SzC7(ot3gbzHRpp1y#`)oCb!W38*Bwl}gb^RBh>H?+*PnOTM zJ%5-JpGHt%FEI4~&iJJ^{;&9wDM_=`iqBM5_T6Q&7ioCPx?*B+U*@bchR>f`UfZ;j z6*ZDj9l=-t46+6`+q>)&g1Y7ue~nM-vwRaQF1U1xkl@Gjk65J}&)hsb=XkHfVFMSJ zBNlz9uNy?qVVEYqpsm;Z*_Cq}1y2~`_MZUInbU!`XH4jIc=o1_?>12RoV({Y3chIf zV>rznaQK*Xan|!298V`mgi$6*QkG{NRxiw2roVeuAk=(8M91*Ti66zvU`yXPM+%VB+1ki%NW4Nj>h<$uy; z^93)K#)dzuEGt}iQP`n;XG{z)-(lthr8aQ~9!)B^us)W7Cct7ffA0;aP(Pbv_dw=* My85}Sb4q9e051(;t^fc4 delta 1341 zcmV-D1;YA-3APN7BYy#fX+uL$Nkc;*aB^>EX>4Tx04R}tkv&MmP!xqvQ>7vm2aAe0 zWT?7W5EXHhDi*;)X)CnqVDi#GXws0RxHt-~1qXi?s}3&Cx;nTDg5VE`o12rOi+2pq zzTZW7miN6sSC5i28Q>F%=a_C-#2dsjo0iUbpE$&dl0tk=JZ?~f#E)E;U4G+Sa9H4( zAtRlfCk_#dg*KMkm=z6`c$zq@s2b%98J88#Tb$K$l{Ne1FAV0il@!;hh7rRO;z&S* zj4Dbf!$O31jeisqNji^u_=g;Sf?P7WN?_zzKm{r!#}EDozh`UarzYK`U=-+lvF(o$ zAg~KGYPS7-Y}<_!!2b+fX)S-H4$OX%UTbOLBcOL1xVUa<@*Z%x0}MXtk|8;gpGwH* zf%h}|rYz8R3v{o!b8DXC^Z`iItd?(pgF|4nK-uda?)bB zfWxVARQTrTM}`Xkhg9>s4S&nB*a83o00;me0Du4heex*)zEC3o^rZF~emUombFMnC z=Kr5F1_hwYn{3ZFZ_UrSbIwiAbH<2Di=01R~VZ+|NQ5kLTdF8M{E zfAF^_|9@K@@cP%wcN?q#c8S3K&u;!U)%wRmM)*fVtN;pv09F74x_{8;p&wQN13n9Q z+zwa~AOHg`{rxr|wg7+?z)}CE_fZl8FsON+n?1~&;d;Gp?_u^>0ck0NV>t!l}3Bl+N*R+7^?*0vbgG z00h7#00967@lOY65lQ0Ad7mn&X0?~*NfJ*3&00000NkvXXu0mjfpx#I< From 59f57400059d20f66d2c5d18afbba2c09cd07d58 Mon Sep 17 00:00:00 2001 From: stellanera Date: Wed, 26 Nov 2025 08:08:36 +0100 Subject: [PATCH 7/8] filter guis work. next up: edit button in node I guess --- .../datagen/provider/BMItemTagProvider.java | 11 + .../datagen/provider/ProviderHelper.java | 1 - .../models/item/filter_composite.json | 6 + .../models/item/filter_enchant.json | 6 + .../bloodmagic/models/item/filter_mod.json | 6 + .../models/item/filter_standard.json | 6 + .../bloodmagic/models/item/filter_tag.json | 6 + .../bloodmagic/tags/item/routing_filter.json | 9 + .../tags/item/routing_filter/enchant.json | 5 + .../tags/item/routing_filter/tag.json | 5 + .../java/wayoftime/bloodmagic/BloodMagic.java | 2 + .../client/event/ClientModEventHandler.java | 1 + .../client/screen/AbstractGhostScreen.java | 35 +++- .../client/screen/FilterScreen.java | 195 ++++++++++++++++++ .../client/screen/TrainerScreen.java | 5 - .../client/widgets/MultiIconButton.java | 26 ++- .../datacomponent/BMDataComponents.java | 13 ++ .../bloodmagic/common/item/BMItems.java | 6 + .../bloodmagic/common/item/FilterItem.java | 122 +++++++++-- .../common/menu/AbstractGhostMenu.java | 8 +- .../bloodmagic/common/menu/BMMenus.java | 2 + .../bloodmagic/common/menu/FilterData.java | 41 ++++ .../bloodmagic/common/menu/FilterMenu.java | 69 +++++++ .../common/menu/GhostItemHandler.java | 14 ++ .../bloodmagic/common/network/BMPackets.java | 16 ++ .../common/network/GhostAmountPacket.java | 36 ++++ .../bloodmagic/common/tag/BMTags.java | 4 + .../bloodmagic/util/helper/FilterHelper.java | 127 ++++++++++++ .../textures/gui/container/filter_item.png | Bin 17389 -> 1147 bytes .../sprites/container/filter/blacklist.png | Bin 0 -> 393 bytes .../gui/sprites/container/filter/enchant.png | Bin 0 -> 724 bytes .../sprites/container/filter/enchant_any.png | Bin 0 -> 774 bytes .../container/filter/enchant_every.png | Bin 0 -> 761 bytes .../container/filter/enchant_level_any.png | Bin 0 -> 658 bytes .../container/filter/enchant_level_exact.png | Bin 0 -> 651 bytes .../gui/sprites/container/filter/tag.png | Bin 0 -> 554 bytes .../gui/sprites/container/filter/tag_all.png | Bin 0 -> 625 bytes .../sprites/container/filter/whitelist.png | Bin 0 -> 459 bytes .../textures/item/filter_composite.png | Bin 0 -> 6722 bytes .../bloodmagic/textures/item/filter_data.png | Bin 0 -> 682 bytes .../textures/item/filter_enchant.png | Bin 0 -> 6545 bytes .../bloodmagic/textures/item/filter_fluid.png | Bin 0 -> 681 bytes .../bloodmagic/textures/item/filter_mod.png | Bin 0 -> 681 bytes .../textures/item/filter_standard.png | Bin 0 -> 6711 bytes .../bloodmagic/textures/item/filter_tag.png | Bin 0 -> 681 bytes 45 files changed, 748 insertions(+), 35 deletions(-) create mode 100644 src/generated/resources/assets/bloodmagic/models/item/filter_composite.json create mode 100644 src/generated/resources/assets/bloodmagic/models/item/filter_enchant.json create mode 100644 src/generated/resources/assets/bloodmagic/models/item/filter_mod.json create mode 100644 src/generated/resources/assets/bloodmagic/models/item/filter_standard.json create mode 100644 src/generated/resources/assets/bloodmagic/models/item/filter_tag.json create mode 100644 src/generated/resources/data/bloodmagic/tags/item/routing_filter.json create mode 100644 src/generated/resources/data/bloodmagic/tags/item/routing_filter/enchant.json create mode 100644 src/generated/resources/data/bloodmagic/tags/item/routing_filter/tag.json create mode 100644 src/main/java/wayoftime/bloodmagic/client/screen/FilterScreen.java create mode 100644 src/main/java/wayoftime/bloodmagic/common/menu/FilterData.java create mode 100644 src/main/java/wayoftime/bloodmagic/common/menu/FilterMenu.java create mode 100644 src/main/java/wayoftime/bloodmagic/common/network/BMPackets.java create mode 100644 src/main/java/wayoftime/bloodmagic/common/network/GhostAmountPacket.java create mode 100644 src/main/java/wayoftime/bloodmagic/util/helper/FilterHelper.java create mode 100644 src/main/resources/assets/bloodmagic/textures/gui/sprites/container/filter/blacklist.png create mode 100644 src/main/resources/assets/bloodmagic/textures/gui/sprites/container/filter/enchant.png create mode 100644 src/main/resources/assets/bloodmagic/textures/gui/sprites/container/filter/enchant_any.png create mode 100644 src/main/resources/assets/bloodmagic/textures/gui/sprites/container/filter/enchant_every.png create mode 100644 src/main/resources/assets/bloodmagic/textures/gui/sprites/container/filter/enchant_level_any.png create mode 100644 src/main/resources/assets/bloodmagic/textures/gui/sprites/container/filter/enchant_level_exact.png create mode 100644 src/main/resources/assets/bloodmagic/textures/gui/sprites/container/filter/tag.png create mode 100644 src/main/resources/assets/bloodmagic/textures/gui/sprites/container/filter/tag_all.png create mode 100644 src/main/resources/assets/bloodmagic/textures/gui/sprites/container/filter/whitelist.png create mode 100644 src/main/resources/assets/bloodmagic/textures/item/filter_composite.png create mode 100644 src/main/resources/assets/bloodmagic/textures/item/filter_data.png create mode 100644 src/main/resources/assets/bloodmagic/textures/item/filter_enchant.png create mode 100644 src/main/resources/assets/bloodmagic/textures/item/filter_fluid.png create mode 100644 src/main/resources/assets/bloodmagic/textures/item/filter_mod.png create mode 100644 src/main/resources/assets/bloodmagic/textures/item/filter_standard.png create mode 100644 src/main/resources/assets/bloodmagic/textures/item/filter_tag.png diff --git a/src/datagen/java/wayoftime/bloodmagic/datagen/provider/BMItemTagProvider.java b/src/datagen/java/wayoftime/bloodmagic/datagen/provider/BMItemTagProvider.java index 20f2270c65..25a6bab021 100644 --- a/src/datagen/java/wayoftime/bloodmagic/datagen/provider/BMItemTagProvider.java +++ b/src/datagen/java/wayoftime/bloodmagic/datagen/provider/BMItemTagProvider.java @@ -61,5 +61,16 @@ protected void addTags(HolderLookup.Provider provider) { .add(BMItems.NODE_ROUTER.get()) .add(BMBlocks.MASTER_NODE.asItem(), BMBlocks.ROUTING_NODE.asItem(), BMBlocks.INPUT_ROUTING_NODE.asItem(), BMBlocks.OUTPUT_ROUTING_NODE.asItem()) .addTag(BMTags.Items.SOUL_GEM); + + tag(BMTags.Items.TAG_FILTER) + .add(BMItems.TAG_FILTER.get()); + + tag(BMTags.Items.ENCHANT_FILTER) + .add(BMItems.ENCHANT_FILTER.get()); + + tag(BMTags.Items.FILTERS) + .addTag(BMTags.Items.TAG_FILTER) + .addTag(BMTags.Items.ENCHANT_FILTER) + .add(BMItems.STANDARD_FILTER.get(), BMItems.MOD_FILTER.get(), BMItems.COMPOSITE_FILTER.get()); } } diff --git a/src/datagen/java/wayoftime/bloodmagic/datagen/provider/ProviderHelper.java b/src/datagen/java/wayoftime/bloodmagic/datagen/provider/ProviderHelper.java index ae36ead71a..9d911cb7be 100644 --- a/src/datagen/java/wayoftime/bloodmagic/datagen/provider/ProviderHelper.java +++ b/src/datagen/java/wayoftime/bloodmagic/datagen/provider/ProviderHelper.java @@ -25,7 +25,6 @@ public GatherDataEvent.DataProviderFromOutputLookup> tagsFor protected void addTags(HolderLookup.Provider provider) { adder.accept(this::tag); } - }; } } diff --git a/src/generated/resources/assets/bloodmagic/models/item/filter_composite.json b/src/generated/resources/assets/bloodmagic/models/item/filter_composite.json new file mode 100644 index 0000000000..74bf92cf9b --- /dev/null +++ b/src/generated/resources/assets/bloodmagic/models/item/filter_composite.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "bloodmagic:item/filter_composite" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/bloodmagic/models/item/filter_enchant.json b/src/generated/resources/assets/bloodmagic/models/item/filter_enchant.json new file mode 100644 index 0000000000..3d9091461d --- /dev/null +++ b/src/generated/resources/assets/bloodmagic/models/item/filter_enchant.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "bloodmagic:item/filter_enchant" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/bloodmagic/models/item/filter_mod.json b/src/generated/resources/assets/bloodmagic/models/item/filter_mod.json new file mode 100644 index 0000000000..1c81149037 --- /dev/null +++ b/src/generated/resources/assets/bloodmagic/models/item/filter_mod.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "bloodmagic:item/filter_mod" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/bloodmagic/models/item/filter_standard.json b/src/generated/resources/assets/bloodmagic/models/item/filter_standard.json new file mode 100644 index 0000000000..76b7c9546f --- /dev/null +++ b/src/generated/resources/assets/bloodmagic/models/item/filter_standard.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "bloodmagic:item/filter_standard" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/bloodmagic/models/item/filter_tag.json b/src/generated/resources/assets/bloodmagic/models/item/filter_tag.json new file mode 100644 index 0000000000..0118d346b4 --- /dev/null +++ b/src/generated/resources/assets/bloodmagic/models/item/filter_tag.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "bloodmagic:item/filter_tag" + } +} \ No newline at end of file diff --git a/src/generated/resources/data/bloodmagic/tags/item/routing_filter.json b/src/generated/resources/data/bloodmagic/tags/item/routing_filter.json new file mode 100644 index 0000000000..44c13cba68 --- /dev/null +++ b/src/generated/resources/data/bloodmagic/tags/item/routing_filter.json @@ -0,0 +1,9 @@ +{ + "values": [ + "#bloodmagic:routing_filter/tag", + "#bloodmagic:routing_filter/enchant", + "bloodmagic:filter_standard", + "bloodmagic:filter_mod", + "bloodmagic:filter_composite" + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/bloodmagic/tags/item/routing_filter/enchant.json b/src/generated/resources/data/bloodmagic/tags/item/routing_filter/enchant.json new file mode 100644 index 0000000000..4a9b06d85c --- /dev/null +++ b/src/generated/resources/data/bloodmagic/tags/item/routing_filter/enchant.json @@ -0,0 +1,5 @@ +{ + "values": [ + "bloodmagic:filter_enchant" + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/bloodmagic/tags/item/routing_filter/tag.json b/src/generated/resources/data/bloodmagic/tags/item/routing_filter/tag.json new file mode 100644 index 0000000000..1ba02e6bd9 --- /dev/null +++ b/src/generated/resources/data/bloodmagic/tags/item/routing_filter/tag.json @@ -0,0 +1,5 @@ +{ + "values": [ + "bloodmagic:filter_tag" + ] +} \ No newline at end of file diff --git a/src/main/java/wayoftime/bloodmagic/BloodMagic.java b/src/main/java/wayoftime/bloodmagic/BloodMagic.java index 5d36afd55e..4fa038ded8 100644 --- a/src/main/java/wayoftime/bloodmagic/BloodMagic.java +++ b/src/main/java/wayoftime/bloodmagic/BloodMagic.java @@ -22,6 +22,7 @@ import wayoftime.bloodmagic.common.fluid.BMFluids; import wayoftime.bloodmagic.common.item.BMItems; import wayoftime.bloodmagic.common.item.BMMaterialsAndTiers; +import wayoftime.bloodmagic.common.network.BMPackets; import wayoftime.bloodmagic.common.recipe.BMRecipes; import wayoftime.bloodmagic.common.registry.BMRegistries; import wayoftime.bloodmagic.common.structure.BMMultiblock; @@ -59,6 +60,7 @@ public BloodMagic(IEventBus modBus, ModContainer container) { BMMaterialsAndTiers.register(modBus); BMItems.register(modBus); modBus.addListener(BMDataMaps::register); + modBus.addListener(BMPackets::register); BMDataAttachments.register(modBus); BMAttributes.register(modBus); BMRecipes.register(modBus); diff --git a/src/main/java/wayoftime/bloodmagic/client/event/ClientModEventHandler.java b/src/main/java/wayoftime/bloodmagic/client/event/ClientModEventHandler.java index 5c1221b924..3fcbf51e6c 100644 --- a/src/main/java/wayoftime/bloodmagic/client/event/ClientModEventHandler.java +++ b/src/main/java/wayoftime/bloodmagic/client/event/ClientModEventHandler.java @@ -47,5 +47,6 @@ public static void registerScreens(RegisterMenuScreensEvent event) { event.register(BMMenus.TRAINER.get(), TrainerScreen::new); event.register(BMMenus.MASTER_NODE.get(), NodeMasterScreen::new); event.register(BMMenus.FILTERED_NODE.get(), NodeFilterScreen::new); + event.register(BMMenus.ITEM_FILTER.get(), FilterScreen::new); } } \ No newline at end of file diff --git a/src/main/java/wayoftime/bloodmagic/client/screen/AbstractGhostScreen.java b/src/main/java/wayoftime/bloodmagic/client/screen/AbstractGhostScreen.java index fc824f12a6..e1c9c08e7e 100644 --- a/src/main/java/wayoftime/bloodmagic/client/screen/AbstractGhostScreen.java +++ b/src/main/java/wayoftime/bloodmagic/client/screen/AbstractGhostScreen.java @@ -6,19 +6,37 @@ import net.minecraft.network.chat.Component; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.entity.player.Inventory; +import net.minecraft.world.inventory.AbstractContainerMenu; +import net.minecraft.world.inventory.ContainerListener; import net.minecraft.world.inventory.Slot; +import net.minecraft.world.item.ItemStack; import wayoftime.bloodmagic.BloodMagic; import wayoftime.bloodmagic.client.widgets.MultiIconButton; import wayoftime.bloodmagic.common.menu.AbstractGhostMenu; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import java.util.Map; public abstract class AbstractGhostScreen> extends AbstractContainerScreen { public static final ResourceLocation SELECTED = BloodMagic.rl("container/ghost_selected"); public AbstractGhostScreen(T menu, Inventory playerInventory, Component title) { super(menu, playerInventory, title); + ContainerListener buttonListener = new ContainerListener() { + @Override + public void slotChanged(AbstractContainerMenu containerToSend, int dataSlotIndex, ItemStack stack) { + } + + @Override + public void dataChanged(AbstractContainerMenu containerMenu, int dataSlotIndex, int value) { + if (updateButtons.containsKey(dataSlotIndex)) { + updateButtons.get(dataSlotIndex).setState(value); + } + } + }; + menu.addSlotListener(buttonListener); } @Override @@ -27,31 +45,30 @@ protected void init() { this.inventoryLabelY = this.imageHeight - 94; // auto recalc } - private final List> updateButtons = new ArrayList<>(); + private final Map updateButtons = new HashMap<>(); public void addMultiIconButton(int dataIndex, MultiIconButton button) { - updateButtons.add(Pair.of(button, dataIndex)); + updateButtons.put(dataIndex, button); addRenderableWidget(button); } @Override - protected void containerTick() { - super.containerTick(); - updateButtons.forEach(pair -> pair.left().setState(this.menu.getData(pair.right()))); + public void render(GuiGraphics guiGraphics, int mouseX, int mouseY, float partialTick) { + super.render(guiGraphics, mouseX, mouseY, partialTick); + renderTooltip(guiGraphics, mouseX, mouseY); } - public abstract ResourceLocation background(); - @Override protected void renderTooltip(GuiGraphics guiGraphics, int x, int y) { super.renderTooltip(guiGraphics, x, y); - updateButtons.forEach(pair -> { - MultiIconButton button = pair.left(); + updateButtons.forEach((key, button) -> { if (button.isHovered()) { guiGraphics.renderTooltip(this.font, button.getHoverText(), x, y); } }); } + + public abstract ResourceLocation background(); @Override protected void renderBg(GuiGraphics guiGraphics, float partialTick, int mouseX, int mouseY) { guiGraphics.blit(this.background(), leftPos, topPos, 0, 0, imageWidth, imageHeight); diff --git a/src/main/java/wayoftime/bloodmagic/client/screen/FilterScreen.java b/src/main/java/wayoftime/bloodmagic/client/screen/FilterScreen.java new file mode 100644 index 0000000000..55aa4cee6e --- /dev/null +++ b/src/main/java/wayoftime/bloodmagic/client/screen/FilterScreen.java @@ -0,0 +1,195 @@ +package wayoftime.bloodmagic.client.screen; + +import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.client.gui.components.Button; +import net.minecraft.client.gui.components.EditBox; +import net.minecraft.client.gui.components.Tooltip; +import net.minecraft.network.chat.Component; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.inventory.AbstractContainerMenu; +import net.minecraft.world.inventory.ContainerListener; +import net.minecraft.world.entity.player.Inventory; +import net.minecraft.world.item.ItemStack; +import net.neoforged.neoforge.network.PacketDistributor; +import wayoftime.bloodmagic.BloodMagic; +import wayoftime.bloodmagic.client.widgets.MultiIconButton; +import wayoftime.bloodmagic.common.datacomponent.BMDataComponents; +import wayoftime.bloodmagic.common.menu.FilterMenu; +import wayoftime.bloodmagic.common.network.GhostAmountPacket; +import wayoftime.bloodmagic.util.helper.FilterHelper; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; + +import static wayoftime.bloodmagic.util.helper.FilterHelper.*; + +public class FilterScreen extends AbstractGhostScreen { + public static final ResourceLocation background = BloodMagic.rl("textures/gui/container/filter_item.png"); + + // sprites dont need .png I guess? + public static final ResourceLocation whitelist = BloodMagic.rl("container/filter/whitelist"); + public static final ResourceLocation blacklist = BloodMagic.rl("container/filter/blacklist"); + public static final ResourceLocation tag = BloodMagic.rl("container/filter/tag"); + public static final ResourceLocation tag_all = BloodMagic.rl("container/filter/tag_all"); + public static final ResourceLocation enchant = BloodMagic.rl("container/filter/enchant"); + public static final ResourceLocation enchant_any = BloodMagic.rl("container/filter/enchant_any"); + public static final ResourceLocation enchant_every = BloodMagic.rl("container/filter/enchant_every"); + public static final ResourceLocation enchant_level_any = BloodMagic.rl("container/filter/enchant_level_any"); + public static final ResourceLocation enchant_level_exact = BloodMagic.rl("container/filter/enchant_level_exact"); + + public FilterScreen(FilterMenu menu, Inventory playerInventory, Component title) { + super(menu, playerInventory, title); + imageWidth = 176; + imageHeight = 187; + } + + private EditBox amountBox; + @Override + protected void init() { + super.init(); + amountBox = new EditBox(font, Button.DEFAULT_WIDTH, Button.DEFAULT_HEIGHT, Component.literal("message?")); + amountBox.setEditable(true); + amountBox.setFilter(newValueString -> { + if (newValueString.equalsIgnoreCase("")) { + return true; + } + try { + Integer.decode(newValueString); + return true; + } catch (final NumberFormatException e) { + return false; + } + }); + amountBox.setResponder(newValueString -> { + BloodMagic.LOGGER.info("responding to '{}'", newValueString); + try { + int amount = Integer.decode(newValueString); + setGhostAmount(amount); + } catch (NumberFormatException e) { + // ignored + } + }); + amountBox.setTooltip(Tooltip.create(Component.translatable("filter.bloodmagic.amount_box"))); + amountBox.setPosition(leftPos + 20, topPos + 16); + amountBox.setSize(77, 14); + + addRenderableWidget(amountBox); + + addMultiIconButton(DATA_BWLIST, MultiIconButton.builder(button -> sendButtonClick(BUTTON_BWLIST)) + .icons(whitelist, blacklist) + .tooltips(FilterHelper.translate("whitelist"), FilterHelper.translate("blacklist")) + .pos(leftPos + 7, topPos + 32) + .size(20, 20) + .build() + ); + + if (menu.isTag) { + addPerSlotButton(DATA_TAG, MultiIconButton.builder(button -> sendButtonClick(BUTTON_TAG)) + .icons(tag_all, tag) + .stateGetter(state -> state == 0 ? 0 : 1) + .pos(leftPos + 27, topPos + 32) + .size(20, 20) + .build() + ); + } + + if (menu.isEnchant) { + addPerSlotButton(DATA_ENCHANT, MultiIconButton.builder(button -> sendButtonClick(BUTTON_ENCHANT)) + .icons(enchant_every, enchant_any, enchant) + .stateGetter(state -> switch (state) { + case 0 -> 0; + case 1 -> 1; + + default -> 2; + }) + .pos(leftPos + 27, topPos + 32) + .size(20, 20) + .build() + ); + + addPerSlotButton(DATA_ENCHANT_LVL, MultiIconButton.builder(button -> sendButtonClick(BUTTON_ENCHANT_LVL)) + .icons(enchant_level_exact, enchant_level_any) + .pos(leftPos + 47, topPos + 32) + .size(20, 20) + .build() + ); + } + } + + private Map perSlotButton = new HashMap<>(); + @Override + protected void containerTick() { + super.containerTick(); + perSlotButton.forEach((index, button) -> { + int slot = menu.getData(DATA_SLOT); + int state = menu.getData(index + slot); + button.setState(state); + }); + } + + @Override + protected void renderTooltip(GuiGraphics guiGraphics, int x, int y) { + super.renderTooltip(guiGraphics, x, y); + perSlotButton.forEach((key, button) -> { + if (button.isHovered()) { + guiGraphics.renderTooltip(this.font, buttonHoverText(key), Optional.empty(), x, y); + } + }); + } + + private List buttonHoverText(int data) { + int slot = menu.getData(DATA_SLOT); + return switch (data) { + case DATA_TAG -> FilterHelper.tagButtonText(menu.handler.getStackInSlot(slot)); + case DATA_ENCHANT -> FilterHelper.enchantButtonText(menu.handler.getStackInSlot(slot)); + case DATA_ENCHANT_LVL -> FilterHelper.enchantLevelButtonText(menu.handler.getStackInSlot(slot)); + + default -> List.of(Component.literal("Huh. dont know button %d".formatted(data))); + }; + } + + private void addPerSlotButton(int dataOffset, MultiIconButton button) { + perSlotButton.put(dataOffset, button); + addRenderableWidget(button); + } + + private void setGhostAmount(int amount) { + int slot = menu.getData(DATA_SLOT); + ItemStack stack = menu.getSlot(slot).getItem(); + int oldAmount = stack.getOrDefault(BMDataComponents.GHOST_AMOUNT, 0); + if (oldAmount == amount) { + return; + } + + GhostAmountPacket packet = new GhostAmountPacket(slot, amount); + PacketDistributor.sendToServer(packet); + } + + private void sendButtonClick(int buttonId) { + this.minecraft.gameMode.handleInventoryButtonClick(this.menu.containerId, buttonId); + } + + @Override + public boolean mouseClicked(double mouseX, double mouseY, int button) { + super.mouseClicked(mouseX, mouseY, button); // otherwise screen dies + + if (menu.getData(DATA_SLOT) != -1) { // Text box only selectable if a ghost slot has been clicked. + if (amountBox.isMouseOver(mouseX, mouseY) && button == 1) // Right-Clicked + { + amountBox.setValue(""); + setGhostAmount(0); + amountBox.setFocused(true); + return true; + } + } + amountBox.setFocused(false); + return true; + } + + @Override + public ResourceLocation background() { + return background; + } +} diff --git a/src/main/java/wayoftime/bloodmagic/client/screen/TrainerScreen.java b/src/main/java/wayoftime/bloodmagic/client/screen/TrainerScreen.java index 4710c357f4..5eec67f507 100644 --- a/src/main/java/wayoftime/bloodmagic/client/screen/TrainerScreen.java +++ b/src/main/java/wayoftime/bloodmagic/client/screen/TrainerScreen.java @@ -60,11 +60,6 @@ public String getLevelString() { private static final ResourceLocation allow = ResourceLocation.fromNamespaceAndPath(BloodMagic.MODID, "container/trainer/allow_others"); private static final ResourceLocation deny = ResourceLocation.fromNamespaceAndPath(BloodMagic.MODID, "container/trainer/deny_others"); - @Override - public void render(GuiGraphics guiGraphics, int mouseX, int mouseY, float partialTick) { - super.render(guiGraphics, mouseX, mouseY, partialTick); - renderTooltip(guiGraphics, mouseX, mouseY); - } @Override protected void renderLabels(GuiGraphics guiGraphics, int mouseX, int mouseY) { diff --git a/src/main/java/wayoftime/bloodmagic/client/widgets/MultiIconButton.java b/src/main/java/wayoftime/bloodmagic/client/widgets/MultiIconButton.java index 3fd91a8373..7af71c1cbd 100644 --- a/src/main/java/wayoftime/bloodmagic/client/widgets/MultiIconButton.java +++ b/src/main/java/wayoftime/bloodmagic/client/widgets/MultiIconButton.java @@ -4,28 +4,35 @@ import net.minecraft.client.gui.components.AbstractButton; import net.minecraft.client.gui.components.Tooltip; import net.minecraft.client.gui.narration.NarrationElementOutput; +import net.minecraft.network.chat.CommonComponents; import net.minecraft.network.chat.Component; import net.minecraft.resources.ResourceLocation; +import wayoftime.bloodmagic.BloodMagic; + +import java.util.function.Function; +import java.util.function.Supplier; public class MultiIconButton extends AbstractButton { private final ResourceLocation[] icons; private final Component[] tooltips; private final OnPress onPress; - public MultiIconButton(int x, int y, int width, int height, Component[] tooltips, ResourceLocation[] icons, OnPress onPress) { + private final Function stateGetter; + public MultiIconButton(int x, int y, int width, int height, Component[] tooltips, ResourceLocation[] icons, OnPress onPress, Function stateGetter) { super(x, y, width, height, Component.literal("")); this.onPress = onPress; this.icons = icons; this.tooltips = tooltips; + this.stateGetter = stateGetter; } public MultiIconButton(Builder builder) { - this(builder.x, builder.y, builder.width, builder.height, builder.tooltips, builder.icons, builder.onPress); + this(builder.x, builder.y, builder.width, builder.height, builder.tooltips, builder.icons, builder.onPress, builder.stateGetter); } private int state = 0; public int getState() { - return this.state; + return this.stateGetter.apply(state); } public void setState(int state) { @@ -38,13 +45,16 @@ public void onPress() { } public Component getHoverText() { - return tooltips[state % tooltips.length]; + return tooltips.length > 0 ? tooltips[stateGetter.apply(state) % tooltips.length] : CommonComponents.EMPTY; } @Override protected void renderWidget(GuiGraphics guiGraphics, int mouseX, int mouseY, float partialTick) { super.renderWidget(guiGraphics, mouseX, mouseY, partialTick); - guiGraphics.blitSprite(icons[state % icons.length], this.getX(), this.getY(), this.getWidth(), this.getHeight()); + int index = stateGetter.apply(state); + ResourceLocation sprite = icons[index % icons.length]; + // BloodMagic.LOGGER.info("got state {}, index {} and res loc {}", state, index, sprite); + guiGraphics.blitSprite(sprite, this.getX(), this.getY(), this.getWidth(), this.getHeight()); } @Override @@ -64,6 +74,7 @@ public static class Builder { private int height = 20; private ResourceLocation[] icons; private Component[] tooltips; + private Function stateGetter = Function.identity(); public Builder(OnPress onPress) { this.onPress = onPress; @@ -100,6 +111,11 @@ public Builder icons(ResourceLocation... icons) { return this; } + public Builder stateGetter(Function stateGetter) { + this.stateGetter = stateGetter; + return this; + } + public MultiIconButton build() { return build(MultiIconButton::new); } diff --git a/src/main/java/wayoftime/bloodmagic/common/datacomponent/BMDataComponents.java b/src/main/java/wayoftime/bloodmagic/common/datacomponent/BMDataComponents.java index 64332ad90e..6cd4a32525 100644 --- a/src/main/java/wayoftime/bloodmagic/common/datacomponent/BMDataComponents.java +++ b/src/main/java/wayoftime/bloodmagic/common/datacomponent/BMDataComponents.java @@ -10,6 +10,7 @@ import net.minecraft.resources.RegistryFixedCodec; import net.minecraft.tags.TagKey; import net.minecraft.world.item.Item; +import net.minecraft.world.item.component.ItemContainerContents; import net.neoforged.bus.api.IEventBus; import net.neoforged.neoforge.fluids.SimpleFluidContent; import net.neoforged.neoforge.registries.DeferredHolder; @@ -19,6 +20,7 @@ import wayoftime.bloodmagic.common.registry.BMRegistries; import java.util.function.Function; +import java.util.function.Supplier; public class BMDataComponents { public static final DeferredRegister.DataComponents DATA_COMPONENTS = DeferredRegister.createDataComponents(Registries.DATA_COMPONENT_TYPE, BloodMagic.MODID); @@ -54,6 +56,17 @@ public class BMDataComponents { public static final DeferredHolder, DataComponentType> PREVIOUS_DAMAGE = DATA_COMPONENTS.registerComponentType("previous_damage", builder -> builder.persistent(Codec.INT)); + public static final DeferredHolder, DataComponentType> FILTER_INVENTORY = DATA_COMPONENTS.registerComponentType("filter_inventory", builder -> builder.persistent(ItemContainerContents.CODEC).networkSynchronized(ItemContainerContents.STREAM_CODEC)); + public static final DeferredHolder, DataComponentType> GHOST_SLOT = DATA_COMPONENTS.registerComponentType("ghost_slot", builder -> builder.persistent(Codec.INT).networkSynchronized(ByteBufCodecs.VAR_INT)); + public static final DeferredHolder, DataComponentType> FILTER_BLACKWHITELIST = DATA_COMPONENTS.registerComponentType("filter_blackwhitelist", builder -> builder.persistent(Codec.INT).networkSynchronized(ByteBufCodecs.VAR_INT)); + + public static final DeferredHolder, DataComponentType> FILTER_ENCHANT_LEVEL = DATA_COMPONENTS.registerComponentType("filter_enchant_level", builder -> builder.persistent(Codec.INT).networkSynchronized(ByteBufCodecs.VAR_INT)); + public static final DeferredHolder, DataComponentType> FILTER_ENCHANT_INDEX = DATA_COMPONENTS.registerComponentType("filter_enchant_index", builder -> builder.persistent(Codec.INT).networkSynchronized(ByteBufCodecs.VAR_INT)); + + public static final DeferredHolder, DataComponentType> FILTER_TAG_INDEX = DATA_COMPONENTS.registerComponentType("filter_tag_index", builder -> builder.persistent(Codec.INT).networkSynchronized(ByteBufCodecs.VAR_INT)); + public static final DeferredHolder, DataComponentType>> FILTER_TAG = DATA_COMPONENTS.registerComponentType("filter_tag", builder -> builder.persistent(TagKey.codec(Registries.ITEM)).networkSynchronized(ByteBufCodecs.fromCodecWithRegistries(TagKey.codec(Registries.ITEM)))); + public static final DeferredHolder, DataComponentType> GHOST_AMOUNT = DATA_COMPONENTS.registerComponentType("ghost_amount", builder -> builder.persistent(Codec.INT).networkSynchronized(ByteBufCodecs.VAR_INT)); + public static void register(IEventBus modBus) { DATA_COMPONENTS.register(modBus); } diff --git a/src/main/java/wayoftime/bloodmagic/common/item/BMItems.java b/src/main/java/wayoftime/bloodmagic/common/item/BMItems.java index 59a502fee5..3af207c584 100644 --- a/src/main/java/wayoftime/bloodmagic/common/item/BMItems.java +++ b/src/main/java/wayoftime/bloodmagic/common/item/BMItems.java @@ -39,6 +39,12 @@ public class BMItems { public static final DeferredHolder NODE_AMOUNT_UPGRADE = BASIC_ITEMS.register("node_upgrade_amount", () -> new Item(new Item.Properties())); public static final DeferredHolder NODE_SPEED_UPGRADE = BASIC_ITEMS.register("node_upgrade_speed", () -> new Item(new Item.Properties().stacksTo(19))); + public static final DeferredHolder STANDARD_FILTER = BASIC_ITEMS.register("filter_standard", () -> new FilterItem(new Item.Properties().stacksTo(16))); + public static final DeferredHolder TAG_FILTER = BASIC_ITEMS.register("filter_tag", () -> new FilterItem(new Item.Properties().stacksTo(16))); + public static final DeferredHolder ENCHANT_FILTER = BASIC_ITEMS.register("filter_enchant", () -> new FilterItem(new Item.Properties().stacksTo(16))); + public static final DeferredHolder MOD_FILTER = BASIC_ITEMS.register("filter_mod", () -> new FilterItem(new Item.Properties().stacksTo(16))); + public static final DeferredHolder COMPOSITE_FILTER = BASIC_ITEMS.register("filter_composite", () -> new FilterItem(new Item.Properties().stacksTo(16))); + private static Supplier makeLivingArmour(ArmorItem.Type type) { return () -> new ArmorItem(BMMaterialsAndTiers.LIVING_ARMOUR_MATERIAL, type, new Item.Properties().durability(type.getDurability(33))); } diff --git a/src/main/java/wayoftime/bloodmagic/common/item/FilterItem.java b/src/main/java/wayoftime/bloodmagic/common/item/FilterItem.java index 50083cb88d..b713975e4f 100644 --- a/src/main/java/wayoftime/bloodmagic/common/item/FilterItem.java +++ b/src/main/java/wayoftime/bloodmagic/common/item/FilterItem.java @@ -1,38 +1,132 @@ package wayoftime.bloodmagic.common.item; -import net.minecraft.network.chat.Component; +import net.minecraft.core.NonNullList; +import net.minecraft.core.component.DataComponentType; import net.minecraft.world.InteractionHand; import net.minecraft.world.InteractionResultHolder; +import net.minecraft.world.MenuProvider; import net.minecraft.world.SimpleMenuProvider; import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.component.ItemContainerContents; import net.minecraft.world.level.Level; import wayoftime.bloodmagic.common.datacomponent.BMDataComponents; +import wayoftime.bloodmagic.common.menu.FilterData; +import wayoftime.bloodmagic.common.menu.FilterMenu; +import wayoftime.bloodmagic.common.menu.GhostItemHandler; +import wayoftime.bloodmagic.common.tag.BMTags; +import wayoftime.bloodmagic.util.helper.FilterHelper; + +import java.util.ArrayList; +import java.util.List; + +import static wayoftime.bloodmagic.util.helper.FilterHelper.*; public class FilterItem extends Item { - private final String name; - public FilterItem(Properties properties, String name) { + public FilterItem(Properties properties) { super(properties); - this.name = name; } @Override public InteractionResultHolder use(Level level, Player player, InteractionHand usedHand) { - ItemStack stack = player.getItemInHand(usedHand); - if (!(stack.getItem() instanceof FilterItem)) { - return InteractionResultHolder.pass(stack); + ItemStack filterStack = player.getItemInHand(usedHand); + if (!(filterStack.getItem() instanceof FilterItem)) { + return InteractionResultHolder.pass(filterStack); } if (!level.isClientSide) { - /* - player.openMenu(new SimpleMenuProvider( - (containerId, playerInventory, player1) -> new FilterMenu(containerId, playerInventory, stack.get(BMDataComponents.FILTER_INVENTORY)), - Component.translatable("gui.bloodmagic.filter." + name)) - ); - */ + int slot = usedHand == InteractionHand.MAIN_HAND ? player.getInventory().selected : 0; + player.openMenu(getFilterProvider(filterStack, slot), buf -> { + buf.writeInt(slot); + buf.writeBoolean(filterStack.is(BMTags.Items.TAG_FILTER)); + buf.writeBoolean(filterStack.is(BMTags.Items.ENCHANT_FILTER)); + }); + } + return InteractionResultHolder.sidedSuccess(filterStack, level.isClientSide); + } + + public static MenuProvider getFilterProvider(ItemStack filterStack, int slot) { + NonNullList stacks = NonNullList.withSize(9, ItemStack.EMPTY); + if (filterStack.has(BMDataComponents.FILTER_INVENTORY)) { + ItemContainerContents contents = filterStack.get(BMDataComponents.FILTER_INVENTORY); + contents.copyInto(stacks); + } + + GhostItemHandler filterInv = new GhostItemHandler(stacks) { + @Override + public boolean isItemValid(int slot, ItemStack stack) { + return !stack.is(BMTags.Items.FILTERS); + } + + @Override + public void onContentsChanged(int slot) { + filterStack.set(BMDataComponents.FILTER_INVENTORY, this.toContents()); + } + }; + List rawData = new ArrayList<>(CONTAINER_DATA_SIZE); + for (int i = 0; i < CONTAINER_DATA_SIZE; i++) { + rawData.add(0); } - return InteractionResultHolder.sidedSuccess(stack, level.isClientSide); + rawData.set(DATA_SLOT, filterStack.getOrDefault(BMDataComponents.GHOST_SLOT, 0)); // dont wanna deal with -1 here really + rawData.set(DATA_BWLIST, filterStack.getOrDefault(BMDataComponents.FILTER_BLACKWHITELIST, 0)); + + for (int i = 0; i < 9; i++) { + ItemStack slotStack = stacks.get(i); + rawData.set(DATA_TAG + i, slotStack.getOrDefault(BMDataComponents.FILTER_TAG_INDEX, 0)); + rawData.set(DATA_ENCHANT + i, slotStack.getOrDefault(BMDataComponents.FILTER_ENCHANT_INDEX, 0)); + rawData.set(DATA_ENCHANT_LVL + i, slotStack.getOrDefault(BMDataComponents.FILTER_ENCHANT_LEVEL, 0)); + } + + FilterData data = new FilterData(rawData) { + @Override + public void set(int index, int value) { + super.set(index, value); + + if (index == DATA_SLOT) { + filterStack.set(BMDataComponents.GHOST_SLOT, value); + return; + } + + if (index == DATA_BWLIST) { + filterStack.set(BMDataComponents.FILTER_BLACKWHITELIST, value); + return; + } + + int kind = (index - 2) / 9; + int offset = (index - 2) % 9; + ItemStack targetStack = filterInv.getStackInSlot(offset); + DataComponentType component = switch (kind) { + case 0 -> { + if (value == 0) { + targetStack.remove(BMDataComponents.FILTER_TAG); + } else { + targetStack.set(BMDataComponents.FILTER_TAG, FilterHelper.getTag(targetStack, value)); + } + yield BMDataComponents.FILTER_TAG_INDEX.get(); + } + case 1 -> BMDataComponents.FILTER_ENCHANT_INDEX.get(); + case 2 -> BMDataComponents.FILTER_ENCHANT_LEVEL.get(); + + default -> throw new IllegalStateException("got {} for index -> {} for kind"); + }; + targetStack.set(component, value); + filterInv.setChanged(offset); + } + }; + + return new SimpleMenuProvider( + (containerId, playerInv, player) -> new FilterMenu( + containerId, + playerInv, + filterInv, + data, + slot, + filterStack.has(BMDataComponents.FILTER_TAG_INDEX), + filterStack.has(BMDataComponents.FILTER_ENCHANT_INDEX) + ), + filterStack.getDisplayName() + ); } } diff --git a/src/main/java/wayoftime/bloodmagic/common/menu/AbstractGhostMenu.java b/src/main/java/wayoftime/bloodmagic/common/menu/AbstractGhostMenu.java index fef2662e6f..a6855ed04a 100644 --- a/src/main/java/wayoftime/bloodmagic/common/menu/AbstractGhostMenu.java +++ b/src/main/java/wayoftime/bloodmagic/common/menu/AbstractGhostMenu.java @@ -19,6 +19,8 @@ public AbstractGhostMenu(MenuType type, int containerId, Inventory playerInve this.tracker = tracker; this.handler = handler; this.addDataSlots(tracker); + this.heldSlot = heldSlot; + this.playerInv = playerInventory; for (int i = 0; i < rows; i++) { for (int j = 0; j < columns; j++) { @@ -43,6 +45,9 @@ public AbstractGhostMenu(MenuType type, int containerId, Inventory playerInve } } + public final int heldSlot; + public final Inventory playerInv; + public final GhostItemHandler handler; public final ContainerData tracker; public int getLastGhostSlotClicked() { @@ -62,11 +67,12 @@ public void clicked(int slotId, int button, ClickType clickType, Player player) if (heldStack.isEmpty() && !slotStack.isEmpty()) { // I clicked on the slot with an empty hand. Selecting! updateGhostSelection(tracker.get(0), slotId); - BloodMagic.LOGGER.info("selected ghost slot {} index {}", slotId, slot.getSlotIndex()); setData(0, slot.getSlotIndex()); // Return here to not save the server-side inventory return; } else if (!heldStack.isEmpty() && slotStack.isEmpty() && ghostSlot.isValid(heldStack)) { + updateGhostSelection(tracker.get(0), slotId); + setData(0, slot.getSlotIndex()); ItemStack copyStack = heldStack.copy(); copyStack.setCount(1); slot.set(copyStack); diff --git a/src/main/java/wayoftime/bloodmagic/common/menu/BMMenus.java b/src/main/java/wayoftime/bloodmagic/common/menu/BMMenus.java index d4e8510bff..f617b90281 100644 --- a/src/main/java/wayoftime/bloodmagic/common/menu/BMMenus.java +++ b/src/main/java/wayoftime/bloodmagic/common/menu/BMMenus.java @@ -21,6 +21,8 @@ public class BMMenus { public static final DeferredHolder, MenuType> MASTER_NODE = MENUS.register("node_master", () -> new MenuType<>(NodeMasterMenu::new, FeatureFlags.DEFAULT_FLAGS)); public static final DeferredHolder, MenuType> FILTERED_NODE = MENUS.register("node_filtered", () -> IMenuTypeExtension.create(NodeFilterMenu::new)); + public static final DeferredHolder, MenuType> ITEM_FILTER = MENUS.register("item_filter", () -> IMenuTypeExtension.create(FilterMenu::new)); + public static void register(IEventBus modbus) { MENUS.register(modbus); } diff --git a/src/main/java/wayoftime/bloodmagic/common/menu/FilterData.java b/src/main/java/wayoftime/bloodmagic/common/menu/FilterData.java new file mode 100644 index 0000000000..1c2d4a265e --- /dev/null +++ b/src/main/java/wayoftime/bloodmagic/common/menu/FilterData.java @@ -0,0 +1,41 @@ +package wayoftime.bloodmagic.common.menu; + +import net.minecraft.world.inventory.ContainerData; + +import java.util.ArrayList; +import java.util.List; + +public class FilterData implements ContainerData { + + private final List contents; + public FilterData(int count) { + List contents = new ArrayList<>(count); + for (int i = 0; i < count; i++) { + contents.add(0); + } + this.contents = contents; + } + + public FilterData(List contents) { + this.contents = new ArrayList<>(contents.size()); + // just so we dont end up with a non-mutable list + for (int i = 0; i < contents.size(); i++) { + this.contents.add(i, contents.get(i)); + } + } + + @Override + public int get(int index) { + return contents.get(index); + } + + @Override + public void set(int index, int value) { + contents.set(index, value); + } + + @Override + public int getCount() { + return contents.size(); + } +} diff --git a/src/main/java/wayoftime/bloodmagic/common/menu/FilterMenu.java b/src/main/java/wayoftime/bloodmagic/common/menu/FilterMenu.java new file mode 100644 index 0000000000..7cf219fcff --- /dev/null +++ b/src/main/java/wayoftime/bloodmagic/common/menu/FilterMenu.java @@ -0,0 +1,69 @@ +package wayoftime.bloodmagic.common.menu; + +import net.minecraft.network.RegistryFriendlyByteBuf; +import net.minecraft.world.entity.player.Inventory; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.ItemStack; +import wayoftime.bloodmagic.util.helper.FilterHelper; + +import static wayoftime.bloodmagic.util.helper.FilterHelper.*; + +public class FilterMenu extends AbstractGhostMenu { + + public final boolean isTag; + public final boolean isEnchant; + public FilterMenu(int containerId, Inventory playerInv, RegistryFriendlyByteBuf buf) { + super(BMMenus.ITEM_FILTER.get(), containerId, playerInv, FilterHelper.CONTAINER_DATA_SIZE, 3, 3, 110, 15, 105, buf.readInt()); + isTag = buf.readBoolean(); + isEnchant = buf.readBoolean(); + } + + public FilterMenu(int containerId, Inventory playerInv, GhostItemHandler filterInv, FilterData filterData, int slot, boolean tag, boolean enchant) { + super(BMMenus.ITEM_FILTER.get(), containerId, playerInv, filterData, filterInv, 3, 3, 110, 15, 105, slot); + isTag = tag; + isEnchant = enchant; + } + + @Override + public boolean clickMenuButton(Player player, int id) { + return switch (id) { + case BUTTON_BWLIST -> { + int state = tracker.get(DATA_BWLIST); + setData(DATA_BWLIST, state == 0 ? 1 : 0); + yield true; + } + + case BUTTON_TAG -> { + int slot = tracker.get(DATA_SLOT); + int state = tracker.get(DATA_TAG + slot); + ItemStack contentStack = handler.getStackInSlot(slot); + state = FilterHelper.cycleTag(contentStack, state); + setData(DATA_TAG + slot, state); + yield true; + } + + case BUTTON_ENCHANT -> { + int slot = tracker.get(DATA_SLOT); + int state = tracker.get(DATA_ENCHANT + slot); + ItemStack contentStack = handler.getStackInSlot(slot); + state = FilterHelper.cycleEnchant(contentStack, state); + setData(DATA_ENCHANT + slot, state); + yield true; + } + + case BUTTON_ENCHANT_LVL -> { + int slot = tracker.get(DATA_SLOT); + int state = tracker.get(DATA_ENCHANT_LVL + slot); + setData(DATA_ENCHANT_LVL + slot, state == 0 ? 1 : 0); + yield true; + } + + default -> false; + }; + } + + @Override + public boolean stillValid(Player player) { + return true; + } +} diff --git a/src/main/java/wayoftime/bloodmagic/common/menu/GhostItemHandler.java b/src/main/java/wayoftime/bloodmagic/common/menu/GhostItemHandler.java index 3d62eaa7bd..1a04d07cae 100644 --- a/src/main/java/wayoftime/bloodmagic/common/menu/GhostItemHandler.java +++ b/src/main/java/wayoftime/bloodmagic/common/menu/GhostItemHandler.java @@ -2,6 +2,7 @@ import net.minecraft.core.NonNullList; import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.component.ItemContainerContents; import net.neoforged.neoforge.items.ItemStackHandler; public class GhostItemHandler extends ItemStackHandler { @@ -13,4 +14,17 @@ public GhostItemHandler(NonNullList initial) { public GhostItemHandler(int size) { super(size); } + + public GhostItemHandler(ItemContainerContents contents) { + super(contents.getSlots()); + contents.copyInto(this.stacks); + } + + public void setChanged(int slot) { + onContentsChanged(slot); + } + + public ItemContainerContents toContents() { + return ItemContainerContents.fromItems(this.stacks); + } } diff --git a/src/main/java/wayoftime/bloodmagic/common/network/BMPackets.java b/src/main/java/wayoftime/bloodmagic/common/network/BMPackets.java new file mode 100644 index 0000000000..5e29731b35 --- /dev/null +++ b/src/main/java/wayoftime/bloodmagic/common/network/BMPackets.java @@ -0,0 +1,16 @@ +package wayoftime.bloodmagic.common.network; + +import net.neoforged.neoforge.network.event.RegisterPayloadHandlersEvent; +import net.neoforged.neoforge.network.registration.PayloadRegistrar; + +public class BMPackets { + public static void register(RegisterPayloadHandlersEvent event) { + final PayloadRegistrar registrar = event.registrar("1"); // no clue what the version is on about, but docs say 1 so we do 1 + + registrar.playToServer( + GhostAmountPacket.TYPE, + GhostAmountPacket.STREAM_CODEC, + GhostAmountPacket::handle + ); + } +} diff --git a/src/main/java/wayoftime/bloodmagic/common/network/GhostAmountPacket.java b/src/main/java/wayoftime/bloodmagic/common/network/GhostAmountPacket.java new file mode 100644 index 0000000000..a47c9c8d07 --- /dev/null +++ b/src/main/java/wayoftime/bloodmagic/common/network/GhostAmountPacket.java @@ -0,0 +1,36 @@ +package wayoftime.bloodmagic.common.network; + +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.network.codec.ByteBufCodecs; +import net.minecraft.network.codec.StreamCodec; +import net.minecraft.network.protocol.common.custom.CustomPacketPayload; +import net.minecraft.world.item.ItemStack; +import net.neoforged.neoforge.network.handling.IPayloadContext; +import wayoftime.bloodmagic.BloodMagic; +import wayoftime.bloodmagic.common.datacomponent.BMDataComponents; +import wayoftime.bloodmagic.common.menu.FilterMenu; + +public record GhostAmountPacket(int slot, int amount) implements CustomPacketPayload { + public static final CustomPacketPayload.Type TYPE = new CustomPacketPayload.Type<>(BloodMagic.rl("ghost_amount")); + + public static final StreamCodec STREAM_CODEC = StreamCodec.composite( + ByteBufCodecs.VAR_INT, GhostAmountPacket::slot, + ByteBufCodecs.VAR_INT, GhostAmountPacket::amount, + GhostAmountPacket::new + ); + + @Override + public Type type() { + return TYPE; + } + + public static void handle(GhostAmountPacket packet, IPayloadContext context) { + if (!(context.player().containerMenu instanceof FilterMenu filterMenu)) { + BloodMagic.LOGGER.warn("ghost amount packet recieved but no open filter menu"); + return; + } + ItemStack contentStack = filterMenu.handler.getStackInSlot(packet.slot); + contentStack.set(BMDataComponents.GHOST_AMOUNT, packet.amount); + filterMenu.handler.setChanged(packet.slot); + } +} diff --git a/src/main/java/wayoftime/bloodmagic/common/tag/BMTags.java b/src/main/java/wayoftime/bloodmagic/common/tag/BMTags.java index 42754ba32a..4fa8de6107 100644 --- a/src/main/java/wayoftime/bloodmagic/common/tag/BMTags.java +++ b/src/main/java/wayoftime/bloodmagic/common/tag/BMTags.java @@ -18,6 +18,10 @@ public static class Items { public static final TagKey NODE_DEBUGGER = tag(bm("node_debugger")); + public static final TagKey FILTERS = tag(bm("routing_filter")); + public static final TagKey TAG_FILTER = withParent(FILTERS, bm("tag")); + public static final TagKey ENCHANT_FILTER = withParent(FILTERS, bm("enchant")); + public static final TagKey STORAGE_BLOCKS_HELLFORGED = fromBlock(Blocks.STORAGE_BLOCKS_HELLFORGED); public static final TagKey ARC_TOOL = tag(bm("arc_tool")); diff --git a/src/main/java/wayoftime/bloodmagic/util/helper/FilterHelper.java b/src/main/java/wayoftime/bloodmagic/util/helper/FilterHelper.java new file mode 100644 index 0000000000..b20c94d955 --- /dev/null +++ b/src/main/java/wayoftime/bloodmagic/util/helper/FilterHelper.java @@ -0,0 +1,127 @@ +package wayoftime.bloodmagic.util.helper; + +import net.minecraft.core.component.DataComponents; +import net.minecraft.network.chat.CommonComponents; +import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.MutableComponent; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.tags.TagKey; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.enchantment.EnchantmentHelper; +import net.minecraft.world.item.enchantment.ItemEnchantments; +import wayoftime.bloodmagic.common.datacomponent.BMDataComponents; + +import java.util.ArrayList; +import java.util.List; + +public class FilterHelper { + public static final int CONTAINER_DATA_SIZE = 2 + (3 * 9); // slot/bwlist + per slot tag/enchant/enchant lvl + + public static final int DATA_SLOT = 0; + public static final int DATA_BWLIST = DATA_SLOT + 1; + public static final int DATA_TAG = DATA_BWLIST + 1; + public static final int DATA_ENCHANT = DATA_TAG + 9; + public static final int DATA_ENCHANT_LVL = DATA_ENCHANT + 9; + + public static final int BUTTON_BWLIST = 0; + public static final int BUTTON_TAG = 1; + public static final int BUTTON_ENCHANT = 2; + public static final int BUTTON_ENCHANT_LVL = 3; + + public static TagKey getTag(ItemStack target, int index) { + return target.getTags().toList().get(index - 1); + } + + public static MutableComponent translate(String name) { + return Component.translatable("filter.bloodmagic." + name); + } + + public static int cycleTag(ItemStack contentStack, int index) { + index++; + List> tags = contentStack.getTags().toList(); + if (index > tags.size()) { + index = 0; + } + + return index; + } + + public static ItemEnchantments getEnchantments(ItemStack contentStack) { + ItemEnchantments enchantmentList; + if (contentStack.has(DataComponents.ENCHANTMENTS)) { + enchantmentList = contentStack.get(DataComponents.ENCHANTMENTS); + } else if (contentStack.has(DataComponents.STORED_ENCHANTMENTS)) { + enchantmentList = contentStack.get(DataComponents.STORED_ENCHANTMENTS); + } else { + // no enchantments, neither applied nor stored + return ItemEnchantments.EMPTY; + } + + return enchantmentList; + } + + public static int cycleEnchant(ItemStack contentStack, int index) { + index++; + ItemEnchantments enchantmentList = getEnchantments(contentStack); + if (index >= enchantmentList.size() + 2 || enchantmentList.isEmpty()) { + index = 0; + } + if (enchantmentList.size() == 1 && index == 1) { // state would have been 0 before, so changing from 1 to 2 means skipping over "any" if there is only 1 enchant since it'd be the same as "every" + index = 2; + } + + return index; + } + + public static List tagButtonText(ItemStack contentStack) { + List component = new ArrayList<>(); + int index = contentStack.getOrDefault(BMDataComponents.FILTER_TAG_INDEX, 0); + if (index == 0) { + component.add(translate("any_tag")); + contentStack.getTags() + .map(TagKey::location) + .map(ResourceLocation::toString) + .map(Component::literal) + .forEachOrdered(component::add); + return component; + } + + if (contentStack.has(BMDataComponents.FILTER_TAG)) { + component.add(translate("specified_tag")); + component.add(Component.literal(contentStack.get(BMDataComponents.FILTER_TAG).location().toString())); + return component; + } + + return List.of(translate("no_valid_tag")); + } + + public static List enchantButtonText(ItemStack contentStack) { + final List component = new ArrayList<>(); + int index = contentStack.getOrDefault(BMDataComponents.FILTER_ENCHANT_INDEX, 0); + ItemEnchantments enchantments = getEnchantments(contentStack); + if (enchantments.isEmpty()) { + return List.of(translate("no_enchant")); + } + if (index < 2) { + if (index == 0) { + component.add(translate("every_enchant")); + } else { + component.add(translate("any_enchant")); + } + EnchantmentHelper.runIterationOnItem(contentStack, (enchantment, level) -> { + component.add(enchantment.value().description()); + }); + } else { + component.add(translate("specified_enchant")); + component.add(enchantments.keySet().stream().toList().get(index - 2).value().description()); + } + + return component; + } + + public static List enchantLevelButtonText(ItemStack contentStack) { + int index = contentStack.getOrDefault(BMDataComponents.FILTER_ENCHANT_LEVEL, 0); + return index == 0 ? List.of(translate("enchant_lvl_exact")) : List.of(translate("enchant_lvl_any")); + } +} diff --git a/src/main/resources/assets/bloodmagic/textures/gui/container/filter_item.png b/src/main/resources/assets/bloodmagic/textures/gui/container/filter_item.png index 804db55592806642265c8cc2ad7da2ff56c1fb59..c08e33e43b2f6c8f73edd3c61787a44589c261e1 100644 GIT binary patch literal 1147 zcmeAS@N?(olHy`uVBq!ia0y~yU<5K5893O0R7}x|G!U;i$lZzY=1HA;AcrO0(btiI zVPik{pF~z5Um@8e$d`ekN{xY`p@o6r7f`6-1p`B=0RzLU1O^7H84L{K1#@-<+5jau z3p^r=85sBufiR<}hF1enkiEpy*OmPxx0slSd0}gb0s{l{MNb#UkcwMx?>gqqb`WWJ z=sq=gX7(A^2_H1~JWwd$eVlyJH&gibCMjma$3OQ?-Ca4+<4?N7*<#WEK8%$sVwy_z zpP2aG`=9d3IXYBn!=(6of1aetxT{|i^=F7@D%cqlBU-lh^{$SN7r*a$CbSASnA>wO zC@=us!o+~Yn6R3Ex`Ms$Wu18wgSvLD+dR9I;luOZjV`yhng9Q4J$>dI3x?;PZ-)L= z+yAg)weW$D6(yQI+54~0>zVTy8MZStL^CM7XE>wYSiQcH ziRr@&6^1A2llQZJ_Y1ly+%{`VG&nwI z`STw)s<8VH8kq_VdW;+l0SnrHGX!~E-1hd7eo~+1n_yAF%O<{pg67@gIV?u${Kf0c znMz~D1qEyGpSM4pQ^+)9Kcn}JisW;bEX|lI*^rY3DD03E3ey82paAP8!4q@to=>zk zW16}7H&D~w7c3x$Zuod?&eGx>mQOs$p@8I3Z~(C!PzBOlDasQpch5guCYQ(3WD7J< z7m_OdD}M-F2umpbX7Id9+rVC=;ivS5mbKfT>CAona7#3nK!zJHz%U&c{2CM19(eYq zj_>wH(HU=UaJ>-&J4NH&kMmY`N{d#l%91*M@o1})Kf~3B1qG%j+SnUj@7UKc+1qKE g{cZ*-fCFN6%(6NVJOBUy literal 17389 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 diff --git a/src/main/resources/assets/bloodmagic/textures/gui/sprites/container/filter/blacklist.png b/src/main/resources/assets/bloodmagic/textures/gui/sprites/container/filter/blacklist.png new file mode 100644 index 0000000000000000000000000000000000000000..b8218fb043e47452b29de5d5c1881ec3706f82ad GIT binary patch literal 393 zcmeAS@N?(olHy`uVBq!ia0vp^A|TAc1|)ksWqE-VV{wqX6XVU3I`u#fOS+@4BLl<6 ze(pbstU$g(vPY0F14ES>14Ba#1H&(%P{RubhEf9thF1v;3|2E37{m+a>`sfOKw47VZL8?C+r0Zo%M8a z46!)<_VQldW&;7%2kgt*Z6zLXT}x==X}H0ZQk9m_&9Owf!8U>6bx>ksszF!Kk_TG< zUw*zE$u`eQJ2}iSZR&-cKlGNB@;{R-zmTwMS!PQ|OGnBqwVzyfo%0VgDVlt8WLQwz zpD6LB>U7Vn6X$lXV-Dn7dg;ZM_G4=f*+j2N-BxXSF>zk%%vhLsA ddA~mYVwe@Vz+cC6hZ4|Z44$rjF6*2UngBAFl{x?b literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/bloodmagic/textures/gui/sprites/container/filter/enchant.png b/src/main/resources/assets/bloodmagic/textures/gui/sprites/container/filter/enchant.png new file mode 100644 index 0000000000000000000000000000000000000000..e206725dcc5e21667f66ffa2bcae06d4217a3ca9 GIT binary patch literal 724 zcmV;_0xSKAP)z@;j|==^1poj5AY({UO#lFTCIA3{ga82g0001h=l}q9FaQARU;qF* zm;eA5aGbhPJOBUy24YJ`L;(K){{a7>y{D4^000SaNLh0L01m=iRh>gD-q$9S8N+Xh_vv;XXA0G7E2NT ztokK)xF`4i@_i@gUijyve)nK^hgVke4)tD*sYL##_o{vc3hmXUp&r`(I-moPTPw(G z>!bQ3hqsJ20WhPhrJ9*_Xl>R2cxL3;4(i%k=n1=})33{W*B2I56;-k766{AE4}0nK z>$0Q6p0HaE`8}n5Fy!QgCr6&5|78_ z{K+PXggg=ndF1h<3At??mP^we5|76v67rSSj&s=3q)8;?V|eTdi^X13-Gk##$@(lK$U|*mOGnK_mWf>p6g1Bl~lr_>THqU2rYAbBV zm(tbYE{igsb~yL6k+E<_{q^V2(xeGMU5yLF+)(`2cKQk@OW+biwS$QO0000z@;j|==^1poj5AY({UO#lFTCIA3{ga82g0001h=l}q9FaQARU;qF* zm;eA5aGbhPJOBUy24YJ`L;(K){{a7>y{D4^000SaNLh0L01m%Kw>Q; zliC;MpA_Eq*9kz#y_)NV;%TZY4FJ6MC)tiv_j{woX_Q8rD)YMUL=`=HPf?C+D^5Di zG}=`8qrw)aQI6P5xp%F{LYOpm41DNLFc-^`R#zHwY9~VLj0M(}0>Wd5RcWd>7cTjy zLKG8e_Yweeu}$j}p>N%>UIn|omX7W$=`ULVnXV;l@{QKeg|uCgb&k5Swls;)uPGzR;xv6@chEa#!3)F5qV$|Vq( z5}(f}=TBS3JTgO#)v646z0%&=s%)FX$YNTVjwR{pJjFqK9id2^ zP$bS^|5Zd+LR8jRSWfX~Dxm}dlMH#i5{)hGe!EQ#M%h{wrFyyO-=7!czWa{^ptI+$ z?0U=Nfs|5ZH3&dyv5t=`8D+p3%bS^;PXh31KFoiNA1*xqim`^P8UO$Q07*qoM6N<$ Ef@_XS6#xJL literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/bloodmagic/textures/gui/sprites/container/filter/enchant_every.png b/src/main/resources/assets/bloodmagic/textures/gui/sprites/container/filter/enchant_every.png new file mode 100644 index 0000000000000000000000000000000000000000..1fe4a983d6d82fbea29d904abef351ba6ac47f0b GIT binary patch literal 761 zcmVz@;j|==^1poj5AY({UO#lFTCIA3{ga82g0001h=l}q9FaQARU;qF* zm;eA5aGbhPJOBUy24YJ`L;(K){{a7>y{D4^000SaNLh0L01mQ~pcgZM|9m!oI~^E*wu&QKka$Mo+R4)bw|vsoo-WE=^`kKbcm{nEeGg*xEQ= zZ==qo$(9P6>Me4}WzF5I{B|Owaij97J;78g3#}+qb81Jz%M1sXl|0~)gPJtd*z$+` zTOo>-v~M1Oso1LZk?=BKSHAOcGNa^KK708AiwV|Q%=lJ7$*QjEbP%1*!t_uIJ(S`` z*E5bbp3k45wp+pNuA-$q3;kmYAk#LFOMYl(X~dl2xYv?qPH;t&GQ#w6&gKzq^`nG)_1gr?2}e zVsbDoOUy2$csrI*g27Rq3=Bxu{YSFx+ij?|$l6m{WR{Ei-gS)|fwue{%AKkJ6cw7# r!z+2UtsVCS;PXs`{@%L^J2QR(-fs3)z@;j|==^1poj5AY({UO#lFTCIA3{ga82g0001h=l}q9FaQARU;qF* zm;eA5aGbhPJOBUy24YJ`L;(K){{a7>y{D4^000SaNLh0L01mb{GX(uvchKz*D!5ZyF2d)@ zjd4C%>srt8{oeP-^L{+v2mhRu{WfM&x>)z>#C4TL$J=wRr5UL2h$arkp+Bhs8UWSr zTf%mKDu3kgUfdP{k7DV-nQ7=0Ee{zq;P8wQ5vv=5N*Lxh(>#4$Zk#!e4Z!Wo=P(T& zAmB8#8`hhQVH!H~n`ul#XKG{s$FZ3j8Suf1mWOHRWKvNf1rBy=qBj|nu3!66+wIJ! z{_Ykbb$I^z3>#JXofa*R?DU+kW__%YeK5y~%*CKXtyQ6`>ljz={Dzjk)B(7AZCL7T zBKHK>b&;+dX@`li(+w!V(Zec5%VRW~2VnX0s&CkJU1oE)c(eFe9-BiQsyI8?#$Ejz^Xg2 z%6bj=+m_Na*h4*GkvI_L{>%b}LIHr;+)a*GUlCdpJZm2cfSSIPlc|U=U!N*z@;j|==^1poj5AY({UO#lFTCIA3{ga82g0001h=l}q9FaQARU;qF* zm;eA5aGbhPJOBUy24YJ`L;(K){{a7>y{D4^000SaNLh0L01mC*z>7!i=$Z=P zQ0h4jYYYd_HI@0jD7vOH+TDU_8jN-OpQXiVciUX9k;VPiDuxpaWHM=t@V2_m0V?}aZby72{#wZv>F|E$)elWN_va9* llLbJH-$N?BD{&ES@fYjmq{V`F?~ecg002ovPDHLkV1me$9Gn0E literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/bloodmagic/textures/gui/sprites/container/filter/tag.png b/src/main/resources/assets/bloodmagic/textures/gui/sprites/container/filter/tag.png new file mode 100644 index 0000000000000000000000000000000000000000..48b3602ef47375c46f1e5435a6e65b826f6889b9 GIT binary patch literal 554 zcmV+_0@eMAP)z@;j|==^1poj5AY({UO#lFTCIA3{ga82g0001h=l}q9FaQARU;qF* zm;eA5aGbhPJOBUy24YJ`L;(K){{a7>y{D4^000SaNLh0L01m+8{%E=B=nxAm2m%M&uA%Noyu-7W=$W49o`=_c zzC1tRuQy?q#kFe1cKW7iv8x^mKL%^nifx*fJ6>9nJkhyXuui*)rfGEAO?U42=)nHI zc0LH`U=LQGVyPkkY;Et@&bPpznu^;1Hj0EjNQfMVa~tpET307*qoM6N<$f{*m&ssI20 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/bloodmagic/textures/gui/sprites/container/filter/tag_all.png b/src/main/resources/assets/bloodmagic/textures/gui/sprites/container/filter/tag_all.png new file mode 100644 index 0000000000000000000000000000000000000000..0e8cce0c8bce1f90164ffd0ba457bd2066b72473 GIT binary patch literal 625 zcmV-%0*?KOP)z@;j|==^1poj5AY({UO#lFTCIA3{ga82g0001h=l}q9FaQARU;qF* zm;eA5aGbhPJOBUy24YJ`L;(K){{a7>y{D4^000SaNLh0L01m`luh+>B%vf zOor2wV{a|_Dk1Lg9q0w%;m-98G~!_au=n;20NI^$MHas&pb-y? zrA32c$-y*p9Yv8D_hjh8Uaw`aZN~!vQkXB$h=;}a#FRJQN^g1)fa`A`F^`(k8{%8# zh^|p-w1`G$u@2K%hiRtuAk%uVzl-hKRT?cS^$XO;0o2eS5nW?tH3i^n=NmbqYfy4f zLr>T*)_?$%oGw`P*H6)I-(Xo~;?JHdU6Eb8^^Fhg7i&}+Es}{z=3--*X0FSu-M(RD zcv!jmedTW$(KP@s^7cCmH8d!VXIW)7cXvhY>koNR8s9Iy{#14Ba#1H&(%P{RubhEf9thF1v;3|2E37{m+a>`sfOKw47A+>A8oIsZ_@_V{C zhFF|_JK53eu!Bh3|AVdGj&J?$JmZ_E^fvbq<2{*0^Aefva!-@Uf8cY@V11}i`Oy!% zJv2jSNnGr`Ab&4O;@-B*zSv!`G|$Lt)3a7m@)S}zY0B}a zbg$#bhy=6Qv*d$UYTf?U%X(nj+U-{jD*Urs7jw)lHaV8FaveiSt-pHuj?CAwx04F{ zSFM_mI#W`{u;qZn)c3icTi5(6`F79vd~sCv&Fp7;(|hjDX!rT%UFs@my{A<0rg1Lc z46`dcl0KXlk({}(!@xJ#M^D{izs22D4hH?#ywA#uC6e1V|LzM3-5F!|C8)QmUG}BO uD#6sqLlO$7^UkiX>*)BB|8d3t#r$u4*aPS0-!%b-7K5j&pUXO@geCyc1h6{* literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/bloodmagic/textures/item/filter_composite.png b/src/main/resources/assets/bloodmagic/textures/item/filter_composite.png new file mode 100644 index 0000000000000000000000000000000000000000..dea72ba3d42be7fa8c2c1bfb06c6b071a2a10e07 GIT binary patch literal 6722 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 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/bloodmagic/textures/item/filter_data.png b/src/main/resources/assets/bloodmagic/textures/item/filter_data.png new file mode 100644 index 0000000000000000000000000000000000000000..d8952e5f660d604114dac0d61bfc2dcfaa715104 GIT binary patch literal 682 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 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/bloodmagic/textures/item/filter_fluid.png b/src/main/resources/assets/bloodmagic/textures/item/filter_fluid.png new file mode 100644 index 0000000000000000000000000000000000000000..5de1391d03e220b1402b6f963cfaeafbda02d0e8 GIT binary patch literal 681 zcmV;a0#^NrP)WFU8GbZ8()Nlj2>E@cM*00Iq3L_t(I%cYawOOtUF z#y@AgvR7=*ww5e0gGEpp3Q0PQs3c6(ya*z3PWl)63%co|3p1!Ff)EA~1VRwqb=QS? z5u~~7B9Sz0nZJh4z1w=<(}iqpGAQc6_vUb(hv#|D`HHIYKjkXd6p_E`0T|^5FArT; z5s|Zf{i+CWUcQhsJ$))7vRARO7u-ECq>+G+>_9}@nop6*W-uxY?R0)Z84_19I2H!e zZ8CH45V?#+Z6JVYn%K6@ls|}NS;WGnc8p?hbOO2?cIfZwrsa4OcOKuzLGbVQQS0;b zG5((DTM8tqx~o7{iB3S*wLx`&FAIx2d>Z5R$ZhV`2S_BASz7sy;dXPPtzDxNyO@#; zdLzSnuC0UWswy7Dp783{P2y=7^8|Tx6o#kb)YUhzwzf)RdsqP}AxQ6}*x1}8xt&79 zMf~mvW1b-6uVt#sBibFK= zA?8U&(OJ1A|9_7+qMha$}1?`L4FezZa3lWbyCSqc2e8qvKHA) zmJ3b}+qO%<1z_<5XzjeH0HNjLJYR3fnExW-f P00000NkvXXu0mjf>b@?t literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/bloodmagic/textures/item/filter_mod.png b/src/main/resources/assets/bloodmagic/textures/item/filter_mod.png new file mode 100644 index 0000000000000000000000000000000000000000..01a6f0b86166f0a35ccb3cf074e05ec78a4ddf1b GIT binary patch literal 681 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 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/bloodmagic/textures/item/filter_tag.png b/src/main/resources/assets/bloodmagic/textures/item/filter_tag.png new file mode 100644 index 0000000000000000000000000000000000000000..253b039925e583c7b8ff09e1e7464c323957ef9f GIT binary patch literal 681 zcmV;a0#^NrP)WFU8GbZ8()Nlj2>E@cM*00Iq3L_t(I%cYawOH*+e z#y{^mV@FLVir9!S7!>_NNztYeMMZ_pf*|aNt1i0grrZ9CE{eM9W>DZoQHT%`K^RS; zyDY^L(Wwn{b%s0cY;}D|5Lt7poshx24GYo_6=N9 z5s^dDGpYz9Lr>*kZ&XD@Hco786rZ{5im)VIBj^hxIcSxX%9JE| z-Z`VS!FrZbizfa|7l8oaaGkD zVmt!3b2j7C(=0E2p}wKryWEyaQDwmH>Ysz^>MB*cppeJIh+Zp^z`I zzk3bWbv@#eu>1gY96hc8;np_YzIUGjgu-F1#Ft9HQAF5?SHe77_}BUYrQ{K$aQf|E P00000NkvXXu0mjfhGr@~ literal 0 HcmV?d00001 From b2770853dc349abb1f9c7b6cd7effe1dc3ea9f2b Mon Sep 17 00:00:00 2001 From: stellanera Date: Mon, 8 Dec 2025 10:51:36 +0100 Subject: [PATCH 8/8] working on filters --- .../client/screen/FilterScreen.java | 26 +++-- .../client/screen/NodeFilterScreen.java | 21 +++- .../common/blockentity/FilterNodeTile.java | 32 ++--- .../bloodmagic/common/item/FilterItem.java | 22 ++-- .../bloodmagic/common/menu/FilterMenu.java | 17 ++- .../common/menu/NodeFilterMenu.java | 109 +++++++++++------- .../bloodmagic/util/helper/FilterHelper.java | 1 + 7 files changed, 150 insertions(+), 78 deletions(-) diff --git a/src/main/java/wayoftime/bloodmagic/client/screen/FilterScreen.java b/src/main/java/wayoftime/bloodmagic/client/screen/FilterScreen.java index 55aa4cee6e..6db95d64d7 100644 --- a/src/main/java/wayoftime/bloodmagic/client/screen/FilterScreen.java +++ b/src/main/java/wayoftime/bloodmagic/client/screen/FilterScreen.java @@ -77,10 +77,17 @@ protected void init() { addRenderableWidget(amountBox); + if (menu.heldSlot == -1) { + addRenderableWidget(Button.builder(FilterHelper.translate("return"), button -> sendButtonClick(BUTTON_RETURN)) + .pos(leftPos + 8, topPos + 55) + .size(50, 20) + .build()); + } + addMultiIconButton(DATA_BWLIST, MultiIconButton.builder(button -> sendButtonClick(BUTTON_BWLIST)) .icons(whitelist, blacklist) .tooltips(FilterHelper.translate("whitelist"), FilterHelper.translate("blacklist")) - .pos(leftPos + 7, topPos + 32) + .pos(leftPos + 8, topPos + 32) .size(20, 20) .build() ); @@ -89,7 +96,7 @@ protected void init() { addPerSlotButton(DATA_TAG, MultiIconButton.builder(button -> sendButtonClick(BUTTON_TAG)) .icons(tag_all, tag) .stateGetter(state -> state == 0 ? 0 : 1) - .pos(leftPos + 27, topPos + 32) + .pos(leftPos + 28, topPos + 32) .size(20, 20) .build() ); @@ -104,14 +111,14 @@ protected void init() { default -> 2; }) - .pos(leftPos + 27, topPos + 32) + .pos(leftPos + 28, topPos + 32) .size(20, 20) .build() ); addPerSlotButton(DATA_ENCHANT_LVL, MultiIconButton.builder(button -> sendButtonClick(BUTTON_ENCHANT_LVL)) .icons(enchant_level_exact, enchant_level_any) - .pos(leftPos + 47, topPos + 32) + .pos(leftPos + 48, topPos + 32) .size(20, 20) .build() ); @@ -175,15 +182,18 @@ private void sendButtonClick(int buttonId) { public boolean mouseClicked(double mouseX, double mouseY, int button) { super.mouseClicked(mouseX, mouseY, button); // otherwise screen dies - if (menu.getData(DATA_SLOT) != -1) { // Text box only selectable if a ghost slot has been clicked. - if (amountBox.isMouseOver(mouseX, mouseY) && button == 1) // Right-Clicked - { + if (menu.getData(DATA_SLOT) != -1 && amountBox.isMouseOver(mouseX, mouseY)) { // Text box only selectable if a ghost slot has been clicked. + if (button == 1) { amountBox.setValue(""); setGhostAmount(0); amountBox.setFocused(true); - return true; } + if (button == 0) { + amountBox.setFocused(true); + } + return true; } + amountBox.setFocused(false); return true; } diff --git a/src/main/java/wayoftime/bloodmagic/client/screen/NodeFilterScreen.java b/src/main/java/wayoftime/bloodmagic/client/screen/NodeFilterScreen.java index 16e38cbac5..38e520ab81 100644 --- a/src/main/java/wayoftime/bloodmagic/client/screen/NodeFilterScreen.java +++ b/src/main/java/wayoftime/bloodmagic/client/screen/NodeFilterScreen.java @@ -16,6 +16,7 @@ import net.minecraft.world.phys.Vec3; import wayoftime.bloodmagic.BloodMagic; import wayoftime.bloodmagic.common.menu.NodeFilterMenu; +import wayoftime.bloodmagic.util.helper.FilterHelper; public class NodeFilterScreen extends AbstractContainerScreen { @@ -60,7 +61,6 @@ public NodeFilterScreen(NodeFilterMenu menu, Inventory playerInv, Component titl up = Direction.UP; down = Direction.DOWN; } - sendButtonClick(front.get3DDataValue()); } @Override @@ -84,6 +84,14 @@ protected void init() { .size(8, 20) .build() ); + + addRenderableWidget(Button.builder(FilterHelper.translate("edit"), button -> sendButtonClick(NodeFilterMenu.BUTTON_EDIT)) + .pos(leftPos + 8, topPos + 31) + .size(50, 20) + .build() + ); + + // sendButtonClick(front.get3DDataValue()); // not sure whether to always focus front or to keep track of last selected } private Button directionButton(Direction dir, Pair pos) { @@ -123,6 +131,17 @@ protected void renderLabels(GuiGraphics guiGraphics, int mouseX, int mouseY) { guiGraphics.blitSprite(selected, activePos.getFirst() - 3, activePos.getSecond() - 3, 24, 24); } + @Override + public boolean keyPressed(int keyCode, int scanCode, int modifiers) { + // TODO implement E/esc/backspace to "go back" one layer + return super.keyPressed(keyCode, scanCode, modifiers); + } + + @Override + public boolean shouldCloseOnEsc() { + return false; // we handle esc ourselves, so ignore in super + } + private Pair getPosForDir(Direction dir) { if (dir == up) { return upLocation; diff --git a/src/main/java/wayoftime/bloodmagic/common/blockentity/FilterNodeTile.java b/src/main/java/wayoftime/bloodmagic/common/blockentity/FilterNodeTile.java index 0d965e4700..9f1eeb75ff 100644 --- a/src/main/java/wayoftime/bloodmagic/common/blockentity/FilterNodeTile.java +++ b/src/main/java/wayoftime/bloodmagic/common/blockentity/FilterNodeTile.java @@ -11,6 +11,7 @@ import net.minecraft.world.entity.player.Inventory; import net.minecraft.world.entity.player.Player; import net.minecraft.world.inventory.AbstractContainerMenu; +import net.minecraft.world.inventory.ContainerData; import net.minecraft.world.inventory.SimpleContainerData; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.block.Block; @@ -28,6 +29,7 @@ import wayoftime.bloodmagic.common.menu.NodeFilterMenu; import wayoftime.bloodmagic.common.routing.IRoutingFilter; import wayoftime.bloodmagic.common.routing.NodeContext; +import wayoftime.bloodmagic.common.tag.BMTags; import java.util.*; import java.util.function.BiConsumer; @@ -35,7 +37,7 @@ public class FilterNodeTile extends RoutingNodeTile implements MenuProvider { public static final int MAX_PRIO = 10; - private final boolean isOutput; + public final boolean isOutput; public FilterNodeTile(BlockPos pos, BlockState blockState, boolean isOutput) { super(BMTiles.FILTER_ROUTING_NODE.get(), pos, blockState); this.isOutput = isOutput; @@ -45,7 +47,7 @@ public FilterNodeTile(BlockPos pos, BlockState state) { this(pos, state, false); } - public int[] priorities = new int[] {0, 0, 0, 0, 0, 0}; + public int[] priorities = new int[] {0, 0, 0, 0, 0, 0, 0}; public final ItemStackHandler filterInv = new ItemStackHandler(6) { @Override @@ -55,7 +57,9 @@ public int getSlotLimit(int slot) { @Override public boolean isItemValid(int slot, ItemStack stack) { - return stack.getCapability(BMCaps.ROUTING_FILTER_PROVIDER, NodeContext.EMPTY) != null; + //return stack.getCapability(BMCaps.ROUTING_FILTER_PROVIDER, NodeContext.EMPTY) != null; + // TODO temporary convenience + return stack.is(BMTags.Items.FILTERS); } @Override @@ -102,25 +106,21 @@ public Component getDisplayName() { @Override public @Nullable AbstractContainerMenu createMenu(int containerId, Inventory playerInventory, Player player) { - return new NodeFilterMenu(containerId, playerInventory, filterInv, new SimpleContainerData(7) { - private int side; + return new NodeFilterMenu(containerId, playerInventory, filterInv, new ContainerData() { @Override public int get(int index) { - if (index < 6) { - return FilterNodeTile.this.priorities[index]; - } else { - return side; - } + return FilterNodeTile.this.priorities[index]; } @Override public void set(int index, int value) { - if (index < 6) { - FilterNodeTile.this.priorities[index] = value; - FilterNodeTile.this.setChanged(); - } else { - side = value; - } + FilterNodeTile.this.priorities[index] = value; + FilterNodeTile.this.setChanged(); + } + + @Override + public int getCount() { + return FilterNodeTile.this.priorities.length; } }, getBlockPos(), isOutput); } diff --git a/src/main/java/wayoftime/bloodmagic/common/item/FilterItem.java b/src/main/java/wayoftime/bloodmagic/common/item/FilterItem.java index b713975e4f..6a196b12e9 100644 --- a/src/main/java/wayoftime/bloodmagic/common/item/FilterItem.java +++ b/src/main/java/wayoftime/bloodmagic/common/item/FilterItem.java @@ -1,7 +1,9 @@ package wayoftime.bloodmagic.common.item; +import net.minecraft.core.BlockPos; import net.minecraft.core.NonNullList; import net.minecraft.core.component.DataComponentType; +import net.minecraft.network.RegistryFriendlyByteBuf; import net.minecraft.world.InteractionHand; import net.minecraft.world.InteractionResultHolder; import net.minecraft.world.MenuProvider; @@ -38,16 +40,19 @@ public InteractionResultHolder use(Level level, Player player, Intera if (!level.isClientSide) { int slot = usedHand == InteractionHand.MAIN_HAND ? player.getInventory().selected : 0; - player.openMenu(getFilterProvider(filterStack, slot), buf -> { - buf.writeInt(slot); - buf.writeBoolean(filterStack.is(BMTags.Items.TAG_FILTER)); - buf.writeBoolean(filterStack.is(BMTags.Items.ENCHANT_FILTER)); - }); + player.openMenu(getFilterProvider(filterStack, slot, BlockPos.ZERO), buf -> writeBuf(filterStack, slot, BlockPos.ZERO, buf)); } return InteractionResultHolder.sidedSuccess(filterStack, level.isClientSide); } - public static MenuProvider getFilterProvider(ItemStack filterStack, int slot) { + public static void writeBuf(ItemStack filterStack, int slot, BlockPos nodePos, RegistryFriendlyByteBuf buf) { + buf.writeInt(slot); + buf.writeBoolean(filterStack.is(BMTags.Items.TAG_FILTER)); + buf.writeBoolean(filterStack.is(BMTags.Items.ENCHANT_FILTER)); + buf.writeBlockPos(nodePos); + } + + public static MenuProvider getFilterProvider(ItemStack filterStack, int slotHeldIn, BlockPos nodePos) { NonNullList stacks = NonNullList.withSize(9, ItemStack.EMPTY); if (filterStack.has(BMDataComponents.FILTER_INVENTORY)) { ItemContainerContents contents = filterStack.get(BMDataComponents.FILTER_INVENTORY); @@ -122,9 +127,10 @@ public void set(int index, int value) { playerInv, filterInv, data, - slot, + slotHeldIn, filterStack.has(BMDataComponents.FILTER_TAG_INDEX), - filterStack.has(BMDataComponents.FILTER_ENCHANT_INDEX) + filterStack.has(BMDataComponents.FILTER_ENCHANT_INDEX), + nodePos ), filterStack.getDisplayName() ); diff --git a/src/main/java/wayoftime/bloodmagic/common/menu/FilterMenu.java b/src/main/java/wayoftime/bloodmagic/common/menu/FilterMenu.java index 7cf219fcff..caf2118015 100644 --- a/src/main/java/wayoftime/bloodmagic/common/menu/FilterMenu.java +++ b/src/main/java/wayoftime/bloodmagic/common/menu/FilterMenu.java @@ -1,9 +1,11 @@ package wayoftime.bloodmagic.common.menu; +import net.minecraft.core.BlockPos; import net.minecraft.network.RegistryFriendlyByteBuf; import net.minecraft.world.entity.player.Inventory; import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.ItemStack; +import wayoftime.bloodmagic.common.blockentity.FilterNodeTile; import wayoftime.bloodmagic.util.helper.FilterHelper; import static wayoftime.bloodmagic.util.helper.FilterHelper.*; @@ -12,21 +14,34 @@ public class FilterMenu extends AbstractGhostMenu { public final boolean isTag; public final boolean isEnchant; + public final BlockPos nodePos; public FilterMenu(int containerId, Inventory playerInv, RegistryFriendlyByteBuf buf) { super(BMMenus.ITEM_FILTER.get(), containerId, playerInv, FilterHelper.CONTAINER_DATA_SIZE, 3, 3, 110, 15, 105, buf.readInt()); isTag = buf.readBoolean(); isEnchant = buf.readBoolean(); + nodePos = buf.readBlockPos(); } - public FilterMenu(int containerId, Inventory playerInv, GhostItemHandler filterInv, FilterData filterData, int slot, boolean tag, boolean enchant) { + public FilterMenu(int containerId, Inventory playerInv, GhostItemHandler filterInv, FilterData filterData, int slot, boolean tag, boolean enchant, BlockPos nodePos) { super(BMMenus.ITEM_FILTER.get(), containerId, playerInv, filterData, filterInv, 3, 3, 110, 15, 105, slot); isTag = tag; isEnchant = enchant; + this.nodePos = nodePos; } @Override public boolean clickMenuButton(Player player, int id) { return switch (id) { + case BUTTON_RETURN -> { + if (player.level().getBlockEntity(nodePos) instanceof FilterNodeTile node) { + player.openMenu(node, buf -> { + buf.writeBlockPos(nodePos); + buf.writeBoolean(node.isOutput); + }); + } + yield true; + } + case BUTTON_BWLIST -> { int state = tracker.get(DATA_BWLIST); setData(DATA_BWLIST, state == 0 ? 1 : 0); diff --git a/src/main/java/wayoftime/bloodmagic/common/menu/NodeFilterMenu.java b/src/main/java/wayoftime/bloodmagic/common/menu/NodeFilterMenu.java index 3cdf119d41..f59cd10dbb 100644 --- a/src/main/java/wayoftime/bloodmagic/common/menu/NodeFilterMenu.java +++ b/src/main/java/wayoftime/bloodmagic/common/menu/NodeFilterMenu.java @@ -3,6 +3,7 @@ import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.network.RegistryFriendlyByteBuf; +import net.minecraft.resources.ResourceLocation; import net.minecraft.world.entity.player.Inventory; import net.minecraft.world.entity.player.Player; import net.minecraft.world.inventory.*; @@ -14,6 +15,8 @@ import wayoftime.bloodmagic.common.block.BMBlocks; import wayoftime.bloodmagic.common.blockentity.BMTiles; import wayoftime.bloodmagic.common.blockentity.FilterNodeTile; +import wayoftime.bloodmagic.common.item.FilterItem; +import wayoftime.bloodmagic.common.tag.BMTags; public class NodeFilterMenu extends AbstractContainerMenu { @@ -40,47 +43,18 @@ public NodeFilterMenu(int containerId, Inventory playerInv, RegistryFriendlyByte public final boolean isOutput; public NodeFilterMenu(int containerId, Inventory playerInv, IItemHandler filterInv, ContainerData priorities, BlockPos nodePos, boolean isOutput) { super(BMMenus.FILTERED_NODE.get(), containerId); - addDataSlots(priorities); this.priorities = priorities; + addDataSlots(this.priorities); this.nodePos = nodePos; this.player = playerInv.player; this.isOutput = isOutput; - // TODO extract into separate class so this is more sightly - this.addSlot(new SlotItemHandler(filterInv, 0, 71, 33) { - @Override - public boolean mayPlace(ItemStack stack) { - if (stack.isEmpty()) - return false; - return getItemHandler().isItemValid(priorities.get(DATA_SIDE), stack); - } - - @Override - public ItemStack getItem() { - return getItemHandler().getStackInSlot(priorities.get(DATA_SIDE)); - } - - @Override - public void set(ItemStack stack) { - ((IItemHandlerModifiable) this.getItemHandler()).setStackInSlot(priorities.get(DATA_SIDE), stack); - this.setChanged(); - } - - public void initialize(ItemStack stack) { - ((IItemHandlerModifiable) this.getItemHandler()).setStackInSlot(priorities.get(DATA_SIDE), stack); - this.setChanged(); - } - - @Override - public boolean mayPickup(Player playerIn) { - return !this.getItemHandler().extractItem(priorities.get(DATA_SIDE), 1, true).isEmpty(); - } - - @Override - public ItemStack remove(int amount) { - return this.getItemHandler().extractItem(priorities.get(DATA_SIDE), amount, false); - } - }); + this.addSlot(new FilterSlot(filterInv, 0, 71, 33)); + this.addSlot(new FilterSlot(filterInv, 1, 71, 33)); + this.addSlot(new FilterSlot(filterInv, 2, 71, 33)); + this.addSlot(new FilterSlot(filterInv, 3, 71, 33)); + this.addSlot(new FilterSlot(filterInv, 4, 71, 33)); + this.addSlot(new FilterSlot(filterInv, 5, 71, 33)); // player inv for (int i = 0; i < 3; i++) { @@ -99,21 +73,27 @@ public ItemStack remove(int amount) { public boolean clickMenuButton(Player player, int id) { return switch (id) { case BUTTON_PRIO_DOWN, BUTTON_PRIO_UP -> { - int side = priorities.get(DATA_SIDE); - int prio = priorities.get(side); + int side = getData(DATA_SIDE); + int prio = getData(side); int newPrio = Math.clamp(prio + (id == BUTTON_PRIO_UP ? 1 : -1), 0, FilterNodeTile.MAX_PRIO); - priorities.set(side, newPrio); - broadcastChanges(); + setData(side, newPrio); yield true; } + case BUTTON_EDIT -> { + int slot = getData(DATA_SIDE); + ItemStack filterStack = getSlot(slot).getItem(); + if (!filterStack.isEmpty() && filterStack.is(BMTags.Items.FILTERS)) { + player.openMenu(FilterItem.getFilterProvider(filterStack, -1, nodePos), buf -> FilterItem.writeBuf(filterStack, -1, nodePos, buf)); + } yield false; } + case DATA_DOWN, DATA_UP, DATA_NORTH, DATA_SOUTH, DATA_WEST, DATA_EAST -> { - priorities.set(DATA_SIDE, id); - broadcastChanges(); + setData(DATA_SIDE, id); yield true; } + default -> false; }; } @@ -122,10 +102,40 @@ public int getData(int index) { return priorities.get(index); } + private static final int playerInvStart = 6; + private static final int playerInvEnd = playerInvStart + (3 * 9); // end is exclusive anyways + private static final int hotbarStart = playerInvEnd; + private static final int hotbarEnd = hotbarStart + 9; @Override public ItemStack quickMoveStack(Player player, int index) { - // TODO at least implement shift-clicking filters out maybe - return ItemStack.EMPTY; + ItemStack movedStack = ItemStack.EMPTY; + Slot movedSlot = this.slots.get(index); + + if (movedSlot.hasItem()) { + ItemStack rawStack = movedSlot.getItem(); + movedStack = rawStack.copy(); + + if (index < playerInvStart) { + if (!this.moveItemStackTo(rawStack, playerInvStart, hotbarEnd, false)) { + return ItemStack.EMPTY; + } + } + + if (index >= playerInvStart) { + int target = getData(DATA_SIDE); + if (!this.moveItemStackTo(rawStack, target, target + 1, false)) { + return ItemStack.EMPTY; + } + } + + if (rawStack.isEmpty()) { + movedSlot.set(ItemStack.EMPTY); + } else { + movedSlot.setChanged(); + } + } + + return movedStack; } @Override @@ -133,4 +143,15 @@ public boolean stillValid(Player player) { return AbstractContainerMenu.stillValid(ContainerLevelAccess.create(this.player.level(), this.nodePos), player, isOutput ? BMBlocks.OUTPUT_ROUTING_NODE.block().get() : BMBlocks.INPUT_ROUTING_NODE.block().get()); } + + public class FilterSlot extends SlotItemHandler { + public FilterSlot(IItemHandler itemHandler, int index, int xPosition, int yPosition) { + super(itemHandler, index, xPosition, yPosition); + } + + @Override + public boolean isActive() { + return index == NodeFilterMenu.this.getData(DATA_SIDE); + } + } } diff --git a/src/main/java/wayoftime/bloodmagic/util/helper/FilterHelper.java b/src/main/java/wayoftime/bloodmagic/util/helper/FilterHelper.java index b20c94d955..62824ae9bd 100644 --- a/src/main/java/wayoftime/bloodmagic/util/helper/FilterHelper.java +++ b/src/main/java/wayoftime/bloodmagic/util/helper/FilterHelper.java @@ -28,6 +28,7 @@ public class FilterHelper { public static final int BUTTON_TAG = 1; public static final int BUTTON_ENCHANT = 2; public static final int BUTTON_ENCHANT_LVL = 3; + public static final int BUTTON_RETURN = 4; public static TagKey getTag(ItemStack target, int index) { return target.getTags().toList().get(index - 1);