Working interaction with drives

This commit is contained in:
DBotThePony 2021-08-28 10:12:13 +07:00
parent de22ab54c0
commit fa72e6ec03
Signed by: DBot
GPG Key ID: DCC23B5715498507
9 changed files with 485 additions and 482 deletions

View File

@ -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);
}

View File

@ -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();

View File

@ -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;
}

View File

@ -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();
}
}
}

View File

@ -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();
}
}

View File

@ -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_);
}
}

View File

@ -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)
);
}

View File

@ -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());
}
}

View File

@ -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;
}
};
}