Adds a starter kit system

This commit is contained in:
zontreck 2023-12-20 17:04:12 -07:00
parent 6f0511990e
commit 97e13a1e17
16 changed files with 714 additions and 20 deletions

View file

@ -0,0 +1,92 @@
package dev.zontreck.otemod.implementation.vault;
import dev.zontreck.libzontreck.profiles.Profile;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.LongTag;
import net.minecraft.nbt.NbtIo;
import net.minecraftforge.items.ItemStackHandler;
import java.io.File;
import java.io.IOException;
public class Starter {
public File file_location;
public final boolean isNew;
private long LastChanged;
private CompoundTag tag;
protected Starter(File loc)
{
file_location=loc;
isNew=!file_location.exists();
CompoundTag tag;
if(!isNew){
try {
tag = NbtIo.read(loc);
this.tag = tag.getCompound("inventory");
this.LastChanged = tag.getLong("changed");
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* This will return the contents of the NBT Vault
* @return
*/
public CompoundTag getContents(){
return tag;
}
/**
* This sets the internal compound tag of the vault provider, but also saves it to the file immediately.
* @param newTag
*/
public void setContents(CompoundTag newTag)
{
tag=newTag;
commit();
}
public void setLastChanged(long change)
{
LastChanged = change;
}
public long getLastChanged() {
return LastChanged;
}
private void commit()
{
CompoundTag newTag = new CompoundTag();
newTag.put("inventory", tag);
newTag.put("changed", LongTag.valueOf(LastChanged));
try {
NbtIo.write(newTag, file_location);
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* This is called to dispose of the vault and the vault file
*/
public void delete()
{
if(file_location.exists())
file_location.delete();
}
public ItemStackHandler getItems()
{
ItemStackHandler H = new ItemStackHandler(32);
H.deserializeNBT(getContents());
return H;
}
}

View file

@ -0,0 +1,105 @@
package dev.zontreck.otemod.implementation.vault;
import dev.zontreck.libzontreck.chat.ChatColor;
import dev.zontreck.libzontreck.profiles.Profile;
import dev.zontreck.libzontreck.profiles.UserProfileNotYetExistsException;
import dev.zontreck.libzontreck.util.ChatHelpers;
import dev.zontreck.otemod.OTEMod;
import dev.zontreck.otemod.configs.OTEServerConfig;
import dev.zontreck.otemod.implementation.events.VaultModifiedEvent;
import net.minecraft.core.BlockPos;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.network.chat.Component;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.inventory.MenuConstructor;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Items;
import net.minecraftforge.items.ItemStackHandler;
import java.time.Instant;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
public class StarterContainer
{
public static Map<UUID, StarterContainer> VAULT_REGISTRY = new HashMap<>();
public StarterMenu theContainer;
public ItemStackHandler myInventory;
public ItemStackHandler startingInventory;
public MenuConstructor serverMenu;
public UUID owner;
private MinecraftServer server;
public final UUID VaultID;
public Starter main_accessor;
public StarterContainer(ServerPlayer player) throws NoMoreVaultException {
myInventory = new ItemStackHandler(54); // Vaults have a fixed size at the same as a double chest
startingInventory = new ItemStackHandler(64);
theContainer = new StarterMenu(player.containerCounter+1, player.getInventory(), myInventory, BlockPos.ZERO, player);
VaultID = theContainer.VaultMenuID;
owner = player.getUUID();
server=player.server;
serverMenu = theContainer.getServerMenu(myInventory);
// Check database for vault
StarterProvider.VaultAccessStrategy strategy;
strategy = StarterProvider.check();
if(strategy == StarterProvider.VaultAccessStrategy.CREATE || strategy == StarterProvider.VaultAccessStrategy.OPEN)
{
Starter accessor = StarterProvider.getStarter();
if(accessor.isNew)
{
main_accessor=accessor;
return;
}else {
myInventory.deserializeNBT(accessor.getContents());
startingInventory.deserializeNBT(accessor.getContents());
}
main_accessor=accessor;
}else {
// DENY
throw new NoMoreVaultException("No more vaults can be created", 0);
}
// Container is now ready to be sent to the client!
}
public void commit()
{
boolean isEmpty=true;
CompoundTag saved = myInventory.serializeNBT();
ChatHelpers.broadcastToAbove(owner, Component.literal(ChatColor.BOLD+ChatColor.DARK_GREEN+"Saving the starter kit's contents..."), server);
main_accessor.setLastChanged(Instant.now().getEpochSecond());
Profile profile=null;
try {
profile = Profile.get_profile_of(owner.toString());
} catch (UserProfileNotYetExistsException e) {
e.printStackTrace();
return;
}
for(int i = 0;i<myInventory.getSlots();i++)
{
ItemStack is = myInventory.getStackInSlot(i);
if(!is.is(Items.AIR))
{
isEmpty=false;
}
}
if(!isEmpty)
main_accessor.setContents(saved);
else
main_accessor.delete();
VaultModifiedEvent vme = new VaultModifiedEvent(-2, profile, VaultProvider.getInUse(profile), myInventory, startingInventory);
OTEMod.bus.post(vme);
}
}

View file

@ -0,0 +1,150 @@
package dev.zontreck.otemod.implementation.vault;
import dev.zontreck.otemod.implementation.inits.ModMenuTypes;
import net.minecraft.core.BlockPos;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.world.entity.player.Inventory;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.inventory.AbstractContainerMenu;
import net.minecraft.world.inventory.MenuConstructor;
import net.minecraft.world.inventory.Slot;
import net.minecraft.world.item.ItemStack;
import net.minecraftforge.items.IItemHandler;
import net.minecraftforge.items.ItemStackHandler;
import net.minecraftforge.items.SlotItemHandler;
import java.util.Map;
import java.util.UUID;
public class StarterMenu extends AbstractContainerMenu
{
//private final ContainerLevelAccess containerAccess;
public final UUID VaultMenuID;
public final Player thePlayer;
public StarterMenu(int id, Inventory player, FriendlyByteBuf buf)
{
this(id, player, new ItemStackHandler(54), player.player.getOnPos(), player.player);
}
public StarterMenu(int id, Inventory player, IItemHandler slots, BlockPos pos, Player play)
{
super(ModMenuTypes.VAULT.get(), id);
thePlayer=play;
VaultMenuID=UUID.randomUUID();
//this.containerAccess = ContainerLevelAccess.create(player.player.level, pos);
final int slotSize = 18;
final int startX = 24;
final int inventoryY = 38;
addPlayerInventory(player);
addPlayerHotbar(player);
for (int row = 0; row < 6; row++)
{
for (int column = 0; column < 9; column++)
{
addSlot(new SlotItemHandler(slots, row*9 + column, startX+column * slotSize , inventoryY + row * slotSize));
}
}
}
// CREDIT GOES TO: diesieben07 | https://github.com/diesieben07/SevenCommons
// must assign a slot number to each of the slots used by the GUI.
// For this container, we can see both the tile inventory's slots as well as the player inventory slots and the hotbar.
// Each time we add a Slot to the container, it automatically increases the slotIndex, which means
// 0 - 8 = hotbar slots (which will map to the InventoryPlayer slot numbers 0 - 8)
// 9 - 35 = player inventory slots (which map to the InventoryPlayer slot numbers 9 - 35)
// 36 - 44 = TileInventory slots, which map to our TileEntity slot numbers 0 - 8)
private static final int HOTBAR_SLOT_COUNT = 9;
private static final int PLAYER_INVENTORY_ROW_COUNT = 3;
private static final int PLAYER_INVENTORY_COLUMN_COUNT = 9;
private static final int PLAYER_INVENTORY_SLOT_COUNT = PLAYER_INVENTORY_COLUMN_COUNT * PLAYER_INVENTORY_ROW_COUNT;
private static final int VANILLA_SLOT_COUNT = HOTBAR_SLOT_COUNT + PLAYER_INVENTORY_SLOT_COUNT;
private static final int VANILLA_FIRST_SLOT_INDEX = 0;
private static final int TE_INVENTORY_FIRST_SLOT_INDEX = VANILLA_FIRST_SLOT_INDEX + VANILLA_SLOT_COUNT;
// THIS YOU HAVE TO DEFINE!
private static final int TE_INVENTORY_SLOT_COUNT = 54; // must be the number of slots you have!
@Override
public ItemStack quickMoveStack(Player playerIn, int index) {
Slot sourceSlot = slots.get(index);
if (sourceSlot == null || !sourceSlot.hasItem()) return ItemStack.EMPTY; //EMPTY_ITEM
ItemStack sourceStack = sourceSlot.getItem();
ItemStack copyOfSourceStack = sourceStack.copy();
// Check if the slot clicked is one of the vanilla container slots
if (index < VANILLA_FIRST_SLOT_INDEX + VANILLA_SLOT_COUNT) {
// This is a vanilla container slot so merge the stack into the tile inventory
if (!moveItemStackTo(sourceStack, TE_INVENTORY_FIRST_SLOT_INDEX, TE_INVENTORY_FIRST_SLOT_INDEX
+ TE_INVENTORY_SLOT_COUNT, false)) {
return ItemStack.EMPTY; // EMPTY_ITEM
}
} else if (index < TE_INVENTORY_FIRST_SLOT_INDEX + TE_INVENTORY_SLOT_COUNT) {
// This is a TE slot so merge the stack into the players inventory
if (!moveItemStackTo(sourceStack, VANILLA_FIRST_SLOT_INDEX, VANILLA_FIRST_SLOT_INDEX + VANILLA_SLOT_COUNT, false)) {
return ItemStack.EMPTY;
}
} else {
System.out.println("Invalid slotIndex:" + index);
return ItemStack.EMPTY;
}
// If stack size == 0 (the entire stack was moved) set slot contents to null
if (sourceStack.getCount() == 0) {
sourceSlot.set(ItemStack.EMPTY);
} else {
sourceSlot.setChanged();
}
sourceSlot.onTake(playerIn, sourceStack);
return copyOfSourceStack;
}
@Override
public boolean stillValid(Player p_38874_) {
return true; // We have no block
}
public static MenuConstructor getServerMenu (ItemStackHandler inventory){
return (id, player, play) -> new StarterMenu(id, player, inventory, BlockPos.ZERO, player.player);
}
public void doCommitAction()
{
// Locate the Vault in the Vault Registry and commit changes.
// Search for myself!
for(Map.Entry<UUID,StarterContainer> e : StarterContainer.VAULT_REGISTRY.entrySet())
{
if(e.getValue().VaultID.equals(VaultMenuID))
{
e.getValue().commit();
}
}
}
private static final int PLAYER_INVENTORY_FIRST_SLOT_HEIGHT = 156;
private static final int PLAYER_INVENTORY_FIRST_SLOT_LEFT = 24;
private static final int PLAYER_HOTBAR_FIRST_SLOT = 212;
private void addPlayerInventory(Inventory inv)
{
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 9; j++) {
this.addSlot(new Slot(inv, j+i*9+9, PLAYER_INVENTORY_FIRST_SLOT_LEFT+j*18, PLAYER_INVENTORY_FIRST_SLOT_HEIGHT+i*18));
}
}
}
private void addPlayerHotbar(Inventory inv)
{
for (int index = 0; index < 9; index++) {
this.addSlot(new Slot(inv, index, PLAYER_INVENTORY_FIRST_SLOT_LEFT+index*18, PLAYER_HOTBAR_FIRST_SLOT));
}
}
}

View file

@ -0,0 +1,56 @@
package dev.zontreck.otemod.implementation.vault;
import dev.zontreck.libzontreck.profiles.Profile;
import dev.zontreck.otemod.configs.OTEServerConfig;
import dev.zontreck.otemod.database.OTEDatastore;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;
public class StarterProvider extends OTEDatastore
{
public enum VaultAccessStrategy
{
OPEN,
CREATE,
DENY
}
public static final Path FILE_TREE_PATH = of("starter");
public static VaultAccessStrategy check()
{
if(!FILE_TREE_PATH.toFile().exists())
{
try {
Files.createDirectory(FILE_TREE_PATH);
} catch (IOException e) {
e.printStackTrace();
}
}
Path starterVaultPath = FILE_TREE_PATH.resolve("starter.nbt");
File vaultFile = starterVaultPath.toFile();
if(vaultFile.exists())
{
return VaultAccessStrategy.OPEN;
}else {
return VaultAccessStrategy.CREATE;
}
}
public static Starter getStarter() throws NoMoreVaultException
{
VaultAccessStrategy strat = check();
if(strat == VaultAccessStrategy.CREATE || strat == VaultAccessStrategy.OPEN)
{
Path userVault = FILE_TREE_PATH.resolve("starter.nbt");
Starter v = new Starter(userVault.toFile());
return v;
}else return null;
}
}

View file

@ -0,0 +1,70 @@
package dev.zontreck.otemod.implementation.vault;
import com.mojang.blaze3d.systems.RenderSystem;
import dev.zontreck.otemod.OTEMod;
import dev.zontreck.otemod.networking.ModMessages;
import dev.zontreck.otemod.networking.packets.OpenStarterVaultC2SPacket;
import dev.zontreck.otemod.networking.packets.OpenVaultC2SPacket;
import net.minecraft.client.gui.GuiGraphics;
import net.minecraft.client.gui.components.Button;
import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen;
import net.minecraft.client.renderer.GameRenderer;
import net.minecraft.network.chat.Component;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.entity.player.Inventory;
import net.minecraft.world.entity.player.Player;
import java.util.UUID;
public class StarterScreen extends AbstractContainerScreen <StarterMenu>
{
// 176x224
public final UUID VaultMenuID;
public final Player thePlayer;
public final StarterMenu THE_CONTAINER;
private static final ResourceLocation TEXTURE = new ResourceLocation(OTEMod.MOD_ID, "textures/gui/vault.png");
public StarterScreen(StarterMenu container, Inventory playerInv, Component comp){
super(container, playerInv, comp);
thePlayer=playerInv.player;
this.VaultMenuID = container.VaultMenuID;
this.leftPos = 0;
this.topPos = 0;
this.THE_CONTAINER=container;
this.imageWidth = 207;
this.imageHeight = 238;
}
@Override
public void render(GuiGraphics stack, int mouseX, int mouseY, float partialTicks)
{
this.renderBackground(stack);
super.render(stack, mouseX, mouseY, partialTicks);
this.renderTooltip(stack, mouseX, mouseY);
}
@Override
protected void init()
{
super.init();
this.inventoryLabelY = 12;
this.inventoryLabelX = 63;
}
@Override
protected void renderBg(GuiGraphics pGuiGraphics, float pPartialTick, int pMouseX, int pMouseY)
{
renderBackground(pGuiGraphics);
RenderSystem.setShader(GameRenderer::getPositionTexShader);
RenderSystem.setShaderColor (1.0f, 1.0f, 1.0f, 1.0f);
RenderSystem.setShaderTexture(0, TEXTURE);
pGuiGraphics.blit(TEXTURE, this.leftPos, this.topPos, 0, 0, this.imageWidth, this.imageHeight);
}
}

View file

@ -29,6 +29,15 @@ public class VaultWatcher {
entry.getValue().commit();
}
}
} else if(ev.getContainer() instanceof StarterMenu)
{
for(Map.Entry<UUID, StarterContainer> entry : StarterContainer.VAULT_REGISTRY.entrySet())
{
if(entry.getKey() == ev.getEntity().getUUID())
{
entry.getValue().commit();
}
}
}
}
}