Fixed TNT and basic networking.

This commit is contained in:
Sebastian Hartte
2020-06-30 11:30:04 +02:00
parent 3337eb9ae3
commit c0a4762ffc
25 changed files with 593 additions and 454 deletions
@@ -83,7 +83,7 @@ public class TinyTNTBlock extends AEBaseBlock {
public void startFuse(final World w, final BlockPos pos, final LivingEntity igniter) {
if (!w.isClient) {
final TinyTNTPrimedEntity primedTinyTNTEntity = new TinyTNTPrimedEntity(w, pos.getX() + 0.5F,
pos.getY() + 0.5F, pos.getZ() + 0.5F, igniter);
pos.getY(), pos.getZ() + 0.5F, igniter);
w.spawnEntity(primedTinyTNTEntity);
w.playSound(null, primedTinyTNTEntity.getX(), primedTinyTNTEntity.getY(),
primedTinyTNTEntity.getZ(), SoundEvents.ENTITY_TNT_PRIMED, SoundCategory.BLOCKS, 1, 1);
@@ -1,7 +1,6 @@
package appeng.client;
import appeng.api.parts.CableRenderMode;
import appeng.block.AEBaseBlock;
import appeng.bootstrap.ModelsReloadCallback;
import appeng.bootstrap.components.IItemColorRegistrationComponent;
import appeng.bootstrap.components.IModelBakeComponent;
@@ -10,18 +9,19 @@ import appeng.client.render.tesr.SkyChestTESR;
import appeng.core.Api;
import appeng.core.ApiDefinitions;
import appeng.core.AppEngBase;
import appeng.core.sync.BasePacket;
import appeng.core.sync.network.ClientNetworkHandler;
import appeng.entity.*;
import net.fabricmc.fabric.api.client.particle.v1.ParticleFactoryRegistry;
import net.fabricmc.fabric.api.client.rendereregistry.v1.EntityRendererRegistry;
import net.fabricmc.fabric.api.event.client.ClientSpriteRegistryCallback;
import net.minecraft.block.entity.BlockEntity;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.render.entity.ItemEntityRenderer;
import net.minecraft.client.render.model.BakedModel;
import net.minecraft.client.util.InputUtil;
import net.minecraft.client.util.SpriteIdentifier;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.integrated.IntegratedServer;
import net.minecraft.util.Identifier;
import net.minecraft.util.hit.HitResult;
import net.minecraft.world.World;
@@ -34,14 +34,17 @@ import java.util.Random;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class AppEngClient extends AppEngBase {
public final class AppEngClient extends AppEngBase {
private final MinecraftClient client;
private final ClientNetworkHandler networkHandler;
public AppEngClient() {
super();
client = MinecraftClient.getInstance();
networkHandler = new ClientNetworkHandler();
ModelsReloadCallback.EVENT.register(this::onModelsReloaded);
@@ -52,18 +55,18 @@ public class AppEngClient extends AppEngBase {
}
@Override
public void bindTileEntitySpecialRenderer(Class<? extends BlockEntity> tile, AEBaseBlock blk) {
public MinecraftServer getServer() {
IntegratedServer server = client.getServer();
if (server != null) {
return server;
}
throw new IllegalStateException("No server is currently running.");
}
@Override
public List<? extends PlayerEntity> getPlayers() {
return null;
}
@Override
public void sendToAllNearExcept(PlayerEntity p, double x, double y, double z, double dist, World w, BasePacket packet) {
public Stream<? extends PlayerEntity> getPlayers() {
return Stream.empty();
}
@Override
+11 -3
View File
@@ -26,6 +26,7 @@ import appeng.core.sync.BasePacket;
import net.minecraft.block.entity.BlockEntity;
import net.minecraft.client.util.InputUtil;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.server.MinecraftServer;
import net.minecraft.util.Identifier;
import net.minecraft.util.hit.HitResult;
import net.minecraft.world.World;
@@ -33,6 +34,7 @@ import net.minecraft.world.World;
import javax.annotation.Nonnull;
import java.util.List;
import java.util.Random;
import java.util.stream.Stream;
public interface AppEng {
@@ -48,9 +50,7 @@ public interface AppEng {
return new Identifier(MOD_ID, id);
}
void bindTileEntitySpecialRenderer(Class<? extends BlockEntity> tile, AEBaseBlock blk);
List<? extends PlayerEntity> getPlayers();
Stream<? extends PlayerEntity> getPlayers();
void sendToAllNearExcept(PlayerEntity p, double x, double y, double z, double dist, World w,
BasePacket packet);
@@ -72,6 +72,14 @@ public interface AppEng {
boolean isActionKey(@Nonnull final ActionKey key, InputUtil.Key input);
/**
* Get the currently running server. On the client-side this may throw if no server
* is currently running or a remote server has been joined.
*
* @return The current server. Never null.
*/
MinecraftServer getServer();
//
// private final Registration registration;
//
+17 -7
View File
@@ -2,13 +2,6 @@ package appeng.core;
import appeng.api.features.IRegistryContainer;
import appeng.api.networking.IGridCacheRegistry;
import appeng.api.networking.crafting.ICraftingGrid;
import appeng.api.networking.energy.IEnergyGrid;
import appeng.api.networking.pathing.IPathingGrid;
import appeng.api.networking.security.ISecurityGrid;
import appeng.api.networking.spatial.ISpatialCache;
import appeng.api.networking.storage.IStorageGrid;
import appeng.api.networking.ticking.ITickManager;
import appeng.bootstrap.components.ITileEntityRegistrationComponent;
import appeng.client.render.effects.ParticleTypes;
import appeng.core.features.registries.cell.BasicCellHandler;
@@ -16,10 +9,15 @@ import appeng.core.features.registries.cell.BasicItemCellGuiHandler;
import appeng.core.features.registries.cell.CreativeCellHandler;
import appeng.core.stats.AdvancementTriggers;
import appeng.core.stats.AeStats;
import appeng.core.sync.BasePacket;
import appeng.core.sync.network.NetworkHandler;
import appeng.core.sync.network.TargetPoint;
import appeng.hooks.ToolItemHook;
import appeng.mixins.CriteriaRegisterMixin;
import net.fabricmc.loader.api.FabricLoader;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.util.registry.Registry;
import net.minecraft.world.World;
public abstract class AppEngBase implements AppEng {
@@ -88,4 +86,16 @@ public abstract class AppEngBase implements AppEng {
.forEachRemaining(ITileEntityRegistrationComponent::register);
}
@Override
public void sendToAllNearExcept(final PlayerEntity p, final double x, final double y, final double z,
final double dist, final World w, final BasePacket packet) {
if (w.isClient()) {
return;
}
NetworkHandler.instance().sendToAllAround(packet, new TargetPoint(
x, y, z, dist, w
));
}
}
@@ -42,6 +42,7 @@ import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings;
import net.fabricmc.fabric.api.tool.attribute.v1.FabricToolTags;
import net.minecraft.block.*;
import net.minecraft.client.render.RenderLayer;
import net.minecraft.entity.EntityDimensions;
import net.minecraft.entity.SpawnGroup;
import net.minecraft.sound.BlockSoundGroup;
@@ -280,7 +281,8 @@ public final class ApiBlocks implements IBlocks {
TinyTNTPrimedEntity.TYPE = registry
.<TinyTNTPrimedEntity>entity("tiny_tnt_primed", TinyTNTPrimedEntity::new, SpawnGroup.MISC)
.customize(p -> p.trackable(16, 4, true))
// Entity properties are a copy of the standard TNT entity
.customize(p -> p.trackable(10, 10, true).dimensions(EntityDimensions.fixed(0.98f, 0.98f)))
.build();
this.tinyTNT = registry
@@ -18,17 +18,14 @@
package appeng.core.features.registries;
import java.util.UUID;
import javax.annotation.Nullable;
import com.mojang.authlib.GameProfile;
import net.minecraft.entity.player.PlayerEntity;
import appeng.api.features.IPlayerRegistry;
import appeng.core.AppEng;
import appeng.core.worlddata.WorldData;
import com.mojang.authlib.GameProfile;
import net.minecraft.entity.player.PlayerEntity;
import javax.annotation.Nullable;
import java.util.UUID;
public class PlayerRegistry implements IPlayerRegistry {
@@ -54,12 +51,9 @@ public class PlayerRegistry implements IPlayerRegistry {
return null;
}
for (final PlayerEntity player : AppEng.instance().getPlayers()) {
if (player.getGameProfile().getId().equals(profileId)) {
return player;
}
}
return null;
return AppEng.instance().getPlayers()
.filter(p -> p.getGameProfile().getId().equals(profileId))
.findFirst()
.orElse(null);
}
}
@@ -43,8 +43,7 @@ public abstract class BasePacket {
}
public final int getPacketID() {
throw new IllegalStateException();
// FIXME FABRIC return BasePacketHandler.PacketTypes.getID(this.getClass()).ordinal();
return BasePacketHandler.PacketTypes.getID(this.getClass()).ordinal();
}
public void clientPacketData(final INetworkInfo network, final PlayerEntity player) {
@@ -0,0 +1,106 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2014, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.core.sync;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Function;
import appeng.core.sync.packets.SpawnEntityPacket;
import net.minecraft.network.PacketByteBuf;
public class BasePacketHandler {
private static final Map<Class<? extends BasePacket>, PacketTypes> REVERSE_LOOKUP = new HashMap<>();
public enum PacketTypes {
// PACKET_COMPASS_REQUEST(CompassRequestPacket.class, CompassRequestPacket::new),
//
// PACKET_COMPASS_RESPONSE(CompassResponsePacket.class, CompassResponsePacket::new),
//
// PACKET_INVENTORY_ACTION(InventoryActionPacket.class, InventoryActionPacket::new),
//
// PACKET_ME_INVENTORY_UPDATE(MEInventoryUpdatePacket.class, MEInventoryUpdatePacket::new),
//
// PACKET_ME_FLUID_INVENTORY_UPDATE(MEFluidInventoryUpdatePacket.class, MEFluidInventoryUpdatePacket::new),
//
// PACKET_CONFIG_BUTTON(ConfigButtonPacket.class, ConfigButtonPacket::new),
//
// PACKET_PART_PLACEMENT(PartPlacementPacket.class, PartPlacementPacket::new),
//
// PACKET_LIGHTNING(LightningPacket.class, LightningPacket::new),
//
// PACKET_MATTER_CANNON(MatterCannonPacket.class, MatterCannonPacket::new),
//
// PACKET_MOCK_EXPLOSION(MockExplosionPacket.class, MockExplosionPacket::new),
//
// PACKET_VALUE_CONFIG(ConfigValuePacket.class, ConfigValuePacket::new),
//
// PACKET_ITEM_TRANSITION_EFFECT(ItemTransitionEffectPacket.class, ItemTransitionEffectPacket::new),
//
// PACKET_BLOCK_TRANSITION_EFFECT(BlockTransitionEffectPacket.class, BlockTransitionEffectPacket::new),
//
// PACKET_PROGRESS_VALUE(ProgressBarPacket.class, ProgressBarPacket::new),
//
// PACKET_CLICK(ClickPacket.class, ClickPacket::new),
//
// PACKET_SWITCH_GUIS(SwitchGuisPacket.class, SwitchGuisPacket::new),
//
// PACKET_SWAP_SLOTS(SwapSlotsPacket.class, SwapSlotsPacket::new),
//
// PACKET_PATTERN_SLOT(PatternSlotPacket.class, PatternSlotPacket::new),
//
// PACKET_RECIPE_JEI(JEIRecipePacket.class, JEIRecipePacket::new),
//
// PACKET_TARGET_ITEM(TargetItemStackPacket.class, TargetItemStackPacket::new),
//
// PACKET_TARGET_FLUID(TargetFluidStackPacket.class, TargetFluidStackPacket::new),
//
// PACKET_CRAFTING_REQUEST(CraftRequestPacket.class, CraftRequestPacket::new),
//
// PACKET_ASSEMBLER_ANIMATION(AssemblerAnimationPacket.class, AssemblerAnimationPacket::new),
//
// PACKET_COMPRESSED_NBT(CompressedNBTPacket.class, CompressedNBTPacket::new),
//
// PACKET_PAINTED_ENTITY(PaintedEntityPacket.class, PaintedEntityPacket::new),
//
// PACKET_FLUID_TANK(FluidSlotPacket.class, FluidSlotPacket::new);
SPAWN_ENTITY(SpawnEntityPacket.class, SpawnEntityPacket::new);
;
private final Function<PacketByteBuf, BasePacket> factory;
PacketTypes(Class<? extends BasePacket> packetClass, Function<PacketByteBuf, BasePacket> factory) {
this.factory = factory;
REVERSE_LOOKUP.put(packetClass, this);
}
public static PacketTypes getPacket(final int id) {
return (values())[id];
}
static PacketTypes getID(final Class<? extends BasePacket> c) {
return REVERSE_LOOKUP.get(c);
}
public BasePacket parsePacket(final PacketByteBuf in) throws IllegalArgumentException {
return this.factory.apply(in);
}
}
}
@@ -0,0 +1,37 @@
package appeng.core.sync.network;
import appeng.core.AELog;
import appeng.core.sync.BasePacket;
import appeng.core.sync.BasePacketHandler;
import net.fabricmc.fabric.api.network.ClientSidePacketRegistry;
import net.fabricmc.fabric.api.network.PacketContext;
import net.minecraft.network.NetworkSide;
import net.minecraft.network.PacketByteBuf;
public class ClientNetworkHandler extends ServerNetworkHandler {
private final ClientSidePacketRegistry registry = ClientSidePacketRegistry.INSTANCE;
public ClientNetworkHandler() {
registry.register(BasePacket.CHANNEL, this::handlePacketFromServer);
}
@Override
public void sendToServer(BasePacket message) {
registry.sendToServer(message.toPacket(NetworkSide.SERVERBOUND));
}
private void handlePacketFromServer(PacketContext packetContext, PacketByteBuf payload) {
final int packetType = payload.readInt();
final BasePacket packet = BasePacketHandler.PacketTypes.getPacket(packetType).parsePacket(payload);
packetContext.getTaskQueue().execute(() -> {
try {
packet.clientPacketData(null, packetContext.getPlayer());
} catch (final IllegalArgumentException e) {
AELog.debug(e);
}
});
}
}
@@ -18,12 +18,24 @@
package appeng.core.sync.network;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.network.INetHandler;
import net.minecraft.network.PacketByteBuf;
import appeng.core.sync.BasePacket;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.world.World;
public interface IPacketHandler {
public interface NetworkHandler {
void onPacketData(INetworkInfo manager, INetHandler handler, PacketByteBuf packet, PlayerEntity player);
static NetworkHandler instance() {
return NetworkHandlerHolder.INSTANCE;
}
void sendToAll(final BasePacket message);
void sendTo(final BasePacket message, final ServerPlayerEntity player);
void sendToAllAround(final BasePacket message, final TargetPoint point);
void sendToDimension(final BasePacket message, final World world);
void sendToServer(final BasePacket message);
}
@@ -0,0 +1,5 @@
package appeng.core.sync.network;
class NetworkHandlerHolder {
static NetworkHandler INSTANCE;
}
@@ -0,0 +1,81 @@
package appeng.core.sync.network;
import appeng.core.AELog;
import appeng.core.AppEng;
import appeng.core.sync.BasePacket;
import appeng.core.sync.BasePacketHandler;
import net.fabricmc.fabric.api.network.PacketContext;
import net.fabricmc.fabric.api.network.ServerSidePacketRegistry;
import net.fabricmc.fabric.api.server.PlayerStream;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.network.NetworkSide;
import net.minecraft.network.Packet;
import net.minecraft.network.PacketByteBuf;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.World;
public class ServerNetworkHandler implements NetworkHandler {
private final ServerSidePacketRegistry registry = ServerSidePacketRegistry.INSTANCE;
public ServerNetworkHandler() {
registry.register(BasePacket.CHANNEL, this::handlePacketFromClient);
}
public void sendToAll(final BasePacket message) {
MinecraftServer server = AppEng.instance().getServer();
Packet<?> packet = message.toPacket(NetworkSide.CLIENTBOUND);
PlayerStream.all(server).forEach(player -> registry.sendToPlayer(player, packet));
}
public void sendTo(final BasePacket message, final ServerPlayerEntity player) {
Packet<?> packet = message.toPacket(NetworkSide.CLIENTBOUND);
registry.sendToPlayer(player, packet);
}
public void sendToAllAround(final BasePacket message, final TargetPoint point) {
Packet<?> packet = message.toPacket(NetworkSide.CLIENTBOUND);
PlayerStream.around(point.world, new Vec3d(point.x, point.y, point.z), point.radius)
.forEach(player -> {
if (player != point.excluded) {
ServerSidePacketRegistry.INSTANCE.sendToPlayer(player, packet);
}
});
}
public void sendToDimension(final BasePacket message, final World world) {
Packet<?> packet = message.toPacket(NetworkSide.CLIENTBOUND);
PlayerStream.world(world)
.forEach(player -> ServerSidePacketRegistry.INSTANCE.sendToPlayer(player, packet));
}
@Override
public void sendToServer(BasePacket message) {
throw new IllegalStateException("Cannot send packets to the server when we're the server!");
}
private void handlePacketFromClient(PacketContext packetContext, PacketByteBuf payload) {
// Deserialize the packet on the netwhrok th
PlayerEntity player = packetContext.getPlayer();
if (!(player instanceof ServerPlayerEntity)) {
AELog.warn("Received a packet for a non-server player entity!", player);
return;
}
final int packetType = payload.readInt();
final BasePacket pack = BasePacketHandler.PacketTypes.getPacket(packetType).parsePacket(payload);
packetContext.getTaskQueue().execute(() -> {
try {
pack.serverPacketData(null, player);
} catch (final IllegalArgumentException e) {
AELog.debug(e);
}
});
}
}
@@ -0,0 +1,31 @@
package appeng.core.sync.network;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.world.World;
/**
* Created by covers1624 on 1/6/20.
*/
public class TargetPoint {
public final ServerPlayerEntity excluded;
public final double x;
public final double y;
public final double z;
public final double radius;
public final World world;
public TargetPoint(double x, double y, double z, double radius, World world) {
this(null, x, y, z, radius, world);
}
public TargetPoint(ServerPlayerEntity excluded, double x, double y, double z, double radius, World world) {
this.excluded = excluded;
this.x = x;
this.y = y;
this.z = z;
this.radius = radius;
this.world = world;
}
}
@@ -0,0 +1,14 @@
package appeng.core.sync.packets;
import net.minecraft.entity.EntityType;
import net.minecraft.network.PacketByteBuf;
public interface ICustomEntity {
default void writeAdditionalSpawnData(PacketByteBuf buf) {
}
default void readAdditionalSpawnData(PacketByteBuf buf) {
}
}
@@ -0,0 +1,118 @@
package appeng.core.sync.packets;
import appeng.core.sync.BasePacket;
import appeng.core.sync.network.INetworkInfo;
import io.netty.buffer.Unpooled;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.client.world.ClientWorld;
import net.minecraft.entity.*;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.network.NetworkSide;
import net.minecraft.network.Packet;
import net.minecraft.network.PacketByteBuf;
import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.Vec3d;
import net.minecraft.util.registry.Registry;
import java.util.UUID;
import java.util.function.Consumer;
// This is essentially a copy of EntitySpawnS2CPacket, supporting custom entities
public class SpawnEntityPacket extends BasePacket {
private int id;
private UUID uuid;
private double x;
private double y;
private double z;
private int velocityX;
private int velocityY;
private int velocityZ;
private int pitch;
private int yaw;
private EntityType<?> entityTypeId;
private PacketByteBuf extraData;
public SpawnEntityPacket(PacketByteBuf buf) {
this.id = buf.readVarInt();
this.uuid = buf.readUuid();
this.entityTypeId = Registry.ENTITY_TYPE.get(buf.readVarInt());
this.x = buf.readDouble();
this.y = buf.readDouble();
this.z = buf.readDouble();
this.pitch = buf.readByte();
this.yaw = buf.readByte();
this.velocityX = buf.readShort();
this.velocityY = buf.readShort();
this.velocityZ = buf.readShort();
this.extraData = new PacketByteBuf(buf.copy());
}
public SpawnEntityPacket(int id, UUID uuid, double x, double y, double z, float pitch, float yaw, EntityType<?> entityTypeId, Vec3d velocity, Consumer<PacketByteBuf> extraSpawnData) {
this.id = id;
this.uuid = uuid;
this.x = x;
this.y = y;
this.z = z;
this.pitch = MathHelper.floor(pitch * 256.0F / 360.0F);
this.yaw = MathHelper.floor(yaw * 256.0F / 360.0F);
this.entityTypeId = entityTypeId;
this.velocityX = (int)(MathHelper.clamp(velocity.x, -3.9D, 3.9D) * 8000.0D);
this.velocityY = (int)(MathHelper.clamp(velocity.y, -3.9D, 3.9D) * 8000.0D);
this.velocityZ = (int)(MathHelper.clamp(velocity.z, -3.9D, 3.9D) * 8000.0D);
final PacketByteBuf data = new PacketByteBuf(Unpooled.buffer());
data.writeInt(this.getPacketID());
data.writeVarInt(this.id);
data.writeUuid(this.uuid);
data.writeVarInt(Registry.ENTITY_TYPE.getRawId(this.entityTypeId));
data.writeDouble(this.x);
data.writeDouble(this.y);
data.writeDouble(this.z);
data.writeByte(this.pitch);
data.writeByte(this.yaw);
data.writeShort(this.velocityX);
data.writeShort(this.velocityY);
data.writeShort(this.velocityZ);
extraSpawnData.accept(data);
this.configureWrite(data);
}
public SpawnEntityPacket(Entity entity, Consumer<PacketByteBuf> extraSpawnData) {
this(entity.getEntityId(), entity.getUuid(), entity.getX(), entity.getY(), entity.getZ(), entity.pitch, entity.yaw, entity.getType(), entity.getVelocity(), extraSpawnData);
}
@Override
@Environment(EnvType.CLIENT)
public void clientPacketData(INetworkInfo network, PlayerEntity player) {
ClientWorld world = (ClientWorld) player.world;
EntityType<?> entityType = entityTypeId;
Entity entity = entityType.create(world);
if (entity != null) {
entity.updateTrackedPosition(x, y, z);
entity.refreshPositionAfterTeleport(x, y, z);
entity.pitch = (float)(pitch * 360) / 256.0F;
entity.yaw = (float)(yaw * 360) / 256.0F;
entity.setEntityId(id);
entity.setUuid(uuid);
if (entity instanceof ICustomEntity) {
((ICustomEntity) entity).readAdditionalSpawnData(extraData);
}
world.addEntity(id, entity);
}
}
public static <T extends Entity & ICustomEntity> Packet<?> create(T entity) {
// Not having this typed local variable will lead to a JVM bug because
// the method reference will have a target type of "Entity" and not "ICustomEntity"
@SuppressWarnings("UnnecessaryLocalVariable") ICustomEntity customEntity = entity;
SpawnEntityPacket packet = new SpawnEntityPacket(entity, customEntity::writeAdditionalSpawnData);
return packet.toPacket(NetworkSide.CLIENTBOUND);
}
}
@@ -21,13 +21,17 @@ package appeng.entity;
import appeng.api.AEApi;
import appeng.api.features.AEFeature;
import appeng.core.AEConfig;
import appeng.core.sync.packets.ICustomEntity;
import appeng.core.sync.packets.SpawnEntityPacket;
import appeng.util.Platform;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks;
import net.minecraft.block.Material;
import net.minecraft.entity.*;
import net.minecraft.entity.damage.DamageSource;
import net.minecraft.network.Packet;
import net.minecraft.network.PacketByteBuf;
import net.minecraft.particle.ParticleTypes;
import net.minecraft.sound.SoundCategory;
import net.minecraft.sound.SoundEvents;
@@ -39,7 +43,7 @@ import net.minecraft.world.explosion.Explosion;
import javax.annotation.Nullable;
import java.util.List;
public final class TinyTNTPrimedEntity extends TntEntity {
public final class TinyTNTPrimedEntity extends TntEntity implements ICustomEntity {
public static EntityType<TinyTNTPrimedEntity> TYPE;
@@ -52,7 +56,7 @@ public final class TinyTNTPrimedEntity extends TntEntity {
public TinyTNTPrimedEntity(final World world, final double x, final double y, final double z,
final LivingEntity igniter) {
this(TYPE, world);
super(TYPE, world);
this.updatePosition(x, y, z);
double d = world.random.nextDouble() * 6.2831854820251465D;
this.setVelocity(-Math.sin(d) * 0.02D, 0.20000000298023224D, -Math.cos(d) * 0.02D);
@@ -74,33 +78,16 @@ public final class TinyTNTPrimedEntity extends TntEntity {
*/
@Override
public void tick() {
this.updateWaterState();
this.prevX = this.getX();
this.prevY = this.getY();
this.prevZ = this.getZ();
this.setVelocity(this.getVelocity().subtract(0, 0.03999999910593033D, 0));
this.move(MovementType.SELF, this.getVelocity());
this.setVelocity(this.getVelocity().multiply(0.9800000190734863D, 0.9800000190734863D, 0.9800000190734863D));
if (this.onGround) {
this.setVelocity(this.getVelocity().multiply(0.699999988079071D, 0.699999988079071D, -0.5D));
if (!this.hasNoGravity()) {
this.setVelocity(this.getVelocity().add(0.0D, -0.04D, 0.0D));
}
if (this.isSubmergedInWater() && Platform.isServer()) // put out the fuse.
{
AEApi.instance().definitions().blocks().tinyTNT().maybeStack(1).ifPresent(tntStack -> {
final ItemEntity item = new ItemEntity(this.world, this.getX(), this.getY(), this.getZ(),
tntStack);
item.setVelocity(this.getVelocity());
item.prevX = this.prevX;
item.prevY = this.prevY;
item.prevZ = this.prevZ;
this.world.spawnEntity(item);
this.remove();
});
this.move(MovementType.SELF, this.getVelocity());
this.setVelocity(this.getVelocity().multiply(0.98D));
if (this.onGround) {
// Bounce up
this.setVelocity(this.getVelocity().multiply(0.7D, -0.5D, 0.7D));
}
if (this.getFuse() <= 0) {
@@ -110,6 +97,23 @@ public final class TinyTNTPrimedEntity extends TntEntity {
this.explode();
}
} else {
this.updateWaterState();
if (this.isSubmergedInWater() && Platform.isServer()) // put out the fuse.
{
AEApi.instance().definitions().blocks().tinyTNT().maybeStack(1).ifPresent(tntStack -> {
final ItemEntity item = new ItemEntity(this.world, this.getX(), this.getY(), this.getZ(),
tntStack);
item.setVelocity(this.getVelocity());
item.prevX = this.prevX;
item.prevY = this.prevY;
item.prevZ = this.prevZ;
this.world.spawnEntity(item);
this.remove();
});
}
this.world.addParticle(ParticleTypes.SMOKE, this.getX(), this.getY(), this.getZ(), 0.0D, 0.0D,
0.0D);
}
@@ -157,11 +161,12 @@ public final class TinyTNTPrimedEntity extends TntEntity {
strength -= (resistance + 0.3F) * 0.11f;
if (strength > 0.01) {
if (state.getMaterial() == Material.AIR) {
if (state.getMaterial() != Material.AIR) {
if (block.shouldDropItemsOnExplosion(ex)) {
Block.dropStacks(state, this.world, blockPos);
}
this.world.setBlockState(blockPos, Blocks.AIR.getDefaultState(), 3);
block.onDestroyedByExplosion(this.world, blockPos, ex);
}
}
@@ -171,16 +176,22 @@ public final class TinyTNTPrimedEntity extends TntEntity {
}
}
throw new IllegalStateException();
// FIXME FABRIC
// AppEng.proxy.sendToAllNearExcept(null, this.getX(), this.getY(), this.getZ(), 64, this.world,
// new MockExplosionPacket(this.getX(), this.getY(), this.getZ()));
this.world.addParticle(ParticleTypes.EXPLOSION, this.getX(), this.getY(), this.getZ(), 1.0D, 0.0D, 0.0D);
}
@Override
public Packet<?> createSpawnPacket() {
// FIXME FABRIC
throw new IllegalStateException();
return SpawnEntityPacket.create(this);
}
@Override
public void writeAdditionalSpawnData(PacketByteBuf buf) {
buf.writeByte(this.getFuse());
}
@Override
public void readAdditionalSpawnData(PacketByteBuf buf) {
this.setFuse(buf.readByte());
}
}
@@ -0,0 +1,83 @@
package appeng.server;
import appeng.api.parts.CableRenderMode;
import appeng.block.AEBaseBlock;
import appeng.client.ActionKey;
import appeng.client.EffectType;
import appeng.core.AppEngBase;
import appeng.core.sync.network.ServerNetworkHandler;
import net.fabricmc.fabric.api.server.PlayerStream;
import net.minecraft.block.entity.BlockEntity;
import net.minecraft.client.util.InputUtil;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.server.MinecraftServer;
import net.minecraft.util.hit.HitResult;
import net.minecraft.world.World;
import javax.annotation.Nonnull;
import java.util.List;
import java.util.Random;
import java.util.stream.Stream;
public final class AppEngServer extends AppEngBase {
private final MinecraftServer server;
private final ServerNetworkHandler networkHandler;
public AppEngServer(MinecraftServer server) {
this.server = server;
this.networkHandler = new ServerNetworkHandler();
}
@Override
public Stream<? extends PlayerEntity> getPlayers() {
return PlayerStream.all(server);
}
@Override
public void spawnEffect(EffectType effect, World world, double posX, double posY, double posZ, Object extra) {
}
@Override
public boolean shouldAddParticles(Random r) {
return false;
}
@Override
public HitResult getRTR() {
return null;
}
@Override
public void postInit() {
}
@Override
public CableRenderMode getRenderMode() {
return null;
}
@Override
public void triggerUpdates() {
}
@Override
public void updateRenderMode(PlayerEntity player) {
}
@Override
public boolean isActionKey(@Nonnull ActionKey key, InputUtil.Key input) {
return false;
}
@Override
public MinecraftServer getServer() {
return server;
}
}
@@ -1,105 +0,0 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2014, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.core.sync;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Function;
import net.minecraft.network.PacketByteBuf;
import appeng.core.sync.packets.*;
public class BasePacketHandler {
private static final Map<Class<? extends BasePacket>, PacketTypes> REVERSE_LOOKUP = new HashMap<>();
public enum PacketTypes {
PACKET_COMPASS_REQUEST(CompassRequestPacket.class, CompassRequestPacket::new),
PACKET_COMPASS_RESPONSE(CompassResponsePacket.class, CompassResponsePacket::new),
PACKET_INVENTORY_ACTION(InventoryActionPacket.class, InventoryActionPacket::new),
PACKET_ME_INVENTORY_UPDATE(MEInventoryUpdatePacket.class, MEInventoryUpdatePacket::new),
PACKET_ME_FLUID_INVENTORY_UPDATE(MEFluidInventoryUpdatePacket.class, MEFluidInventoryUpdatePacket::new),
PACKET_CONFIG_BUTTON(ConfigButtonPacket.class, ConfigButtonPacket::new),
PACKET_PART_PLACEMENT(PartPlacementPacket.class, PartPlacementPacket::new),
PACKET_LIGHTNING(LightningPacket.class, LightningPacket::new),
PACKET_MATTER_CANNON(MatterCannonPacket.class, MatterCannonPacket::new),
PACKET_MOCK_EXPLOSION(MockExplosionPacket.class, MockExplosionPacket::new),
PACKET_VALUE_CONFIG(ConfigValuePacket.class, ConfigValuePacket::new),
PACKET_ITEM_TRANSITION_EFFECT(ItemTransitionEffectPacket.class, ItemTransitionEffectPacket::new),
PACKET_BLOCK_TRANSITION_EFFECT(BlockTransitionEffectPacket.class, BlockTransitionEffectPacket::new),
PACKET_PROGRESS_VALUE(ProgressBarPacket.class, ProgressBarPacket::new),
PACKET_CLICK(ClickPacket.class, ClickPacket::new),
PACKET_SWITCH_GUIS(SwitchGuisPacket.class, SwitchGuisPacket::new),
PACKET_SWAP_SLOTS(SwapSlotsPacket.class, SwapSlotsPacket::new),
PACKET_PATTERN_SLOT(PatternSlotPacket.class, PatternSlotPacket::new),
PACKET_RECIPE_JEI(JEIRecipePacket.class, JEIRecipePacket::new),
PACKET_TARGET_ITEM(TargetItemStackPacket.class, TargetItemStackPacket::new),
PACKET_TARGET_FLUID(TargetFluidStackPacket.class, TargetFluidStackPacket::new),
PACKET_CRAFTING_REQUEST(CraftRequestPacket.class, CraftRequestPacket::new),
PACKET_ASSEMBLER_ANIMATION(AssemblerAnimationPacket.class, AssemblerAnimationPacket::new),
PACKET_COMPRESSED_NBT(CompressedNBTPacket.class, CompressedNBTPacket::new),
PACKET_PAINTED_ENTITY(PaintedEntityPacket.class, PaintedEntityPacket::new),
PACKET_FLUID_TANK(FluidSlotPacket.class, FluidSlotPacket::new);
private final Function<PacketByteBuf, BasePacket> factory;
PacketTypes(Class<? extends BasePacket> packetClass, Function<PacketByteBuf, BasePacket> factory) {
this.factory = factory;
REVERSE_LOOKUP.put(packetClass, this);
}
public static PacketTypes getPacket(final int id) {
return (values())[id];
}
static PacketTypes getID(final Class<? extends BasePacket> c) {
return REVERSE_LOOKUP.get(c);
}
public BasePacket parsePacket(final PacketByteBuf in) throws IllegalArgumentException {
return this.factory.apply(in);
}
}
}
@@ -1,4 +0,0 @@
package appeng.core.sync.network;
public class ClientNetworkHandler {
}
@@ -1,43 +0,0 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2014, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.core.sync.network;
import net.minecraft.client.MinecraftClient;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.network.INetHandler;
import net.minecraft.network.PacketByteBuf;
import appeng.core.AELog;
import appeng.core.sync.BasePacket;
import appeng.core.sync.BasePacketHandler;
public class ClientPacketHandler extends BasePacketHandler implements IPacketHandler {
@Override
public void onPacketData(final INetworkInfo manager, final INetHandler handler, final PacketByteBuf packet,
final PlayerEntity player) {
try {
final int packetType = packet.readInt();
final BasePacket pack = PacketTypes.getPacket(packetType).parsePacket(packet);
pack.clientPacketData(manager, MinecraftClient.getInstance().player);
} catch (final IllegalArgumentException e) {
AELog.debug(e);
}
}
}
@@ -1,138 +0,0 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2014, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.core.sync.network;
import net.minecraft.client.MinecraftClient;
import net.minecraft.network.NetworkSide;
import net.minecraft.network.Packet;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.network.INetHandler;
import net.minecraft.network.ThreadQuickExitException;
import net.minecraft.network.play.ServerPlayNetHandler;
import net.minecraft.server.MinecraftServer;
import net.minecraft.util.Identifier;
import net.minecraft.world.dimension.DimensionType;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.DistExecutor;
import net.minecraftforge.fml.LogicalSide;
import net.minecraftforge.fml.LogicalSidedProvider;
import net.minecraftforge.fml.network.NetworkEvent;
import net.minecraftforge.fml.network.NetworkRegistry;
import net.minecraftforge.fml.network.event.EventNetworkChannel;
import appeng.core.sync.BasePacket;
public class NetworkHandler {
private static NetworkHandler instance;
private final Identifier myChannelName;
private final IPacketHandler clientHandler;
private final IPacketHandler serverHandler;
public NetworkHandler(final Identifier channelName) {
EventNetworkChannel ec = NetworkRegistry.ChannelBuilder.named(myChannelName = channelName)
.networkProtocolVersion(() -> "1").clientAcceptedVersions(s -> true).serverAcceptedVersions(s -> true)
.eventNetworkChannel();
ec.registerObject(this);
this.clientHandler = DistExecutor.unsafeRunForDist(() -> ClientPacketHandler::new, () -> () -> null);
this.serverHandler = this.createServerSide();
}
public static void init(final Identifier channelName) {
instance = new NetworkHandler(channelName);
}
public static NetworkHandler instance() {
return instance;
}
private IPacketHandler createServerSide() {
try {
return new ServerPacketHandler();
} catch (final Throwable t) {
return null;
}
}
@SubscribeEvent
public void serverPacket(final NetworkEvent.ClientCustomPayloadEvent ev) {
if (this.serverHandler != null) {
try {
NetworkEvent.Context ctx = ev.getSource().get();
ServerPlayNetHandler netHandler = (ServerPlayNetHandler) ctx.getNetworkManager().getNetHandler();
ctx.setPacketHandled(true);
ctx.enqueueWork(
() -> this.serverHandler.onPacketData(null, netHandler, ev.getPayload(), netHandler.player));
} catch (final ThreadQuickExitException ignored) {
}
}
}
@SubscribeEvent
public void clientPacket(final NetworkEvent.ServerCustomPayloadEvent ev) {
if (ev instanceof NetworkEvent.ServerCustomPayloadLoginEvent) {
return;
}
if (this.clientHandler != null) {
try {
NetworkEvent.Context ctx = ev.getSource().get();
INetHandler netHandler = ctx.getNetworkManager().getNetHandler();
ctx.setPacketHandled(true);
ctx.enqueueWork(() -> this.clientHandler.onPacketData(null, netHandler, ev.getPayload(), null));
} catch (final ThreadQuickExitException ignored) {
}
}
}
public Identifier getChannel() {
return this.myChannelName;
}
public void sendToAll(final BasePacket message) {
getServer().getPlayerList().sendPacketToAllPlayers(message.toPacket(NetworkSide.PLAY_TO_CLIENT));
}
public void sendTo(final BasePacket message, final ServerPlayerEntity player) {
player.connection.sendPacket(message.toPacket(NetworkSide.PLAY_TO_CLIENT));
}
public void sendToAllAround(final BasePacket message, final TargetPoint point) {
Packet<?> pkt = message.toPacket(NetworkSide.PLAY_TO_CLIENT);
getServer().getPlayerList().sendToAllNearExcept(point.excluded, point.x, point.y, point.z, point.r2, point.dim,
pkt);
}
public void sendToDimension(final BasePacket message, final DimensionType dim) {
getServer().getPlayerList().sendPacketToAllPlayersInDimension(message.toPacket(NetworkSide.PLAY_TO_CLIENT),
dim);
}
public void sendToServer(final BasePacket message) {
MinecraftClient.getInstance().getConnection().sendPacket(message.toPacket(NetworkSide.PLAY_TO_SERVER));
}
private MinecraftServer getServer() {
return LogicalSidedProvider.INSTANCE.get(LogicalSide.SERVER);
}
}
@@ -1,4 +0,0 @@
package appeng.core.sync.network;
public class ServerNetworkHandler {
}
@@ -1,42 +0,0 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2014, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.core.sync.network;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.network.INetHandler;
import net.minecraft.network.PacketByteBuf;
import appeng.core.AELog;
import appeng.core.sync.BasePacket;
import appeng.core.sync.BasePacketHandler;
public final class ServerPacketHandler extends BasePacketHandler implements IPacketHandler {
@Override
public void onPacketData(final INetworkInfo manager, final INetHandler handler, final PacketByteBuf packet,
final PlayerEntity player) {
try {
final int packetType = packet.readInt();
final BasePacket pack = PacketTypes.getPacket(packetType).parsePacket(packet);
pack.serverPacketData(manager, player);
} catch (final IllegalArgumentException e) {
AELog.debug(e);
}
}
}
@@ -1,39 +0,0 @@
package appeng.core.sync.network;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.world.dimension.DimensionType;
/**
* Created by covers1624 on 1/6/20.
*/
public class TargetPoint {
public final ServerPlayerEntity excluded;
public final double x;
public final double y;
public final double z;
public final double r2;
public final DimensionType dim;
public TargetPoint(double x, double y, double z, double r2, DimensionType dim) {
this(null, x, y, z, r2, dim);
}
public TargetPoint(ServerPlayerEntity excluded, double x, double y, double z, double r2, DimensionType dim) {
this.excluded = excluded;
this.x = x;
this.y = y;
this.z = z;
this.r2 = r2;
this.dim = dim;
}
public static TargetPoint at(double x, double y, double z, double r2, DimensionType dim) {
return new TargetPoint(x, y, z, r2, dim);
}
public static TargetPoint at(ServerPlayerEntity excluded, double x, double y, double z, double r2,
DimensionType dim) {
return new TargetPoint(excluded, x, y, z, r2, dim);
}
}