Move net packet to kotlin, add more network channels

This commit is contained in:
DBotThePony 2022-08-25 11:27:57 +07:00
parent 69b8115395
commit de7f89186d
Signed by: DBot
GPG Key ID: DCC23B5715498507
39 changed files with 518 additions and 859 deletions

View File

@ -28,8 +28,7 @@ import ru.dbotthepony.mc.otm.item.weapon.AbstractWeaponItem;
import ru.dbotthepony.mc.otm.item.PortableCondensationDriveItem;
import ru.dbotthepony.mc.otm.matter.MatterDataKt;
import ru.dbotthepony.mc.otm.matter.MatterRegistryKt;
import ru.dbotthepony.mc.otm.network.AndroidNetworkChannel;
import ru.dbotthepony.mc.otm.network.MatteryNetworking;
import ru.dbotthepony.mc.otm.network.*;
import ru.dbotthepony.mc.otm.registry.*;
import ru.dbotthepony.mc.otm.storage.*;
@ -100,8 +99,11 @@ public final class OverdriveThatMatters {
}
private void setup(final FMLCommonSetupEvent event) {
MatteryNetworking.register();
AndroidNetworkChannel.INSTANCE.register();
MenuNetworkChannel.INSTANCE.register();
WeaponNetworkChannel.INSTANCE.register();
RegistryNetworkChannel.INSTANCE.register();
WorldNetworkChannel.INSTANCE.register();
ITEM_STORAGE = StorageRegistry.register(ItemStackWrapper.class, ItemStackWrapper.EMPTY, new ImpreciseFraction("3.125"));

View File

@ -2,6 +2,7 @@ package ru.dbotthepony.mc.otm.capability;
import mekanism.api.energy.IStrictEnergyHandler;
import net.minecraftforge.common.capabilities.*;
import org.jetbrains.annotations.NotNull;
import ru.dbotthepony.mc.otm.capability.drive.IMatteryDrive;
import ru.dbotthepony.mc.otm.capability.matter.IMatterHandler;
import ru.dbotthepony.mc.otm.capability.matter.IMatterTaskProvider;
@ -10,16 +11,43 @@ import ru.dbotthepony.mc.otm.graph.matter.IMatterGraphNode;
import ru.dbotthepony.mc.otm.graph.storage.IStorageGraphNode;
import ru.dbotthepony.mc.otm.storage.IStorageStack;
import javax.annotation.Nonnull;
public class MatteryCapability {
@Nonnull
@NotNull
public static final Capability<IMatteryEnergyStorage> ENERGY = CapabilityManager.get(new CapabilityToken<>() {});
@Nonnull
@NotNull
public static final Capability<AndroidCapability> ANDROID = CapabilityManager.get(new CapabilityToken<>() {});
@Nonnull
@NotNull
public static final Capability<IMatterHandler> MATTER = CapabilityManager.get(new CapabilityToken<>() {});
@Nonnull
@NotNull
public static final Capability<IMatterGraphNode> MATTER_NODE = CapabilityManager.get(new CapabilityToken<>() {});
@Nonnull
@NotNull
public static final Capability<IPatternStorage> PATTERN = CapabilityManager.get(new CapabilityToken<>() {});
@Nonnull
@NotNull
public static final Capability<IMatterTaskProvider> TASK = CapabilityManager.get(new CapabilityToken<>() {});
@Nonnull
@NotNull
public static final Capability<IMatteryDrive<IStorageStack>> DRIVE = CapabilityManager.get(new CapabilityToken<>() {});
@Nonnull
@NotNull
public static final Capability<IStorageGraphNode> STORAGE_NODE = CapabilityManager.get(new CapabilityToken<>() {});
@Nonnull
@NotNull
public static final Capability<IStrictEnergyHandler> MEKANISM_ENERGY = CapabilityManager.get(new CapabilityToken<>() {});
@SuppressWarnings("unused")

View File

@ -8,8 +8,8 @@ import net.minecraft.world.item.ItemStack;
import ru.dbotthepony.mc.otm.capability.matter.MatterTask;
import ru.dbotthepony.mc.otm.capability.matter.PatternState;
import ru.dbotthepony.mc.otm.menu.MatterPanelMenu;
import ru.dbotthepony.mc.otm.network.MatteryNetworking;
import ru.dbotthepony.mc.otm.network.PatternReplicationRequestPacket;
import ru.dbotthepony.mc.otm.menu.ReplicationRequestPacket;
import ru.dbotthepony.mc.otm.network.MenuNetworkChannel;
import ru.dbotthepony.mc.otm.client.screen.panels.*;
import javax.annotation.Nonnull;
@ -388,7 +388,7 @@ public class MatterPanelScreen extends MatteryScreen<MatterPanelMenu> {
}
MatteryNetworking.CHANNEL.sendToServer(new PatternReplicationRequestPacket(state, value));
MenuNetworkChannel.INSTANCE.sendToServer(new ReplicationRequestPacket(state, value));
pattern_frame.remove();
});

View File

@ -1,30 +0,0 @@
package ru.dbotthepony.mc.otm.menu.data;
import net.minecraft.client.Minecraft;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraftforge.network.NetworkEvent;
import java.util.function.Supplier;
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 INetworkedItemViewSupplier supplier && Minecraft.getInstance().player.containerMenu.containerId == id ? supplier.getNetworkedItemView() : null;
if (get == null) {
throw new IllegalStateException("No such item tracker with id " + id);
}
get.clear();
});
}
}

View File

@ -1,11 +0,0 @@
package ru.dbotthepony.mc.otm.menu.data;
import net.minecraft.MethodsReturnNonnullByDefault;
import javax.annotation.ParametersAreNonnullByDefault;
@MethodsReturnNonnullByDefault
@ParametersAreNonnullByDefault
public interface INetworkedItemViewSupplier {
NetworkedItemView getNetworkedItemView();
}

View File

@ -1,37 +0,0 @@
package ru.dbotthepony.mc.otm.menu.data;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.world.inventory.ClickAction;
import net.minecraft.world.inventory.ClickType;
import net.minecraftforge.network.NetworkEvent;
import java.util.function.Supplier;
public record InteractPacket(int id, int stack_id, ClickType click, ClickAction action) {
public void write(FriendlyByteBuf buffer) {
buffer.writeInt(id);
buffer.writeInt(stack_id);
buffer.writeEnum(click);
buffer.writeEnum(action);
}
public static InteractPacket read(FriendlyByteBuf buffer) {
var id = buffer.readInt();
var stack = buffer.readInt();
var click = buffer.readEnum(ClickType.class);
var action = buffer.readEnum(ClickAction.class);
return new InteractPacket(id, stack, click, action);
}
public void play(Supplier<NetworkEvent.Context> context) {
context.get().setPacketHandled(true);
context.get().enqueueWork(() -> {
var ply = context.get().getSender();
if (ply.containerMenu instanceof INetworkedItemViewSupplier supplier && ply.containerMenu.containerId == id) {
ply.resetLastActionTime();
supplier.getNetworkedItemView().playerInteract(this);
}
});
}
}

View File

@ -1,40 +0,0 @@
package ru.dbotthepony.mc.otm.network;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraftforge.network.NetworkEvent;
import ru.dbotthepony.mc.otm.capability.matter.MatterTask;
import ru.dbotthepony.mc.otm.menu.MatterPanelMenu;
import java.util.UUID;
import java.util.function.Supplier;
public record CancelMatterTaskPacket(UUID id) {
public CancelMatterTaskPacket(UUID id) {
this.id = id;
}
public CancelMatterTaskPacket(MatterTask task) {
this(task.id());
}
public void write(FriendlyByteBuf buffer) {
buffer.writeLong(id.getMostSignificantBits());
buffer.writeLong(id.getLeastSignificantBits());
}
public void play(Supplier<NetworkEvent.Context> context) {
context.get().setPacketHandled(true);
context.get().enqueueWork(() -> {
var player = context.get().getSender();
if (player.containerMenu instanceof MatterPanelMenu menu) {
menu.receiveTaskCancel(player, id);
}
});
}
public static CancelMatterTaskPacket read(FriendlyByteBuf buffer) {
return new CancelMatterTaskPacket(new UUID(buffer.readLong(), buffer.readLong()));
}
}

View File

@ -1,54 +0,0 @@
package ru.dbotthepony.mc.otm.network;
import net.minecraft.client.Minecraft;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.fml.DistExecutor;
import net.minecraftforge.network.NetworkEvent;
import ru.dbotthepony.mc.otm.OverdriveThatMatters;
import ru.dbotthepony.mc.otm.capability.matter.MatterTask;
import ru.dbotthepony.mc.otm.menu.MatterPanelMenu;
import javax.annotation.ParametersAreNonnullByDefault;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Objects;
import java.util.function.Supplier;
@ParametersAreNonnullByDefault
public record MatterTaskPacket(boolean action, Collection<MatterTask> state) {
public void write(FriendlyByteBuf buffer) {
buffer.writeBoolean(action);
buffer.writeInt(state.size());
for (var state1 : state)
state1.write(buffer);
}
public void play(Supplier<NetworkEvent.Context> context) {
context.get().setPacketHandled(true);
context.get().enqueueWork(() -> DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> this::playClient));
}
private void playClient() {
if (Minecraft.getInstance().player.containerMenu instanceof MatterPanelMenu menu) {
if (action)
menu.networkTasksUpdated(state);
else
menu.networkTasksRemoved(state);
} else {
OverdriveThatMatters.LOGGER.error("Receive task state list, but no valid container is open / open container is not MatterPanelMenu!");
}
}
public static MatterTaskPacket read(FriendlyByteBuf buffer) {
boolean action = buffer.readBoolean();
int amount = buffer.readInt();
var list = new ArrayList<MatterTask>(amount);
for (int i = 0; i < amount; i++)
list.add(Objects.requireNonNull(MatterTask.read(buffer)));
return new MatterTaskPacket(action, list);
}
}

View File

@ -1,262 +0,0 @@
package ru.dbotthepony.mc.otm.network;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.level.ServerPlayer;
import net.minecraftforge.network.NetworkDirection;
import net.minecraftforge.network.NetworkRegistry;
import net.minecraftforge.network.PacketDistributor;
import net.minecraftforge.network.simple.SimpleChannel;
import ru.dbotthepony.mc.otm.OverdriveThatMatters;
import ru.dbotthepony.mc.otm.block.entity.EnergyCounterPacket;
import ru.dbotthepony.mc.otm.block.entity.storage.ItemMonitorPlayerSettings;
import ru.dbotthepony.mc.otm.container.ItemFilterSlotPacket;
import ru.dbotthepony.mc.otm.item.weapon.WeaponScopePacket;
import ru.dbotthepony.mc.otm.item.weapon.WeaponFireInputPacket;
import ru.dbotthepony.mc.otm.matter.RegistryPacketClear;
import ru.dbotthepony.mc.otm.matter.RegistryPacketFullUpdate;
import ru.dbotthepony.mc.otm.matter.RegistryPacketRemove;
import ru.dbotthepony.mc.otm.matter.RegistryPacketUpdate;
import ru.dbotthepony.mc.otm.menu.data.*;
import ru.dbotthepony.mc.otm.menu.widget.BooleanPlayerInputPacket;
import ru.dbotthepony.mc.otm.menu.widget.NumberPlayerInputPacket;
import ru.dbotthepony.mc.otm.menu.widget.OneWayPlayerInputPacket;
import java.util.Optional;
public class MatteryNetworking {
private static final String PROTOCOL_VERSION = "2";
private static int next_network_id = 0;
public static final SimpleChannel CHANNEL = NetworkRegistry.newSimpleChannel(
new ResourceLocation(OverdriveThatMatters.MOD_ID, "main"),
() -> PROTOCOL_VERSION,
PROTOCOL_VERSION::equals,
PROTOCOL_VERSION::equals
);
public static void send(ServerPlayer ply, Object ...messages) {
if (ply == null) {
for (var message : messages) {
CHANNEL.sendToServer(message);
}
return;
}
var supplier = PacketDistributor.PLAYER.with(() -> ply);
for (var message : messages) {
CHANNEL.send(supplier, message);
}
}
public static void register() {
CHANNEL.registerMessage(
next_network_id++,
PatternGridPacket.class,
PatternGridPacket::write,
PatternGridPacket::read,
PatternGridPacket::play,
Optional.of(NetworkDirection.PLAY_TO_CLIENT)
);
CHANNEL.registerMessage(
next_network_id++,
MatterTaskPacket.class,
MatterTaskPacket::write,
MatterTaskPacket::read,
MatterTaskPacket::play,
Optional.of(NetworkDirection.PLAY_TO_CLIENT)
);
CHANNEL.registerMessage(
next_network_id++,
CancelMatterTaskPacket.class,
CancelMatterTaskPacket::write,
CancelMatterTaskPacket::read,
CancelMatterTaskPacket::play,
Optional.of(NetworkDirection.PLAY_TO_SERVER)
);
CHANNEL.registerMessage(
next_network_id++,
PatternReplicationRequestPacket.class,
PatternReplicationRequestPacket::write,
PatternReplicationRequestPacket::read,
PatternReplicationRequestPacket::play,
Optional.of(NetworkDirection.PLAY_TO_SERVER)
);
CHANNEL.registerMessage(
next_network_id++,
RegistryPacketClear.class,
RegistryPacketClear::write,
RegistryPacketClear.Companion::read,
RegistryPacketClear::play,
Optional.of(NetworkDirection.PLAY_TO_CLIENT)
);
CHANNEL.registerMessage(
next_network_id++,
RegistryPacketUpdate.class,
RegistryPacketUpdate::write,
RegistryPacketUpdate.Companion::read,
RegistryPacketUpdate::play,
Optional.of(NetworkDirection.PLAY_TO_CLIENT)
);
CHANNEL.registerMessage(
next_network_id++,
RegistryPacketFullUpdate.class,
RegistryPacketFullUpdate::write,
RegistryPacketFullUpdate.Companion::read,
RegistryPacketFullUpdate::play,
Optional.of(NetworkDirection.PLAY_TO_CLIENT)
);
CHANNEL.registerMessage(
next_network_id++,
RegistryPacketRemove.class,
RegistryPacketRemove::write,
RegistryPacketRemove.Companion::read,
RegistryPacketRemove::play,
Optional.of(NetworkDirection.PLAY_TO_CLIENT)
);
CHANNEL.registerMessage(
next_network_id++,
ClearPacket.class,
ClearPacket::write,
ClearPacket::read,
ClearPacket::play,
Optional.of(NetworkDirection.PLAY_TO_CLIENT)
);
CHANNEL.registerMessage(
next_network_id++,
StackAddPacket.class,
StackAddPacket::write,
StackAddPacket.Companion::read,
StackAddPacket::play,
Optional.of(NetworkDirection.PLAY_TO_CLIENT)
);
CHANNEL.registerMessage(
next_network_id++,
StackChangePacket.class,
StackChangePacket::write,
StackChangePacket.Companion::read,
StackChangePacket::play,
Optional.of(NetworkDirection.PLAY_TO_CLIENT)
);
CHANNEL.registerMessage(
next_network_id++,
StackRemovePacket.class,
StackRemovePacket::write,
StackRemovePacket.Companion::read,
StackRemovePacket::play,
Optional.of(NetworkDirection.PLAY_TO_CLIENT)
);
CHANNEL.registerMessage(
next_network_id++,
InteractPacket.class,
InteractPacket::write,
InteractPacket::read,
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)
);
CHANNEL.registerMessage(
next_network_id++,
EnergyCounterPacket.class,
EnergyCounterPacket::write,
EnergyCounterPacket.Companion::read,
EnergyCounterPacket::play,
Optional.of(NetworkDirection.PLAY_TO_CLIENT)
);
CHANNEL.registerMessage(
next_network_id++,
BooleanPlayerInputPacket.class,
BooleanPlayerInputPacket::write,
BooleanPlayerInputPacket.Companion::read,
BooleanPlayerInputPacket::play,
Optional.of(NetworkDirection.PLAY_TO_SERVER)
);
CHANNEL.registerMessage(
next_network_id++,
OneWayPlayerInputPacket.class,
OneWayPlayerInputPacket::write,
OneWayPlayerInputPacket.Companion::read,
OneWayPlayerInputPacket::play,
Optional.of(NetworkDirection.PLAY_TO_SERVER)
);
CHANNEL.registerMessage(
next_network_id++,
NumberPlayerInputPacket.class,
NumberPlayerInputPacket::write,
NumberPlayerInputPacket.Companion::read,
NumberPlayerInputPacket::play,
Optional.of(NetworkDirection.PLAY_TO_SERVER)
);
CHANNEL.registerMessage(
next_network_id++,
MultiByteDataContainerPacket.class,
MultiByteDataContainerPacket::write,
MultiByteDataContainerPacket.Companion::read,
MultiByteDataContainerPacket::play,
Optional.of(NetworkDirection.PLAY_TO_CLIENT)
);
CHANNEL.registerMessage(
next_network_id++,
WeaponScopePacket.class,
WeaponScopePacket::write,
WeaponScopePacket.Companion::read,
WeaponScopePacket::play,
Optional.of(NetworkDirection.PLAY_TO_SERVER)
);
CHANNEL.registerMessage(
next_network_id++,
WeaponFireInputPacket.class,
WeaponFireInputPacket::write,
WeaponFireInputPacket.Companion::read,
WeaponFireInputPacket::play,
Optional.of(NetworkDirection.PLAY_TO_SERVER)
);
CHANNEL.registerMessage(
next_network_id++,
ItemFilterSlotPacket.class,
ItemFilterSlotPacket::write,
ItemFilterSlotPacket.Companion::read,
ItemFilterSlotPacket::play
// Optional.of(NetworkDirection.)
);
CHANNEL.registerMessage(
next_network_id++,
ItemMonitorPlayerSettings.class,
ItemMonitorPlayerSettings::write,
ItemMonitorPlayerSettings.Companion::read,
ItemMonitorPlayerSettings::play
// Optional.of(NetworkDirection.)
);
}
}

View File

@ -1,62 +0,0 @@
package ru.dbotthepony.mc.otm.network;
import net.minecraft.network.FriendlyByteBuf;
import java.math.BigDecimal;
import java.math.BigInteger;
public class NetworkHelper {
public static BigDecimal readDecimal(FriendlyByteBuf buffer) {
int scale = buffer.readInt();
int length = buffer.readByte() & 0xFF;
byte[] bytes = new byte[length];
for (int i = 0; i < length; i++)
bytes[i] = buffer.readByte();
return new BigDecimal(new BigInteger(bytes), scale);
}
public static void writeDecimal(FriendlyByteBuf buffer, BigDecimal value) {
buffer.writeInt(value.scale());
byte[] build = value.unscaledValue().toByteArray();
buffer.writeByte(build.length);
for (byte b : build) buffer.writeByte(b);
}
public static short[] bytesToShorts(byte[] input) {
if (input.length % 2 != 0) {
short[] values = new short[input.length / 2 + 1];
for (int i = 0; i < values.length - 1; i++)
values[i] = (short) ((input[i * 2] & 0xFF) | (input[i * 2 + 1] & 0xFF) << 8);
values[values.length - 1] = input[input.length - 1];
return values;
}
short[] values = new short[input.length / 2];
for (int i = 0; i < values.length; i++)
values[i] = (short) ((input[i * 2] & 0xFF) | (input[i * 2 + 1] & 0xFF) << 8);
return values;
}
public static byte[] shortsToBytes(short[] input) {
return shortsToBytes(input, 0);
}
public static byte[] shortsToBytes(short[] input, int offset) {
byte[] values = new byte[(input.length - offset) * 2];
for (int i = offset; i < input.length; i++) {
int realI = i - offset;
values[realI * 2] = (byte) (input[i] & 0xFF);
values[realI * 2 + 1] = (byte) ((input[i] & 0xFF00) >> 8);
}
return values;
}
}

View File

@ -1,56 +0,0 @@
package ru.dbotthepony.mc.otm.network;
import net.minecraft.client.Minecraft;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.fml.DistExecutor;
import net.minecraftforge.network.NetworkEvent;
import ru.dbotthepony.mc.otm.OverdriveThatMatters;
import ru.dbotthepony.mc.otm.capability.matter.PatternState;
import ru.dbotthepony.mc.otm.menu.MatterPanelMenu;
import javax.annotation.ParametersAreNonnullByDefault;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Objects;
import java.util.function.Supplier;
@ParametersAreNonnullByDefault
public record PatternGridPacket(boolean action, Collection<PatternState> state) {
public void write(FriendlyByteBuf buffer) {
buffer.writeBoolean(action);
buffer.writeInt(state.size());
for (var state1 : state)
state1.write(buffer);
}
public void play(Supplier<NetworkEvent.Context> context) {
context.get().setPacketHandled(true);
context.get().enqueueWork(() -> DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> this::playClient));
}
private void playClient() {
if (Minecraft.getInstance().player.containerMenu instanceof MatterPanelMenu menu) {
if (action)
menu.networkPatternsUpdated(state);
else
menu.networkPatternsRemoved(state);
return;
}
OverdriveThatMatters.LOGGER.error("Receive pattern state list, but no valid container is open / container is not MatterPanelMenu!");
}
public static PatternGridPacket read(FriendlyByteBuf buffer) {
boolean action = buffer.readBoolean();
int amount = buffer.readInt();
var list = new ArrayList<PatternState>(amount);
for (int i = 0; i < amount; i++)
list.add(Objects.requireNonNull(PatternState.read(buffer)));
return new PatternGridPacket(action, list);
}
}

View File

@ -1,38 +0,0 @@
package ru.dbotthepony.mc.otm.network;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraftforge.network.NetworkEvent;
import ru.dbotthepony.mc.otm.capability.matter.PatternState;
import ru.dbotthepony.mc.otm.menu.MatterPanelMenu;
import java.util.function.Supplier;
public record PatternReplicationRequestPacket(PatternState state, int how_much) {
public PatternReplicationRequestPacket(PatternState state, int how_much) {
this.state = state;
this.how_much = Math.max(1, Math.min(99999, how_much));
}
public void write(FriendlyByteBuf buffer) {
state.write(buffer);
buffer.writeInt(how_much);
}
public void play(Supplier<NetworkEvent.Context> context) {
context.get().setPacketHandled(true);
context.get().enqueueWork(() -> {
if (state == null)
return;
var ply = context.get().getSender();
if (ply.containerMenu instanceof MatterPanelMenu menu)
menu.requestReplication(ply, state, how_much);
});
}
public static PatternReplicationRequestPacket read(FriendlyByteBuf buffer) {
return new PatternReplicationRequestPacket(PatternState.read(buffer), buffer.readInt());
}
}

View File

@ -1,27 +0,0 @@
package ru.dbotthepony.mc.otm.network;
import net.minecraft.client.Minecraft;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.world.item.ItemStack;
import net.minecraftforge.network.NetworkEvent;
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

@ -12,19 +12,12 @@ import net.minecraft.core.Vec3i
import net.minecraft.nbt.CompoundTag
import net.minecraft.nbt.LongArrayTag
import net.minecraft.nbt.Tag
import net.minecraft.network.chat.MutableComponent
import net.minecraft.network.chat.contents.LiteralContents
import net.minecraft.network.chat.contents.TranslatableContents
import net.minecraft.resources.ResourceLocation
import net.minecraft.world.Container
import net.minecraft.world.entity.Entity
import net.minecraft.world.item.Item
import net.minecraft.world.item.ItemStack
import net.minecraft.world.phys.Vec3
import net.minecraftforge.common.util.LazyOptional
import net.minecraftforge.items.IItemHandler
import net.minecraftforge.registries.ForgeRegistries
import net.minecraftforge.registries.IForgeRegistry
import java.util.*
import kotlin.properties.ReadWriteProperty
import kotlin.reflect.KProperty

View File

@ -39,6 +39,11 @@ val MINECRAFT_SERVER: MinecraftServer
return _server ?: throw NullPointerException("Not running a server!")
}
val NULLABLE_MINECRAFT_SERVER: MinecraftServer?
get() {
return _server
}
// Flag whenever is server alive
// To avoid baby deadlocks caused by minecraft engine design issues
var SERVER_IS_DYING = true

View File

@ -18,7 +18,6 @@ import net.minecraft.world.level.block.state.BlockState
import net.minecraftforge.common.capabilities.Capability
import net.minecraftforge.common.capabilities.ForgeCapabilities
import net.minecraftforge.common.util.LazyOptional
import net.minecraftforge.energy.CapabilityEnergy
import net.minecraftforge.energy.IEnergyStorage
import net.minecraftforge.network.NetworkEvent
import net.minecraftforge.network.PacketDistributor
@ -28,14 +27,15 @@ import ru.dbotthepony.mc.otm.capability.*
import ru.dbotthepony.mc.otm.compat.mekanism.MatteryToMekanismEnergyWrapper
import ru.dbotthepony.mc.otm.core.ImpreciseFraction
import ru.dbotthepony.mc.otm.menu.EnergyCounterMenu
import ru.dbotthepony.mc.otm.network.MatteryNetworking
import ru.dbotthepony.mc.otm.network.MatteryPacket
import ru.dbotthepony.mc.otm.network.WorldNetworkChannel
import ru.dbotthepony.mc.otm.registry.MBlockEntities
import java.lang.ref.WeakReference
import java.util.*
import java.util.function.Supplier
data class EnergyCounterPacket(val pos: BlockPos, val thisTick: ImpreciseFraction, val total: ImpreciseFraction, val index: Int, val value: ImpreciseFraction) {
fun write(buff: FriendlyByteBuf) {
data class EnergyCounterPacket(val pos: BlockPos, val thisTick: ImpreciseFraction, val total: ImpreciseFraction, val index: Int, val value: ImpreciseFraction) : MatteryPacket {
override fun write(buff: FriendlyByteBuf) {
buff.writeBlockPos(pos)
thisTick.write(buff)
total.write(buff)
@ -43,7 +43,7 @@ data class EnergyCounterPacket(val pos: BlockPos, val thisTick: ImpreciseFractio
value.write(buff)
}
fun play(context: Supplier<NetworkEvent.Context>) {
override fun play(context: Supplier<NetworkEvent.Context>) {
context.get().packetHandled = true
context.get().enqueueWork {
@ -459,7 +459,7 @@ class EnergyCounterBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : Mat
historyTick = (historyTick + 1) % history.size
history[historyTick] = ImpreciseFraction.ZERO
MatteryNetworking.CHANNEL.send(PacketDistributor.NEAR.with(this::distributor), EnergyCounterPacket(blockPos, lastTick, passed, index, accumulated))
WorldNetworkChannel.send(PacketDistributor.NEAR.with(this::distributor), EnergyCounterPacket(blockPos, lastTick, passed, index, accumulated))
}
fun clientTick() {

View File

@ -37,6 +37,7 @@ import ru.dbotthepony.mc.otm.graph.storage.BasicStorageGraphNode
import ru.dbotthepony.mc.otm.graph.storage.StorageNetworkGraph
import ru.dbotthepony.mc.otm.ifHas
import ru.dbotthepony.mc.otm.menu.ItemMonitorMenu
import ru.dbotthepony.mc.otm.network.MatteryPacket
import ru.dbotthepony.mc.otm.registry.MBlockEntities
import ru.dbotthepony.mc.otm.set
import ru.dbotthepony.mc.otm.storage.*
@ -46,7 +47,7 @@ import java.util.function.Supplier
import kotlin.collections.HashMap
import kotlin.collections.HashSet
class ItemMonitorPlayerSettings : INBTSerializable<CompoundTag> {
class ItemMonitorPlayerSettings : INBTSerializable<CompoundTag>, MatteryPacket {
enum class RefillSource(val component: Component) {
// Refill everything from system
SYSTEM(TranslatableComponent("otm.gui.item_monitor.refill_source.system")),
@ -112,7 +113,7 @@ class ItemMonitorPlayerSettings : INBTSerializable<CompoundTag> {
craftingAmount = other.craftingAmount
}
fun write(buff: FriendlyByteBuf) {
override fun write(buff: FriendlyByteBuf) {
buff.writeEnum(refillSource)
buff.writeEnum(resultTarget)
buff.writeEnum(craftingAmount)
@ -131,7 +132,7 @@ class ItemMonitorPlayerSettings : INBTSerializable<CompoundTag> {
(container.tile as ItemMonitorBlockEntity).setChangedLight()
}
fun play(context: Supplier<NetworkEvent.Context>) {
override fun play(context: Supplier<NetworkEvent.Context>) {
context.get().packetHandled = true
val ply = context.get().sender

View File

@ -52,15 +52,15 @@ class DriveViewerScreen(menu: DriveViewerMenu, inventory: Inventory, title: Comp
val grid = GridPanel(this, frame, 28f, 16f, GRID_WIDTH * 18f, GRID_HEIGHT * 18f, GRID_WIDTH, GRID_HEIGHT)
val scrollBar = ScrollBarPanel(this, frame, 192f, 14f, 92f)
scrollBar.setupRowMultiplier { menu.view.itemCount / GRID_WIDTH }
scrollBar.setupRowMultiplier { menu.networkedItemView.itemCount / GRID_WIDTH }
views.add(grid)
views.add(scrollBar)
for (i in 0 until GRID_WIDTH * GRID_HEIGHT) {
object : AbstractSlotPanel(this@DriveViewerScreen, grid, 0f, 0f) {
override fun getItemStack(): ItemStack {
val index = i + scrollBar.getScroll(menu.view.sortedView.size / GRID_WIDTH)
return menu.view.sortedView.getOrNull(index)?.stack?.item ?: ItemStack.EMPTY
val index = i + scrollBar.getScroll(menu.networkedItemView.sortedView.size / GRID_WIDTH)
return menu.networkedItemView.sortedView.getOrNull(index)?.stack?.item ?: ItemStack.EMPTY
}
override fun mouseScrolledInner(mouse_x: Double, mouse_y: Double, scroll: Double): Boolean {
@ -69,7 +69,7 @@ class DriveViewerScreen(menu: DriveViewerMenu, inventory: Inventory, title: Comp
override fun mouseClickedInner(mouse_x: Double, mouse_y: Double, mouse_click_type: Int): Boolean {
val index = i + scrollBar.getScroll(GRID_WIDTH)
menu.view.mouseClick(index, mouse_click_type)
menu.networkedItemView.mouseClick(index, mouse_click_type)
return true
}
@ -81,8 +81,8 @@ class DriveViewerScreen(menu: DriveViewerMenu, inventory: Inventory, title: Comp
override fun getItemStackTooltip(stack: ItemStack): List<Component> {
return super.getItemStackTooltip(stack).also {
it as MutableList<Component>
val index = i + scrollBar.getScroll(menu.view.sortedView.size / GRID_WIDTH)
val realStack = menu.view.sortedView.getOrNull(index)!!.stack
val index = i + scrollBar.getScroll(menu.networkedItemView.sortedView.size / GRID_WIDTH)
val realStack = menu.networkedItemView.sortedView.getOrNull(index)!!.stack
it.add(TranslatableComponent("otm.gui.item_amount", realStack.count.toString()))
}
}

View File

@ -10,7 +10,6 @@ import net.minecraft.world.item.Items
import org.lwjgl.opengl.GL11
import ru.dbotthepony.mc.otm.TranslatableComponent
import ru.dbotthepony.mc.otm.block.entity.storage.ItemMonitorPlayerSettings
import ru.dbotthepony.mc.otm.client.render.SkinGrid
import ru.dbotthepony.mc.otm.client.render.UVWindingOrder
import ru.dbotthepony.mc.otm.client.render.Widgets8
import ru.dbotthepony.mc.otm.client.screen.panels.*
@ -40,7 +39,7 @@ class ItemMonitorScreen(menu: ItemMonitorMenu, inventory: Inventory, title: Comp
frame.width = 178f + frame.dockPadding.left + frame.dockPadding.right
val viewScrollBar = ScrollBarPanel(this, topPanel, 28f + ITEM_GRID_WIDTH * 18f + 2f, 16f, ITEM_GRID_HEIGHT * 18f)
viewScrollBar.setupRowMultiplier { equalDownDivision(menu.view.itemCount, ITEM_GRID_WIDTH) }
viewScrollBar.setupRowMultiplier { equalDownDivision(menu.networkedItemView.itemCount, ITEM_GRID_WIDTH) }
viewScrollBar.dock = Dock.RIGHT
viewScrollBar.setDockMargin(left = 2f)
@ -50,10 +49,10 @@ class ItemMonitorScreen(menu: ItemMonitorMenu, inventory: Inventory, title: Comp
for (i in 0 until ITEM_GRID_WIDTH * ITEM_GRID_HEIGHT) {
object : AbstractSlotPanel(this@ItemMonitorScreen, gridPanel) {
private val index get() = i + viewScrollBar.getScroll(equalDownDivision(menu.view.itemCount, ITEM_GRID_WIDTH)) * ITEM_GRID_WIDTH
private val index get() = i + viewScrollBar.getScroll(equalDownDivision(menu.networkedItemView.itemCount, ITEM_GRID_WIDTH)) * ITEM_GRID_WIDTH
override fun getItemStack(): ItemStack {
return menu.view.sortedView.getOrNull(index)?.stack?.item ?: ItemStack.EMPTY
return menu.networkedItemView.sortedView.getOrNull(index)?.stack?.item ?: ItemStack.EMPTY
}
override fun mouseScrolledInner(mouse_x: Double, mouse_y: Double, scroll: Double): Boolean {
@ -61,14 +60,14 @@ class ItemMonitorScreen(menu: ItemMonitorMenu, inventory: Inventory, title: Comp
}
override fun mouseClickedInner(mouse_x: Double, mouse_y: Double, mouse_click_type: Int): Boolean {
menu.view.mouseClick(index, mouse_click_type)
menu.networkedItemView.mouseClick(index, mouse_click_type)
return true
}
override fun innerRender(stack: PoseStack, mouse_x: Float, mouse_y: Float, flag: Float) {
renderSlotBackground(stack, mouse_x, mouse_y, flag)
val itemstack = menu.view.sortedView.getOrNull(index)?.stack ?: ITEM_STORAGE.empty
val itemstack = menu.networkedItemView.sortedView.getOrNull(index)?.stack ?: ITEM_STORAGE.empty
renderRegular(stack, itemstack.stack, "")
@ -94,7 +93,7 @@ class ItemMonitorScreen(menu: ItemMonitorMenu, inventory: Inventory, title: Comp
override fun getItemStackTooltip(stack: ItemStack): List<Component> {
return super.getItemStackTooltip(stack).also {
it as MutableList<Component>
val realStack = menu.view.sortedView.getOrNull(index)!!.stack
val realStack = menu.networkedItemView.sortedView.getOrNull(index)!!.stack
it.add(TranslatableComponent("otm.gui.stored_amount", realStack.count.formatReadableNumber()).withStyle(ChatFormatting.DARK_GRAY))
}
}

View File

@ -4,7 +4,7 @@ import net.minecraft.world.item.ItemStack
import ru.dbotthepony.mc.otm.client.screen.MatteryScreen
import ru.dbotthepony.mc.otm.container.ItemFilterNetworkSlot
import ru.dbotthepony.mc.otm.container.ItemFilterSlotPacket
import ru.dbotthepony.mc.otm.network.MatteryNetworking
import ru.dbotthepony.mc.otm.network.MenuNetworkChannel
open class FilterSlotPanel(
screen: MatteryScreen<*>,
@ -21,9 +21,9 @@ open class FilterSlotPanel(
override fun mouseClickedInner(mouse_x: Double, mouse_y: Double, mouse_click_type: Int): Boolean {
if (screen.menu.carried.isEmpty) {
MatteryNetworking.CHANNEL.sendToServer(ItemFilterSlotPacket(slot.networkID, ItemStack.EMPTY))
MenuNetworkChannel.sendToServer(ItemFilterSlotPacket(slot.networkID, ItemStack.EMPTY))
} else {
MatteryNetworking.CHANNEL.sendToServer(ItemFilterSlotPacket(slot.networkID, screen.menu.carried))
MenuNetworkChannel.sendToServer(ItemFilterSlotPacket(slot.networkID, screen.menu.carried))
}
return true

View File

@ -13,18 +13,19 @@ import org.apache.logging.log4j.LogManager
import ru.dbotthepony.mc.otm.client.minecraft
import ru.dbotthepony.mc.otm.ifHas
import ru.dbotthepony.mc.otm.menu.MatteryMenu
import ru.dbotthepony.mc.otm.network.MatteryPacket
import ru.dbotthepony.mc.otm.set
import java.util.Arrays
import java.util.LinkedList
import java.util.function.Supplier
data class ItemFilterSlotPacket(val slotID: Int, val newValue: ItemStack) {
fun write(buff: FriendlyByteBuf) {
data class ItemFilterSlotPacket(val slotID: Int, val newValue: ItemStack) : MatteryPacket {
override fun write(buff: FriendlyByteBuf) {
buff.writeInt(slotID)
buff.writeItemStack(newValue, true)
}
fun play(context: Supplier<NetworkEvent.Context>) {
override fun play(context: Supplier<NetworkEvent.Context>) {
context.get().packetHandled = true
if (context.get().sender != null) {

View File

@ -1,12 +1,9 @@
package ru.dbotthepony.mc.otm.item.weapon
import com.mojang.blaze3d.systems.RenderSystem
import com.mojang.blaze3d.vertex.*
import com.mojang.math.Vector3f
import net.minecraft.client.Minecraft
import net.minecraft.client.model.HumanoidModel
import net.minecraft.client.renderer.GameRenderer
import net.minecraft.client.renderer.block.model.ItemTransforms
import net.minecraft.nbt.CompoundTag
import net.minecraft.network.FriendlyByteBuf
import net.minecraft.server.level.ServerPlayer
@ -31,7 +28,8 @@ import ru.dbotthepony.mc.otm.client.render.drawRect
import ru.dbotthepony.mc.otm.client.render.setDrawColor
import ru.dbotthepony.mc.otm.core.*
import ru.dbotthepony.mc.otm.core.Vector
import ru.dbotthepony.mc.otm.network.MatteryNetworking
import ru.dbotthepony.mc.otm.network.MatteryPacket
import ru.dbotthepony.mc.otm.network.WeaponNetworkChannel
import java.util.*
import java.util.function.Supplier
import kotlin.math.PI
@ -42,19 +40,19 @@ import kotlin.reflect.full.primaryConstructor
private val ItemStack.weaponDataTable get() = tag?.let(::WeaponDataTable)
enum class WeaponScopePacket(val scope: Boolean) {
enum class WeaponScopePacket(val scope: Boolean) : MatteryPacket {
SCOPE_IN(true), SCOPE_OUT(false);
fun write(buff: FriendlyByteBuf) {
override fun write(buff: FriendlyByteBuf) {
buff.writeBoolean(scope)
}
fun play(supplier: Supplier<NetworkEvent.Context>) {
supplier.get().packetHandled = true
override fun play(context: Supplier<NetworkEvent.Context>) {
context.get().packetHandled = true
// TODO: Manual synchronization
supplier.get().enqueueWork {
val stack = supplier.get().sender!!.mainHandItem
context.get().enqueueWork {
val stack = context.get().sender!!.mainHandItem
val item = stack.item as? AbstractWeaponItem<*> ?: return@enqueueWork
item.dataTable(stack).wantsToScope = scope
@ -66,19 +64,19 @@ enum class WeaponScopePacket(val scope: Boolean) {
}
}
enum class WeaponFireInputPacket(val primary: Boolean) {
enum class WeaponFireInputPacket(val primary: Boolean) : MatteryPacket {
PRIMARY(true), SECONDARY(false);
fun write(buff: FriendlyByteBuf) {
override fun write(buff: FriendlyByteBuf) {
buff.writeBoolean(primary)
}
fun play(supplier: Supplier<NetworkEvent.Context>) {
supplier.get().packetHandled = true
override fun play(context: Supplier<NetworkEvent.Context>) {
context.get().packetHandled = true
// TODO: Manual synchronization
supplier.get().enqueueWork {
val stack = supplier.get().sender!!.mainHandItem
context.get().enqueueWork {
val stack = context.get().sender!!.mainHandItem
val item = stack.item as? AbstractWeaponItem<*> ?: return@enqueueWork
// Listen server: client and server thread compete for lock
@ -87,9 +85,9 @@ enum class WeaponFireInputPacket(val primary: Boolean) {
item.dataTable = null
if (primary)
item.tryPrimaryFire(stack, supplier.get().sender!!)
item.tryPrimaryFire(stack, context.get().sender!!)
else
item.trySecondaryFire(stack, supplier.get().sender!!)
item.trySecondaryFire(stack, context.get().sender!!)
(item as AbstractWeaponItem<WeaponDataTable>).dataTable = predictedData
}
@ -498,17 +496,17 @@ abstract class AbstractWeaponItem<D : WeaponDataTable>(val tables: KClass<D>, ra
if (!dt.wantsToScope && minecraft.options.keyUse.isDown) {
dt.wantsToScope = true
MatteryNetworking.CHANNEL.sendToServer(WeaponScopePacket.SCOPE_IN)
WeaponNetworkChannel.sendToServer(WeaponScopePacket.SCOPE_IN)
} else if (dt.wantsToScope && !minecraft.options.keyUse.isDown) {
dt.wantsToScope = false
MatteryNetworking.CHANNEL.sendToServer(WeaponScopePacket.SCOPE_OUT)
WeaponNetworkChannel.sendToServer(WeaponScopePacket.SCOPE_OUT)
}
if (minecraft.options.keyAttack.isDown && (item.primaryAutomatic || !firedPrimary)) {
firedPrimary = true
if (item.tryPrimaryFire(itemStack, player)) {
MatteryNetworking.CHANNEL.sendToServer(WeaponFireInputPacket.PRIMARY)
WeaponNetworkChannel.sendToServer(WeaponFireInputPacket.PRIMARY)
}
} else if (!minecraft.options.keyAttack.isDown) {
firedPrimary = false
@ -518,7 +516,7 @@ abstract class AbstractWeaponItem<D : WeaponDataTable>(val tables: KClass<D>, ra
firedSecondary = true
if (item.trySecondaryFire(itemStack, player)) {
MatteryNetworking.CHANNEL.sendToServer(WeaponFireInputPacket.SECONDARY)
WeaponNetworkChannel.sendToServer(WeaponFireInputPacket.SECONDARY)
}
} else if (!minecraft.options.keyAttack.isDown) {
firedSecondary = false

View File

@ -5,6 +5,7 @@ import net.minecraft.ChatFormatting
import net.minecraft.client.Minecraft
import net.minecraft.network.FriendlyByteBuf
import net.minecraft.server.dedicated.DedicatedServer
import net.minecraft.server.level.ServerPlayer
import net.minecraft.world.item.Item
import net.minecraft.world.item.ItemStack
import net.minecraftforge.event.entity.player.ItemTooltipEvent
@ -15,24 +16,18 @@ import net.minecraftforge.eventbus.api.SubscribeEvent
import net.minecraftforge.network.NetworkEvent
import net.minecraftforge.network.PacketDistributor
import org.lwjgl.glfw.GLFW
import ru.dbotthepony.mc.otm.OverdriveThatMatters
import ru.dbotthepony.mc.otm.TranslatableComponent
import ru.dbotthepony.mc.otm.*
import ru.dbotthepony.mc.otm.capability.MatteryCapability
import ru.dbotthepony.mc.otm.capability.drive.IMatteryDrive
import ru.dbotthepony.mc.otm.core.*
import ru.dbotthepony.mc.otm.network.MatteryNetworking
import ru.dbotthepony.mc.otm.orNull
import ru.dbotthepony.mc.otm.network.MatteryPacket
import ru.dbotthepony.mc.otm.network.RegistryNetworkChannel
import ru.dbotthepony.mc.otm.storage.ItemStackWrapper
import ru.dbotthepony.mc.otm.writeRegistryId
import java.math.BigInteger
import java.util.function.Supplier
internal var building = false
interface MatterTuplePredicate {
fun accept(item: Item): MatterTuple?
}
interface IMatterItem {
fun getMatterValue(stack: ItemStack): MatterTuple?
fun hasMatterValue(stack: ItemStack) = getMatterValue(stack) != null
@ -51,7 +46,7 @@ private val derivedEntries = HashMap<Item, MatterTuple>()
@JvmField
val rootEntriesAccess = object : MutableMap<Item, MatterTuple> by rootEntries {
override fun put(key: Item, value: MatterTuple): MatterTuple? {
MatteryNetworking.CHANNEL.send(PacketDistributor.ALL.noArg(), RegistryPacketUpdate(MatterRegistryType.ROOT, key, value))
RegistryNetworkChannel.send(PacketDistributor.ALL.noArg(), RegistryPacketUpdate(MatterRegistryType.ROOT, key, value))
return rootEntries.put(key, value)
}
@ -62,7 +57,7 @@ val rootEntriesAccess = object : MutableMap<Item, MatterTuple> by rootEntries {
val distr = PacketDistributor.ALL.noArg()
for ((key, value) in from) {
MatteryNetworking.CHANNEL.send(distr, RegistryPacketUpdate(MatterRegistryType.ROOT, key, value))
RegistryNetworkChannel.send(distr, RegistryPacketUpdate(MatterRegistryType.ROOT, key, value))
}
}
}
@ -71,7 +66,7 @@ val rootEntriesAccess = object : MutableMap<Item, MatterTuple> by rootEntries {
val value = rootEntries.remove(key)
if (!building && value != null)
MatteryNetworking.CHANNEL.send(PacketDistributor.ALL.noArg(), RegistryPacketRemove(MatterRegistryType.ROOT, key))
RegistryNetworkChannel.send(PacketDistributor.ALL.noArg(), RegistryPacketRemove(MatterRegistryType.ROOT, key))
return value
}
@ -79,8 +74,8 @@ val rootEntriesAccess = object : MutableMap<Item, MatterTuple> by rootEntries {
override fun clear() {
rootEntries.clear()
if (!building && server != null) {
MatteryNetworking.CHANNEL.send(PacketDistributor.ALL.noArg(), RegistryPacketClear.ROOT)
if (!building && NULLABLE_MINECRAFT_SERVER != null) {
RegistryNetworkChannel.send(PacketDistributor.ALL.noArg(), RegistryPacketClear.ROOT)
}
}
}
@ -94,7 +89,7 @@ val rootEntriesAccess = object : MutableMap<Item, MatterTuple> by rootEntries {
@JvmField
val derivedEntriesAccess = object : MutableMap<Item, MatterTuple> by derivedEntries {
override fun put(key: Item, value: MatterTuple): MatterTuple? {
MatteryNetworking.CHANNEL.send(PacketDistributor.ALL.noArg(), RegistryPacketUpdate(MatterRegistryType.DERIVED, key, value))
RegistryNetworkChannel.send(PacketDistributor.ALL.noArg(), RegistryPacketUpdate(MatterRegistryType.DERIVED, key, value))
return derivedEntries.put(key, value)
}
@ -105,7 +100,7 @@ val derivedEntriesAccess = object : MutableMap<Item, MatterTuple> by derivedEntr
val distr = PacketDistributor.ALL.noArg()
for ((key, value) in from) {
MatteryNetworking.CHANNEL.send(distr, RegistryPacketUpdate(MatterRegistryType.DERIVED, key, value))
RegistryNetworkChannel.send(distr, RegistryPacketUpdate(MatterRegistryType.DERIVED, key, value))
}
}
}
@ -114,7 +109,7 @@ val derivedEntriesAccess = object : MutableMap<Item, MatterTuple> by derivedEntr
val value = derivedEntries.remove(key)
if (!building && value != null)
MatteryNetworking.CHANNEL.send(PacketDistributor.ALL.noArg(), RegistryPacketRemove(MatterRegistryType.DERIVED, key))
RegistryNetworkChannel.send(PacketDistributor.ALL.noArg(), RegistryPacketRemove(MatterRegistryType.DERIVED, key))
return value
}
@ -122,8 +117,8 @@ val derivedEntriesAccess = object : MutableMap<Item, MatterTuple> by derivedEntr
override fun clear() {
derivedEntries.clear()
if (!building && server != null) {
MatteryNetworking.CHANNEL.send(PacketDistributor.ALL.noArg(), RegistryPacketClear.DERIVED)
if (!building && NULLABLE_MINECRAFT_SERVER != null) {
RegistryNetworkChannel.send(PacketDistributor.ALL.noArg(), RegistryPacketClear.DERIVED)
}
}
}
@ -221,29 +216,15 @@ fun getMatterValue(stack: ItemStack): MatterTuple {
return getMatterValue(stack, 0)
}
private var server: DedicatedServer? = null
@SubscribeEvent
@Suppress("unused")
fun onPlayerJoin(event: PlayerEvent.PlayerLoggedInEvent) {
if (server != null) {
MatteryNetworking.CHANNEL.send(PacketDistributor.ALL.noArg(), RegistryPacketFullUpdate(MatterRegistryType.ROOT, rootEntries))
MatteryNetworking.CHANNEL.send(PacketDistributor.ALL.noArg(), RegistryPacketFullUpdate(MatterRegistryType.DERIVED, derivedEntries))
if (NULLABLE_MINECRAFT_SERVER != null) {
RegistryNetworkChannel.send(PacketDistributor.PLAYER.with { event.entity as ServerPlayer }, RegistryPacketFullUpdate(MatterRegistryType.ROOT, rootEntries))
RegistryNetworkChannel.send(PacketDistributor.PLAYER.with { event.entity as ServerPlayer }, RegistryPacketFullUpdate(MatterRegistryType.DERIVED, derivedEntries))
}
}
@SubscribeEvent
@Suppress("unused")
fun serverStartRegistry(event: ServerStartedEvent) {
server = event.server as? DedicatedServer
}
@SubscribeEvent
@Suppress("unused")
fun serverStopRegistry(event: ServerStoppingEvent) {
server = null
}
@SubscribeEvent
@Suppress("unused")
fun tooltipEvent(event: ItemTooltipEvent) {
@ -305,8 +286,8 @@ data class MatterTuple(val value: ImpreciseFraction, val complexity: Double): Co
internal enum class MatterRegistryType {ROOT, DERIVED}
internal class RegistryPacketUpdate(val type: MatterRegistryType, val item: Item, val tuple: MatterTuple) {
fun play(context: Supplier<NetworkEvent.Context>) {
internal class RegistryPacketUpdate(val type: MatterRegistryType, val item: Item, val tuple: MatterTuple) : MatteryPacket {
override fun play(context: Supplier<NetworkEvent.Context>) {
context.get().packetHandled = true
when (type) {
@ -324,7 +305,7 @@ internal class RegistryPacketUpdate(val type: MatterRegistryType, val item: Item
}
}
fun write(buff: FriendlyByteBuf) {
override fun write(buff: FriendlyByteBuf) {
buff.writeEnum(type)
buff.writeRegistryId(item)
tuple.write(buff)
@ -337,8 +318,8 @@ internal class RegistryPacketUpdate(val type: MatterRegistryType, val item: Item
}
}
internal class RegistryPacketRemove(val type: MatterRegistryType, val item: Item) {
fun play(context: Supplier<NetworkEvent.Context>) {
internal class RegistryPacketRemove(val type: MatterRegistryType, val item: Item) : MatteryPacket {
override fun play(context: Supplier<NetworkEvent.Context>) {
context.get().packetHandled = true
when (type) {
@ -356,7 +337,7 @@ internal class RegistryPacketRemove(val type: MatterRegistryType, val item: Item
}
}
fun write(buff: FriendlyByteBuf) {
override fun write(buff: FriendlyByteBuf) {
buff.writeEnum(type)
buff.writeRegistryId(item)
}
@ -368,8 +349,8 @@ internal class RegistryPacketRemove(val type: MatterRegistryType, val item: Item
}
}
internal class RegistryPacketFullUpdate(val type: MatterRegistryType, val map: Map<Item, MatterTuple>) {
fun play(context: Supplier<NetworkEvent.Context>) {
internal class RegistryPacketFullUpdate(val type: MatterRegistryType, val map: Map<Item, MatterTuple>) : MatteryPacket {
override fun play(context: Supplier<NetworkEvent.Context>) {
context.get().packetHandled = true
when (type) {
@ -389,7 +370,7 @@ internal class RegistryPacketFullUpdate(val type: MatterRegistryType, val map: M
}
}
fun write(buff: FriendlyByteBuf) {
override fun write(buff: FriendlyByteBuf) {
buff.writeEnum(type)
buff.writeInt(map.size)
@ -415,11 +396,11 @@ internal class RegistryPacketFullUpdate(val type: MatterRegistryType, val map: M
}
}
internal enum class RegistryPacketClear(val type: MatterRegistryType) {
internal enum class RegistryPacketClear(val type: MatterRegistryType) : MatteryPacket {
ROOT(MatterRegistryType.ROOT),
DERIVED(MatterRegistryType.DERIVED);
fun play(context: Supplier<NetworkEvent.Context>) {
override fun play(context: Supplier<NetworkEvent.Context>) {
context.get().packetHandled = true
when (type) {
@ -437,7 +418,7 @@ internal enum class RegistryPacketClear(val type: MatterRegistryType) {
}
}
fun write(buff: FriendlyByteBuf) {
override fun write(buff: FriendlyByteBuf) {
buff.writeEnum(type)
}

View File

@ -7,14 +7,13 @@ import net.minecraft.world.entity.player.Player
import net.minecraft.world.inventory.Slot
import net.minecraft.world.item.ItemStack
import net.minecraftforge.common.capabilities.ForgeCapabilities
import net.minecraftforge.energy.CapabilityEnergy
import ru.dbotthepony.mc.otm.block.entity.storage.DriveViewerBlockEntity
import ru.dbotthepony.mc.otm.capability.MatteryCapability
import ru.dbotthepony.mc.otm.capability.drive.IMatteryDrive
import ru.dbotthepony.mc.otm.container.ItemFilter
import ru.dbotthepony.mc.otm.ifPresentK
import ru.dbotthepony.mc.otm.item.PortableCondensationDriveItem
import ru.dbotthepony.mc.otm.menu.data.INetworkedItemViewSupplier
import ru.dbotthepony.mc.otm.menu.data.INetworkedItemViewProvider
import ru.dbotthepony.mc.otm.menu.data.NetworkedItemView
import ru.dbotthepony.mc.otm.menu.widget.BooleanPlayerInputWidget
import ru.dbotthepony.mc.otm.registry.MMenus
@ -28,15 +27,13 @@ class DriveViewerMenu @JvmOverloads constructor(
tile: DriveViewerBlockEntity? = null
) : MatteryPoweredMenu(
MMenus.DRIVE_VIEWER, containerID, inventory, tile
), INetworkedItemViewSupplier {
val view = NetworkedItemView(inventory.player, this, tile == null)
), INetworkedItemViewProvider {
override val networkedItemView = NetworkedItemView(inventory.player, this, tile == null)
val driveSlot: MatterySlot
private val powered: PoweredVirtualComponent<ItemStackWrapper>?
private var lastDrive: IMatteryDrive<ItemStackWrapper>? = null
override fun getNetworkedItemView() = view
init {
val container = tile?.container ?: SimpleContainer(1)
@ -52,7 +49,7 @@ class DriveViewerMenu @JvmOverloads constructor(
tile.getCapability(MatteryCapability.ENERGY).resolve().get()
)
view.setComponent(powered)
this.networkedItemView.setComponent(powered)
} else {
powered = null
}
@ -102,7 +99,7 @@ class DriveViewerMenu @JvmOverloads constructor(
if (prev != lastDrive) {
prev?.let(powered!!::remove)
view.clear()
this.networkedItemView.clear()
lastDrive?.let(powered!!::add)
if (lastDrive != null) {
@ -133,7 +130,7 @@ class DriveViewerMenu @JvmOverloads constructor(
}
}
view.network()
this.networkedItemView.network()
}
}
@ -143,7 +140,7 @@ class DriveViewerMenu @JvmOverloads constructor(
if (lastDrive != null)
powered?.remove(lastDrive!!)
view.removed()
this.networkedItemView.removed()
}
override fun quickMoveStack(ply: Player, slotIndex: Int): ItemStack {

View File

@ -11,9 +11,9 @@ import net.minecraftforge.network.PacketDistributor
import ru.dbotthepony.mc.otm.block.entity.storage.ItemMonitorBlockEntity
import ru.dbotthepony.mc.otm.block.entity.storage.ItemMonitorPlayerSettings
import ru.dbotthepony.mc.otm.get
import ru.dbotthepony.mc.otm.menu.data.INetworkedItemViewSupplier
import ru.dbotthepony.mc.otm.menu.data.INetworkedItemViewProvider
import ru.dbotthepony.mc.otm.menu.data.NetworkedItemView
import ru.dbotthepony.mc.otm.network.MatteryNetworking
import ru.dbotthepony.mc.otm.network.MenuNetworkChannel
import ru.dbotthepony.mc.otm.registry.MMenus
import ru.dbotthepony.mc.otm.storage.*
import java.util.*
@ -77,21 +77,17 @@ class ItemMonitorMenu @JvmOverloads constructor(
p_38852_: Int,
inventory: Inventory,
tile: ItemMonitorBlockEntity? = null
) : MatteryPoweredMenu(MMenus.ITEM_MONITOR, p_38852_, inventory, tile), INetworkedItemViewSupplier {
val view = NetworkedItemView(inventory.player, this, tile == null)
) : MatteryPoweredMenu(MMenus.ITEM_MONITOR, p_38852_, inventory, tile), INetworkedItemViewProvider {
override val networkedItemView = NetworkedItemView(inventory.player, this, tile == null)
val settings: ItemMonitorPlayerSettings = tile?.getSettings(inventory.player as ServerPlayer) ?: ItemMonitorPlayerSettings()
private var settingsNetworked = false
override fun getNetworkedItemView(): NetworkedItemView {
return view
}
val craftingResult: MatterySlot
val craftingSlots: List<MatterySlot>
init {
if (tile != null) {
view.setComponent(tile.poweredView)
networkedItemView.setComponent(tile.poweredView)
craftingResult = ResultSlot(tile.craftingResultContainer)
craftingSlots = Collections.unmodifiableList(Array(9) { MatterySlot(tile.craftingGrid, it) }.asList())
} else {
@ -108,25 +104,25 @@ class ItemMonitorMenu @JvmOverloads constructor(
override fun broadcastFullState() {
super.broadcastFullState()
MatteryNetworking.CHANNEL.send(PacketDistributor.PLAYER.with { ply as ServerPlayer }, settings)
MenuNetworkChannel.send(PacketDistributor.PLAYER.with { ply as ServerPlayer }, settings)
settingsNetworked = true
}
fun sendSettingsToServer() {
MatteryNetworking.CHANNEL.sendToServer(settings)
MenuNetworkChannel.sendToServer(settings)
}
override fun removed(p_38940_: Player) {
super.removed(p_38940_)
view.removed()
networkedItemView.removed()
}
override fun broadcastChanges() {
super.broadcastChanges()
view.network()
networkedItemView.network()
if (!settingsNetworked) {
MatteryNetworking.CHANNEL.send(PacketDistributor.PLAYER.with { ply as ServerPlayer }, settings)
MenuNetworkChannel.send(PacketDistributor.PLAYER.with { ply as ServerPlayer }, settings)
settingsNetworked = true
}
}
@ -145,7 +141,7 @@ class ItemMonitorMenu @JvmOverloads constructor(
return ItemStack.EMPTY
}
val leftover = view.provider?.insertStack(ItemStackWrapper(slot.item), false)?.stack ?: slot.item
val leftover = networkedItemView.provider?.insertStack(ItemStackWrapper(slot.item), false)?.stack ?: slot.item
if (leftover.count == slot.item.count) {
return ItemStack.EMPTY
@ -169,7 +165,7 @@ class ItemMonitorMenu @JvmOverloads constructor(
return item
}
remainder = view.provider?.insertStack(ItemStackWrapper(remainder), false)?.stack ?: remainder
remainder = networkedItemView.provider?.insertStack(ItemStackWrapper(remainder), false)?.stack ?: remainder
slots[slotIndex].set(remainder)
if (remainder.isEmpty) {

View File

@ -1,23 +1,131 @@
package ru.dbotthepony.mc.otm.menu
import net.minecraft.network.FriendlyByteBuf
import net.minecraft.server.level.ServerPlayer
import net.minecraft.world.entity.player.Inventory
import net.minecraft.world.entity.player.Player
import net.minecraft.world.inventory.Slot
import net.minecraftforge.network.NetworkEvent
import net.minecraftforge.network.PacketDistributor
import ru.dbotthepony.mc.otm.OverdriveThatMatters
import ru.dbotthepony.mc.otm.block.entity.matter.MatterPanelBlockEntity
import ru.dbotthepony.mc.otm.capability.matter.MatterTask
import ru.dbotthepony.mc.otm.capability.matter.PatternState
import ru.dbotthepony.mc.otm.client.minecraft
import ru.dbotthepony.mc.otm.graph.matter.IMatterGraphListener
import ru.dbotthepony.mc.otm.graph.matter.MatterNetworkGraph
import ru.dbotthepony.mc.otm.network.CancelMatterTaskPacket
import ru.dbotthepony.mc.otm.network.MatterTaskPacket
import ru.dbotthepony.mc.otm.network.MatteryNetworking
import ru.dbotthepony.mc.otm.network.PatternGridPacket
import ru.dbotthepony.mc.otm.network.*
import ru.dbotthepony.mc.otm.registry.MMenus
import java.util.*
import java.util.function.Consumer
import java.util.function.Supplier
class CancelTaskPacket(val id: UUID) : MatteryPacket {
override fun write(buff: FriendlyByteBuf) {
buff.writeUUID(id)
}
override fun play(context: Supplier<NetworkEvent.Context>) {
context.packetHandled = true
context.enqueueWork {
val sender = context.sender!!
(sender.containerMenu as? MatterPanelMenu)?.receiveTaskCancel(sender, id)
}
}
companion object {
fun read(buff: FriendlyByteBuf): CancelTaskPacket {
return CancelTaskPacket(buff.readUUID())
}
}
}
class PatternsChangePacket(val isUpdate: Boolean, val patterns: Collection<PatternState>) : MatteryPacket {
override fun write(buff: FriendlyByteBuf) {
buff.writeBoolean(isUpdate)
buff.writeInt(patterns.size)
for (pattern in patterns) {
pattern.write(buff)
}
}
override fun play(context: Supplier<NetworkEvent.Context>) {
context.packetHandled = true
context.enqueueWork {
val menu = minecraft.player?.containerMenu as? MatterPanelMenu ?: return@enqueueWork
if (isUpdate) {
menu.networkPatternsUpdated(patterns)
} else {
menu.networkPatternsRemoved(patterns)
}
}
}
companion object {
fun read(buff: FriendlyByteBuf): PatternsChangePacket {
val isUpdate = buff.readBoolean()
val size = buff.readInt()
return PatternsChangePacket(isUpdate, ArrayList<PatternState>(size).also {
for (i in 0 until size) it.add(PatternState.read(buff) ?: throw NullPointerException("Unable to read PatternState from network at $i")) })
}
}
}
class TasksChangePacket(val isUpdate: Boolean, val tasks: Collection<MatterTask>) : MatteryPacket {
override fun write(buff: FriendlyByteBuf) {
buff.writeBoolean(isUpdate)
buff.writeInt(tasks.size)
for (task in tasks) {
task.write(buff)
}
}
override fun play(context: Supplier<NetworkEvent.Context>) {
context.packetHandled = true
context.enqueueWork {
val menu = minecraft.player?.containerMenu as? MatterPanelMenu ?: return@enqueueWork
if (isUpdate) {
menu.networkTasksUpdated(tasks)
} else {
menu.networkTasksRemoved(tasks)
}
}
}
companion object {
fun read(buff: FriendlyByteBuf): TasksChangePacket {
val isUpdate = buff.readBoolean()
val size = buff.readInt()
return TasksChangePacket(isUpdate, ArrayList<MatterTask>(size).also {
for (i in 0 until size) it.add(MatterTask.read(buff) ?: throw NullPointerException("Unable to read PatternState from network at $i")) })
}
}
}
class ReplicationRequestPacket(val state: PatternState, amount: Int) : MatteryPacket {
val amount = amount.coerceAtLeast(1).coerceAtMost(99999)
override fun write(buff: FriendlyByteBuf) {
state.write(buff)
buff.writeInt(amount)
}
override fun play(context: Supplier<NetworkEvent.Context>) {
context.packetHandled = true
context.enqueueWork {
val sender = context.sender ?: return@enqueueWork
val menu = sender.containerMenu as? MatterPanelMenu ?: return@enqueueWork
menu.requestReplication(sender, state, amount)
}
}
}
class MatterPanelMenu @JvmOverloads constructor(
p_38852_: Int,
@ -25,11 +133,11 @@ class MatterPanelMenu @JvmOverloads constructor(
tile: MatterPanelBlockEntity? = null
) : MatteryMenu(MMenus.MATTER_PANEL, p_38852_, inventory, tile), IMatterGraphListener {
fun taskUpdated(task: MatterTask) {
sendNetwork(MatterTaskPacket(true, listOf(task)))
sendNetwork(TasksChangePacket(true, listOf(task)))
}
fun taskRemoved(task: MatterTask) {
sendNetwork(MatterTaskPacket(false, listOf(task)))
sendNetwork(TasksChangePacket(false, listOf(task)))
}
// client code
@ -111,19 +219,19 @@ class MatterPanelMenu @JvmOverloads constructor(
}
fun requestTaskCancel(id: UUID) {
MatteryNetworking.CHANNEL.sendToServer(CancelMatterTaskPacket(id))
MenuNetworkChannel.sendToServer(CancelTaskPacket(id))
}
override fun onPatternAdded(state: PatternState) {
sendNetwork(PatternGridPacket(true, listOf(state)))
sendNetwork(PatternsChangePacket(true, listOf(state)))
}
override fun onPatternRemoved(state: PatternState) {
sendNetwork(PatternGridPacket(false, listOf(state)))
sendNetwork(PatternsChangePacket(false, listOf(state)))
}
override fun onPatternUpdated(new_state: PatternState, old_state: PatternState) {
sendNetwork(PatternGridPacket(true, listOf(new_state)))
sendNetwork(PatternsChangePacket(true, listOf(new_state)))
}
private var initial_send = false
@ -150,7 +258,7 @@ class MatterPanelMenu @JvmOverloads constructor(
}
private fun sendNetwork(packet: Any) {
MatteryNetworking.CHANNEL.send(PacketDistributor.PLAYER.with { inventory.player as ServerPlayer }, packet)
MenuNetworkChannel.send(PacketDistributor.PLAYER.with { inventory.player as ServerPlayer }, packet)
}
fun fullPatternBroadcast() {
@ -166,10 +274,10 @@ class MatterPanelMenu @JvmOverloads constructor(
if (grid != null) {
initial_send = true
sendNetwork(PatternGridPacket(true, grid.getStoredPatterns()))
sendNetwork(PatternsChangePacket(true, grid.getStoredPatterns()))
}
sendNetwork(MatterTaskPacket(true, tile.allTasks))
sendNetwork(TasksChangePacket(true, tile.allTasks))
}
}

View File

@ -11,7 +11,7 @@ import ru.dbotthepony.mc.otm.container.ItemFilter
import ru.dbotthepony.mc.otm.container.ItemFilterNetworkSlot
import ru.dbotthepony.mc.otm.menu.data.MultiByteDataContainer
import ru.dbotthepony.mc.otm.menu.widget.AbstractWidget
import ru.dbotthepony.mc.otm.network.MatteryNetworking
import ru.dbotthepony.mc.otm.network.MenuNetworkChannel
import java.util.Collections
abstract class MatteryMenu @JvmOverloads protected constructor(
@ -148,7 +148,7 @@ abstract class MatteryMenu @JvmOverloads protected constructor(
for (data in multiByteContainers) {
if (data.dirty) {
data.dirty = false
MatteryNetworking.CHANNEL.send(playerPacketDistributor, data.makePacket())
MenuNetworkChannel.send(playerPacketDistributor, data.makePacket())
}
}
@ -160,7 +160,7 @@ abstract class MatteryMenu @JvmOverloads protected constructor(
val packet = slot.sendChanges()
if (packet != null) {
MatteryNetworking.CHANNEL.send(consumer, packet)
MenuNetworkChannel.send(consumer, packet)
}
}
}
@ -171,7 +171,7 @@ abstract class MatteryMenu @JvmOverloads protected constructor(
}
for (data in multiByteContainers) {
MatteryNetworking.CHANNEL.send(playerPacketDistributor, data.makePacket())
MenuNetworkChannel.send(playerPacketDistributor, data.makePacket())
}
super.broadcastFullState()
@ -182,7 +182,7 @@ abstract class MatteryMenu @JvmOverloads protected constructor(
val packet = slot.sendChanges(true)
if (packet != null) {
MatteryNetworking.CHANNEL.send(consumer, packet)
MenuNetworkChannel.send(consumer, packet)
}
}
}

View File

@ -1,11 +1,8 @@
package ru.dbotthepony.mc.otm.menu.data
import net.minecraft.world.inventory.ContainerData
import org.apache.logging.log4j.LogManager
import ru.dbotthepony.mc.otm.core.Fraction
import ru.dbotthepony.mc.otm.core.ImpreciseFraction
import ru.dbotthepony.mc.otm.network.NetworkHelper
import java.util.zip.CRC32
class FractionDataContainer : ComplexDataContainer<Fraction>(128) {
companion object {

View File

@ -4,18 +4,19 @@ import net.minecraft.client.Minecraft
import net.minecraft.network.FriendlyByteBuf
import net.minecraftforge.network.NetworkEvent
import ru.dbotthepony.mc.otm.menu.MatteryMenu
import ru.dbotthepony.mc.otm.network.MatteryPacket
import java.nio.ByteBuffer
import java.util.function.Supplier
class MultiByteDataContainerPacket(val slotID: Int, val offset: Int, val payload: ByteArray) {
fun play(context: Supplier<NetworkEvent.Context>) {
class MultiByteDataContainerPacket(val slotID: Int, val offset: Int, val payload: ByteArray) : MatteryPacket {
override fun play(context: Supplier<NetworkEvent.Context>) {
context.get().packetHandled = true
context.get().enqueueWork {
(Minecraft.getInstance().player?.containerMenu as? MatteryMenu)?.getDataContainer(slotID)?.handle(this)
}
}
fun write(buff: FriendlyByteBuf) {
override fun write(buff: FriendlyByteBuf) {
buff.writeInt(slotID)
buff.writeInt(offset)
buff.writeByteArray(payload)

View File

@ -12,25 +12,73 @@ import net.minecraft.world.inventory.ClickType
import net.minecraft.world.item.ItemStack
import net.minecraftforge.network.NetworkEvent
import net.minecraftforge.network.PacketDistributor
import ru.dbotthepony.mc.otm.client.minecraft
import ru.dbotthepony.mc.otm.core.readBigInteger
import ru.dbotthepony.mc.otm.core.writeBigInteger
import ru.dbotthepony.mc.otm.menu.MatteryMenu
import ru.dbotthepony.mc.otm.network.MatteryNetworking
import ru.dbotthepony.mc.otm.network.SetCarriedPacket
import ru.dbotthepony.mc.otm.network.*
import ru.dbotthepony.mc.otm.registryName
import ru.dbotthepony.mc.otm.storage.*
import java.math.BigInteger
import java.util.*
import java.util.function.Supplier
class StackAddPacket(val containerId: Int, val id: Int, val stack: ItemStackWrapper) {
fun write(buffer: FriendlyByteBuf) {
buffer.writeInt(containerId)
buffer.writeInt(id)
buffer.writeBigItem(stack)
interface INetworkedItemViewProvider {
val networkedItemView: NetworkedItemView
}
class ItemViewInteractPacket(val stackID: Int, val type: ClickType, val action: ClickAction) : MatteryPacket {
override fun write(buff: FriendlyByteBuf) {
buff.writeInt(stackID)
buff.writeEnum(type)
buff.writeEnum(action)
}
fun play(context: Supplier<NetworkEvent.Context>) {
override fun play(context: Supplier<NetworkEvent.Context>) {
context.packetHandled = true
context.enqueueWork {
val sender = context.sender ?: return@enqueueWork
sender.resetLastActionTime()
(sender.containerMenu as? INetworkedItemViewProvider)?.networkedItemView?.playerInteract(this)
}
}
companion object {
fun read(buff: FriendlyByteBuf): ItemViewInteractPacket {
return ItemViewInteractPacket(buff.readInt(), buff.readEnum(ClickType::class.java), buff.readEnum(ClickAction::class.java))
}
}
}
object ClearItemViewPacket : MatteryPacket {
override fun write(buff: FriendlyByteBuf) {
// NO-OP
}
override fun play(context: Supplier<NetworkEvent.Context>) {
context.packetHandled = true
context.enqueueWork {
(minecraft.player?.containerMenu as? INetworkedItemViewProvider)?.networkedItemView?.clear()
}
}
fun read(buff: FriendlyByteBuf): ClearItemViewPacket {
return ClearItemViewPacket
}
fun send(ply: ServerPlayer) {
MenuNetworkChannel.send(ply, this)
}
}
class StackAddPacket(val containerId: Int, val id: Int, val stack: ItemStackWrapper) : MatteryPacket {
override fun write(buff: FriendlyByteBuf) {
buff.writeInt(containerId)
buff.writeInt(id)
buff.writeBigItem(stack)
}
override fun play(context: Supplier<NetworkEvent.Context>) {
context.get().packetHandled = true
context.get().enqueueWork {
val get = Minecraft.getInstance().player?.containerMenu ?: return@enqueueWork
@ -38,7 +86,7 @@ class StackAddPacket(val containerId: Int, val id: Int, val stack: ItemStackWrap
if (get.containerId != containerId)
return@enqueueWork
val view = (get as? INetworkedItemViewSupplier)?.networkedItemView ?: throw IllegalStateException("No such item tracker with id $containerId")
val view = (get as? INetworkedItemViewProvider)?.networkedItemView ?: throw IllegalStateException("No such item tracker with id $containerId")
if (view.localState.containsKey(id)) {
throw IllegalStateException("Item tracker $containerId already has stack with id of $id")
@ -81,14 +129,14 @@ class StackAddPacket(val containerId: Int, val id: Int, val stack: ItemStackWrap
}
}
class StackChangePacket(val id: Int, val stackID: Int, val newCount: BigInteger) {
fun write(buffer: FriendlyByteBuf) {
buffer.writeInt(id)
buffer.writeInt(stackID)
buffer.writeBigInteger(newCount)
class StackChangePacket(val id: Int, val stackID: Int, val newCount: BigInteger) : MatteryPacket {
override fun write(buff: FriendlyByteBuf) {
buff.writeInt(id)
buff.writeInt(stackID)
buff.writeBigInteger(newCount)
}
fun play(context: Supplier<NetworkEvent.Context>) {
override fun play(context: Supplier<NetworkEvent.Context>) {
context.get().packetHandled = true
context.get().enqueueWork {
val get = Minecraft.getInstance().player?.containerMenu ?: return@enqueueWork
@ -96,7 +144,7 @@ class StackChangePacket(val id: Int, val stackID: Int, val newCount: BigInteger)
if (get.containerId != id)
return@enqueueWork
val view = (get as? INetworkedItemViewSupplier)?.networkedItemView ?: throw IllegalStateException("No such item tracker with id $id")
val view = (get as? INetworkedItemViewProvider)?.networkedItemView ?: throw IllegalStateException("No such item tracker with id $id")
val state = view.localState[stackID] ?: throw IllegalStateException("No such stack with id $stackID in $view")
state.stack.count = newCount
@ -114,13 +162,13 @@ class StackChangePacket(val id: Int, val stackID: Int, val newCount: BigInteger)
}
}
class StackRemovePacket(val id: Int, val stackID: Int) {
fun write(buffer: FriendlyByteBuf) {
buffer.writeInt(id)
buffer.writeInt(stackID)
class StackRemovePacket(val id: Int, val stackID: Int) : MatteryPacket {
override fun write(buff: FriendlyByteBuf) {
buff.writeInt(id)
buff.writeInt(stackID)
}
fun play(context: Supplier<NetworkEvent.Context>) {
override fun play(context: Supplier<NetworkEvent.Context>) {
context.get().packetHandled = true
context.get().enqueueWork {
val get = Minecraft.getInstance().player?.containerMenu ?: return@enqueueWork
@ -128,7 +176,7 @@ class StackRemovePacket(val id: Int, val stackID: Int) {
if (get.containerId != id)
return@enqueueWork
val view = (get as? INetworkedItemViewSupplier)?.networkedItemView ?: throw IllegalStateException("No such item tracker with id $id")
val view = (get as? INetworkedItemViewProvider)?.networkedItemView ?: throw IllegalStateException("No such item tracker with id $id")
val obj = view.localState.remove(stackID) ?: throw IllegalStateException("No such stack with id $stackID in $view")
view.sortedView.remove(obj)
view.resort()
@ -203,9 +251,8 @@ open class NetworkedItemView(val ply: Player, val menu: MatteryMenu, val remote:
val type =
if (mouse_click_type == InputConstants.MOUSE_BUTTON_MIDDLE) ClickType.CLONE else if (Screen.hasShiftDown()) ClickType.QUICK_MOVE else ClickType.PICKUP
MatteryNetworking.send(
null,
InteractPacket(menu.containerId, if (index >= list.size) -1 else list[index].id, type, action)
MenuNetworkChannel.sendToServer(
ItemViewInteractPacket(if (index >= list.size) -1 else list[index].id, type, action)
)
}
@ -261,39 +308,43 @@ open class NetworkedItemView(val ply: Player, val menu: MatteryMenu, val remote:
if (!remote) {
networkBacklog.clear()
networkBacklog.add(ClearPacket(menu.containerId))
networkBacklog.add(ClearItemViewPacket)
}
}
fun network() {
check(!remote) { "Not a server" }
val consumer = PacketDistributor.PLAYER.with { ply as ServerPlayer }
for (packet in networkBacklog) MatteryNetworking.CHANNEL.send(consumer, packet)
for (packet in networkBacklog) {
MenuNetworkChannel.send(consumer, packet)
}
networkBacklog.clear()
}
fun playerInteract(packet: InteractPacket) {
fun playerInteract(packet: ItemViewInteractPacket) {
val provider = provider ?: return
val click = packet.click
val click = packet.type
val action = packet.action
val stack_id = packet.stack_id
val stackId = packet.stackID
if (click == ClickType.CLONE) {
if (stack_id < 0 || !ply.abilities.instabuild) return
if (stackId < 0 || !ply.abilities.instabuild) return
val state = get(stack_id) ?: return
val state = get(stackId) ?: return
val copy = state.stack.stack.also { it.count = it.maxStackSize }
ply.containerMenu.carried = copy
MatteryNetworking.send(ply as ServerPlayer, SetCarriedPacket(ply.containerMenu.carried))
MenuNetworkChannel.send(ply as ServerPlayer, SetCarriedPacket(ply.containerMenu.carried))
ply.containerMenu.setRemoteCarried(ply.containerMenu.carried.copy())
return
}
if (click == ClickType.QUICK_MOVE && stack_id > -1) {
val state = get(stack_id) ?: return
if (click == ClickType.QUICK_MOVE && stackId > -1) {
val state = get(stackId) ?: return
val amount =
if (action == ClickAction.PRIMARY)
@ -323,7 +374,7 @@ open class NetworkedItemView(val ply: Player, val menu: MatteryMenu, val remote:
if (amount == carried.count) {
val stack = provider.insertStack(ItemStackWrapper(menu.carried), false).stack
menu.carried = stack
MatteryNetworking.send(ply as ServerPlayer, SetCarriedPacket(menu.carried))
MenuNetworkChannel.send(ply as ServerPlayer, SetCarriedPacket(menu.carried))
menu.setRemoteCarried(menu.carried.copy())
}
} else {
@ -332,12 +383,12 @@ open class NetworkedItemView(val ply: Player, val menu: MatteryMenu, val remote:
if (provider.insertStack(ItemStackWrapper(copy), false).isEmpty) {
menu.carried.shrink(1)
MatteryNetworking.send(ply as ServerPlayer, SetCarriedPacket(menu.carried))
MenuNetworkChannel.send(ply as ServerPlayer, SetCarriedPacket(menu.carried))
menu.setRemoteCarried(menu.carried.copy())
}
}
} else if (stack_id > -1) {
val state = get(stack_id) ?: return
} else if (stackId > -1) {
val state = get(stackId) ?: return
val amount =
if (action == ClickAction.PRIMARY)
@ -347,7 +398,7 @@ open class NetworkedItemView(val ply: Player, val menu: MatteryMenu, val remote:
val extracted = provider.extractStack(state.upstreamId!!, amount.toBigInteger(), false)
menu.carried = extracted.stack
MatteryNetworking.send(ply as ServerPlayer, SetCarriedPacket(menu.carried))
MenuNetworkChannel.send(ply as ServerPlayer, SetCarriedPacket(menu.carried))
menu.setRemoteCarried(menu.carried.copy())
}
}

View File

@ -4,12 +4,13 @@ import net.minecraft.network.FriendlyByteBuf
import net.minecraftforge.network.NetworkEvent
import ru.dbotthepony.mc.otm.menu.MatteryMenu
import ru.dbotthepony.mc.otm.menu.data.BooleanDataContainer
import ru.dbotthepony.mc.otm.network.MatteryNetworking
import ru.dbotthepony.mc.otm.network.MatteryPacket
import ru.dbotthepony.mc.otm.network.MenuNetworkChannel
import java.util.function.Supplier
import kotlin.reflect.KMutableProperty0
class BooleanPlayerInputPacket(val id: Int, val value: Boolean) {
fun play(context: Supplier<NetworkEvent.Context>) {
class BooleanPlayerInputPacket(val id: Int, val value: Boolean) : MatteryPacket {
override fun play(context: Supplier<NetworkEvent.Context>) {
context.get().packetHandled = true
context.get().enqueueWork {
@ -17,7 +18,7 @@ class BooleanPlayerInputPacket(val id: Int, val value: Boolean) {
}
}
fun write(buff: FriendlyByteBuf) {
override fun write(buff: FriendlyByteBuf) {
buff.writeInt(id)
buff.writeBoolean(value)
}
@ -70,7 +71,7 @@ class BooleanPlayerInputWidget(menu: MatteryMenu) : AbstractWidget(menu) {
fun asClient(): BooleanPlayerInputWidget {
supplier = null
clicker = {
MatteryNetworking.CHANNEL.sendToServer(BooleanPlayerInputPacket(slotID, it))
MenuNetworkChannel.sendToServer(BooleanPlayerInputPacket(slotID, it))
}
return this

View File

@ -4,13 +4,12 @@ import net.minecraft.network.FriendlyByteBuf
import net.minecraftforge.network.NetworkEvent
import ru.dbotthepony.mc.otm.menu.MatteryMenu
import ru.dbotthepony.mc.otm.menu.data.BigDecimalDataContainer
import ru.dbotthepony.mc.otm.network.MatteryNetworking
import ru.dbotthepony.mc.otm.network.NetworkHelper
import ru.dbotthepony.mc.otm.network.*
import java.math.BigDecimal
import java.util.function.Supplier
class NumberPlayerInputPacket(val id: Int, val value: BigDecimal) {
fun play(context: Supplier<NetworkEvent.Context>) {
class NumberPlayerInputPacket(val id: Int, val value: BigDecimal) : MatteryPacket {
override fun play(context: Supplier<NetworkEvent.Context>) {
context.get().packetHandled = true
context.get().enqueueWork {
@ -18,14 +17,14 @@ class NumberPlayerInputPacket(val id: Int, val value: BigDecimal) {
}
}
fun write(buff: FriendlyByteBuf) {
override fun write(buff: FriendlyByteBuf) {
buff.writeInt(id)
NetworkHelper.writeDecimal(buff, value)
buff.writeDecimal(value)
}
companion object {
fun read(buff: FriendlyByteBuf): NumberPlayerInputPacket {
return NumberPlayerInputPacket(buff.readInt(), NetworkHelper.readDecimal(buff))
return NumberPlayerInputPacket(buff.readInt(), buff.readDecimal())
}
}
}
@ -57,7 +56,7 @@ class NumberPlayerInputWidget(menu: MatteryMenu) : AbstractWidget(menu) {
supplier = null
consumer = {
MatteryNetworking.CHANNEL.sendToServer(NumberPlayerInputPacket(slotID, it))
MenuNetworkChannel.sendToServer(NumberPlayerInputPacket(slotID, it))
}
return this

View File

@ -3,11 +3,12 @@ package ru.dbotthepony.mc.otm.menu.widget
import net.minecraft.network.FriendlyByteBuf
import net.minecraftforge.network.NetworkEvent
import ru.dbotthepony.mc.otm.menu.MatteryMenu
import ru.dbotthepony.mc.otm.network.MatteryNetworking
import ru.dbotthepony.mc.otm.network.MatteryPacket
import ru.dbotthepony.mc.otm.network.MenuNetworkChannel
import java.util.function.Supplier
class OneWayPlayerInputPacket(val id: Int) {
fun play(context: Supplier<NetworkEvent.Context>) {
class OneWayPlayerInputPacket(val id: Int) : MatteryPacket {
override fun play(context: Supplier<NetworkEvent.Context>) {
context.get().packetHandled = true
context.get().enqueueWork {
@ -15,7 +16,7 @@ class OneWayPlayerInputPacket(val id: Int) {
}
}
fun write(buff: FriendlyByteBuf) {
override fun write(buff: FriendlyByteBuf) {
buff.writeInt(id)
}
@ -33,7 +34,7 @@ class OneWayPlayerInputWidget(menu: MatteryMenu, clicker: (() -> Unit)? = null)
if (clicker != null) {
this.clicker = clicker
} else {
this.clicker = { MatteryNetworking.CHANNEL.sendToServer(OneWayPlayerInputPacket(slotID)) }
this.clicker = { MenuNetworkChannel.sendToServer(OneWayPlayerInputPacket(slotID)) }
}
}

View File

@ -11,10 +11,34 @@ import net.minecraftforge.network.NetworkRegistry
import net.minecraftforge.network.PacketDistributor
import net.minecraftforge.network.simple.SimpleChannel
import ru.dbotthepony.mc.otm.OverdriveThatMatters
import java.math.BigDecimal
import java.math.BigInteger
import java.util.Optional
import java.util.concurrent.CompletableFuture
import java.util.function.BiConsumer
import java.util.function.Supplier
fun Supplier<NetworkEvent.Context>.enqueueWork(lambda: Runnable): CompletableFuture<Void> = get().enqueueWork(lambda)
fun Supplier<NetworkEvent.Context>.enqueueWork(lambda: () -> Unit): CompletableFuture<Void> = get().enqueueWork(lambda)
var Supplier<NetworkEvent.Context>.packetHandled: Boolean
get() = get().packetHandled
set(value) { get().packetHandled = value }
val Supplier<NetworkEvent.Context>.sender: ServerPlayer?
get() = get().sender
fun FriendlyByteBuf.writeDecimal(value: BigDecimal) {
writeInt(value.scale())
writeByteArray(value.unscaledValue().toByteArray())
}
fun FriendlyByteBuf.readDecimal(): BigDecimal {
val scale = readInt()
val bytes = readByteArray()
return BigDecimal(BigInteger(bytes), scale)
}
interface MatteryPacket {
fun write(buff: FriendlyByteBuf)
fun play(context: Supplier<NetworkEvent.Context>)

View File

@ -0,0 +1,69 @@
package ru.dbotthepony.mc.otm.network
import net.minecraft.network.FriendlyByteBuf
import net.minecraft.world.item.ItemStack
import net.minecraftforge.network.NetworkDirection
import net.minecraftforge.network.NetworkEvent
import ru.dbotthepony.mc.otm.block.entity.storage.ItemMonitorPlayerSettings
import ru.dbotthepony.mc.otm.client.minecraft
import ru.dbotthepony.mc.otm.container.ItemFilterSlotPacket
import ru.dbotthepony.mc.otm.menu.CancelTaskPacket
import ru.dbotthepony.mc.otm.menu.PatternsChangePacket
import ru.dbotthepony.mc.otm.menu.TasksChangePacket
import ru.dbotthepony.mc.otm.menu.data.*
import ru.dbotthepony.mc.otm.menu.widget.BooleanPlayerInputPacket
import ru.dbotthepony.mc.otm.menu.widget.NumberPlayerInputPacket
import ru.dbotthepony.mc.otm.menu.widget.OneWayPlayerInputPacket
import java.util.function.Supplier
class SetCarriedPacket(val item: ItemStack) : MatteryPacket {
override fun write(buff: FriendlyByteBuf) {
buff.writeItem(item)
}
override fun play(context: Supplier<NetworkEvent.Context>) {
context.get().packetHandled = true
context.get().enqueueWork { minecraft.player?.containerMenu?.carried = item }
}
companion object {
fun read(buff: FriendlyByteBuf): SetCarriedPacket {
return SetCarriedPacket(buff.readItem())
}
}
}
object MenuNetworkChannel : MatteryNetworkChannel(
version = "1",
name = "menu"
) {
fun register() {
add(SetCarriedPacket::class.java, SetCarriedPacket.Companion::read, NetworkDirection.PLAY_TO_CLIENT)
add(ItemFilterSlotPacket::class.java, ItemFilterSlotPacket.Companion::read)
// networked view
add(ClearItemViewPacket::class.java, ClearItemViewPacket::read, NetworkDirection.PLAY_TO_CLIENT)
add(ItemViewInteractPacket::class.java, ItemViewInteractPacket.Companion::read, NetworkDirection.PLAY_TO_SERVER)
add(StackAddPacket::class.java, StackAddPacket.Companion::read, NetworkDirection.PLAY_TO_SERVER)
add(StackChangePacket::class.java, StackChangePacket.Companion::read, NetworkDirection.PLAY_TO_SERVER)
add(StackRemovePacket::class.java, StackRemovePacket.Companion::read, NetworkDirection.PLAY_TO_SERVER)
// container data
add(MultiByteDataContainerPacket::class.java, MultiByteDataContainerPacket.Companion::read, NetworkDirection.PLAY_TO_CLIENT)
// Player input in menus
add(NumberPlayerInputPacket::class.java, NumberPlayerInputPacket.Companion::read, NetworkDirection.PLAY_TO_CLIENT)
add(OneWayPlayerInputPacket::class.java, OneWayPlayerInputPacket.Companion::read, NetworkDirection.PLAY_TO_CLIENT)
add(BooleanPlayerInputPacket::class.java, BooleanPlayerInputPacket.Companion::read, NetworkDirection.PLAY_TO_CLIENT)
// menu specific
// Item monitor
add(ItemMonitorPlayerSettings::class.java, ItemMonitorPlayerSettings.Companion::read)
// matter panel menu
add(CancelTaskPacket::class.java, CancelTaskPacket.Companion::read, NetworkDirection.PLAY_TO_SERVER)
add(PatternsChangePacket::class.java, PatternsChangePacket.Companion::read, NetworkDirection.PLAY_TO_CLIENT)
add(TasksChangePacket::class.java, TasksChangePacket.Companion::read, NetworkDirection.PLAY_TO_CLIENT)
}
}

View File

@ -0,0 +1,19 @@
package ru.dbotthepony.mc.otm.network
import net.minecraftforge.network.NetworkDirection
import ru.dbotthepony.mc.otm.matter.RegistryPacketClear
import ru.dbotthepony.mc.otm.matter.RegistryPacketFullUpdate
import ru.dbotthepony.mc.otm.matter.RegistryPacketRemove
import ru.dbotthepony.mc.otm.matter.RegistryPacketUpdate
object RegistryNetworkChannel : MatteryNetworkChannel(
version = "1",
name = "registry"
) {
fun register() {
add(RegistryPacketRemove::class.java, RegistryPacketRemove.Companion::read, NetworkDirection.PLAY_TO_CLIENT)
add(RegistryPacketClear::class.java, RegistryPacketClear.Companion::read, NetworkDirection.PLAY_TO_CLIENT)
add(RegistryPacketFullUpdate::class.java, RegistryPacketFullUpdate.Companion::read, NetworkDirection.PLAY_TO_CLIENT)
add(RegistryPacketUpdate::class.java, RegistryPacketUpdate.Companion::read, NetworkDirection.PLAY_TO_CLIENT)
}
}

View File

@ -0,0 +1,15 @@
package ru.dbotthepony.mc.otm.network
import net.minecraftforge.network.NetworkDirection
import ru.dbotthepony.mc.otm.item.weapon.WeaponFireInputPacket
import ru.dbotthepony.mc.otm.item.weapon.WeaponScopePacket
object WeaponNetworkChannel : MatteryNetworkChannel(
version = "1",
name = "weapon"
) {
fun register() {
add(WeaponScopePacket::class.java, WeaponScopePacket.Companion::read, NetworkDirection.PLAY_TO_SERVER)
add(WeaponFireInputPacket::class.java, WeaponFireInputPacket.Companion::read, NetworkDirection.PLAY_TO_SERVER)
}
}

View File

@ -0,0 +1,13 @@
package ru.dbotthepony.mc.otm.network
import net.minecraftforge.network.NetworkDirection
import ru.dbotthepony.mc.otm.block.entity.EnergyCounterPacket
object WorldNetworkChannel : MatteryNetworkChannel(
version = "1",
name = "world"
) {
fun register() {
add(EnergyCounterPacket::class.java, EnergyCounterPacket.Companion::read, NetworkDirection.PLAY_TO_CLIENT)
}
}

View File

@ -4,8 +4,6 @@ import org.junit.jupiter.api.DisplayName
import org.junit.jupiter.api.Test
import ru.dbotthepony.mc.otm.core.Fraction
import ru.dbotthepony.mc.otm.menu.data.FractionDataContainer
import ru.dbotthepony.mc.otm.network.NetworkHelper
import kotlin.experimental.and
object NetworkingTests {
@Test
@ -24,25 +22,4 @@ object NetworkingTests {
container.handle(container.makePacket())
assert(container.value.compareTo(frac) == 0) { "${container.value} != $frac" }
}
@Test
@DisplayName("Test NetworkHelper byte/short transition")
fun networkHelper() {
var bytes = byteArrayOf(7, 8, -10)
var shorts = NetworkHelper.bytesToShorts(bytes)
assert(shorts.size == 2) { "Shorts array is not size of 2, but size of ${shorts.size}" }
assert((shorts[0].toInt() and 0xFF).toByte() == bytes[0]) { "${shorts[0] and 0xFF} != ${bytes[0]} ${shorts.joinToString()}" }
assert(((shorts[0].toInt() and 0xFF00) shr 8).toByte() == bytes[1]) { "${(shorts[0].toInt() and 0xFF00) shr 8} != ${bytes[1]} ${shorts.joinToString()}" }
assert((shorts[1].toInt() and 0xFF).toByte() == bytes[2]) { "${shorts[1] and 0xFF} != ${bytes[2]} ${shorts.joinToString()}" }
bytes = byteArrayOf(7, 8, -10, 4)
shorts = NetworkHelper.bytesToShorts(bytes)
assert(shorts.size == 2) { "Shorts array is not size of 2, but size of ${shorts.size}" }
assert((shorts[0].toInt() and 0xFF).toByte() == bytes[0]) { "${shorts[0] and 0xFF} != ${bytes[0]} ${shorts.joinToString()}" }
assert(((shorts[0].toInt() and 0xFF00) shr 8).toByte() == bytes[1]) { "${(shorts[0].toInt() and 0xFF00) shr 8} != ${bytes[1]} ${shorts.joinToString()}" }
assert((shorts[1].toInt() and 0xFF).toByte() == bytes[2]) { "${shorts[1] and 0xFF} != ${bytes[2]} ${shorts.joinToString()}" }
assert(((shorts[1].toInt() and 0xFF00) shr 8).toByte() == bytes[3]) { "${(shorts[1].toInt() and 0xFF00) shr 8} != ${bytes[3]} ${shorts.joinToString()}" }
}
}