Fix issues when loading on a dedicated server

This commit is contained in:
Sollace 2021-03-22 20:18:31 +02:00
parent f74d7be038
commit 3c1eaec5d4
5 changed files with 54 additions and 32 deletions

View file

@ -120,7 +120,7 @@ public class BlockDestructionManager {
MsgBlockDestruction msg = new MsgBlockDestruction(values);
if (msg.toBuffer().writerIndex() > 1048576) {
if (Channel.toBuffer(msg).writerIndex() > 1048576) {
throw new IllegalStateException("Payload may not be larger than 1048576 bytes. Here's what we were trying to send: ["
+ values.size() + "]\n"
+ Arrays.toString(values.values().stream().mapToInt(Integer::intValue).toArray()));

View file

@ -4,6 +4,8 @@ import com.minelittlepony.unicopia.UTags;
import com.minelittlepony.unicopia.client.sound.MagicAuraSoundInstance;
import com.minelittlepony.unicopia.entity.Living;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.client.MinecraftClient;
import net.minecraft.enchantment.EnchantmentTarget;
import net.minecraft.entity.EquipmentSlot;
@ -32,6 +34,7 @@ public class GemFindingEnchantment extends SimpleEnchantment {
user.getEnchants().computeIfAbsent(this, Data::new).level = volume * (1.3F + level * 0.3F);
}
@Environment(EnvType.CLIENT)
@Override
public void onEquipped(Living<?> user) {
if (user.isClient()) {

View file

@ -30,6 +30,7 @@ import net.minecraft.util.registry.Registry;
public class PoisonedJokeEnchantment extends SimpleEnchantment implements IdentifiableResourceReloadListener {
private static final Identifier ID = new Identifier("unicopia", "data/poisoned_joke_sounds");
private static final Identifier FILE = new Identifier("unicopia", "poisoned_joke_sounds.json");
private static final Type TYPE = TypeUtils.parameterize(List.class, Identifier.class);
private List<SoundEvent> sounds = new ArrayList<>();
@ -76,9 +77,8 @@ public class PoisonedJokeEnchantment extends SimpleEnchantment implements Identi
clientProfiler.startTick();
clientProfiler.push("Loading poisoned joke sound options");
sounds = manager.getAllNamespaces().stream()
.map(domain -> new Identifier(domain, "poisoned_joke_sounds.json"))
.flatMap(id -> getResources(manager, id))
sounds = getResources(manager, FILE)
.flatMap(this::loadFile)
.distinct()
.flatMap(this::findSound)

View file

@ -2,6 +2,8 @@ package com.minelittlepony.unicopia.network;
import java.util.function.Function;
import com.google.common.base.Preconditions;
import io.netty.buffer.Unpooled;
import net.fabricmc.api.EnvType;
import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking;
@ -9,18 +11,16 @@ import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking;
import net.fabricmc.loader.api.FabricLoader;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.util.Identifier;
import net.minecraft.util.thread.ThreadExecutor;
import net.minecraft.world.World;
import net.minecraft.network.PacketByteBuf;
import net.minecraft.server.network.ServerPlayerEntity;
public interface Channel {
SPacketType<MsgPlayerAbility<?>> CLIENT_PLAYER_ABILITY = clientToServer(new Identifier("unicopia", "player_ability"), MsgPlayerAbility::new);
SPacketType<MsgRequestCapabilities> CLIENT_REQUEST_CAPABILITIES = clientToServer(new Identifier("unicopia", "request_capabilities"), MsgRequestCapabilities::new);
CPacketType<MsgPlayerCapabilities> SERVER_PLAYER_CAPABILITIES = serverToClient(new Identifier("unicopia", "player_capabilities"), MsgPlayerCapabilities::new);
MPacketType<MsgOtherPlayerCapabilities> SERVER_OTHER_PLAYER_CAPABILITIES = serverToClients(new Identifier("unicopia", "other_player_capabilities"), MsgOtherPlayerCapabilities::new);
BPacketType<MsgOtherPlayerCapabilities> SERVER_OTHER_PLAYER_CAPABILITIES = serverToClients(new Identifier("unicopia", "other_player_capabilities"), MsgOtherPlayerCapabilities::new);
CPacketType<MsgSpawnProjectile> SERVER_SPAWN_PROJECTILE = serverToClient(new Identifier("unicopia", "projectile_entity"), MsgSpawnProjectile::new);
CPacketType<MsgBlockDestruction> SERVER_BLOCK_DESTRUCTION = serverToClient(new Identifier("unicopia", "block_destruction"), MsgBlockDestruction::new);
@ -29,61 +29,65 @@ public interface Channel {
static <T extends Packet> SPacketType<T> clientToServer(Identifier id, Function<PacketByteBuf, T> factory) {
ServerPlayNetworking.registerGlobalReceiver(id, (server, player, handler, buffer, responder) -> {
factory.apply(buffer).handleOnMain(server, player);
T packet = factory.apply(buffer);
server.execute(() -> packet.handle(player));
});
return () -> id;
}
static <T extends Packet> CPacketType<T> serverToClient(Identifier id, Function<PacketByteBuf, T> factory) {
if (FabricLoader.getInstance().getEnvironmentType() == EnvType.CLIENT) {
ClientPlayNetworking.registerGlobalReceiver(id, (client, ignore1, buffer, ignore2) -> {
factory.apply(buffer).handleOnMain(client, client.player);
});
ClientProxy.register(id, factory);
}
return () -> id;
}
static <T extends Packet> MPacketType<T> serverToClients(Identifier id, Function<PacketByteBuf, T> factory) {
static <T extends Packet> BPacketType<T> serverToClients(Identifier id, Function<PacketByteBuf, T> factory) {
if (FabricLoader.getInstance().getEnvironmentType() == EnvType.CLIENT) {
ClientPlayNetworking.registerGlobalReceiver(id, (client, ignore1, buffer, ignore2) -> {
factory.apply(buffer).handleOnMain(client, client.player);
});
ClientProxy.register(id, factory);
}
return () -> id;
}
interface MPacketType<T extends Packet> {
/**
* A broadcast packet type. Sent by the server to all surrounding players.
*/
interface BPacketType<T extends Packet> {
Identifier getId();
default void send(World world, T packet) {
world.getPlayers().forEach(player -> {
if (player != null) {
ServerPlayNetworking.send((ServerPlayerEntity)player, getId(), packet.toBuffer());
if (player instanceof ServerPlayerEntity) {
ServerPlayNetworking.send((ServerPlayerEntity)player, getId(), toBuffer(packet));
}
});
}
}
/**
* A client packet type. Sent by the server to a specific player.
*/
interface CPacketType<T extends Packet> {
Identifier getId();
default void send(PlayerEntity recipient, T packet) {
ServerPlayNetworking.send((ServerPlayerEntity)recipient, getId(), packet.toBuffer());
ServerPlayNetworking.send(((ServerPlayerEntity)recipient), getId(), toBuffer(packet));
}
default net.minecraft.network.Packet<?> toPacket(T packet) {
return ServerPlayNetworking.createS2CPacket(getId(), packet.toBuffer());
return ServerPlayNetworking.createS2CPacket(getId(), toBuffer(packet));
}
}
/**
* A server packet type. Sent by the client to the server.
*/
interface SPacketType<T extends Packet> {
Identifier getId();
default void send(T packet) {
if (FabricLoader.getInstance().getEnvironmentType() != EnvType.CLIENT) {
throw new RuntimeException("Client packet send called by the server");
}
ClientPlayNetworking.send(getId(), packet.toBuffer());
Preconditions.checkState(FabricLoader.getInstance().getEnvironmentType() == EnvType.CLIENT, "Client packet send called by the server");
ClientPlayNetworking.send(getId(), toBuffer(packet));
}
}
@ -91,15 +95,20 @@ public interface Channel {
void handle(PlayerEntity sender);
void toBuffer(PacketByteBuf buffer);
}
default void handleOnMain(ThreadExecutor<?> server, PlayerEntity player) {
server.execute(() -> handle(player));
}
static PacketByteBuf toBuffer(Packet packet) {
PacketByteBuf buf = new PacketByteBuf(Unpooled.buffer());
packet.toBuffer(buf);
return buf;
}
default PacketByteBuf toBuffer() {
PacketByteBuf buf = new PacketByteBuf(Unpooled.buffer());
toBuffer(buf);
return buf;
class ClientProxy {
static <T extends Packet> void register(Identifier id, Function<PacketByteBuf, T> factory) {
ClientPlayNetworking.registerGlobalReceiver(id, (client, ignore1, buffer, ignore2) -> {
T packet = factory.apply(buffer);
client.execute(() -> packet.handle(client.player));
});
}
}
}

View file

@ -5,6 +5,8 @@ import java.util.Optional;
import com.minelittlepony.unicopia.Owned;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.world.ClientWorld;
import net.minecraft.entity.Entity;
@ -33,9 +35,17 @@ public class MsgSpawnProjectile extends EntitySpawnS2CPacket implements Channel.
}
}
@SuppressWarnings("unchecked")
@Override
public void handle(PlayerEntity sender) {
if (sender.world.isClient) {
handledByClient(sender);
}
}
@Environment(EnvType.CLIENT)
@SuppressWarnings("unchecked")
private void handledByClient(PlayerEntity sender) {
ClientWorld world = MinecraftClient.getInstance().world;
Entity entity = getEntityTypeId().create(world);