Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Modification Table and Gui Implementation #2

Open
wants to merge 4 commits into
base: 1.17.x
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,18 +1,48 @@
package mininggadgets.blockentities;

import mininggadgets.init.MGBlockEntities;
import mininggadgets.items.MiningGadget;
import mininggadgets.items.upgrade.Upgrade;
import mininggadgets.items.upgrade.UpgradeTools;
import net.minecraft.block.BlockState;
import net.minecraft.block.entity.BlockEntity;
import net.minecraft.block.entity.BlockEntityType;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NbtCompound;
import net.minecraft.network.packet.s2c.play.BlockEntityUpdateS2CPacket;
import net.minecraft.util.math.BlockPos;
import reborncore.api.blockentity.InventoryProvider;
import reborncore.client.screen.BuiltScreenHandlerProvider;
import reborncore.client.screen.builder.BuiltScreenHandler;
import reborncore.client.screen.builder.ScreenHandlerBuilder;
import reborncore.common.blockentity.MachineBaseBlockEntity;
import reborncore.common.util.RebornInventory;

import java.util.ArrayList;
import java.util.List;

import static mininggadgets.init.MGContent.MODIFICATIONTABLE_ENTITY;
public class ModificationTableBlockEntity extends MachineBaseBlockEntity implements InventoryProvider, BuiltScreenHandlerProvider {
private final int inventorySize = 2;

public RebornInventory<ModificationTableBlockEntity> inventory = new RebornInventory<>(inventorySize, "ModificationTableBlockEntity", 64, this);
public List<Upgrade> upgradesCache = new ArrayList<>();

public enum Slots {
TOOL(0),
UPGRADE(1);

private final int id;

Slots(int number) {
id = number;
}

public int getId() {
return id;
}
}

public class ModificationTableBlockEntity extends BlockEntity {
public ModificationTableBlockEntity(BlockPos pos, BlockState state) {
super(MODIFICATIONTABLE_ENTITY, pos, state);
super(MGBlockEntities.MODIFICATION_TABLE, pos, state);
}

@Override
Expand Down Expand Up @@ -40,5 +70,45 @@ public NbtCompound writeNbt(NbtCompound nbt) {
return super.writeNbt(nbt);
}

@Override
public RebornInventory<ModificationTableBlockEntity> getInventory() {
return inventory;
}

@Override
public boolean canBeUpgraded() {
return false;
}

@Override
public boolean hasSlotConfig() {
return false;
}

@Override
public BuiltScreenHandler createScreenHandler(int syncID, PlayerEntity player) {
return new ScreenHandlerBuilder("modification_table")
.player(player.getInventory()).inventory().hotbar().addInventory()
.blockEntity(this)
.slot(Slots.TOOL.getId(), -16, 84, this::itemIsGadget)
.addInventory().create(this, syncID);
}

public boolean itemIsGadget(ItemStack itemStack) {
return itemStack.getItem() instanceof MiningGadget;
}

public void updateUpgradeCache(final int index) {
ItemStack stack = this.getStack(index);
if ((stack.isEmpty() && !upgradesCache.isEmpty()) || !(stack.getItem() instanceof MiningGadget)) {
upgradesCache.clear();
} else {
upgradesCache.clear();
upgradesCache = UpgradeTools.getUpgrades(stack);
}
}

public List<Upgrade> getUpgradesCache() {
return upgradesCache;
}
}
42 changes: 42 additions & 0 deletions src/main/java/mininggadgets/blocks/GenericMachineBlock.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package mininggadgets.blocks;

import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.block.entity.BlockEntity;
import net.minecraft.util.math.BlockPos;
import reborncore.api.blockentity.IMachineGuiHandler;
import reborncore.common.blocks.BlockMachineBase;

import java.util.function.BiFunction;

public class GenericMachineBlock extends BlockMachineBase {

private final IMachineGuiHandler gui;
BiFunction<BlockPos, BlockState, BlockEntity> blockEntityClass;

public GenericMachineBlock(IMachineGuiHandler gui, BiFunction<BlockPos, BlockState, BlockEntity> blockEntityClass) {
super();
this.blockEntityClass = blockEntityClass;
this.gui = gui;
}

public GenericMachineBlock(Block.Settings settings, IMachineGuiHandler gui, BiFunction<BlockPos, BlockState, BlockEntity> blockEntityClass) {
super(settings);
this.blockEntityClass = blockEntityClass;
this.gui = gui;
}

@Override
public BlockEntity createBlockEntity(BlockPos pos, BlockState state) {
if (blockEntityClass == null) {
return null;
}
return blockEntityClass.apply(pos, state);
}


@Override
public IMachineGuiHandler getGui() {
return gui;
}
}
97 changes: 80 additions & 17 deletions src/main/java/mininggadgets/blocks/ModificationTable.java
Original file line number Diff line number Diff line change
@@ -1,38 +1,101 @@
package mininggadgets.blocks;

import mininggadgets.blockentities.ModificationTableBlockEntity;
import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings;
import net.minecraft.block.Block;
import net.minecraft.block.BlockEntityProvider;
import net.minecraft.block.BlockState;
import net.minecraft.block.Material;
import net.minecraft.block.*;
import net.minecraft.block.entity.BlockEntity;
import net.minecraft.block.entity.BlockEntityTicker;
import net.minecraft.block.entity.BlockEntityType;
import net.minecraft.item.ItemPlacementContext;
import net.minecraft.state.StateManager;
import net.minecraft.state.property.DirectionProperty;
import net.minecraft.util.function.BooleanBiFunction;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.minecraft.util.shape.VoxelShape;
import net.minecraft.util.shape.VoxelShapes;
import net.minecraft.world.BlockView;
import net.minecraft.world.World;
import net.minecraft.world.event.listener.GameEventListener;
import org.jetbrains.annotations.Nullable;

import java.util.stream.Stream;

public class ModificationTable extends Block implements BlockEntityProvider {
public static DirectionProperty FACING = HorizontalFacingBlock.FACING;

private static final VoxelShape SHAPE_N = Stream.of(
Block.createCuboidShape(2, 11, 12, 14, 16, 16),
Block.createCuboidShape(0,0,0,16,10,16),
Block.createCuboidShape(1,10,1,15,11,9),
Block.createCuboidShape(0,10,11,16,11,16),
Block.createCuboidShape(0,11,0,16,12,10),
Block.createCuboidShape(13,12,2,14,13,8)
).reduce((v1, v2) -> VoxelShapes.combine(v1, v2, BooleanBiFunction.OR)).get();

private static final VoxelShape SHAPE_E = Stream.of(
Block.createCuboidShape(0, 11, 2, 4, 16, 14),
Block.createCuboidShape(0, 0, 0, 16, 10, 16),
Block.createCuboidShape(7, 10, 1, 15, 11, 15),
Block.createCuboidShape(0, 10, 0, 5, 11, 16),
Block.createCuboidShape(6, 11, 0, 16, 12, 16),
Block.createCuboidShape(8, 12, 13, 14, 13, 14)
).reduce((v1, v2) -> VoxelShapes.combine(v1, v2, BooleanBiFunction.OR)).get();

private static final VoxelShape SHAPE_S = Stream.of(
Block.createCuboidShape(2, 11, 0, 14, 16, 4),
Block.createCuboidShape(0, 0, 0, 16, 10, 16),
Block.createCuboidShape(1, 10, 7, 15, 11, 15),
Block.createCuboidShape(0, 10, 0, 16, 11, 5),
Block.createCuboidShape(0, 11, 6, 16, 12, 16),
Block.createCuboidShape(2, 12, 8, 3, 13, 14)
).reduce((v1, v2) -> VoxelShapes.combine(v1, v2, BooleanBiFunction.OR)).get();

private static final VoxelShape SHAPE_W = Stream.of(
Block.createCuboidShape(12, 11, 2, 16, 16, 14),
Block.createCuboidShape(0, 0, 0, 16, 10, 16),
Block.createCuboidShape(1, 10, 1, 9, 11, 15),
Block.createCuboidShape(11, 10, 0, 16, 11, 16),
Block.createCuboidShape(0, 11, 0, 10, 12, 16),
Block.createCuboidShape(2, 12, 2, 8, 13, 3)
).reduce((v1, v2) -> VoxelShapes.combine(v1, v2, BooleanBiFunction.OR)).get();

public ModificationTable() {
super(FabricBlockSettings.of(Material.METAL).strength(2.0f));

this.setDefaultState(this.getDefaultState().with(FACING, Direction.NORTH));
}

@Nullable
@Override
public BlockEntity createBlockEntity(BlockPos pos, BlockState state) {
return null;
public VoxelShape getOutlineShape(BlockState state, BlockView world, BlockPos pos, ShapeContext context) {
return switch (state.get(FACING)) {
case NORTH -> SHAPE_N;
case EAST -> SHAPE_E;
case SOUTH -> SHAPE_S;
case WEST -> SHAPE_W;
default -> throw new IllegalStateException("Invalid State");
};
}

@Nullable
@Override
public <T extends BlockEntity> BlockEntityTicker<T> getTicker(World world, BlockState state, BlockEntityType<T> type) {
return BlockEntityProvider.super.getTicker(world, state, type);
public BlockState getPlacementState(ItemPlacementContext context) {
return this.getDefaultState().with(FACING, context.getPlayerLookDirection().getOpposite());
}

@Override
protected void appendProperties(StateManager.Builder<Block, BlockState> builder) {
builder.add(FACING);
}

@Override
public BlockEntity createBlockEntity(BlockPos pos, BlockState state) {
return new ModificationTableBlockEntity(pos, state);
}

@Nullable
@Override
public <T extends BlockEntity> GameEventListener getGameEventListener(World world, T blockEntity) {
return BlockEntityProvider.super.getGameEventListener(world, blockEntity);
public void onStateReplaced(BlockState state, World world, BlockPos pos, BlockState newState, boolean moved) {
if (newState.getBlock() != this) {
BlockEntity blockEntity = world.getBlockEntity(pos);
if (blockEntity != null) {
// handler stuff.
}
super.onStateReplaced(state, world, pos, newState, moved);
}
}
}
126 changes: 126 additions & 0 deletions src/main/java/mininggadgets/client/GuiType.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
package mininggadgets.client;

import mininggadgets.MiningGadgets;
import mininggadgets.blockentities.ModificationTableBlockEntity;
import mininggadgets.client.gui.GuiModificationTable;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.fabricmc.fabric.api.client.screenhandler.v1.ScreenRegistry;
import net.fabricmc.fabric.api.screenhandler.v1.ExtendedScreenHandlerFactory;
import net.fabricmc.fabric.api.screenhandler.v1.ScreenHandlerRegistry;
import net.minecraft.block.entity.BlockEntity;
import net.minecraft.client.gui.screen.ingame.HandledScreen;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.entity.player.PlayerInventory;
import net.minecraft.network.PacketByteBuf;
import net.minecraft.screen.ScreenHandler;
import net.minecraft.screen.ScreenHandlerType;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.text.LiteralText;
import net.minecraft.text.Text;
import net.minecraft.util.Identifier;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import org.jetbrains.annotations.Nullable;
import reborncore.RebornCore;
import reborncore.api.blockentity.IMachineGuiHandler;
import reborncore.client.screen.BuiltScreenHandlerProvider;
import reborncore.client.screen.builder.BuiltScreenHandler;

import java.util.HashMap;
import java.util.Map;
import java.util.function.Supplier;

public class GuiType<T extends BlockEntity> implements IMachineGuiHandler {
private static final Map<Identifier, GuiType<?>> TYPES = new HashMap<>();

public static final GuiType<ModificationTableBlockEntity> MODIFICATION_TABLE = register("modificationtable", () -> () -> GuiModificationTable::new);

private static <T extends BlockEntity> GuiType<T> register(String id, Supplier<Supplier<GuiFactory<T>>> factorySupplierMeme) {
return register(new Identifier(MiningGadgets.MOD_ID, id), factorySupplierMeme);
}

public static <T extends BlockEntity> GuiType<T> register(Identifier identifier, Supplier<Supplier<GuiFactory<T>>> factorySupplierMeme) {
if (TYPES.containsKey(identifier)) {
throw new RuntimeException("Duplicate gui type found");
}
GuiType<T> type = new GuiType<>(identifier, factorySupplierMeme);
TYPES.put(identifier, type);
return type;
}

private final Identifier identifier;
private final Supplier<Supplier<GuiFactory<T>>> guiFactory;
private final ScreenHandlerType<BuiltScreenHandler> screenHandlerType;

@Environment(EnvType.CLIENT)
private GuiType(Identifier identifier, Supplier<Supplier<GuiFactory<T>>> factorySupplierMeme) {
this.identifier = identifier;
this.guiFactory = factorySupplierMeme;
this.screenHandlerType = ScreenHandlerRegistry.registerExtended(identifier, getScreenHandlerFactory());
RebornCore.clientOnly(() -> () -> ScreenRegistry.register(screenHandlerType, getGuiFactory()));
}

private ScreenHandlerRegistry.ExtendedClientHandlerFactory<BuiltScreenHandler> getScreenHandlerFactory() {
return (syncId, playerInventory, packetByteBuf) -> {
final BlockEntity blockEntity = playerInventory.player.world.getBlockEntity(packetByteBuf.readBlockPos());
assert blockEntity != null;
BuiltScreenHandler screenHandler = ((BuiltScreenHandlerProvider) blockEntity).createScreenHandler(syncId, playerInventory.player);

//Set the screen handler type, not ideal but works lol
screenHandler.setType(screenHandlerType);

return screenHandler;
};
}

@Environment(EnvType.CLIENT)
private GuiFactory<T> getGuiFactory() {
return guiFactory.get().get();
}

@Override
public void open(PlayerEntity player, BlockPos pos, World world) {
if (!world.isClient) {
//This is awful
player.openHandledScreen(new ExtendedScreenHandlerFactory() {
@Override
public void writeScreenOpeningData(ServerPlayerEntity serverPlayerEntity, PacketByteBuf packetByteBuf) {
packetByteBuf.writeBlockPos(pos);
}

@Override
public Text getDisplayName() {
return new LiteralText("What is this for?");
}

@Nullable
@Override
public ScreenHandler createMenu(int syncId, PlayerInventory inv, PlayerEntity player) {
final BlockEntity blockEntity = player.world.getBlockEntity(pos);
BuiltScreenHandler screenHandler = ((BuiltScreenHandlerProvider) blockEntity).createScreenHandler(syncId, player);
screenHandler.setType(screenHandlerType);
return screenHandler;
}
});
}
}

public Identifier getIdentifier() {
return identifier;
}

@Environment(EnvType.CLIENT)
public interface GuiFactory<T extends BlockEntity> extends ScreenRegistry.Factory<BuiltScreenHandler, HandledScreen<BuiltScreenHandler>> {
HandledScreen<?> create(int syncId, PlayerEntity playerEntity, T blockEntity);

@Override
default HandledScreen create(BuiltScreenHandler builtScreenHandler, PlayerInventory playerInventory, Text text) {
PlayerEntity playerEntity = playerInventory.player;
//noinspection unchecked
T blockEntity = (T) builtScreenHandler.getBlockEntity();
return create(builtScreenHandler.syncId, playerEntity, blockEntity);
}
}

}
Loading