mirror of
https://github.com/Minestom/Minestom.git
synced 2024-12-27 03:27:56 +01:00
Reworked packet writer
This commit is contained in:
parent
c407e384ab
commit
d5d3dab6c7
@ -21,6 +21,13 @@ import java.lang.reflect.InvocationTargetException;
|
|||||||
|
|
||||||
public class Main {
|
public class Main {
|
||||||
|
|
||||||
|
// Thread number
|
||||||
|
public static final int THREAD_COUNT_PACKET_WRITER = 3;
|
||||||
|
public static final int THREAD_COUNT_CHUNK_BATCH = 2;
|
||||||
|
public static final int THREAD_COUNT_OBJECTS_ENTITIES = 2;
|
||||||
|
public static final int THREAD_COUNT_CREATURES_ENTITIES = 2;
|
||||||
|
public static final int THREAD_COUNT_PLAYERS_ENTITIES = 2;
|
||||||
|
|
||||||
public static final int TICK_MS = 50;
|
public static final int TICK_MS = 50;
|
||||||
|
|
||||||
// Networking
|
// Networking
|
||||||
@ -101,12 +108,14 @@ public class Main {
|
|||||||
currentTime = System.nanoTime();
|
currentTime = System.nanoTime();
|
||||||
|
|
||||||
// Keep Alive Handling
|
// Keep Alive Handling
|
||||||
server.getConnections().stream().filter(connection -> packetProcessor.hasPlayerConnection(connection) && connectionManager.getPlayer(packetProcessor.getPlayerConnection(connection)) != null && System.currentTimeMillis() - connectionManager.getPlayer(packetProcessor.getPlayerConnection(connection)).getLastKeepAlive() > 20000).map(connection -> connectionManager.getPlayer(packetProcessor.getPlayerConnection(connection))).forEach(player -> {
|
for (Player player : getConnectionManager().getOnlinePlayers()) {
|
||||||
long id = System.currentTimeMillis();
|
if (System.currentTimeMillis() - player.getLastKeepAlive() > 20000) {
|
||||||
player.refreshKeepAlive(id);
|
long id = System.currentTimeMillis();
|
||||||
KeepAlivePacket keepAlivePacket = new KeepAlivePacket(id);
|
player.refreshKeepAlive(id);
|
||||||
player.getPlayerConnection().sendPacket(keepAlivePacket);
|
KeepAlivePacket keepAlivePacket = new KeepAlivePacket(id);
|
||||||
});
|
player.getPlayerConnection().sendPacket(keepAlivePacket);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Entities update
|
// Entities update
|
||||||
entityManager.update();
|
entityManager.update();
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package fr.themode.minestom;
|
package fr.themode.minestom;
|
||||||
|
|
||||||
import fr.themode.minestom.entity.Player;
|
import fr.themode.minestom.entity.Player;
|
||||||
|
import fr.themode.minestom.net.PacketWriter;
|
||||||
import fr.themode.minestom.net.packet.server.ServerPacket;
|
import fr.themode.minestom.net.packet.server.ServerPacket;
|
||||||
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
@ -21,8 +22,13 @@ public interface Viewable {
|
|||||||
if (getViewers().isEmpty())
|
if (getViewers().isEmpty())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
//Packet p = PacketUtils.writePacket(packet);
|
PacketWriter.writeCallbackPacket(packet, buffer -> {
|
||||||
getViewers().forEach(player -> player.getPlayerConnection().sendPacket(packet));
|
buffer.getData().retain(getViewers().size()).markReaderIndex();
|
||||||
|
getViewers().forEach(player -> {
|
||||||
|
player.getPlayerConnection().sendUnencodedPacket(buffer);
|
||||||
|
buffer.getData().resetReaderIndex();
|
||||||
|
});
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
default void sendPacketsToViewers(ServerPacket... packets) {
|
default void sendPacketsToViewers(ServerPacket... packets) {
|
||||||
@ -30,17 +36,29 @@ public interface Viewable {
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
for (ServerPacket packet : packets) {
|
for (ServerPacket packet : packets) {
|
||||||
//Packet p = PacketUtils.writePacket(packet);
|
PacketWriter.writeCallbackPacket(packet, buffer -> {
|
||||||
getViewers().forEach(player -> player.getPlayerConnection().sendPacket(packet));
|
buffer.getData().retain(getViewers().size()).markReaderIndex();
|
||||||
|
getViewers().forEach(player -> {
|
||||||
|
player.getPlayerConnection().sendUnencodedPacket(buffer);
|
||||||
|
buffer.getData().resetReaderIndex();
|
||||||
|
});
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
default void sendPacketToViewersAndSelf(ServerPacket packet) {
|
default void sendPacketToViewersAndSelf(ServerPacket packet) {
|
||||||
if (this instanceof Player) {
|
if (this instanceof Player) {
|
||||||
//Packet p = PacketUtils.writePacket(packet);
|
PacketWriter.writeCallbackPacket(packet, buffer -> {
|
||||||
((Player) this).getPlayerConnection().sendPacket(packet);
|
buffer.getData().retain(getViewers().size() + 1).markReaderIndex();
|
||||||
if (!getViewers().isEmpty())
|
((Player) this).getPlayerConnection().sendUnencodedPacket(buffer);
|
||||||
getViewers().forEach(player -> player.getPlayerConnection().sendPacket(packet));
|
buffer.getData().resetReaderIndex();
|
||||||
|
if (!getViewers().isEmpty()) {
|
||||||
|
getViewers().forEach(player -> {
|
||||||
|
buffer.getData().resetReaderIndex();
|
||||||
|
player.getPlayerConnection().sendUnencodedPacket(buffer);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -225,7 +225,12 @@ public abstract class Entity implements Viewable {
|
|||||||
|
|
||||||
public void setOnFire(boolean fire) {
|
public void setOnFire(boolean fire) {
|
||||||
this.onFire = fire;
|
this.onFire = fire;
|
||||||
sendMetadata(0);
|
sendMetadataIndex(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setNoGravity(boolean noGravity) {
|
||||||
|
this.noGravity = noGravity;
|
||||||
|
sendMetadataIndex(5);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isChunkUnloaded(float x, float z) {
|
public boolean isChunkUnloaded(float x, float z) {
|
||||||
@ -264,12 +269,12 @@ public abstract class Entity implements Viewable {
|
|||||||
|
|
||||||
public void refreshSneaking(boolean sneaking) {
|
public void refreshSneaking(boolean sneaking) {
|
||||||
this.crouched = sneaking;
|
this.crouched = sneaking;
|
||||||
sendMetadata(0);
|
sendMetadataIndex(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void refreshSprinting(boolean sprinting) {
|
public void refreshSprinting(boolean sprinting) {
|
||||||
this.sprinting = sprinting;
|
this.sprinting = sprinting;
|
||||||
sendMetadata(0);
|
sendMetadataIndex(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Position getPosition() {
|
public Position getPosition() {
|
||||||
@ -302,10 +307,11 @@ public abstract class Entity implements Viewable {
|
|||||||
Buffer buffer = Buffer.create();
|
Buffer buffer = Buffer.create();
|
||||||
fillMetadataIndex(buffer, 0);
|
fillMetadataIndex(buffer, 0);
|
||||||
fillMetadataIndex(buffer, 1);
|
fillMetadataIndex(buffer, 1);
|
||||||
|
fillMetadataIndex(buffer, 5);
|
||||||
return buffer;
|
return buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void sendMetadata(int index) {
|
protected void sendMetadataIndex(int index) {
|
||||||
Buffer buffer = Buffer.create();
|
Buffer buffer = Buffer.create();
|
||||||
fillMetadataIndex(buffer, index);
|
fillMetadataIndex(buffer, index);
|
||||||
|
|
||||||
@ -329,6 +335,9 @@ public abstract class Entity implements Viewable {
|
|||||||
case 2:
|
case 2:
|
||||||
fillCustomNameMetaData(buffer);
|
fillCustomNameMetaData(buffer);
|
||||||
break;
|
break;
|
||||||
|
case 5:
|
||||||
|
fillNoGravityMetaData(buffer);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -367,6 +376,12 @@ public abstract class Entity implements Viewable {
|
|||||||
Utils.writeString(buffer, customName);
|
Utils.writeString(buffer, customName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void fillNoGravityMetaData(Buffer buffer) {
|
||||||
|
buffer.putByte((byte) 5);
|
||||||
|
buffer.putByte(METADATA_BOOLEAN);
|
||||||
|
buffer.putBoolean(noGravity);
|
||||||
|
}
|
||||||
|
|
||||||
private boolean shouldUpdate() {
|
private boolean shouldUpdate() {
|
||||||
return (float) (System.currentTimeMillis() - lastUpdate) >= Main.TICK_MS * 0.9f; // Margin of error
|
return (float) (System.currentTimeMillis() - lastUpdate) >= Main.TICK_MS * 0.9f; // Margin of error
|
||||||
}
|
}
|
||||||
|
@ -13,9 +13,9 @@ public class EntityManager {
|
|||||||
|
|
||||||
private static InstanceManager instanceManager = Main.getInstanceManager();
|
private static InstanceManager instanceManager = Main.getInstanceManager();
|
||||||
|
|
||||||
private ExecutorService objectsPool = Executors.newFixedThreadPool(2);
|
private ExecutorService objectsPool = Executors.newFixedThreadPool(Main.THREAD_COUNT_OBJECTS_ENTITIES);
|
||||||
private ExecutorService creaturesPool = Executors.newFixedThreadPool(2);
|
private ExecutorService creaturesPool = Executors.newFixedThreadPool(Main.THREAD_COUNT_CREATURES_ENTITIES);
|
||||||
private ExecutorService playersPool = Executors.newFixedThreadPool(2);
|
private ExecutorService playersPool = Executors.newFixedThreadPool(Main.THREAD_COUNT_PLAYERS_ENTITIES);
|
||||||
|
|
||||||
// TODO API for custom thread division (
|
// TODO API for custom thread division (
|
||||||
public void update() {
|
public void update() {
|
||||||
|
@ -2,6 +2,7 @@ package fr.themode.minestom.entity;
|
|||||||
|
|
||||||
import fr.adamaq01.ozao.net.Buffer;
|
import fr.adamaq01.ozao.net.Buffer;
|
||||||
import fr.themode.minestom.item.ItemStack;
|
import fr.themode.minestom.item.ItemStack;
|
||||||
|
import fr.themode.minestom.net.packet.server.play.EntityRelativeMovePacket;
|
||||||
import fr.themode.minestom.utils.Utils;
|
import fr.themode.minestom.utils.Utils;
|
||||||
|
|
||||||
public class ItemEntity extends ObjectEntity {
|
public class ItemEntity extends ObjectEntity {
|
||||||
@ -16,7 +17,11 @@ public class ItemEntity extends ObjectEntity {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void update() {
|
public void update() {
|
||||||
|
// TODO how to keep items at the same position?
|
||||||
|
EntityRelativeMovePacket entityRelativeMovePacket = new EntityRelativeMovePacket();
|
||||||
|
entityRelativeMovePacket.entityId = getEntityId();
|
||||||
|
entityRelativeMovePacket.onGround = false;
|
||||||
|
sendPacketToViewers(entityRelativeMovePacket);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -37,6 +42,11 @@ public class ItemEntity extends ObjectEntity {
|
|||||||
return itemStack;
|
return itemStack;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setItemStack(ItemStack itemStack) {
|
||||||
|
this.itemStack = itemStack;
|
||||||
|
sendMetadataIndex(7); // Refresh itemstack for viewers
|
||||||
|
}
|
||||||
|
|
||||||
public boolean isPickable() {
|
public boolean isPickable() {
|
||||||
return pickable;
|
return pickable;
|
||||||
}
|
}
|
||||||
|
@ -1,16 +1,9 @@
|
|||||||
package fr.themode.minestom.entity;
|
package fr.themode.minestom.entity;
|
||||||
|
|
||||||
import fr.themode.minestom.Viewable;
|
|
||||||
import fr.themode.minestom.net.packet.server.play.SpawnObjectPacket;
|
import fr.themode.minestom.net.packet.server.play.SpawnObjectPacket;
|
||||||
import fr.themode.minestom.net.player.PlayerConnection;
|
import fr.themode.minestom.net.player.PlayerConnection;
|
||||||
|
|
||||||
import java.util.Collections;
|
public abstract class ObjectEntity extends Entity {
|
||||||
import java.util.Set;
|
|
||||||
import java.util.concurrent.CopyOnWriteArraySet;
|
|
||||||
|
|
||||||
public abstract class ObjectEntity extends Entity implements Viewable {
|
|
||||||
|
|
||||||
private Set<Player> viewers = new CopyOnWriteArraySet<>();
|
|
||||||
|
|
||||||
public ObjectEntity(int entityType) {
|
public ObjectEntity(int entityType) {
|
||||||
super(entityType);
|
super(entityType);
|
||||||
@ -37,9 +30,4 @@ public abstract class ObjectEntity extends Entity implements Viewable {
|
|||||||
public void removeViewer(Player player) {
|
public void removeViewer(Player player) {
|
||||||
super.removeViewer(player);
|
super.removeViewer(player);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public Set<Player> getViewers() {
|
|
||||||
return Collections.unmodifiableSet(viewers);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -20,9 +20,9 @@ import fr.themode.minestom.world.Dimension;
|
|||||||
import fr.themode.minestom.world.LevelType;
|
import fr.themode.minestom.world.LevelType;
|
||||||
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.LinkedList;
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||||
import java.util.concurrent.CopyOnWriteArraySet;
|
import java.util.concurrent.CopyOnWriteArraySet;
|
||||||
|
|
||||||
public class Player extends LivingEntity {
|
public class Player extends LivingEntity {
|
||||||
@ -31,7 +31,7 @@ public class Player extends LivingEntity {
|
|||||||
|
|
||||||
private String username;
|
private String username;
|
||||||
private PlayerConnection playerConnection;
|
private PlayerConnection playerConnection;
|
||||||
private LinkedList<ClientPlayPacket> packets = new LinkedList<>();
|
private ConcurrentLinkedQueue<ClientPlayPacket> packets = new ConcurrentLinkedQueue<>();
|
||||||
|
|
||||||
private Dimension dimension;
|
private Dimension dimension;
|
||||||
private GameMode gameMode;
|
private GameMode gameMode;
|
||||||
@ -87,6 +87,7 @@ public class Player extends LivingEntity {
|
|||||||
((EntityCreature) entity).kill();
|
((EntityCreature) entity).kill();
|
||||||
sendMessage("You killed an entity!");
|
sendMessage("You killed an entity!");
|
||||||
}
|
}
|
||||||
|
sendMessage("ATTACK");
|
||||||
/*UpdateHealthPacket updateHealthPacket = new UpdateHealthPacket();
|
/*UpdateHealthPacket updateHealthPacket = new UpdateHealthPacket();
|
||||||
updateHealthPacket.health = -1f;
|
updateHealthPacket.health = -1f;
|
||||||
updateHealthPacket.food = 5;
|
updateHealthPacket.food = 5;
|
||||||
@ -101,11 +102,9 @@ public class Player extends LivingEntity {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void update() {
|
public void update() {
|
||||||
synchronized (packets) {
|
ClientPlayPacket packet = null;
|
||||||
while (!packets.isEmpty()) {
|
while ((packet = packets.poll()) != null) {
|
||||||
ClientPlayPacket packet = packets.pollFirst();
|
packet.process(this);
|
||||||
packet.process(this);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Target block stage
|
// Target block stage
|
||||||
@ -422,9 +421,7 @@ public class Player extends LivingEntity {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void addPacketToQueue(ClientPlayPacket packet) {
|
public void addPacketToQueue(ClientPlayPacket packet) {
|
||||||
synchronized (packets) {
|
this.packets.add(packet);
|
||||||
this.packets.add(packet);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void refreshDimension(Dimension dimension) {
|
public void refreshDimension(Dimension dimension) {
|
||||||
|
24
src/main/java/fr/themode/minestom/entity/demo/TestArrow.java
Normal file
24
src/main/java/fr/themode/minestom/entity/demo/TestArrow.java
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
package fr.themode.minestom.entity.demo;
|
||||||
|
|
||||||
|
import fr.themode.minestom.entity.LivingEntity;
|
||||||
|
import fr.themode.minestom.entity.ObjectEntity;
|
||||||
|
|
||||||
|
public class TestArrow extends ObjectEntity {
|
||||||
|
|
||||||
|
private LivingEntity shooter;
|
||||||
|
|
||||||
|
public TestArrow(LivingEntity shooter) {
|
||||||
|
super(2);
|
||||||
|
this.shooter = shooter;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getData() {
|
||||||
|
return shooter.getEntityId() + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void update() {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -1,10 +1,14 @@
|
|||||||
package fr.themode.minestom.instance;
|
package fr.themode.minestom.instance;
|
||||||
|
|
||||||
|
import fr.adamaq01.ozao.net.Buffer;
|
||||||
|
import fr.adamaq01.ozao.net.packet.Packet;
|
||||||
import fr.themode.minestom.Main;
|
import fr.themode.minestom.Main;
|
||||||
import fr.themode.minestom.entity.Entity;
|
import fr.themode.minestom.entity.Entity;
|
||||||
import fr.themode.minestom.entity.EntityCreature;
|
import fr.themode.minestom.entity.EntityCreature;
|
||||||
import fr.themode.minestom.entity.ObjectEntity;
|
import fr.themode.minestom.entity.ObjectEntity;
|
||||||
import fr.themode.minestom.entity.Player;
|
import fr.themode.minestom.entity.Player;
|
||||||
|
import fr.themode.minestom.net.packet.server.play.ChunkDataPacket;
|
||||||
|
import fr.themode.minestom.utils.PacketUtils;
|
||||||
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
@ -26,10 +30,14 @@ public class Chunk {
|
|||||||
// Block entities
|
// Block entities
|
||||||
private Set<Integer> blockEntities = new CopyOnWriteArraySet<>();
|
private Set<Integer> blockEntities = new CopyOnWriteArraySet<>();
|
||||||
|
|
||||||
|
// Cache
|
||||||
|
private Buffer fullDataPacket;
|
||||||
|
|
||||||
public Chunk(Biome biome, int chunkX, int chunkZ) {
|
public Chunk(Biome biome, int chunkX, int chunkZ) {
|
||||||
this.biome = biome;
|
this.biome = biome;
|
||||||
this.chunkX = chunkX;
|
this.chunkX = chunkX;
|
||||||
this.chunkZ = chunkZ;
|
this.chunkZ = chunkZ;
|
||||||
|
//refreshDataPacket(); // TODO remove
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void setBlock(byte x, byte y, byte z, short blockId) {
|
protected void setBlock(byte x, byte y, byte z, short blockId) {
|
||||||
@ -130,6 +138,10 @@ public class Chunk {
|
|||||||
return Collections.unmodifiableSet(players);
|
return Collections.unmodifiableSet(players);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Buffer getFullDataPacket() {
|
||||||
|
return fullDataPacket;
|
||||||
|
}
|
||||||
|
|
||||||
private boolean isBlockEntity(short blockId) {
|
private boolean isBlockEntity(short blockId) {
|
||||||
// TODO complete
|
// TODO complete
|
||||||
return blockId == 2033;
|
return blockId == 2033;
|
||||||
@ -145,4 +157,20 @@ public class Chunk {
|
|||||||
index |= (z << 12) & 0xF000;
|
index |= (z << 12) & 0xF000;
|
||||||
return index & 0xffff;
|
return index & 0xffff;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setFullDataPacket(Buffer fullDataPacket) {
|
||||||
|
this.fullDataPacket = fullDataPacket;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected ChunkDataPacket getFreshFullDataPacket() {
|
||||||
|
ChunkDataPacket fullDataPacket = new ChunkDataPacket();
|
||||||
|
fullDataPacket.chunk = this;
|
||||||
|
fullDataPacket.fullChunk = true;
|
||||||
|
return fullDataPacket;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void refreshDataPacket() {
|
||||||
|
Packet packet = PacketUtils.writePacket(getFreshFullDataPacket());
|
||||||
|
this.fullDataPacket = PacketUtils.encode(packet); // TODO write packet buffer in another thread (heavy calculations)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
package fr.themode.minestom.instance;
|
package fr.themode.minestom.instance;
|
||||||
|
|
||||||
|
import fr.themode.minestom.Main;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.concurrent.ExecutorService;
|
import java.util.concurrent.ExecutorService;
|
||||||
@ -7,7 +9,7 @@ import java.util.concurrent.Executors;
|
|||||||
|
|
||||||
public class ChunkBatch implements BlockModifier {
|
public class ChunkBatch implements BlockModifier {
|
||||||
|
|
||||||
private static volatile ExecutorService batchesPool = Executors.newFixedThreadPool(3);
|
private static volatile ExecutorService batchesPool = Executors.newFixedThreadPool(Main.THREAD_COUNT_CHUNK_BATCH);
|
||||||
|
|
||||||
private Instance instance;
|
private Instance instance;
|
||||||
private Chunk chunk;
|
private Chunk chunk;
|
||||||
@ -47,6 +49,7 @@ public class ChunkBatch implements BlockModifier {
|
|||||||
for (BlockData data : dataList) {
|
for (BlockData data : dataList) {
|
||||||
data.apply(chunk);
|
data.apply(chunk);
|
||||||
}
|
}
|
||||||
|
chunk.refreshDataPacket(); // TODO partial refresh instead of full
|
||||||
instance.sendChunkUpdate(chunk); // TODO partial chunk data
|
instance.sendChunkUpdate(chunk); // TODO partial chunk data
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,12 @@
|
|||||||
package fr.themode.minestom.instance;
|
package fr.themode.minestom.instance;
|
||||||
|
|
||||||
|
import fr.adamaq01.ozao.net.Buffer;
|
||||||
import fr.themode.minestom.entity.Entity;
|
import fr.themode.minestom.entity.Entity;
|
||||||
import fr.themode.minestom.entity.EntityCreature;
|
import fr.themode.minestom.entity.EntityCreature;
|
||||||
import fr.themode.minestom.entity.ObjectEntity;
|
import fr.themode.minestom.entity.ObjectEntity;
|
||||||
import fr.themode.minestom.entity.Player;
|
import fr.themode.minestom.entity.Player;
|
||||||
import fr.themode.minestom.event.BlockBreakEvent;
|
import fr.themode.minestom.event.BlockBreakEvent;
|
||||||
|
import fr.themode.minestom.net.PacketWriter;
|
||||||
import fr.themode.minestom.net.packet.server.play.ChunkDataPacket;
|
import fr.themode.minestom.net.packet.server.play.ChunkDataPacket;
|
||||||
import fr.themode.minestom.net.packet.server.play.DestroyEntitiesPacket;
|
import fr.themode.minestom.net.packet.server.play.DestroyEntitiesPacket;
|
||||||
import fr.themode.minestom.net.packet.server.play.ParticlePacket;
|
import fr.themode.minestom.net.packet.server.play.ParticlePacket;
|
||||||
@ -39,7 +41,10 @@ public class Instance implements BlockModifier {
|
|||||||
Chunk chunk = getChunkAt(x, z);
|
Chunk chunk = getChunkAt(x, z);
|
||||||
synchronized (chunk) {
|
synchronized (chunk) {
|
||||||
chunk.setBlock((byte) (x % 16), (byte) y, (byte) (z % 16), blockId);
|
chunk.setBlock((byte) (x % 16), (byte) y, (byte) (z % 16), blockId);
|
||||||
sendChunkUpdate(chunk);
|
PacketWriter.writeCallbackPacket(chunk.getFreshFullDataPacket(), buffer -> {
|
||||||
|
chunk.setFullDataPacket(buffer);
|
||||||
|
sendChunkUpdate(chunk);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -48,7 +53,10 @@ public class Instance implements BlockModifier {
|
|||||||
Chunk chunk = getChunkAt(x, z);
|
Chunk chunk = getChunkAt(x, z);
|
||||||
synchronized (chunk) {
|
synchronized (chunk) {
|
||||||
chunk.setBlock((byte) (x % 16), (byte) y, (byte) (z % 16), blockId);
|
chunk.setBlock((byte) (x % 16), (byte) y, (byte) (z % 16), blockId);
|
||||||
sendChunkUpdate(chunk);
|
PacketWriter.writeCallbackPacket(chunk.getFreshFullDataPacket(), buffer -> {
|
||||||
|
chunk.setFullDataPacket(buffer);
|
||||||
|
sendChunkUpdate(chunk);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -56,6 +64,7 @@ public class Instance implements BlockModifier {
|
|||||||
BlockBreakEvent blockBreakEvent = new BlockBreakEvent(blockPosition);
|
BlockBreakEvent blockBreakEvent = new BlockBreakEvent(blockPosition);
|
||||||
player.callEvent(BlockBreakEvent.class, blockBreakEvent);
|
player.callEvent(BlockBreakEvent.class, blockBreakEvent);
|
||||||
if (!blockBreakEvent.isCancelled()) {
|
if (!blockBreakEvent.isCancelled()) {
|
||||||
|
// TODO blockbreak setBlock result
|
||||||
int x = blockPosition.getX();
|
int x = blockPosition.getX();
|
||||||
int y = blockPosition.getY();
|
int y = blockPosition.getY();
|
||||||
int z = blockPosition.getZ();
|
int z = blockPosition.getZ();
|
||||||
@ -67,7 +76,7 @@ public class Instance implements BlockModifier {
|
|||||||
particlePacket.y = y;
|
particlePacket.y = y;
|
||||||
particlePacket.z = z + 0.5f;
|
particlePacket.z = z + 0.5f;
|
||||||
particlePacket.offsetX = 0.4f;
|
particlePacket.offsetX = 0.4f;
|
||||||
particlePacket.offsetY = 0.65f;
|
particlePacket.offsetY = 0.6f;
|
||||||
particlePacket.offsetZ = 0.4f;
|
particlePacket.offsetZ = 0.4f;
|
||||||
particlePacket.particleData = 0.3f;
|
particlePacket.particleData = 0.3f;
|
||||||
particlePacket.particleCount = 75;
|
particlePacket.particleCount = 75;
|
||||||
@ -221,18 +230,29 @@ public class Instance implements BlockModifier {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected void sendChunkUpdate(Chunk chunk) {
|
protected void sendChunkUpdate(Chunk chunk) {
|
||||||
ChunkDataPacket chunkDataPacket = new ChunkDataPacket();
|
Buffer chunkData = chunk.getFullDataPacket();
|
||||||
chunkDataPacket.fullChunk = false;
|
chunkData.getData().retain(getPlayers().size()).markReaderIndex();
|
||||||
chunkDataPacket.chunk = chunk;
|
getPlayers().forEach(player -> {
|
||||||
getPlayers().forEach(player -> player.getPlayerConnection().sendPacket(chunkDataPacket)); // TODO write packet buffer in another thread (Chunk packets are heavy)
|
player.getPlayerConnection().sendUnencodedPacket(chunkData);
|
||||||
|
chunkData.getData().resetReaderIndex();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void sendChunks(Player player) {
|
private void sendChunks(Player player) {
|
||||||
ChunkDataPacket chunkDataPacket = new ChunkDataPacket();
|
|
||||||
chunkDataPacket.fullChunk = true;
|
|
||||||
for (Chunk chunk : getChunks()) {
|
for (Chunk chunk : getChunks()) {
|
||||||
chunkDataPacket.chunk = chunk;
|
Buffer chunkData = chunk.getFullDataPacket();
|
||||||
player.getPlayerConnection().sendPacket(chunkDataPacket); // TODO write packet buffer in another thread (Chunk packets are heavy)
|
if (chunkData == null) {
|
||||||
|
PacketWriter.writeCallbackPacket(chunk.getFreshFullDataPacket(), buffer -> {
|
||||||
|
buffer.getData().retain(1).markReaderIndex();
|
||||||
|
player.getPlayerConnection().sendUnencodedPacket(buffer);
|
||||||
|
buffer.getData().resetReaderIndex();
|
||||||
|
chunk.setFullDataPacket(buffer);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
chunkData.getData().retain(1).markReaderIndex();
|
||||||
|
player.getPlayerConnection().sendUnencodedPacket(chunkData);
|
||||||
|
chunkData.getData().resetReaderIndex();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -14,10 +14,8 @@ public class ChunkGeneratorDemo extends ChunkGenerator {
|
|||||||
public void generateChunkData(ChunkBatch batch, int chunkX, int chunkZ) {
|
public void generateChunkData(ChunkBatch batch, int chunkX, int chunkZ) {
|
||||||
for (byte x = 0; x < 16; x++)
|
for (byte x = 0; x < 16; x++)
|
||||||
for (byte z = 0; z < 16; z++) {
|
for (byte z = 0; z < 16; z++) {
|
||||||
if (random.nextInt(10) > 5) {
|
for (byte y = 0; y < 65; y++) {
|
||||||
batch.setBlock(x, (byte) 4, z, (short) 10);
|
batch.setBlock(x, y, z, "custom_block");
|
||||||
} else {
|
|
||||||
batch.setBlock(x, (byte) 4, z, "custom_block");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,7 @@ import fr.themode.minestom.net.packet.client.play.ClientChatMessagePacket;
|
|||||||
public class ChatMessageListener {
|
public class ChatMessageListener {
|
||||||
|
|
||||||
public static void listener(ClientChatMessagePacket packet, Player player) {
|
public static void listener(ClientChatMessagePacket packet, Player player) {
|
||||||
|
// TODO commands check
|
||||||
Main.getConnectionManager().getOnlinePlayers().forEach(p -> p.sendMessage(String.format("<%s> %s", player.getUsername(), packet.message)));
|
Main.getConnectionManager().getOnlinePlayers().forEach(p -> p.sendMessage(String.format("<%s> %s", player.getUsername(), packet.message)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -44,14 +44,15 @@ public class PacketProcessor {
|
|||||||
|
|
||||||
public void process(Connection connection, Packet packet) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
|
public void process(Connection connection, Packet packet) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
|
||||||
int id = packet.get(PACKET_ID_IDENTIFIER);
|
int id = packet.get(PACKET_ID_IDENTIFIER);
|
||||||
if (!printBlackList.contains(id)) {
|
|
||||||
//System.out.println("RECEIVED ID: 0x" + Integer.toHexString(id));
|
|
||||||
}
|
|
||||||
Buffer buffer = packet.getPayload();
|
Buffer buffer = packet.getPayload();
|
||||||
connectionPlayerConnectionMap.get(connection);
|
connectionPlayerConnectionMap.get(connection);
|
||||||
PlayerConnection playerConnection = connectionPlayerConnectionMap.computeIfAbsent(connection, c -> new PlayerConnection(c));
|
PlayerConnection playerConnection = connectionPlayerConnectionMap.computeIfAbsent(connection, c -> new PlayerConnection(c));
|
||||||
ConnectionState connectionState = playerConnection.getConnectionState();
|
ConnectionState connectionState = playerConnection.getConnectionState();
|
||||||
|
|
||||||
|
if (!printBlackList.contains(id)) {
|
||||||
|
System.out.println("RECEIVED ID: 0x" + Integer.toHexString(id) + " State: " + connectionState);
|
||||||
|
}
|
||||||
|
|
||||||
if (connectionState == ConnectionState.UNKNOWN) {
|
if (connectionState == ConnectionState.UNKNOWN) {
|
||||||
// Should be handshake packet
|
// Should be handshake packet
|
||||||
if (id == 0) {
|
if (id == 0) {
|
||||||
|
24
src/main/java/fr/themode/minestom/net/PacketWriter.java
Normal file
24
src/main/java/fr/themode/minestom/net/PacketWriter.java
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
package fr.themode.minestom.net;
|
||||||
|
|
||||||
|
import fr.adamaq01.ozao.net.Buffer;
|
||||||
|
import fr.adamaq01.ozao.net.packet.Packet;
|
||||||
|
import fr.themode.minestom.Main;
|
||||||
|
import fr.themode.minestom.net.packet.server.ServerPacket;
|
||||||
|
import fr.themode.minestom.utils.PacketUtils;
|
||||||
|
|
||||||
|
import java.util.concurrent.ExecutorService;
|
||||||
|
import java.util.concurrent.Executors;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
|
public class PacketWriter {
|
||||||
|
|
||||||
|
private static volatile ExecutorService batchesPool = Executors.newFixedThreadPool(Main.THREAD_COUNT_PACKET_WRITER);
|
||||||
|
|
||||||
|
public static void writeCallbackPacket(ServerPacket serverPacket, Consumer<Buffer> consumer) {
|
||||||
|
batchesPool.submit(() -> {
|
||||||
|
Packet p = PacketUtils.writePacket(serverPacket);
|
||||||
|
consumer.accept(PacketUtils.encode(p));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -9,6 +9,7 @@ import fr.themode.minestom.entity.GameMode;
|
|||||||
import fr.themode.minestom.entity.ItemEntity;
|
import fr.themode.minestom.entity.ItemEntity;
|
||||||
import fr.themode.minestom.entity.Player;
|
import fr.themode.minestom.entity.Player;
|
||||||
import fr.themode.minestom.entity.demo.ChickenCreature;
|
import fr.themode.minestom.entity.demo.ChickenCreature;
|
||||||
|
import fr.themode.minestom.entity.demo.TestArrow;
|
||||||
import fr.themode.minestom.instance.Instance;
|
import fr.themode.minestom.instance.Instance;
|
||||||
import fr.themode.minestom.instance.demo.ChunkGeneratorDemo;
|
import fr.themode.minestom.instance.demo.ChunkGeneratorDemo;
|
||||||
import fr.themode.minestom.inventory.PlayerInventory;
|
import fr.themode.minestom.inventory.PlayerInventory;
|
||||||
@ -19,6 +20,7 @@ import fr.themode.minestom.net.ConnectionState;
|
|||||||
import fr.themode.minestom.net.packet.client.ClientPreplayPacket;
|
import fr.themode.minestom.net.packet.client.ClientPreplayPacket;
|
||||||
import fr.themode.minestom.net.packet.server.login.JoinGamePacket;
|
import fr.themode.minestom.net.packet.server.login.JoinGamePacket;
|
||||||
import fr.themode.minestom.net.packet.server.login.LoginSuccessPacket;
|
import fr.themode.minestom.net.packet.server.login.LoginSuccessPacket;
|
||||||
|
import fr.themode.minestom.net.packet.server.play.DeclareCommandsPacket;
|
||||||
import fr.themode.minestom.net.packet.server.play.PlayerInfoPacket;
|
import fr.themode.minestom.net.packet.server.play.PlayerInfoPacket;
|
||||||
import fr.themode.minestom.net.packet.server.play.PlayerPositionAndLookPacket;
|
import fr.themode.minestom.net.packet.server.play.PlayerPositionAndLookPacket;
|
||||||
import fr.themode.minestom.net.packet.server.play.SpawnPositionPacket;
|
import fr.themode.minestom.net.packet.server.play.SpawnPositionPacket;
|
||||||
@ -31,6 +33,9 @@ import java.util.UUID;
|
|||||||
|
|
||||||
public class LoginStartPacket implements ClientPreplayPacket {
|
public class LoginStartPacket implements ClientPreplayPacket {
|
||||||
|
|
||||||
|
// Test
|
||||||
|
private static Instance instance;
|
||||||
|
|
||||||
static {
|
static {
|
||||||
ChunkGeneratorDemo chunkGeneratorDemo = new ChunkGeneratorDemo();
|
ChunkGeneratorDemo chunkGeneratorDemo = new ChunkGeneratorDemo();
|
||||||
instance = Main.getInstanceManager().createInstance();
|
instance = Main.getInstanceManager().createInstance();
|
||||||
@ -45,9 +50,6 @@ public class LoginStartPacket implements ClientPreplayPacket {
|
|||||||
System.out.println("Time to load all chunks: " + (System.currentTimeMillis() - time) + " ms");
|
System.out.println("Time to load all chunks: " + (System.currentTimeMillis() - time) + " ms");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test
|
|
||||||
private static Instance instance;
|
|
||||||
|
|
||||||
public String username;
|
public String username;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -72,7 +74,7 @@ public class LoginStartPacket implements ClientPreplayPacket {
|
|||||||
Dimension dimension = Dimension.OVERWORLD;
|
Dimension dimension = Dimension.OVERWORLD;
|
||||||
LevelType levelType = LevelType.DEFAULT;
|
LevelType levelType = LevelType.DEFAULT;
|
||||||
float x = 5;
|
float x = 5;
|
||||||
float y = 5;
|
float y = 65;
|
||||||
float z = 5;
|
float z = 5;
|
||||||
|
|
||||||
player.refreshDimension(dimension);
|
player.refreshDimension(dimension);
|
||||||
@ -117,12 +119,15 @@ public class LoginStartPacket implements ClientPreplayPacket {
|
|||||||
playerInfoPacket.playerInfos.add(addPlayer);
|
playerInfoPacket.playerInfos.add(addPlayer);
|
||||||
connection.sendPacket(playerInfoPacket);
|
connection.sendPacket(playerInfoPacket);
|
||||||
|
|
||||||
|
// Next is optional TODO put all that somewhere else (LoginEvent)
|
||||||
|
// TODO LoginEvent in another thread (here we are in netty thread)
|
||||||
|
|
||||||
player.setInstance(instance);
|
player.setInstance(instance);
|
||||||
|
|
||||||
for (int cx = 0; cx < 4; cx++)
|
for (int cx = 0; cx < 4; cx++)
|
||||||
for (int cz = 0; cz < 4; cz++) {
|
for (int cz = 0; cz < 4; cz++) {
|
||||||
ChickenCreature chickenCreature = new ChickenCreature();
|
ChickenCreature chickenCreature = new ChickenCreature();
|
||||||
chickenCreature.refreshPosition(0 + (float) cx * 1, 5, 0 + (float) cz * 1);
|
chickenCreature.refreshPosition(0 + (float) cx * 1, 65, 0 + (float) cz * 1);
|
||||||
//chickenCreature.setOnFire(true);
|
//chickenCreature.setOnFire(true);
|
||||||
chickenCreature.setInstance(instance);
|
chickenCreature.setInstance(instance);
|
||||||
//chickenCreature.addPassenger(player);
|
//chickenCreature.addPassenger(player);
|
||||||
@ -144,10 +149,36 @@ public class LoginStartPacket implements ClientPreplayPacket {
|
|||||||
for (int ix = 0; ix < 4; ix++)
|
for (int ix = 0; ix < 4; ix++)
|
||||||
for (int iz = 0; iz < 4; iz++) {
|
for (int iz = 0; iz < 4; iz++) {
|
||||||
ItemEntity itemEntity = new ItemEntity(new ItemStack(1, (byte) 32));
|
ItemEntity itemEntity = new ItemEntity(new ItemStack(1, (byte) 32));
|
||||||
itemEntity.refreshPosition(ix, 5, iz);
|
itemEntity.refreshPosition(ix, 66, iz);
|
||||||
|
itemEntity.setNoGravity(true);
|
||||||
itemEntity.setInstance(instance);
|
itemEntity.setInstance(instance);
|
||||||
//itemEntity.remove();
|
//itemEntity.remove();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TestArrow arrow = new TestArrow(player);
|
||||||
|
arrow.refreshPosition(5, 65, 5);
|
||||||
|
arrow.setInstance(instance);
|
||||||
|
arrow.setNoGravity(true);
|
||||||
|
|
||||||
|
DeclareCommandsPacket declareCommandsPacket = new DeclareCommandsPacket();
|
||||||
|
DeclareCommandsPacket.Node argumentNode = new DeclareCommandsPacket.Node();
|
||||||
|
argumentNode.flags = 0b1010;
|
||||||
|
argumentNode.children = new int[0];
|
||||||
|
argumentNode.name = "arg name";
|
||||||
|
argumentNode.parser = "minecraft:nbt_path";
|
||||||
|
DeclareCommandsPacket.Node literalNode = new DeclareCommandsPacket.Node();
|
||||||
|
literalNode.flags = 0b1;
|
||||||
|
literalNode.children = new int[]{2};
|
||||||
|
literalNode.name = "hey";
|
||||||
|
DeclareCommandsPacket.Node rootNode = new DeclareCommandsPacket.Node();
|
||||||
|
rootNode.flags = 0;
|
||||||
|
rootNode.children = new int[]{1};
|
||||||
|
|
||||||
|
declareCommandsPacket.nodes = new DeclareCommandsPacket.Node[]{rootNode, literalNode, argumentNode};
|
||||||
|
declareCommandsPacket.rootIndex = 0;
|
||||||
|
|
||||||
|
|
||||||
|
connection.sendPacket(declareCommandsPacket);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -0,0 +1,77 @@
|
|||||||
|
package fr.themode.minestom.net.packet.server.play;
|
||||||
|
|
||||||
|
import fr.adamaq01.ozao.net.Buffer;
|
||||||
|
import fr.themode.minestom.net.packet.server.ServerPacket;
|
||||||
|
import fr.themode.minestom.utils.Utils;
|
||||||
|
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
|
public class DeclareCommandsPacket implements ServerPacket {
|
||||||
|
|
||||||
|
|
||||||
|
public Node[] nodes;
|
||||||
|
public int rootIndex;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void write(Buffer buffer) {
|
||||||
|
Utils.writeVarInt(buffer, nodes.length);
|
||||||
|
for (Node node : nodes) {
|
||||||
|
node.write(buffer);
|
||||||
|
}
|
||||||
|
Utils.writeVarInt(buffer, rootIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getId() {
|
||||||
|
return 0x11;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Node {
|
||||||
|
|
||||||
|
public byte flags;
|
||||||
|
public int[] children;
|
||||||
|
public int redirectedNode; // Only if flags & 0x08
|
||||||
|
public String name; // Only for literal and argument
|
||||||
|
public String parser; // Only for argument
|
||||||
|
public Consumer<Buffer> properties; // Only for argument
|
||||||
|
public String suggestionsType; // Only if flags 0x10
|
||||||
|
|
||||||
|
private void write(Buffer buffer) {
|
||||||
|
buffer.putByte(flags);
|
||||||
|
Utils.writeVarInt(buffer, children.length);
|
||||||
|
for (int child : children) {
|
||||||
|
Utils.writeVarInt(buffer, child);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((flags & 0x08) != 0) {
|
||||||
|
Utils.writeVarInt(buffer, redirectedNode);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isLiteral() || isArgument()) {
|
||||||
|
Utils.writeString(buffer, name);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isArgument()) {
|
||||||
|
Utils.writeString(buffer, parser);
|
||||||
|
if (properties != null) {
|
||||||
|
properties.accept(buffer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((flags & 0x10) != 0) {
|
||||||
|
Utils.writeString(buffer, suggestionsType);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isLiteral() {
|
||||||
|
return (flags & 0b1) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isArgument() {
|
||||||
|
return (flags & 0b10) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,10 +1,14 @@
|
|||||||
package fr.themode.minestom.net.player;
|
package fr.themode.minestom.net.player;
|
||||||
|
|
||||||
|
import fr.adamaq01.ozao.net.Buffer;
|
||||||
import fr.adamaq01.ozao.net.packet.Packet;
|
import fr.adamaq01.ozao.net.packet.Packet;
|
||||||
import fr.adamaq01.ozao.net.server.Connection;
|
import fr.adamaq01.ozao.net.server.Connection;
|
||||||
import fr.themode.minestom.net.ConnectionState;
|
import fr.themode.minestom.net.ConnectionState;
|
||||||
import fr.themode.minestom.net.packet.server.ServerPacket;
|
import fr.themode.minestom.net.packet.server.ServerPacket;
|
||||||
import fr.themode.minestom.utils.PacketUtils;
|
import fr.themode.minestom.utils.PacketUtils;
|
||||||
|
import io.netty.channel.socket.SocketChannel;
|
||||||
|
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
|
||||||
public class PlayerConnection {
|
public class PlayerConnection {
|
||||||
|
|
||||||
@ -20,6 +24,30 @@ public class PlayerConnection {
|
|||||||
this.connection.sendPacket(packet);
|
this.connection.sendPacket(packet);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// TODO make that proper (remove reflection)
|
||||||
|
private Field field;
|
||||||
|
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
field = Class.forName("fr.adamaq01.ozao.net.server.backend.tcp.TCPConnection").getDeclaredField("channel");
|
||||||
|
} catch (NoSuchFieldException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} catch (ClassNotFoundException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
field.setAccessible(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void sendUnencodedPacket(Buffer packet) {
|
||||||
|
try {
|
||||||
|
SocketChannel channel = ((SocketChannel) field.get(connection));
|
||||||
|
channel.writeAndFlush(packet.getData());
|
||||||
|
} catch (IllegalAccessException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void sendPacket(ServerPacket serverPacket) {
|
public void sendPacket(ServerPacket serverPacket) {
|
||||||
sendPacket(PacketUtils.writePacket(serverPacket));
|
sendPacket(PacketUtils.writePacket(serverPacket));
|
||||||
}
|
}
|
||||||
|
@ -3,12 +3,12 @@ package fr.themode.minestom.net.protocol;
|
|||||||
import fr.adamaq01.ozao.net.Buffer;
|
import fr.adamaq01.ozao.net.Buffer;
|
||||||
import fr.adamaq01.ozao.net.packet.Packet;
|
import fr.adamaq01.ozao.net.packet.Packet;
|
||||||
import fr.adamaq01.ozao.net.protocol.Protocol;
|
import fr.adamaq01.ozao.net.protocol.Protocol;
|
||||||
|
import fr.themode.minestom.utils.PacketUtils;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
|
||||||
import static fr.themode.minestom.utils.Utils.readVarInt;
|
import static fr.themode.minestom.utils.Utils.readVarInt;
|
||||||
import static fr.themode.minestom.utils.Utils.writeVarInt;
|
|
||||||
|
|
||||||
public class MinecraftProtocol extends Protocol {
|
public class MinecraftProtocol extends Protocol {
|
||||||
|
|
||||||
@ -29,7 +29,7 @@ public class MinecraftProtocol extends Protocol {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean verify(Packet packet) {
|
public boolean verify(Packet packet) {
|
||||||
return packet.get("id") != null;
|
return PacketUtils.verify(packet);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -56,12 +56,6 @@ public class MinecraftProtocol extends Protocol {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Buffer encode(Packet packet) {
|
public Buffer encode(Packet packet) {
|
||||||
Buffer buffer = Buffer.create();
|
return PacketUtils.encode(packet);
|
||||||
Buffer idAndPayload = Buffer.create();
|
|
||||||
writeVarInt(idAndPayload, packet.get(PACKET_ID_IDENTIFIER));
|
|
||||||
idAndPayload.putBuffer(packet.getPayload());
|
|
||||||
writeVarInt(buffer, idAndPayload.length());
|
|
||||||
buffer.putBuffer(idAndPayload);
|
|
||||||
return buffer;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -43,6 +43,6 @@ public class BlockPosition {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "Position[" + x + ":" + y + ":" + z + "]";
|
return "BlockPosition[" + x + ":" + y + ":" + z + "]";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,7 @@ import fr.adamaq01.ozao.net.packet.Packet;
|
|||||||
import fr.themode.minestom.net.packet.server.ServerPacket;
|
import fr.themode.minestom.net.packet.server.ServerPacket;
|
||||||
|
|
||||||
import static fr.themode.minestom.net.protocol.MinecraftProtocol.PACKET_ID_IDENTIFIER;
|
import static fr.themode.minestom.net.protocol.MinecraftProtocol.PACKET_ID_IDENTIFIER;
|
||||||
|
import static fr.themode.minestom.utils.Utils.writeVarInt;
|
||||||
|
|
||||||
public class PacketUtils {
|
public class PacketUtils {
|
||||||
|
|
||||||
@ -13,10 +14,22 @@ public class PacketUtils {
|
|||||||
Packet packet = Packet.create();
|
Packet packet = Packet.create();
|
||||||
Buffer buffer = packet.getPayload();
|
Buffer buffer = packet.getPayload();
|
||||||
serverPacket.write(buffer);
|
serverPacket.write(buffer);
|
||||||
/*if (id != 40 && id != 64)
|
|
||||||
System.out.println("ID: 0x" + Integer.toHexString(id));*/
|
|
||||||
packet.put(PACKET_ID_IDENTIFIER, id);
|
packet.put(PACKET_ID_IDENTIFIER, id);
|
||||||
return packet;
|
return packet;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static boolean verify(Packet packet) {
|
||||||
|
return packet.get("id") != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Buffer encode(Packet packet) {
|
||||||
|
Buffer buffer = Buffer.create();
|
||||||
|
Buffer idAndPayload = Buffer.create();
|
||||||
|
writeVarInt(idAndPayload, packet.get(PACKET_ID_IDENTIFIER));
|
||||||
|
idAndPayload.putBuffer(packet.getPayload());
|
||||||
|
writeVarInt(buffer, idAndPayload.length());
|
||||||
|
buffer.putBuffer(idAndPayload);
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -21,10 +21,20 @@ public class Position {
|
|||||||
this(0, 0, 0);
|
this(0, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void add(float x, float y, float z) {
|
||||||
|
this.x += x;
|
||||||
|
this.y += y;
|
||||||
|
this.z += z;
|
||||||
|
}
|
||||||
|
|
||||||
public float getDistance(Position position) {
|
public float getDistance(Position position) {
|
||||||
return (float) Math.sqrt(Math.pow(position.getX() - getX(), 2) + Math.pow(position.getY() - getY(), 2) + Math.pow(position.getZ() - getZ(), 2));
|
return (float) Math.sqrt(Math.pow(position.getX() - getX(), 2) + Math.pow(position.getY() - getY(), 2) + Math.pow(position.getZ() - getZ(), 2));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Position clone() {
|
||||||
|
return new Position(getX(), getY(), getZ(), getYaw(), getPitch());
|
||||||
|
}
|
||||||
|
|
||||||
public float getX() {
|
public float getX() {
|
||||||
return x;
|
return x;
|
||||||
}
|
}
|
||||||
@ -64,4 +74,9 @@ public class Position {
|
|||||||
public void setPitch(float pitch) {
|
public void setPitch(float pitch) {
|
||||||
this.pitch = pitch;
|
this.pitch = pitch;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "Position[" + x + ":" + y + ":" + z + "] (" + yaw + "/" + pitch + ")";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user