mirror of https://github.com/cabaletta/baritone
177 lines
5.9 KiB
Java
177 lines
5.9 KiB
Java
/*
|
|
* This file is part of Baritone.
|
|
*
|
|
* Baritone is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU Lesser General Public License as published by
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* Baritone is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public License
|
|
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
package baritone.cache;
|
|
|
|
import baritone.api.cache.IContainerMemory;
|
|
import baritone.api.cache.IRememberedInventory;
|
|
import baritone.api.utils.IPlayerContext;
|
|
import io.netty.buffer.ByteBuf;
|
|
import io.netty.buffer.Unpooled;
|
|
import net.minecraft.item.ItemStack;
|
|
import net.minecraft.network.PacketBuffer;
|
|
import net.minecraft.util.math.BlockPos;
|
|
|
|
import java.io.IOException;
|
|
import java.nio.file.Files;
|
|
import java.nio.file.Path;
|
|
import java.util.*;
|
|
|
|
public class ContainerMemory implements IContainerMemory {
|
|
|
|
private final Path saveTo;
|
|
/**
|
|
* The current remembered inventories
|
|
*/
|
|
private final Map<BlockPos, RememberedInventory> inventories = new HashMap<>();
|
|
|
|
|
|
public ContainerMemory(Path saveTo) {
|
|
this.saveTo = saveTo;
|
|
try {
|
|
read(Files.readAllBytes(saveTo));
|
|
} catch (Exception ex) {
|
|
ex.printStackTrace();
|
|
inventories.clear();
|
|
}
|
|
}
|
|
|
|
private void read(byte[] bytes) throws IOException {
|
|
PacketBuffer in = new PacketBuffer(Unpooled.wrappedBuffer(bytes));
|
|
int chests = in.readInt();
|
|
for (int i = 0; i < chests; i++) {
|
|
int x = in.readInt();
|
|
int y = in.readInt();
|
|
int z = in.readInt();
|
|
RememberedInventory rem = new RememberedInventory();
|
|
rem.items.addAll(readItemStacks(in));
|
|
rem.size = rem.items.size();
|
|
rem.windowId = -1;
|
|
if (rem.items.isEmpty()) {
|
|
continue; // this only happens if the list has no elements, not if the list has elements that are all empty item stacks
|
|
}
|
|
inventories.put(new BlockPos(x, y, z), rem);
|
|
}
|
|
}
|
|
|
|
public synchronized void save() throws IOException {
|
|
ByteBuf buf = Unpooled.buffer(0, Integer.MAX_VALUE);
|
|
PacketBuffer out = new PacketBuffer(buf);
|
|
out.writeInt(inventories.size());
|
|
for (Map.Entry<BlockPos, RememberedInventory> entry : inventories.entrySet()) {
|
|
out = new PacketBuffer(out.writeInt(entry.getKey().getX()));
|
|
out = new PacketBuffer(out.writeInt(entry.getKey().getY()));
|
|
out = new PacketBuffer(out.writeInt(entry.getKey().getZ()));
|
|
out = writeItemStacks(entry.getValue().getContents(), out);
|
|
}
|
|
Files.write(saveTo, out.array());
|
|
}
|
|
|
|
public synchronized void setup(BlockPos pos, int windowId, int slotCount) {
|
|
RememberedInventory inventory = inventories.computeIfAbsent(pos, x -> new RememberedInventory());
|
|
inventory.windowId = windowId;
|
|
inventory.size = slotCount;
|
|
}
|
|
|
|
public synchronized Optional<RememberedInventory> getInventoryFromWindow(int windowId) {
|
|
return inventories.values().stream().filter(i -> i.windowId == windowId).findFirst();
|
|
}
|
|
|
|
@Override
|
|
public final synchronized RememberedInventory getInventoryByPos(BlockPos pos) {
|
|
return inventories.get(pos);
|
|
}
|
|
|
|
@Override
|
|
public final synchronized Map<BlockPos, IRememberedInventory> getRememberedInventories() {
|
|
// make a copy since this map is modified from the packet thread
|
|
return new HashMap<>(inventories);
|
|
}
|
|
|
|
public static List<ItemStack> readItemStacks(byte[] bytes) throws IOException {
|
|
PacketBuffer in = new PacketBuffer(Unpooled.wrappedBuffer(bytes));
|
|
return readItemStacks(in);
|
|
}
|
|
|
|
public static List<ItemStack> readItemStacks(PacketBuffer in) throws IOException {
|
|
int count = in.readInt();
|
|
List<ItemStack> result = new ArrayList<>();
|
|
for (int i = 0; i < count; i++) {
|
|
result.add(in.readItemStack());
|
|
}
|
|
return result;
|
|
}
|
|
|
|
public static byte[] writeItemStacks(List<ItemStack> write) {
|
|
ByteBuf buf = Unpooled.buffer(0, Integer.MAX_VALUE);
|
|
PacketBuffer out = new PacketBuffer(buf);
|
|
out = writeItemStacks(write, out);
|
|
return out.array();
|
|
}
|
|
|
|
public static PacketBuffer writeItemStacks(List<ItemStack> write, PacketBuffer out2) {
|
|
PacketBuffer out = out2; // avoid reassigning an argument LOL
|
|
out = new PacketBuffer(out.writeInt(write.size()));
|
|
for (ItemStack stack : write) {
|
|
out = out.writeItemStack(stack);
|
|
}
|
|
return out;
|
|
}
|
|
|
|
/**
|
|
* An inventory that we are aware of.
|
|
* <p>
|
|
* Associated with a {@link BlockPos} in {@link ContainerMemory#inventories}.
|
|
*/
|
|
public static class RememberedInventory implements IRememberedInventory {
|
|
|
|
/**
|
|
* The list of items in the inventory
|
|
*/
|
|
private final List<ItemStack> items;
|
|
|
|
/**
|
|
* The last known window ID of the inventory
|
|
*/
|
|
private int windowId;
|
|
|
|
/**
|
|
* The size of the inventory
|
|
*/
|
|
private int size;
|
|
|
|
private RememberedInventory() {
|
|
this.items = new ArrayList<>();
|
|
}
|
|
|
|
@Override
|
|
public final List<ItemStack> getContents() {
|
|
return Collections.unmodifiableList(this.items);
|
|
}
|
|
|
|
@Override
|
|
public final int getSize() {
|
|
return this.size;
|
|
}
|
|
|
|
public void updateFromOpenWindow(IPlayerContext ctx) {
|
|
items.clear();
|
|
items.addAll(ctx.player().openContainer.getInventory().subList(0, size));
|
|
}
|
|
}
|
|
}
|