forked from BRNSystems/Server_storage
Fix naming and add gamerules
This commit is contained in:
109
src/main/java/systems/brn/serverstorage/ServerStorage.java
Normal file
109
src/main/java/systems/brn/serverstorage/ServerStorage.java
Normal file
@@ -0,0 +1,109 @@
|
||||
package systems.brn.serverstorage;
|
||||
|
||||
import eu.pb4.polymer.resourcepack.api.PolymerResourcePackUtils;
|
||||
import net.fabricmc.api.ModInitializer;
|
||||
import net.fabricmc.fabric.api.gamerule.v1.GameRuleFactory;
|
||||
import net.fabricmc.fabric.api.gamerule.v1.GameRuleRegistry;
|
||||
import net.minecraft.block.entity.BlockEntityType;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.ItemGroups;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.world.GameRules;
|
||||
import systems.brn.serverstorage.blockentities.HardDriveContainerBlockEntity;
|
||||
import systems.brn.serverstorage.blockentities.InventoryInterfaceBlockEntity;
|
||||
import systems.brn.serverstorage.blockentities.StorageInterfaceBlockEntity;
|
||||
import systems.brn.serverstorage.blocks.BusConnectorBlock;
|
||||
import systems.brn.serverstorage.blocks.HardDriveContainerBlock;
|
||||
import systems.brn.serverstorage.blocks.InventoryInterfaceBlock;
|
||||
import systems.brn.serverstorage.blocks.StorageInterfaceBlock;
|
||||
import systems.brn.serverstorage.items.HardDriveItem;
|
||||
import systems.brn.serverstorage.items.SimpleBlockItem;
|
||||
import systems.brn.serverstorage.items.SimpleItem;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
public class ServerStorage implements ModInitializer {
|
||||
public static final List<String> moduleList = Arrays.asList("bus", "configuration", "container", "display", "drive", "filtering", "inventory", "pagination", "pcb", "transport");
|
||||
public static final List<String> tiers = Arrays.asList("iron", "golden", "diamond", "netherite");
|
||||
|
||||
public static final String MOD_ID = "serverstorage";
|
||||
|
||||
public static final String BUS_CONNECTOR_MODEL_ID = "bus_connector";
|
||||
public static BusConnectorBlock BUS_CONNECTOR_BLOCK;
|
||||
|
||||
public static final String HARD_DRIVE_CONTAINER_BLOCK_MODEL_ID = "drive_container";
|
||||
public static BlockEntityType<HardDriveContainerBlockEntity> HARD_DRIVE_CONTAINER_BLOCK_ENTITY;
|
||||
public static HardDriveContainerBlock HARD_DRIVE_CONTAINER_BLOCK;
|
||||
|
||||
public static final String STORAGE_MODEL_ID = "storage";
|
||||
public static StorageInterfaceBlock STORAGE_INTERFACE_BLOCK;
|
||||
public static BlockEntityType<StorageInterfaceBlockEntity> STORAGE_INTERFACE_BLOCK_ENTITY;
|
||||
|
||||
public static final String INVENTORY_INTERFACE_BLOCK_MODEL_ID = "inventory_interface";
|
||||
public static InventoryInterfaceBlock INVENTORY_INTERFACE_BLOCK;
|
||||
public static BlockEntityType<InventoryInterfaceBlockEntity> INVENTORY_INTERFACE_BLOCK_ENTITY;
|
||||
|
||||
public static final GameRules.Key<GameRules.BooleanRule> ServerStorage_Crafting_Enable =
|
||||
GameRuleRegistry.register("serverstoragecraftingmodule", GameRules.Category.MISC, GameRuleFactory.createBooleanRule(true));
|
||||
|
||||
public static final GameRules.Key<GameRules.BooleanRule> ServerStorage_Terminal_Enable =
|
||||
GameRuleRegistry.register("serverstorageterminalmodule", GameRules.Category.MISC, GameRuleFactory.createBooleanRule(true));
|
||||
|
||||
public static final GameRules.Key<GameRules.BooleanRule> ServerStorage_Interface_Enable =
|
||||
GameRuleRegistry.register("serverstorageinterfacemodule", GameRules.Category.MISC, GameRuleFactory.createBooleanRule(true));
|
||||
|
||||
|
||||
public static Item DRIVE_CASING;
|
||||
public static Item CPU;
|
||||
public static Item CPU_SUBSTRATE;
|
||||
public static Item DRIVE_CONTROLLER;
|
||||
public static Item PCB;
|
||||
public static Item PCB_SUBSTRATE;
|
||||
public static List<Item> MODULES;
|
||||
public static List<Item> PLATTERS;
|
||||
public static List<Item> DRIVES;
|
||||
public static List<Item> HEADS;
|
||||
|
||||
|
||||
public static Identifier id(String path) {
|
||||
return Identifier.of(MOD_ID, path);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onInitialize()
|
||||
{
|
||||
StorageInterfaceBlock.register();
|
||||
SimpleBlockItem.register(STORAGE_INTERFACE_BLOCK);
|
||||
|
||||
HardDriveContainerBlock.register();
|
||||
SimpleBlockItem.register(HARD_DRIVE_CONTAINER_BLOCK);
|
||||
|
||||
BusConnectorBlock.register();
|
||||
SimpleBlockItem.register(BUS_CONNECTOR_BLOCK);
|
||||
|
||||
InventoryInterfaceBlock.register();
|
||||
SimpleBlockItem.register(INVENTORY_INTERFACE_BLOCK);
|
||||
|
||||
PCB = SimpleItem.register("pcb", ItemGroups.INGREDIENTS);
|
||||
PCB_SUBSTRATE = SimpleItem.register("pcb_substrate", ItemGroups.INGREDIENTS);
|
||||
CPU = SimpleItem.register("cpu", ItemGroups.INGREDIENTS);
|
||||
CPU_SUBSTRATE = SimpleItem.register("cpu_substrate", ItemGroups.INGREDIENTS);
|
||||
DRIVE_CONTROLLER = SimpleItem.register("drive_controller", ItemGroups.INGREDIENTS);
|
||||
DRIVE_CASING = SimpleItem.register("drive_casing", ItemGroups.INGREDIENTS);
|
||||
|
||||
MODULES = SimpleItem.register("module", moduleList, false, ItemGroups.INGREDIENTS);
|
||||
|
||||
HEADS = SimpleItem.register("head", tiers, ItemGroups.INGREDIENTS);
|
||||
PLATTERS = SimpleItem.register("platter", tiers, ItemGroups.INGREDIENTS);
|
||||
|
||||
DRIVES = HardDriveItem.register(tiers);
|
||||
|
||||
|
||||
|
||||
PolymerResourcePackUtils.addModAssets(MOD_ID);
|
||||
PolymerResourcePackUtils.markAsRequired();
|
||||
|
||||
|
||||
}
|
||||
}
|
@@ -0,0 +1,120 @@
|
||||
package systems.brn.serverstorage.blockentities;
|
||||
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.block.entity.LootableContainerBlockEntity;
|
||||
import net.minecraft.entity.player.PlayerInventory;
|
||||
import net.minecraft.inventory.Inventories;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.nbt.NbtCompound;
|
||||
import net.minecraft.registry.RegistryWrapper;
|
||||
import net.minecraft.screen.ScreenHandler;
|
||||
import net.minecraft.text.Text;
|
||||
import net.minecraft.util.collection.DefaultedList;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import systems.brn.serverstorage.items.HardDrive;
|
||||
import systems.brn.serverstorage.lib.StorageNetwork;
|
||||
import systems.brn.serverstorage.screenhandlers.DriveContainerScreenHandler;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import static systems.brn.serverstorage.ServerStorage.DRIVES;
|
||||
import static systems.brn.serverstorage.ServerStorage.HARD_DRIVE_CONTAINER_BLOCK_ENTITY;
|
||||
|
||||
public class HardDriveContainerBlockEntity extends LootableContainerBlockEntity {
|
||||
public DefaultedList<ItemStack> inventory;
|
||||
public ArrayList<HardDrive> drives = new ArrayList<>();
|
||||
public static final int INVENTORY_SIZE = 5;
|
||||
|
||||
private int totalSlots;
|
||||
private int usedSlots;
|
||||
private int availableSlots;
|
||||
public StorageNetwork network;
|
||||
|
||||
public HardDriveContainerBlockEntity(BlockPos pos, BlockState state) {
|
||||
super(HARD_DRIVE_CONTAINER_BLOCK_ENTITY, pos, state);
|
||||
this.inventory = DefaultedList.ofSize(INVENTORY_SIZE, ItemStack.EMPTY);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Text getContainerName() {
|
||||
return Text.translatable("block.serverstorage.drive_container");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected DefaultedList<ItemStack> getHeldStacks() {
|
||||
return inventory;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setHeldStacks(DefaultedList<ItemStack> inventory) {
|
||||
this.inventory = inventory;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ScreenHandler createScreenHandler(int syncId, PlayerInventory playerInventory) {
|
||||
return new DriveContainerScreenHandler(syncId, playerInventory, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return INVENTORY_SIZE;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void readNbt(NbtCompound nbt, RegistryWrapper.WrapperLookup registryLookup) {
|
||||
super.readNbt(nbt, registryLookup);
|
||||
this.inventory = DefaultedList.ofSize(this.size(), ItemStack.EMPTY);
|
||||
if (!this.readLootTable(nbt)) {
|
||||
Inventories.readNbt(nbt, this.inventory, registryLookup);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void writeNbt(NbtCompound nbt, RegistryWrapper.WrapperLookup registryLookup) {
|
||||
super.writeNbt(nbt, registryLookup);
|
||||
if (!this.writeLootTable(nbt)) {
|
||||
Inventories.writeNbt(nbt, this.inventory, registryLookup);
|
||||
}
|
||||
}
|
||||
|
||||
public void commitDrives(){
|
||||
for (int i = 0; i < this.inventory.size(); i++) {
|
||||
for (HardDrive drive: this.drives) {
|
||||
if(drive.getContainerIndex() == i){
|
||||
this.inventory.set(i, drive.getCommitedStack());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void indexDrives() {
|
||||
drives = new ArrayList<>();
|
||||
totalSlots = 0;
|
||||
availableSlots = 0;
|
||||
usedSlots = 0;
|
||||
for (int i = 0; i < this.inventory.size(); i++) {
|
||||
ItemStack stack = this.inventory.get(i);
|
||||
if (!stack.isEmpty() && DRIVES.contains(stack.getItem())) {
|
||||
HardDrive drive = new HardDrive(stack, this, i);
|
||||
totalSlots += drive.getMaxItems();
|
||||
availableSlots += drive.getAvailableItems();
|
||||
usedSlots += drive.getUsedItems();
|
||||
drive.loadComponents();
|
||||
drives.add(drive);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public int getTotalSlots() {
|
||||
return totalSlots;
|
||||
}
|
||||
|
||||
public int getUsedSlots() {
|
||||
return usedSlots;
|
||||
}
|
||||
|
||||
public int getAvailableSlots() {
|
||||
return availableSlots;
|
||||
}
|
||||
}
|
@@ -0,0 +1,178 @@
|
||||
package systems.brn.serverstorage.blockentities;
|
||||
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.block.entity.BlockEntity;
|
||||
import net.minecraft.inventory.Inventory;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.nbt.NbtCompound;
|
||||
import net.minecraft.registry.RegistryWrapper;
|
||||
import net.minecraft.state.property.EnumProperty;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Direction;
|
||||
import net.minecraft.world.World;
|
||||
import systems.brn.serverstorage.lib.ConnectionType;
|
||||
import systems.brn.serverstorage.lib.StorageNetwork;
|
||||
import systems.brn.serverstorage.screens.SettingsScreen;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import static systems.brn.serverstorage.ServerStorage.INVENTORY_INTERFACE_BLOCK_ENTITY;
|
||||
import static systems.brn.serverstorage.ServerStorage.ServerStorage_Interface_Enable;
|
||||
import static systems.brn.serverstorage.blocks.ConnectedBlock.getPropertyForDirection;
|
||||
import static systems.brn.serverstorage.lib.StorageOperations.*;
|
||||
|
||||
public class InventoryInterfaceBlockEntity extends BlockEntity {
|
||||
|
||||
public StorageNetwork network;
|
||||
|
||||
public final ArrayList<SettingsScreen> openSettingsScreens = new ArrayList<>();
|
||||
|
||||
public boolean isOutput = false;
|
||||
|
||||
public String query = "";
|
||||
|
||||
public int tickCounter = 0;
|
||||
|
||||
public Direction direction = Direction.NORTH;
|
||||
|
||||
public InventoryInterfaceBlockEntity(BlockPos pos, BlockState state) {
|
||||
super(INVENTORY_INTERFACE_BLOCK_ENTITY, pos, state);
|
||||
}
|
||||
|
||||
public void reindexDrives() {
|
||||
if (this.network != null) {
|
||||
this.network.searchString = query;
|
||||
this.network.reindexNetwork();
|
||||
} else {
|
||||
this.network = new StorageNetwork(world, this.pos, false, query);
|
||||
}
|
||||
}
|
||||
|
||||
public void updateDisplays() {
|
||||
for (SettingsScreen screen : openSettingsScreens) {
|
||||
screen.updateDisplay();
|
||||
}
|
||||
}
|
||||
|
||||
public void nextDirection() {
|
||||
int newId = (direction.getId() + 1) % 6;
|
||||
direction = Direction.byId(newId);
|
||||
}
|
||||
|
||||
// Serialize the BlockEntity
|
||||
@Override
|
||||
public void writeNbt(NbtCompound nbt, RegistryWrapper.WrapperLookup wrapperLookup) {
|
||||
// Save the current value of the number to the nbt
|
||||
nbt.putBoolean("isOutput", isOutput);
|
||||
nbt.putInt("direction", direction.getId());
|
||||
nbt.putInt("tickCounter", tickCounter);
|
||||
nbt.putString("query", query);
|
||||
super.writeNbt(nbt, wrapperLookup);
|
||||
}
|
||||
|
||||
// Deserialize the BlockEntity
|
||||
@Override
|
||||
public void readNbt(NbtCompound nbt, RegistryWrapper.WrapperLookup wrapperLookup) {
|
||||
super.readNbt(nbt, wrapperLookup);
|
||||
isOutput = nbt.getBoolean("isOutput");
|
||||
direction = Direction.byId(nbt.getInt("direction"));
|
||||
tickCounter = nbt.getInt("tickCounter");
|
||||
query = nbt.getString("query");
|
||||
}
|
||||
|
||||
private static int processIncomingInternal(ItemStack stack, int count, InventoryInterfaceBlockEntity blockEntity, Inventory targetedBlockEntityInventory) {
|
||||
int maxFit = howMuchFits(stack, targetedBlockEntityInventory);
|
||||
int finalCount = Math.min(count, maxFit);
|
||||
ItemStack insertedStack = stack.copy();
|
||||
insertedStack.setCount(finalCount);
|
||||
blockEntity.network.removeItemStack(insertedStack);
|
||||
blockEntity.network.updateDisplays();
|
||||
int remainingToInsert = finalCount;
|
||||
for (int i = 0; i < Math.ceilDivExact(finalCount, stack.getMaxCount()); i++) {
|
||||
ItemStack cappedStack = insertedStack.copy();
|
||||
cappedStack.setCount(Math.min(insertedStack.getMaxCount(), remainingToInsert));
|
||||
|
||||
ItemStack remaining = insertStackIntoInventory(targetedBlockEntityInventory, cappedStack.copy());
|
||||
if (!remaining.isEmpty()) {
|
||||
ItemStack reverseStack = stack.copy();
|
||||
reverseStack.setCount(remaining.getCount() + remainingToInsert);
|
||||
blockEntity.network.putItemStackRemainder(reverseStack);
|
||||
break;
|
||||
}
|
||||
remainingToInsert -= cappedStack.getCount();
|
||||
}
|
||||
return count - (finalCount - remainingToInsert);
|
||||
}
|
||||
|
||||
public int processIncoming(ItemStack stack, int count) {
|
||||
if (world != null && world.getGameRules().getBoolean(ServerStorage_Interface_Enable) && isOutput && filterItem(stack.getItem(), query)) {
|
||||
BlockPos targetedPos = pos.offset(direction);
|
||||
BlockEntity targetedBlockEntity = world.getBlockEntity(targetedPos);
|
||||
EnumProperty<ConnectionType> connectionType = getPropertyForDirection(direction);
|
||||
BlockState thisState = world.getBlockState(pos);
|
||||
if (targetedBlockEntity instanceof Inventory targetedBlockEntityInventory &&
|
||||
thisState.contains(connectionType) &&
|
||||
thisState.get(connectionType) == ConnectionType.INVENTORY) {
|
||||
reindexDrives();
|
||||
|
||||
return processIncomingInternal(stack, count, this, targetedBlockEntityInventory);
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
public static <T extends BlockEntity> void tick(World world, BlockPos blockPos, BlockState ignoredState, T ignoredt) {
|
||||
if (!world.getGameRules().getBoolean(ServerStorage_Interface_Enable)){
|
||||
return;
|
||||
}
|
||||
InventoryInterfaceBlockEntity blockEntity = (InventoryInterfaceBlockEntity) world.getBlockEntity(blockPos);
|
||||
if (blockEntity != null) {
|
||||
if (blockEntity.tickCounter == 0) {
|
||||
BlockPos targetedPos = blockPos.offset(blockEntity.direction);
|
||||
BlockEntity targetedBlockEntity = world.getBlockEntity(targetedPos);
|
||||
BlockState thisState = world.getBlockState(blockPos);
|
||||
EnumProperty<ConnectionType> connectionType = getPropertyForDirection(blockEntity.direction);
|
||||
if (targetedBlockEntity instanceof Inventory targetedBlockEntityInventory &&
|
||||
thisState.contains(connectionType) &&
|
||||
thisState.get(connectionType) == ConnectionType.INVENTORY) {
|
||||
blockEntity.reindexDrives();
|
||||
|
||||
if (blockEntity.isOutput) {
|
||||
for (Map.Entry<ItemStack, Integer> entry : blockEntity.network.filteredItemStackMap.entrySet()) {
|
||||
int leftOver = processIncomingInternal(entry.getKey(), entry.getValue(), blockEntity, targetedBlockEntityInventory);
|
||||
if (leftOver > 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Map<ItemStack, Integer> targetedBlockInventoryMap = new HashMap<>();
|
||||
addInventoryToMap(targetedBlockEntityInventory, targetedBlockInventoryMap);
|
||||
targetedBlockInventoryMap = sortAndFilterMap(targetedBlockInventoryMap, false, blockEntity.query);
|
||||
for (Map.Entry<ItemStack, Integer> entry : targetedBlockInventoryMap.entrySet()) {
|
||||
ItemStack stack = entry.getKey();
|
||||
int count = entry.getValue();
|
||||
ItemStack insertingStack = stack.copy();
|
||||
insertingStack.setCount(count);
|
||||
if (count > 0) {
|
||||
int canPutInside = count - blockEntity.network.putItemStackRemainder(insertingStack.copy());
|
||||
blockEntity.network.updateDisplays();
|
||||
if (canPutInside > 0) {
|
||||
removeFromInventory(targetedBlockEntityInventory, insertingStack.copy(), canPutInside);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
blockEntity.tickCounter = (blockEntity.tickCounter + 1) % 160;
|
||||
}
|
||||
}
|
||||
|
||||
public void doSearch(String query) {
|
||||
this.query = query;
|
||||
reindexDrives();
|
||||
updateDisplays();
|
||||
}
|
||||
}
|
@@ -0,0 +1,74 @@
|
||||
package systems.brn.serverstorage.blockentities;
|
||||
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.block.entity.BlockEntity;
|
||||
import net.minecraft.nbt.NbtCompound;
|
||||
import net.minecraft.registry.RegistryWrapper;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import systems.brn.serverstorage.lib.StorageNetwork;
|
||||
import systems.brn.serverstorage.screens.CraftingScreen;
|
||||
import systems.brn.serverstorage.screens.StorageScreen;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import static systems.brn.serverstorage.ServerStorage.STORAGE_INTERFACE_BLOCK_ENTITY;
|
||||
|
||||
public class StorageInterfaceBlockEntity extends BlockEntity {
|
||||
|
||||
public Boolean sortAlphabetically = false;
|
||||
public String searchString = "";
|
||||
public int page = 0;
|
||||
public StorageNetwork network;
|
||||
|
||||
public final ArrayList<StorageScreen> openStorageScreens = new ArrayList<>();
|
||||
public final ArrayList<CraftingScreen> openCraftingScreens = new ArrayList<>();
|
||||
|
||||
public StorageInterfaceBlockEntity(BlockPos pos, BlockState state) {
|
||||
super(STORAGE_INTERFACE_BLOCK_ENTITY, pos, state);
|
||||
}
|
||||
|
||||
public void reindexDrives() {
|
||||
if (this.network != null) {
|
||||
this.network.searchString = searchString;
|
||||
this.network.sortAlphabetically = sortAlphabetically;
|
||||
this.network.reindexNetwork();
|
||||
} else {
|
||||
this.network = new StorageNetwork(world, this.pos, sortAlphabetically, searchString);
|
||||
}
|
||||
}
|
||||
|
||||
public void refreshTerminals() {
|
||||
reindexDrives();
|
||||
this.network.updateDisplays();
|
||||
}
|
||||
|
||||
public void updateDisplays() {
|
||||
for (StorageScreen screen : openStorageScreens) {
|
||||
screen.updateDisplay();
|
||||
}
|
||||
for (CraftingScreen screen : openCraftingScreens) {
|
||||
screen.updateDisplay();
|
||||
}
|
||||
}
|
||||
|
||||
// Serialize the BlockEntity
|
||||
@Override
|
||||
public void writeNbt(NbtCompound nbt, RegistryWrapper.WrapperLookup wrapperLookup) {
|
||||
// Save the current value of the number to the nbt
|
||||
nbt.putInt("page", page);
|
||||
nbt.putBoolean("sortAlphabetically", sortAlphabetically);
|
||||
nbt.putString("searchString", searchString);
|
||||
|
||||
super.writeNbt(nbt, wrapperLookup);
|
||||
}
|
||||
|
||||
// Deserialize the BlockEntity
|
||||
@Override
|
||||
public void readNbt(NbtCompound nbt, RegistryWrapper.WrapperLookup wrapperLookup) {
|
||||
super.readNbt(nbt, wrapperLookup);
|
||||
|
||||
page = nbt.getInt("page");
|
||||
sortAlphabetically = nbt.getBoolean("sortAlphabetically");
|
||||
searchString = nbt.getString("searchString");
|
||||
}
|
||||
}
|
@@ -0,0 +1,40 @@
|
||||
package systems.brn.serverstorage.blocks;
|
||||
|
||||
import eu.pb4.polymer.blocks.api.BlockModelType;
|
||||
import eu.pb4.polymer.blocks.api.PolymerBlockModel;
|
||||
import eu.pb4.polymer.blocks.api.PolymerBlockResourceUtils;
|
||||
import eu.pb4.polymer.blocks.api.PolymerTexturedBlock;
|
||||
import net.minecraft.block.*;
|
||||
import net.minecraft.registry.Registries;
|
||||
import net.minecraft.registry.Registry;
|
||||
import net.minecraft.util.Identifier;
|
||||
|
||||
import static systems.brn.serverstorage.ServerStorage.*;
|
||||
|
||||
public class BusConnectorBlock extends ConnectedBlock implements PolymerTexturedBlock {
|
||||
final Identifier identifier;
|
||||
private final BlockState polymerBlockState;
|
||||
|
||||
public BusConnectorBlock(Settings settings, Identifier identifier) {
|
||||
super(settings, Blocks.NOTE_BLOCK);
|
||||
this.identifier = identifier;
|
||||
this.polymerBlockState = PolymerBlockResourceUtils.requestBlock(
|
||||
BlockModelType.FULL_BLOCK,
|
||||
PolymerBlockModel.of(
|
||||
identifier.withPath("block/" + identifier.getPath())
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockState getPolymerBlockState(BlockState state) {
|
||||
return this.polymerBlockState;
|
||||
}
|
||||
|
||||
public static void register() {
|
||||
var modId = id(BUS_CONNECTOR_MODEL_ID);
|
||||
BUS_CONNECTOR_BLOCK = Registry.register(Registries.BLOCK, modId,
|
||||
new BusConnectorBlock(AbstractBlock.Settings.copy(Blocks.WHITE_WOOL), modId));
|
||||
BUS_CONNECTOR_BLOCK.setDefaultState();
|
||||
}
|
||||
}
|
@@ -0,0 +1,90 @@
|
||||
package systems.brn.serverstorage.blocks;
|
||||
|
||||
import eu.pb4.polymer.core.api.block.SimplePolymerBlock;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.block.entity.BlockEntity;
|
||||
import net.minecraft.entity.LivingEntity;
|
||||
import net.minecraft.inventory.Inventory;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.state.StateManager;
|
||||
import net.minecraft.state.property.EnumProperty;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Direction;
|
||||
import net.minecraft.world.World;
|
||||
import systems.brn.serverstorage.lib.ConnectionType;
|
||||
|
||||
public class ConnectedBlock extends SimplePolymerBlock {
|
||||
|
||||
public static final EnumProperty<ConnectionType> NORTH = EnumProperty.of("north", ConnectionType.class);
|
||||
public static final EnumProperty<ConnectionType> SOUTH = EnumProperty.of("south", ConnectionType.class);
|
||||
public static final EnumProperty<ConnectionType> WEST = EnumProperty.of("west", ConnectionType.class);
|
||||
public static final EnumProperty<ConnectionType> EAST = EnumProperty.of("east", ConnectionType.class);
|
||||
public static final EnumProperty<ConnectionType> UP = EnumProperty.of("up", ConnectionType.class);
|
||||
public static final EnumProperty<ConnectionType> DOWN = EnumProperty.of("down", ConnectionType.class);
|
||||
|
||||
public void setDefaultState() {
|
||||
setDefaultState(getStateManager().getDefaultState()
|
||||
.with(NORTH, ConnectionType.NONE)
|
||||
.with(SOUTH, ConnectionType.NONE)
|
||||
.with(WEST, ConnectionType.NONE)
|
||||
.with(EAST, ConnectionType.NONE)
|
||||
.with(UP, ConnectionType.NONE)
|
||||
.with(DOWN, ConnectionType.NONE));
|
||||
}
|
||||
|
||||
public ConnectedBlock(Settings settings, Block block) {
|
||||
super(settings, block);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPlaced(World world, BlockPos pos, BlockState state, LivingEntity placer, ItemStack itemStack) {
|
||||
super.onPlaced(world, pos, state, placer, itemStack);
|
||||
updateBlockState(world, pos, state);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void appendProperties(StateManager.Builder<Block, BlockState> builder) {
|
||||
builder.add(NORTH, SOUTH, WEST, EAST, UP, DOWN);
|
||||
}
|
||||
|
||||
public void updateBlockState(World world, BlockPos pos, BlockState state) {
|
||||
world.setBlockState(pos, updateState(state, world, pos), Block.NOTIFY_LISTENERS);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void neighborUpdate(BlockState state, World world, BlockPos pos, Block block, BlockPos fromPos, boolean notify) {
|
||||
updateBlockState(world, pos, state);
|
||||
super.neighborUpdate(state, world, pos, block, fromPos, notify);
|
||||
}
|
||||
|
||||
private BlockState updateState(BlockState state, World world, BlockPos pos) {
|
||||
for (Direction direction : Direction.values()) {
|
||||
BlockPos neighborPos = pos.offset(direction);
|
||||
BlockState neighborState = world.getBlockState(neighborPos);
|
||||
boolean isConnectedToBus = neighborState.getBlock() instanceof ConnectedBlock;
|
||||
BlockEntity blockEntity = world.getBlockEntity(neighborPos);
|
||||
boolean isConnectedToInventory = blockEntity instanceof Inventory;
|
||||
ConnectionType connectionType = ConnectionType.NONE;
|
||||
if (isConnectedToBus){
|
||||
connectionType = ConnectionType.BUS;
|
||||
} else if (isConnectedToInventory){
|
||||
connectionType = ConnectionType.INVENTORY;
|
||||
}
|
||||
|
||||
state = state.with(getPropertyForDirection(direction), connectionType);
|
||||
}
|
||||
return state;
|
||||
}
|
||||
|
||||
public static EnumProperty<ConnectionType> getPropertyForDirection(Direction direction) {
|
||||
return switch (direction) {
|
||||
case NORTH -> NORTH;
|
||||
case SOUTH -> SOUTH;
|
||||
case WEST -> WEST;
|
||||
case EAST -> EAST;
|
||||
case UP -> UP;
|
||||
case DOWN -> DOWN;
|
||||
};
|
||||
}
|
||||
}
|
@@ -0,0 +1,113 @@
|
||||
package systems.brn.serverstorage.blocks;
|
||||
|
||||
import eu.pb4.polymer.blocks.api.BlockModelType;
|
||||
import eu.pb4.polymer.blocks.api.PolymerBlockModel;
|
||||
import eu.pb4.polymer.blocks.api.PolymerBlockResourceUtils;
|
||||
import eu.pb4.polymer.blocks.api.PolymerTexturedBlock;
|
||||
import eu.pb4.polymer.core.api.block.PolymerBlockUtils;
|
||||
import net.fabricmc.fabric.api.event.player.UseBlockCallback;
|
||||
import net.minecraft.block.*;
|
||||
import net.minecraft.block.entity.BlockEntity;
|
||||
import net.minecraft.block.entity.BlockEntityType;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.item.ItemPlacementContext;
|
||||
import net.minecraft.registry.Registries;
|
||||
import net.minecraft.registry.Registry;
|
||||
import net.minecraft.state.StateManager;
|
||||
import net.minecraft.state.property.DirectionProperty;
|
||||
import net.minecraft.util.ActionResult;
|
||||
import net.minecraft.util.Hand;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.ItemScatterer;
|
||||
import net.minecraft.util.hit.BlockHitResult;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Direction;
|
||||
import net.minecraft.world.World;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import systems.brn.serverstorage.blockentities.HardDriveContainerBlockEntity;
|
||||
import systems.brn.serverstorage.lib.StorageNetwork;
|
||||
|
||||
import static systems.brn.serverstorage.ServerStorage.*;
|
||||
|
||||
public class HardDriveContainerBlock extends ConnectedBlock implements PolymerTexturedBlock, BlockEntityProvider {
|
||||
|
||||
final Identifier identifier;
|
||||
public static final DirectionProperty FACING = FacingBlock.FACING;
|
||||
private final BlockState polymerBlockState;
|
||||
|
||||
public HardDriveContainerBlock(AbstractBlock.Settings settings, Identifier identifier) {
|
||||
super(settings, Blocks.NOTE_BLOCK);
|
||||
this.identifier = identifier;
|
||||
this.setDefaultState(this.stateManager.getDefaultState().with(FACING, Direction.NORTH));
|
||||
this.polymerBlockState = PolymerBlockResourceUtils.requestBlock(BlockModelType.FULL_BLOCK, PolymerBlockModel.of(identifier.withPath("block/" + identifier.getPath())));
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockState getPlacementState(ItemPlacementContext ctx) {
|
||||
return this.getDefaultState().with(FACING, ctx.getHorizontalPlayerFacing().getOpposite());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void appendProperties(StateManager.Builder<Block, BlockState> builder) {
|
||||
super.appendProperties(builder);
|
||||
builder.add(FACING);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockState getPolymerBlockState(BlockState state) {
|
||||
return this.polymerBlockState;
|
||||
}
|
||||
|
||||
public static void register() {
|
||||
var modId = id(HARD_DRIVE_CONTAINER_BLOCK_MODEL_ID);
|
||||
HARD_DRIVE_CONTAINER_BLOCK = Registry.register(Registries.BLOCK, modId,
|
||||
new HardDriveContainerBlock(Settings.copy(Blocks.WHITE_WOOL), modId));
|
||||
UseBlockCallback.EVENT.register(HardDriveContainerBlock::onUse);
|
||||
|
||||
HARD_DRIVE_CONTAINER_BLOCK.setDefaultState();
|
||||
|
||||
HARD_DRIVE_CONTAINER_BLOCK_ENTITY = Registry.register(
|
||||
Registries.BLOCK_ENTITY_TYPE,
|
||||
modId,
|
||||
BlockEntityType.Builder.create(HardDriveContainerBlockEntity::new, HARD_DRIVE_CONTAINER_BLOCK).build(null)
|
||||
);
|
||||
PolymerBlockUtils.registerBlockEntity(HARD_DRIVE_CONTAINER_BLOCK_ENTITY);
|
||||
}
|
||||
|
||||
private static ActionResult onUse(PlayerEntity player, World world, Hand hand, BlockHitResult hitResult) {
|
||||
BlockPos pos = hitResult.getBlockPos();
|
||||
BlockState state = world.getBlockState(pos);
|
||||
Block block = state.getBlock();
|
||||
|
||||
if (block instanceof HardDriveContainerBlock) {
|
||||
if (!world.isClient && !player.isSpectator()) {
|
||||
if (!player.isSneaking()) {
|
||||
BlockEntity storageBlockEntity = world.getBlockEntity(pos);
|
||||
if (storageBlockEntity instanceof HardDriveContainerBlockEntity driveContainerBlockEntity) {
|
||||
if (driveContainerBlockEntity.network == null){
|
||||
driveContainerBlockEntity.network = new StorageNetwork(world, pos, false, "");
|
||||
}
|
||||
player.openHandledScreen(driveContainerBlockEntity);
|
||||
}
|
||||
|
||||
} else {
|
||||
return ActionResult.PASS;
|
||||
}
|
||||
}
|
||||
return ActionResult.SUCCESS;
|
||||
}
|
||||
return ActionResult.PASS;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public BlockEntity createBlockEntity(BlockPos pos, BlockState state) {
|
||||
return new HardDriveContainerBlockEntity(pos, state);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStateReplaced(BlockState state, World world, BlockPos pos, BlockState newState, boolean moved) {
|
||||
ItemScatterer.onStateReplaced(state, newState, world, pos);
|
||||
super.onStateReplaced(state, world, pos, newState, moved);
|
||||
}
|
||||
}
|
@@ -0,0 +1,187 @@
|
||||
package systems.brn.serverstorage.blocks;
|
||||
|
||||
import eu.pb4.polymer.blocks.api.BlockModelType;
|
||||
import eu.pb4.polymer.blocks.api.PolymerBlockModel;
|
||||
import eu.pb4.polymer.blocks.api.PolymerBlockResourceUtils;
|
||||
import eu.pb4.polymer.blocks.api.PolymerTexturedBlock;
|
||||
import eu.pb4.polymer.core.api.block.PolymerBlockUtils;
|
||||
import eu.pb4.sgui.api.elements.GuiElementBuilder;
|
||||
import net.fabricmc.fabric.api.event.player.UseBlockCallback;
|
||||
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.entity.player.PlayerEntity;
|
||||
import net.minecraft.item.ItemPlacementContext;
|
||||
import net.minecraft.item.Items;
|
||||
import net.minecraft.registry.Registries;
|
||||
import net.minecraft.registry.Registry;
|
||||
import net.minecraft.server.network.ServerPlayerEntity;
|
||||
import net.minecraft.server.world.ServerWorld;
|
||||
import net.minecraft.state.StateManager;
|
||||
import net.minecraft.state.property.DirectionProperty;
|
||||
import net.minecraft.text.Text;
|
||||
import net.minecraft.util.ActionResult;
|
||||
import net.minecraft.util.Formatting;
|
||||
import net.minecraft.util.Hand;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.hit.BlockHitResult;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Direction;
|
||||
import net.minecraft.world.World;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import systems.brn.serverstorage.blockentities.InventoryInterfaceBlockEntity;
|
||||
import systems.brn.serverstorage.lib.PagedGui;
|
||||
import systems.brn.serverstorage.screens.SearchScreen;
|
||||
import systems.brn.serverstorage.screens.SettingsScreen;
|
||||
|
||||
import static systems.brn.serverstorage.ServerStorage.*;
|
||||
import static systems.brn.serverstorage.lib.PagedGui.*;
|
||||
|
||||
public class InventoryInterfaceBlock extends ConnectedBlock implements PolymerTexturedBlock, BlockEntityProvider {
|
||||
final Identifier identifier;
|
||||
public static final DirectionProperty FACING = FacingBlock.FACING;
|
||||
private final BlockState polymerBlockState;
|
||||
|
||||
public InventoryInterfaceBlock(Settings settings, Identifier identifier) {
|
||||
super(settings, Blocks.NOTE_BLOCK);
|
||||
this.identifier = identifier;
|
||||
this.setDefaultState(this.stateManager.getDefaultState().with(FACING, Direction.NORTH));
|
||||
this.polymerBlockState = PolymerBlockResourceUtils.requestBlock(BlockModelType.FULL_BLOCK, PolymerBlockModel.of(identifier.withPath("block/" + identifier.getPath())));
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockState getPlacementState(ItemPlacementContext ctx) {
|
||||
return this.getDefaultState().with(FACING, ctx.getHorizontalPlayerFacing().getOpposite());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void appendProperties(StateManager.Builder<Block, BlockState> builder) {
|
||||
super.appendProperties(builder);
|
||||
builder.add(FACING);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockState getPolymerBlockState(BlockState state) {
|
||||
return this.polymerBlockState;
|
||||
}
|
||||
|
||||
public static void register() {
|
||||
var modId = id(INVENTORY_INTERFACE_BLOCK_MODEL_ID);
|
||||
INVENTORY_INTERFACE_BLOCK = Registry.register(Registries.BLOCK, modId,
|
||||
new InventoryInterfaceBlock(Settings.copy(Blocks.WHITE_WOOL), modId));
|
||||
UseBlockCallback.EVENT.register(InventoryInterfaceBlock::onUse);
|
||||
INVENTORY_INTERFACE_BLOCK.setDefaultState();
|
||||
INVENTORY_INTERFACE_BLOCK_ENTITY = Registry.register(
|
||||
Registries.BLOCK_ENTITY_TYPE,
|
||||
modId,
|
||||
BlockEntityType.Builder.create(InventoryInterfaceBlockEntity::new, INVENTORY_INTERFACE_BLOCK).build(null)
|
||||
);
|
||||
PolymerBlockUtils.registerBlockEntity(INVENTORY_INTERFACE_BLOCK_ENTITY);
|
||||
}
|
||||
|
||||
private static void loadSettings(SettingsScreen settingsScreen, InventoryInterfaceBlockEntity blockEntity) {
|
||||
settingsScreen.clearSettings();
|
||||
settingsScreen.addSetting(PagedGui.DisplayElement.of(
|
||||
new GuiElementBuilder(Items.PLAYER_HEAD)
|
||||
.setName(Text.translatable(switch (blockEntity.direction) {
|
||||
case NORTH -> "gui.serverstorage.direction_north";
|
||||
case SOUTH -> "gui.serverstorage.direction_south";
|
||||
case WEST -> "gui.serverstorage.direction_west";
|
||||
case EAST -> "gui.serverstorage.direction_east";
|
||||
case UP -> "gui.serverstorage.direction_up";
|
||||
case DOWN -> "gui.serverstorage.direction_down";
|
||||
}).formatted(Formatting.WHITE))
|
||||
.hideDefaultTooltip().noDefaults()
|
||||
.setSkullOwner(switch (blockEntity.direction) {
|
||||
case NORTH -> GUI_SIDE_NORTH;
|
||||
case SOUTH -> GUI_SIDE_SOUTH;
|
||||
case WEST -> GUI_SIDE_WEST;
|
||||
case EAST -> GUI_SIDE_EAST;
|
||||
case UP -> GUI_SIDE_UP;
|
||||
case DOWN -> GUI_SIDE_DOWN;
|
||||
})
|
||||
.setCallback((x, y, z) -> {
|
||||
playClickSound(settingsScreen.getPlayer());
|
||||
blockEntity.nextDirection();
|
||||
loadSettings(settingsScreen, blockEntity);
|
||||
blockEntity.updateDisplays();
|
||||
})
|
||||
));
|
||||
|
||||
settingsScreen.addSetting(PagedGui.DisplayElement.of(
|
||||
new GuiElementBuilder(Items.PLAYER_HEAD)
|
||||
.setName(Text.translatable(blockEntity.isOutput ? "gui.serverstorage.mode_output" : "gui.serverstorage.mode_input").formatted(Formatting.WHITE))
|
||||
.hideDefaultTooltip().noDefaults()
|
||||
.setSkullOwner(blockEntity.isOutput ? GUI_MODE_OUTPUT : GUI_MODE_INPUT)
|
||||
.setCallback((x, y, z) -> {
|
||||
playClickSound(settingsScreen.getPlayer());
|
||||
blockEntity.isOutput ^= true;
|
||||
loadSettings(settingsScreen, blockEntity);
|
||||
blockEntity.updateDisplays();
|
||||
})
|
||||
));
|
||||
|
||||
String queryNow = blockEntity.query;
|
||||
if (queryNow == null || queryNow.isEmpty() || queryNow.equals("*")) {
|
||||
queryNow = "Filter not set";
|
||||
}
|
||||
|
||||
settingsScreen.addSetting(PagedGui.DisplayElement.of(
|
||||
new GuiElementBuilder(Items.PLAYER_HEAD)
|
||||
.setName(Text.literal(queryNow).formatted(Formatting.WHITE))
|
||||
.hideDefaultTooltip().noDefaults()
|
||||
.setSkullOwner(GUI_QUESTION_MARK)
|
||||
.setCallback((x, y, z) -> {
|
||||
playClickSound(settingsScreen.getPlayer());
|
||||
if (y.isRight) {
|
||||
blockEntity.doSearch("");
|
||||
} else if (y.isLeft) {
|
||||
SearchScreen searchScreen = new SearchScreen(settingsScreen, "");
|
||||
searchScreen.open();
|
||||
}
|
||||
})
|
||||
));
|
||||
}
|
||||
|
||||
private static ActionResult onUse(PlayerEntity playerEntity, World world, Hand hand, BlockHitResult hitResult) {
|
||||
BlockPos pos = hitResult.getBlockPos();
|
||||
BlockState state = world.getBlockState(pos);
|
||||
Block block = state.getBlock();
|
||||
|
||||
if (block instanceof InventoryInterfaceBlock) {
|
||||
if (!world.getGameRules().getBoolean(ServerStorage_Interface_Enable)){
|
||||
playerEntity.sendMessage(Text.translatable("message.serverstorage.block_disabled"), true);
|
||||
return ActionResult.PASS;
|
||||
}
|
||||
BlockEntity tempBlockEntity = world.getBlockEntity(pos);
|
||||
if (tempBlockEntity instanceof InventoryInterfaceBlockEntity blockEntity) {
|
||||
if (!world.isClient && !playerEntity.isSpectator()) {
|
||||
ServerPlayerEntity player = (ServerPlayerEntity) playerEntity;
|
||||
if (!player.isSneaking()) {
|
||||
SettingsScreen settingsScreen = new SettingsScreen(player, blockEntity);
|
||||
blockEntity.reindexDrives();
|
||||
loadSettings(settingsScreen, blockEntity);
|
||||
settingsScreen.updateDisplay();
|
||||
settingsScreen.open();
|
||||
} else {
|
||||
return ActionResult.PASS;
|
||||
}
|
||||
}
|
||||
return ActionResult.SUCCESS;
|
||||
}
|
||||
}
|
||||
return ActionResult.PASS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends BlockEntity> BlockEntityTicker<T> getTicker(World world, BlockState state, BlockEntityType<T> type) {
|
||||
return world instanceof ServerWorld && type == INVENTORY_INTERFACE_BLOCK_ENTITY ? InventoryInterfaceBlockEntity::tick : null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public BlockEntity createBlockEntity(BlockPos pos, BlockState state) {
|
||||
return new InventoryInterfaceBlockEntity(pos, state);
|
||||
}
|
||||
}
|
@@ -0,0 +1,125 @@
|
||||
package systems.brn.serverstorage.blocks;
|
||||
|
||||
import eu.pb4.polymer.blocks.api.BlockModelType;
|
||||
import eu.pb4.polymer.blocks.api.PolymerBlockModel;
|
||||
import eu.pb4.polymer.blocks.api.PolymerBlockResourceUtils;
|
||||
import eu.pb4.polymer.blocks.api.PolymerTexturedBlock;
|
||||
import eu.pb4.polymer.core.api.block.PolymerBlockUtils;
|
||||
import net.fabricmc.fabric.api.event.player.UseBlockCallback;
|
||||
import net.minecraft.block.*;
|
||||
import net.minecraft.block.entity.BlockEntity;
|
||||
import net.minecraft.block.entity.BlockEntityType;
|
||||
import net.minecraft.component.DataComponentTypes;
|
||||
import net.minecraft.component.type.WrittenBookContentComponent;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.item.ItemPlacementContext;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.item.Items;
|
||||
import net.minecraft.registry.Registries;
|
||||
import net.minecraft.registry.Registry;
|
||||
import net.minecraft.server.network.ServerPlayerEntity;
|
||||
import net.minecraft.state.StateManager;
|
||||
import net.minecraft.state.property.DirectionProperty;
|
||||
import net.minecraft.text.RawFilteredPair;
|
||||
import net.minecraft.text.Text;
|
||||
import net.minecraft.util.ActionResult;
|
||||
import net.minecraft.util.Hand;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.hit.BlockHitResult;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Direction;
|
||||
import net.minecraft.world.World;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import systems.brn.serverstorage.blockentities.StorageInterfaceBlockEntity;
|
||||
import systems.brn.serverstorage.screens.StorageScreen;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static systems.brn.serverstorage.ServerStorage.*;
|
||||
import static systems.brn.serverstorage.lib.Util.generateBookContent;
|
||||
|
||||
public class StorageInterfaceBlock extends ConnectedBlock implements PolymerTexturedBlock, BlockEntityProvider {
|
||||
final Identifier identifier;
|
||||
public static final DirectionProperty FACING = FacingBlock.FACING;
|
||||
private final BlockState polymerBlockState;
|
||||
|
||||
public StorageInterfaceBlock(Settings settings, Identifier identifier) {
|
||||
super(settings, Blocks.NOTE_BLOCK);
|
||||
this.identifier = identifier;
|
||||
this.setDefaultState(this.stateManager.getDefaultState().with(FACING, Direction.NORTH));
|
||||
this.polymerBlockState = PolymerBlockResourceUtils.requestBlock(BlockModelType.FULL_BLOCK, PolymerBlockModel.of(identifier.withPath("block/" + identifier.getPath())));
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockState getPlacementState(ItemPlacementContext ctx) {
|
||||
return this.getDefaultState().with(FACING, ctx.getHorizontalPlayerFacing().getOpposite());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void appendProperties(StateManager.Builder<Block, BlockState> builder) {
|
||||
super.appendProperties(builder);
|
||||
builder.add(FACING);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockState getPolymerBlockState(BlockState state) {
|
||||
return this.polymerBlockState;
|
||||
}
|
||||
|
||||
public static void register() {
|
||||
var modId = id(STORAGE_MODEL_ID);
|
||||
STORAGE_INTERFACE_BLOCK = Registry.register(Registries.BLOCK, modId,
|
||||
new StorageInterfaceBlock(AbstractBlock.Settings.copy(Blocks.WHITE_WOOL), modId));
|
||||
UseBlockCallback.EVENT.register(StorageInterfaceBlock::onUse);
|
||||
STORAGE_INTERFACE_BLOCK.setDefaultState();
|
||||
STORAGE_INTERFACE_BLOCK_ENTITY = Registry.register(
|
||||
Registries.BLOCK_ENTITY_TYPE,
|
||||
modId,
|
||||
BlockEntityType.Builder.create(StorageInterfaceBlockEntity::new, STORAGE_INTERFACE_BLOCK).build(null)
|
||||
);
|
||||
PolymerBlockUtils.registerBlockEntity(STORAGE_INTERFACE_BLOCK_ENTITY);
|
||||
}
|
||||
|
||||
private static ActionResult onUse(PlayerEntity player, World world, Hand hand, BlockHitResult hitResult) {
|
||||
BlockPos pos = hitResult.getBlockPos();
|
||||
BlockState state = world.getBlockState(pos);
|
||||
Block block = state.getBlock();
|
||||
|
||||
if (block instanceof StorageInterfaceBlock) {
|
||||
if (!world.getGameRules().getBoolean(ServerStorage_Terminal_Enable)){
|
||||
player.sendMessage(Text.translatable("message.serverstorage.block_disabled"), true);
|
||||
return ActionResult.PASS;
|
||||
}
|
||||
if (!world.isClient && !player.isSpectator()) {
|
||||
if (!player.isSneaking()) {
|
||||
StorageScreen storageScreen = new StorageScreen((ServerPlayerEntity) player, pos, null);
|
||||
storageScreen.updateDisplay();
|
||||
storageScreen.open();
|
||||
|
||||
} else if (player.getStackInHand(hand).getItem() == Items.WRITTEN_BOOK) {
|
||||
ItemStack book = player.getStackInHand(hand);
|
||||
StorageInterfaceBlockEntity storageInterfaceBlockEntity = (StorageInterfaceBlockEntity) world.getBlockEntity(pos);
|
||||
assert storageInterfaceBlockEntity != null;
|
||||
List<RawFilteredPair<Text>> generatedContent = generateBookContent(storageInterfaceBlockEntity.network.itemStackMap);
|
||||
book.set(DataComponentTypes.WRITTEN_BOOK_CONTENT, new WrittenBookContentComponent(
|
||||
RawFilteredPair.of("Item Listing"),
|
||||
player.getGameProfile().getName(),
|
||||
0,
|
||||
generatedContent,
|
||||
false
|
||||
));
|
||||
} else {
|
||||
return ActionResult.PASS;
|
||||
}
|
||||
}
|
||||
return ActionResult.SUCCESS;
|
||||
}
|
||||
return ActionResult.PASS;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public BlockEntity createBlockEntity(BlockPos pos, BlockState state) {
|
||||
return new StorageInterfaceBlockEntity(pos, state);
|
||||
}
|
||||
}
|
296
src/main/java/systems/brn/serverstorage/items/HardDrive.java
Normal file
296
src/main/java/systems/brn/serverstorage/items/HardDrive.java
Normal file
@@ -0,0 +1,296 @@
|
||||
package systems.brn.serverstorage.items;
|
||||
|
||||
import net.minecraft.component.DataComponentTypes;
|
||||
import net.minecraft.component.type.LoreComponent;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.item.Items;
|
||||
import net.minecraft.text.Style;
|
||||
import net.minecraft.text.Text;
|
||||
import net.minecraft.util.Formatting;
|
||||
import systems.brn.serverstorage.blockentities.HardDriveContainerBlockEntity;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import static systems.brn.serverstorage.lib.DriveComponents.*;
|
||||
import static systems.brn.serverstorage.lib.StorageOperations.canCombine;
|
||||
|
||||
public class HardDrive {
|
||||
private ItemStack driveStack;
|
||||
public final HardDriveContainerBlockEntity blockEntity;
|
||||
private int containerIndex;
|
||||
|
||||
private int maxItems;
|
||||
private int usedItems;
|
||||
private int availableItems;
|
||||
private final UUID myUUID;
|
||||
private int tier;
|
||||
|
||||
public Map<ItemStack, Integer> items;
|
||||
|
||||
public void loadComponents() {
|
||||
this.items = driveStack.getComponents().getOrDefault(ITEMSTACK_MAP, new HashMap<>());
|
||||
updateData();
|
||||
}
|
||||
|
||||
public void setMaxItems() {
|
||||
String itemName = driveStack.getItem().getRegistryEntry().registryKey().getValue().getPath();
|
||||
switch (itemName) {
|
||||
case "iron_drive":
|
||||
tier = 0;
|
||||
break;
|
||||
case "golden_drive":
|
||||
tier = 1;
|
||||
break;
|
||||
case "diamond_drive":
|
||||
tier = 2;
|
||||
break;
|
||||
case "netherite_drive":
|
||||
tier = 3;
|
||||
break;
|
||||
default:
|
||||
tier = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
maxItems = 0;
|
||||
|
||||
if (tier >= 0) {
|
||||
maxItems = (int) Math.pow(2, tier + 8);
|
||||
}
|
||||
}
|
||||
|
||||
public void updateData() {
|
||||
usedItems = 0;
|
||||
for (Map.Entry<ItemStack, Integer> entry : items.entrySet()) {
|
||||
if (entry.getKey().getItem() == Items.AIR) {
|
||||
items.remove(entry.getKey());
|
||||
} else {
|
||||
usedItems += entry.getValue();
|
||||
}
|
||||
}
|
||||
addLoreInfo();
|
||||
availableItems = maxItems - usedItems;
|
||||
assert maxItems >= usedItems;
|
||||
assert usedItems >= 0;
|
||||
}
|
||||
|
||||
public void saveComponents() {
|
||||
ItemStack tempStack = driveStack.copy();
|
||||
HashMap<ItemStack, Integer> itemsTemp = new HashMap<>();
|
||||
for (Map.Entry<ItemStack, Integer> entry : items.entrySet()) {
|
||||
int count = entry.getKey().getCount();
|
||||
if (count > entry.getKey().getMaxCount()) {
|
||||
count = entry.getKey().getMaxCount();
|
||||
}
|
||||
ItemStack limitedStack = entry.getKey().copy();
|
||||
limitedStack.setCount(count);
|
||||
itemsTemp.put(limitedStack, entry.getValue());
|
||||
}
|
||||
tempStack.remove(ITEMSTACK_MAP);
|
||||
tempStack.set(ITEMSTACK_MAP, itemsTemp);
|
||||
driveStack = tempStack;
|
||||
}
|
||||
|
||||
private boolean isNotTheSameDrive(ItemStack currentStack) {
|
||||
return currentStack.getItem() != driveStack.getItem() || (currentStack.contains(UUID_COMPONENT) && currentStack.get(UUID_COMPONENT) != myUUID);
|
||||
}
|
||||
|
||||
public ItemStack getCommitedStack() {
|
||||
ItemStack tempDriveStack = driveStack.copy();
|
||||
driveStack = ensureUUID(tempDriveStack);
|
||||
loadComponents();
|
||||
updateData();
|
||||
saveComponents();
|
||||
return driveStack;
|
||||
}
|
||||
|
||||
public void commitChangesToContainer() {
|
||||
getCommitedStack();
|
||||
ItemStack currentStack = blockEntity.inventory.get(containerIndex);
|
||||
boolean updated = false;
|
||||
if (isNotTheSameDrive(currentStack)) {
|
||||
updateIndex();
|
||||
updated = true;
|
||||
}
|
||||
if (updated && isNotTheSameDrive(currentStack)) {
|
||||
return;
|
||||
}
|
||||
|
||||
blockEntity.inventory.set(containerIndex, driveStack);
|
||||
blockEntity.markDirty();
|
||||
}
|
||||
|
||||
public ItemStack removeStackFromInventoryRemains(ItemStack stack) {
|
||||
int outCount = stack.getCount();
|
||||
ItemStack outStack = stack.copy();
|
||||
for (Map.Entry<ItemStack, Integer> entry : items.entrySet()) {
|
||||
if (canCombine(entry.getKey(), stack)) {
|
||||
int countInDrive = entry.getValue();
|
||||
|
||||
if (countInDrive <= outCount) {
|
||||
items.remove(entry.getKey());
|
||||
outCount -= countInDrive;
|
||||
} else {
|
||||
entry.setValue(countInDrive - outCount);
|
||||
outCount -= countInDrive;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
outStack.setCount(outCount);
|
||||
commitChangesToContainer();
|
||||
blockEntity.markDirty();
|
||||
return outStack;
|
||||
}
|
||||
|
||||
public ItemStack insertStackIntoInventory(ItemStack stack) {
|
||||
// First, try to merge with existing stacks
|
||||
boolean merged = false;
|
||||
if (stack.isEmpty()) {
|
||||
return stack;
|
||||
}
|
||||
int transferAmount = Math.min(stack.getCount(), availableItems);
|
||||
if (transferAmount > 0) {
|
||||
for (Map.Entry<ItemStack, Integer> entry : items.entrySet()) {
|
||||
ItemStack slotStack = entry.getKey();
|
||||
if (canCombine(slotStack, stack)) {
|
||||
entry.setValue(transferAmount + entry.getValue());
|
||||
stack.decrement(transferAmount);
|
||||
merged = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!merged) {
|
||||
ItemStack inStack = stack.copy();
|
||||
inStack.capCount(inStack.getMaxCount());
|
||||
items.put(inStack, transferAmount);
|
||||
stack.decrement(transferAmount);
|
||||
}
|
||||
}
|
||||
commitChangesToContainer();
|
||||
blockEntity.markDirty();
|
||||
if (stack.isEmpty() || stack.getCount() < 1) {
|
||||
return ItemStack.EMPTY;
|
||||
} else {
|
||||
return stack;
|
||||
}
|
||||
}
|
||||
|
||||
private void addLoreInfo() {
|
||||
ItemStack tempDriveStack = driveStack.copy();
|
||||
|
||||
Formatting availableLineFormatting;
|
||||
Formatting usedLineFormatting;
|
||||
|
||||
if (usedItems > maxItems){
|
||||
usedLineFormatting = Formatting.LIGHT_PURPLE;
|
||||
} else if (usedItems == maxItems) {
|
||||
usedLineFormatting = Formatting.RED;
|
||||
} else if (usedItems >= maxItems * 0.8){
|
||||
usedLineFormatting = Formatting.YELLOW;
|
||||
} else if (usedItems >= maxItems * 0.5){
|
||||
usedLineFormatting = Formatting.GOLD;
|
||||
} else {
|
||||
usedLineFormatting = Formatting.GREEN;
|
||||
}
|
||||
|
||||
if (usedItems > maxItems) {
|
||||
availableLineFormatting = Formatting.LIGHT_PURPLE; //how did you do this
|
||||
} else if (usedItems == maxItems) {
|
||||
availableLineFormatting = Formatting.RED; // full
|
||||
} else if (usedItems >= maxItems * 0.9) {
|
||||
availableLineFormatting = Formatting.YELLOW; //90% or more full
|
||||
} else {
|
||||
availableLineFormatting = Formatting.GREEN; //good
|
||||
}
|
||||
|
||||
|
||||
Formatting totalLineFormatting = switch (tier) {
|
||||
case 0 -> Formatting.DARK_GRAY;
|
||||
case 1 -> Formatting.GOLD;
|
||||
case 2 -> Formatting.AQUA;
|
||||
case 3 -> Formatting.BLACK;
|
||||
default -> Formatting.OBFUSCATED;
|
||||
};
|
||||
|
||||
Text usedLine = Text.literal("Used slots: " + usedItems).setStyle(Style.EMPTY.withColor(usedLineFormatting).withItalic(true));
|
||||
Text availableLine = Text.literal("Available slots: " + availableItems).setStyle(Style.EMPTY.withColor(availableLineFormatting).withItalic(true));
|
||||
Text totalLine = Text.literal("Total slots: " + maxItems).setStyle(Style.EMPTY.withColor(totalLineFormatting).withItalic(true));
|
||||
|
||||
LoreComponent newLore;
|
||||
List<Text> loreList = new ArrayList<>();
|
||||
loreList.add(availableLine);
|
||||
loreList.add(usedLine);
|
||||
loreList.add(totalLine);
|
||||
newLore = new LoreComponent(loreList);
|
||||
|
||||
tempDriveStack.set(DataComponentTypes.LORE, newLore);
|
||||
driveStack = tempDriveStack;
|
||||
}
|
||||
|
||||
private void updateIndex() {
|
||||
for (int i = 0; i < blockEntity.inventory.size(); i++) {
|
||||
ItemStack stack = blockEntity.inventory.get(i);
|
||||
UUID foundUUID = stack.getOrDefault(UUID_COMPONENT, null);
|
||||
if (foundUUID != null && foundUUID.equals(myUUID)) {
|
||||
containerIndex = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public HardDrive(ItemStack driveStack, HardDriveContainerBlockEntity blockEntity, int containerIndex) {
|
||||
this.driveStack = driveStack;
|
||||
this.blockEntity = blockEntity;
|
||||
this.myUUID = driveStack.get(UUID_COMPONENT);
|
||||
this.containerIndex = containerIndex;
|
||||
setMaxItems();
|
||||
loadComponents();
|
||||
updateData();
|
||||
}
|
||||
|
||||
public int getMaxItems() {
|
||||
return maxItems;
|
||||
}
|
||||
|
||||
public int getAvailableItems() {
|
||||
return availableItems;
|
||||
}
|
||||
|
||||
public int getUsedItems() {
|
||||
return usedItems;
|
||||
}
|
||||
|
||||
public Map<ItemStack, Integer> addToMap(Map<ItemStack, Integer> itemStackMap) {
|
||||
for (Map.Entry<ItemStack, Integer> diskEntry : items.entrySet()) {
|
||||
boolean found = false;
|
||||
for (Map.Entry<ItemStack, Integer> mapEntry : itemStackMap.entrySet()) {
|
||||
ItemStack existingStack = mapEntry.getKey();
|
||||
if (ItemStack.areItemsAndComponentsEqual(diskEntry.getKey(), existingStack)) {
|
||||
int newCount = mapEntry.getValue() + diskEntry.getValue();
|
||||
itemStackMap.put(existingStack, newCount);
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
itemStackMap.put(diskEntry.getKey(), diskEntry.getValue());
|
||||
}
|
||||
}
|
||||
return itemStackMap;
|
||||
}
|
||||
|
||||
public int getContainerIndex() {
|
||||
return containerIndex;
|
||||
}
|
||||
|
||||
public static ItemStack ensureUUID(ItemStack driveStack) {
|
||||
if (driveStack.getComponents().contains(UUID_COMPONENT)) {
|
||||
return driveStack;
|
||||
} else {
|
||||
ItemStack tempStack = driveStack.copy();
|
||||
tempStack.set(UUID_COMPONENT, UUID.randomUUID());
|
||||
return tempStack;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,35 @@
|
||||
package systems.brn.serverstorage.items;
|
||||
|
||||
import net.fabricmc.fabric.api.itemgroup.v1.ItemGroupEvents;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.ItemGroups;
|
||||
import net.minecraft.registry.Registries;
|
||||
import net.minecraft.registry.Registry;
|
||||
import net.minecraft.util.Identifier;
|
||||
import systems.brn.serverstorage.lib.DriveComponents;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
import static systems.brn.serverstorage.ServerStorage.id;
|
||||
|
||||
public class HardDriveItem extends SimpleItem {
|
||||
public HardDriveItem(Settings settings, Identifier identifier) {
|
||||
super(settings, identifier);
|
||||
}
|
||||
|
||||
public static List<Item> register(List<String> tiers){
|
||||
ArrayList<Item> items = new ArrayList<>();
|
||||
for (String tier : tiers) {
|
||||
Identifier identifier = id(tier + "_drive");
|
||||
Item item = Registry.register(Registries.ITEM, identifier, new SimpleItem(new Settings()
|
||||
.maxCount(1)
|
||||
.component(DriveComponents.ITEMSTACK_MAP, new HashMap<>())
|
||||
, identifier));
|
||||
ItemGroupEvents.modifyEntriesEvent(ItemGroups.FUNCTIONAL).register(content -> content.add(item));
|
||||
items.add(item);
|
||||
}
|
||||
return items;
|
||||
}
|
||||
}
|
@@ -0,0 +1,44 @@
|
||||
package systems.brn.serverstorage.items;
|
||||
|
||||
import eu.pb4.polymer.core.api.item.PolymerBlockItem;
|
||||
import eu.pb4.polymer.core.api.item.PolymerItem;
|
||||
import eu.pb4.polymer.resourcepack.api.PolymerModelData;
|
||||
import eu.pb4.polymer.resourcepack.api.PolymerResourcePackUtils;
|
||||
import net.fabricmc.fabric.api.itemgroup.v1.ItemGroupEvents;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.ItemGroups;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.item.Items;
|
||||
import net.minecraft.registry.Registries;
|
||||
import net.minecraft.registry.Registry;
|
||||
import net.minecraft.server.network.ServerPlayerEntity;
|
||||
import net.minecraft.util.Identifier;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import static systems.brn.serverstorage.ServerStorage.id;
|
||||
|
||||
public class SimpleBlockItem extends PolymerBlockItem implements PolymerItem {
|
||||
private final PolymerModelData polymerModel;
|
||||
|
||||
public SimpleBlockItem(Item.Settings settings, Block block, Identifier identifier) {
|
||||
super(block, settings, Items.BARRIER);
|
||||
this.polymerModel = PolymerResourcePackUtils.requestModel(Items.BARRIER, identifier.withPath("item/" + identifier.getPath()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Item getPolymerItem(ItemStack itemStack, @Nullable ServerPlayerEntity player) {
|
||||
return this.polymerModel.item();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPolymerCustomModelData(ItemStack itemStack, @Nullable ServerPlayerEntity player) {
|
||||
return this.polymerModel.value();
|
||||
}
|
||||
|
||||
public static void register(Block block) {
|
||||
Identifier identifier = id(block.getRegistryEntry().registryKey().getValue().getPath());
|
||||
Item item = Registry.register(Registries.ITEM, identifier, new SimpleBlockItem(new Item.Settings(), block, identifier));
|
||||
ItemGroupEvents.modifyEntriesEvent(ItemGroups.FUNCTIONAL).register(content -> content.add(item));
|
||||
}
|
||||
}
|
@@ -0,0 +1,71 @@
|
||||
package systems.brn.serverstorage.items;
|
||||
|
||||
import eu.pb4.polymer.core.api.item.PolymerItem;
|
||||
import eu.pb4.polymer.core.api.item.SimplePolymerItem;
|
||||
import eu.pb4.polymer.resourcepack.api.PolymerModelData;
|
||||
import eu.pb4.polymer.resourcepack.api.PolymerResourcePackUtils;
|
||||
import net.fabricmc.fabric.api.itemgroup.v1.ItemGroupEvents;
|
||||
import net.minecraft.item.*;
|
||||
import net.minecraft.registry.Registries;
|
||||
import net.minecraft.registry.Registry;
|
||||
import net.minecraft.registry.RegistryKey;
|
||||
import net.minecraft.server.network.ServerPlayerEntity;
|
||||
import net.minecraft.util.Identifier;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import static systems.brn.serverstorage.ServerStorage.id;
|
||||
|
||||
public class SimpleItem extends SimplePolymerItem implements PolymerItem {
|
||||
private final PolymerModelData polymerModel;
|
||||
|
||||
public SimpleItem(Settings settings, Identifier identifier) {
|
||||
super(settings, Items.BARRIER);
|
||||
this.polymerModel = PolymerResourcePackUtils.requestModel(Items.BARRIER, identifier.withPath("item/" + identifier.getPath()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Item getPolymerItem(ItemStack itemStack, @Nullable ServerPlayerEntity player) {
|
||||
return this.polymerModel.item();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPolymerCustomModelData(ItemStack itemStack, @Nullable ServerPlayerEntity player) {
|
||||
return this.polymerModel.value();
|
||||
}
|
||||
|
||||
public static Item register(String name, RegistryKey<ItemGroup> group){
|
||||
return register(name, 64, group);
|
||||
}
|
||||
|
||||
public static Item register(String name, int maxCount, RegistryKey<ItemGroup> group) {
|
||||
Identifier identifier = id(name);
|
||||
Item item = Registry.register(Registries.ITEM, identifier, new SimpleItem(new Settings().maxCount(maxCount), identifier));
|
||||
ItemGroupEvents.modifyEntriesEvent(group).register(content -> content.add(item));
|
||||
return item;
|
||||
}
|
||||
|
||||
public static List<Item> register(String name, List<String> tiers, boolean tierFirst, RegistryKey<ItemGroup> group) {
|
||||
return register(name, tiers, 64, tierFirst, group);
|
||||
}
|
||||
|
||||
public static List<Item> register(String name, List<String> tiers, RegistryKey<ItemGroup> group) {
|
||||
return register(name, tiers, 64, true, group);
|
||||
}
|
||||
|
||||
public static List<Item> register(String name, List<String> tiers, int maxCount, boolean tierFirst, RegistryKey<ItemGroup> group) {
|
||||
ArrayList<Item> items = new ArrayList<>();
|
||||
for (String tier : tiers) {
|
||||
String itemName;
|
||||
if (tierFirst){
|
||||
itemName = tier + "_" + name;
|
||||
} else {
|
||||
itemName = name + "_" + tier;
|
||||
}
|
||||
items.add(SimpleItem.register(itemName, maxCount, group));
|
||||
}
|
||||
return items;
|
||||
}
|
||||
}
|
@@ -0,0 +1,24 @@
|
||||
package systems.brn.serverstorage.lib;
|
||||
|
||||
import net.minecraft.util.StringIdentifiable;
|
||||
|
||||
public enum ConnectionType implements StringIdentifiable {
|
||||
NONE("none"),
|
||||
BUS("bus"),
|
||||
INVENTORY("inventory");
|
||||
private final String name;
|
||||
|
||||
ConnectionType(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String asString() {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return this.name;
|
||||
}
|
||||
}
|
@@ -0,0 +1,44 @@
|
||||
package systems.brn.serverstorage.lib;
|
||||
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.recipe.CraftingRecipe;
|
||||
import net.minecraft.recipe.RecipeEntry;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import static systems.brn.serverstorage.lib.Util.addCountToLore;
|
||||
|
||||
public class CraftingEntry {
|
||||
public final ArrayList<ItemStack> outputStacks;
|
||||
public final RecipeEntry<CraftingRecipe> recipeEntry;
|
||||
public final ArrayList<RecipeEntry<CraftingRecipe>> myCraftingRecipeEntries;
|
||||
|
||||
public CraftingEntry(ItemStack itemStack, RecipeEntry<CraftingRecipe> recipeEntry, HashMap<ItemStack, Integer> inputs, Integer maxCount) {
|
||||
ArrayList<ItemStack> tempOutputStacks = new ArrayList<>();
|
||||
ItemStack outputStack = itemStack.copy();
|
||||
outputStack.setCount(maxCount);
|
||||
outputStack = addCountToLore(itemStack.getCount() * maxCount, outputStack, "Total max: ");
|
||||
outputStack = addCountToLore(itemStack.getCount(), outputStack, "Each craft: ");
|
||||
outputStack = addCountToLore(maxCount, outputStack, "Max crafts: ");
|
||||
tempOutputStacks.add(outputStack);
|
||||
for (Map.Entry<ItemStack, Integer> entry : inputs.entrySet()) {
|
||||
ItemStack stackIn = entry.getKey();
|
||||
Integer count = entry.getValue();
|
||||
if (count > 0 && stackIn.isEmpty() && stackIn.getItem().hasRecipeRemainder()) {
|
||||
Item remainderItem = stackIn.getItem().getRecipeRemainder();
|
||||
if (remainderItem != null) {
|
||||
ItemStack remainderStack = new ItemStack(stackIn.getItem().getRecipeRemainder(), count);
|
||||
tempOutputStacks.add(remainderStack);
|
||||
}
|
||||
}
|
||||
}
|
||||
this.outputStacks = tempOutputStacks;
|
||||
this.recipeEntry = recipeEntry;
|
||||
this.myCraftingRecipeEntries = new ArrayList<>();
|
||||
|
||||
}
|
||||
}
|
||||
|
@@ -0,0 +1,58 @@
|
||||
package systems.brn.serverstorage.lib;
|
||||
|
||||
import com.mojang.serialization.Codec;
|
||||
import com.mojang.serialization.codecs.RecordCodecBuilder;
|
||||
import eu.pb4.polymer.core.api.other.PolymerComponent;
|
||||
import net.minecraft.component.ComponentType;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.registry.Registries;
|
||||
import net.minecraft.registry.Registry;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.function.UnaryOperator;
|
||||
|
||||
|
||||
public class DriveComponents {
|
||||
public static final Codec<List<ItemStack>> ITEMSTACK_LIST_CODEC = Codec.list(ItemStack.CODEC);
|
||||
public static final Codec<List<Integer>> INTEGER_LIST_CODEC = Codec.list(Codec.INT);
|
||||
|
||||
public static final Codec<Map<ItemStack, Integer>> ITEMSTACK_MAP_CODEC = RecordCodecBuilder.create(instance ->
|
||||
instance.group(
|
||||
ITEMSTACK_LIST_CODEC.fieldOf("itemStacks").forGetter(map -> new ArrayList<>(map.keySet())),
|
||||
INTEGER_LIST_CODEC.fieldOf("counts").forGetter(map -> new ArrayList<>(map.values()))
|
||||
).apply(instance, (itemStacks, counts) -> {
|
||||
Map<ItemStack, Integer> map = new HashMap<>();
|
||||
for (int i = 0; i < itemStacks.size(); i++) {
|
||||
map.put(itemStacks.get(i), counts.get(i));
|
||||
}
|
||||
return map;
|
||||
})
|
||||
);
|
||||
|
||||
public static final Codec<UUID> UUID_CODEC = RecordCodecBuilder.create(instance ->
|
||||
instance.group(
|
||||
Codec.LONG.fieldOf("mostSigBits").forGetter(UUID::getMostSignificantBits),
|
||||
Codec.LONG.fieldOf("leastSigBits").forGetter(UUID::getLeastSignificantBits)
|
||||
).apply(instance, UUID::new));
|
||||
|
||||
public static final ComponentType<Map<ItemStack, Integer>> ITEMSTACK_MAP = register(
|
||||
"itemstack_map",
|
||||
builder -> builder.codec(ITEMSTACK_MAP_CODEC) // No packetCodec needed for this example
|
||||
);
|
||||
|
||||
public static final ComponentType<UUID> UUID_COMPONENT = register(
|
||||
"drive_uuid",
|
||||
builder -> builder.codec(UUID_CODEC) // No packetCodec needed for this example
|
||||
);
|
||||
|
||||
|
||||
private static <T> ComponentType<T> register(String id, UnaryOperator<ComponentType.Builder<T>> builderOperator) {
|
||||
ComponentType<T> componentType = Registry.register(
|
||||
Registries.DATA_COMPONENT_TYPE,
|
||||
id,
|
||||
builderOperator.apply(ComponentType.builder()).build()
|
||||
);
|
||||
PolymerComponent.registerDataComponent(componentType);
|
||||
return componentType;
|
||||
}
|
||||
}
|
@@ -0,0 +1,24 @@
|
||||
package systems.brn.serverstorage.lib;
|
||||
|
||||
import net.minecraft.inventory.Inventory;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.screen.slot.Slot;
|
||||
|
||||
import static systems.brn.serverstorage.ServerStorage.DRIVES;
|
||||
|
||||
public class HardDriveSlot extends Slot {
|
||||
public HardDriveSlot(Inventory inventory, int index, int x, int y) {
|
||||
super(inventory, index, x, y);
|
||||
}
|
||||
|
||||
public static boolean isHardDrive(Item item){
|
||||
return DRIVES.contains(item);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canInsert(ItemStack stack) {
|
||||
return isHardDrive(stack.getItem());
|
||||
}
|
||||
|
||||
}
|
242
src/main/java/systems/brn/serverstorage/lib/PagedGui.java
Normal file
242
src/main/java/systems/brn/serverstorage/lib/PagedGui.java
Normal file
@@ -0,0 +1,242 @@
|
||||
package systems.brn.serverstorage.lib;
|
||||
|
||||
import eu.pb4.sgui.api.elements.GuiElement;
|
||||
import eu.pb4.sgui.api.elements.GuiElementBuilder;
|
||||
import eu.pb4.sgui.api.elements.GuiElementBuilderInterface;
|
||||
import eu.pb4.sgui.api.elements.GuiElementInterface;
|
||||
import eu.pb4.sgui.api.gui.SimpleGui;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.item.Items;
|
||||
import net.minecraft.screen.ScreenHandlerType;
|
||||
import net.minecraft.screen.slot.Slot;
|
||||
import net.minecraft.server.network.ServerPlayerEntity;
|
||||
import net.minecraft.sound.SoundCategory;
|
||||
import net.minecraft.sound.SoundEvents;
|
||||
import net.minecraft.text.Text;
|
||||
import net.minecraft.util.Formatting;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
|
||||
//from https://github.com/Patbox/get-off-my-lawn-reserved/blob/6c03c6b004f65616d1d8cb773c19da970eb8c1d1/src/main/java/draylar/goml/ui/PagedGui.java
|
||||
@ApiStatus.Internal
|
||||
public abstract class PagedGui extends SimpleGui {
|
||||
|
||||
public static final String GUI_PREVIOUS_PAGE = "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMzEwODI5OGZmMmIyNjk1MWQ2ODNlNWFkZTQ2YTQyZTkwYzJmN2M3ZGQ0MWJhYTkwOGJjNTg1MmY4YzMyZTU4MyJ9fX0";
|
||||
public static final String GUI_PREVIOUS_PAGE_BLOCKED = "ewogICJ0aW1lc3RhbXAiIDogMTY0MDYxNjE5MjE0MiwKICAicHJvZmlsZUlkIiA6ICJmMjc0YzRkNjI1MDQ0ZTQxOGVmYmYwNmM3NWIyMDIxMyIsCiAgInByb2ZpbGVOYW1lIiA6ICJIeXBpZ3NlbCIsCiAgInNpZ25hdHVyZVJlcXVpcmVkIiA6IHRydWUsCiAgInRleHR1cmVzIiA6IHsKICAgICJTS0lOIiA6IHsKICAgICAgInVybCIgOiAiaHR0cDovL3RleHR1cmVzLm1pbmVjcmFmdC5uZXQvdGV4dHVyZS81MDgyMGY3NmUzZTA0MWM3NWY3NmQwZjMwMTIzMmJkZjQ4MzIxYjUzNGZlNmE4NTljY2I4NzNkMjk4MWE5NjIzIiwKICAgICAgIm1ldGFkYXRhIiA6IHsKICAgICAgICAibW9kZWwiIDogInNsaW0iCiAgICAgIH0KICAgIH0KICB9Cn0=";
|
||||
public static final String GUI_NEXT_PAGE = "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYzg2MTg1YjFkNTE5YWRlNTg1ZjE4NGMzNGYzZjNlMjBiYjY0MWRlYjg3OWU4MTM3OGU0ZWFmMjA5Mjg3In19fQ";
|
||||
public static final String GUI_NEXT_PAGE_BLOCKED = "ewogICJ0aW1lc3RhbXAiIDogMTY0MDYxNjExMDQ4OCwKICAicHJvZmlsZUlkIiA6ICIxZjEyNTNhYTVkYTQ0ZjU5YWU1YWI1NmFhZjRlNTYxNyIsCiAgInByb2ZpbGVOYW1lIiA6ICJOb3RNaUt5IiwKICAic2lnbmF0dXJlUmVxdWlyZWQiIDogdHJ1ZSwKICAidGV4dHVyZXMiIDogewogICAgIlNLSU4iIDogewogICAgICAidXJsIiA6ICJodHRwOi8vdGV4dHVyZXMubWluZWNyYWZ0Lm5ldC90ZXh0dXJlLzdlNTc3MjBhNDg3OGM4YmNhYjBlOWM5YzQ3ZDllNTUxMjhjY2Q3N2JhMzQ0NWE1NGE5MWUzZTFlMWEyNzM1NmUiLAogICAgICAibWV0YWRhdGEiIDogewogICAgICAgICJtb2RlbCIgOiAic2xpbSIKICAgICAgfQogICAgfQogIH0KfQ==";
|
||||
public static final String GUI_QUESTION_MARK = "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYmM4ZWExZjUxZjI1M2ZmNTE0MmNhMTFhZTQ1MTkzYTRhZDhjM2FiNWU5YzZlZWM4YmE3YTRmY2I3YmFjNDAifX19";
|
||||
public static final String GUI_REFRESH = "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZDc1ZDNkYjAzZGMyMWU1NjNiMDM0MTk3ZGE0MzViNzllY2ZlZjRiOGUyZWNkYjczMGUzNzBjMzE2NjI5ZDM2ZiJ9fX0=";
|
||||
public static final String GUI_A = "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNGU0MTc0ODEyMTYyNmYyMmFlMTZhNGM2NjRjNzMwMWE5ZjhlYTU5MWJmNGQyOTg4ODk1NzY4MmE5ZmRhZiJ9fX0=";
|
||||
public static final String GUI_1 = "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvY2E1MTZmYmFlMTYwNThmMjUxYWVmOWE2OGQzMDc4NTQ5ZjQ4ZjZkNWI2ODNmMTljZjVhMTc0NTIxN2Q3MmNjIn19fQ==";
|
||||
public static final String GUI_STORE_ALL = "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMWFkNmM4MWY4OTlhNzg1ZWNmMjZiZTFkYzQ4ZWFlMmJjZmU3NzdhODYyMzkwZjU3ODVlOTViZDgzYmQxNGQifX19";
|
||||
public static final String GUI_SETTINGS = "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZTRkNDliYWU5NWM3OTBjM2IxZmY1YjJmMDEwNTJhNzE0ZDYxODU0ODFkNWIxYzg1OTMwYjNmOTlkMjMyMTY3NCJ9fX0=";
|
||||
public static final String GUI_CRAFTING = "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYWQyYzBjZWRmYzMyZTNiZWVlOTU1Y2FiZDY2ZmQ0ZDc2NWVlZGEzYWRjYzg0YmM0NTFjOWZkYmVjZjNjYjdjMiJ9fX0=";
|
||||
|
||||
public static final String GUI_SIDE_NORTH = "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZGEyMjFlNGY5NmJlZTYyNjE3NTIzOTZhMzI2NWZmYTRkZWRmOGZmNDgzOWFiZDE0ZjQ5ZWRlZTFlNTMwOTIifX19";
|
||||
public static final String GUI_SIDE_SOUTH = "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZDcxMDEzODQxNjUyODg4OTgxNTU0OGI0NjIzZDI4ZDg2YmJiYWU1NjE5ZDY5Y2Q5ZGJjNWFkNmI0Mzc0NCJ9fX0=";
|
||||
public static final String GUI_SIDE_EAST = "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMWFlZWY4OGUyYzkyOGI0NjZjNmVkNWRlYWE0ZTE5NzVhOTQzNmMyYjFiNDk4ZjlmN2NiZjkyYTliNTk5YTYifX19";
|
||||
public static final String GUI_SIDE_WEST = "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvODBjOTQ4M2Y1MWQxMjY3NDMyZTBmMmYzYmFhOGNkOTNlNjViNWVhYzc0ODJiMjdkYmNjZWJhZmI3MjE3NDhiIn19fQ==";
|
||||
public static final String GUI_SIDE_UP = "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZDY5OTFkY2JhMjVlYWUyNDNlYjVjZWI4MzI1ZjRhYjc4ZjlmMTQxMjdjMzgyZjZjZDQyYzRjNzgwNDJkNGI1In19fQ==";
|
||||
public static final String GUI_SIDE_DOWN = "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZmE2NjE0MTlkZTQ5ZmY0YTJjOTdiMjdmODY4MDE0ZmJkYWViOGRkN2Y0MzkyNzc3ODMwYjI3MTRjYWFmZDFmIn19fQ==";
|
||||
public static final String GUI_MODE_INPUT = "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNWM5OWRmYjI3MDRlMWJkNmU3ZmFjZmI0M2IzZTZmYmFiYWYxNmViYzdlMWZhYjA3NDE3YTZjNDY0ZTFkIn19fQ==";
|
||||
public static final String GUI_MODE_OUTPUT = "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvY2JiMWQxN2NlYmM1ZjBlY2M5ODdiODBlZmMwM2UzMmVjYjFjYjQwZGJjNWJjZTJmYWYzZTYwNTQyYTQwIn19fQ==";
|
||||
|
||||
public static final int PAGE_SIZE = 9 * 5;
|
||||
protected final Runnable closeCallback;
|
||||
public boolean ignoreCloseCallback;
|
||||
|
||||
public int page = 0;
|
||||
|
||||
public PagedGui(ServerPlayerEntity player, @Nullable Runnable closeCallback) {
|
||||
super(ScreenHandlerType.GENERIC_9X6, player, false);
|
||||
this.closeCallback = closeCallback;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClose() {
|
||||
if (this.closeCallback != null && !ignoreCloseCallback) {
|
||||
this.closeCallback.run();
|
||||
}
|
||||
}
|
||||
|
||||
protected void nextPage() {
|
||||
this.page = Math.min(this.getPageAmount() - 1, this.page + 1);
|
||||
this.updateDisplay();
|
||||
}
|
||||
|
||||
protected boolean canNextPage() {
|
||||
return this.getPageAmount() > this.page + 1;
|
||||
}
|
||||
|
||||
protected void previousPage() {
|
||||
this.page = Math.max(0, this.page - 1);
|
||||
this.updateDisplay();
|
||||
}
|
||||
|
||||
protected boolean canPreviousPage() {
|
||||
return this.page - 1 >= 0;
|
||||
}
|
||||
|
||||
public void updateDisplay() {
|
||||
var offset = page * PAGE_SIZE;
|
||||
|
||||
for (int i = 0; i < PAGE_SIZE; i++) {
|
||||
var element = this.getElement(offset + i);
|
||||
|
||||
if (element == null) {
|
||||
element = DisplayElement.empty();
|
||||
}
|
||||
|
||||
if (element.element() != null) {
|
||||
this.setSlot(i, element.element());
|
||||
} else if (element.slot() != null) {
|
||||
this.setSlotRedirect(i, element.slot());
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < 9; i++) {
|
||||
var navElement = this.getNavElement(i);
|
||||
|
||||
if (navElement == null) {
|
||||
navElement = DisplayElement.EMPTY;
|
||||
}
|
||||
|
||||
if (navElement.element != null) {
|
||||
this.setSlot(i + PAGE_SIZE, navElement.element);
|
||||
} else if (navElement.slot != null) {
|
||||
this.setSlotRedirect(i + PAGE_SIZE, navElement.slot);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract int getPageAmount();
|
||||
|
||||
protected abstract DisplayElement getElement(int id);
|
||||
|
||||
protected DisplayElement getNavElement(int id) {
|
||||
return switch (id) {
|
||||
case 0 -> DisplayElement.previousPage(this);
|
||||
case 1 -> this.search();
|
||||
case 2 -> this.sorting();
|
||||
case 3 -> this.refresh();
|
||||
case 4 -> this.storeAll();
|
||||
case 5 -> this.settings();
|
||||
case 6 -> this.crafting();
|
||||
case 7 -> DisplayElement.nextPage(this);
|
||||
case 8 -> DisplayElement.of(
|
||||
new GuiElementBuilder(Items.STRUCTURE_VOID)
|
||||
.setName(Text.translatable(this.closeCallback != null ? "gui.back" : "mco.selectServer.close").formatted(Formatting.RED))
|
||||
.hideDefaultTooltip().noDefaults()
|
||||
.setCallback((i, clickType, slotActionType) -> {
|
||||
playClickSound(this.player);
|
||||
this.close();
|
||||
})
|
||||
);
|
||||
default -> DisplayElement.filler();
|
||||
};
|
||||
}
|
||||
|
||||
protected DisplayElement refresh() {
|
||||
return DisplayElement.filler();
|
||||
}
|
||||
|
||||
protected DisplayElement crafting() {
|
||||
return DisplayElement.filler();
|
||||
}
|
||||
|
||||
protected DisplayElement search(){
|
||||
return DisplayElement.filler();
|
||||
}
|
||||
|
||||
protected DisplayElement sorting(){
|
||||
return DisplayElement.filler();
|
||||
}
|
||||
|
||||
protected DisplayElement storeAll(){
|
||||
return DisplayElement.filler();
|
||||
}
|
||||
|
||||
protected DisplayElement settings(){
|
||||
return DisplayElement.filler();
|
||||
}
|
||||
|
||||
|
||||
public record DisplayElement(@Nullable GuiElementInterface element, @Nullable Slot slot) {
|
||||
private static final DisplayElement EMPTY = DisplayElement.of(new GuiElement(ItemStack.EMPTY, GuiElementInterface.EMPTY_CALLBACK));
|
||||
private static final DisplayElement FILLER = DisplayElement.of(
|
||||
new GuiElementBuilder(Items.WHITE_STAINED_GLASS_PANE)
|
||||
.setName(Text.empty())
|
||||
.hideTooltip()
|
||||
);
|
||||
|
||||
public static DisplayElement of(GuiElementInterface element) {
|
||||
return new DisplayElement(element, null);
|
||||
}
|
||||
|
||||
public static DisplayElement of(GuiElementBuilderInterface<?> element) {
|
||||
return new DisplayElement(element.build(), null);
|
||||
}
|
||||
|
||||
public static DisplayElement of(Slot slot) {
|
||||
return new DisplayElement(null, slot);
|
||||
}
|
||||
|
||||
public static DisplayElement nextPage(PagedGui gui) {
|
||||
if (gui.canNextPage()) {
|
||||
return DisplayElement.of(
|
||||
new GuiElementBuilder(Items.PLAYER_HEAD)
|
||||
.setName(Text.translatable("createWorld.customize.custom.next").formatted(Formatting.WHITE))
|
||||
.hideDefaultTooltip().noDefaults()
|
||||
.setSkullOwner(GUI_NEXT_PAGE)
|
||||
.setCallback((x, y, z) -> {
|
||||
playClickSound(gui.player);
|
||||
gui.nextPage();
|
||||
})
|
||||
);
|
||||
} else {
|
||||
return DisplayElement.of(
|
||||
new GuiElementBuilder(Items.PLAYER_HEAD)
|
||||
.setName(Text.translatable("createWorld.customize.custom.next").formatted(Formatting.DARK_GRAY))
|
||||
.hideDefaultTooltip().noDefaults()
|
||||
.setSkullOwner(GUI_NEXT_PAGE_BLOCKED)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
public static DisplayElement previousPage(PagedGui gui) {
|
||||
if (gui.canPreviousPage()) {
|
||||
return DisplayElement.of(
|
||||
new GuiElementBuilder(Items.PLAYER_HEAD)
|
||||
.setName(Text.translatable("createWorld.customize.custom.prev").formatted(Formatting.WHITE))
|
||||
.hideDefaultTooltip().noDefaults()
|
||||
.setSkullOwner(GUI_PREVIOUS_PAGE)
|
||||
.setCallback((x, y, z) -> {
|
||||
playClickSound(gui.player);
|
||||
gui.previousPage();
|
||||
})
|
||||
);
|
||||
} else {
|
||||
return DisplayElement.of(
|
||||
new GuiElementBuilder(Items.PLAYER_HEAD)
|
||||
.setName(Text.translatable("createWorld.customize.custom.prev").formatted(Formatting.DARK_GRAY))
|
||||
.hideDefaultTooltip().noDefaults()
|
||||
.setSkullOwner(GUI_PREVIOUS_PAGE_BLOCKED)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
public static DisplayElement filler() {
|
||||
return FILLER;
|
||||
}
|
||||
|
||||
public static DisplayElement empty() {
|
||||
return EMPTY;
|
||||
}
|
||||
}
|
||||
|
||||
public static void playClickSound(ServerPlayerEntity player) {
|
||||
player.playSoundToPlayer(SoundEvents.UI_BUTTON_CLICK.value(), SoundCategory.MASTER, 1, 1);
|
||||
}
|
||||
}
|
222
src/main/java/systems/brn/serverstorage/lib/StorageNetwork.java
Normal file
222
src/main/java/systems/brn/serverstorage/lib/StorageNetwork.java
Normal file
@@ -0,0 +1,222 @@
|
||||
package systems.brn.serverstorage.lib;
|
||||
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.block.entity.*;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Direction;
|
||||
import net.minecraft.world.World;
|
||||
import systems.brn.serverstorage.blockentities.HardDriveContainerBlockEntity;
|
||||
import systems.brn.serverstorage.blockentities.InventoryInterfaceBlockEntity;
|
||||
import systems.brn.serverstorage.blockentities.StorageInterfaceBlockEntity;
|
||||
import systems.brn.serverstorage.blocks.BusConnectorBlock;
|
||||
import systems.brn.serverstorage.blocks.HardDriveContainerBlock;
|
||||
import systems.brn.serverstorage.blocks.InventoryInterfaceBlock;
|
||||
import systems.brn.serverstorage.blocks.StorageInterfaceBlock;
|
||||
import systems.brn.serverstorage.items.HardDrive;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import static systems.brn.serverstorage.ServerStorage.DRIVES;
|
||||
import static systems.brn.serverstorage.blocks.BusConnectorBlock.*;
|
||||
import static systems.brn.serverstorage.lib.StorageOperations.*;
|
||||
|
||||
public class StorageNetwork {
|
||||
public List<HardDriveContainerBlockEntity> driveContainers;
|
||||
public List<StorageInterfaceBlockEntity> storageInterfaceBlockEntities;
|
||||
public List<InventoryInterfaceBlockEntity> inventoryInterfaceBlockEntities;
|
||||
public List<HardDrive> drives;
|
||||
public Map<ItemStack, Integer> itemStackMap;
|
||||
public Map<ItemStack, Integer> filteredItemStackMap;
|
||||
|
||||
public final World world;
|
||||
public final BlockPos startPos;
|
||||
public boolean sortAlphabetically;
|
||||
public String searchString;
|
||||
|
||||
public int driveContainerCount;
|
||||
public int drivesCount;
|
||||
public int driveTotalSlots;
|
||||
public int driveUsedSlots;
|
||||
public int driveFreeSlots;
|
||||
|
||||
public StorageNetwork(World world, BlockPos startPos, boolean sortAlphabetically, String searchString) {
|
||||
this.world = world;
|
||||
this.startPos = startPos;
|
||||
this.sortAlphabetically = sortAlphabetically;
|
||||
this.searchString = searchString;
|
||||
reindexNetwork();
|
||||
}
|
||||
|
||||
public void reindexNetwork() {
|
||||
List<HardDriveContainerBlockEntity> driveContainers = new ArrayList<>();
|
||||
List<StorageInterfaceBlockEntity> storageInterfaceBlockEntities = new ArrayList<>();
|
||||
List<InventoryInterfaceBlockEntity> inventoryInterfaceBlockEntities = new ArrayList<>();
|
||||
List<HardDrive> drives = new ArrayList<>();
|
||||
Set<BlockPos> visited = new HashSet<>();
|
||||
|
||||
scan(world, startPos, startPos, driveContainers, storageInterfaceBlockEntities, inventoryInterfaceBlockEntities, drives, visited);
|
||||
|
||||
this.driveContainers = driveContainers;
|
||||
this.drives = drives;
|
||||
this.storageInterfaceBlockEntities = storageInterfaceBlockEntities;
|
||||
this.inventoryInterfaceBlockEntities = inventoryInterfaceBlockEntities;
|
||||
|
||||
countStuff();
|
||||
|
||||
filteredItemStackMap = getCombinedMap(sortAlphabetically, searchString);
|
||||
}
|
||||
|
||||
private void countStuff() {
|
||||
driveUsedSlots = 0;
|
||||
driveFreeSlots = 0;
|
||||
driveTotalSlots = 0;
|
||||
driveContainerCount = driveContainers.size();
|
||||
drivesCount = drives.size();
|
||||
for (HardDriveContainerBlockEntity driveContainer : this.driveContainers) {
|
||||
driveFreeSlots += driveContainer.getAvailableSlots();
|
||||
driveUsedSlots += driveContainer.getUsedSlots();
|
||||
driveTotalSlots += driveContainer.getTotalSlots();
|
||||
}
|
||||
}
|
||||
|
||||
public void updateDisplays(){
|
||||
for (StorageInterfaceBlockEntity storageInterfaceBlockEntity : storageInterfaceBlockEntities) {
|
||||
storageInterfaceBlockEntity.updateDisplays();
|
||||
}
|
||||
}
|
||||
|
||||
public ItemStack findSimilarStack(ItemStack stack){
|
||||
if (!stack.isEmpty()) {
|
||||
for (Map.Entry<ItemStack, Integer> entry : filteredItemStackMap.entrySet()) {
|
||||
if(canCombine(entry.getKey(), stack)){
|
||||
ItemStack stackCopy = entry.getKey().copy();
|
||||
stackCopy.setCount(entry.getValue());
|
||||
return stackCopy;
|
||||
}
|
||||
}
|
||||
}
|
||||
return stack;
|
||||
}
|
||||
|
||||
private static void scan(World world, BlockPos pos, BlockPos startPos, List<HardDriveContainerBlockEntity> driveContainers, List<StorageInterfaceBlockEntity> storageInterfaceBlockEntities, List<InventoryInterfaceBlockEntity> inventoryInterfaceBlockEntities, List<HardDrive> drives, Set<BlockPos> visited) {
|
||||
if (visited.contains(pos)) {
|
||||
return;
|
||||
}
|
||||
visited.add(pos);
|
||||
|
||||
BlockState blockState = world.getBlockState(pos);
|
||||
|
||||
Block block = blockState.getBlock();
|
||||
|
||||
if (block instanceof HardDriveContainerBlock) {
|
||||
BlockEntity blockEntity = world.getBlockEntity(pos);
|
||||
if (blockEntity instanceof HardDriveContainerBlockEntity driveContainerBlockEntity) {
|
||||
driveContainers.add(driveContainerBlockEntity);
|
||||
driveContainerBlockEntity.indexDrives();
|
||||
drives.addAll(driveContainerBlockEntity.drives);
|
||||
}
|
||||
}
|
||||
|
||||
if (block instanceof StorageInterfaceBlock) {
|
||||
BlockEntity blockEntity = world.getBlockEntity(pos);
|
||||
if (blockEntity instanceof StorageInterfaceBlockEntity storageInterfaceBlockEntity){
|
||||
storageInterfaceBlockEntities.add(storageInterfaceBlockEntity);
|
||||
}
|
||||
}
|
||||
|
||||
if (block instanceof InventoryInterfaceBlock) {
|
||||
BlockEntity blockEntity = world.getBlockEntity(pos);
|
||||
if (blockEntity instanceof InventoryInterfaceBlockEntity inventoryInterfaceBlockEntity){
|
||||
inventoryInterfaceBlockEntities.add(inventoryInterfaceBlockEntity);
|
||||
}
|
||||
}
|
||||
|
||||
if (block instanceof BusConnectorBlock || pos == startPos) {
|
||||
|
||||
if (blockState.getOrEmpty(NORTH).isPresent() && blockState.get(NORTH) == ConnectionType.BUS) {
|
||||
BlockPos nextPos = pos.offset(Direction.NORTH);
|
||||
scan(world, nextPos, startPos, driveContainers, storageInterfaceBlockEntities, inventoryInterfaceBlockEntities, drives, visited);
|
||||
}
|
||||
if (blockState.getOrEmpty(SOUTH).isPresent() && blockState.get(SOUTH) == ConnectionType.BUS) {
|
||||
BlockPos nextPos = pos.offset(Direction.SOUTH);
|
||||
scan(world, nextPos, startPos, driveContainers, storageInterfaceBlockEntities, inventoryInterfaceBlockEntities, drives, visited);
|
||||
}
|
||||
if (blockState.getOrEmpty(EAST).isPresent() && blockState.get(EAST) == ConnectionType.BUS) {
|
||||
BlockPos nextPos = pos.offset(Direction.EAST);
|
||||
scan(world, nextPos, startPos, driveContainers, storageInterfaceBlockEntities, inventoryInterfaceBlockEntities, drives, visited);
|
||||
}
|
||||
if (blockState.getOrEmpty(WEST).isPresent() && blockState.get(WEST) == ConnectionType.BUS) {
|
||||
BlockPos nextPos = pos.offset(Direction.WEST);
|
||||
scan(world, nextPos, startPos, driveContainers, storageInterfaceBlockEntities, inventoryInterfaceBlockEntities, drives, visited);
|
||||
}
|
||||
if (blockState.getOrEmpty(UP).isPresent() && blockState.get(UP) == ConnectionType.BUS) {
|
||||
BlockPos nextPos = pos.offset(Direction.UP);
|
||||
scan(world, nextPos, startPos, driveContainers, storageInterfaceBlockEntities, inventoryInterfaceBlockEntities, drives, visited);
|
||||
}
|
||||
if (blockState.getOrEmpty(DOWN).isPresent() && blockState.get(DOWN) == ConnectionType.BUS) {
|
||||
BlockPos nextPos = pos.offset(Direction.DOWN);
|
||||
scan(world, nextPos, startPos, driveContainers, storageInterfaceBlockEntities, inventoryInterfaceBlockEntities, drives, visited);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Modify getCombinedInventoryFromChests to include item metadata and combine stacks
|
||||
private TreeMap<ItemStack, Integer> getCombinedMap(boolean sortAlphabetically, String query) {
|
||||
itemStackMap = new HashMap<>();
|
||||
for (HardDrive drive : drives) {
|
||||
itemStackMap = drive.addToMap(itemStackMap);
|
||||
}
|
||||
return sortAndFilterMap(itemStackMap, sortAlphabetically, query);
|
||||
}
|
||||
|
||||
|
||||
public int putItemStackRemainder(ItemStack stack) {
|
||||
if (DRIVES.contains(stack.getItem())){
|
||||
return stack.getCount();
|
||||
}
|
||||
// Iterate over each chest to try and insert the ItemStack
|
||||
int leftOvers = stack.getCount();
|
||||
for (InventoryInterfaceBlockEntity inventoryInterfaceBlockEntity : inventoryInterfaceBlockEntities) {
|
||||
leftOvers = inventoryInterfaceBlockEntity.processIncoming(stack.copy(), leftOvers);
|
||||
if (leftOvers <= 0) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
ItemStack driveStack = stack.copy();
|
||||
driveStack.setCount(leftOvers);
|
||||
for (HardDrive drive : drives) {
|
||||
driveStack = drive.insertStackIntoInventory(driveStack);
|
||||
if (driveStack.isEmpty()) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// If we still have remaining items, return false
|
||||
return driveStack.getCount();
|
||||
}
|
||||
|
||||
public boolean canAddItemStack(ItemStack stack) {
|
||||
return stack.getCount() <= driveFreeSlots && !DRIVES.contains(stack.getItem());
|
||||
}
|
||||
|
||||
public boolean canRemove(ItemStack stackToRemove) {
|
||||
|
||||
return canRemoveRemainingCount(stackToRemove, itemStackMap) == 0;
|
||||
}
|
||||
|
||||
public ItemStack removeItemStack(ItemStack stackToRemove) {
|
||||
ItemStack outStack = stackToRemove.copy();
|
||||
|
||||
for (HardDrive drive : drives) {
|
||||
ItemStack removedStack = drive.removeStackFromInventoryRemains(outStack);
|
||||
if (removedStack.getCount() <= 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// If we still have remaining items, return false
|
||||
return outStack;
|
||||
}
|
||||
}
|
@@ -0,0 +1,206 @@
|
||||
package systems.brn.serverstorage.lib;
|
||||
|
||||
import net.minecraft.entity.player.PlayerInventory;
|
||||
import net.minecraft.inventory.Inventory;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.TreeMap;
|
||||
|
||||
public class StorageOperations {
|
||||
// Modify getSimpleInventory to include item metadata and sort conditionally
|
||||
public static TreeMap<ItemStack, Integer> sortAndFilterMap(Map<ItemStack, Integer> itemStackMap, boolean sortAlphabetically, String query) {
|
||||
TreeMap<ItemStack, Integer> sortedMap = getItemStackIntegerTreeMap(itemStackMap, sortAlphabetically);
|
||||
|
||||
if (query == null || query.isEmpty() || query.equals("*")) {
|
||||
sortedMap.putAll(itemStackMap);
|
||||
} else {
|
||||
Map<ItemStack, Integer> filteredMap = new HashMap<>();
|
||||
for (Map.Entry<ItemStack, Integer> entry : itemStackMap.entrySet()) {
|
||||
if (filterItem(entry.getKey().getItem(), query)){
|
||||
filteredMap.put(entry.getKey(), entry.getValue());
|
||||
}
|
||||
}
|
||||
sortedMap.putAll(filteredMap);
|
||||
}
|
||||
return sortedMap;
|
||||
}
|
||||
|
||||
public static boolean filterItem(Item item, String query){
|
||||
if (item != null) {
|
||||
String itemName = String.valueOf(item);
|
||||
return itemName == null || itemName.contains(query);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static @NotNull TreeMap<ItemStack, Integer> getItemStackIntegerTreeMap(Map<ItemStack, Integer> itemStackMap, boolean sortAlphabetically) {
|
||||
TreeMap<ItemStack, Integer> sortedMap;
|
||||
|
||||
if (sortAlphabetically) {
|
||||
// Sort alphabetically by item name
|
||||
sortedMap = new TreeMap<>((o1, o2) -> {
|
||||
String name1 = String.valueOf(o1.getItem());
|
||||
String name2 = String.valueOf(o2.getItem());
|
||||
return name1.compareToIgnoreCase(name2);
|
||||
});
|
||||
} else {
|
||||
// Sort by count in descending order
|
||||
sortedMap = new TreeMap<>((o1, o2) -> {
|
||||
int count1 = itemStackMap.get(o1);
|
||||
int count2 = itemStackMap.get(o2);
|
||||
int countCompare = Integer.compare(count2, count1);
|
||||
// If counts are equal, compare items alphabetically by name
|
||||
return countCompare == 0 ? String.valueOf(o1.getItem()).compareToIgnoreCase(String.valueOf(o2.getItem())) : countCompare;
|
||||
});
|
||||
}
|
||||
return sortedMap;
|
||||
}
|
||||
|
||||
public static int canInsertToStack(ItemStack stack1, ItemStack stack2, int maxInsert) {
|
||||
if (stack1.isEmpty() || ItemStack.areItemsEqual(stack1, stack2)) {
|
||||
int remainingSpace = stack1.isEmpty() ? stack2.getMaxCount() : stack1.getMaxCount() - stack1.getCount();
|
||||
maxInsert += remainingSpace;
|
||||
// If the maximum insertion count is greater than or equal to the item count, return the item count
|
||||
if (maxInsert >= stack2.getCount()) {
|
||||
return stack2.getCount();
|
||||
}
|
||||
}
|
||||
return maxInsert;
|
||||
}
|
||||
|
||||
public static int canInsertItemIntoInventory(Inventory inventory, ItemStack itemStack) {
|
||||
// Get the player's inventory
|
||||
int maxInsert = 0;
|
||||
|
||||
if (inventory instanceof PlayerInventory playerInventory) {
|
||||
// Iterate through the slots in the player's inventory
|
||||
for (int i = 0; i < playerInventory.main.size(); i++) {
|
||||
ItemStack slotStack = playerInventory.main.get(i);
|
||||
maxInsert = canInsertToStack(slotStack, itemStack, maxInsert);
|
||||
}
|
||||
} else {
|
||||
for (int i = 0; i < inventory.size(); i++) {
|
||||
ItemStack slotStack = inventory.getStack(i);
|
||||
maxInsert = canInsertToStack(slotStack, itemStack, maxInsert);
|
||||
}
|
||||
}
|
||||
|
||||
return maxInsert; // Return the maximum insertion count
|
||||
}
|
||||
|
||||
public static ItemStack insertStackIntoInventory(Inventory inventory, ItemStack stack) {
|
||||
// First, try to merge with existing stacks
|
||||
for (int i = 0; i < inventory.size(); i++) {
|
||||
ItemStack slotStack = inventory.getStack(i);
|
||||
if (canCombine(slotStack, stack)) {
|
||||
int transferAmount = Math.min(stack.getCount(), slotStack.getMaxCount() - slotStack.getCount());
|
||||
if (transferAmount > 0) {
|
||||
slotStack.increment(transferAmount);
|
||||
stack.decrement(transferAmount);
|
||||
inventory.markDirty();
|
||||
if (stack.isEmpty()) {
|
||||
return ItemStack.EMPTY;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Next, try to find an empty slot
|
||||
for (int i = 0; i < inventory.size(); i++) {
|
||||
ItemStack slotStack = inventory.getStack(i);
|
||||
if (slotStack.isEmpty()) {
|
||||
inventory.setStack(i, stack.copy());
|
||||
stack.setCount(0);
|
||||
inventory.markDirty();
|
||||
return ItemStack.EMPTY;
|
||||
}
|
||||
}
|
||||
|
||||
return stack;
|
||||
}
|
||||
|
||||
public static void removeFromInventory(Inventory inventory, ItemStack stackToRemove, int remainingToRemove) {
|
||||
for (int i = 0; i < inventory.size(); i++) {
|
||||
ItemStack slotStack = inventory.getStack(i);
|
||||
if (canCombine(slotStack, stackToRemove)) {
|
||||
int removeAmount = Math.min(slotStack.getCount(), remainingToRemove);
|
||||
slotStack.decrement(removeAmount);
|
||||
remainingToRemove -= removeAmount;
|
||||
inventory.markDirty();
|
||||
|
||||
if (slotStack.isEmpty()) {
|
||||
inventory.setStack(i, ItemStack.EMPTY);
|
||||
}
|
||||
|
||||
if (remainingToRemove <= 0) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static int howMuchFits(ItemStack stack, Inventory inventory){
|
||||
int out = 0;
|
||||
for (int i = 0; i < inventory.size(); i++) {
|
||||
ItemStack slotStack = inventory.getStack(i);
|
||||
if (slotStack.isEmpty()) {
|
||||
out += stack.getMaxCount();
|
||||
continue;
|
||||
}
|
||||
if (canCombine(slotStack, stack)) {
|
||||
int remaining = slotStack.getMaxCount() - slotStack.getCount();
|
||||
out += remaining;
|
||||
}
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
public static int canRemoveRemainingCount(ItemStack stackToRemove, Map<ItemStack, Integer> itemsMap) {
|
||||
int remainingToRemove = stackToRemove.getCount();
|
||||
|
||||
for (Map.Entry<ItemStack, Integer> entry : itemsMap.entrySet()) {
|
||||
ItemStack slotStack = entry.getKey();
|
||||
if (canCombine(slotStack, stackToRemove)) {
|
||||
// If the slot contains the same item type
|
||||
if (entry.getValue() >= remainingToRemove) {
|
||||
// If the count in the slot is sufficient to remove the requested amount
|
||||
return 0;
|
||||
} else {
|
||||
// If the count in the slot is not sufficient, update remainingToRemove
|
||||
remainingToRemove -= slotStack.getCount();
|
||||
}
|
||||
}
|
||||
}
|
||||
// If no matching stack with sufficient count is found, return false
|
||||
return remainingToRemove;
|
||||
}
|
||||
|
||||
public static boolean canCombine(ItemStack stack1, ItemStack stack2) {
|
||||
return !stack1.isEmpty() && stack1.getItem() == stack2.getItem() && ItemStack.areItemsAndComponentsEqual(stack1, stack2);
|
||||
}
|
||||
|
||||
public static void addInventoryToMap(Inventory inventory, Map<ItemStack, Integer> itemStackMap) {
|
||||
for (int i = 0; i < inventory.size(); i++) {
|
||||
ItemStack stack = inventory.getStack(i);
|
||||
if (!stack.isEmpty()) {
|
||||
addToMap(itemStackMap, stack);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void addToMap(Map<ItemStack, Integer> itemStackMap, ItemStack stack) {
|
||||
for (Map.Entry<ItemStack, Integer> entry : itemStackMap.entrySet()) {
|
||||
ItemStack existingStack = entry.getKey();
|
||||
if (ItemStack.areItemsAndComponentsEqual(stack, existingStack)) {
|
||||
int newCount = entry.getValue() + stack.getCount();
|
||||
entry.setValue(newCount);
|
||||
return;
|
||||
}
|
||||
}
|
||||
itemStackMap.put(stack.copy(), stack.getCount());
|
||||
}
|
||||
}
|
171
src/main/java/systems/brn/serverstorage/lib/Util.java
Normal file
171
src/main/java/systems/brn/serverstorage/lib/Util.java
Normal file
@@ -0,0 +1,171 @@
|
||||
package systems.brn.serverstorage.lib;
|
||||
|
||||
import net.minecraft.component.DataComponentTypes;
|
||||
import net.minecraft.component.type.LoreComponent;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.recipe.*;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.text.RawFilteredPair;
|
||||
import net.minecraft.text.Style;
|
||||
import net.minecraft.text.Text;
|
||||
import net.minecraft.util.Formatting;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class Util {
|
||||
|
||||
public static List<RawFilteredPair<Text>> generateBookContent(Map<ItemStack, Integer> itemMap) {
|
||||
List<String> pages = new ArrayList<>();
|
||||
for (Map.Entry<ItemStack, Integer> entry : itemMap.entrySet()) {
|
||||
ItemStack slotStack = entry.getKey();
|
||||
if (!slotStack.isEmpty()) {
|
||||
Item itemName = slotStack.getItem();
|
||||
pages.add(itemName + " " + entry.getValue());
|
||||
}
|
||||
}
|
||||
return stringToBookContent(String.join(System.lineSeparator(), pages));
|
||||
}
|
||||
|
||||
public static List<RawFilteredPair<Text>> stringToBookContent(String string) {
|
||||
List<RawFilteredPair<Text>> pages = new ArrayList<>();
|
||||
List<String> lines = new ArrayList<>();
|
||||
String[] words = string.split("\\s+");
|
||||
|
||||
StringBuilder currentLine = new StringBuilder();
|
||||
for (String word : words) {
|
||||
if (currentLine.length() + word.length() + 1 <= 21) { // Max line length in Minecraft
|
||||
currentLine.append(word).append(" ");
|
||||
} else {
|
||||
lines.add(currentLine.toString().trim());
|
||||
currentLine = new StringBuilder(word + " ");
|
||||
}
|
||||
}
|
||||
lines.add(currentLine.toString().trim());
|
||||
|
||||
List<String> pageContent = new ArrayList<>();
|
||||
for (int i = 0; i < lines.size(); i++) {
|
||||
if (i % 14 == 0 && i != 0) { // Max lines per page in Minecraft
|
||||
pages.add(RawFilteredPair.of(Text.literal(String.join("\n", pageContent))));
|
||||
pageContent.clear();
|
||||
}
|
||||
pageContent.add(lines.get(i));
|
||||
}
|
||||
if (!pageContent.isEmpty()) {
|
||||
pages.add(RawFilteredPair.of(Text.literal(String.join("\n", pageContent))));
|
||||
}
|
||||
|
||||
return pages;
|
||||
}
|
||||
|
||||
public static ItemStack addCountToLore(final int count, ItemStack stack, String name) {
|
||||
if (count > 0) {
|
||||
ItemStack newStack = stack.copy();
|
||||
LoreComponent lore = stack.get(DataComponentTypes.LORE);
|
||||
name = name != null ? name : "Amount: ";
|
||||
Text countLine = Text.literal(name + count).setStyle(Style.EMPTY.withColor(Formatting.GOLD).withItalic(true));
|
||||
|
||||
LoreComponent newLore;
|
||||
if (lore == null) {
|
||||
List<Text> loreList = new ArrayList<>();
|
||||
loreList.addFirst(countLine);
|
||||
newLore = new LoreComponent(loreList);
|
||||
} else {
|
||||
List<Text> newLines = new ArrayList<>(lore.lines());
|
||||
newLines.addFirst(countLine);
|
||||
newLore = new LoreComponent(newLines);
|
||||
}
|
||||
newStack.set(DataComponentTypes.LORE, newLore);
|
||||
return newStack;
|
||||
} else {
|
||||
return stack;
|
||||
}
|
||||
}
|
||||
|
||||
public static ItemStack removeCountFromLore(ItemStack stack) {
|
||||
LoreComponent oldLore = stack.get(DataComponentTypes.LORE);
|
||||
|
||||
if (oldLore != null) {
|
||||
ItemStack newStack = stack.copy();
|
||||
List<Text> filteredLines = oldLore.lines().stream()
|
||||
.filter(line -> !line.getString().matches("Amount: \\d+"))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
LoreComponent newLore = new LoreComponent(filteredLines);
|
||||
|
||||
newStack.set(DataComponentTypes.LORE, newLore);
|
||||
return newStack;
|
||||
} else {
|
||||
return stack;
|
||||
}
|
||||
}
|
||||
|
||||
public static ArrayList<CraftingEntry> getCraftableRecipes(Map<ItemStack, Integer> itemStackMap, MinecraftServer server) {
|
||||
RecipeManager recipeManager = server.getRecipeManager();
|
||||
List<RecipeEntry<CraftingRecipe>> allRecipes = recipeManager.listAllOfType(RecipeType.CRAFTING);
|
||||
|
||||
ArrayList<CraftingEntry> craftingEntries = new ArrayList<>();
|
||||
|
||||
for (RecipeEntry<CraftingRecipe> recipe : allRecipes) {
|
||||
int maxAmount = Integer.MAX_VALUE;
|
||||
boolean canMake = true;
|
||||
HashMap<ItemStack, Integer> finalInputs = new HashMap<>();
|
||||
Map<Item, Integer> ingredientCounts = new HashMap<>();
|
||||
|
||||
// Count the occurrences of each ingredient in the recipe
|
||||
for (Ingredient ingredient : recipe.value().getIngredients()) {
|
||||
for (ItemStack stack : ingredient.getMatchingStacks()) {
|
||||
if (stack.isEmpty()) continue;
|
||||
ingredientCounts.put(stack.getItem(), ingredientCounts.getOrDefault(stack.getItem(), 0) + 1);
|
||||
}
|
||||
}
|
||||
|
||||
boolean usesAnyIngredient = false;
|
||||
|
||||
for (Ingredient ingredient : recipe.value().getIngredients()) {
|
||||
int totalAvailable = 0;
|
||||
HashMap<ItemStack, Integer> inputsTemp = new HashMap<>();
|
||||
|
||||
for (ItemStack stack : ingredient.getMatchingStacks()) {
|
||||
if (stack.isEmpty()) continue;
|
||||
for (Map.Entry<ItemStack, Integer> entry : itemStackMap.entrySet()) {
|
||||
ItemStack inventoryStack = entry.getKey();
|
||||
int inventoryCount = entry.getValue();
|
||||
|
||||
if (ItemStack.areItemsEqual(stack, inventoryStack)) {
|
||||
totalAvailable += inventoryCount;
|
||||
inputsTemp.put(stack, inventoryCount);
|
||||
usesAnyIngredient = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (totalAvailable == 0) {
|
||||
canMake = false;
|
||||
break;
|
||||
}
|
||||
|
||||
int requiredCount = ingredient.getMatchingStacks()[0].getCount();
|
||||
int occurrences = ingredientCounts.get(ingredient.getMatchingStacks()[0].getItem());
|
||||
maxAmount = Math.min(maxAmount, totalAvailable / (requiredCount * occurrences));
|
||||
|
||||
for (Map.Entry<ItemStack, Integer> entry : inputsTemp.entrySet()) {
|
||||
ItemStack stackIn = entry.getKey();
|
||||
int count = entry.getValue();
|
||||
finalInputs.put(stackIn, count);
|
||||
}
|
||||
}
|
||||
|
||||
if (canMake && maxAmount > 0 && usesAnyIngredient) {
|
||||
ItemStack outputItem = recipe.value().getResult(server.getRegistryManager()).copy();
|
||||
CraftingEntry finalEntry = new CraftingEntry(outputItem, recipe, finalInputs, maxAmount);
|
||||
craftingEntries.add(finalEntry);
|
||||
}
|
||||
}
|
||||
return craftingEntries;
|
||||
}
|
||||
}
|
@@ -0,0 +1,92 @@
|
||||
package systems.brn.serverstorage.screenhandlers;
|
||||
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.entity.player.PlayerInventory;
|
||||
import net.minecraft.inventory.Inventory;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.screen.ScreenHandler;
|
||||
import net.minecraft.screen.ScreenHandlerType;
|
||||
import net.minecraft.screen.slot.Slot;
|
||||
import systems.brn.serverstorage.blockentities.HardDriveContainerBlockEntity;
|
||||
import systems.brn.serverstorage.lib.HardDriveSlot;
|
||||
|
||||
public class DriveContainerScreenHandler extends ScreenHandler {
|
||||
private final Inventory inventory;
|
||||
private final HardDriveContainerBlockEntity blockEntity;
|
||||
|
||||
public DriveContainerScreenHandler(int syncId, PlayerInventory playerInventory, HardDriveContainerBlockEntity blockEntity) {
|
||||
super(ScreenHandlerType.HOPPER, syncId);
|
||||
this.blockEntity = blockEntity;
|
||||
checkSize(blockEntity, HardDriveContainerBlockEntity.INVENTORY_SIZE);
|
||||
this.inventory = blockEntity;
|
||||
blockEntity.indexDrives();
|
||||
blockEntity.commitDrives();
|
||||
inventory.onOpen(playerInventory.player);
|
||||
|
||||
int j;
|
||||
for (j = 0; j < 5; ++j) {
|
||||
this.addSlot(new HardDriveSlot(inventory, j, 44 + j * 18, 20));
|
||||
}
|
||||
|
||||
for (j = 0; j < 3; ++j) {
|
||||
for (int k = 0; k < 9; ++k) {
|
||||
this.addSlot(new Slot(playerInventory, k + j * 9 + 9, 8 + k * 18, j * 18 + 51));
|
||||
}
|
||||
}
|
||||
|
||||
for (j = 0; j < 9; ++j) {
|
||||
this.addSlot(new Slot(playerInventory, j, 8 + j * 18, 109));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canUse(PlayerEntity player) {
|
||||
return this.inventory.canPlayerUse(player);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public ItemStack quickMove(PlayerEntity player, int slot) {
|
||||
ItemStack temp = quickMoveHelper(player, slot);
|
||||
blockEntity.indexDrives();
|
||||
return temp;
|
||||
}
|
||||
|
||||
public ItemStack quickMoveHelper(PlayerEntity player, int slot) {
|
||||
ItemStack itemStack = ItemStack.EMPTY;
|
||||
Slot slot2 = this.slots.get(slot);
|
||||
if (slot2.hasStack()) {
|
||||
ItemStack itemStack2 = slot2.getStack();
|
||||
itemStack = itemStack2.copy();
|
||||
if (slot < this.inventory.size()) {
|
||||
if (!this.insertItem(itemStack2, this.inventory.size(), this.slots.size(), true)) {
|
||||
return ItemStack.EMPTY;
|
||||
}
|
||||
} else if (!this.insertItem(itemStack2, 0, this.inventory.size(), false)) {
|
||||
return ItemStack.EMPTY;
|
||||
}
|
||||
|
||||
if (itemStack2.isEmpty()) {
|
||||
slot2.setStack(ItemStack.EMPTY);
|
||||
} else {
|
||||
slot2.markDirty();
|
||||
}
|
||||
|
||||
if (itemStack2.getCount() == itemStack.getCount()) {
|
||||
return ItemStack.EMPTY;
|
||||
}
|
||||
|
||||
slot2.onTakeItem(player, itemStack2);
|
||||
}
|
||||
|
||||
return itemStack;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClosed(PlayerEntity player) {
|
||||
super.onClosed(player);
|
||||
this.inventory.onClose(player);
|
||||
blockEntity.indexDrives();
|
||||
blockEntity.network.reindexNetwork();
|
||||
}
|
||||
}
|
@@ -0,0 +1,215 @@
|
||||
package systems.brn.serverstorage.screens;
|
||||
|
||||
import eu.pb4.sgui.api.elements.GuiElementBuilder;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.entity.player.PlayerInventory;
|
||||
import net.minecraft.inventory.Inventory;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.recipe.CraftingRecipe;
|
||||
import net.minecraft.recipe.Ingredient;
|
||||
import net.minecraft.recipe.RecipeEntry;
|
||||
import net.minecraft.text.Text;
|
||||
import systems.brn.serverstorage.blockentities.StorageInterfaceBlockEntity;
|
||||
import systems.brn.serverstorage.lib.CraftingEntry;
|
||||
import systems.brn.serverstorage.lib.PagedGui;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
import static systems.brn.serverstorage.lib.StorageOperations.*;
|
||||
import static systems.brn.serverstorage.lib.Util.getCraftableRecipes;
|
||||
|
||||
public class CraftingScreen extends PagedGui {
|
||||
private final StorageScreen storageScreen;
|
||||
private ArrayList<CraftingEntry> craftingEntries;
|
||||
private final StorageInterfaceBlockEntity blockEntity;
|
||||
private ArrayList<DisplayElement> recipesList;
|
||||
|
||||
public CraftingScreen(StorageScreen storageScreen) {
|
||||
super(storageScreen.getPlayer(), null);
|
||||
this.storageScreen = storageScreen;
|
||||
this.blockEntity = storageScreen.blockEntity;
|
||||
this.setTitle(Text.translatable("container.crafting"));
|
||||
this.updateDisplay();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateDisplay() {
|
||||
blockEntity.reindexDrives(); // Use justReindexDrives to avoid looping
|
||||
Map<ItemStack, Integer> itemStackMap = new HashMap<>();
|
||||
addInventoryToMap(storageScreen.getPlayer().getInventory(), itemStackMap);
|
||||
itemStackMap.putAll(blockEntity.network.itemStackMap);
|
||||
Map<ItemStack, Integer> items = sortAndFilterMap(itemStackMap, false, null);
|
||||
this.craftingEntries = getCraftableRecipes(items, Objects.requireNonNull(player.getServer()));
|
||||
this.recipesList = getAvailableRecipes();
|
||||
super.updateDisplay();
|
||||
}
|
||||
|
||||
private ArrayList<DisplayElement> getAvailableRecipes() {
|
||||
ArrayList<DisplayElement> recipes = new ArrayList<>();
|
||||
|
||||
for (CraftingEntry craftingEntry : craftingEntries) {
|
||||
ItemStack stackWithCount = craftingEntry.outputStacks.getFirst().copy();
|
||||
if (stackWithCount.getCount() > stackWithCount.getMaxCount()) {
|
||||
stackWithCount.setCount(stackWithCount.getMaxCount());
|
||||
}
|
||||
recipes.add(
|
||||
DisplayElement.of(new GuiElementBuilder(stackWithCount)
|
||||
.setCallback((i, clickType, slotActionType) -> {
|
||||
playClickSound(player);
|
||||
RecipeEntry<CraftingRecipe> recipeEntry = craftingEntry.recipeEntry;
|
||||
|
||||
// Crafting logic based on click type
|
||||
if (clickType.isLeft) { // put into player inventory
|
||||
if (clickType.shift) { // craft all
|
||||
craftAll(player, recipeEntry, true);
|
||||
} else { // craft one
|
||||
craftOne(player, recipeEntry, true);
|
||||
}
|
||||
} else if (clickType.isRight) { // put back into storage
|
||||
if (clickType.shift) { // craft all
|
||||
craftAll(player, recipeEntry, false);
|
||||
} else { // craft one
|
||||
craftOne(player, recipeEntry, false);
|
||||
}
|
||||
}
|
||||
updateDisplay();
|
||||
})
|
||||
)
|
||||
);
|
||||
}
|
||||
return recipes;
|
||||
}
|
||||
|
||||
private void craftAll(PlayerEntity player, RecipeEntry<CraftingRecipe> recipeEntry, boolean toPlayerInventory) {
|
||||
while (canCraft(recipeEntry)) {
|
||||
if (craftOne(player, recipeEntry, toPlayerInventory)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean canCraft(RecipeEntry<CraftingRecipe> recipeEntry) {
|
||||
blockEntity.reindexDrives();
|
||||
for (Ingredient ingredient : recipeEntry.value().getIngredients()) {
|
||||
if (findMatchingStack(ingredient) == null) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean craftOne(PlayerEntity player, RecipeEntry<CraftingRecipe> recipeEntry, boolean toPlayerInventory) {
|
||||
ArrayList<ItemStack> stacksToRemove = new ArrayList<>();
|
||||
|
||||
// Check and remove ingredients for one crafting operation
|
||||
for (Ingredient ingredient : recipeEntry.value().getIngredients()) {
|
||||
ItemStack stackToRemove = findMatchingStack(ingredient);
|
||||
if (stackToRemove == null) {
|
||||
return false; // Unable to find required ingredient
|
||||
}
|
||||
stacksToRemove.add(stackToRemove);
|
||||
}
|
||||
|
||||
// Remove ingredients from inventory and network
|
||||
for (ItemStack stack : stacksToRemove) {
|
||||
removeItems(stack);
|
||||
}
|
||||
|
||||
// Add crafted item to the appropriate inventory
|
||||
ItemStack outputStack = recipeEntry.value().getResult(storageScreen.getPlayer().getRegistryManager()).copy();
|
||||
|
||||
if (toPlayerInventory) {
|
||||
PlayerInventory playerInventory = player.getInventory();
|
||||
ItemStack insertStack = outputStack.copy();
|
||||
if (canInsertItemIntoInventory(playerInventory, insertStack) == insertStack.getCount()) {
|
||||
playerInventory.insertStack(insertStack);
|
||||
} else {
|
||||
return true; // Inventory full or unable to insert all items
|
||||
}
|
||||
} else {
|
||||
ItemStack insertStack = outputStack.copy();
|
||||
if (this.blockEntity.network.canAddItemStack(insertStack)) {
|
||||
this.blockEntity.network.putItemStackRemainder(insertStack);
|
||||
} else {
|
||||
return true; // Storage full or unable to insert all items
|
||||
}
|
||||
}
|
||||
|
||||
return false; // Crafted one item successfully
|
||||
}
|
||||
|
||||
private ItemStack findMatchingStack(Ingredient ingredient) {
|
||||
// Check player's inventory first
|
||||
PlayerInventory playerInventory = storageScreen.getPlayer().getInventory();
|
||||
for (int i = 0; i < playerInventory.size(); i++) {
|
||||
ItemStack playerStack = playerInventory.getStack(i);
|
||||
if (ingredient.test(playerStack)) {
|
||||
ItemStack stackToRemove = playerStack.copy();
|
||||
for (ItemStack matchingStack : ingredient.getMatchingStacks()){
|
||||
if (matchingStack.getItem() == stackToRemove.getItem()) {
|
||||
stackToRemove.setCount(matchingStack.getCount()); // Set count to ingredient requirement
|
||||
break;
|
||||
}
|
||||
}
|
||||
return stackToRemove;
|
||||
}
|
||||
}
|
||||
|
||||
// Check storage network
|
||||
for (ItemStack stack : ingredient.getMatchingStacks()) {
|
||||
if (this.blockEntity.network.canRemove(stack)) {
|
||||
ItemStack stackToRemove = stack.copy();
|
||||
stackToRemove.setCount(ingredient.getMatchingStacks()[0].getCount()); // Set count to ingredient requirement
|
||||
return stackToRemove;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private void removeItems(ItemStack stack) {
|
||||
ItemStack removedFromStorage = this.blockEntity.network.removeItemStack(stack);
|
||||
ItemStack fromPlayer = stack.copy();
|
||||
fromPlayer.setCount(stack.getCount() - removedFromStorage.getCount());
|
||||
if (fromPlayer.getCount() > 0) {
|
||||
Inventory playerInventory = player.getInventory();
|
||||
for (int i = 0; i < playerInventory.size(); i++) {
|
||||
if (ItemStack.areItemsEqual(playerInventory.getStack(i), fromPlayer)) {
|
||||
playerInventory.removeStack(i, fromPlayer.getCount());
|
||||
break; // Only remove one stack per crafting iteration
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean open() {
|
||||
page = blockEntity.page;
|
||||
this.blockEntity.openCraftingScreens.add(this);
|
||||
blockEntity.updateDisplays();
|
||||
return super.open();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClose() {
|
||||
super.onClose();
|
||||
this.blockEntity.openCraftingScreens.remove(this);
|
||||
storageScreen.open();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getPageAmount() {
|
||||
return Math.ceilDivExact(recipesList.size(), 9 * 6);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected DisplayElement getElement(int id) {
|
||||
if (id >= 0 && id < recipesList.size()) {
|
||||
return recipesList.get(id);
|
||||
} else {
|
||||
return DisplayElement.empty();
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,29 @@
|
||||
package systems.brn.serverstorage.screens;
|
||||
|
||||
import eu.pb4.sgui.api.gui.AnvilInputGui;
|
||||
import eu.pb4.sgui.api.gui.SimpleGui;
|
||||
import systems.brn.serverstorage.blockentities.InventoryInterfaceBlockEntity;
|
||||
|
||||
public class SearchScreen extends AnvilInputGui {
|
||||
|
||||
private final SimpleGui parentScreen;
|
||||
|
||||
public SearchScreen(SimpleGui parentScreen, String defaultText) {
|
||||
super(parentScreen.getPlayer(), parentScreen.getLockPlayerInventory());
|
||||
this.parentScreen = parentScreen;
|
||||
parentScreen.close();
|
||||
this.setDefaultInputValue(defaultText);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClose() {
|
||||
super.onClose();
|
||||
parentScreen.open();
|
||||
String query = this.getInput();
|
||||
if (parentScreen instanceof StorageScreen storageScreen) {
|
||||
storageScreen.doSearch(query);
|
||||
} else if (parentScreen instanceof SettingsScreen settingsScreen && settingsScreen.blockEntity instanceof InventoryInterfaceBlockEntity inventoryInterfaceBlockEntity) {
|
||||
inventoryInterfaceBlockEntity.doSearch(query);
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,93 @@
|
||||
package systems.brn.serverstorage.screens;
|
||||
|
||||
import eu.pb4.sgui.api.elements.GuiElementBuilder;
|
||||
import eu.pb4.sgui.api.gui.SimpleGui;
|
||||
import net.minecraft.block.entity.BlockEntity;
|
||||
import net.minecraft.item.Items;
|
||||
import net.minecraft.server.network.ServerPlayerEntity;
|
||||
import net.minecraft.text.Text;
|
||||
import net.minecraft.util.Formatting;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import systems.brn.serverstorage.blockentities.InventoryInterfaceBlockEntity;
|
||||
import systems.brn.serverstorage.lib.PagedGui;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class SettingsScreen extends PagedGui {
|
||||
|
||||
private final SimpleGui parentScreen;
|
||||
|
||||
private ArrayList<DisplayElement> settingsList;
|
||||
|
||||
public final BlockEntity blockEntity;
|
||||
|
||||
public SettingsScreen(@Nullable SimpleGui parentScreen, ServerPlayerEntity player, BlockEntity blockEntity) {
|
||||
super(player, null);
|
||||
this.parentScreen = parentScreen;
|
||||
this.blockEntity = blockEntity;
|
||||
clearSettings();
|
||||
this.setTitle(Text.translatable("mco.configure.world.buttons.settings"));
|
||||
if (blockEntity instanceof InventoryInterfaceBlockEntity inventoryInterfaceBlockEntity) {
|
||||
inventoryInterfaceBlockEntity.openSettingsScreens.add(this);
|
||||
}
|
||||
this.updateDisplay();
|
||||
}
|
||||
|
||||
public SettingsScreen(StorageScreen parentScreen) {
|
||||
this(parentScreen, parentScreen.getPlayer(), parentScreen.blockEntity);
|
||||
}
|
||||
|
||||
public SettingsScreen(ServerPlayerEntity player, BlockEntity blockEntity) {
|
||||
this(null, player, blockEntity);
|
||||
}
|
||||
|
||||
public void addSetting(DisplayElement setting) {
|
||||
this.settingsList.add(setting);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClose() {
|
||||
super.onClose();
|
||||
if (parentScreen != null) {
|
||||
parentScreen.open();
|
||||
}
|
||||
if (blockEntity instanceof InventoryInterfaceBlockEntity inventoryInterfaceBlockEntity) {
|
||||
inventoryInterfaceBlockEntity.openSettingsScreens.remove(this);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getPageAmount() {
|
||||
return Math.ceilDivExact(settingsList.size(), 9 * 5);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected DisplayElement getElement(int id) {
|
||||
if (id >= 0 && id < settingsList.size()) {
|
||||
return settingsList.get(id);
|
||||
} else {
|
||||
return DisplayElement.empty();
|
||||
}
|
||||
}
|
||||
|
||||
public DisplayElement getItem() {
|
||||
if (settingsList.isEmpty()) {
|
||||
return DisplayElement.filler();
|
||||
} else {
|
||||
return DisplayElement.of(
|
||||
new GuiElementBuilder(Items.PLAYER_HEAD)
|
||||
.setName(Text.translatable("mco.configure.world.settings.title").formatted(Formatting.WHITE))
|
||||
.hideDefaultTooltip().noDefaults()
|
||||
.setSkullOwner(GUI_SETTINGS)
|
||||
.setCallback((x, y, z) -> {
|
||||
playClickSound(getPlayer());
|
||||
this.open();
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
public void clearSettings() {
|
||||
this.settingsList = new ArrayList<>();
|
||||
}
|
||||
}
|
@@ -0,0 +1,253 @@
|
||||
package systems.brn.serverstorage.screens;
|
||||
|
||||
import eu.pb4.sgui.api.ClickType;
|
||||
import eu.pb4.sgui.api.elements.GuiElementBuilder;
|
||||
import eu.pb4.sgui.api.elements.GuiElementInterface;
|
||||
import net.minecraft.entity.player.PlayerInventory;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.item.Items;
|
||||
import net.minecraft.screen.slot.SlotActionType;
|
||||
import net.minecraft.server.network.ServerPlayerEntity;
|
||||
import net.minecraft.text.Text;
|
||||
import net.minecraft.util.Formatting;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.World;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import systems.brn.serverstorage.blockentities.StorageInterfaceBlockEntity;
|
||||
import systems.brn.serverstorage.lib.PagedGui;
|
||||
|
||||
import static systems.brn.serverstorage.ServerStorage.ServerStorage_Crafting_Enable;
|
||||
import static systems.brn.serverstorage.lib.StorageOperations.*;
|
||||
import static systems.brn.serverstorage.lib.Util.addCountToLore;
|
||||
import static systems.brn.serverstorage.lib.Util.removeCountFromLore;
|
||||
|
||||
public class StorageScreen extends PagedGui {
|
||||
private final ServerPlayerEntity player;
|
||||
public final StorageInterfaceBlockEntity blockEntity;
|
||||
|
||||
public StorageScreen(ServerPlayerEntity player, BlockPos pos, @Nullable Runnable closeCallback) {
|
||||
super(player, closeCallback);
|
||||
this.player = player;
|
||||
this.setLockPlayerInventory(false);
|
||||
this.blockEntity = (StorageInterfaceBlockEntity) player.getWorld().getBlockEntity(pos);
|
||||
assert blockEntity != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean open() {
|
||||
page = blockEntity.page;
|
||||
this.blockEntity.openStorageScreens.add(this);
|
||||
blockEntity.updateDisplays();
|
||||
return super.open();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateDisplay() {
|
||||
blockEntity.reindexDrives();
|
||||
String title = blockEntity.network.driveUsedSlots +
|
||||
"u/" +
|
||||
blockEntity.network.driveTotalSlots +
|
||||
"t(" +
|
||||
blockEntity.network.driveFreeSlots +
|
||||
"f)" +
|
||||
"[" +
|
||||
blockEntity.network.driveContainerCount +
|
||||
"c]" +
|
||||
"[" +
|
||||
blockEntity.network.drivesCount +
|
||||
"d]";
|
||||
|
||||
setTitle(Text.of(title));
|
||||
super.updateDisplay();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getPageAmount() {
|
||||
return Math.ceilDivExact(blockEntity.network.filteredItemStackMap.size(), 9 * 5);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected DisplayElement getElement(int id) {
|
||||
if (blockEntity.network.filteredItemStackMap.size() > id) {
|
||||
ItemStack itemStackKey = (ItemStack) blockEntity.network.filteredItemStackMap.keySet().toArray()[id];
|
||||
ItemStack aestheticStack = itemStackKey.copy();
|
||||
int count = blockEntity.network.filteredItemStackMap.get(itemStackKey);
|
||||
aestheticStack.setCount(Math.min(aestheticStack.getMaxCount(), count));
|
||||
ItemStack newStack = addCountToLore(count, aestheticStack, null);
|
||||
GuiElementBuilder guiElement = new GuiElementBuilder(newStack);
|
||||
return DisplayElement.of(guiElement);
|
||||
}
|
||||
return DisplayElement.empty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onClick(int index, ClickType type, SlotActionType action, GuiElementInterface element) {
|
||||
GuiElementInterface clickedElement = getSlot(index);
|
||||
ItemStack cursorStack = getPlayer().currentScreenHandler.getCursorStack();
|
||||
if (clickedElement != null && cursorStack.isEmpty()) {
|
||||
ItemStack clickedItem = clickedElement.getItemStack();
|
||||
ItemStack noLoreStack = removeCountFromLore(clickedItem);
|
||||
noLoreStack = blockEntity.network.findSimilarStack(noLoreStack);
|
||||
if (type.isRight) {
|
||||
if (!type.shift) {
|
||||
noLoreStack.setCount(Math.min(noLoreStack.getMaxCount(), noLoreStack.getCount() / 2)); //half stack
|
||||
} else {
|
||||
for (int i = 0; i < player.getInventory().main.size(); i++) {
|
||||
ItemStack stack = player.getInventory().main.get(i);
|
||||
if (ItemStack.areItemsAndComponentsEqual(stack, noLoreStack)) {
|
||||
insertItem(stack, 0, getVirtualSize(), false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} else if (type.isLeft) {
|
||||
if (noLoreStack.getCount() > noLoreStack.getMaxCount() && !type.shift) {
|
||||
noLoreStack.setCount(noLoreStack.getMaxCount()); // if not shift, get one stack
|
||||
}
|
||||
}
|
||||
if (!(type.isRight && type.shift)) {
|
||||
PlayerInventory playerInventory = player.getInventory();
|
||||
int insertCount = canInsertItemIntoInventory(playerInventory, noLoreStack);
|
||||
ItemStack insertingStack = noLoreStack.copy();
|
||||
insertingStack.setCount(insertCount);
|
||||
blockEntity.refreshTerminals();
|
||||
if (blockEntity.network.canRemove(noLoreStack) && insertCount > 0) {
|
||||
playerInventory.insertStack(insertingStack.copy());
|
||||
blockEntity.network.removeItemStack(insertingStack);
|
||||
blockEntity.refreshTerminals();
|
||||
}
|
||||
}
|
||||
} else if (!cursorStack.isEmpty()) {
|
||||
insertItem(cursorStack);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void insertItem(ItemStack stack) {
|
||||
int canPutIn = stack.getCount() - blockEntity.network.putItemStackRemainder(stack);
|
||||
if (canPutIn > 0) {
|
||||
removeFromInventory(player.getInventory(), stack, canPutIn);
|
||||
blockEntity.refreshTerminals();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean insertItem(ItemStack stack, int startIndex, int endIndex, boolean fromLast) {
|
||||
blockEntity.refreshTerminals();
|
||||
insertItem(stack);
|
||||
return super.insertItem(stack, startIndex, endIndex, fromLast);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected DisplayElement search() {
|
||||
String searchString = blockEntity.searchString;
|
||||
if (searchString == null || searchString.isEmpty() || searchString.equals("*")) {
|
||||
searchString = "Filter not set";
|
||||
}
|
||||
return DisplayElement.of(
|
||||
new GuiElementBuilder(Items.PLAYER_HEAD)
|
||||
.setName(Text.literal(searchString).formatted(Formatting.WHITE))
|
||||
.hideDefaultTooltip().noDefaults()
|
||||
.setSkullOwner(GUI_QUESTION_MARK)
|
||||
.setCallback((x, y, z) -> {
|
||||
playClickSound(getPlayer());
|
||||
if (y.isRight) {
|
||||
doSearch("");
|
||||
} else if (y.isLeft) {
|
||||
SearchScreen searchScreen = new SearchScreen(this, "");
|
||||
searchScreen.open();
|
||||
}
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected DisplayElement settings() {
|
||||
SettingsScreen settingsScreen = new SettingsScreen(this);
|
||||
return settingsScreen.getItem();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected DisplayElement sorting() {
|
||||
return DisplayElement.of(
|
||||
new GuiElementBuilder(Items.PLAYER_HEAD)
|
||||
.setName(Text.translatable(this.blockEntity.sortAlphabetically ? "A->Z" : "9->1").formatted(Formatting.WHITE))
|
||||
.hideDefaultTooltip().noDefaults()
|
||||
.setSkullOwner(this.blockEntity.sortAlphabetically ? GUI_A : GUI_1)
|
||||
.setCallback((x, y, z) -> {
|
||||
this.blockEntity.sortAlphabetically ^= true;
|
||||
playClickSound(getPlayer());
|
||||
this.blockEntity.refreshTerminals();
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected DisplayElement storeAll() {
|
||||
return DisplayElement.of(
|
||||
new GuiElementBuilder(Items.PLAYER_HEAD)
|
||||
.setName(Text.translatable("gui.all").formatted(Formatting.WHITE))
|
||||
.hideDefaultTooltip().noDefaults()
|
||||
.setSkullOwner(GUI_STORE_ALL)
|
||||
.setCallback((x, y, z) -> {
|
||||
playClickSound(player);
|
||||
for (int i = 0; i < player.getInventory().main.size(); i++) {
|
||||
ItemStack stack = player.getInventory().main.get(i);
|
||||
insertItem(stack, 0, getVirtualSize(), false);
|
||||
}
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected DisplayElement crafting() {
|
||||
World world = blockEntity.getWorld();
|
||||
if (world != null && world.getGameRules().getBoolean(ServerStorage_Crafting_Enable)) {
|
||||
return DisplayElement.of(
|
||||
new GuiElementBuilder(Items.PLAYER_HEAD)
|
||||
.setName(Text.translatable("container.crafting").formatted(Formatting.WHITE))
|
||||
.hideDefaultTooltip().noDefaults()
|
||||
.setSkullOwner(GUI_CRAFTING)
|
||||
.setCallback((x, y, z) -> {
|
||||
playClickSound(player);
|
||||
CraftingScreen craftingScreen = new CraftingScreen(this);
|
||||
playClickSound(getPlayer());
|
||||
craftingScreen.open();
|
||||
})
|
||||
);
|
||||
} else {
|
||||
return DisplayElement.filler();
|
||||
}
|
||||
}
|
||||
|
||||
public void doSearch(String query) {
|
||||
this.blockEntity.searchString = query;
|
||||
this.blockEntity.refreshTerminals();
|
||||
this.page = 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected DisplayElement refresh() {
|
||||
return DisplayElement.of(
|
||||
new GuiElementBuilder(Items.PLAYER_HEAD)
|
||||
.setSkullOwner(GUI_REFRESH)
|
||||
.setName(Text.translatable("selectServer.refresh").formatted(Formatting.WHITE))
|
||||
.hideDefaultTooltip().noDefaults()
|
||||
.setCallback((x, y, z) -> {
|
||||
playClickSound(player);
|
||||
this.page = 0;
|
||||
this.blockEntity.searchString = "";
|
||||
this.blockEntity.refreshTerminals();
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClose() {
|
||||
this.blockEntity.page = page;
|
||||
this.blockEntity.markDirty();
|
||||
this.blockEntity.openStorageScreens.remove(this);
|
||||
super.onClose();
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user