Working interaction with drives
This commit is contained in:
parent
de22ab54c0
commit
fa72e6ec03
@ -0,0 +1,11 @@
|
||||
package ru.dbotthepony.mc.otm.capability.drive;
|
||||
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public interface IItemViewListener {
|
||||
void addViewItem(ItemStack stack, UUID id_upstream);
|
||||
void changeViewItem(UUID id_upstream, int new_count);
|
||||
void removeViewItem(UUID id_upstream);
|
||||
}
|
@ -5,6 +5,7 @@ import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.world.item.Item;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraftforge.common.util.INBTSerializable;
|
||||
import ru.dbotthepony.mc.otm.menu.DriveViewerMenu;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
@ -36,8 +37,10 @@ public interface IMatteryDrive {
|
||||
*/
|
||||
List<StoredStack> findItems(ItemStack stack);
|
||||
|
||||
@Nullable
|
||||
StoredStack getItem(UUID id);
|
||||
ItemStack getItem(UUID id);
|
||||
|
||||
void addListener(IItemViewListener listener);
|
||||
void removeListener(IItemViewListener listener);
|
||||
|
||||
int getStoredCount();
|
||||
int getCapacity();
|
||||
|
@ -115,10 +115,38 @@ public class MatteryDrive implements IMatteryDrive {
|
||||
return build_list;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
protected final ArrayList<IItemViewListener> listeners = new ArrayList<>();
|
||||
|
||||
@Override
|
||||
public StoredStack getItem(UUID id) {
|
||||
return items_by_id.get(id);
|
||||
public void addListener(IItemViewListener listener) {
|
||||
if (listeners.contains(listener))
|
||||
return;
|
||||
|
||||
listeners.add(listener);
|
||||
|
||||
for (var list : this.items.values()) {
|
||||
for (var state : list) {
|
||||
listener.addViewItem(state.stack(), state.id());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeListener(IItemViewListener listener) {
|
||||
if (listeners.remove(listener)) {
|
||||
for (var list : this.items.values()) {
|
||||
for (var state : list) {
|
||||
listener.removeViewItem(state.id());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public ItemStack getItem(UUID id) {
|
||||
var stack = items_by_id.get(id);
|
||||
return stack != null ? stack.stack() : ItemStack.EMPTY;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@ -136,6 +164,11 @@ public class MatteryDrive implements IMatteryDrive {
|
||||
if (!simulate) {
|
||||
state.stack().grow(max_insert);
|
||||
stored += max_insert;
|
||||
|
||||
for (var listener : listeners) {
|
||||
listener.changeViewItem(state.id(), state.stack().getCount());
|
||||
}
|
||||
|
||||
markDirty();
|
||||
}
|
||||
|
||||
@ -156,6 +189,11 @@ public class MatteryDrive implements IMatteryDrive {
|
||||
var state = new StoredStack(copy, UUID.randomUUID());
|
||||
listing.add(state);
|
||||
items_by_id.put(state.id(), state);
|
||||
|
||||
for (var listener : listeners) {
|
||||
listener.addViewItem(state.stack(), state.id());
|
||||
}
|
||||
|
||||
markDirty();
|
||||
}
|
||||
|
||||
@ -180,18 +218,30 @@ public class MatteryDrive implements IMatteryDrive {
|
||||
if (extract <= 0)
|
||||
return ItemStack.EMPTY;
|
||||
|
||||
var copy = get.stack().copy();
|
||||
copy.setCount(extract);
|
||||
|
||||
if (!simulate) {
|
||||
if (extract == get.stack().getCount()) {
|
||||
var listing = items.get(get.stack().getItem());
|
||||
listing.remove(get);
|
||||
|
||||
for (var listener : listeners) {
|
||||
listener.removeViewItem(get.id());
|
||||
}
|
||||
}
|
||||
|
||||
get.stack().shrink(extract);
|
||||
|
||||
if (get.stack().getCount() != 0) {
|
||||
for (var listener : listeners) {
|
||||
listener.changeViewItem(get.id(), get.stack().getCount());
|
||||
}
|
||||
}
|
||||
|
||||
markDirty();
|
||||
}
|
||||
|
||||
var copy = get.stack().copy();
|
||||
copy.setCount(extract);
|
||||
return copy;
|
||||
}
|
||||
|
||||
|
@ -1,29 +1,36 @@
|
||||
package ru.dbotthepony.mc.otm.menu;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.world.SimpleContainer;
|
||||
import net.minecraft.world.entity.player.Inventory;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.item.Item;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraftforge.fmllegacy.network.NetworkEvent;
|
||||
import net.minecraftforge.fmllegacy.network.PacketDistributor;
|
||||
import ru.dbotthepony.mc.otm.Registry;
|
||||
import ru.dbotthepony.mc.otm.block.entity.BlockEntityDriveViewer;
|
||||
import ru.dbotthepony.mc.otm.capability.MatteryCapability;
|
||||
import ru.dbotthepony.mc.otm.capability.drive.IItemViewListener;
|
||||
import ru.dbotthepony.mc.otm.capability.drive.IMatteryDrive;
|
||||
import ru.dbotthepony.mc.otm.menu.data.NetworkedItemView;
|
||||
import ru.dbotthepony.mc.otm.menu.data.UUIDDataContainer;
|
||||
import ru.dbotthepony.mc.otm.menu.slot.MatterySlot;
|
||||
import ru.dbotthepony.mc.otm.network.MatteryNetworking;
|
||||
import ru.dbotthepony.mc.otm.network.SetCarriedPacket;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public class DriveViewerMenu extends PoweredMatteryMenu {
|
||||
public UUIDDataContainer view_uuid;
|
||||
public NetworkedItemView view;
|
||||
public MatterySlot drive_slot;
|
||||
protected IMatteryDrive last_drive;
|
||||
|
||||
public NetworkedItemView getView() {
|
||||
return view != null ? view : NetworkedItemView.getRemote(view_uuid.getValue());
|
||||
}
|
||||
|
||||
public DriveViewerMenu(int containerID, Inventory inventory) {
|
||||
this(containerID, inventory, null);
|
||||
}
|
||||
@ -31,7 +38,6 @@ public class DriveViewerMenu extends PoweredMatteryMenu {
|
||||
public DriveViewerMenu(int containerID, Inventory inventory, @Nullable BlockEntityDriveViewer tile) {
|
||||
super(Registry.Menus.DRIVE_VIEWER, containerID, inventory, tile);
|
||||
|
||||
view_uuid = new UUIDDataContainer();
|
||||
var container = tile != null ? tile.drive_slot : new SimpleContainer(1);
|
||||
|
||||
drive_slot = new MatterySlot(container, 0) {
|
||||
@ -42,13 +48,7 @@ public class DriveViewerMenu extends PoweredMatteryMenu {
|
||||
};
|
||||
|
||||
addSlot(drive_slot);
|
||||
|
||||
if (tile != null) {
|
||||
view = new NetworkedItemView(inventory.player);
|
||||
view_uuid.setValue(view.id);
|
||||
}
|
||||
|
||||
addDataSlots(view_uuid);
|
||||
view = new NetworkedItemView();
|
||||
|
||||
addBatterySlot();
|
||||
addInventorySlots();
|
||||
@ -63,6 +63,7 @@ public class DriveViewerMenu extends PoweredMatteryMenu {
|
||||
|
||||
if (get.isEmpty()) {
|
||||
if (last_drive != null) {
|
||||
last_drive.removeListener(view);
|
||||
view.clear();
|
||||
}
|
||||
|
||||
@ -72,17 +73,18 @@ public class DriveViewerMenu extends PoweredMatteryMenu {
|
||||
|
||||
if (get_cap.isEmpty()) {
|
||||
if (last_drive != null) {
|
||||
last_drive.removeListener(view);
|
||||
view.clear();
|
||||
}
|
||||
|
||||
last_drive = null;
|
||||
} else {
|
||||
if (last_drive != get_cap.get()) {
|
||||
view.clear();
|
||||
if (last_drive != null)
|
||||
last_drive.removeListener(view);
|
||||
|
||||
for (var stack : get_cap.get().getItems()) {
|
||||
view.addItem(stack.stack(), stack.id());
|
||||
}
|
||||
view.clear();
|
||||
get_cap.get().addListener(view);
|
||||
}
|
||||
|
||||
last_drive = get_cap.get();
|
||||
@ -93,18 +95,6 @@ public class DriveViewerMenu extends PoweredMatteryMenu {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removed(Player p_38940_) {
|
||||
super.removed(p_38940_);
|
||||
|
||||
if (!p_38940_.level.isClientSide) {
|
||||
var view = getView();
|
||||
|
||||
if (view != null)
|
||||
view.remove();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getWorkingSlotStart() {
|
||||
return 0;
|
||||
@ -114,4 +104,304 @@ public class DriveViewerMenu extends PoweredMatteryMenu {
|
||||
protected int getWorkingSlotEnd() {
|
||||
return 2;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removed(Player p_38940_) {
|
||||
super.removed(p_38940_);
|
||||
|
||||
if (last_drive != null) {
|
||||
last_drive.removeListener(view);
|
||||
view.clear();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a virtual, slotless container for Player's interaction with.
|
||||
*/
|
||||
public class NetworkedItemView implements IItemViewListener {
|
||||
public record NetworkedItem(int id, ItemStack stack, UUID id_upstream) {
|
||||
public NetworkedItem(int id, ItemStack stack) {
|
||||
this(id, stack, null);
|
||||
}
|
||||
}
|
||||
|
||||
public record ClearPacket(int id) {
|
||||
public void write(FriendlyByteBuf buffer) {
|
||||
buffer.writeInt(id);
|
||||
}
|
||||
|
||||
public static ClearPacket read(FriendlyByteBuf buffer) {
|
||||
return new ClearPacket(buffer.readInt());
|
||||
}
|
||||
|
||||
public void play(Supplier<NetworkEvent.Context> context) {
|
||||
context.get().setPacketHandled(true);
|
||||
context.get().enqueueWork(() -> {
|
||||
var get = Minecraft.getInstance().player.containerMenu instanceof DriveViewerMenu menu && menu.containerId == id ? menu.view : null;
|
||||
|
||||
if (get == null) {
|
||||
throw new IllegalStateException("No such item tracker with id " + id);
|
||||
}
|
||||
|
||||
get.clear();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public record StackAddPacket(int id, int stack_id, ItemStack stack) {
|
||||
public void write(FriendlyByteBuf buffer) {
|
||||
buffer.writeInt(id);
|
||||
buffer.writeInt(stack_id);
|
||||
buffer.writeRegistryId(stack.getItem());
|
||||
buffer.writeInt(stack.getCount());
|
||||
buffer.writeBoolean(stack.getTag() != null);
|
||||
|
||||
if (stack.getTag() != null)
|
||||
buffer.writeNbt(stack.getShareTag());
|
||||
}
|
||||
|
||||
public static StackAddPacket read(FriendlyByteBuf buffer) {
|
||||
var id = buffer.readInt();
|
||||
var stack = buffer.readInt();
|
||||
var item = buffer.readRegistryIdSafe(Item.class);
|
||||
var count = buffer.readInt();
|
||||
|
||||
var state = new ItemStack(item, count);
|
||||
|
||||
if (buffer.readBoolean())
|
||||
state.readShareTag(buffer.readNbt());
|
||||
|
||||
return new StackAddPacket(id, stack, state);
|
||||
}
|
||||
|
||||
public void play(Supplier<NetworkEvent.Context> context) {
|
||||
context.get().setPacketHandled(true);
|
||||
context.get().enqueueWork(() -> {
|
||||
var get = Minecraft.getInstance().player.containerMenu instanceof DriveViewerMenu menu && menu.containerId == id ? menu.view : null;
|
||||
|
||||
if (get == null) {
|
||||
throw new IllegalStateException("No such item tracker with id " + id);
|
||||
}
|
||||
|
||||
if (get.state.containsKey(stack_id)) {
|
||||
throw new IllegalStateException("Item tracker " + id + " already has stack with id of " + stack_id);
|
||||
}
|
||||
|
||||
get.state.put(stack_id, new NetworkedItem(stack_id, stack));
|
||||
get.clearCache();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public record StackChangePacket(int id, int stack_id, int new_count) {
|
||||
public void write(FriendlyByteBuf buffer) {
|
||||
buffer.writeInt(id);
|
||||
buffer.writeInt(stack_id);
|
||||
buffer.writeInt(new_count);
|
||||
}
|
||||
|
||||
public static StackChangePacket read(FriendlyByteBuf buffer) {
|
||||
var id = buffer.readInt();
|
||||
var stack_id = buffer.readInt();
|
||||
var new_count = buffer.readInt();
|
||||
|
||||
return new StackChangePacket(id, stack_id, new_count);
|
||||
}
|
||||
|
||||
public void play(Supplier<NetworkEvent.Context> context) {
|
||||
context.get().setPacketHandled(true);
|
||||
context.get().enqueueWork(() -> {
|
||||
var get = Minecraft.getInstance().player.containerMenu instanceof DriveViewerMenu menu && menu.containerId == id ? menu.view : null;
|
||||
|
||||
if (get == null) {
|
||||
throw new IllegalStateException("No such item tracker with id " + id);
|
||||
}
|
||||
|
||||
var get_state = get.state.get(stack_id);
|
||||
|
||||
if (get_state == null) {
|
||||
throw new IllegalStateException("Item tracker " + id + " has no stack with id of " + stack_id);
|
||||
}
|
||||
|
||||
get_state.stack.setCount(new_count);
|
||||
get.clearCache();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public record StackRemovePacket(int id, int stack_id) {
|
||||
public void write(FriendlyByteBuf buffer) {
|
||||
buffer.writeInt(id);
|
||||
buffer.writeInt(stack_id);
|
||||
}
|
||||
|
||||
public static StackRemovePacket read(FriendlyByteBuf buffer) {
|
||||
var id = buffer.readInt();
|
||||
var stack_id = buffer.readInt();
|
||||
|
||||
return new StackRemovePacket(id, stack_id);
|
||||
}
|
||||
|
||||
public void play(Supplier<NetworkEvent.Context> context) {
|
||||
context.get().setPacketHandled(true);
|
||||
context.get().enqueueWork(() -> {
|
||||
var get = Minecraft.getInstance().player.containerMenu instanceof DriveViewerMenu menu && menu.containerId == id ? menu.view : null;
|
||||
|
||||
if (get == null) {
|
||||
throw new IllegalStateException("No such item tracker with id " + id);
|
||||
}
|
||||
|
||||
var get_state = get.state.remove(stack_id);
|
||||
|
||||
if (get_state == null) {
|
||||
throw new IllegalStateException("Item tracker " + id + " has no stack with id of " + stack_id);
|
||||
}
|
||||
|
||||
get.clearCache();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public record InteractPacket(int id, int stack_id) {
|
||||
public void write(FriendlyByteBuf buffer) {
|
||||
buffer.writeInt(id);
|
||||
buffer.writeInt(stack_id);
|
||||
}
|
||||
|
||||
public static InteractPacket read(FriendlyByteBuf buffer) {
|
||||
var id = buffer.readInt();
|
||||
var stack = buffer.readInt();
|
||||
return new InteractPacket(id, stack);
|
||||
}
|
||||
|
||||
public void play(Supplier<NetworkEvent.Context> context) {
|
||||
context.get().setPacketHandled(true);
|
||||
context.get().enqueueWork(() -> {
|
||||
var ply = context.get().getSender();
|
||||
|
||||
if (ply.containerMenu instanceof DriveViewerMenu menu) {
|
||||
var get = menu.containerId == id ? menu.view : null;
|
||||
|
||||
if (get == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
ply.resetLastActionTime();
|
||||
|
||||
if (menu.last_drive == null)
|
||||
return;
|
||||
|
||||
if (!menu.getCarried().isEmpty()) {
|
||||
// try to put
|
||||
menu.setCarried(menu.last_drive.insertItem(menu.getCarried(), false));
|
||||
MatteryNetworking.send(ply, new SetCarriedPacket(menu.getCarried()));
|
||||
menu.setRemoteCarried(menu.getCarried().copy());
|
||||
} else if (stack_id > -1) {
|
||||
var get_state = get.state.get(stack_id);
|
||||
|
||||
if (get_state == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
menu.setCarried(menu.last_drive.extractItem(get_state.id_upstream, 64, false));
|
||||
MatteryNetworking.send(ply, new SetCarriedPacket(menu.getCarried()));
|
||||
menu.setRemoteCarried(menu.getCarried().copy());
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
protected int next_stack_id = 0;
|
||||
|
||||
protected final HashMap<Integer, NetworkedItem> state = new HashMap<>();
|
||||
protected final HashMap<UUID, NetworkedItem> upstream_state = new HashMap<>();
|
||||
protected final ArrayList<Object> backlog = new ArrayList<>();
|
||||
|
||||
private List<NetworkedItem> view_cache;
|
||||
|
||||
public void clearCache() {
|
||||
view_cache = null;
|
||||
}
|
||||
|
||||
public List<NetworkedItem> getItems() {
|
||||
if (view_cache != null)
|
||||
return view_cache;
|
||||
|
||||
return view_cache = List.copyOf(state.values());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addViewItem(ItemStack stack, UUID id_upstream) {
|
||||
if (upstream_state.containsKey(id_upstream))
|
||||
throw new IllegalStateException("Already tracking ItemStack with upstream id " + id_upstream + "!");
|
||||
|
||||
var state = new NetworkedItem(next_stack_id++, stack.copy(), id_upstream);
|
||||
this.state.put(state.id, state);
|
||||
this.upstream_state.put(id_upstream, state);
|
||||
|
||||
if (tile != null) {
|
||||
backlog.add(new StackAddPacket(containerId, state.id, stack));
|
||||
}
|
||||
|
||||
clearCache();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void changeViewItem(UUID id_upstream, int new_count) {
|
||||
var get = upstream_state.get(id_upstream);
|
||||
|
||||
if (get == null)
|
||||
throw new IllegalStateException("Unknown ItemStack with upstream id " + id_upstream + "!");
|
||||
|
||||
get.stack.setCount(new_count);
|
||||
|
||||
if (tile != null) {
|
||||
backlog.add(new StackChangePacket(containerId, get.id, new_count));
|
||||
}
|
||||
|
||||
clearCache();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeViewItem(UUID id_upstream) {
|
||||
var get = upstream_state.get(id_upstream);
|
||||
|
||||
if (get == null)
|
||||
throw new IllegalStateException("Unknown ItemStack with upstream id " + id_upstream + "!");
|
||||
|
||||
upstream_state.remove(id_upstream);
|
||||
state.remove(get.id);
|
||||
|
||||
if (tile != null) {
|
||||
backlog.add(new StackRemovePacket(containerId, get.id));
|
||||
}
|
||||
|
||||
clearCache();
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
clearCache();
|
||||
upstream_state.clear();
|
||||
state.clear();
|
||||
|
||||
if (tile != null) {
|
||||
backlog.clear();
|
||||
backlog.add(new ClearPacket(containerId));
|
||||
}
|
||||
}
|
||||
|
||||
public void network() {
|
||||
if (tile == null)
|
||||
throw new IllegalStateException("Not a server");
|
||||
|
||||
var consumer = PacketDistributor.PLAYER.with(() -> (ServerPlayer) ply);
|
||||
|
||||
for (var packet : backlog) {
|
||||
MatteryNetworking.CHANNEL.send(consumer, packet);
|
||||
}
|
||||
|
||||
backlog.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,370 +0,0 @@
|
||||
package ru.dbotthepony.mc.otm.menu.data;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.item.Item;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraftforge.fmllegacy.network.NetworkEvent;
|
||||
import net.minecraftforge.fmllegacy.network.PacketDistributor;
|
||||
import ru.dbotthepony.mc.otm.network.MatteryNetworking;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
/**
|
||||
* Creates a virtual, slotless container for Player's interaction with.
|
||||
*/
|
||||
public class NetworkedItemView {
|
||||
public record NetworkedItem(int id, ItemStack stack, UUID id_upstream) {
|
||||
public NetworkedItem(int id, ItemStack stack) {
|
||||
this(id, stack, null);
|
||||
}
|
||||
}
|
||||
|
||||
public record ClearPacket(UUID id, boolean remove) {
|
||||
public void write(FriendlyByteBuf buffer) {
|
||||
buffer.writeLong(id.getMostSignificantBits());
|
||||
buffer.writeLong(id.getLeastSignificantBits());
|
||||
buffer.writeBoolean(remove);
|
||||
}
|
||||
|
||||
public static ClearPacket read(FriendlyByteBuf buffer) {
|
||||
return new ClearPacket(new UUID(buffer.readLong(), buffer.readLong()), buffer.readBoolean());
|
||||
}
|
||||
|
||||
public void play(Supplier<NetworkEvent.Context> context) {
|
||||
context.get().setPacketHandled(true);
|
||||
context.get().enqueueWork(() -> {
|
||||
var get = TRACKERS_REMOTE.get(id);
|
||||
|
||||
if (get == null) {
|
||||
throw new IllegalStateException("No such item tracker with id " + id);
|
||||
}
|
||||
|
||||
if (remove) {
|
||||
get.remove();
|
||||
} else {
|
||||
get.clear();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public record CreatedPacket(UUID id) {
|
||||
public void write(FriendlyByteBuf buffer) {
|
||||
buffer.writeLong(id.getMostSignificantBits());
|
||||
buffer.writeLong(id.getLeastSignificantBits());
|
||||
}
|
||||
|
||||
public static CreatedPacket read(FriendlyByteBuf buffer) {
|
||||
return new CreatedPacket(new UUID(buffer.readLong(), buffer.readLong()));
|
||||
}
|
||||
|
||||
public void play(Supplier<NetworkEvent.Context> context) {
|
||||
context.get().setPacketHandled(true);
|
||||
context.get().enqueueWork(() -> {
|
||||
new NetworkedItemView(Minecraft.getInstance().player, id, true);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public record StackAddPacket(UUID id, int stack_id, ItemStack stack) {
|
||||
public void write(FriendlyByteBuf buffer) {
|
||||
buffer.writeLong(id.getMostSignificantBits());
|
||||
buffer.writeLong(id.getLeastSignificantBits());
|
||||
buffer.writeInt(stack_id);
|
||||
buffer.writeRegistryId(stack.getItem());
|
||||
buffer.writeInt(stack.getCount());
|
||||
buffer.writeBoolean(stack.getTag() != null);
|
||||
|
||||
if (stack.getTag() != null)
|
||||
buffer.writeNbt(stack.getShareTag());
|
||||
}
|
||||
|
||||
public static StackAddPacket read(FriendlyByteBuf buffer) {
|
||||
var id = new UUID(buffer.readLong(), buffer.readLong());
|
||||
var stack = buffer.readInt();
|
||||
var item = buffer.readRegistryIdSafe(Item.class);
|
||||
var count = buffer.readInt();
|
||||
|
||||
var state = new ItemStack(item, count);
|
||||
|
||||
if (buffer.readBoolean())
|
||||
state.readShareTag(buffer.readNbt());
|
||||
|
||||
return new StackAddPacket(id, stack, state);
|
||||
}
|
||||
|
||||
public void play(Supplier<NetworkEvent.Context> context) {
|
||||
context.get().setPacketHandled(true);
|
||||
context.get().enqueueWork(() -> {
|
||||
var get = TRACKERS_REMOTE.get(id);
|
||||
|
||||
if (get == null) {
|
||||
throw new IllegalStateException("No such item tracker with id " + id);
|
||||
}
|
||||
|
||||
if (get.state.containsKey(stack_id)) {
|
||||
throw new IllegalStateException("Item tracker " + id + " already has stack with id of " + stack_id);
|
||||
}
|
||||
|
||||
get.state.put(stack_id, new NetworkedItem(stack_id, stack));
|
||||
get.clearCache();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public record InteractPacket(UUID id, int stack_id) {
|
||||
public void write(FriendlyByteBuf buffer) {
|
||||
buffer.writeLong(id.getMostSignificantBits());
|
||||
buffer.writeLong(id.getLeastSignificantBits());
|
||||
buffer.writeInt(stack_id);
|
||||
}
|
||||
|
||||
public static InteractPacket read(FriendlyByteBuf buffer) {
|
||||
var id = new UUID(buffer.readLong(), buffer.readLong());
|
||||
var stack = buffer.readInt();
|
||||
return new InteractPacket(id, stack);
|
||||
}
|
||||
|
||||
public void play(Supplier<NetworkEvent.Context> context) {
|
||||
context.get().setPacketHandled(true);
|
||||
context.get().enqueueWork(() -> {
|
||||
var get = TRACKERS_REMOTE.get(id);
|
||||
|
||||
if (get == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
var get_state = get.state.get(stack_id);
|
||||
|
||||
if (get_state == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
var ply = context.get().getSender();
|
||||
ply.resetLastActionTime();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public record StackChangePacket(UUID id, int stack_id, int new_count) {
|
||||
public void write(FriendlyByteBuf buffer) {
|
||||
buffer.writeLong(id.getMostSignificantBits());
|
||||
buffer.writeLong(id.getLeastSignificantBits());
|
||||
buffer.writeInt(stack_id);
|
||||
buffer.writeInt(new_count);
|
||||
}
|
||||
|
||||
public static StackChangePacket read(FriendlyByteBuf buffer) {
|
||||
var id = new UUID(buffer.readLong(), buffer.readLong());
|
||||
var stack_id = buffer.readInt();
|
||||
var new_count = buffer.readInt();
|
||||
|
||||
return new StackChangePacket(id, stack_id, new_count);
|
||||
}
|
||||
|
||||
public void play(Supplier<NetworkEvent.Context> context) {
|
||||
context.get().setPacketHandled(true);
|
||||
context.get().enqueueWork(() -> {
|
||||
var get = TRACKERS_REMOTE.get(id);
|
||||
|
||||
if (get == null) {
|
||||
throw new IllegalStateException("No such item tracker with id " + id);
|
||||
}
|
||||
|
||||
var get_state = get.state.get(stack_id);
|
||||
|
||||
if (get_state == null) {
|
||||
throw new IllegalStateException("Item tracker " + id + " has no stack with id of " + stack_id);
|
||||
}
|
||||
|
||||
get_state.stack.setCount(new_count);
|
||||
get.clearCache();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public record StackRemovePacket(UUID id, int stack_id) {
|
||||
public void write(FriendlyByteBuf buffer) {
|
||||
buffer.writeLong(id.getMostSignificantBits());
|
||||
buffer.writeLong(id.getLeastSignificantBits());
|
||||
buffer.writeInt(stack_id);
|
||||
}
|
||||
|
||||
public static StackRemovePacket read(FriendlyByteBuf buffer) {
|
||||
var id = new UUID(buffer.readLong(), buffer.readLong());
|
||||
var stack_id = buffer.readInt();
|
||||
|
||||
return new StackRemovePacket(id, stack_id);
|
||||
}
|
||||
|
||||
public void play(Supplier<NetworkEvent.Context> context) {
|
||||
context.get().setPacketHandled(true);
|
||||
context.get().enqueueWork(() -> {
|
||||
var get = TRACKERS_REMOTE.get(id);
|
||||
|
||||
if (get == null) {
|
||||
throw new IllegalStateException("No such item tracker with id " + id);
|
||||
}
|
||||
|
||||
var get_state = get.state.remove(stack_id);
|
||||
|
||||
if (get_state == null) {
|
||||
throw new IllegalStateException("Item tracker " + id + " has no stack with id of " + stack_id);
|
||||
}
|
||||
|
||||
get.clearCache();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public final Player ply;
|
||||
public final UUID id;
|
||||
public final boolean remote;
|
||||
protected int next_stack_id = 0;
|
||||
|
||||
protected final HashMap<Integer, NetworkedItem> state = new HashMap<>();
|
||||
protected final HashMap<UUID, NetworkedItem> upstream_state = new HashMap<>();
|
||||
protected final ArrayList<Object> backlog = new ArrayList<>();
|
||||
|
||||
// normally, filled only on server
|
||||
private static final HashMap<UUID, NetworkedItemView> TRACKERS_LOCAL = new HashMap<>();
|
||||
|
||||
// normally, filled only on client
|
||||
private static final HashMap<UUID, NetworkedItemView> TRACKERS_REMOTE = new HashMap<>();
|
||||
|
||||
public static NetworkedItemView getLocal(UUID id) {
|
||||
return TRACKERS_LOCAL.get(id);
|
||||
}
|
||||
|
||||
public static NetworkedItemView getRemote(UUID id) {
|
||||
return TRACKERS_REMOTE.get(id);
|
||||
}
|
||||
|
||||
public NetworkedItemView(Player ply) {
|
||||
this(ply, UUID.randomUUID());
|
||||
}
|
||||
|
||||
public NetworkedItemView(Player ply, UUID id) {
|
||||
this(ply, id, false);
|
||||
}
|
||||
|
||||
public NetworkedItemView(Player ply, UUID id, boolean remote) {
|
||||
this.remote = remote;
|
||||
this.ply = ply;
|
||||
this.id = id;
|
||||
|
||||
if (remote) {
|
||||
TRACKERS_REMOTE.put(this.id, this);
|
||||
} else {
|
||||
TRACKERS_LOCAL.put(this.id, this);
|
||||
MatteryNetworking.CHANNEL.send(PacketDistributor.PLAYER.with(() -> (ServerPlayer) ply), new CreatedPacket(this.id));
|
||||
}
|
||||
}
|
||||
|
||||
private List<ItemStack> view_cache;
|
||||
|
||||
public void clearCache() {
|
||||
view_cache = null;
|
||||
}
|
||||
|
||||
public boolean mayPlace(ItemStack stack) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public List<ItemStack> getItems() {
|
||||
if (view_cache != null)
|
||||
return view_cache;
|
||||
|
||||
var list = new ArrayList<ItemStack>(state.size());
|
||||
|
||||
for (var state : this.state.values())
|
||||
list.add(state.stack);
|
||||
|
||||
return view_cache = list;
|
||||
}
|
||||
|
||||
public void addItem(ItemStack stack, UUID id_upstream) {
|
||||
if (upstream_state.containsKey(id_upstream))
|
||||
throw new IllegalStateException("Already tracking ItemStack with upstream id " + id_upstream + "!");
|
||||
|
||||
var state = new NetworkedItem(next_stack_id++, stack, id_upstream);
|
||||
this.state.put(state.id, state);
|
||||
this.upstream_state.put(id_upstream, state);
|
||||
|
||||
if (!remote) {
|
||||
backlog.add(new StackAddPacket(id, state.id, stack));
|
||||
}
|
||||
|
||||
clearCache();
|
||||
}
|
||||
|
||||
public void changeItem(UUID id_upstream, int new_count) {
|
||||
var get = upstream_state.get(id_upstream);
|
||||
|
||||
if (get == null)
|
||||
throw new IllegalStateException("Unknown ItemStack with upstream id " + id_upstream + "!");
|
||||
|
||||
get.stack.setCount(new_count);
|
||||
|
||||
if (!remote) {
|
||||
backlog.add(new StackChangePacket(id, get.id, new_count));
|
||||
}
|
||||
|
||||
clearCache();
|
||||
}
|
||||
|
||||
public void removeItem(UUID id_upstream) {
|
||||
var get = upstream_state.get(id_upstream);
|
||||
|
||||
if (get == null)
|
||||
throw new IllegalStateException("Unknown ItemStack with upstream id " + id_upstream + "!");
|
||||
|
||||
upstream_state.remove(id_upstream);
|
||||
state.remove(get.id);
|
||||
|
||||
if (!remote) {
|
||||
backlog.add(new StackRemovePacket(id, get.id));
|
||||
}
|
||||
|
||||
clearCache();
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
clearCache();
|
||||
upstream_state.clear();
|
||||
state.clear();
|
||||
|
||||
if (!remote) {
|
||||
backlog.clear();
|
||||
backlog.add(new ClearPacket(id, false));
|
||||
}
|
||||
}
|
||||
|
||||
public void remove() {
|
||||
if (!remote) {
|
||||
TRACKERS_LOCAL.remove(id);
|
||||
backlog.clear();
|
||||
backlog.add(new ClearPacket(id, true));
|
||||
}
|
||||
}
|
||||
|
||||
public void network() {
|
||||
if (remote)
|
||||
throw new IllegalStateException("Not a server");
|
||||
|
||||
var consumer = PacketDistributor.PLAYER.with(() -> (ServerPlayer) ply);
|
||||
|
||||
for (var packet : backlog) {
|
||||
MatteryNetworking.CHANNEL.send(consumer, packet);
|
||||
}
|
||||
|
||||
backlog.clear();
|
||||
}
|
||||
}
|
@ -1,35 +0,0 @@
|
||||
package ru.dbotthepony.mc.otm.menu.slot;
|
||||
|
||||
import net.minecraft.world.Container;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import ru.dbotthepony.mc.otm.menu.data.NetworkedItemView;
|
||||
|
||||
public class ItemViewInputSlot extends MatterySlot {
|
||||
public ItemViewInputSlot(Container p_40223_, int index, int x, int y, boolean auto_bg) {
|
||||
super(p_40223_, index, x, y, auto_bg);
|
||||
}
|
||||
|
||||
public ItemViewInputSlot(Container p_40223_, int index, int x, int y) {
|
||||
super(p_40223_, index, x, y);
|
||||
}
|
||||
|
||||
public ItemViewInputSlot(Container p_40223_, int index) {
|
||||
super(p_40223_, index);
|
||||
}
|
||||
|
||||
public NetworkedItemView view;
|
||||
|
||||
@Override
|
||||
public boolean mayPlace(ItemStack p_40231_) {
|
||||
if (view == null || view.remote) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return view.mayPlace(p_40231_);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void set(ItemStack p_40240_) {
|
||||
super.set(p_40240_);
|
||||
}
|
||||
}
|
@ -1,11 +1,13 @@
|
||||
package ru.dbotthepony.mc.otm.network;
|
||||
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraftforge.fmllegacy.network.NetworkDirection;
|
||||
import net.minecraftforge.fmllegacy.network.NetworkRegistry;
|
||||
import net.minecraftforge.fmllegacy.network.PacketDistributor;
|
||||
import net.minecraftforge.fmllegacy.network.simple.SimpleChannel;
|
||||
import ru.dbotthepony.mc.otm.OverdriveThatMatters;
|
||||
import ru.dbotthepony.mc.otm.menu.data.NetworkedItemView;
|
||||
import ru.dbotthepony.mc.otm.menu.DriveViewerMenu;
|
||||
import ru.dbotthepony.mc.otm.network.android.*;
|
||||
|
||||
import java.util.Optional;
|
||||
@ -22,6 +24,20 @@ public class MatteryNetworking {
|
||||
PROTOCOL_VERSION::equals
|
||||
);
|
||||
|
||||
public static void send(ServerPlayer ply, Object ...messages) {
|
||||
var supplier = PacketDistributor.PLAYER.with(() -> ply);
|
||||
|
||||
for (var message : messages) {
|
||||
CHANNEL.send(supplier, message);
|
||||
}
|
||||
}
|
||||
|
||||
public static void send(Object ...messages) {
|
||||
for (var message : messages) {
|
||||
CHANNEL.sendToServer(message);
|
||||
}
|
||||
}
|
||||
|
||||
public static void register() {
|
||||
CHANNEL.registerMessage(
|
||||
next_network_id++,
|
||||
@ -133,46 +149,55 @@ public class MatteryNetworking {
|
||||
|
||||
CHANNEL.registerMessage(
|
||||
next_network_id++,
|
||||
NetworkedItemView.ClearPacket.class,
|
||||
NetworkedItemView.ClearPacket::write,
|
||||
NetworkedItemView.ClearPacket::read,
|
||||
NetworkedItemView.ClearPacket::play,
|
||||
DriveViewerMenu.NetworkedItemView.ClearPacket.class,
|
||||
DriveViewerMenu.NetworkedItemView.ClearPacket::write,
|
||||
DriveViewerMenu.NetworkedItemView.ClearPacket::read,
|
||||
DriveViewerMenu.NetworkedItemView.ClearPacket::play,
|
||||
Optional.of(NetworkDirection.PLAY_TO_CLIENT)
|
||||
);
|
||||
|
||||
CHANNEL.registerMessage(
|
||||
next_network_id++,
|
||||
NetworkedItemView.CreatedPacket.class,
|
||||
NetworkedItemView.CreatedPacket::write,
|
||||
NetworkedItemView.CreatedPacket::read,
|
||||
NetworkedItemView.CreatedPacket::play,
|
||||
DriveViewerMenu.NetworkedItemView.StackAddPacket.class,
|
||||
DriveViewerMenu.NetworkedItemView.StackAddPacket::write,
|
||||
DriveViewerMenu.NetworkedItemView.StackAddPacket::read,
|
||||
DriveViewerMenu.NetworkedItemView.StackAddPacket::play,
|
||||
Optional.of(NetworkDirection.PLAY_TO_CLIENT)
|
||||
);
|
||||
|
||||
CHANNEL.registerMessage(
|
||||
next_network_id++,
|
||||
NetworkedItemView.StackAddPacket.class,
|
||||
NetworkedItemView.StackAddPacket::write,
|
||||
NetworkedItemView.StackAddPacket::read,
|
||||
NetworkedItemView.StackAddPacket::play,
|
||||
DriveViewerMenu.NetworkedItemView.StackChangePacket.class,
|
||||
DriveViewerMenu.NetworkedItemView.StackChangePacket::write,
|
||||
DriveViewerMenu.NetworkedItemView.StackChangePacket::read,
|
||||
DriveViewerMenu.NetworkedItemView.StackChangePacket::play,
|
||||
Optional.of(NetworkDirection.PLAY_TO_CLIENT)
|
||||
);
|
||||
|
||||
CHANNEL.registerMessage(
|
||||
next_network_id++,
|
||||
NetworkedItemView.StackChangePacket.class,
|
||||
NetworkedItemView.StackChangePacket::write,
|
||||
NetworkedItemView.StackChangePacket::read,
|
||||
NetworkedItemView.StackChangePacket::play,
|
||||
DriveViewerMenu.NetworkedItemView.StackRemovePacket.class,
|
||||
DriveViewerMenu.NetworkedItemView.StackRemovePacket::write,
|
||||
DriveViewerMenu.NetworkedItemView.StackRemovePacket::read,
|
||||
DriveViewerMenu.NetworkedItemView.StackRemovePacket::play,
|
||||
Optional.of(NetworkDirection.PLAY_TO_CLIENT)
|
||||
);
|
||||
|
||||
CHANNEL.registerMessage(
|
||||
next_network_id++,
|
||||
NetworkedItemView.StackRemovePacket.class,
|
||||
NetworkedItemView.StackRemovePacket::write,
|
||||
NetworkedItemView.StackRemovePacket::read,
|
||||
NetworkedItemView.StackRemovePacket::play,
|
||||
DriveViewerMenu.NetworkedItemView.InteractPacket.class,
|
||||
DriveViewerMenu.NetworkedItemView.InteractPacket::write,
|
||||
DriveViewerMenu.NetworkedItemView.InteractPacket::read,
|
||||
DriveViewerMenu.NetworkedItemView.InteractPacket::play,
|
||||
Optional.of(NetworkDirection.PLAY_TO_SERVER)
|
||||
);
|
||||
|
||||
CHANNEL.registerMessage(
|
||||
next_network_id++,
|
||||
SetCarriedPacket.class,
|
||||
SetCarriedPacket::write,
|
||||
SetCarriedPacket::read,
|
||||
SetCarriedPacket::play,
|
||||
Optional.of(NetworkDirection.PLAY_TO_CLIENT)
|
||||
);
|
||||
}
|
||||
|
@ -0,0 +1,32 @@
|
||||
package ru.dbotthepony.mc.otm.network;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import net.minecraft.world.inventory.AbstractContainerMenu;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraftforge.api.distmarker.Dist;
|
||||
import net.minecraftforge.fml.DistExecutor;
|
||||
import net.minecraftforge.fmllegacy.network.NetworkEvent;
|
||||
import ru.dbotthepony.mc.otm.capability.MatteryCapability;
|
||||
import ru.dbotthepony.mc.otm.network.android.AndroidBatteryPacket;
|
||||
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public record SetCarriedPacket(ItemStack carried) {
|
||||
public void write(FriendlyByteBuf buffer) {
|
||||
buffer.writeItem(carried);
|
||||
}
|
||||
|
||||
public void play(Supplier<NetworkEvent.Context> context) {
|
||||
context.get().setPacketHandled(true);
|
||||
context.get().enqueueWork(() -> {
|
||||
if (Minecraft.getInstance().player.containerMenu != null) {
|
||||
Minecraft.getInstance().player.containerMenu.setCarried(carried);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static SetCarriedPacket read(FriendlyByteBuf buffer) {
|
||||
return new SetCarriedPacket(buffer.readItem());
|
||||
}
|
||||
}
|
@ -9,6 +9,7 @@ import ru.dbotthepony.mc.otm.menu.MatteryMenu;
|
||||
import ru.dbotthepony.mc.otm.menu.slot.BatterySlot;
|
||||
import ru.dbotthepony.mc.otm.menu.slot.MatterySlot;
|
||||
import ru.dbotthepony.mc.otm.menu.widget.GaugeWidget;
|
||||
import ru.dbotthepony.mc.otm.network.MatteryNetworking;
|
||||
import ru.dbotthepony.mc.otm.screen.panels.*;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
@ -49,13 +50,7 @@ public class DriveViewerScreen extends MatteryScreen<DriveViewerMenu> implements
|
||||
var scroll_bar = new ScrollBarPanel(this, frame, 0, 0, 0);
|
||||
scroll_bar.setDock(Dock.RIGHT);
|
||||
scroll_bar.setupRowMultiplier(() -> {
|
||||
var view = menu.getView();
|
||||
|
||||
if (view != null) {
|
||||
return view.getItems().size() / GRID_WIDTH;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return menu.view.getItems().size() / GRID_WIDTH;
|
||||
});
|
||||
|
||||
for (int i = 0; i < GRID_WIDTH * GRID_HEIGHT; i++) {
|
||||
@ -65,27 +60,29 @@ public class DriveViewerScreen extends MatteryScreen<DriveViewerMenu> implements
|
||||
@Nonnull
|
||||
@Override
|
||||
protected ItemStack getItemStack() {
|
||||
int findex = index + scroll_bar.getScroll(GRID_WIDTH);
|
||||
int findex = index + scroll_bar.getScroll(menu.view.getItems().size() / GRID_WIDTH);
|
||||
|
||||
var view = menu.getView();
|
||||
|
||||
if (view != null) {
|
||||
var list = view.getItems();
|
||||
var list = menu.view.getItems();
|
||||
|
||||
if (findex >= list.size()) {
|
||||
return ItemStack.EMPTY;
|
||||
}
|
||||
|
||||
return list.get(findex);
|
||||
}
|
||||
|
||||
return ItemStack.EMPTY;
|
||||
return list.get(findex).stack();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean mouseScrolledInner(double mouse_x, double mouse_y, double scroll) {
|
||||
return scroll_bar.mouseScrolledInner(mouse_x, mouse_y, scroll);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean mouseClickedInner(double mouse_x, double mouse_y, int flag) {
|
||||
int findex = index + scroll_bar.getScroll(GRID_WIDTH);
|
||||
var list = menu.view.getItems();
|
||||
MatteryNetworking.send(new DriveViewerMenu.NetworkedItemView.InteractPacket(menu.containerId, findex >= list.size() ? -1 : list.get(findex).id()));
|
||||
return true;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user