Ported "stackable empty shulkerboxes on ground" based on @maruohon's tweakeroo code

This commit is contained in:
Marc Hannappel committed 2019-05-16 18:05:15 +02:00
1 parent 723f863d98
commit 9e72423a41
5 files changed
+175 -2

No files matched your search

+2 -1
View File
@@ -60,6 +60,7 @@ public class CarpetSettings
public static boolean b_disableSpawnChunks = false;
public static boolean b_movableTileEntities = false;
public static boolean b_huskSpawningInTemples = false;
public static boolean b_stackableShulkerBoxes = false;
private static CarpetSettingEntry rule(String s1, String s2, String s3) { return CarpetSettingEntry.create(s1,s2,s3);}
@@ -82,7 +83,7 @@ public class CarpetSettings
rule("xpNoCooldown", "creative", "Players absorb XP instantly, without delay"),
rule("combineXPOrbs", "creative", "XP orbs combine with other into bigger orbs"),
rule("stackableShulkerBoxes", "survival", "Empty shulker boxes can stack to 64 when dropped on the ground")
.extraInfo("To move them around between inventories, use shift click to move entire stacks"),
.extraInfo("To move them around between inventories, use shift click to move entire stacks").boolAccelerate().defaultFalse(),
rule("explosionNoBlockDamage", "tnt", "Explosions won't destroy blocks"),
rule("tntPrimerMomentumRemoved", "tnt", "Removes random TNT momentum when primed"),
rule("fastRedstoneDust", "experimental optimizations", "Lag optimizations for redstone dust")
@@ -0,0 +1,57 @@
package carpet.helpers;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.CompoundTag;
public class InventoryHelper
{
// From nbt/Tag.java createTag()
public static final int TAG_END = 0;
public static final int TAG_BYTE = 1;
public static final int TAG_SHORT = 2;
public static final int TAG_INT = 3;
public static final int TAG_LONG = 4;
public static final int TAG_FLOAT = 5;
public static final int TAG_DOUBLE = 6;
public static final int TAG_BYTEARRAY = 7;
public static final int TAG_STRING = 8;
public static final int TAG_LIST = 9;
public static final int TAG_COMPOUND = 10;
public static final int TAG_INTARRAY = 11;
public static final int TAG_LONGARRAY = 12;
public static boolean cleanUpShulkerBoxTag(ItemStack stack)
{
boolean changed = false;
CompoundTag tag = stack.getTag();
if (tag == null || !tag.containsKey("BlockEntityTag", TAG_COMPOUND))
return false;
CompoundTag bet = tag.getCompound("BlockEntityTag");
if (bet.containsKey("Items", TAG_LIST) && bet.getList("Items", TAG_COMPOUND).isEmpty())
{
bet.remove("Items");
changed = true;
}
if (bet.isEmpty())
{
stack.setTag(null);
changed = true;
}
return changed;
}
public static boolean shulkerBoxHasItems(ItemStack stack)
{
CompoundTag tag = stack.getTag();
if (tag == null || !tag.containsKey("BlockEntityTag", TAG_COMPOUND))
return false;
CompoundTag bet = tag.getCompound("BlockEntityTag");
return bet.containsKey("Items", TAG_LIST) && !bet.getList("Items", TAG_COMPOUND).isEmpty();
}
}
@@ -0,0 +1,108 @@
package carpet.mixins;
import carpet.CarpetSettings;
import carpet.helpers.InventoryHelper;
import carpet.utils.IItemEntity;
import net.minecraft.block.ShulkerBoxBlock;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityType;
import net.minecraft.entity.ItemEntity;
import net.minecraft.item.BlockItem;
import net.minecraft.item.ItemStack;
import net.minecraft.world.World;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.Redirect;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(ItemEntity.class)
public abstract class ItemEntityMixin extends Entity implements IItemEntity {
private static final int SHULKERBOX_MAX_STACK_AMOUNT = 64;
@Shadow private int age;
@Shadow private int pickupDelay;
public ItemEntityMixin(EntityType<?> entityType_1, World world_1) {
super(entityType_1, world_1);
}
@Override
public int getAge() {
return this.age;
}
@Override
public int getPickupDelay() {
return this.pickupDelay;
}
@Inject(method="<init>(Lnet/minecraft/world/World;DDDLnet/minecraft/item/ItemStack;)V", at = @At("RETURN"))
private void removeEmptyShulkerBoxTags(World worldIn, double x, double y, double z, ItemStack stack, CallbackInfo ci)
{
if (CarpetSettings.b_stackableShulkerBoxes
&& stack.getItem() instanceof BlockItem
&& ((BlockItem)stack.getItem()).getBlock() instanceof ShulkerBoxBlock)
{
if (InventoryHelper.cleanUpShulkerBoxTag(stack)) {
((ItemEntity) (Object) this).setStack(stack);
}
}
}
@Redirect(
method = "method_20397",
at = @At(
value = "INVOKE",
target = "Lnet/minecraft/item/ItemStack;getMaxAmount()I"
)
)
private int getItemStackMaxAmount(ItemStack stack) {
if (CarpetSettings.b_stackableShulkerBoxes && stack.getItem() instanceof BlockItem && ((BlockItem)stack.getItem()).getBlock() instanceof ShulkerBoxBlock)
return SHULKERBOX_MAX_STACK_AMOUNT;
return stack.getMaxAmount();
}
@Inject(
method = "tryMerge(Lnet/minecraft/entity/ItemEntity;)V",
at = @At("HEAD"),
cancellable = true
)
private void tryStackShulkerBoxes(ItemEntity other, CallbackInfo ci)
{
ItemEntity self = (ItemEntity)(Object)this;
ItemStack selfStack = self.getStack();
if (!CarpetSettings.b_stackableShulkerBoxes || !(selfStack.getItem() instanceof BlockItem) || !(((BlockItem)selfStack.getItem()).getBlock() instanceof ShulkerBoxBlock)) {
return;
}
ItemStack otherStack = other.getStack();
if (selfStack.getItem() == otherStack.getItem()
&& !InventoryHelper.shulkerBoxHasItems(selfStack)
&& selfStack.hasTag() == otherStack.hasTag()
&& selfStack.getAmount() + otherStack.getAmount() <= SHULKERBOX_MAX_STACK_AMOUNT)
{
int amount = Math.min(otherStack.getAmount(), SHULKERBOX_MAX_STACK_AMOUNT - selfStack.getAmount());
selfStack.addAmount(amount);
self.setStack(selfStack);
this.pickupDelay = Math.max(((IItemEntity)other).getPickupDelay(), this.pickupDelay);
this.age = Math.min(other.getAge(), this.age);
otherStack.subtractAmount(amount);
if (otherStack.isEmpty())
{
other.remove();
}
else
{
other.setStack(otherStack);
}
ci.cancel();
}
}
}
@@ -0,0 +1,6 @@
package carpet.utils;
public interface IItemEntity {
int getAge();
int getPickupDelay();
}