Merged in dmitriymx/location-refactory (pull request #5)
Dmitriymx/location refactory
This commit is contained in:
@@ -35,8 +35,9 @@ subprojects {
|
||||
|
||||
/* Components */
|
||||
compile (group: 'org.projectlombok', name: 'lombok', version: '1.16.16')
|
||||
compile 'com.flowpowered:flow-nbt:1.0.0' //Named Binary Tags
|
||||
testCompile 'junit:junit:4.12'
|
||||
|
||||
/* Test */
|
||||
testCompile (group: 'junit', name: 'junit', version: '4.12')
|
||||
}
|
||||
|
||||
task copyDep(type: Copy) {
|
||||
|
||||
34
core/src/main/java/mc/core/EntityLocation.java
Normal file
34
core/src/main/java/mc/core/EntityLocation.java
Normal file
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* DmitriyMX <dimon550@gmail.com>
|
||||
* 2018-08-08
|
||||
*/
|
||||
package mc.core;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import mc.core.world.World;
|
||||
|
||||
public class EntityLocation extends Location implements Cloneable {
|
||||
@Getter
|
||||
@Setter
|
||||
private float yaw, pitch;
|
||||
|
||||
public EntityLocation(double x, double y, double z, float yaw, float pitch, World world) {
|
||||
super(x, y, z, world);
|
||||
setYawPitch(yaw, pitch);
|
||||
}
|
||||
|
||||
public void setYawPitch(float yaw, float pitch) {
|
||||
this.yaw = yaw;
|
||||
this.pitch = pitch;
|
||||
}
|
||||
|
||||
public void setYawPitch(EntityLocation entityLocation) {
|
||||
setYawPitch(entityLocation.yaw, entityLocation.pitch);
|
||||
}
|
||||
|
||||
@Override
|
||||
public EntityLocation clone() {
|
||||
return (EntityLocation) super.clone();
|
||||
}
|
||||
}
|
||||
@@ -1,12 +1,12 @@
|
||||
/*
|
||||
* DmitriyMX <dimon550@gmail.com>
|
||||
* 2018-04-15
|
||||
* 2018-08-08
|
||||
*/
|
||||
package mc.core;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import mc.core.exception.ResourceUnloadedException;
|
||||
import mc.core.world.Region;
|
||||
import mc.core.world.World;
|
||||
import mc.core.world.chunk.Chunk;
|
||||
|
||||
@@ -14,77 +14,39 @@ import java.io.Serializable;
|
||||
import java.lang.ref.Reference;
|
||||
import java.lang.ref.WeakReference;
|
||||
|
||||
@Data
|
||||
public class Location implements Serializable{
|
||||
public class Location implements Serializable, Cloneable {
|
||||
@Getter
|
||||
@Setter
|
||||
private double x, y, z;
|
||||
private Reference<World> world;
|
||||
|
||||
private static int floor_double(double value) {
|
||||
int i = (int)value;
|
||||
return value < (double)i ? i - 1 : i;
|
||||
}
|
||||
|
||||
public static Location copyOf(Location location) {
|
||||
return new Location(
|
||||
location.x,
|
||||
location.y,
|
||||
location.z,
|
||||
location.getWorld()
|
||||
);
|
||||
}
|
||||
private Reference<World> refWorld;
|
||||
|
||||
public Location (double x, double y, double z, World world) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.z = z;
|
||||
this.world = new WeakReference<>(world);
|
||||
setXYZ(x, y, z);
|
||||
setWorld(world);
|
||||
}
|
||||
|
||||
public Location (double x, double y, double z) {
|
||||
public void setXYZ(double x, double y, double z) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.z = z;
|
||||
}
|
||||
|
||||
public static Location startPointLocation () {
|
||||
return new Location(0,10,0, null);
|
||||
public void setXYZ(Location location) {
|
||||
setXYZ(location.x, location.y, location.z);
|
||||
}
|
||||
|
||||
public Location(long compactValue) {
|
||||
set(compactValue);
|
||||
this.world = new WeakReference<>(null);
|
||||
public World getWorld() {
|
||||
if (refWorld == null) {
|
||||
return null;
|
||||
} else if (refWorld.get() == null) {
|
||||
throw new ResourceUnloadedException("You're trying to get unloaded world");
|
||||
} else {
|
||||
return refWorld.get();
|
||||
}
|
||||
}
|
||||
|
||||
public Location(long compactValue, World world) {
|
||||
set(compactValue);
|
||||
this.world = new WeakReference<>(world);
|
||||
}
|
||||
|
||||
public void set(double x, double y, double z) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.z = z;
|
||||
}
|
||||
|
||||
public void set(Location location) {
|
||||
this.x = location.x;
|
||||
this.y = location.y;
|
||||
this.z = location.z;
|
||||
}
|
||||
|
||||
public void set(long compactValue) {
|
||||
this.x = compactValue >> 38;
|
||||
this.y = (compactValue >> 26) & 0xFFF;
|
||||
this.z = compactValue << 38 >> 38; // is normal?
|
||||
}
|
||||
|
||||
public Location diff(Location location) {
|
||||
return new Location(
|
||||
this.x - location.x,
|
||||
this.y - location.y,
|
||||
this.z - location.z,
|
||||
this.getWorld().equals(location.getWorld()) ? this.getWorld() : null
|
||||
);
|
||||
public void setWorld (World world) {
|
||||
this.refWorld = new WeakReference<>(world);
|
||||
}
|
||||
|
||||
public int getBlockX() {
|
||||
@@ -99,29 +61,23 @@ public class Location implements Serializable{
|
||||
return (int) z;
|
||||
}
|
||||
|
||||
public long toLong() {
|
||||
return ((floor_double(x) & 0x3FFFFFF) << 38)
|
||||
| ((floor_double(y) & 0xFFF) << 26)
|
||||
| (floor_double(z) & 0x3FFFFFF);
|
||||
public Chunk getChunk() {
|
||||
World world;
|
||||
if ((world = getWorld()) == null) {
|
||||
return null;
|
||||
} else {
|
||||
return world.getRegion((int) (x / 256), (int) (z / 256))
|
||||
.getChunk((int) ((x % 256) / 16), (int) ((z % 256) / 16));
|
||||
}
|
||||
}
|
||||
|
||||
public World getWorld () {
|
||||
if (world == null) {
|
||||
@Override
|
||||
public Location clone() {
|
||||
try {
|
||||
return (Location) super.clone();
|
||||
} catch (CloneNotSupportedException e) { // такое в нашем случае вообще возможно?
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
if (world.get() == null) {
|
||||
throw new ResourceUnloadedException("You're trying to get unloaded world");
|
||||
}
|
||||
return this.world.get();
|
||||
}
|
||||
|
||||
public void setWorld (World world) {
|
||||
this.world = new WeakReference<>(world);
|
||||
}
|
||||
|
||||
public Chunk getChunk() {
|
||||
Region region = getWorld().getRegion((int) (x / 256), (int) (z / 256));
|
||||
return region.getChunk((int) ((x % 256) / 16), (int) ((z % 256) / 16));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
package mc.core;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import mc.core.player.Look;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
public class WarpPosition implements Serializable {
|
||||
private Location location;
|
||||
private Look look;
|
||||
}
|
||||
@@ -4,11 +4,10 @@
|
||||
*/
|
||||
package mc.core.embedded;
|
||||
|
||||
import mc.core.Location;
|
||||
import mc.core.EntityLocation;
|
||||
import mc.core.chat.MessageType;
|
||||
import mc.core.network.NetChannel;
|
||||
import mc.core.network.SCPacket;
|
||||
import mc.core.player.Look;
|
||||
import mc.core.player.Player;
|
||||
import mc.core.player.PlayerManager;
|
||||
import mc.core.text.Text;
|
||||
@@ -52,7 +51,7 @@ public class FakePlayerManager implements PlayerManager {
|
||||
private static final NetChannel FAKE_NET_CHANNEL = new FakeNetChannet();
|
||||
|
||||
@Override
|
||||
public Player createPlayer(String name, Location defaultLocation, Look defaultLook) {
|
||||
public Player createPlayer(String name, EntityLocation defaultLocation) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ package mc.core.events;
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.Setter;
|
||||
import mc.core.player.Look;
|
||||
import mc.core.EntityLocation;
|
||||
import mc.core.player.Player;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
@@ -15,5 +15,5 @@ import mc.core.player.Player;
|
||||
@Setter
|
||||
public class PlayerLookEvent extends EventBase {
|
||||
private final Player player;
|
||||
private Look newLook;
|
||||
private EntityLocation newLook;
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ package mc.core.player;
|
||||
import lombok.Setter;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import mc.core.Config;
|
||||
import mc.core.Location;
|
||||
import mc.core.EntityLocation;
|
||||
import mc.core.network.BroadcastNetChannel;
|
||||
import mc.core.network.NetChannel;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
@@ -31,13 +31,13 @@ public class InMemoryPlayerManager implements PlayerManager, Runnable {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Player createPlayer(String name, Location defaultLocation, Look defaultLook) {
|
||||
public Player createPlayer(String name, EntityLocation defaultLocation) {
|
||||
SimplePlayer player = new SimplePlayer();
|
||||
player.setId(rand.nextInt(10000));
|
||||
player.setUUID(UUID.nameUUIDFromBytes(name.getBytes()));
|
||||
player.setName(name);
|
||||
player.getLocation().set(defaultLocation);
|
||||
player.getLook().set(defaultLook);
|
||||
player.getLocation().setXYZ(defaultLocation);
|
||||
player.getLocation().setYawPitch(defaultLocation);
|
||||
player.setSettings(new PlayerSettings());
|
||||
|
||||
synchronized (lock) {
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
/*
|
||||
* DmitriyMX <dimon550@gmail.com>
|
||||
* 2018-04-22
|
||||
*/
|
||||
package mc.core.player;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
public class Look implements Serializable{
|
||||
private float yaw, pitch;
|
||||
|
||||
public void set(Look look) {
|
||||
this.yaw = look.yaw;
|
||||
this.pitch = look.pitch;
|
||||
}
|
||||
}
|
||||
@@ -4,7 +4,7 @@
|
||||
*/
|
||||
package mc.core.player;
|
||||
|
||||
import mc.core.Location;
|
||||
import mc.core.EntityLocation;
|
||||
import mc.core.network.NetChannel;
|
||||
|
||||
import java.util.UUID;
|
||||
@@ -18,9 +18,7 @@ public interface Player {
|
||||
NetChannel getChannel();
|
||||
void setChannel(NetChannel channel);
|
||||
|
||||
Location getLocation();
|
||||
|
||||
Look getLook();
|
||||
EntityLocation getLocation();
|
||||
|
||||
boolean isFlying();
|
||||
void setFlying(boolean value);
|
||||
|
||||
@@ -4,14 +4,14 @@
|
||||
*/
|
||||
package mc.core.player;
|
||||
|
||||
import mc.core.Location;
|
||||
import mc.core.EntityLocation;
|
||||
import mc.core.network.NetChannel;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
public interface PlayerManager {
|
||||
Player createPlayer(String name, Location defaultLocation, Look defaultLook);
|
||||
Player createPlayer(String name, EntityLocation defaultLocation);
|
||||
void joinServer(Player player);
|
||||
void leftServer(Player player);
|
||||
Optional<Player> getPlayer(String name);
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
package mc.core.player;
|
||||
|
||||
import lombok.Data;
|
||||
import mc.core.Location;
|
||||
import mc.core.EntityLocation;
|
||||
import mc.core.network.NetChannel;
|
||||
|
||||
import java.util.UUID;
|
||||
@@ -17,17 +17,13 @@ public class SimplePlayer implements Player {
|
||||
private String name;
|
||||
private boolean online = false;
|
||||
private NetChannel channel;
|
||||
private Location location = new Location(0, 0, 0);
|
||||
private Look look = new Look(0, 0);
|
||||
private EntityLocation location = new EntityLocation(0d, 0d, 0d, 0f, 0f, null);
|
||||
private boolean flying = false;
|
||||
private PlayerSettings settings;
|
||||
|
||||
public void setLocation(Location location) {
|
||||
this.location.set(location);
|
||||
}
|
||||
|
||||
public void setLook(Look look) {
|
||||
this.look.set(look);
|
||||
public void setLocation(EntityLocation location) {
|
||||
this.location.setXYZ(location);
|
||||
this.location.setYawPitch(location);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
*/
|
||||
package mc.core.world;
|
||||
|
||||
import mc.core.WarpPosition;
|
||||
import mc.core.EntityLocation;
|
||||
import mc.core.nbt.Taggable;
|
||||
|
||||
import java.io.Serializable;
|
||||
@@ -45,8 +45,8 @@ public interface World extends Taggable, Serializable{
|
||||
UUID getWorldId();
|
||||
IWorldType getWorldType();
|
||||
|
||||
WarpPosition getSpawn();
|
||||
void setSpawn(WarpPosition location);
|
||||
EntityLocation getSpawn();
|
||||
void setSpawn(EntityLocation location);
|
||||
|
||||
ChunkSection getChunk(int x, int y, int z);
|
||||
void setChunk(int x, int y, int z, ChunkSection chunkSection);
|
||||
|
||||
@@ -22,7 +22,7 @@ public class BlockFactory {
|
||||
private class EmbeddedBlock extends AbstractBlock {
|
||||
EmbeddedBlock(BlockType type, int meta, int x, int y, int z) {
|
||||
super(type, meta);
|
||||
super.setLocation(new Location(x,y,z));
|
||||
super.setLocation(new Location(x,y,z, null));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
100
core/src/test/java/mc/core/EntityLocationTest.java
Normal file
100
core/src/test/java/mc/core/EntityLocationTest.java
Normal file
@@ -0,0 +1,100 @@
|
||||
package mc.core;
|
||||
|
||||
import com.flowpowered.nbt.Tag;
|
||||
import mc.core.world.ChunkSection;
|
||||
import mc.core.world.IWorldType;
|
||||
import mc.core.world.Region;
|
||||
import mc.core.world.World;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.UUID;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
public class EntityLocationTest {
|
||||
@Test
|
||||
public void cloneTest() {
|
||||
World dummyWorld = new World() {
|
||||
@Override
|
||||
public UUID getWorldId() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IWorldType getWorldType() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public EntityLocation getSpawn() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSpawn(EntityLocation location) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChunkSection getChunk(int x, int y, int z) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setChunk(int x, int y, int z, ChunkSection chunkSection) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public Region getRegion(int x, int z) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setRegion(int x, int z, Region region) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSeed() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setName(String name) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public Tag<?> getTag(String name) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTag(Tag<?> tag) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public Stream<Tag<?>> tagStream() {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
EntityLocation firstLocation = new EntityLocation(10, 20, 30, 40, 50, dummyWorld);
|
||||
Assert.assertSame("Lost world reference before cloning", dummyWorld, firstLocation.getWorld());
|
||||
EntityLocation locationClone = firstLocation.clone();
|
||||
|
||||
Assert.assertEquals("X mismatch", firstLocation.getX(), locationClone.getX(), 0);
|
||||
Assert.assertEquals("Y mismatch", firstLocation.getY(), locationClone.getY(), 0);
|
||||
Assert.assertEquals("Z mismatch", firstLocation.getZ(), locationClone.getZ(), 0);
|
||||
Assert.assertEquals("Pitch mismatch", firstLocation.getPitch(), locationClone.getPitch(), 0);
|
||||
Assert.assertEquals("Yaw mismatch", firstLocation.getYaw(), locationClone.getYaw(), 0);
|
||||
Assert.assertSame("World mismatch (accidental clone of the World object?)", firstLocation.getWorld(), locationClone.getWorld());
|
||||
}
|
||||
}
|
||||
@@ -7,9 +7,7 @@ package mc.world.flat;
|
||||
import com.flowpowered.nbt.Tag;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import mc.core.Location;
|
||||
import mc.core.WarpPosition;
|
||||
import mc.core.player.Look;
|
||||
import mc.core.EntityLocation;
|
||||
import mc.core.world.*;
|
||||
|
||||
import java.util.UUID;
|
||||
@@ -26,7 +24,7 @@ public class FlatWorld implements World {
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
private WarpPosition spawn = new WarpPosition(new Location(0, 6, 0), new Look(0, 0));
|
||||
private EntityLocation spawn = new EntityLocation(0d, 6d, 0d, 0f, 0f, this);
|
||||
private ChunkSection chunkSection = new SimpleChunkSection();
|
||||
|
||||
@Override
|
||||
|
||||
@@ -2,7 +2,7 @@ package mc.world.generated_world.serialization;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import mc.core.WarpPosition;
|
||||
import mc.core.EntityLocation;
|
||||
import mc.core.world.World;
|
||||
import mc.world.generated_world.world.CubicWorld;
|
||||
|
||||
@@ -55,7 +55,7 @@ public class WorldReaderWriter {
|
||||
|
||||
@Data
|
||||
public static class WorldInfo implements Serializable {
|
||||
private WarpPosition spawn;
|
||||
private EntityLocation spawn;
|
||||
private String name;
|
||||
private int seed;
|
||||
}
|
||||
|
||||
@@ -5,16 +5,8 @@ import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import mc.core.Direction;
|
||||
import mc.core.Location;
|
||||
import mc.core.WarpPosition;
|
||||
import mc.core.player.Look;
|
||||
import mc.core.world.ChunkSection;
|
||||
import mc.core.world.IWorldType;
|
||||
import mc.core.world.Region;
|
||||
import mc.core.world.World;
|
||||
import mc.core.world.WorldGenerator;
|
||||
import mc.core.world.block.BlockType;
|
||||
import mc.core.world.chunk.Chunk;
|
||||
import mc.core.EntityLocation;
|
||||
import mc.core.world.*;
|
||||
import mc.world.generated_world.serialization.RegionReaderWriter;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
@@ -28,7 +20,7 @@ import java.util.concurrent.locks.Lock;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import static mc.world.generated_world.WorldConstants.*;
|
||||
import static mc.world.generated_world.WorldConstants.REGION_FILE_NAME_TEMPLATE;
|
||||
|
||||
/*
|
||||
* NORTH
|
||||
@@ -61,7 +53,7 @@ public class CubicWorld implements World {
|
||||
@Getter
|
||||
private final UUID worldId;
|
||||
private final int seed;
|
||||
private volatile WarpPosition warpPosition;
|
||||
private volatile EntityLocation spawn;
|
||||
private final transient Object spawnLocationLock = new Object();
|
||||
private final Map<String, Tag<?>> nbtTagMap = new HashMap<>();
|
||||
@Getter@Setter
|
||||
@@ -89,19 +81,24 @@ public class CubicWorld implements World {
|
||||
|
||||
@Override
|
||||
public IWorldType getWorldType() {
|
||||
return null;
|
||||
return null; //FIXME
|
||||
}
|
||||
|
||||
@Override
|
||||
public WarpPosition getSpawn() {
|
||||
public EntityLocation getSpawn() {
|
||||
/* FIXME */
|
||||
return new WarpPosition(new Location(0, 100, 0), new Look(0, 0));
|
||||
if (spawn == null) {
|
||||
log.warn("Spawn is not defined! Set default spawn: [8, 128, 8]");
|
||||
setSpawn(new EntityLocation(8d, 128d, 8d, 0f, 0f, this));
|
||||
}
|
||||
return spawn;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSpawn(WarpPosition warpPosition) {
|
||||
public void setSpawn(EntityLocation entityLocation) {
|
||||
synchronized (spawnLocationLock) {
|
||||
this.warpPosition = warpPosition;
|
||||
entityLocation.setWorld(this);
|
||||
this.spawn = entityLocation;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -113,7 +110,7 @@ public class CubicWorld implements World {
|
||||
|
||||
@Override
|
||||
public void setChunk(int x, int y, int z, ChunkSection chunkSection) {
|
||||
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
package mc.core.network.proto_1_12_2;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import mc.core.Location;
|
||||
import mc.core.EntityLocation;
|
||||
import mc.core.player.Player;
|
||||
|
||||
import java.util.HashMap;
|
||||
@@ -22,7 +22,7 @@ public class TeleportManager {
|
||||
@AllArgsConstructor
|
||||
private class TpData {
|
||||
public Player player;
|
||||
public Location newLocation;
|
||||
public EntityLocation newLocation;
|
||||
// TODO необходимо добавить TimeStamp, что бы понимать, когда клиент отвергнул телепортацию
|
||||
// т.е. идея такова: долгое молчание клиента знак отвержения телепортации.
|
||||
}
|
||||
@@ -32,20 +32,21 @@ public class TeleportManager {
|
||||
|
||||
private TeleportManager() {}
|
||||
|
||||
public int append(Player player, Location location) {
|
||||
public int append(Player player, EntityLocation location) {
|
||||
int teleportId;
|
||||
do {
|
||||
teleportId = RAND.nextInt(9999);
|
||||
} while (teleportMap.containsKey(teleportId));
|
||||
|
||||
teleportMap.put(teleportId, new TpData(player, Location.copyOf(location)));
|
||||
teleportMap.put(teleportId, new TpData(player, location.clone()));
|
||||
return teleportId;
|
||||
}
|
||||
|
||||
public void apply(int teleportId) {
|
||||
if (teleportMap.containsKey(teleportId)) {
|
||||
TpData data = teleportMap.remove(teleportId);
|
||||
data.player.getLocation().set(data.newLocation);
|
||||
data.player.getLocation().setXYZ(data.newLocation);
|
||||
data.player.getLocation().setYawPitch(data.newLocation);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -8,17 +8,18 @@ import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
import lombok.ToString;
|
||||
import mc.core.Location;
|
||||
import mc.core.network.*;
|
||||
import mc.core.player.Look;
|
||||
import mc.core.EntityLocation;
|
||||
import mc.core.network.CSPacket;
|
||||
import mc.core.network.NetInputStream;
|
||||
import mc.core.network.NetOutputStream;
|
||||
import mc.core.network.SCPacket;
|
||||
|
||||
@NoArgsConstructor
|
||||
@Getter
|
||||
@Setter
|
||||
@ToString
|
||||
public class PlayerPositionAndLookPacket implements SCPacket, CSPacket {
|
||||
private Location location;
|
||||
private Look look;
|
||||
private EntityLocation location;
|
||||
private int teleportId;
|
||||
private boolean onGround = false;
|
||||
|
||||
@@ -27,9 +28,9 @@ public class PlayerPositionAndLookPacket implements SCPacket, CSPacket {
|
||||
netStream.writeDouble(location.getX());
|
||||
netStream.writeDouble(location.getY());
|
||||
netStream.writeDouble(location.getZ());
|
||||
netStream.writeFloat(look.getYaw());
|
||||
netStream.writeFloat(look.getPitch());
|
||||
netStream.writeByte(0); // It's a bitfield, X/Y/Z/Y_ROT/X_ROT. If X is set, the x value is relative and not absolute.
|
||||
netStream.writeFloat(location.getYaw());
|
||||
netStream.writeFloat(location.getPitch());
|
||||
netStream.writeByte(0); // It's a bitfield, X/Y/Z/Y_ROT/X_ROT. If X is setXYZ, the x value is relative and not absolute.
|
||||
/* X - 0x01
|
||||
* Y - 0x02
|
||||
* Z - 0x04
|
||||
@@ -41,15 +42,13 @@ public class PlayerPositionAndLookPacket implements SCPacket, CSPacket {
|
||||
|
||||
@Override
|
||||
public void readSelf(NetInputStream netStream) {
|
||||
this.location = new Location(
|
||||
this.location = new EntityLocation(
|
||||
netStream.readDouble(),
|
||||
netStream.readDouble(),
|
||||
netStream.readDouble(),
|
||||
netStream.readDouble()
|
||||
);
|
||||
|
||||
this.look = new Look(
|
||||
netStream.readFloat(),
|
||||
netStream.readFloat()
|
||||
netStream.readFloat(),
|
||||
null
|
||||
);
|
||||
|
||||
this.onGround = netStream.readBoolean();
|
||||
|
||||
@@ -8,7 +8,7 @@ import lombok.AllArgsConstructor;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
import lombok.ToString;
|
||||
import mc.core.Location;
|
||||
import mc.core.EntityLocation;
|
||||
import mc.core.network.NetOutputStream;
|
||||
import mc.core.network.SCPacket;
|
||||
|
||||
@@ -17,10 +17,21 @@ import mc.core.network.SCPacket;
|
||||
@Setter
|
||||
@ToString
|
||||
public class SpawnPositionPacket implements SCPacket {
|
||||
private Location location;
|
||||
private EntityLocation location;
|
||||
|
||||
private int floor_double(double value) {
|
||||
int i = (int)value;
|
||||
return value < (double)i ? i - 1 : i;
|
||||
}
|
||||
|
||||
private long location2long(EntityLocation entityLocation) {
|
||||
return ((floor_double(entityLocation.getX()) & 0x3FFFFFF) << 38)
|
||||
| ((floor_double(entityLocation.getY()) & 0xFFF) << 26)
|
||||
| (floor_double(entityLocation.getZ()) & 0x3FFFFFF);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeSelf(NetOutputStream netStream) {
|
||||
netStream.writeLong(location.toLong());
|
||||
netStream.writeLong(location2long(location));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,7 +21,13 @@ public class TabCompletePacket implements CSPacket {
|
||||
this.hasPosition = netStream.readBoolean();
|
||||
|
||||
if (this.hasPosition) {
|
||||
this.location = new Location(netStream.readLong());
|
||||
long compactValue = netStream.readLong();
|
||||
|
||||
double x = compactValue >> 38;
|
||||
double y = (compactValue >> 26) & 0xFFF;
|
||||
double z = compactValue << 38 >> 38; // is normal?
|
||||
|
||||
this.location = new Location(x, y, z, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,8 +47,7 @@ public class LoginHandler extends AbstractStateHandler implements LoginStateHand
|
||||
Player player = playerManager.getPlayer(packet.getPlayerName())
|
||||
.orElseGet(() -> playerManager.createPlayer(
|
||||
packet.getPlayerName(),
|
||||
world.getSpawn().getLocation(),
|
||||
world.getSpawn().getLook()));
|
||||
world.getSpawn()));
|
||||
|
||||
channel.writeAndFlush(new LoginSuccessPacket(
|
||||
player.getUUID(),
|
||||
@@ -62,12 +61,12 @@ public class LoginHandler extends AbstractStateHandler implements LoginStateHand
|
||||
pkt1.setMode(PlayerMode.CREATIVE);
|
||||
pkt1.setDimension(0/*Overworld*/);
|
||||
pkt1.setDifficulty(0/*Peaceful*/);
|
||||
pkt1.setLevelType("flat");
|
||||
pkt1.setLevelType("flat"); //FIXME
|
||||
channel.write(pkt1);
|
||||
|
||||
// Spawn Position
|
||||
SpawnPositionPacket pkt2 = new SpawnPositionPacket();
|
||||
pkt2.setLocation(world.getSpawn().getLocation());
|
||||
pkt2.setLocation(world.getSpawn());
|
||||
channel.write(pkt2);
|
||||
|
||||
// Player Abilities
|
||||
@@ -90,7 +89,6 @@ public class LoginHandler extends AbstractStateHandler implements LoginStateHand
|
||||
// Player Position And Look
|
||||
PlayerPositionAndLookPacket pkt4 = new PlayerPositionAndLookPacket();
|
||||
pkt4.setLocation(player.getLocation());
|
||||
pkt4.setLook(player.getLook());
|
||||
pkt4.setTeleportId(TeleportManager.getInstance().append(player, player.getLocation()));
|
||||
channel.writeAndFlush(pkt4);
|
||||
|
||||
|
||||
@@ -52,8 +52,8 @@ public class PlayHandler extends AbstractStateHandler implements PlayStateHandle
|
||||
@Handler
|
||||
public void onPositionAndLook(Channel channel, PlayerPositionAndLookPacket packet) {
|
||||
Player player = channel.attr(ATTR_PLAYER).get();
|
||||
player.getLocation().set(packet.getLocation());
|
||||
player.getLook().set(packet.getLook());
|
||||
player.getLocation().setXYZ(packet.getLocation());
|
||||
player.getLocation().setYawPitch(packet.getLocation());
|
||||
}
|
||||
|
||||
@Handler
|
||||
|
||||
Reference in New Issue
Block a user