Skip to content

Commit

Permalink
Release 1.7.6: Human readable container inventory interaction logs
Browse files Browse the repository at this point in the history
  • Loading branch information
kivattt committed May 5, 2024
1 parent fa5c367 commit 5b34c75
Show file tree
Hide file tree
Showing 6 changed files with 115 additions and 29 deletions.
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
## Features
- Improved player chat, with colors, nicknames, pronouns, flags aswell as red usernames for OP players
- Player teleport request commands
- Adds spawn and home commands
- Adds spawn, home and warp commands
- Adds a stricter mob cap which allows mobs to be enabled for servers without lag
- Improved logging for chests and crates, see items being taken/added
- Fixes 100% CPU usage on 1 core
Expand Down Expand Up @@ -306,6 +306,8 @@ Doing `/sethome` then covering up the home location with blocks, unloading the c
then doing `/home` can make you fall into an underground cave\
This will also affect other commands like `/spawn`, since it's really an underlying issue with teleporting

A crate/drawer which has items inside, when taken out of a chest, will not be logged

You can't place blocks beside protected regions when right-clicking a block in the region

When `/maxhomes` is set to 1, all commands after the first sethome will fail and the player will have to manually `/delhome` every time
Expand Down
7 changes: 2 additions & 5 deletions TODO.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
- Make container logging queued in a thread to make it less spammy, with handling on server close

- Better system for configuration, less confusing commands (something like /gamerule \<key> \<value>)

- Chat messages stored in a file with the normal Minecraft language format string system
Expand All @@ -13,11 +15,6 @@ prob need some explanation to the user about it

- Improve the 100% CPU fix to not sleep on server close (saving chunks?)

More descriptive logging?
- Itemstack amount changed
- Itemstack added
- Itemstack removed

# Kiva config
Just make it thought-out, not requiring `...disabled` to be the default
just have something like
Expand Down
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ buildscript {

apply plugin: 'foxloader.dev'

version '1.7.5'
version '1.7.6'

foxloader {
// forceReload = true
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ public class KivaServerUtils extends Mod {
public static LinkedHashMap<String, String> nameColorChoicesNames = new LinkedHashMap<>();
public static LinkedHashMap<String, String> flagColorChoicesNames = new LinkedHashMap<>();
public static LinkedHashMap<String, String> pronounColorChoicesNames = new LinkedHashMap<>();
public static String version = "1.7.5";
public static String version = "1.7.6";
public static String KSUBroadcastPrefix = ChatColors.DARK_GRAY + "[" + ChatColors.GRAY + "KSU" + ChatColors.DARK_GRAY + "] " + ChatColors.RESET;

public static String handleWindowClickLatestPlayerUsername;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package com.kiva.kivaserverutils;

import net.minecraft.src.game.item.ItemStack;
import net.minecraft.src.game.nbt.NBTTagCompound;

import java.util.Objects;

public class ItemStackWithoutStackSize {
public int itemID;
public int itemDamage;
public NBTTagCompound nbtTagCompound;
private final int hashCode;

public ItemStackWithoutStackSize(ItemStack itemStack) {
this.itemID = itemStack.itemID;
this.itemDamage = itemStack.itemDamage;
this.nbtTagCompound = itemStack.nbtTagCompound;
this.hashCode = Objects.hash(this.itemID, this.itemDamage, this.nbtTagCompound);
}

public ItemStack asItemStack(int withStackSize) {
return new ItemStack(this.itemID, withStackSize, this.itemDamage, this.nbtTagCompound);
}

@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null || getClass() != obj.getClass())
return false;

ItemStackWithoutStackSize that = (ItemStackWithoutStackSize) obj;
return itemID == that.itemID && itemDamage == that.itemDamage && nbtTagCompound == that.nbtTagCompound;
}

@Override
public int hashCode() {
return this.hashCode;
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.kiva.kivaserverutils.server.mixins;

import com.kiva.kivaserverutils.ItemStackWithoutStackSize;
import com.kiva.kivaserverutils.KivaServerUtils;
import net.minecraft.src.game.item.ItemStack;
import net.minecraft.src.game.recipe.ICrafting;
Expand All @@ -8,7 +9,9 @@
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Overwrite;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.Unique;

import java.util.HashMap;
import java.util.List;
import java.util.logging.Logger;

Expand All @@ -31,42 +34,86 @@ public abstract class MixinContainer{
*/
@Overwrite
public void updateInventory(){
StringBuilder containerItemsChangedLog = new StringBuilder();
HashMap<ItemStackWithoutStackSize, Integer> diff = new HashMap<>();

for(int var1 = 0; var1 < this.inventorySlots.size(); ++var1) {
ItemStack itemStack = this.inventorySlots.get(var1).getStack();
ItemStack var3 = (ItemStack)this.inventoryItemStacks.get(var1);
if (!ItemStack.areItemStacksEqual(var3, itemStack)) {
String containerTypeName = "Unknown";
if (this.inventoryItemStacks.size() == 45)
containerTypeName = "Crate";
else if (this.inventoryItemStacks.size() == 63)
containerTypeName = "Chest";
else if (this.inventoryItemStacks.size() == 90)
containerTypeName = "Double chest";
String containerTypeName = "Unknown";
if (inventoryItemStacks.size() == 45)
containerTypeName = "Crate";
else if (inventoryItemStacks.size() == 63)
containerTypeName = "Chest";
else if (inventoryItemStacks.size() == 90)
containerTypeName = "Double chest";

for(int var1 = 0; var1 < this.inventorySlots.size(); ++var1) {
ItemStack itemTo = this.inventorySlots.get(var1).getStack();
ItemStack itemFrom = (ItemStack)this.inventoryItemStacks.get(var1);
if (!ItemStack.areItemStacksEqual(itemFrom, itemTo)) {
final boolean fromHandleWindowClick = Thread.currentThread().getStackTrace()[2].getMethodName().equals("handleWindowClick"); // Least hacky foxloader mod
final boolean itemChangedWasPlayersInventory = var1 < this.inventoryItemStacks.size() && var1 >= this.inventoryItemStacks.size() - 36;
final boolean eitherIsNull = var3 == null || itemStack == null;
final boolean eitherIsNull = itemFrom == null || itemTo == null;
boolean disqualifyForEqual = false;
if (!eitherIsNull)
disqualifyForEqual = (var3.itemID == itemStack.itemID && var3.stackSize == itemStack.stackSize);
disqualifyForEqual = itemFrom.isStackEqual(itemTo);

if (!disqualifyForEqual && fromHandleWindowClick && !itemChangedWasPlayersInventory && !containerTypeName.equals("Unknown") && KivaServerUtils.handleWindowClickLatestPlayerUsername != null && this.windowId != 0) {
if (itemFrom != null) {
int newStackSize;
if (!diff.containsKey(new ItemStackWithoutStackSize(itemFrom)))
newStackSize = -itemFrom.stackSize;
else
newStackSize = diff.get(new ItemStackWithoutStackSize(itemFrom)) - itemFrom.stackSize;

if (!itemChangedWasPlayersInventory && (!containerTypeName.equals("Unknown")) && !disqualifyForEqual && KivaServerUtils.handleWindowClickLatestPlayerUsername != null && this.windowId != 0) {
containerItemsChangedLog.append("\n").append(KivaServerUtils.handleWindowClickLatestPlayerUsername).append(" in ").append(containerTypeName).append(", item ").append((var3 == null) ? "null" : var3).append(" replaced with ").append((itemStack == null) ? "null" : itemStack);
diff.put(new ItemStackWithoutStackSize(itemFrom), newStackSize);
}

if (itemTo != null) {
int newStackSize;
if (!diff.containsKey(new ItemStackWithoutStackSize(itemTo)))
newStackSize = itemTo.stackSize;
else
newStackSize = diff.get(new ItemStackWithoutStackSize(itemTo)) + itemTo.stackSize;

diff.put(new ItemStackWithoutStackSize(itemTo), newStackSize);
}
}

var3 = itemStack == null ? null : itemStack.copy();
this.inventoryItemStacks.set(var1, var3);
itemFrom = itemTo == null ? null : itemTo.copy();
this.inventoryItemStacks.set(var1, itemFrom);

for(int var4 = 0; var4 < this.crafters.size(); ++var4)
this.crafters.get(var4).updateCraftingInventorySlot((Container)(Object)this, var1, var3);
for (ICrafting crafter : this.crafters)
crafter.updateCraftingInventorySlot((Container) (Object) this, var1, itemFrom);
}
}

diff.values().remove(0);
if (diff.isEmpty())
return;

StringBuilder containerItemsChangedLog = new StringBuilder();
diff.forEach((key, value) -> {
String putInOrTookOut = value < 0 ? "Took out " : "Put in ";
containerItemsChangedLog.append("\n").append(putInOrTookOut).append(itemStackToString(key.asItemStack(Math.abs(value))));
});

if (containerItemsChangedLog.length() > 0) {
final Logger logger = Logger.getLogger("Minecraft");
logger.warning("Inventory update:" + containerItemsChangedLog);
logger.warning(KivaServerUtils.handleWindowClickLatestPlayerUsername + " in " + containerTypeName + ":" + containerItemsChangedLog);
}
}

@Unique
public String itemStackToString(ItemStack itemStack) {
return itemStack.stackSize + " " + itemNameWithoutTileOrItemPrefix(itemStack.getDisplayName()) + (itemStack.itemDamage == 0 ? "" : " @ " + itemStack.itemDamage);
}

@Unique
public String itemNameWithoutTileOrItemPrefix(String itemName) {
if (itemName.startsWith("tile."))
return itemName.substring("tile.".length());

if (itemName.startsWith("item."))
return itemName.substring("item.".length());

return itemName;
}
}

0 comments on commit 5b34c75

Please sign in to comment.