Skip to content

Commit

Permalink
Make the compact mob farm store xp nuggets from create (if it's prese…
Browse files Browse the repository at this point in the history
…nt), make it apply mending to the sword item, if it has mending and rewrite the whole inventory as a `SlottedStorage`.

I didn't want to merge these two things together in one commit, but I forgot to commit the xp stuff when I was done with it, and I'm too lazy to go through all the changes :D No one's gonna see this anyway
  • Loading branch information
OffsetMonkey538 committed Oct 5, 2023
1 parent 28d3df7 commit b01ef59
Show file tree
Hide file tree
Showing 8 changed files with 200 additions and 77 deletions.
2 changes: 2 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,8 @@ dependencies {

// Mixin Extras
includeImplementation annotationProcessor("com.github.llamalad7.mixinextras:mixinextras-fabric:${project.mixinextras_version}")
// TODO: don't commit this, just for debugging
implementation files("/opt/idea/plugins/java-decompiler/lib/java-decompiler.jar")
}

processResources {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import net.fabricmc.api.ModInitializer;
import net.fabricmc.fabric.api.loot.v2.LootTableEvents;
import net.fabricmc.fabric.api.transfer.v1.item.ItemStorage;
import net.minecraft.block.Blocks;
import net.minecraft.enchantment.Enchantments;
import net.minecraft.loot.LootPool;
Expand Down Expand Up @@ -29,6 +30,9 @@ public void onInitialize() {
ModBlockEntityTypes.register();
ModScreenHandlers.register();

//noinspection UnstableApiUsage
ItemStorage.SIDED.registerForBlockEntity((block, direction) -> block.getDropInventory(), ModBlockEntityTypes.COMPACT_MOB_FARM);

LootTableEvents.MODIFY.register((resourceManager, lootManager, id, tableBuilder, source) -> {
if (!Blocks.SPAWNER.getLootTableId().equals(id) || !source.isBuiltin()) return;

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package top.offsetmonkey538.compactmobfarms.accessor;

import java.util.function.Consumer;

public interface LivingEntityAccessor {

void compact_mob_farms$setXpDropMethod(Consumer<Integer> dropMethod);
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,12 @@
import net.fabricmc.fabric.api.entity.FakePlayer;
import net.fabricmc.fabric.api.networking.v1.PacketByteBufs;
import net.fabricmc.fabric.api.screenhandler.v1.ExtendedScreenHandlerFactory;
import net.fabricmc.fabric.api.transfer.v1.item.ItemVariant;
import net.fabricmc.fabric.api.transfer.v1.transaction.Transaction;
import net.minecraft.block.BlockState;
import net.minecraft.block.entity.BlockEntity;
import net.minecraft.enchantment.EnchantmentHelper;
import net.minecraft.enchantment.Enchantments;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityType;
import net.minecraft.entity.EquipmentSlot;
Expand All @@ -19,10 +22,10 @@
import net.minecraft.entity.player.PlayerInventory;
import net.minecraft.inventory.Inventory;
import net.minecraft.inventory.SimpleInventory;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NbtCompound;
import net.minecraft.nbt.NbtElement;
import net.minecraft.nbt.NbtList;
import net.minecraft.network.PacketByteBuf;
import net.minecraft.network.listener.ClientPlayPacketListener;
import net.minecraft.network.packet.Packet;
Expand All @@ -39,22 +42,24 @@
import net.minecraft.world.World;
import org.jetbrains.annotations.Nullable;
import top.offsetmonkey538.compactmobfarms.accessor.EntityAccessor;
import top.offsetmonkey538.compactmobfarms.accessor.LivingEntityAccessor;
import top.offsetmonkey538.compactmobfarms.inventory.CompactMobFarmInventory;
import top.offsetmonkey538.compactmobfarms.item.SampleTakerItem;
import top.offsetmonkey538.compactmobfarms.item.upgrade.CompactMobFarmUpgradeItem;
import top.offsetmonkey538.compactmobfarms.network.ModPackets;
import top.offsetmonkey538.compactmobfarms.screen.CompactMobFarmScreenHandler;

public class CompactMobFarmBlockEntity extends BlockEntity implements CompactMobFarmInventory, ExtendedScreenHandlerFactory {
public class CompactMobFarmBlockEntity extends BlockEntity implements ExtendedScreenHandlerFactory {
public static final int DEFAULT_ATTACK_SPEED = 30 * 20; // 30 seconds, multiplied by 20 because it needs to be in ticks.
public static final Item NUGGET_OF_EXPERIENCE = Registries.ITEM.get(new Identifier("create:experience_nugget"));

private int killTimer = 0;
private boolean isTurnedOn = true;
private float maxEntityHealth = -1;
private float currentEntityHealth = -1;
private LivingEntity currentEntity = null;
private final List<BiConsumer<Identifier, PacketByteBuf>> packetSenders = new ArrayList<>();
final List<ItemStack> dropInventory = new ArrayList<>(1);
final CompactMobFarmInventory dropInventory = new CompactMobFarmInventory();
private final SimpleInventory upgrades = new SimpleInventory(4) {
@Override
public int getMaxCountPerStack() {
Expand Down Expand Up @@ -230,8 +235,15 @@ private float getAttackDamage(@Nullable ItemStack sword, LivingEntity target) {
return result;
}

@SuppressWarnings("UnstableApiUsage")
private void killEntity(PlayerEntity player) {
((EntityAccessor) currentEntity).compact_mob_farms$setDropMethod(this::addStack);
((EntityAccessor) currentEntity).compact_mob_farms$setDropMethod(stack -> {
try (Transaction transaction = Transaction.openOuter()) {
dropInventory.insert(ItemVariant.of(stack), stack.getCount(), transaction);
transaction.commit();
}
});
((LivingEntityAccessor) currentEntity).compact_mob_farms$setXpDropMethod(this::dropXp);

currentEntity.age = 1;
currentEntity.setAttacker(player);
Expand Down Expand Up @@ -263,9 +275,7 @@ public void writeScreenOpeningData(ServerPlayerEntity player, PacketByteBuf buf)

@Override
protected void writeNbt(NbtCompound nbt) {
NbtList dropInventoryNbt = new NbtList();
this.dropInventory.forEach(item -> dropInventoryNbt.add(item.writeNbt(new NbtCompound())));
nbt.put("DropInventory", dropInventoryNbt);
nbt.put("DropInventory", dropInventory.toNbtList());
nbt.put("SampleTaker", sampleTaker.toNbtList());
nbt.put("Upgrades", upgrades.toNbtList());
nbt.put("Sword", sword.toNbtList());
Expand All @@ -278,19 +288,13 @@ protected void writeNbt(NbtCompound nbt) {
public void readNbt(NbtCompound nbt) {
super.readNbt(nbt);

nbt.getList("DropInventory", NbtElement.COMPOUND_TYPE)
.forEach(itemNbt -> this.dropInventory.add(ItemStack.fromNbt((NbtCompound) itemNbt)));
dropInventory.fromNbt(nbt.getList("DropInventory", NbtElement.COMPOUND_TYPE));
sampleTaker.readNbtList(nbt.getList("SampleTaker", NbtElement.COMPOUND_TYPE));
upgrades.readNbtList(nbt.getList("Upgrades", NbtElement.COMPOUND_TYPE));
sword.readNbtList(nbt.getList("Sword", NbtElement.COMPOUND_TYPE));
isTurnedOn = nbt.getBoolean("TurnedOn");
}

@Override
public List<ItemStack> getItems() {
return dropInventory;
}

@Nullable
@Override
public Packet<ClientPlayPacketListener> toUpdatePacket() {
Expand All @@ -302,6 +306,23 @@ public NbtCompound toInitialChunkDataNbt() {
return createNbt();
}

@SuppressWarnings("UnstableApiUsage")
private void dropXp(int amount) {
final ItemStack sword = getSword();

if (EnchantmentHelper.get(sword).containsKey(Enchantments.MENDING) && sword.isDamaged()) {
int repairAmount = Math.min(amount * 2, sword.getDamage());
sword.setDamage(sword.getDamage() - repairAmount);

amount -= repairAmount / 2;
}

try (Transaction transaction = Transaction.openOuter()) {
dropInventory.insert(ItemVariant.of(NUGGET_OF_EXPERIENCE), amount / 3, transaction);
transaction.commit();
}
}

@Override
public void markDirty() {
super.markDirty();
Expand All @@ -320,6 +341,10 @@ public ItemStack getSword() {
return sword.getStack(0);
}

public CompactMobFarmInventory getDropInventory() {
return dropInventory;
}

public void setTurnedOn(boolean turnedOn) {
this.isTurnedOn = turnedOn;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,100 +1,142 @@
package top.offsetmonkey538.compactmobfarms.inventory;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.inventory.Inventories;
import net.minecraft.inventory.Inventory;
import net.fabricmc.fabric.api.transfer.v1.item.ItemVariant;
import net.fabricmc.fabric.api.transfer.v1.item.base.SingleStackStorage;
import net.fabricmc.fabric.api.transfer.v1.storage.SlottedStorage;
import net.fabricmc.fabric.api.transfer.v1.storage.StorageView;
import net.fabricmc.fabric.api.transfer.v1.storage.base.SingleSlotStorage;
import net.fabricmc.fabric.api.transfer.v1.transaction.TransactionContext;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NbtCompound;
import net.minecraft.nbt.NbtList;

public interface CompactMobFarmInventory extends Inventory {

List<ItemStack> getItems();
@SuppressWarnings("UnstableApiUsage")
public class CompactMobFarmInventory implements SlottedStorage<ItemVariant> {
private final List<Slot> slots = new ArrayList<>();

@Override
default int size() {
return getItems().size();
public int getSlotCount() {
return slots.size();
}

@Override
default boolean isEmpty() {
return getItems().isEmpty();
public SingleSlotStorage<ItemVariant> getSlot(int slot) {
return slots.get(slot);
}

@Override
default ItemStack getStack(int slot) {
if (slot >= size()) return ItemStack.EMPTY;
return getItems().get(slot);
public boolean supportsInsertion() {
return false;
}

@Override
default ItemStack removeStack(int slot, int amount) {
if (slot >= size()) return ItemStack.EMPTY;
ItemStack removedStack;

if (getStack(slot).getCount() - amount <= 0) {
removedStack = getItems().remove(slot);
} else {
removedStack = Inventories.splitStack(getItems(), slot, amount);
}
public long insert(ItemVariant resource, long maxAmount, TransactionContext transaction) {
if (resource.isBlank()) return 0;

for (Slot slot : slots) {
final ItemStack storedStack = slot.getStack();
if (!storedStack.isOf(resource.getItem()) || (resource.getNbt() != null && resource.getNbt().equals(storedStack.getNbt()))) continue;

int oldCount = storedStack.getCount();
int newCount = (int) Math.min(64, oldCount + maxAmount);

if (!removedStack.isEmpty()) {
this.markDirty();
storedStack.setCount(newCount);
slot.setStack(storedStack);

return newCount - oldCount;
}
return removedStack;
}

@Override
default ItemStack removeStack(int slot) {
this.markDirty();
return getItems().remove(slot);
}

default void addStack(ItemStack stack) {
if (stack.isEmpty()) return;
// None of the already stored stacks match the new stack.

int count = (int) Math.min(64, maxAmount);
final ItemStack addedStack = resource.toStack(count);

slots.add(new Slot(addedStack));

return count;
}

for (int i = 0; i < size(); i++) {
ItemStack storedStack = getStack(i);
@Override
public long extract(ItemVariant resource, long maxAmount, TransactionContext transaction) {
if (resource.isBlank()) return 0;

if (!storedStack.isOf(stack.getItem()) || (stack.getNbt() != null && !stack.getNbt().equals(storedStack.getNbt()))) continue;
for (Slot slot : slots) {
final ItemStack storedStack = slot.getStack();
if (!storedStack.isOf(resource.getItem()) || (resource.getNbt() != null && resource.getNbt().equals(storedStack.getNbt()))) continue;

int newCount = stack.getCount() + storedStack.getCount();
if (newCount > getMaxCountPerStack()) newCount = getMaxCountPerStack();
int oldCount = storedStack.getCount();
int newCount = (int) Math.min(0, oldCount - maxAmount);

storedStack.setCount(newCount);
getItems().set(i, storedStack);
markDirty();
return;
slot.setStack(storedStack);
if (newCount == 0) slots.remove(slot);

return oldCount - newCount;
}

getItems().add(stack);
markDirty();
return 0;
}

@Override
default void setStack(int slot, ItemStack stack) {
if (slot >= size()) return;
if (stack.isEmpty()) {
getItems().remove(slot);
return;
}
getItems().set(slot, stack);
this.markDirty();
public Iterator<StorageView<ItemVariant>> iterator() {
return new Iterator<>() {
int i = 0;

@Override
public boolean hasNext() {
return CompactMobFarmInventory.this.slots.size() > i;
}

@Override
public StorageView<ItemVariant> next() {
return CompactMobFarmInventory.this.slots.get(i++);
}
};
}

@Override
default boolean isValid(int slot, ItemStack stack) {
// We don't want hoppers or anything to put items in here
return false;
public NbtList toNbtList() {
final NbtList nbt = new NbtList();

slots.forEach((Slot slot) -> nbt.add(slot.toNbt()));

return nbt;
}

@Override
default boolean canPlayerUse(PlayerEntity player) {
return true;
public void fromNbt(NbtList nbtList) {
nbtList.forEach(nbt -> slots.add(new Slot((NbtCompound) nbt)));
}

@Override
default void clear() {
getItems().clear();
markDirty();
private class Slot extends SingleStackStorage {
private ItemStack stack;

public Slot(ItemStack stack) {
this.stack = stack;
}
public Slot(NbtCompound nbt) {
this(ItemStack.fromNbt(nbt));
}

@Override
protected ItemStack getStack() {
return stack;
}

@Override
protected void setStack(ItemStack stack) {
this.stack = stack;
}

@Override
protected void onFinalCommit() {
if (stack.isEmpty()) CompactMobFarmInventory.this.slots.remove(this);
}

public NbtCompound toNbt() {
return stack.writeNbt(new NbtCompound());
}
}
}
Loading

0 comments on commit b01ef59

Please sign in to comment.