Merge branch 'world' into proto_1.12.2
This commit is contained in:
@@ -1,12 +0,0 @@
|
||||
package mc.core.exception;
|
||||
|
||||
public abstract class McCoreUncheckedException extends RuntimeException {
|
||||
|
||||
public McCoreUncheckedException() {
|
||||
super();
|
||||
}
|
||||
|
||||
public McCoreUncheckedException(String msg) {
|
||||
super(msg);
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,6 @@
|
||||
package mc.core.exception;
|
||||
|
||||
public class ResourceUnloadedException extends McCoreUncheckedException {
|
||||
|
||||
public class ResourceUnloadedException extends RuntimeException {
|
||||
public ResourceUnloadedException(String msg) {
|
||||
super(msg);
|
||||
}
|
||||
|
||||
@@ -14,6 +14,12 @@ public interface World {
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
Chunk getChunk(int x, int z);
|
||||
void setChunk(int x, int z, Chunk chunkSection);
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package mc.core.world.chunk;
|
||||
|
||||
import mc.core.world.Biome;
|
||||
import mc.core.world.World;
|
||||
|
||||
public interface Chunk {
|
||||
int getX();
|
||||
@@ -12,7 +11,4 @@ public interface Chunk {
|
||||
|
||||
Biome getBiome(int localX, int localZ);
|
||||
void setBiome(int localX, int localZ, Biome biome);
|
||||
|
||||
World getWorld();
|
||||
void setWorld(World world);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
package mc.core.world.chunk;
|
||||
|
||||
public interface ChunkProvider {
|
||||
Chunk getChunk(int x , int z);
|
||||
|
||||
void saveChunk(Chunk chunk);
|
||||
void saveChunk(Chunk... chunks);
|
||||
}
|
||||
@@ -5,7 +5,6 @@
|
||||
package mc.core.world.chunk;
|
||||
|
||||
import mc.core.world.Biome;
|
||||
import mc.core.world.World;
|
||||
import mc.core.world.block.Block;
|
||||
|
||||
/* 16x16x16 */
|
||||
@@ -24,6 +23,4 @@ public interface ChunkSection {
|
||||
void setAddition(int x, int y, int z, int value);
|
||||
|
||||
Biome getBiome(int localX, int localZ);
|
||||
|
||||
World getWorld();
|
||||
}
|
||||
|
||||
@@ -5,8 +5,7 @@ import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.concurrent.ThreadLocalRandom;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotEquals;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
class EntityLocationTest {
|
||||
private static final ThreadLocalRandom rnd = ThreadLocalRandom.current();
|
||||
@@ -42,6 +41,7 @@ class EntityLocationTest {
|
||||
EntityLocation locOrig = new EntityLocation(x, y, z, yaw, pitch);
|
||||
EntityLocation locClone = locOrig.clone();
|
||||
assertEquals(locOrig, locClone);
|
||||
assertNotSame(locOrig, locClone);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
# Flat world
|
||||
|
||||
Плоский мир
|
||||
|
||||
## Spring bean
|
||||
|
||||
```xml
|
||||
<bean id="flatWorld" class="mc.world.flat.FlatWorld">
|
||||
<property name="spawn">
|
||||
<bean class="mc.core.Location">
|
||||
<constructor-arg index="0" type="double" value="8"/>
|
||||
<constructor-arg index="1" type="double" value="6"/>
|
||||
<constructor-arg index="2" type="double" value="8"/>
|
||||
</bean>
|
||||
</property>
|
||||
</bean>
|
||||
```
|
||||
|
||||
`spawn` - точка спавна
|
||||
@@ -12,6 +12,7 @@ import mc.core.player.PlayerManager;
|
||||
import mc.core.player.PlayerSettings;
|
||||
import mc.core.world.World;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@@ -26,8 +27,6 @@ public class H2PlayerManager implements PlayerManager {
|
||||
@Autowired
|
||||
private H2PlayerService h2PlayerService;
|
||||
private List<H2Player> playerList = Collections.synchronizedList(new ArrayList<>());
|
||||
@Autowired
|
||||
private World world; //FIXME
|
||||
|
||||
@Override
|
||||
public Player createPlayer(String name, EntityLocation location, World world) {
|
||||
@@ -91,25 +90,9 @@ public class H2PlayerManager implements PlayerManager {
|
||||
|
||||
@Override
|
||||
public Player getOfflinePlayer(String name) {
|
||||
//TODO похоже в попытке где-то оптимизировать/сэконопить я сам себя ******[обманул]
|
||||
//необходимо этот участок кода переписать
|
||||
//потому как похоже на экономию на спичках
|
||||
H2Player h2Player = playerList.stream()
|
||||
return playerList.stream()
|
||||
.filter(player -> player.getName().equals(name))
|
||||
.filter(player -> !player.isOnline())
|
||||
.findFirst().orElse(null);
|
||||
|
||||
if (h2Player == null) {
|
||||
h2Player = h2PlayerService.getByName(name);
|
||||
if (h2Player != null) {
|
||||
h2Player.setWorld(world);
|
||||
return h2Player;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
} else {
|
||||
h2Player.setWorld(world);
|
||||
return h2Player;
|
||||
}
|
||||
.findFirst().orElseGet(() -> h2PlayerService.getByName(name));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,9 @@ import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import mc.core.EntityLocation;
|
||||
import mc.core.h2db.H2Player;
|
||||
import mc.core.world.World;
|
||||
import org.hibernate.annotations.GenericGenerator;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
|
||||
import javax.persistence.*;
|
||||
import java.util.UUID;
|
||||
@@ -55,11 +57,7 @@ public class H2PlayerEntity {
|
||||
this.locationZ = player.getLocation().getZ();
|
||||
this.locationYaw = player.getLocation().getYaw();
|
||||
this.locationPitch = player.getLocation().getPitch();
|
||||
if (player.getWorld() != null) { //FIXME
|
||||
this.locationWorld = player.getWorld().getName();
|
||||
} else {
|
||||
this.locationWorld = "null_world";
|
||||
}
|
||||
this.locationWorld = player.getWorld().getName();
|
||||
}
|
||||
|
||||
public void setUuid(String uuid) {
|
||||
@@ -78,12 +76,12 @@ public class H2PlayerEntity {
|
||||
}
|
||||
}
|
||||
|
||||
public H2Player toPlayer() {
|
||||
public H2Player toPlayer(ApplicationContext context) {
|
||||
H2Player player = new H2Player();
|
||||
return toPlayer(player);
|
||||
return toPlayer(player, context);
|
||||
}
|
||||
|
||||
public H2Player toPlayer(H2Player player) {
|
||||
public H2Player toPlayer(H2Player player, ApplicationContext context) {
|
||||
player.setId(this.id.intValue());
|
||||
player.setUuid(UUID.fromString(this.uuid));
|
||||
player.setName(this.name);
|
||||
@@ -97,7 +95,7 @@ public class H2PlayerEntity {
|
||||
player.getLocation().setYawPitch(this.locationYaw, this.locationPitch);
|
||||
}
|
||||
|
||||
player.setWorld(null); //FIXME
|
||||
player.setWorld(context.getBean(this.locationWorld, World.class));
|
||||
|
||||
return player;
|
||||
}
|
||||
|
||||
@@ -4,12 +4,15 @@ import mc.core.h2db.H2Player;
|
||||
import mc.core.h2db.entity.H2PlayerEntity;
|
||||
import mc.core.h2db.repository.H2PlayerEntityRepository;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
@Service
|
||||
public class H2PlayerServiceImpl implements H2PlayerService {
|
||||
@Autowired
|
||||
private ApplicationContext context;
|
||||
@Autowired
|
||||
private H2PlayerEntityRepository h2PlayerEntityRepository;
|
||||
|
||||
@@ -19,7 +22,7 @@ public class H2PlayerServiceImpl implements H2PlayerService {
|
||||
//TODO возможно имеет смысл здесь оптимизация
|
||||
//вместо toPlayer() сделать toPlayer(H2Player) который в существующий
|
||||
//будет дописывать/обновлять данные
|
||||
return h2PlayerEntityRepository.saveAndFlush(entity).toPlayer(player);
|
||||
return h2PlayerEntityRepository.saveAndFlush(entity).toPlayer(player, context);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -30,12 +33,12 @@ public class H2PlayerServiceImpl implements H2PlayerService {
|
||||
@Override
|
||||
public H2Player getByName(String name) {
|
||||
Optional<H2PlayerEntity> optEntity = h2PlayerEntityRepository.findByName(name);
|
||||
return optEntity.map(H2PlayerEntity::toPlayer).orElse(null);
|
||||
return optEntity.map(entiry -> entiry.toPlayer(context)).orElse(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public H2Player getById(int id) {
|
||||
Optional<H2PlayerEntity> optEntity = h2PlayerEntityRepository.findById((long) id);
|
||||
return optEntity.map(H2PlayerEntity::toPlayer).orElse(null);
|
||||
return optEntity.map(entiry -> entiry.toPlayer(context)).orElse(null);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -44,10 +44,10 @@ public class TestSpringConfig {
|
||||
return properties;
|
||||
}
|
||||
|
||||
@Bean
|
||||
@Bean("mockWorld")
|
||||
public World mockWorld() {
|
||||
World mockWorld = mock(World.class);
|
||||
when(mockWorld.getName()).thenReturn("mock_world");
|
||||
when(mockWorld.getName()).thenReturn("mockWorld");
|
||||
return mockWorld;
|
||||
}
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@ package mc.core.h2db.service;
|
||||
import mc.core.EntityLocation;
|
||||
import mc.core.h2db.H2Player;
|
||||
import mc.core.h2db.TestSpringConfig;
|
||||
import mc.core.world.World;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
@@ -21,6 +22,8 @@ import static org.junit.jupiter.api.Assertions.*;
|
||||
class H2PlayerServiceTest {
|
||||
@Autowired
|
||||
private H2PlayerService h2PlayerService;
|
||||
@Autowired
|
||||
private World world;
|
||||
|
||||
private H2Player buildPlayer() {
|
||||
final ThreadLocalRandom rnd = ThreadLocalRandom.current();
|
||||
@@ -38,18 +41,26 @@ class H2PlayerServiceTest {
|
||||
rnd.nextFloat() * (maxF - minF) + minF,
|
||||
rnd.nextFloat() * (maxF - minF) + minF
|
||||
));
|
||||
player.setWorld(null); //FIXME
|
||||
player.setWorld(world);
|
||||
|
||||
return player;
|
||||
}
|
||||
|
||||
private void assertPlayers(H2Player expected, H2Player actual) {
|
||||
assertEquals(expected, actual);
|
||||
assertEquals(expected.getName(), actual.getName());
|
||||
assertEquals(expected.getLocation(), actual.getLocation());
|
||||
assertNotNull(actual.getWorld());
|
||||
assertEquals(expected.getWorld(), actual.getWorld());
|
||||
}
|
||||
|
||||
@Test
|
||||
void save() {
|
||||
H2Player player = buildPlayer();
|
||||
H2Player savedPlayer = h2PlayerService.save(player);
|
||||
|
||||
player.setId(savedPlayer.getId()); //FIXME костыль, однако
|
||||
assertEquals(player, savedPlayer);
|
||||
assertPlayers(player, savedPlayer);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -111,7 +122,7 @@ class H2PlayerServiceTest {
|
||||
H2Player player = h2PlayerService.save(buildPlayer());
|
||||
|
||||
H2Player player2 = h2PlayerService.getByName(player.getName());
|
||||
assertEquals(player, player2);
|
||||
assertPlayers(player, player2);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -134,7 +145,7 @@ class H2PlayerServiceTest {
|
||||
H2Player player = h2PlayerService.save(buildPlayer());
|
||||
|
||||
H2Player player2 = h2PlayerService.getById(player.getId());
|
||||
assertEquals(player, player2);
|
||||
assertPlayers(player, player2);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -100,6 +100,7 @@ public class ChunkDataPacket implements SCPacket {
|
||||
netStream.writeInt(z); // Chunk Y
|
||||
netStream.writeBoolean(initChunk); // Init Chunk
|
||||
|
||||
int maxH = 0;
|
||||
if (sectionList == null && chunk != null) {
|
||||
int bitMask = 0;
|
||||
for (int h = 15; h >= 0; h--) {
|
||||
@@ -107,6 +108,7 @@ public class ChunkDataPacket implements SCPacket {
|
||||
ChunkSection chunkSection = chunk.getChunkSection(h);
|
||||
if (chunkSection != null && chunkSection.getY() == h) {
|
||||
bitMask |= 0x01;
|
||||
maxH++;
|
||||
} else {
|
||||
bitMask |= 0x00;
|
||||
}
|
||||
@@ -121,6 +123,7 @@ public class ChunkDataPacket implements SCPacket {
|
||||
ChunkSection chunkSection = sectionList.get(i);
|
||||
if (chunkSection != null && chunkSection.getY() == h) {
|
||||
bitMask |= 0x01;
|
||||
maxH++;
|
||||
} else {
|
||||
bitMask |= 0x00;
|
||||
}
|
||||
@@ -136,7 +139,7 @@ public class ChunkDataPacket implements SCPacket {
|
||||
int dataItems = 0;
|
||||
final int airBlockPalette = serializeBlockState(BlockType.AIR);
|
||||
|
||||
for (int h = 0; h < 16; h++) {
|
||||
for (int h = 0; h < maxH; h++) {
|
||||
ChunkSection chunkSection = null;
|
||||
|
||||
if (chunk != null) {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
rootProject.name = 'mc-server'
|
||||
|
||||
include('core') // Core
|
||||
include('flat_world')
|
||||
include('simple_world')
|
||||
include('h2_playermanager')
|
||||
include('vanilla_commands')
|
||||
include('proto_1.12.2') // Protocol 1.12.2
|
||||
|
||||
39
simple_world/README.MD
Normal file
39
simple_world/README.MD
Normal file
@@ -0,0 +1,39 @@
|
||||
# Simple world
|
||||
|
||||
Простая реализация мира
|
||||
|
||||
## Spring bean
|
||||
|
||||
```xml
|
||||
<bean id="simpleWorld" class="mc.world.simple.SimpleWorld">
|
||||
<property name="spawn">
|
||||
<bean class="mc.core.EntityLocation">
|
||||
<constructor-arg index="0" type="double" value="8"/>
|
||||
<constructor-arg index="1" type="double" value="6"/>
|
||||
<constructor-arg index="2" type="double" value="8"/>
|
||||
<constructor-arg index="3" type="float" value="0"/>
|
||||
<constructor-arg index="4" type="float" value="0"/>
|
||||
<constructor-arg index="5" type="mc.core.world.World">
|
||||
<null/>
|
||||
</constructor-arg>
|
||||
</bean>
|
||||
</property>
|
||||
<property name="layersBlock">
|
||||
<list value-type="java.lang.String">
|
||||
<value>1;BEDROCK</value>
|
||||
<value>2;DIRT</value>
|
||||
<value>1;GRASS</value>
|
||||
</list>
|
||||
</property>
|
||||
</bean>
|
||||
```
|
||||
|
||||
`spawn` - точка спавна.
|
||||
|
||||
При указании точки спавна, указывать шестой параметр `World` не имеет смысла,
|
||||
т.к. `SimpleWorld` всё равно перезапишет этот параметр.
|
||||
|
||||
`layersBlock` - слои блоков.
|
||||
|
||||
В качестве значения указывается спиток строк, каждая из которых описывает слой блоков.
|
||||
Формат строк такой: `кол-во_слоёв;тип_блока`. Порядок строк такой: сверху нижние слои, а снизу - верхние.
|
||||
@@ -0,0 +1,55 @@
|
||||
package mc.world.simple;
|
||||
|
||||
import mc.core.world.block.BlockType;
|
||||
import mc.core.world.chunk.Chunk;
|
||||
import mc.core.world.chunk.ChunkProvider;
|
||||
import mc.core.world.chunk.ChunkSection;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class FlatChunkProvider implements ChunkProvider {
|
||||
private ChunkSection chunkSection;
|
||||
|
||||
public void setLayersBlockAsString(List<String> listOfLayers) {
|
||||
List<BlockType> layoutsBlock = new ArrayList<>();
|
||||
|
||||
for (String value : listOfLayers) {
|
||||
String[] splitValue = value.split(";");
|
||||
|
||||
BlockType blockType;
|
||||
try {
|
||||
blockType = BlockType.valueOf(splitValue[1]);
|
||||
} catch (IllegalArgumentException e) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (int i = 0; i < Integer.parseInt(splitValue[0]); i++) {
|
||||
layoutsBlock.add(blockType);
|
||||
}
|
||||
}
|
||||
|
||||
setLayersBlock(layoutsBlock);
|
||||
}
|
||||
|
||||
public void setLayersBlock(List<BlockType> layoutsBlock) {
|
||||
this.chunkSection = new SimpleChunkSection(layoutsBlock);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Chunk getChunk(int x, int z) {
|
||||
Chunk chunk = new SimpleChunk(x, z);
|
||||
chunk.setChunkSection(0, chunkSection);
|
||||
return chunk;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveChunk(Chunk chunk) {
|
||||
//FIXME nope...
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveChunk(Chunk... chunks) {
|
||||
//FIXME nope...
|
||||
}
|
||||
}
|
||||
@@ -1,29 +1,20 @@
|
||||
package mc.world.flat;
|
||||
package mc.world.simple;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import mc.core.world.Biome;
|
||||
import mc.core.world.World;
|
||||
import mc.core.world.chunk.Chunk;
|
||||
import mc.core.world.chunk.ChunkSection;
|
||||
|
||||
import java.lang.ref.Reference;
|
||||
import java.lang.ref.WeakReference;
|
||||
|
||||
@Slf4j
|
||||
@RequiredArgsConstructor
|
||||
public class SimpleChunk implements Chunk {
|
||||
@Getter
|
||||
private int x, z;
|
||||
private Reference<World> refWorld;
|
||||
private final int x, z;
|
||||
private ChunkSection chunkSection;
|
||||
private final Biome biome = Biome.PLAINS;
|
||||
|
||||
public SimpleChunk(int x, int z, World world) {
|
||||
this.x = x;
|
||||
this.z = z;
|
||||
setWorld(world);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChunkSection getChunkSection(int height) {
|
||||
return chunkSection;
|
||||
@@ -43,19 +34,4 @@ public class SimpleChunk implements Chunk {
|
||||
public void setBiome(int localX, int localZ, Biome biome) {
|
||||
// ignore
|
||||
}
|
||||
|
||||
@Override
|
||||
public World getWorld() {
|
||||
if (refWorld.get() == null) {
|
||||
log.error("World unloaded?");
|
||||
return null;
|
||||
} else {
|
||||
return refWorld.get();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setWorld(World world) {
|
||||
this.refWorld = new WeakReference<>(world);
|
||||
}
|
||||
}
|
||||
@@ -1,17 +1,21 @@
|
||||
/*
|
||||
* DmitriyMX <dimon550@gmail.com>
|
||||
* 2018-04-28
|
||||
*/
|
||||
package mc.world.flat;
|
||||
package mc.world.simple;
|
||||
|
||||
import mc.core.world.Biome;
|
||||
import mc.core.world.World;
|
||||
import mc.core.world.block.Block;
|
||||
import mc.core.world.block.BlockFactory;
|
||||
import mc.core.world.block.BlockType;
|
||||
import mc.core.world.chunk.ChunkSection;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class SimpleChunkSection implements ChunkSection {
|
||||
private final BlockFactory blockFactory = new BlockFactory();
|
||||
private final List<BlockType> layersBlock;
|
||||
|
||||
public SimpleChunkSection(List<BlockType> layersBlock) {
|
||||
this.layersBlock = layersBlock;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSkyLight(int x, int y, int z) {
|
||||
if (y <= 3) return 0;
|
||||
@@ -57,16 +61,20 @@ public class SimpleChunkSection implements ChunkSection {
|
||||
|
||||
@Override
|
||||
public Block getBlock(int x, int y, int z) {
|
||||
BlockFactory blockFactory = new BlockFactory();
|
||||
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;
|
||||
|
||||
if (y == 0) return blockFactory.create(BlockType.BEDROCK, x, y, z);
|
||||
else if (y >= 1 && y <= 2) return blockFactory.create(BlockType.DIRT, x, y, z);
|
||||
else if (y == 3) return blockFactory.create(BlockType.GRASS, x, y, z);
|
||||
else return blockFactory.create(BlockType.AIR, x, y, z);
|
||||
}
|
||||
if (y >= layersBlock.size()) {
|
||||
return blockFactory.create(BlockType.AIR, x, y, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public World getWorld() {
|
||||
return null;
|
||||
BlockType blockType = layersBlock.get(y);
|
||||
if (blockType == null) return blockFactory.create(BlockType.AIR, x, y, z);
|
||||
|
||||
return blockFactory.create(blockType, x, y, z);
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,4 @@
|
||||
/*
|
||||
* DmitriyMX <dimon550@gmail.com>
|
||||
* 2018-04-28
|
||||
*/
|
||||
package mc.world.flat;
|
||||
package mc.world.simple;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
@@ -11,37 +7,50 @@ import mc.core.EntityLocation;
|
||||
import mc.core.world.World;
|
||||
import mc.core.world.WorldType;
|
||||
import mc.core.world.chunk.Chunk;
|
||||
import mc.core.world.chunk.ChunkSection;
|
||||
import mc.core.world.chunk.ChunkProvider;
|
||||
import org.springframework.beans.factory.BeanNameAware;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
@Slf4j
|
||||
public class FlatWorld implements World {
|
||||
@Component
|
||||
public class SimpleWorld implements World, BeanNameAware {
|
||||
@Getter
|
||||
private final String name = "flat";
|
||||
private String name;
|
||||
@Getter
|
||||
private final WorldType worldType = WorldType.FLAT;
|
||||
@Setter
|
||||
private EntityLocation spawn;
|
||||
private ChunkSection chunkSection = new SimpleChunkSection();
|
||||
@Setter
|
||||
private ChunkProvider chunkProvider;
|
||||
|
||||
@Override
|
||||
public EntityLocation getSpawn() {
|
||||
if (this.spawn == null) {
|
||||
log.warn("Spawn is not defined! Set spawn [0, 6, 0]");
|
||||
this.spawn = new EntityLocation(0d, 6d, 0d, 0f, 0f);
|
||||
setSpawn(0d, 6d, 0d);
|
||||
}
|
||||
|
||||
return this.spawn;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSpawn(EntityLocation location) {
|
||||
this.spawn = location;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Chunk getChunk(int x, int z) {
|
||||
Chunk chunk = new SimpleChunk(x, z, this);
|
||||
chunk.setChunkSection(0, chunkSection);
|
||||
return chunk;
|
||||
return chunkProvider.getChunk(x, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setChunk(int x, int z, Chunk chunk) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBeanName(@Nonnull String name) {
|
||||
this.name = name;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
package mc.world.simple;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import mc.core.world.block.Block;
|
||||
import mc.core.world.block.BlockType;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
class SimpleChunkSectionTest {
|
||||
private SimpleChunkSection chunkSection;
|
||||
private List<BlockType> layersBlock;
|
||||
|
||||
@BeforeEach
|
||||
void before() {
|
||||
layersBlock = Lists.newArrayList(
|
||||
BlockType.BEDROCK,
|
||||
BlockType.DIRT,
|
||||
BlockType.DIRT,
|
||||
BlockType.GRASS
|
||||
);
|
||||
|
||||
chunkSection = new SimpleChunkSection(layersBlock);
|
||||
}
|
||||
|
||||
@Test
|
||||
void getBlock() {
|
||||
for (int y = 15; y >= 0; y--) {
|
||||
for (int x = 0; x < 16; x++) {
|
||||
for (int z = 0; z < 16; z++) {
|
||||
Block block = chunkSection.getBlock(x, y, z);
|
||||
if (y > layersBlock.size()-1) {
|
||||
assertEquals(block.getBlockType(), BlockType.AIR);
|
||||
} else {
|
||||
assertEquals(block.getBlockType(), layersBlock.get(y));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
package mc.world.simple;
|
||||
|
||||
import mc.core.EntityLocation;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.test.annotation.DirtiesContext;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit.jupiter.SpringExtension;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
@ExtendWith(SpringExtension.class)
|
||||
@ContextConfiguration(classes = {TestSpringConfig.class})
|
||||
@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_EACH_TEST_METHOD)
|
||||
class SimpleWorldTest {
|
||||
@Autowired
|
||||
private SimpleWorld world;
|
||||
|
||||
@Test
|
||||
void spawn() {
|
||||
final EntityLocation location = new EntityLocation(1d, 2d, 3d,4f, 5f);
|
||||
|
||||
world.setSpawn(location);
|
||||
assertEquals(location, world.getSpawn());
|
||||
assertSame(location, world.getSpawn());
|
||||
|
||||
world.setSpawn(1d, 2d, 3d, 4f, 5f);
|
||||
assertEquals(location, world.getSpawn());
|
||||
assertNotSame(location, world.getSpawn());
|
||||
|
||||
location.setYawPitch(0, 0);
|
||||
world.setSpawn(1d, 2d, 3d);
|
||||
assertEquals(location, world.getSpawn());
|
||||
assertNotSame(location, world.getSpawn());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package mc.world.simple;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import mc.core.world.block.BlockType;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.ComponentScan;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Configuration
|
||||
@ComponentScan("mc.world.simple")
|
||||
public class TestSpringConfig {
|
||||
@Bean
|
||||
public List<BlockType> layersBlock() {
|
||||
return Lists.newArrayList(
|
||||
BlockType.BEDROCK,
|
||||
BlockType.DIRT,
|
||||
BlockType.DIRT,
|
||||
BlockType.GRASS
|
||||
);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public SimpleChunkSection chunkSection(List<BlockType> layersBlock) {
|
||||
return new SimpleChunkSection(layersBlock);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public SimpleWorld simpleWorld(List<BlockType> layersBlock) {
|
||||
FlatChunkProvider chunkProvider = new FlatChunkProvider();
|
||||
chunkProvider.setLayersBlock(layersBlock);
|
||||
|
||||
SimpleWorld world = new SimpleWorld();
|
||||
world.setChunkProvider(chunkProvider);
|
||||
return world;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user