Archived
0

Merge branch 'proto_1.12.2' into event

This commit is contained in:
2019-01-12 15:29:02 +03:00
31 changed files with 679 additions and 290 deletions

1
.gitignore vendored
View File

@@ -15,3 +15,4 @@ gradlew.*
## PROJECT ##
libs/
*.log

View File

@@ -1,3 +1,25 @@
buildscript {
repositories {
maven { url "https://plugins.gradle.org/m2/" }
}
dependencies {
classpath (group: 'org.sonarsource.scanner.gradle', name: 'sonarqube-gradle-plugin', version: '2.6.2')
}
}
/**
* Проверка кода в SonarQube.
* Для запуска локальной проверки кода, используются следующий command line:
* gradle sonarqube \
* -Dsonar.host.url=http://127.0.0.1:9000
* -Dsonar.login=<TOKEN>
* где
* - <TOKEN> - сгенерированный токен учетки "сонара"
*/
plugins {
id "org.sonarqube" version "2.6.2"
}
allprojects {
apply plugin: 'java'
@@ -9,9 +31,7 @@ allprojects {
repositories {
mavenCentral()
maven {
url 'https://oss.sonatype.org/content/groups/public/'
}
maven { url 'https://oss.sonatype.org/content/groups/public/' }
}
}
@@ -41,6 +61,8 @@ subprojects {
/* Lombok */
annotationProcessor (group: 'org.projectlombok', name: 'lombok', version: lombok_version)
compileOnly (group: 'org.projectlombok', name: 'lombok', version: lombok_version)
testAnnotationProcessor (group: 'org.projectlombok', name: 'lombok', version: lombok_version)
testCompileOnly (group: 'org.projectlombok', name: 'lombok', version: lombok_version)
/* Testing */
testImplementation (group: 'org.junit.jupiter', name: 'junit-jupiter-api', version: junit_version)
@@ -64,22 +86,32 @@ subprojects {
}
}
task runApp(type: JavaExec) {
/**
* Запуск сервера.
* Для указания рабочей папки, указываем JVM параметр
* -DworkDir=path\to\workdir
* Если используется отдельная папка для имплементации логгера, то указываем
* -DlogImplDir=path\to\logimpldir
* Если необходимо передать дополнительные JVM параметры серверу, то указываем их с двойной "D", например:
* -DDspringConfig=spring.xml
* -DDlog4j.configurationFile=log4j2.xml
*/
task runServer(type: JavaExec) {
main = 'mc.core.Main'
workingDir = (project.hasProperty("workDir") ? project.workDir : '.')
workingDir = System.getProperty("workDir", ".")
subprojects.findAll().each{ prj ->
classpath += prj.sourceSets.main.runtimeClasspath
}
/* Uncomment, if your Log Implements are folder '{workDir}/log-impl' */
//classpath += files(fileTree(dir: new File(workingDir, "log-impl")))
/* Uncomment, if you used VM args */
//jvmArgs = [
// "-DspringConfig=spring.xml",
// "-Dlog4j.configurationFile=log4j2.xml"
//]
if (System.getProperty("logImplDir") != null) {
classpath += files(fileTree(dir: new File(System.getProperty("logImplDir"))))
}
System.getProperties().stringPropertyNames().stream()
.filter{propName -> propName.startsWith("D")}
.forEach{propName -> jvmArgs += "-D" + propName.substring(1) + "=" + System.getProperty(propName)}
ignoreExitValue = true
}

View File

@@ -24,10 +24,10 @@ public class CoreEventListener {
log.trace("(GameLoop) playerMoveEventHandler()");
Chunk chunk;
chunk = event.getPlayer().getWorld().getChunk(event.getOldLocation()); // Old chunk
chunk = event.getPlayer().getWorld().getChunk(event.getOldLocation().toBlockLocation()); // Old chunk
int ccX = chunk.getX();
int ccZ = chunk.getZ();
chunk = event.getPlayer().getWorld().getChunk(event.getNewLocation()); // Next chunk
chunk = event.getPlayer().getWorld().getChunk(event.getNewLocation().toBlockLocation()); // Next chunk
int ncX = chunk.getX();
int ncZ = chunk.getZ();

View File

@@ -3,6 +3,8 @@ package mc.core;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import mc.core.world.block.BlockLocation;
import org.springframework.lang.Nullable;
@NoArgsConstructor
@AllArgsConstructor
@@ -32,15 +34,19 @@ public class EntityLocation implements Cloneable {
}
public int getBlockX() {
return Double.valueOf(Math.floor(x)).intValue();
return (int) Math.floor(x);
}
public int getBlockY() {
return Double.valueOf(Math.floor(y)).intValue();
return (int) Math.floor(y);
}
public int getBlockZ() {
return Double.valueOf(Math.floor(z)).intValue();
return (int) Math.floor(z);
}
public BlockLocation toBlockLocation() {
return new BlockLocation(getBlockX(), getBlockY(), getBlockZ());
}
@Override
@@ -49,7 +55,7 @@ public class EntityLocation implements Cloneable {
return (EntityLocation) super.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
return null;
return ZERO();
}
}
}

View File

@@ -1,11 +0,0 @@
package mc.core.nbt;
import com.flowpowered.nbt.Tag;
import java.util.stream.Stream;
public interface Taggable {
Tag<?> getTag(String name);
void setTag(Tag<?> tag);
Stream<Tag<?>> tagStream();
}

View File

@@ -1,22 +1,23 @@
/*
* DmitriyMX <dimon550@gmail.com>
* 2018-07-25
*/
package mc.core.network;
import lombok.Getter;
import lombok.Setter;
import java.io.IOException;
import java.io.InputStream;
import java.util.UUID;
public abstract class NetInputStream {
public abstract class NetInputStream extends InputStream {
@Getter
@Setter
private int dataSize;
public abstract boolean readBoolean();
public abstract byte readByte();
public abstract void readBytes(byte[] buffer);
public int readBytes(byte[] buffer) {
return readBytes(buffer, 0, buffer.length);
}
public abstract int readBytes(byte[] buffer, int offset, int length);
public abstract int readUnsignedByte();
public abstract int readUnsignedShort();
public abstract short readShort();
@@ -30,4 +31,25 @@ public abstract class NetInputStream {
public abstract UUID readUUID();
public abstract void skipBytes(int count);
@Override
public int read() throws IOException {
return readByte();
}
@Override
public int read(byte[] b) throws IOException {
return readBytes(b);
}
@Override
public int read(byte[] b, int off, int len) throws IOException {
return readBytes(b, off, len);
}
@Override
public long skip(long n) throws IOException {
skipBytes((int) n);
return n;
}
}

View File

@@ -1,16 +1,17 @@
/*
* DmitriyMX <dimon550@gmail.com>
* 2018-07-25
*/
package mc.core.network;
import java.io.IOException;
import java.io.OutputStream;
import java.util.UUID;
public abstract class NetOutputStream {
public abstract class NetOutputStream extends OutputStream {
public abstract void writeBoolean(boolean value);
public abstract void writeByte(int value);
public abstract void writeUnsignedByte(int value);
public abstract void writeBytes(byte[] buffer);
public void writeBytes(byte[] buffer) {
writeBytes(buffer, 0, buffer.length);
}
public abstract void writeBytes(byte[] buffer, int offset, int lengtn);
public abstract void writeShort(int value);
public abstract void writeInt(int value);
public abstract void writeVarInt(int value);
@@ -19,4 +20,19 @@ public abstract class NetOutputStream {
public abstract void writeDouble(double value);
public abstract void writeString(String value);
public abstract void writeUUID(UUID uuid);
@Override
public void write(int b) throws IOException {
writeByte(b);
}
@Override
public void write(byte[] b) throws IOException {
writeBytes(b);
}
@Override
public void write(byte[] b, int off, int len) throws IOException {
writeBytes(b, off, len);
}
}

View File

@@ -1,34 +1,57 @@
/*
* DmitriyMX <dimon550@gmail.com>
* 2018-04-15
*/
package mc.core.world;
import mc.core.EntityLocation;
import mc.core.world.block.Block;
import mc.core.world.block.BlockLocation;
import mc.core.world.chunk.Chunk;
public interface World {
String getName();
WorldType getWorldType();
WorldType getType();
EntityLocation getSpawn();
void setSpawn(EntityLocation location);
default void setSpawn(double x, double y, double z, float yaw, float pitch) {
setSpawn(new EntityLocation(x, y, z, yaw, pitch));
}
default void setSpawn(double x, double y, double z) {
setSpawn(x, y, z, 0f, 0f);
}
/**
* Получить чанк по его координатам
* @param x chunk X
* @param z chunk Z
* @return {@link Chunk}
*/
Chunk getChunk(int x, int z);
void setChunk(int x, int z, Chunk chunkSection);
/**
* Получить чанк по глобальным координатам блока
* @param location {@link BlockLocation}
* @return {@link Chunk}
*/
default Chunk getChunk(BlockLocation location) {
return getChunk(location.getX() >> 4, location.getZ() >> 4);
}
default Chunk getChunk(EntityLocation location) {
return getChunk(location.getBlockX() >> 4, location.getBlockZ() >> 4);
void setChunk(int x, int z, Chunk chunk);
/**
* Получить блок по его координатам
* @param x X
* @param y Y
* @param z Z
* @return {@link Block}
*/
Block getBlock(int x, int y, int z);
default Block getBlock(BlockLocation location) {
return getBlock(location.getX(), location.getY(), location.getZ());
}
void setBlock(Block block);
}

View File

@@ -1,13 +1,8 @@
package mc.core.world.block;
import com.flowpowered.nbt.Tag;
import lombok.Getter;
import lombok.Setter;
import java.util.HashMap;
import java.util.Map;
import java.util.stream.Stream;
public abstract class AbstractBlock implements Block {
@Getter
@Setter
@@ -15,11 +10,10 @@ public abstract class AbstractBlock implements Block {
@Getter
private int light = 0;
@Getter
private final BlockType blockType;
private final Map<String, Tag<?>> nbtTagsMap = new HashMap<>();
private final BlockType type;
protected AbstractBlock(BlockType type) {
this.blockType = type;
this.type = type;
}
@Override
@@ -28,19 +22,4 @@ public abstract class AbstractBlock implements Block {
else if (light < 0) this.light = 0;
else this.light = light;
}
@Override
public Tag<?> getTag(String name) {
return nbtTagsMap.get(name);
}
@Override
public void setTag(Tag<?> tag) {
nbtTagsMap.put(tag.getName(), tag);
}
@Override
public Stream<Tag<?>> tagStream() {
return nbtTagsMap.values().stream();
}
}

View File

@@ -1,10 +1,8 @@
package mc.core.world.block;
import mc.core.nbt.Taggable;
public interface Block extends Taggable{
public interface Block {
int getLight();
void setLight(int light);
BlockType getBlockType();
BlockType getType();
BlockLocation getLocation();
}

View File

@@ -26,7 +26,7 @@ public class BlockLocation implements Cloneable {
return (BlockLocation) super.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
return null;
return ZERO();
}
}
}

View File

@@ -1,6 +1,7 @@
package mc.core.world.chunk;
import mc.core.world.Biome;
import mc.core.world.block.Block;
public interface Chunk {
int getX();
@@ -9,6 +10,28 @@ public interface Chunk {
ChunkSection getChunkSection(int height);
void setChunkSection(int height, ChunkSection chunkSection);
Biome getBiome(int localX, int localZ);
void setBiome(int localX, int localZ, Biome biome);
/**
* Получить блок по глобальным координатам секции чанка
* @param x global X
* @param y global Y
* @param z global Z
* @return {@link Block}
*/
Block getBlock(int x, int y, int z);
void setBlock(Block block);
int getSkyLight(int x, int y, int z);
void setSkyLight(int x, int y, int z, int lightLevel);
int getAddition(int x, int y, int z);
void setAddition(int x, int y, int z, int value);
/**
* Получить тип биома по глобальным координатам
* @param x global X
* @param z global Z
* @return
*/
Biome getBiome(int x, int z);
void setBiome(int x, int z, Biome biome);
}

View File

@@ -1,26 +1,29 @@
/*
* DmitriyMX <dimon550@gmail.com>
* 2018-04-15
*/
package mc.core.world.chunk;
import mc.core.world.Biome;
import mc.core.world.block.Block;
/* 16x16x16 */
/**
* Секция чанка размером 16x16x16 блоков
*/
public interface ChunkSection {
int getX();
Chunk getParent();
void setParent(Chunk chunk);
int getY();
int getZ();
/**
* Получить блок по локальным координатам секции чанка
* @param localX local X (0-15)
* @param localY local Y (0-15)
* @param localZ local Z (0-15)
* @return {@link Block}
*/
Block getBlock(int localX, int localY, int localZ);
void setBlock(Block block);
Block getBlock(int x, int y, int z);
int getSkyLight(int x, int y, int z);
void setSkyLight(int x, int y, int z, int lightLevel);
int getSkyLight(int localX, int localY, int localZ);
void setSkyLight(int localX, int localY, int localZ, int lightLevel);
int getAddition(int x, int y, int z);
void setAddition(int x, int y, int z, int value);
Biome getBiome(int localX, int localZ);
int getAddition(int localX, int localY, int localZ);
void setAddition(int localX, int localY, int localZ, int value);
}

View File

@@ -1,7 +1,3 @@
/*
* DmitriyMX <dimon550@gmail.com>
* 2018-06-10
*/
package mc.core.network.proto_1_12_2;
import java.io.ByteArrayOutputStream;
@@ -25,34 +21,34 @@ public class ByteArrayOutputNetStream extends NetOutputStream_p340 {
}
@Override
public void writeBytes(byte[] buffer) {
baos.write(buffer, 0, buffer.length);
public void writeBytes(byte[] buffer, int offset, int lengtn) {
baos.write(buffer, offset, lengtn);
}
@Override
public void writeShort(int value) {
baos.write((byte) value >>> 8);
baos.write((byte) (value >>> 8));
baos.write((byte) value);
}
@Override
public void writeInt(int value) {
baos.write((byte)((int)(value >>> 24)));
baos.write((byte)((int)(value >>> 16)));
baos.write((byte)((int)(value >>> 8)));
baos.write((byte)((int)(value)));
baos.write((value >>> 24) & 0xFF);
baos.write((value >>> 16) & 0xFF);
baos.write((value >>> 8) & 0xFF);
baos.write(value & 0xFF);
}
@Override
public void writeLong(long value) {
baos.write((byte)((int)(value >>> 56)));
baos.write((byte)((int)(value >>> 48)));
baos.write((byte)((int)(value >>> 40)));
baos.write((byte)((int)(value >>> 32)));
baos.write((byte)((int)(value >>> 24)));
baos.write((byte)((int)(value >>> 16)));
baos.write((byte)((int)(value >>> 8)));
baos.write((byte)((int)(value)));
baos.write((int) ((value >>> 56) & 0xFF));
baos.write((int) ((value >>> 48) & 0xFF));
baos.write((int) ((value >>> 40) & 0xFF));
baos.write((int) ((value >>> 32) & 0xFF));
baos.write((int) ((value >>> 24) & 0xFF));
baos.write((int) ((value >>> 16) & 0xFF));
baos.write((int) ((value >>> 8) & 0xFF));
baos.write((int) (value & 0xFF));
}
@Override

View File

@@ -1,43 +0,0 @@
/*
* DmitriyMX <dimon550@gmail.com>
* 2018-06-11
*/
package mc.core.network.proto_1_12_2;
import lombok.extern.slf4j.Slf4j;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.util.Random;
@Slf4j
public class Crypter {
private static final Crypter instance = new Crypter();
private KeyPair keyPair;
private byte[] verifyToken;
public static KeyPair getKeyPair() {
if (instance.keyPair == null) {
try {
KeyPairGenerator keypairgenerator = KeyPairGenerator.getInstance("RSA");
keypairgenerator.initialize(1024);
instance.keyPair = keypairgenerator.generateKeyPair();
} catch (NoSuchAlgorithmException e) {
log.error("WTF?! Algorithm \"RSA\" not defined?!", e);
}
}
return instance.keyPair;
}
public static byte[] getVerifyToken() {
if (instance.verifyToken == null) {
instance.verifyToken = new byte[4];
Random rand = new Random();
rand.nextBytes(instance.verifyToken);
}
return instance.verifyToken;
}
}

View File

@@ -1,7 +1,3 @@
/*
* DmitriyMX <dimon550@gmail.com>
* 2018-07-25
*/
package mc.core.network.proto_1_12_2;
import lombok.extern.slf4j.Slf4j;
@@ -22,8 +18,6 @@ public abstract class NetOutputStream_p340 extends NetOutputStream {
writeByte(value);
}
@Override
public void writeString(String value) {
if (value.length() > Short.MAX_VALUE) {

View File

@@ -171,7 +171,7 @@ public class ChunkDataPacket implements SCPacket {
for (int z = 0; z < 16; z++) {
for (int x = 0; x < 16; x++) {
Block block = chunkSection.getBlock(x, y, z);
int blockState = serializeBlockState(block.getBlockType());
int blockState = serializeBlockState(block.getType());
int currentIndexPaletteBlock;
if (!palette.contains(blockState)) {
@@ -207,7 +207,7 @@ public class ChunkDataPacket implements SCPacket {
}
if (!biomeFinally) {
biomes.writeByte(chunkSection.getBiome(x, z).getId());
biomes.writeByte(chunk.getBiome(x, z).getId());
if (x == 15 && z == 15) {
biomeFinally = true;
}

View File

@@ -1,7 +1,3 @@
/*
* DmitriyMX <dimon550@gmail.com>
* 2018-06-11
*/
package mc.core.network.proto_1_12_2.packets;
import lombok.AllArgsConstructor;
@@ -19,15 +15,10 @@ import mc.core.network.SCPacket;
public class SpawnPositionPacket implements SCPacket {
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);
return (((long) entityLocation.getBlockX() & 0x3FFFFFF) << 38)
| (((long) entityLocation.getBlockY() & 0x0000FFF) << 26)
| ((long) entityLocation.getBlockZ() & 0x3FFFFFF);
}
@Override

View File

@@ -1,9 +1,11 @@
package mc.core.network.proto_1_12_2.packets;
package mc.core.network.proto_1_12_2;
import mc.core.network.proto_1_12_2.NetInputStream_p340;
import lombok.extern.slf4j.Slf4j;
import java.io.ByteArrayInputStream;
import java.io.IOException;
@Slf4j
public class ByteArrayInputNetStream extends NetInputStream_p340 {
private ByteArrayInputStream bais;
@@ -13,7 +15,7 @@ public class ByteArrayInputNetStream extends NetInputStream_p340 {
@Override
public boolean readBoolean() {
return false;
throw new UnsupportedOperationException();
}
@Override
@@ -22,22 +24,32 @@ public class ByteArrayInputNetStream extends NetInputStream_p340 {
}
@Override
public void readBytes(byte[] buffer) {
public int readBytes(byte[] buffer, int offset, int length) {
try {
int read = bais.read(buffer, offset, length);
if (read < length) {
throw new IOException("not enough data");
}
return read;
} catch (IOException e) {
log.error("", e);
return -1;
}
}
@Override
public int readUnsignedByte() {
return 0;
throw new UnsupportedOperationException();
}
@Override
public int readUnsignedShort() {
return 0;
throw new UnsupportedOperationException();
}
@Override
public short readShort() {
return 0;
throw new UnsupportedOperationException();
}
@Override
@@ -47,12 +59,12 @@ public class ByteArrayInputNetStream extends NetInputStream_p340 {
int ch3 = bais.read();
int ch4 = bais.read();
if ((ch1 | ch2 | ch3 | ch4) < 0) return 0;
return ((ch1 << 24) + (ch2 << 16) + (ch3 << 8) + (ch4 << 0));
return ((ch1 << 24) + (ch2 << 16) + (ch3 << 8) + (ch4));
}
@Override
public long readLong() {
return 0;
throw new UnsupportedOperationException();
}
@Override
@@ -62,11 +74,11 @@ public class ByteArrayInputNetStream extends NetInputStream_p340 {
@Override
public double readDouble() {
return 0;
throw new UnsupportedOperationException();
}
@Override
public void skipBytes(int count) {
throw new UnsupportedOperationException();
}
}

View File

@@ -0,0 +1,99 @@
package mc.core.network.proto_1_12_2;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import java.io.IOException;
import java.util.Random;
import static org.junit.jupiter.api.Assertions.assertArrayEquals;
import static org.junit.jupiter.api.Assertions.assertEquals;
class ByteArrayInputNetStreamTest {
private Random random;
@BeforeEach
void before() {
random = new Random(System.currentTimeMillis());
}
@Test
void testReadByte() throws IOException {
final byte[] bytes = new byte[1];
random.nextBytes(bytes);
ByteArrayOutputNetStream byteArrayOutputNetStream = new ByteArrayOutputNetStream();
byteArrayOutputNetStream.writeByte(bytes[0]);
ByteArrayInputNetStream byteArrayInputNetStream = new ByteArrayInputNetStream(byteArrayOutputNetStream.toByteArray());
assertEquals(bytes[0], byteArrayInputNetStream.readByte());
byteArrayInputNetStream = new ByteArrayInputNetStream(byteArrayOutputNetStream.toByteArray());
assertEquals(bytes[0], byteArrayInputNetStream.read());
}
@Test
void testReadBytes() throws IOException {
final byte[] expectedBytes = new byte[10];
random.nextBytes(expectedBytes);
ByteArrayOutputNetStream byteArrayOutputNetStream = new ByteArrayOutputNetStream();
byteArrayOutputNetStream.writeBytes(expectedBytes);
ByteArrayInputNetStream byteArrayInputNetStream = new ByteArrayInputNetStream(byteArrayOutputNetStream.toByteArray());
byte[] actualBytes = new byte[10];
byteArrayInputNetStream.readBytes(actualBytes);
assertArrayEquals(expectedBytes, actualBytes);
byteArrayInputNetStream = new ByteArrayInputNetStream(byteArrayOutputNetStream.toByteArray());
actualBytes = new byte[10];
int r = byteArrayInputNetStream.read(actualBytes);
assertArrayEquals(expectedBytes, actualBytes);
assertEquals(expectedBytes.length, r);
byteArrayInputNetStream = new ByteArrayInputNetStream(byteArrayOutputNetStream.toByteArray());
actualBytes = new byte[10];
byteArrayInputNetStream.readBytes(actualBytes, 2, 5);
byte[] nibbleExpectedBytes = new byte[10];
System.arraycopy(expectedBytes, 0, nibbleExpectedBytes, 2, 5);
assertArrayEquals(nibbleExpectedBytes, actualBytes);
byteArrayInputNetStream = new ByteArrayInputNetStream(byteArrayOutputNetStream.toByteArray());
actualBytes = new byte[10];
r = byteArrayInputNetStream.read(actualBytes, 2, 5);
nibbleExpectedBytes = new byte[10];
System.arraycopy(expectedBytes, 0, nibbleExpectedBytes, 2, 5);
assertArrayEquals(nibbleExpectedBytes, actualBytes);
assertEquals(5, r);
}
@Test
void testReadInt() {
final int integerDig = random.nextInt();
ByteArrayOutputNetStream byteArrayOutputNetStream = new ByteArrayOutputNetStream();
byteArrayOutputNetStream.writeInt(integerDig);
ByteArrayInputNetStream byteArrayInputNetStream = new ByteArrayInputNetStream(byteArrayOutputNetStream.toByteArray());
assertEquals(integerDig, byteArrayInputNetStream.readInt());
}
@Test
void readFloat() {
final float floatDig = random.nextFloat();
ByteArrayOutputNetStream byteArrayOutputNetStream = new ByteArrayOutputNetStream();
byteArrayOutputNetStream.writeFloat(floatDig);
ByteArrayInputNetStream byteArrayInputNetStream = new ByteArrayInputNetStream(byteArrayOutputNetStream.toByteArray());
assertEquals(floatDig, byteArrayInputNetStream.readFloat());
}
}

View File

@@ -0,0 +1,259 @@
package mc.core.network.proto_1_12_2;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.Random;
import java.util.UUID;
import static org.junit.jupiter.api.Assertions.assertArrayEquals;
class ByteArrayOutputNetStreamTest {
private Random random;
@BeforeEach
void before() {
random = new Random(System.currentTimeMillis());
}
@Test
void testWriteBoolean() {
ByteArrayOutputNetStream byteArrayOutputNetStream = new ByteArrayOutputNetStream();
byteArrayOutputNetStream.writeBoolean(true);
assertArrayEquals(new byte[]{0x01}, byteArrayOutputNetStream.toByteArray());
byteArrayOutputNetStream = new ByteArrayOutputNetStream();
byteArrayOutputNetStream.writeBoolean(false);
assertArrayEquals(new byte[]{0x00}, byteArrayOutputNetStream.toByteArray());
}
@Test
void testWriteByte() throws IOException {
final byte[] bytes = new byte[1];
random.nextBytes(bytes);
ByteArrayOutputNetStream byteArrayOutputNetStream = new ByteArrayOutputNetStream();
byteArrayOutputNetStream.writeByte(bytes[0]);
assertArrayEquals(bytes, byteArrayOutputNetStream.toByteArray());
byteArrayOutputNetStream = new ByteArrayOutputNetStream();
byteArrayOutputNetStream.write(bytes[0]);
assertArrayEquals(bytes, byteArrayOutputNetStream.toByteArray());
}
@Test
void testWriteUnsignedByte() {
final byte[] bytes = new byte[1];
random.nextBytes(bytes);
ByteArrayOutputNetStream byteArrayOutputNetStream = new ByteArrayOutputNetStream();
byteArrayOutputNetStream.writeUnsignedByte(bytes[0]);
assertArrayEquals(bytes, byteArrayOutputNetStream.toByteArray());
byteArrayOutputNetStream = new ByteArrayOutputNetStream();
byteArrayOutputNetStream.writeUnsignedByte(0xFF);
assertArrayEquals(new byte[]{(byte) 0xFF}, byteArrayOutputNetStream.toByteArray());
}
@Test
void testWriteBytes() throws IOException {
final byte[] expectedBytes = new byte[10];
random.nextBytes(expectedBytes);
ByteArrayOutputNetStream byteArrayOutputNetStream = new ByteArrayOutputNetStream();
byteArrayOutputNetStream.writeBytes(expectedBytes);
assertArrayEquals(expectedBytes, byteArrayOutputNetStream.toByteArray());
byteArrayOutputNetStream = new ByteArrayOutputNetStream();
byteArrayOutputNetStream.write(expectedBytes);
assertArrayEquals(expectedBytes, byteArrayOutputNetStream.toByteArray());
byteArrayOutputNetStream = new ByteArrayOutputNetStream();
byteArrayOutputNetStream.writeBytes(expectedBytes, 2, 5);
byte[] nibbleExpectedBytes = new byte[5];
System.arraycopy(expectedBytes, 2, nibbleExpectedBytes, 0, 5);
assertArrayEquals(nibbleExpectedBytes, byteArrayOutputNetStream.toByteArray());
byteArrayOutputNetStream = new ByteArrayOutputNetStream();
byteArrayOutputNetStream.write(expectedBytes, 2, 5);
nibbleExpectedBytes = new byte[5];
System.arraycopy(expectedBytes, 2, nibbleExpectedBytes, 0, 5);
assertArrayEquals(nibbleExpectedBytes, byteArrayOutputNetStream.toByteArray());
}
@Test
void testWriteShort() {
int smallInt;
do {
smallInt = random.nextInt();
} while (smallInt > Short.MAX_VALUE || smallInt < Short.MIN_VALUE);
ByteArrayOutputNetStream byteArrayOutputNetStream = new ByteArrayOutputNetStream();
byteArrayOutputNetStream.writeShort(smallInt);
assertArrayEquals(new byte[]{ (byte) (smallInt >>> 8),
(byte) smallInt },
byteArrayOutputNetStream.toByteArray());
}
@Test
void testWriteInt() {
final int integerDig = random.nextInt();
ByteArrayOutputNetStream byteArrayOutputNetStream = new ByteArrayOutputNetStream();
byteArrayOutputNetStream.writeInt(integerDig);
assertArrayEquals(new byte[]{ (byte) ((integerDig >>> 24) & 0xFF),
(byte) ((integerDig >>> 16) & 0xFF),
(byte) ((integerDig >>> 8) & 0xFF),
(byte) (integerDig & 0xFF) },
byteArrayOutputNetStream.toByteArray());
}
@Test
void testWriteLong() {
final long longDig = random.nextLong();
ByteArrayOutputNetStream byteArrayOutputNetStream = new ByteArrayOutputNetStream();
byteArrayOutputNetStream.writeLong(longDig);
assertArrayEquals(new byte[]{ (byte) ((longDig >>> 56) & 0xFF),
(byte) ((longDig >>> 48) & 0xFF),
(byte) ((longDig >>> 40) & 0xFF),
(byte) ((longDig >>> 32) & 0xFF),
(byte) ((longDig >>> 24) & 0xFF),
(byte) ((longDig >>> 16) & 0xFF),
(byte) ((longDig >>> 8) & 0xFF),
(byte) (longDig & 0xFF) },
byteArrayOutputNetStream.toByteArray());
}
@Test
void testWriteFloat() {
final float floatDig = random.nextFloat();
ByteArrayOutputNetStream byteArrayOutputNetStream = new ByteArrayOutputNetStream();
byteArrayOutputNetStream.writeFloat(floatDig);
final int floatBits = Float.floatToIntBits(floatDig);
assertArrayEquals(new byte[]{ (byte) ((floatBits >>> 24) & 0xFF),
(byte) ((floatBits >>> 16) & 0xFF),
(byte) ((floatBits >>> 8) & 0xFF),
(byte) (floatBits & 0xFF) },
byteArrayOutputNetStream.toByteArray());
}
@Test
void testWriteDouble() {
final double doubleDig = random.nextDouble();
ByteArrayOutputNetStream byteArrayOutputNetStream = new ByteArrayOutputNetStream();
byteArrayOutputNetStream.writeDouble(doubleDig);
final long doubleBits = Double.doubleToLongBits(doubleDig);
assertArrayEquals(new byte[]{ (byte) ((doubleBits >>> 56) & 0xFF),
(byte) ((doubleBits >>> 48) & 0xFF),
(byte) ((doubleBits >>> 40) & 0xFF),
(byte) ((doubleBits >>> 32) & 0xFF),
(byte) ((doubleBits >>> 24) & 0xFF),
(byte) ((doubleBits >>> 16) & 0xFF),
(byte) ((doubleBits >>> 8) & 0xFF),
(byte) (doubleBits & 0xFF) },
byteArrayOutputNetStream.toByteArray());
}
@Test
void testWriteVarInt() {
final int b1Int = 120;
ByteArrayOutputNetStream byteArrayOutputNetStream = new ByteArrayOutputNetStream();
byteArrayOutputNetStream.writeVarInt(b1Int);
assertArrayEquals(new byte[]{ 0x78 },
byteArrayOutputNetStream.toByteArray());
final int b2Int = 12000;
byteArrayOutputNetStream = new ByteArrayOutputNetStream();
byteArrayOutputNetStream.writeVarInt(b2Int);
assertArrayEquals(new byte[]{ (byte) 0xE0, 0x5D },
byteArrayOutputNetStream.toByteArray());
final int b3Int = 120000;
byteArrayOutputNetStream = new ByteArrayOutputNetStream();
byteArrayOutputNetStream.writeVarInt(b3Int);
assertArrayEquals(new byte[]{ (byte) 0xC0, (byte) 0xA9, 0x07 },
byteArrayOutputNetStream.toByteArray());
final int b4Int = 120000000;
byteArrayOutputNetStream = new ByteArrayOutputNetStream();
byteArrayOutputNetStream.writeVarInt(b4Int);
assertArrayEquals(new byte[]{ (byte) 0x80, (byte) 0x9C, (byte) 0x9C, (byte) 0x39 },
byteArrayOutputNetStream.toByteArray());
final int b5Int = 1200000000;
byteArrayOutputNetStream = new ByteArrayOutputNetStream();
byteArrayOutputNetStream.writeVarInt(b5Int);
assertArrayEquals(new byte[]{ (byte) 0x80, (byte) 0x98, (byte) 0x9A, (byte) 0xBC, 0x04 },
byteArrayOutputNetStream.toByteArray());
}
@Test
void testWriteString() {
final String string = "Hello? Есть тут кто?";
ByteArrayOutputNetStream byteArrayOutputNetStream = new ByteArrayOutputNetStream();
byteArrayOutputNetStream.writeString(string);
final byte[] strBytes = string.getBytes(StandardCharsets.UTF_8);
final byte[] bytes = new byte[strBytes.length + 1];
bytes[0] = (byte) string.length(); // здесь считается, что размер поместится в один байт
System.arraycopy(strBytes, 0, bytes, 1, strBytes.length);
assertArrayEquals(bytes, byteArrayOutputNetStream.toByteArray());
}
@Test
void testWriteUUID() {
final UUID uuid = UUID.randomUUID();
ByteArrayOutputNetStream byteArrayOutputNetStream = new ByteArrayOutputNetStream();
byteArrayOutputNetStream.writeUUID(uuid);
final long mostSignificantBits = uuid.getMostSignificantBits();
final long leastSignificantBits = uuid.getLeastSignificantBits();
assertArrayEquals(new byte[]{ (byte) ((mostSignificantBits >>> 56) & 0xFF),
(byte) ((mostSignificantBits >>> 48) & 0xFF),
(byte) ((mostSignificantBits >>> 40) & 0xFF),
(byte) ((mostSignificantBits >>> 32) & 0xFF),
(byte) ((mostSignificantBits >>> 24) & 0xFF),
(byte) ((mostSignificantBits >>> 16) & 0xFF),
(byte) ((mostSignificantBits >>> 8) & 0xFF),
(byte) (mostSignificantBits & 0xFF),
(byte) ((leastSignificantBits >>> 56) & 0xFF),
(byte) ((leastSignificantBits >>> 48) & 0xFF),
(byte) ((leastSignificantBits >>> 40) & 0xFF),
(byte) ((leastSignificantBits >>> 32) & 0xFF),
(byte) ((leastSignificantBits >>> 24) & 0xFF),
(byte) ((leastSignificantBits >>> 16) & 0xFF),
(byte) ((leastSignificantBits >>> 8) & 0xFF),
(byte) (leastSignificantBits & 0xFF) },
byteArrayOutputNetStream.toByteArray());
}
}

View File

@@ -1,48 +0,0 @@
package mc.core.network.proto_1_12_2.packets;
import mc.core.network.proto_1_12_2.ByteArrayOutputNetStream;
import org.junit.jupiter.api.Test;
import java.util.Random;
import static org.junit.jupiter.api.Assertions.assertEquals;
class ByteArrayInputNetStreamTest {
private Random rnd = new Random();
@Test
void readByte() {
final byte b0 = (byte) rnd.nextInt();
ByteArrayOutputNetStream netStream = new ByteArrayOutputNetStream();
netStream.writeByte(b0);
byte[] buffer = netStream.toByteArray();
ByteArrayInputNetStream netInputStream = new ByteArrayInputNetStream(buffer);
byte b1 = netInputStream.readByte();
assertEquals(b0, b1);
}
@Test
void readInt() {
final int i0 = rnd.nextInt();
ByteArrayOutputNetStream netStream = new ByteArrayOutputNetStream();
netStream.writeInt(i0);
byte[] buffer = netStream.toByteArray();
ByteArrayInputNetStream netInputStream = new ByteArrayInputNetStream(buffer);
int i1 = netInputStream.readInt();
assertEquals(i0, i1);
}
@Test
void readFloat() {
final float f0 = rnd.nextFloat();
ByteArrayOutputNetStream netStream = new ByteArrayOutputNetStream();
netStream.writeFloat(f0);
byte[] buffer = netStream.toByteArray();
ByteArrayInputNetStream netInputStream = new ByteArrayInputNetStream(buffer);
float f1 = netInputStream.readFloat();
assertEquals(f0, f1, 0.00001f);
}
}

View File

@@ -41,7 +41,6 @@ class ChunkdataPacketTest {
if (y <= 3) return 0;
else return 15;
});
when(chunkSection.getBiome(anyInt(), anyInt())).thenReturn(Biome.PLAINS);
when(chunkSection.getBlock(anyInt(), anyInt(), anyInt())).thenAnswer(invocation -> {
Object[] args = invocation.getArguments();
int x = (int) args[0];
@@ -57,7 +56,7 @@ class ChunkdataPacketTest {
});
world = mock(World.class);
when(world.getWorldType()).thenReturn(WorldType.FLAT);
when(world.getType()).thenReturn(WorldType.FLAT);
when(world.getChunk(anyInt(), anyInt())).thenAnswer(invocation -> {
Object[] args = invocation.getArguments();

View File

@@ -1,5 +1,6 @@
package mc.core.network.proto_1_12_2.packets;
import mc.core.network.proto_1_12_2.ByteArrayInputNetStream;
import mc.core.network.proto_1_12_2.ByteArrayOutputNetStream;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

View File

@@ -73,7 +73,7 @@ public class LoginHandler extends AbstractStateHandler implements LoginStateHand
pkt1.setMode(PlayerMode.CREATIVE); //TODO перенести в Config
pkt1.setDimension(0/*Overworld*/); //TODO перенести в World
pkt1.setDifficulty(0/*Peaceful*/); //TODO перенести в Config
pkt1.setLevelType(world.getWorldType().getName());
pkt1.setLevelType(world.getType().getName());
channel.write(pkt1);
// Spawn Position

View File

@@ -1,7 +1,3 @@
/*
* DmitriyMX <dimon550@gmail.com>
* 2018-07-25
*/
package mc.core.network.proto_1_12_2.netty.wrappers;
import io.netty.buffer.ByteBuf;
@@ -25,8 +21,9 @@ public class WrapperNetInputStream extends NetInputStream_p340 {
}
@Override
public void readBytes(byte[] buffer) {
byteBuf.readBytes(buffer);
public int readBytes(byte[] buffer, int offset, int length) {
byteBuf.readBytes(buffer, offset, length);
return length;
}
@Override

View File

@@ -1,7 +1,3 @@
/*
* DmitriyMX <dimon550@gmail.com>
* 2018-07-25
*/
package mc.core.network.proto_1_12_2.netty.wrappers;
import io.netty.buffer.ByteBuf;
@@ -30,8 +26,8 @@ public class WrapperNetOutputStream extends NetOutputStream_p340 {
}
@Override
public void writeBytes(byte[] buffer) {
byteBuf.writeBytes(buffer);
public void writeBytes(byte[] buffer, int offset, int lengtn) {
byteBuf.writeBytes(buffer, offset, lengtn);
}
@Override

View File

@@ -4,6 +4,7 @@ import lombok.Getter;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import mc.core.world.Biome;
import mc.core.world.block.Block;
import mc.core.world.chunk.Chunk;
import mc.core.world.chunk.ChunkSection;
@@ -13,7 +14,6 @@ public class SimpleChunk implements Chunk {
@Getter
private final int x, z;
private ChunkSection chunkSection;
private final Biome biome = Biome.PLAINS;
@Override
public ChunkSection getChunkSection(int height) {
@@ -23,15 +23,58 @@ public class SimpleChunk implements Chunk {
@Override
public void setChunkSection(int height, ChunkSection chunkSection) {
this.chunkSection = chunkSection;
this.chunkSection.setParent(this);
}
@Override
public Biome getBiome(int localX, int localZ) {
return biome;
public Block getBlock(int x, int y, int z) {
return chunkSection.getBlock(
x - (x >> 4) << 4,
y - (y >> 4) << 4,
z - (z >> 4) << 4
);
}
@Override
public void setBiome(int localX, int localZ, Biome biome) {
public void setBlock(Block block) {
// ignore
}
@Override
public int getSkyLight(int x, int y, int z) {
return chunkSection.getSkyLight(
x - (x >> 4) << 4,
y - (y >> 4) << 4,
z - (z >> 4) << 4
);
}
@Override
public void setSkyLight(int x, int y, int z, int lightLevel) {
// ignore
}
@Override
public int getAddition(int x, int y, int z) {
return chunkSection.getAddition(
x - (x >> 4) << 4,
y - (y >> 4) << 4,
z - (z >> 4) << 4
);
}
@Override
public void setAddition(int x, int y, int z, int value) {
// ignore
}
@Override
public Biome getBiome(int x, int z) {
return Biome.PLAINS;
}
@Override
public void setBiome(int x, int z, Biome biome) {
// ignore
}
}

View File

@@ -1,14 +1,19 @@
package mc.world.simple;
import mc.core.world.Biome;
import lombok.Getter;
import lombok.Setter;
import mc.core.world.block.Block;
import mc.core.world.block.BlockFactory;
import mc.core.world.block.BlockType;
import mc.core.world.chunk.Chunk;
import mc.core.world.chunk.ChunkSection;
import java.util.List;
public class SimpleChunkSection implements ChunkSection {
@Getter
@Setter
private Chunk parent;
private final BlockFactory blockFactory = new BlockFactory();
private final List<BlockType> layersBlock;
@@ -17,32 +22,22 @@ public class SimpleChunkSection implements ChunkSection {
}
@Override
public int getSkyLight(int x, int y, int z) {
if (y <= 3) return 0;
public int getSkyLight(int localX, int localY, int localZ) {
if (localY <= 3) return 0;
else return 15;
}
@Override
public void setSkyLight(int x, int y, int z, int lightLevel) {
public void setSkyLight(int localX, int localY, int localZ, int lightLevel) {
}
@Override
public int getAddition(int x, int y, int z) {
public int getAddition(int localX, int localY, int localZ) {
return 0;
}
@Override
public void setAddition(int x, int y, int z, int value) {
}
@Override
public Biome getBiome(int localX, int localZ) {
return Biome.PLAINS;
}
@Override
public int getX() {
return 0;
public void setAddition(int localX, int localY, int localZ, int value) {
}
@Override
@@ -50,31 +45,26 @@ public class SimpleChunkSection implements ChunkSection {
return 0;
}
@Override
public int getZ() {
return 0;
}
@Override
public void setBlock(Block block) {
}
@Override
public Block getBlock(int x, int y, int z) {
if (x < 0) x = 0;
else if (x > 15) x = 15;
if (y < 0) y = 0;
else if (y > 15) y = 15;
if (z < 0) z = 0;
else if (z > 15) z = 15;
public Block getBlock(int localX, int localY, int localZ) {
if (localX < 0) localX = 0;
else if (localX > 15) localX = 15;
if (localY < 0) localY = 0;
else if (localY > 15) localY = 15;
if (localZ < 0) localZ = 0;
else if (localZ > 15) localZ = 15;
if (y >= layersBlock.size()) {
return blockFactory.create(BlockType.AIR, x, y, z);
if (localY >= layersBlock.size()) {
return blockFactory.create(BlockType.AIR, localX, localY, localZ);
}
BlockType blockType = layersBlock.get(y);
if (blockType == null) return blockFactory.create(BlockType.AIR, x, y, z);
BlockType blockType = layersBlock.get(localY);
if (blockType == null) return blockFactory.create(BlockType.AIR, localX, localY, localZ);
return blockFactory.create(blockType, x, y, z);
return blockFactory.create(blockType, localX, localY, localZ);
}
}

View File

@@ -6,6 +6,7 @@ import lombok.extern.slf4j.Slf4j;
import mc.core.EntityLocation;
import mc.core.world.World;
import mc.core.world.WorldType;
import mc.core.world.block.Block;
import mc.core.world.chunk.Chunk;
import mc.core.world.chunk.ChunkProvider;
import org.springframework.beans.factory.BeanNameAware;
@@ -19,7 +20,7 @@ public class SimpleWorld implements World, BeanNameAware {
@Getter
private String name;
@Getter
private final WorldType worldType = WorldType.FLAT;
private final WorldType type = WorldType.FLAT;
private EntityLocation spawn;
@Setter
private ChunkProvider chunkProvider;
@@ -49,6 +50,16 @@ public class SimpleWorld implements World, BeanNameAware {
throw new UnsupportedOperationException();
}
@Override
public Block getBlock(int x, int y, int z) {
return chunkProvider.getChunk(x >> 4, z >> 4).getBlock(x, y, z);
}
@Override
public void setBlock(Block block) {
// nope...
}
@Override
public void setBeanName(@Nonnull String name) {
this.name = name;

View File

@@ -33,9 +33,9 @@ class SimpleChunkSectionTest {
for (int z = 0; z < 16; z++) {
Block block = chunkSection.getBlock(x, y, z);
if (y > layersBlock.size()-1) {
assertEquals(block.getBlockType(), BlockType.AIR);
assertEquals(block.getType(), BlockType.AIR);
} else {
assertEquals(block.getBlockType(), layersBlock.get(y));
assertEquals(block.getType(), layersBlock.get(y));
}
}
}