yo what the FUCK did they do to GUIs

This commit is contained in:
Halbear
2026-07-27 19:35:41 +01:00
parent a92d49f214
commit 4bc528f3d5
14 changed files with 707 additions and 57 deletions
@@ -1,12 +1,17 @@
package net.halbear.aotg; package net.halbear.aotg;
import net.halbear.aotg.registries.ModBiomes; import net.halbear.aotg.registries.ModBiomes;
import net.halbear.aotg.registries.ModMenus;
import net.halbear.aotg.utility.DataGenerators.AgeOfTheGodsDataGeneration; import net.halbear.aotg.utility.DataGenerators.AgeOfTheGodsDataGeneration;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.network.codec.StreamCodec;
import net.minecraft.network.protocol.common.custom.CustomPacketPayload;
import net.minecraft.world.level.biome.Biome; import net.minecraft.world.level.biome.Biome;
import net.minecraft.world.level.dimension.DimensionType; import net.minecraft.world.level.dimension.DimensionType;
import net.minecraft.world.level.levelgen.WorldGenSettings; import net.minecraft.world.level.levelgen.WorldGenSettings;
import net.neoforged.bus.api.Event; import net.neoforged.bus.api.Event;
import net.neoforged.neoforge.network.handling.IPayloadHandler;
import org.slf4j.Logger; import org.slf4j.Logger;
import com.mojang.logging.LogUtils; import com.mojang.logging.LogUtils;
@@ -38,6 +43,9 @@ import net.neoforged.neoforge.registries.DeferredHolder;
import net.neoforged.neoforge.registries.DeferredItem; import net.neoforged.neoforge.registries.DeferredItem;
import net.neoforged.neoforge.registries.DeferredRegister; import net.neoforged.neoforge.registries.DeferredRegister;
import java.util.HashMap;
import java.util.Map;
import static net.halbear.aotg.registries.ModBlockEntities.BLOCK_ENTITY_TYPES; import static net.halbear.aotg.registries.ModBlockEntities.BLOCK_ENTITY_TYPES;
import static net.halbear.aotg.registries.ModBlocks.*; import static net.halbear.aotg.registries.ModBlocks.*;
import static net.halbear.aotg.registries.ModFoliagePlacers.FOLIAGE_PLACERS; import static net.halbear.aotg.registries.ModFoliagePlacers.FOLIAGE_PLACERS;
@@ -78,6 +86,7 @@ public class AgeoftheGods {
// Register the Deferred Register to the mod event bus so blocks get registered // Register the Deferred Register to the mod event bus so blocks get registered
BLOCKS.register(modEventBus); BLOCKS.register(modEventBus);
BLOCK_ENTITY_TYPES.register(modEventBus); BLOCK_ENTITY_TYPES.register(modEventBus);
ModMenus.MENUS.register(modEventBus);
// Register the Deferred Register to the mod event bus so items get registered // Register the Deferred Register to the mod event bus so items get registered
ITEMS.register(modEventBus); ITEMS.register(modEventBus);
// Register the Deferred Register to the mod event bus so tabs get registered // Register the Deferred Register to the mod event bus so tabs get registered
@@ -122,4 +131,18 @@ public class AgeoftheGods {
// Do something when the server starts // Do something when the server starts
LOGGER.info("HELLO from server starting"); LOGGER.info("HELLO from server starting");
} }
private static boolean networkingRegistered = false;
private static final Map<CustomPacketPayload.Type<?>, NetworkMessage<?>> MESSAGES = new HashMap<>();
private record NetworkMessage<T extends CustomPacketPayload>(StreamCodec<? extends FriendlyByteBuf, T> reader, IPayloadHandler<T> handler) {
}
public static <T extends CustomPacketPayload> void addNetworkMessage(CustomPacketPayload.Type<T> id, StreamCodec<? extends FriendlyByteBuf, T> reader, IPayloadHandler<T> handler) {
if (networkingRegistered)
throw new IllegalStateException("Cannot register new network messages after networking has been registered");
MESSAGES.put(id, new NetworkMessage<>(reader, handler));
}
} }
@@ -0,0 +1,66 @@
package net.halbear.aotg.custom.GuiScreens;
import com.mojang.blaze3d.platform.InputConstants;
import net.halbear.aotg.custom.blocks.AlloyFurnace.AlloyFurnaceGUI;
import net.halbear.aotg.registries.ModScreens;
import net.minecraft.client.gui.GuiGraphicsExtractor;
import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen;
import net.minecraft.client.input.KeyEvent;
import net.minecraft.client.renderer.RenderPipelines;
import net.minecraft.network.chat.Component;
import net.minecraft.resources.Identifier;
import net.minecraft.world.entity.player.Inventory;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.level.Level;
public class AlloyFurnaceGUIScreen extends AbstractContainerScreen<AlloyFurnaceGUI> implements ModScreens.ScreenAccessor {
private final Level world;
private final int x, y, z;
private final Player entity;
private boolean menuStateUpdateActive = false;
private static final Identifier BACKGROUND = Identifier.parse("ageofthegods:textures/screens/example_gui.png");
public AlloyFurnaceGUIScreen(AlloyFurnaceGUI container, Inventory inventory, Component text) {
super(container, inventory, text, 176, 166);
this.world = container.world;
this.x = container.x;
this.y = container.y;
this.z = container.z;
this.entity = container.entity;
}
@Override
public void updateMenuState(int elementType, String name, Object elementState) {
menuStateUpdateActive = false;
}
@Override
public void extractRenderState(GuiGraphicsExtractor guiGraphics, int mouseX, int mouseY, float partialTicks) {
super.extractRenderState(guiGraphics, mouseX, mouseY, partialTicks);
}
@Override
public void extractBackground(GuiGraphicsExtractor guiGraphics, int mouseX, int mouseY, float partialTicks) {
super.extractBackground(guiGraphics, mouseX, mouseY, partialTicks);
guiGraphics.blit(RenderPipelines.GUI_TEXTURED, BACKGROUND, this.leftPos, this.topPos, 0, 0, this.imageWidth, this.imageHeight, this.imageWidth, this.imageHeight);
}
@Override
public boolean keyPressed(KeyEvent event) {
int key = InputConstants.getKey(event).getValue();
if (key == 256) {
this.minecraft.player.closeContainer();
return true;
}
return super.keyPressed(event);
}
@Override
protected void extractLabels(GuiGraphicsExtractor guiGraphics, int mouseX, int mouseY) {
}
@Override
public void init() {
super.init();
}
}
@@ -1,30 +1,43 @@
package net.halbear.aotg.custom.blocks; package net.halbear.aotg.custom.blocks.AlloyFurnace;
import net.halbear.aotg.registries.ModBlocks; import net.halbear.aotg.registries.ModBlocks;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction; import net.minecraft.core.Direction;
import net.minecraft.core.HolderLookup; import net.minecraft.core.HolderLookup;
import net.minecraft.core.NonNullList;
import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.CompoundTag;
import net.minecraft.network.Connection; import net.minecraft.network.Connection;
import net.minecraft.network.chat.Component;
import net.minecraft.network.protocol.Packet; import net.minecraft.network.protocol.Packet;
import net.minecraft.network.protocol.game.ClientGamePacketListener; import net.minecraft.network.protocol.game.ClientGamePacketListener;
import net.minecraft.network.protocol.game.ClientboundBlockEntityDataPacket; import net.minecraft.network.protocol.game.ClientboundBlockEntityDataPacket;
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.Level;
import net.minecraft.world.level.block.Rotation; import net.minecraft.world.level.block.Rotation;
import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.storage.ValueInput; import net.minecraft.world.level.storage.ValueInput;
import net.minecraft.world.level.storage.ValueOutput; import net.minecraft.world.level.storage.ValueOutput;
import net.neoforged.neoforge.transfer.ResourceHandler;
import net.neoforged.neoforge.transfer.StacksResourceHandler;
import net.neoforged.neoforge.transfer.item.ItemResource;
import net.neoforged.neoforge.transfer.item.ItemStacksResourceHandler;
import org.jspecify.annotations.Nullable;
import static net.halbear.aotg.custom.blocks.AlloyFurnaceMultiBlock.MULTI_BLOCK_POSITIONS; import static net.halbear.aotg.custom.blocks.AlloyFurnace.AlloyFurnaceMultiBlock.*;
import static net.halbear.aotg.custom.blocks.AlloyFurnaceMultiBlock.FACING; import static net.halbear.aotg.custom.blocks.AlloyFurnace.AlloyFurnaceUpdateHandler.getInverseRotationForDirection;
import static net.halbear.aotg.custom.blocks.AlloyFurnaceUpdateHandler.getInverseRotationForDirection;
import static net.halbear.aotg.registries.ModBlockEntities.ALLOY_FURNACE_BLOCK_ENTITY; import static net.halbear.aotg.registries.ModBlockEntities.ALLOY_FURNACE_BLOCK_ENTITY;
public class AlloyFurnaceBlockEntity extends BlockEntity { public class AlloyFurnaceBlockEntity extends BlockEntity implements MenuProvider {
private boolean isFormed = false; private boolean isFormed = false;
private float Fuel = 0.0f; private float Fuel = 0.0f;
private int progress = 0; private int progress = 0;
private final NonNullList<ItemStack> items = NonNullList.withSize(2, ItemStack.EMPTY);
public AlloyFurnaceBlockEntity(BlockPos worldPosition, BlockState blockState) { public AlloyFurnaceBlockEntity(BlockPos worldPosition, BlockState blockState) {
super(ALLOY_FURNACE_BLOCK_ENTITY.get(), worldPosition, blockState); super(ALLOY_FURNACE_BLOCK_ENTITY.get(), worldPosition, blockState);
@@ -45,6 +58,19 @@ public class AlloyFurnaceBlockEntity extends BlockEntity {
Complete = false; Complete = false;
} }
} }
if(Complete){
for (BlockPos offset : MULTI_BLOCK_POSITIONS) {
int Part = AlloyFurnaceUpdateHandler.GetModelPart(offset);
BlockPos Rotated = offset.rotate(rotation);
BlockPos targetPos = masterPos.offset(Rotated);
BlockState state = level.getBlockState(targetPos);
if(state.getValue(PARENT_BLOCK) && !(offset.getX() == 0 && offset.getY() == 0 && offset.getZ() == 0)) state = state.setValue(AlloyFurnaceMultiBlock.PARENT_BLOCK,false);
if(state.getValue(MODEL_PART) != Part) state = state.setValue(AlloyFurnaceMultiBlock.MODEL_PART,Part);
if(state.getValue(FACING) != direction) state = state.setValue(FACING,direction);
level.setBlockAndUpdate(targetPos,state);
}
}
return Complete; return Complete;
} }
@@ -94,4 +120,26 @@ public class AlloyFurnaceBlockEntity extends BlockEntity {
public void onDataPacket(Connection connection, ValueInput input) { public void onDataPacket(Connection connection, ValueInput input) {
super.onDataPacket(connection, input); super.onDataPacket(connection, input);
} }
@Override
public Component getDisplayName() {
return Component.translatable("container.ageofthegods.alloy_furnace");
}
@Override
public @Nullable AbstractContainerMenu createMenu(int i, Inventory inventory, Player player) {
return null;
}
private final StacksResourceHandler<ItemStack, ItemResource> resourceHandler = new ItemStacksResourceHandler(this.items) {
@Override
protected void onContentsChanged(int index, ItemStack stack) {
super.onContentsChanged(index, stack);
setChanged();
}
};
public StacksResourceHandler<ItemStack, ItemResource> getResourceHandler() {
return this.resourceHandler;
}
} }
@@ -0,0 +1,266 @@
package net.halbear.aotg.custom.blocks.AlloyFurnace;
import net.halbear.aotg.registries.ModBlocks;
import net.halbear.aotg.registries.ModMenus;
import net.minecraft.core.BlockPos;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.Container;
import net.minecraft.world.entity.Entity;
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.minecraft.world.level.Level;
import net.minecraft.world.level.block.entity.BaseContainerBlockEntity;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.neoforged.neoforge.capabilities.Capabilities;
import net.neoforged.neoforge.transfer.IndexModifier;
import net.neoforged.neoforge.transfer.ResourceHandler;
import net.neoforged.neoforge.transfer.StacksResourceHandler;
import net.neoforged.neoforge.transfer.access.ItemAccess;
import net.neoforged.neoforge.transfer.item.*;
import net.neoforged.neoforge.transfer.transaction.Transaction;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Supplier;
public class AlloyFurnaceGUI extends AbstractContainerMenu implements ModMenus.MenuAccessor {
public final Map<String, Object> menuState = new HashMap<>() {
@Override
public Object put(String key, Object value) {
if (!this.containsKey(key) && this.size() >= 4)
return null;
return super.put(key, value);
}
};
public final Level world;
public final Player entity;
public int x, y, z;
private ContainerLevelAccess access = ContainerLevelAccess.NULL;
private ResourceHandler<ItemResource> internal;
private final Map<Integer, Slot> customSlots = new HashMap<>();
private boolean bound = false;
private Supplier<Boolean> boundItemMatcher = null;
private Entity boundEntity = null;
private BlockEntity boundBlockEntity = null;
public AlloyFurnaceGUI(int containerId, Inventory playerInv, FriendlyByteBuf buffer) {
super(ModMenus.ALLOY_FURNACE_GUI.get(), containerId);
this.entity = playerInv.player;
this.world = playerInv.player.level();
this.internal = new ItemStacksResourceHandler(4);
BlockPos pos = null;
if (buffer != null) {
pos = buffer.readBlockPos();
this.x = pos.getX();
this.y = pos.getY();
this.z = pos.getZ();
access = ContainerLevelAccess.create(world, pos);
}
if (pos != null) {
boundBlockEntity = this.world.getBlockEntity(pos);
if (boundBlockEntity instanceof BaseContainerBlockEntity baseContainerBlockEntity) {
this.internal = VanillaContainerWrapper.of(baseContainerBlockEntity);
this.bound = true;
}
}
this.customSlots.put(0, this.addSlot(new ResourceHandlerSlot(internal, this::setItemInSlot, 0, 42, 41) {
private final int slot = 0;
private int x = this.x;
private int y = this.y;
}));
this.customSlots.put(1, this.addSlot(new ResourceHandlerSlot(internal, this::setItemInSlot, 1, 21, 40) {
private final int slot = 1;
private int x = this.x;
private int y = this.y;
}));
this.customSlots.put(2, this.addSlot(new ResourceHandlerSlot(internal, this::setItemInSlot, 2, 63, 41) {
private final int slot = 2;
private int x = this.x;
private int y = this.y;
}));
this.customSlots.put(3, this.addSlot(new ResourceHandlerSlot(internal, this::setItemInSlot, 3, 129, 41) {
private final int slot = 3;
private int x = this.x;
private int y = this.y;
@Override
public boolean mayPlace(ItemStack stack) {
return false;
}
}));
for (int row = 0; row < 3; ++row) {
for (int col = 0; col < 9; ++col) {
this.addSlot(new Slot(playerInv, col + row * 9 + 9, 8 + col * 18, 84 + row * 18));
}
}
for (int col = 0; col < 9; ++col) {
this.addSlot(new Slot(playerInv, col, 8 + col * 18, 142));
}
}
private void setItemInSlot(int index, ItemResource resource, int amount) {
if (internal instanceof ItemStacksResourceHandler handler) {
handler.set(index, resource, amount);
} else if (boundBlockEntity instanceof Container container) {
container.setItem(index, resource.toStack(Math.max(0, amount)));
} else {
try (var tx = Transaction.openRoot()) {
if (!internal.getResource(index).isEmpty())
internal.extract(index, internal.getResource(index), internal.getAmountAsInt(index), tx);
if (!resource.isEmpty() && amount > 0)
internal.insert(index, resource, amount, tx);
tx.commit();
}
}
}
@Override
public boolean stillValid(Player player) {
if (this.bound) {
if (this.boundItemMatcher != null)
return this.boundItemMatcher.get();
else if (this.boundBlockEntity != null)
return AbstractContainerMenu.stillValid(this.access, player, this.boundBlockEntity.getBlockState().getBlock());
else if (this.boundEntity != null)
return this.boundEntity.isAlive();
}
return true;
}
@Override
public ItemStack quickMoveStack(Player playerIn, int index) {
ItemStack itemstack = ItemStack.EMPTY;
Slot slot = this.slots.get(index);
if (slot != null && slot.hasItem()) {
ItemStack itemstack1 = slot.getItem();
itemstack = itemstack1.copy();
if (index < 4) {
if (!this.moveItemStackTo(itemstack1, 4, this.slots.size(), true))
return ItemStack.EMPTY;
slot.onQuickCraft(itemstack1, itemstack);
} else if (!this.moveItemStackTo(itemstack1, 0, 4, false)) {
if (index < 4 + 27) {
if (!this.moveItemStackTo(itemstack1, 4 + 27, this.slots.size(), true))
return ItemStack.EMPTY;
} else {
if (!this.moveItemStackTo(itemstack1, 4, 4 + 27, false))
return ItemStack.EMPTY;
}
return ItemStack.EMPTY;
}
if (itemstack1.isEmpty()) {
slot.setByPlayer(ItemStack.EMPTY);
} else {
slot.setChanged();
}
if (itemstack1.getCount() == itemstack.getCount()) {
return ItemStack.EMPTY;
}
slot.onTake(playerIn, itemstack1);
}
return itemstack;
}
@Override
protected boolean moveItemStackTo(ItemStack itemStack, int startSlot, int endSlot, boolean backwards) {
boolean anythingChanged = false;
int destSlot = startSlot;
if (backwards) {
destSlot = endSlot - 1;
}
if (itemStack.isStackable()) {
while (!itemStack.isEmpty() && (backwards ? destSlot >= startSlot : destSlot < endSlot)) {
Slot slot = this.slots.get(destSlot);
ItemStack target = slot.getItem();
if (slot.mayPlace(target) && !target.isEmpty() && ItemStack.isSameItemSameComponents(itemStack, target)) {
int totalStack = target.getCount() + itemStack.getCount();
int maxStackSize = slot.getMaxStackSize(target);
if (totalStack <= maxStackSize) {
itemStack.setCount(0);
target.setCount(totalStack);
slot.set(target);
anythingChanged = true;
} else if (target.getCount() < maxStackSize) {
itemStack.shrink(maxStackSize - target.getCount());
target.setCount(maxStackSize);
slot.set(target);
anythingChanged = true;
}
}
if (backwards) {
destSlot--;
} else {
destSlot++;
}
}
}
if (!itemStack.isEmpty()) {
if (backwards) {
destSlot = endSlot - 1;
} else {
destSlot = startSlot;
}
while (backwards ? destSlot >= startSlot : destSlot < endSlot) {
Slot slotx = this.slots.get(destSlot);
ItemStack targetx = slotx.getItem();
if (targetx.isEmpty() && slotx.mayPlace(itemStack)) {
int maxStackSize = slotx.getMaxStackSize(itemStack);
slotx.setByPlayer(itemStack.split(Math.min(itemStack.getCount(), maxStackSize)));
slotx.setChanged();
anythingChanged = true;
break;
}
if (backwards) {
destSlot--;
} else {
destSlot++;
}
}
}
return anythingChanged;
}
@Override
public void removed(Player playerIn) {
super.removed(playerIn);
if (!bound && playerIn instanceof ServerPlayer serverPlayer) {
if (!serverPlayer.isAlive() || serverPlayer.hasDisconnected()) {
for (int j = 0; j < internal.size(); ++j) {
playerIn.drop(ItemUtil.getStack(internal, j), false);
setItemInSlot(j, ItemResource.EMPTY, 0);
}
} else {
for (int i = 0; i < internal.size(); ++i) {
playerIn.getInventory().placeItemBackInInventory(ItemUtil.getStack(internal, i));
setItemInSlot(i, ItemResource.EMPTY, 0);
}
}
}
}
@Override
public Map<Integer, Slot> getSlots() {
return Collections.unmodifiableMap(customSlots);
}
@Override
public Map<String, Object> getMenuState() {
return menuState;
}
}
@@ -1,17 +1,23 @@
package net.halbear.aotg.custom.blocks; package net.halbear.aotg.custom.blocks.AlloyFurnace;
import com.mojang.serialization.MapCodec; import io.netty.buffer.Unpooled;
import net.halbear.aotg.AgeoftheGods; import net.halbear.aotg.AgeoftheGods;
import net.halbear.aotg.registries.ModBlocks; import net.halbear.aotg.registries.ModBlocks;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction; import net.minecraft.core.Direction;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.network.chat.Component;
import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerLevel;
import net.minecraft.util.TriState; import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.Containers; import net.minecraft.world.Containers;
import net.minecraft.world.InteractionResult;
import net.minecraft.world.MenuProvider;
import net.minecraft.world.SimpleMenuProvider;
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.context.BlockPlaceContext; import net.minecraft.world.item.context.BlockPlaceContext;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.Level; import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.BaseEntityBlock;
import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.EntityBlock; import net.minecraft.world.level.block.EntityBlock;
import net.minecraft.world.level.block.Rotation; import net.minecraft.world.level.block.Rotation;
@@ -24,9 +30,10 @@ 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.BooleanProperty;
import net.minecraft.world.level.block.state.properties.EnumProperty; import net.minecraft.world.level.block.state.properties.EnumProperty;
import net.minecraft.world.level.block.state.properties.IntegerProperty; import net.minecraft.world.level.block.state.properties.IntegerProperty;
import net.minecraft.world.phys.BlockHitResult;
import org.jspecify.annotations.Nullable; import org.jspecify.annotations.Nullable;
import static net.halbear.aotg.custom.blocks.AlloyFurnaceUpdateHandler.getInverseRotationForDirection; import static net.halbear.aotg.custom.blocks.AlloyFurnace.AlloyFurnaceUpdateHandler.getInverseRotationForDirection;
import static net.halbear.aotg.registries.ModBlockEntities.ALLOY_FURNACE_BLOCK_ENTITY; import static net.halbear.aotg.registries.ModBlockEntities.ALLOY_FURNACE_BLOCK_ENTITY;
public class AlloyFurnaceMultiBlock extends Block implements EntityBlock { public class AlloyFurnaceMultiBlock extends Block implements EntityBlock {
@@ -74,23 +81,45 @@ public class AlloyFurnaceMultiBlock extends Block implements EntityBlock {
for(int x = -1; x < 2; x++){ for(int x = -1; x < 2; x++){
for(int z = -1; z < 2; z++){ for(int z = -1; z < 2; z++){
for(int y = -1; y < 2; y++){ for(int y = -1; y < 2; y++){
if(x == 0 && y == 0 && z == 0) continue; //skip if it is the block we're checking to place
/*check 3x3x3 area
and assign a BlockPos, and BlockState to the block at each offset*/
BlockPos parentPos = position.offset(x,y,z); BlockPos parentPos = position.offset(x,y,z);
BlockState state = level.getBlockState(parentPos); BlockState state = level.getBlockState(parentPos);
if(state.is(ModBlocks.ALLOY_FURNACE.get()) && state.getValue(PARENT_BLOCK)) { if(state.is(ModBlocks.ALLOY_FURNACE.get()) && state.getValue(PARENT_BLOCK)) {
AgeoftheGods.LOGGER.debug("LOCATED PARENT BLOCK AT: " + parentPos); //make sure the block matches, and that it has the "PARENT_BLOCK" boolean set to true, this means it is the parent block
Direction direction = state.getValue(FACING); Direction direction = state.getValue(FACING);
//get direction of parent block and then flip it to get the rotation
Rotation rotation = getInverseRotationForDirection(direction); Rotation rotation = getInverseRotationForDirection(direction);
AgeoftheGods.LOGGER.debug("Placed Next to PARENT_BLOCK");
for (BlockPos offset : MULTI_BLOCK_POSITIONS) { for (BlockPos offset : MULTI_BLOCK_POSITIONS) {
//iterate through the child block positions
BlockPos Rotated = offset.rotate(rotation); BlockPos Rotated = offset.rotate(rotation);
//rotate the child block position to face the direction of the parent block
BlockPos targetPos = parentPos.offset(Rotated); BlockPos targetPos = parentPos.offset(Rotated);
AgeoftheGods.LOGGER.debug("TARGET_POS: " + targetPos + " | CURRENT_POS: " + position + " | ROTATION: " + Rotated); //get the World Position of the child block and check if it matches the block we want to place
if (targetPos.getX() == position.getX() && targetPos.getY() == position.getY() && targetPos.getZ() == position.getZ()) { if (targetPos.getX() == position.getX() && targetPos.getY() == position.getY() && targetPos.getZ() == position.getZ()) {
//if it matches, the block we're placing is a child block, so set its parent value to false and its direction to the parent
blockState = blockState.setValue(PARENT_BLOCK, false); blockState = blockState.setValue(PARENT_BLOCK, false);
blockState = blockState.setValue(FACING, direction); blockState = blockState.setValue(FACING, direction);
//get an absolute value of the original child offset before rotating it
BlockPos purePos = new BlockPos(Math.abs(offset.getX()) , Math.abs(offset.getY()),Math.abs(offset.getZ()));
//set the model part to whatever value gets cross-matched when looking up offset positions in a Map containing the position and the respective model value
blockState = blockState.setValue(MODEL_PART, Math.max(AlloyFurnaceUpdateHandler.GetModelPart(purePos), 0));
return blockState;
}
}
}
}
}
}
if (blockState.getValue(PARENT_BLOCK)) AgeoftheGods.LOGGER.debug("becoming PARENT_BLOCK");
return blockState;
}
//old case switch hard code
/*// AgeoftheGods.LOGGER.debug("POS_STRING: " + PosString);
String PosString = Math.abs(offset.getX()) + "_" + Math.abs(offset.getY()) + "_" + Math.abs(offset.getZ()); String PosString = Math.abs(offset.getX()) + "_" + Math.abs(offset.getY()) + "_" + Math.abs(offset.getZ());
AgeoftheGods.LOGGER.debug("POS_STRING: " + PosString);
switch (PosString) { switch (PosString) {
case "0_0_0": case "0_0_0":
blockState = blockState.setValue(PARENT_BLOCK, true); blockState = blockState.setValue(PARENT_BLOCK, true);
@@ -117,17 +146,7 @@ public class AlloyFurnaceMultiBlock extends Block implements EntityBlock {
case "0_1_1": case "0_1_1":
blockState = blockState.setValue(MODEL_PART, 7); blockState = blockState.setValue(MODEL_PART, 7);
break; break;
} }*/
}
}
}
}
}
}
if (blockState.getValue(PARENT_BLOCK)) AgeoftheGods.LOGGER.debug("becoming PARENT_BLOCK");
return blockState;
}
@Override @Override
protected void createBlockStateDefinition(StateDefinition.Builder<Block,BlockState> builder){ protected void createBlockStateDefinition(StateDefinition.Builder<Block,BlockState> builder){
@@ -136,6 +155,26 @@ public class AlloyFurnaceMultiBlock extends Block implements EntityBlock {
builder.add(PARENT_BLOCK); builder.add(PARENT_BLOCK);
} }
@Override
public InteractionResult useWithoutItem(BlockState blockstate, Level world, BlockPos pos, Player entity, BlockHitResult hit) {
super.useWithoutItem(blockstate, world, pos, entity, hit);
if (entity instanceof ServerPlayer player) {
player.openMenu(new MenuProvider() {
@Override
public Component getDisplayName() {
return Component.literal("Sigma");
}
@Override
public AbstractContainerMenu createMenu(int id, Inventory inventory, Player player) {
return new AlloyFurnaceGUI(id, inventory, new FriendlyByteBuf(Unpooled.buffer()).writeBlockPos(pos));
}
}, pos);
}
return InteractionResult.SUCCESS;
}
@Override @Override
public @Nullable BlockEntity newBlockEntity(BlockPos blockPos, BlockState blockState) { public @Nullable BlockEntity newBlockEntity(BlockPos blockPos, BlockState blockState) {
return new AlloyFurnaceBlockEntity(blockPos,blockState); return new AlloyFurnaceBlockEntity(blockPos,blockState);
@@ -1,18 +1,22 @@
package net.halbear.aotg.custom.blocks; package net.halbear.aotg.custom.blocks.AlloyFurnace;
import net.halbear.aotg.AgeoftheGods; import net.halbear.aotg.AgeoftheGods;
import net.halbear.aotg.registries.ModBlocks; import net.halbear.aotg.registries.ModItems;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction; import net.minecraft.core.Direction;
import net.minecraft.core.component.DataComponents;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Items;
import net.minecraft.world.item.component.ItemContainerContents;
import net.minecraft.world.level.ItemLike;
import net.minecraft.world.level.block.Rotation; import net.minecraft.world.level.block.Rotation;
import net.minecraft.world.level.block.TestBlock;
import net.minecraft.world.level.block.state.BlockState;
import net.neoforged.bus.api.SubscribeEvent;
import net.neoforged.fml.common.EventBusSubscriber; import net.neoforged.fml.common.EventBusSubscriber;
import net.neoforged.neoforge.event.level.BlockEvent; import net.neoforged.neoforge.event.level.BlockEvent;
import java.util.ArrayList; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map;
@EventBusSubscriber(modid = AgeoftheGods.MODID) @EventBusSubscriber(modid = AgeoftheGods.MODID)
public class AlloyFurnaceUpdateHandler { public class AlloyFurnaceUpdateHandler {
@@ -20,6 +24,31 @@ public class AlloyFurnaceUpdateHandler {
public static final BlockPos[] parts = new BlockPos[]{new BlockPos(0,0,0),new BlockPos(-1,0,0),new BlockPos(-1,0,1),new BlockPos(0,0,1), public static final BlockPos[] parts = new BlockPos[]{new BlockPos(0,0,0),new BlockPos(-1,0,0),new BlockPos(-1,0,1),new BlockPos(0,0,1),
new BlockPos(0,1,0),new BlockPos(-1,1,0),new BlockPos(-1,1,1),new BlockPos(0,1,1)}; new BlockPos(0,1,0),new BlockPos(-1,1,0),new BlockPos(-1,1,1),new BlockPos(0,1,1)};
public static final Map<String, Integer> ModelPartLookup = new HashMap<>();
static{
for(int i = 0; i < 8; i++) {
String PosString = Math.abs(parts[i].getX()) + "_" + Math.abs(parts[i].getY()) + "_" + Math.abs(parts[i].getZ());
ModelPartLookup.put(PosString, i);
}
}
public static int GetModelPart(BlockPos MultipartLocation){
String PosString = Math.abs(MultipartLocation.getX()) + "_" + Math.abs(MultipartLocation.getY()) + "_" + Math.abs(MultipartLocation.getZ());
return ModelPartLookup.get(PosString);
}
protected ItemStack CreateFilledPot(Item ItemToFillWith, int StackSize){
ItemStack potStack = new ItemStack(Items.DECORATED_POT);
ItemStack newContents = new ItemStack(ItemToFillWith,StackSize);
ItemStack liquidMarker = new ItemStack(ModItems.FLUID_INDICATOR_ITEM.asItem(),1);
ItemContainerContents contents = ItemContainerContents.fromItems(List.of(liquidMarker, newContents));
potStack.set(DataComponents.CONTAINER, contents);
return potStack;
}
//@SubscribeEvent //@SubscribeEvent
public static void onNeighborNotify(BlockEvent.NeighborNotifyEvent event) { public static void onNeighborNotify(BlockEvent.NeighborNotifyEvent event) {
var level = event.getLevel(); var level = event.getLevel();
@@ -36,15 +65,6 @@ public class AlloyFurnaceUpdateHandler {
var state = event.getPlacedBlock(); var state = event.getPlacedBlock();
} }
public static int GetModelPart(BlockPos MultipartLocation){
for(int i = 0; i < 8; i++){
if(MultipartLocation.getX() == parts[i].getX() && MultipartLocation.getZ() == parts[i].getZ() && MultipartLocation.getY() == parts[i].getY()){
return i;
}
}
return -1;
}
public static BlockPos GetMultipartLocation(int ModelPart){ public static BlockPos GetMultipartLocation(int ModelPart){
return parts[Math.clamp(ModelPart,0,7)]; return parts[Math.clamp(ModelPart,0,7)];
} }
@@ -1,19 +1,11 @@
package net.halbear.aotg.registries; package net.halbear.aotg.registries;
import net.halbear.aotg.AgeoftheGods; import net.halbear.aotg.AgeoftheGods;
import net.halbear.aotg.custom.blocks.AlloyFurnaceBlockEntity; import net.halbear.aotg.custom.blocks.AlloyFurnace.AlloyFurnaceBlockEntity;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.core.registries.Registries; import net.minecraft.core.registries.Registries;
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.entity.BlockEntityType;
import net.minecraft.world.level.block.state.BlockBehaviour;
import net.neoforged.neoforge.registries.DeferredBlock;
import net.neoforged.neoforge.registries.DeferredHolder;
import net.neoforged.neoforge.registries.DeferredRegister; import net.neoforged.neoforge.registries.DeferredRegister;
import org.intellij.lang.annotations.Identifier;
import java.util.function.Function;
import java.util.function.Supplier; import java.util.function.Supplier;
public class ModBlockEntities { public class ModBlockEntities {
@@ -1,14 +1,10 @@
package net.halbear.aotg.registries; package net.halbear.aotg.registries;
import net.halbear.aotg.AgeoftheGods; import net.halbear.aotg.AgeoftheGods;
import net.halbear.aotg.custom.blocks.AlloyFurnaceMultiBlock; import net.halbear.aotg.custom.blocks.AlloyFurnace.AlloyFurnaceMultiBlock;
import net.halbear.aotg.custom.blocks.RockCoveredGrassBlock; import net.halbear.aotg.custom.blocks.RockCoveredGrassBlock;
import net.minecraft.core.registries.Registries;
import net.minecraft.resources.ResourceKey;
import net.minecraft.world.item.BlockItem; import net.minecraft.world.item.BlockItem;
import net.minecraft.world.item.Item;
import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.RotatedPillarBlock; import net.minecraft.world.level.block.RotatedPillarBlock;
import net.minecraft.world.level.block.SoundType; import net.minecraft.world.level.block.SoundType;
import net.minecraft.world.level.block.state.BlockBehaviour; import net.minecraft.world.level.block.state.BlockBehaviour;
@@ -24,6 +24,10 @@ public class ModItems {
public static final DeferredItem<BlockItem> OLIVE_LOG_ITEM = ITEMS.registerSimpleBlockItem("olive_log", OLIVE_LOG); public static final DeferredItem<BlockItem> OLIVE_LOG_ITEM = ITEMS.registerSimpleBlockItem("olive_log", OLIVE_LOG);
public static final DeferredItem<BlockItem> ALLOY_FURNACE_ITEM = ITEMS.registerSimpleBlockItem("alloy_furnace", ALLOY_FURNACE); public static final DeferredItem<BlockItem> ALLOY_FURNACE_ITEM = ITEMS.registerSimpleBlockItem("alloy_furnace", ALLOY_FURNACE);
public static final DeferredItem<Item> FLUID_INDICATOR_ITEM = RegisterItem("fluid_indicator_debug_item", properties -> new Item(properties
.fireResistant()
));
public static final DeferredItem<Item> XIPHOS_SWORD = RegisterItem("xiphos", public static final DeferredItem<Item> XIPHOS_SWORD = RegisterItem("xiphos",
properties -> new Item(properties properties -> new Item(properties
.tool(ModTiers.SWORD_TIER, .tool(ModTiers.SWORD_TIER,
@@ -0,0 +1,54 @@
package net.halbear.aotg.registries;
import net.halbear.aotg.AgeoftheGods;
import net.halbear.aotg.custom.blocks.AlloyFurnace.AlloyFurnaceGUI;
import net.halbear.aotg.utility.Networking.MenuStateUpdate;
import net.minecraft.client.Minecraft;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.inventory.MenuType;
import net.minecraft.world.inventory.Slot;
import net.neoforged.neoforge.client.network.ClientPacketDistributor;
import net.neoforged.neoforge.common.extensions.IMenuTypeExtension;
import net.neoforged.neoforge.network.PacketDistributor;
import net.neoforged.neoforge.registries.DeferredHolder;
import net.neoforged.neoforge.registries.DeferredRegister;
import java.util.Map;
public class ModMenus {
public static DeferredRegister<MenuType<?>> MENUS =
DeferredRegister.create(BuiltInRegistries.MENU, AgeoftheGods.MODID);
public static final DeferredHolder<MenuType<?>, MenuType<AlloyFurnaceGUI>> ALLOY_FURNACE_GUI =
MENUS.register("alloy_furnace_gui", () -> IMenuTypeExtension.create(AlloyFurnaceGUI::new));
public interface MenuAccessor {
Map<String, Object> getMenuState();
Map<Integer, Slot> getSlots();
default void sendMenuStateUpdate(Player player, int elementType, String name, Object elementState, boolean needClientUpdate) {
getMenuState().put(elementType + ":" + name, elementState);
if (player instanceof ServerPlayer serverPlayer) {
PacketDistributor.sendToPlayer(serverPlayer, new MenuStateUpdate(elementType, name, elementState));
} else if (player.level().isClientSide()) {
if (Minecraft.getInstance().screen instanceof ModScreens.ScreenAccessor accessor && needClientUpdate)
accessor.updateMenuState(elementType, name, elementState);
ClientPacketDistributor.sendToServer(new MenuStateUpdate(elementType, name, elementState));
}
}
default <T> T getMenuState(int elementType, String name, T defaultValue) {
try {
return (T) getMenuState().getOrDefault(elementType + ":" + name, defaultValue);
} catch (ClassCastException e) {
return defaultValue;
}
}
}
}
@@ -0,0 +1,21 @@
package net.halbear.aotg.registries;
import net.halbear.aotg.custom.GuiScreens.AlloyFurnaceGUIScreen;
import net.halbear.aotg.custom.blocks.AlloyFurnace.AlloyFurnaceGUI;
import net.neoforged.api.distmarker.Dist;
import net.neoforged.bus.api.SubscribeEvent;
import net.neoforged.fml.common.EventBusSubscriber;
import net.neoforged.neoforge.client.event.RegisterMenuScreensEvent;
@EventBusSubscriber(Dist.CLIENT)
public class ModScreens {
@SubscribeEvent
public static void clientLoad(RegisterMenuScreensEvent event) {
event.register(ModMenus.ALLOY_FURNACE_GUI.get(), AlloyFurnaceGUIScreen::new);
}
public interface ScreenAccessor {
void updateMenuState(int elementType, String name, Object elementState);
}
}
@@ -0,0 +1,75 @@
package net.halbear.aotg.utility.Networking;
import net.halbear.aotg.AgeoftheGods;
import net.halbear.aotg.registries.ModMenus;
import net.halbear.aotg.registries.ModScreens;
import net.minecraft.client.Minecraft;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.network.RegistryFriendlyByteBuf;
import net.minecraft.network.chat.Component;
import net.minecraft.network.codec.StreamCodec;
import net.minecraft.network.protocol.PacketFlow;
import net.minecraft.network.protocol.common.custom.CustomPacketPayload;
import net.minecraft.resources.Identifier;
import net.neoforged.bus.api.SubscribeEvent;
import net.neoforged.fml.common.EventBusSubscriber;
import net.neoforged.fml.event.lifecycle.FMLCommonSetupEvent;
import net.neoforged.neoforge.network.handling.IPayloadContext;
@EventBusSubscriber
public record MenuStateUpdate(int elementType, String name, Object elementState) implements CustomPacketPayload {
public static final Type<MenuStateUpdate> TYPE = new Type<>(Identifier.fromNamespaceAndPath(AgeoftheGods.MODID, "menustate_update"));
public static final StreamCodec<RegistryFriendlyByteBuf, MenuStateUpdate> STREAM_CODEC = StreamCodec.of(MenuStateUpdate::write, MenuStateUpdate::read);
public static void write(FriendlyByteBuf buffer, MenuStateUpdate message) {
buffer.writeInt(message.elementType);
buffer.writeUtf(message.name);
if (message.elementType == 0) {
buffer.writeUtf((String) message.elementState);
} else if (message.elementType == 1) {
buffer.writeBoolean((boolean) message.elementState);
} else if (message.elementType == 2 && message.elementState instanceof Number n) {
buffer.writeDouble(n.doubleValue());
}
}
public static MenuStateUpdate read(FriendlyByteBuf buffer) {
int elementType = buffer.readInt();
String name = buffer.readUtf();
Object elementState = null;
if (elementType == 0) {
elementState = buffer.readUtf();
} else if (elementType == 1) {
elementState = buffer.readBoolean();
} else if (elementType == 2) {
elementState = buffer.readDouble();
}
return new MenuStateUpdate(elementType, name, elementState);
}
@Override
public Type<MenuStateUpdate> type() {
return TYPE;
}
public static void handleMenuState(final MenuStateUpdate message, final IPayloadContext context) {
if (message.name.length() > 256 || message.elementState instanceof String string && string.length() > 8192)
return;
context.enqueueWork(() -> {
if (context.player().containerMenu instanceof ModMenus.MenuAccessor menu) {
menu.getMenuState().put(message.elementType + ":" + message.name, message.elementState);
if (context.flow() == PacketFlow.CLIENTBOUND && Minecraft.getInstance().screen instanceof ModScreens.ScreenAccessor accessor) {
accessor.updateMenuState(message.elementType, message.name, message.elementState);
}
}
}).exceptionally(e -> {
context.connection().disconnect(Component.literal(e.getMessage()));
return null;
});
}
@SubscribeEvent
public static void registerMessage(FMLCommonSetupEvent event) {
AgeoftheGods.addNetworkMessage(MenuStateUpdate.TYPE, MenuStateUpdate.STREAM_CODEC, MenuStateUpdate::handleMenuState);
}
}
@@ -0,0 +1,46 @@
package net.halbear.aotg.utility;
import net.halbear.aotg.AgeoftheGods;
import net.halbear.aotg.registries.ModItems;
import net.minecraft.core.BlockPos;
import net.minecraft.core.NonNullList;
import net.minecraft.core.component.DataComponents;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Items;
import net.minecraft.world.item.component.ItemContainerContents;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.entity.DecoratedPotBlockEntity;
import net.minecraft.world.level.material.Fluids;
import net.neoforged.bus.api.SubscribeEvent;
import net.neoforged.fml.common.EventBusSubscriber;
import net.neoforged.neoforge.event.level.BlockEvent;
@EventBusSubscriber(modid = AgeoftheGods.MODID)
public class ServerModEventHandler {
@SubscribeEvent
public static void OnAlloyPotDestroy(BlockEvent.BreakEvent event){
if (!(event.getLevel() instanceof Level level)) return;
if (level.isClientSide()) return;
BlockPos pos = event.getPos();
BlockEntity blockEntity = level.getBlockEntity(pos);
if (blockEntity instanceof DecoratedPotBlockEntity potEntity) {
ItemContainerContents contents = potEntity.getContainerBlockEntity().components().get(DataComponents.CONTAINER);
if (contents != null) {
boolean hasMarker = contents.getStackInSlot(0).is(ModItems.FLUID_INDICATOR_ITEM.asItem());
if (hasMarker) {
potEntity.getContainerBlockEntity().setRemoved();
potEntity.setChanged();
level.setBlock(pos, Fluids.WATER.defaultFluidState().createLegacyBlock(), 3);
event.setCanceled(true);
}
}
}
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB