Merge branch 'proto_1.12.2' into world
This commit is contained in:
@@ -10,6 +10,7 @@ import lombok.extern.slf4j.Slf4j;
|
||||
import mc.core.events.CS_PlayerMoveEvent;
|
||||
import mc.core.events.EventBusGetter;
|
||||
import mc.core.events.SC_ChunkLoadEvent;
|
||||
import mc.core.events.SC_ChunkUnloadEvent;
|
||||
import mc.core.player.PlayerManager;
|
||||
import mc.core.time.TimeProcessor;
|
||||
import mc.core.utils.CompactedCoords;
|
||||
@@ -17,6 +18,8 @@ import mc.core.world.World;
|
||||
import mc.core.world.chunk.Chunk;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
import java.util.Iterator;
|
||||
|
||||
@Slf4j
|
||||
public class GameLoop extends Thread {
|
||||
private final TpsWatcher TPS_WATCHER = TpsWatcher.getInstance();
|
||||
@@ -48,22 +51,37 @@ public class GameLoop extends Thread {
|
||||
@Subscribe
|
||||
public void playerMoveEventHandler(CS_PlayerMoveEvent event) {
|
||||
log.trace("(GameLoop) playerMoveEventHandler()");
|
||||
event.getPlayer().getLocation().setXYZ(event.getNewLocation());
|
||||
|
||||
Chunk chunk = event.getNewLocation().getChunk(); // Next chunk
|
||||
int ncX = chunk.getX();
|
||||
int ncZ = chunk.getZ();
|
||||
chunk = event.getPlayer().getLocation().getChunk(); // Current chunk
|
||||
Chunk chunk;
|
||||
chunk = event.getOldLocation().getChunk(); // Old chunk
|
||||
int ccX = chunk.getX();
|
||||
int ccZ = chunk.getZ();
|
||||
chunk = event.getNewLocation().getChunk(); // Next chunk
|
||||
int ncX = chunk.getX();
|
||||
int ncZ = chunk.getZ();
|
||||
|
||||
if (event.isRecalcChunk() || (ncX != ccX && ncZ != ccZ)) {
|
||||
final int viewDistance = event.getPlayer().getSettings().getViewDistance();
|
||||
if (event.isRecalcChunk() || (ncX != ccX || ncZ != ccZ)) {
|
||||
final int viewDistance = event.getPlayer().getSettings().getViewDistance() + 1;
|
||||
int cMinX = chunk.getX() - viewDistance;
|
||||
int cMaxX = chunk.getX() + viewDistance;
|
||||
int cMinZ = chunk.getZ() - viewDistance;
|
||||
int cMaxZ = chunk.getZ() + viewDistance;
|
||||
|
||||
SC_ChunkUnloadEvent eventChunkUnload = new SC_ChunkUnloadEvent(event.getPlayer());
|
||||
Iterator<Integer> itr = event.getPlayer().getLoadedChunks().iterator();
|
||||
while(itr.hasNext()) {
|
||||
int compressXZ = itr.next();
|
||||
int[] xz = CompactedCoords.uncompressXZ(compressXZ);
|
||||
if (xz[0] > cMaxX || xz[0] < cMinX || xz[1] > cMaxZ || xz[1] < cMinZ) {
|
||||
eventChunkUnload.getNeedUnloadChunks().add(compressXZ);
|
||||
itr.remove();
|
||||
}
|
||||
}
|
||||
|
||||
if (!eventChunkUnload.getNeedUnloadChunks().isEmpty()) {
|
||||
EventBusGetter.INSTANCE.post(eventChunkUnload);
|
||||
}
|
||||
|
||||
SC_ChunkLoadEvent eventChunkLoad = new SC_ChunkLoadEvent(event.getPlayer());
|
||||
for (int cZ = cMinZ; cZ <= cMaxZ; cZ++) {
|
||||
for (int cX = cMinX; cX <= cMaxX; cX++) {
|
||||
@@ -71,6 +89,7 @@ public class GameLoop extends Thread {
|
||||
if (!event.getPlayer().getLoadedChunks().contains(compressXZ)) {
|
||||
if (!event.getPlayer().getLoadedChunks().contains(compressXZ)) {
|
||||
eventChunkLoad.getNeedLoadChunks().add(compressXZ);
|
||||
event.getPlayer().getLoadedChunks().add(compressXZ);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -81,6 +100,8 @@ public class GameLoop extends Thread {
|
||||
}
|
||||
}
|
||||
|
||||
event.getPlayer().getLocation().setXYZ(event.getNewLocation());
|
||||
|
||||
// TODO отсылать клиенту только(!) для корректировки позиции
|
||||
// SC_PlayerMoveEvent nextEvent = new SC_PlayerMoveEvent(event.getPlayer());
|
||||
// nextEvent.setNewLocation(event.getNewLocation());
|
||||
|
||||
@@ -50,15 +50,15 @@ public class Location implements Cloneable {
|
||||
}
|
||||
|
||||
public int getBlockX() {
|
||||
return (int) x;
|
||||
return Double.valueOf(Math.floor(x)).intValue();
|
||||
}
|
||||
|
||||
public int getBlockY() {
|
||||
return (int) y;
|
||||
return Double.valueOf(Math.floor(y)).intValue();
|
||||
}
|
||||
|
||||
public int getBlockZ() {
|
||||
return (int) z;
|
||||
return Double.valueOf(Math.floor(z)).intValue();
|
||||
}
|
||||
|
||||
public Chunk getChunk() {
|
||||
@@ -66,7 +66,7 @@ public class Location implements Cloneable {
|
||||
if (world == null) {
|
||||
return null;
|
||||
} else {
|
||||
return world.getChunk((int)(x / 16), (int)(z / 16));
|
||||
return world.getChunk(getBlockX() >> 4, getBlockZ() >> 4);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -75,7 +75,7 @@ public class Location implements Cloneable {
|
||||
if (chunk == null) {
|
||||
return null;
|
||||
} else {
|
||||
return chunk.getChunkSection((int)(y / 16));
|
||||
return chunk.getChunkSection(getBlockY() >> 4);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
16
core/src/main/java/mc/core/events/SC_ChunkUnloadEvent.java
Normal file
16
core/src/main/java/mc/core/events/SC_ChunkUnloadEvent.java
Normal file
@@ -0,0 +1,16 @@
|
||||
package mc.core.events;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import mc.core.player.Player;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
public class SC_ChunkUnloadEvent extends EventBase {
|
||||
@Getter
|
||||
private final Player player;
|
||||
@Getter
|
||||
private List<Integer> needUnloadChunks = new ArrayList<>();
|
||||
}
|
||||
@@ -20,4 +20,23 @@ public class CompactedCoords {
|
||||
(int)(short) (compactValue | 0xFFFF0000)
|
||||
};
|
||||
}
|
||||
|
||||
private static int floor_double(double value) {
|
||||
int i = (int)value;
|
||||
return value < (double)i ? i - 1 : i;
|
||||
}
|
||||
|
||||
public static long compressXYZ(double x, double y, double z) {
|
||||
return ((floor_double(x) & 0x3FFFFFF) << 38)
|
||||
| ((floor_double(y) & 0xFFF) << 26)
|
||||
| (floor_double(z) & 0x3FFFFFF);
|
||||
}
|
||||
|
||||
public static double[] uncompressXYZ(long compactValue) {
|
||||
return new double[]{
|
||||
compactValue >> 38,
|
||||
(compactValue >> 26) & 0x0FFF,
|
||||
compactValue << 38 >> 38 // is normal?
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,50 +1,26 @@
|
||||
package mc.core;
|
||||
|
||||
import mc.core.world.World;
|
||||
import mc.core.world.WorldType;
|
||||
import mc.core.world.chunk.Chunk;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertSame;
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
public class TestEntityLocation {
|
||||
@Test
|
||||
public void cloneTest() {
|
||||
World dummyWorld = new World() {
|
||||
@Override
|
||||
public WorldType getWorldType() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public EntityLocation getSpawn() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSpawn(EntityLocation location) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public Chunk getChunk(int x, int z) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setChunk(int x, int z, Chunk chunk) {
|
||||
|
||||
}
|
||||
};
|
||||
World dummyWorld = mock(World.class);
|
||||
|
||||
EntityLocation firstLocation = new EntityLocation(10, 20, 30, 40, 50, dummyWorld);
|
||||
Assert.assertSame("Lost world reference before cloning", dummyWorld, firstLocation.getWorld());
|
||||
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());
|
||||
assertEquals("X mismatch", firstLocation.getX(), locationClone.getX(), 0);
|
||||
assertEquals("Y mismatch", firstLocation.getY(), locationClone.getY(), 0);
|
||||
assertEquals("Z mismatch", firstLocation.getZ(), locationClone.getZ(), 0);
|
||||
assertEquals("Pitch mismatch", firstLocation.getPitch(), locationClone.getPitch(), 0);
|
||||
assertEquals("Yaw mismatch", firstLocation.getYaw(), locationClone.getYaw(), 0);
|
||||
assertSame("World mismatch (accidental clone of the World object?)", firstLocation.getWorld(), locationClone.getWorld());
|
||||
}
|
||||
}
|
||||
|
||||
124
core/src/test/java/mc/core/TestLocation.java
Normal file
124
core/src/test/java/mc/core/TestLocation.java
Normal file
@@ -0,0 +1,124 @@
|
||||
package mc.core;
|
||||
|
||||
import mc.core.world.World;
|
||||
import mc.core.world.chunk.Chunk;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
public class TestLocation {
|
||||
private World world;
|
||||
|
||||
@Before
|
||||
public void prepareWorld() {
|
||||
this.world = mock(World.class);
|
||||
when(world.getChunk(anyInt(), anyInt())).thenAnswer(invocation -> {
|
||||
Object[] args = invocation.getArguments();
|
||||
|
||||
Chunk chunk = mock(Chunk.class);
|
||||
when(chunk.getX()).thenReturn((int) args[0]);
|
||||
when(chunk.getZ()).thenReturn((int) args[1]);
|
||||
|
||||
return chunk;
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetBlockXZ() {
|
||||
Location location;
|
||||
|
||||
location = new Location(0d, 0, 0d, world);
|
||||
assertEquals(0, location.getBlockX());
|
||||
assertEquals(0, location.getBlockZ());
|
||||
|
||||
location.setXYZ(0.1d, 0, 0.1d);
|
||||
assertEquals(0, location.getBlockX());
|
||||
assertEquals(0, location.getBlockZ());
|
||||
|
||||
location.setXYZ(0.5d, 0, 0.5d);
|
||||
assertEquals(0, location.getBlockX());
|
||||
assertEquals(0, location.getBlockZ());
|
||||
|
||||
location.setXYZ(0.9d, 0, 0.9d);
|
||||
assertEquals(0, location.getBlockX());
|
||||
assertEquals(0, location.getBlockZ());
|
||||
|
||||
location.setXYZ(1d, 0, 1d);
|
||||
assertEquals(1, location.getBlockX());
|
||||
assertEquals(1, location.getBlockZ());
|
||||
|
||||
location.setXYZ(-0.1d, 0, -0.1d);
|
||||
assertEquals(-1, location.getBlockX());
|
||||
assertEquals(-1, location.getBlockZ());
|
||||
|
||||
location.setXYZ(-0.5d, 0, -0.5d);
|
||||
assertEquals(-1, location.getBlockX());
|
||||
assertEquals(-1, location.getBlockZ());
|
||||
|
||||
location.setXYZ(-0.9d, 0, -0.9d);
|
||||
assertEquals(-1, location.getBlockX());
|
||||
assertEquals(-1, location.getBlockZ());
|
||||
|
||||
location.setXYZ(-1d, 0, -1d);
|
||||
assertEquals(-1, location.getBlockX());
|
||||
assertEquals(-1, location.getBlockZ());
|
||||
|
||||
location.setXYZ(-1.1d, 0, -1.1d);
|
||||
assertEquals(-2, location.getBlockX());
|
||||
assertEquals(-2, location.getBlockZ());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetChunk() {
|
||||
Location location;
|
||||
Chunk chunk;
|
||||
|
||||
location = new Location(0d, 0, 0d, world);
|
||||
chunk = location.getChunk();
|
||||
assertEquals(0, chunk.getX());
|
||||
assertEquals(0, chunk.getZ());
|
||||
|
||||
location.setXYZ(1d, 0, 1d);
|
||||
chunk = location.getChunk();
|
||||
assertEquals(0, chunk.getX());
|
||||
assertEquals(0, chunk.getZ());
|
||||
|
||||
location.setXYZ(15d, 0, 15d);
|
||||
chunk = location.getChunk();
|
||||
assertEquals(0, chunk.getX());
|
||||
assertEquals(0, chunk.getZ());
|
||||
|
||||
location.setXYZ(16d, 0, 16d);
|
||||
chunk = location.getChunk();
|
||||
assertEquals(1, chunk.getX());
|
||||
assertEquals(1, chunk.getZ());
|
||||
|
||||
location.setXYZ(-0.1d, 0, -0.1d);
|
||||
chunk = location.getChunk();
|
||||
assertEquals(-1, chunk.getX());
|
||||
assertEquals(-1, chunk.getZ());
|
||||
|
||||
location.setXYZ(-1d, 0, -1d);
|
||||
chunk = location.getChunk();
|
||||
assertEquals(-1, chunk.getX());
|
||||
assertEquals(-1, chunk.getZ());
|
||||
|
||||
location.setXYZ(-15d, 0, -15d);
|
||||
chunk = location.getChunk();
|
||||
assertEquals(-1, chunk.getX());
|
||||
assertEquals(-1, chunk.getZ());
|
||||
|
||||
//TODO на практике, таких точных значений не встретиться, но тем не менее данный тест не проходит
|
||||
//location.setXYZ(-16.0d, 0, -16.0d);
|
||||
//chunk = location.getChunk();
|
||||
//assertEquals(-2, chunk.getX());
|
||||
//assertEquals(-2, chunk.getZ());
|
||||
|
||||
location.setXYZ(-16.001d, 0, -16.001d);
|
||||
chunk = location.getChunk();
|
||||
assertEquals(-2, chunk.getX());
|
||||
assertEquals(-2, chunk.getZ());
|
||||
}
|
||||
}
|
||||
@@ -1,27 +1,28 @@
|
||||
package mc.core.utils;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
|
||||
public class TestCompactedCoords {
|
||||
@Test
|
||||
public void testSimple() {
|
||||
public void testXZSimple() {
|
||||
for (int z = -100; z <= 100; z++) {
|
||||
for (int x = -100; x <= 100; x++) {
|
||||
int compressXZ = CompactedCoords.compressXZ(x, z);
|
||||
int[] xz = CompactedCoords.uncompressXZ(compressXZ);
|
||||
|
||||
Assert.assertEquals(x, xz[0]);
|
||||
Assert.assertEquals(z, xz[1]);
|
||||
assertEquals(x, xz[0]);
|
||||
assertEquals(z, xz[1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRandom() {
|
||||
public void testXZRandom() {
|
||||
Random random = new Random();
|
||||
int x,z;
|
||||
|
||||
@@ -38,8 +39,24 @@ public class TestCompactedCoords {
|
||||
int compressXZ = CompactedCoords.compressXZ(x, z);
|
||||
int[] xz = CompactedCoords.uncompressXZ(compressXZ);
|
||||
|
||||
Assert.assertEquals(x, xz[0]);
|
||||
Assert.assertEquals(z, xz[1]);
|
||||
assertEquals(x, xz[0]);
|
||||
assertEquals(z, xz[1]);
|
||||
}
|
||||
}
|
||||
|
||||
// @Test
|
||||
public void testXYZSimple() {
|
||||
for (int z = -100; z <= 100; z++) {
|
||||
for (int x = -100; x <= 100; x++) {
|
||||
for (int y = -100; y <= 100; y++) {
|
||||
long compressXYZ = CompactedCoords.compressXYZ(x, y, z);
|
||||
double[] xyz = CompactedCoords.uncompressXYZ(compressXYZ);
|
||||
|
||||
assertEquals(x, xyz[0], 0.001d);
|
||||
assertEquals(y, xyz[1], 0.001d);
|
||||
assertEquals(z, xyz[2], 0.001d);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user