Merge branch 'proto_1.12.2' into world
This commit is contained in:
85
core/src/main/java/mc/core/CoreEventListener.java
Normal file
85
core/src/main/java/mc/core/CoreEventListener.java
Normal file
@@ -0,0 +1,85 @@
|
||||
package mc.core;
|
||||
|
||||
import com.google.common.eventbus.Subscribe;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import mc.core.eventbus.EventBusGetter;
|
||||
import mc.core.eventbus.events.CS_PlayerMoveEvent;
|
||||
import mc.core.eventbus.events.SC_ChunkLoadEvent;
|
||||
import mc.core.eventbus.events.SC_ChunkUnloadEvent;
|
||||
import mc.core.utils.CompactedCoords;
|
||||
import mc.core.world.chunk.Chunk;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
import java.util.Iterator;
|
||||
|
||||
@Slf4j
|
||||
public class CoreEventListener {
|
||||
@PostConstruct
|
||||
public void registerEventHandlers() {
|
||||
EventBusGetter.getInstance().register(this);
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void handlerPlayerMoveEvent(CS_PlayerMoveEvent event) {
|
||||
log.trace("(GameLoop) playerMoveEventHandler()");
|
||||
|
||||
Chunk chunk;
|
||||
chunk = event.getPlayer().getWorld().getChunk(event.getOldLocation()); // Old chunk
|
||||
int ccX = chunk.getX();
|
||||
int ccZ = chunk.getZ();
|
||||
chunk = event.getPlayer().getWorld().getChunk(event.getNewLocation()); // Next chunk
|
||||
int ncX = chunk.getX();
|
||||
int ncZ = chunk.getZ();
|
||||
|
||||
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.getInstance().post(eventChunkUnload);
|
||||
}
|
||||
|
||||
SC_ChunkLoadEvent eventChunkLoad = new SC_ChunkLoadEvent(event.getPlayer());
|
||||
for (int cZ = cMinZ; cZ <= cMaxZ; cZ++) {
|
||||
for (int cX = cMinX; cX <= cMaxX; cX++) {
|
||||
int compressXZ = CompactedCoords.compressXZ(cX, cZ);
|
||||
if (!event.getPlayer().getLoadedChunks().contains(compressXZ)) {
|
||||
if (!event.getPlayer().getLoadedChunks().contains(compressXZ)) {
|
||||
eventChunkLoad.getNeedLoadChunks().add(compressXZ);
|
||||
event.getPlayer().getLoadedChunks().add(compressXZ);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!eventChunkLoad.getNeedLoadChunks().isEmpty()) {
|
||||
EventBusGetter.getInstance().post(eventChunkLoad);
|
||||
}
|
||||
}
|
||||
|
||||
event.getPlayer().getLocation().setXYZ(
|
||||
event.getNewLocation().getX(),
|
||||
event.getNewLocation().getY(),
|
||||
event.getNewLocation().getZ()
|
||||
);
|
||||
|
||||
// TODO отсылать клиенту только(!) для корректировки позиции
|
||||
// SC_PlayerMoveEvent nextEvent = new SC_PlayerMoveEvent(event.getPlayer());
|
||||
// nextEvent.setNewLocation(event.getNewLocation());
|
||||
// EventBusGetter.INSTANCE.post(nextEvent);
|
||||
}
|
||||
}
|
||||
@@ -1,29 +1,29 @@
|
||||
/*
|
||||
* DmitriyMX <dimon550@gmail.com>
|
||||
* 2018-08-08
|
||||
*/
|
||||
package mc.core;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import mc.core.exception.ResourceUnloadedException;
|
||||
import mc.core.world.World;
|
||||
import mc.core.world.chunk.Chunk;
|
||||
import mc.core.world.chunk.ChunkSection;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.lang.ref.Reference;
|
||||
import java.lang.ref.WeakReference;
|
||||
|
||||
public class EntityLocation extends Location implements Cloneable {
|
||||
@Getter
|
||||
@Setter
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Data
|
||||
public class EntityLocation implements Cloneable {
|
||||
private double x, y, z;
|
||||
private float yaw, pitch;
|
||||
private Reference<World> refWorld;
|
||||
|
||||
public EntityLocation(double x, double y, double z, float yaw, float pitch, World world) {
|
||||
super(x, y, z);
|
||||
setYawPitch(yaw, pitch);
|
||||
setWorld(world);
|
||||
public static EntityLocation ZERO() {
|
||||
return new EntityLocation(0d,0d,0d,0f,0f);
|
||||
}
|
||||
|
||||
public void set(EntityLocation location) {
|
||||
setXYZ(location.x, location.y, location.z);
|
||||
setYawPitch(location.yaw, location.pitch);
|
||||
}
|
||||
|
||||
public void setXYZ(double x, double y, double z) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.z = z;
|
||||
}
|
||||
|
||||
public void setYawPitch(float yaw, float pitch) {
|
||||
@@ -31,44 +31,25 @@ public class EntityLocation extends Location implements Cloneable {
|
||||
this.pitch = pitch;
|
||||
}
|
||||
|
||||
public void setYawPitch(EntityLocation entityLocation) {
|
||||
setYawPitch(entityLocation.yaw, entityLocation.pitch);
|
||||
public int getBlockX() {
|
||||
return Double.valueOf(Math.floor(x)).intValue();
|
||||
}
|
||||
|
||||
public World getWorld() {
|
||||
if (refWorld == null) {
|
||||
return null;
|
||||
} else if (refWorld.get() == null) {
|
||||
throw new ResourceUnloadedException("World unloaded");
|
||||
} else {
|
||||
return refWorld.get();
|
||||
}
|
||||
public int getBlockY() {
|
||||
return Double.valueOf(Math.floor(y)).intValue();
|
||||
}
|
||||
|
||||
public void setWorld (World world) {
|
||||
this.refWorld = new WeakReference<>(world);
|
||||
}
|
||||
|
||||
public Chunk getChunk() {
|
||||
World world = getWorld();
|
||||
if (world == null) {
|
||||
return null;
|
||||
} else {
|
||||
return world.getChunk(getBlockX() >> 4, getBlockZ() >> 4);
|
||||
}
|
||||
}
|
||||
|
||||
public ChunkSection getChunkSection() {
|
||||
Chunk chunk = getChunk();
|
||||
if (chunk == null) {
|
||||
return null;
|
||||
} else {
|
||||
return chunk.getChunkSection(getBlockY() >> 4);
|
||||
}
|
||||
public int getBlockZ() {
|
||||
return Double.valueOf(Math.floor(z)).intValue();
|
||||
}
|
||||
|
||||
@Override
|
||||
public EntityLocation clone() {
|
||||
return (EntityLocation) super.clone();
|
||||
try {
|
||||
return (EntityLocation) super.clone();
|
||||
} catch (CloneNotSupportedException e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,22 +4,12 @@
|
||||
*/
|
||||
package mc.core;
|
||||
|
||||
import com.google.common.eventbus.Subscribe;
|
||||
import lombok.Setter;
|
||||
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;
|
||||
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,77 +38,16 @@ public class GameLoop extends Thread {
|
||||
TPS_WATCHER.setTraceTPS(value);
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void playerMoveEventHandler(CS_PlayerMoveEvent event) {
|
||||
log.trace("(GameLoop) playerMoveEventHandler()");
|
||||
|
||||
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() + 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++) {
|
||||
int compressXZ = CompactedCoords.compressXZ(cX, cZ);
|
||||
if (!event.getPlayer().getLoadedChunks().contains(compressXZ)) {
|
||||
if (!event.getPlayer().getLoadedChunks().contains(compressXZ)) {
|
||||
eventChunkLoad.getNeedLoadChunks().add(compressXZ);
|
||||
event.getPlayer().getLoadedChunks().add(compressXZ);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!eventChunkLoad.getNeedLoadChunks().isEmpty()) {
|
||||
EventBusGetter.INSTANCE.post(eventChunkLoad);
|
||||
}
|
||||
}
|
||||
|
||||
event.getPlayer().getLocation().setXYZ(event.getNewLocation());
|
||||
|
||||
// TODO отсылать клиенту только(!) для корректировки позиции
|
||||
// SC_PlayerMoveEvent nextEvent = new SC_PlayerMoveEvent(event.getPlayer());
|
||||
// nextEvent.setNewLocation(event.getNewLocation());
|
||||
// EventBusGetter.INSTANCE.post(nextEvent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
TPS_WATCHER.startWatch();
|
||||
|
||||
EventBusGetter.INSTANCE.register(this);
|
||||
|
||||
while (!isInterrupted()) {
|
||||
TPS_WATCHER.check();
|
||||
|
||||
/* --- --- --- */
|
||||
|
||||
/* TODO нужно перенести этот функционал на Network */
|
||||
playerManager.getBroadcastChannel().sendTimeUpdate(
|
||||
gameTimer.getGameTime(),
|
||||
gameTimer.getWorldAge()
|
||||
|
||||
57
core/src/main/java/mc/core/ImmutableEntityLocation.java
Normal file
57
core/src/main/java/mc/core/ImmutableEntityLocation.java
Normal file
@@ -0,0 +1,57 @@
|
||||
package mc.core;
|
||||
|
||||
public class ImmutableEntityLocation extends EntityLocation {
|
||||
public ImmutableEntityLocation(double x, double y, double z, float yaw, float pitch) {
|
||||
super(x, y, z, yaw, pitch);
|
||||
}
|
||||
|
||||
public ImmutableEntityLocation(EntityLocation location) {
|
||||
this(
|
||||
location.getX(),
|
||||
location.getY(),
|
||||
location.getZ(),
|
||||
location.getYaw(),
|
||||
location.getPitch()
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setX(double x) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setY(double y) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setZ(double z) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setYaw(float yaw) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPitch(float pitch) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void set(EntityLocation location) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setXYZ(double x, double y, double z) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setYawPitch(float yaw, float pitch) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
||||
@@ -1,50 +0,0 @@
|
||||
/*
|
||||
* DmitriyMX <dimon550@gmail.com>
|
||||
* 2018-08-08
|
||||
*/
|
||||
package mc.core;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
public class Location implements Cloneable {
|
||||
@Getter
|
||||
@Setter
|
||||
private double x, y, z;
|
||||
|
||||
public Location (double x, double y, double z) {
|
||||
setXYZ(x, y, z);
|
||||
}
|
||||
|
||||
public void setXYZ(double x, double y, double z) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.z = z;
|
||||
}
|
||||
|
||||
public void setXYZ(Location location) {
|
||||
setXYZ(location.x, location.y, location.z);
|
||||
}
|
||||
|
||||
public int getBlockX() {
|
||||
return Double.valueOf(Math.floor(x)).intValue();
|
||||
}
|
||||
|
||||
public int getBlockY() {
|
||||
return Double.valueOf(Math.floor(y)).intValue();
|
||||
}
|
||||
|
||||
public int getBlockZ() {
|
||||
return Double.valueOf(Math.floor(z)).intValue();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Location clone() {
|
||||
try {
|
||||
return (Location) super.clone();
|
||||
} catch (CloneNotSupportedException e) { // такое в нашем случае вообще возможно?
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,3 @@
|
||||
/*
|
||||
* DmitriyMX <dimon550@gmail.com>
|
||||
* 2018-06-29
|
||||
*/
|
||||
package mc.core.embedded;
|
||||
|
||||
import mc.core.EntityLocation;
|
||||
@@ -12,8 +8,7 @@ import mc.core.player.Player;
|
||||
import mc.core.player.PlayerManager;
|
||||
import mc.core.text.Text;
|
||||
import mc.core.text.Title;
|
||||
import mc.core.world.chunk.Chunk;
|
||||
import mc.core.world.chunk.ChunkSection;
|
||||
import mc.core.world.World;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
@@ -21,9 +16,6 @@ import java.util.Optional;
|
||||
|
||||
public class FakePlayerManager implements PlayerManager {
|
||||
public static class FakeNetChannet implements NetChannel {
|
||||
@Override
|
||||
public void sendKeepAlive() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendTimeUpdate(long time, long age) {
|
||||
@@ -53,7 +45,7 @@ public class FakePlayerManager implements PlayerManager {
|
||||
private static final NetChannel FAKE_NET_CHANNEL = new FakeNetChannet();
|
||||
|
||||
@Override
|
||||
public Player createPlayer(String name, EntityLocation defaultLocation) {
|
||||
public Player createPlayer(String name, EntityLocation location, World world) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -66,13 +58,8 @@ public class FakePlayerManager implements PlayerManager {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<Player> getPlayer(String name) {
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<Player> getPlayerById(int id) {
|
||||
return Optional.empty();
|
||||
public Player getPlayer(String name) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -81,7 +68,7 @@ public class FakePlayerManager implements PlayerManager {
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCountOnlinePlayers() {
|
||||
public int getCountPlayers() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -89,4 +76,9 @@ public class FakePlayerManager implements PlayerManager {
|
||||
public NetChannel getBroadcastChannel() {
|
||||
return FAKE_NET_CHANNEL;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Player getOfflinePlayer(String name) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* DmitriyMX <dimon550@gmail.com>
|
||||
* 2018-05-02
|
||||
*/
|
||||
package mc.core.events;
|
||||
package mc.core.eventbus;
|
||||
|
||||
public interface Event {
|
||||
void setCanceled(boolean value);
|
||||
@@ -2,7 +2,7 @@
|
||||
* DmitriyMX <dimon550@gmail.com>
|
||||
* 2018-05-02
|
||||
*/
|
||||
package mc.core.events;
|
||||
package mc.core.eventbus;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
@@ -2,12 +2,14 @@
|
||||
* DmitriyMX <dimon550@gmail.com>
|
||||
* 2018-05-02
|
||||
*/
|
||||
package mc.core.events;
|
||||
package mc.core.eventbus;
|
||||
|
||||
import com.google.common.eventbus.EventBus;
|
||||
import lombok.Getter;
|
||||
|
||||
public final class EventBusGetter {
|
||||
public static final EventBus INSTANCE = new EventBus();
|
||||
@Getter
|
||||
private static final EventBus instance = new EventBus();
|
||||
|
||||
private EventBusGetter() {
|
||||
}
|
||||
@@ -2,22 +2,26 @@
|
||||
* DmitriyMX <dimon550@gmail.com>
|
||||
* 2018-05-02
|
||||
*/
|
||||
package mc.core.events;
|
||||
package mc.core.eventbus.events;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.Setter;
|
||||
import mc.core.EntityLocation;
|
||||
import mc.core.ImmutableEntityLocation;
|
||||
import mc.core.eventbus.EventBase;
|
||||
import mc.core.player.Player;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
@Getter
|
||||
public class CS_PlayerMoveEvent extends EventBase {
|
||||
private final Player player;
|
||||
private final EntityLocation oldLocation; // TODO сомнительное решение
|
||||
// вообще нужно будет создать реализацию "иммутабл локейшен" для подобных ситуаций
|
||||
private final ImmutableEntityLocation oldLocation;
|
||||
@Setter
|
||||
private EntityLocation newLocation;
|
||||
@Setter
|
||||
private boolean recalcChunk = false;
|
||||
|
||||
public CS_PlayerMoveEvent(Player player, EntityLocation oldLocation) {
|
||||
this.player = player;
|
||||
this.oldLocation = new ImmutableEntityLocation(oldLocation);
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,8 @@
|
||||
package mc.core.events;
|
||||
package mc.core.eventbus.events;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import mc.core.eventbus.EventBase;
|
||||
import mc.core.player.Player;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@@ -1,7 +1,8 @@
|
||||
package mc.core.events;
|
||||
package mc.core.eventbus.events;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import mc.core.eventbus.EventBase;
|
||||
import mc.core.player.Player;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@@ -2,18 +2,19 @@
|
||||
* DmitriyMX <dimon550@gmail.com>
|
||||
* 2018-05-02
|
||||
*/
|
||||
package mc.core.events;
|
||||
package mc.core.eventbus.events;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.Setter;
|
||||
import mc.core.eventbus.EventBase;
|
||||
|
||||
import java.net.SocketAddress;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
@Getter
|
||||
@Setter
|
||||
public class LoginEvent extends EventBase {
|
||||
public class SC_LoginEvent extends EventBase {
|
||||
private String playerName;
|
||||
private final SocketAddress remoteAddress;
|
||||
private boolean deny;
|
||||
@@ -2,18 +2,19 @@
|
||||
* DmitriyMX <dimon550@gmail.com>
|
||||
* 2018-05-02
|
||||
*/
|
||||
package mc.core.events;
|
||||
package mc.core.eventbus.events;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.Setter;
|
||||
import mc.core.EntityLocation;
|
||||
import mc.core.eventbus.EventBase;
|
||||
import mc.core.player.Player;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
@Getter
|
||||
@Setter
|
||||
public class PlayerLookEvent extends EventBase {
|
||||
public class SC_PlayerLookEvent extends EventBase {
|
||||
private final Player player;
|
||||
private EntityLocation newLook;
|
||||
}
|
||||
@@ -1,9 +1,10 @@
|
||||
package mc.core.events;
|
||||
package mc.core.eventbus.events;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.Setter;
|
||||
import mc.core.EntityLocation;
|
||||
import mc.core.eventbus.EventBase;
|
||||
import mc.core.player.Player;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
@@ -2,18 +2,19 @@
|
||||
* DmitriyMX <dimon550@gmail.com>
|
||||
* 2018-05-02
|
||||
*/
|
||||
package mc.core.events;
|
||||
package mc.core.eventbus.events;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.Setter;
|
||||
import mc.core.eventbus.EventBase;
|
||||
|
||||
import java.net.SocketAddress;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
@Getter
|
||||
@Setter
|
||||
public class ServerPingEvent extends EventBase {
|
||||
public class SC_ServerPingEvent extends EventBase {
|
||||
private final SocketAddress remoteAddress;
|
||||
private String description;
|
||||
private int online;
|
||||
@@ -16,11 +16,6 @@ import java.util.stream.Stream;
|
||||
public class BroadcastNetChannel implements NetChannel {
|
||||
private final Stream<Player> playerStream;
|
||||
|
||||
@Override
|
||||
public void sendKeepAlive() {
|
||||
playerStream.forEach(player -> player.getChannel().sendKeepAlive());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendTimeUpdate(final long time, final long age) {
|
||||
playerStream.forEach(player -> player.getChannel().sendTimeUpdate(time, age));
|
||||
|
||||
@@ -9,7 +9,6 @@ import mc.core.text.Text;
|
||||
import mc.core.text.Title;
|
||||
|
||||
public interface NetChannel {
|
||||
void sendKeepAlive();
|
||||
void sendTimeUpdate(long time, long age);
|
||||
default void sendChatMessage(Text text) {
|
||||
sendChatMessage(text, MessageType.CHAT_MESSAGE);
|
||||
|
||||
@@ -22,6 +22,7 @@ public abstract class NetInputStream {
|
||||
public abstract short readShort();
|
||||
public abstract int readInt();
|
||||
public abstract int readVarInt();
|
||||
public abstract int readVarInt(int[] countReadBytes);
|
||||
public abstract long readLong();
|
||||
public abstract float readFloat();
|
||||
public abstract double readDouble();
|
||||
|
||||
@@ -1,112 +0,0 @@
|
||||
/*
|
||||
* DmitriyMX <dimon550@gmail.com>
|
||||
* 2018-04-15
|
||||
*/
|
||||
package mc.core.player;
|
||||
|
||||
import lombok.Setter;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import mc.core.Config;
|
||||
import mc.core.EntityLocation;
|
||||
import mc.core.network.BroadcastNetChannel;
|
||||
import mc.core.network.NetChannel;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Slf4j
|
||||
public class InMemoryPlayerManager implements PlayerManager, Runnable {
|
||||
private static final Random rand = new Random();
|
||||
private List<Player> players;
|
||||
private final Object lock = new Object();
|
||||
@Setter
|
||||
private int keepAliveInterval = 1;
|
||||
|
||||
@Autowired
|
||||
public InMemoryPlayerManager(Config config) {
|
||||
final int c = config.getMaxPlayers() > 50 ? 50 : config.getMaxPlayers();
|
||||
players = Collections.synchronizedList(new ArrayList<>(c));
|
||||
(new Thread(this, "KeepAlive")).start();
|
||||
}
|
||||
|
||||
@Override
|
||||
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().setXYZ(defaultLocation);
|
||||
player.getLocation().setYawPitch(defaultLocation);
|
||||
player.getLocation().setWorld(defaultLocation.getWorld());
|
||||
player.setSettings(new PlayerSettings());
|
||||
|
||||
synchronized (lock) {
|
||||
players.add(player);
|
||||
lock.notify();
|
||||
}
|
||||
return player;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void joinServer(Player player) {
|
||||
((SimplePlayer) player).setOnline(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void leftServer(Player player) {
|
||||
((SimplePlayer) player).setOnline(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<Player> getPlayer(final String name) {
|
||||
return players.stream()
|
||||
.filter(player -> player.getName().equalsIgnoreCase(name))
|
||||
.findFirst();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<Player> getPlayerById(final int id) {
|
||||
return players.stream()
|
||||
.filter(player -> player.getId() == id)
|
||||
.findFirst();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Player> getPlayers() {
|
||||
return players.stream().filter(Player::isOnline).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCountOnlinePlayers() {
|
||||
return (int) players.stream().filter(Player::isOnline).count();
|
||||
}
|
||||
|
||||
@Override
|
||||
public NetChannel getBroadcastChannel() {
|
||||
return new BroadcastNetChannel(players.stream().filter(Player::isOnline));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
while (!Thread.currentThread().isInterrupted()) {
|
||||
synchronized (lock) {
|
||||
while (players.size() == 0) {
|
||||
try {
|
||||
lock.wait();
|
||||
} catch (InterruptedException e) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
getBroadcastChannel().sendKeepAlive();
|
||||
|
||||
try {
|
||||
Thread.sleep(keepAliveInterval);
|
||||
} catch (InterruptedException e) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6,13 +6,14 @@ package mc.core.player;
|
||||
|
||||
import mc.core.EntityLocation;
|
||||
import mc.core.network.NetChannel;
|
||||
import mc.core.world.World;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
public interface Player {
|
||||
int getId();
|
||||
UUID getUUID();
|
||||
UUID getUuid();
|
||||
String getName();
|
||||
boolean isOnline();
|
||||
|
||||
@@ -23,7 +24,8 @@ public interface Player {
|
||||
void setChannel(NetChannel channel);
|
||||
|
||||
EntityLocation getLocation();
|
||||
//TODO надо определиться - нужно ли здесь setLocation() или нет
|
||||
World getWorld();
|
||||
void setWorld(World world);
|
||||
|
||||
boolean isFlying();
|
||||
void setFlying(boolean value);
|
||||
|
||||
@@ -1,22 +1,20 @@
|
||||
/*
|
||||
* DmitriyMX <dimon550@gmail.com>
|
||||
* 2018-04-15
|
||||
*/
|
||||
package mc.core.player;
|
||||
|
||||
import mc.core.EntityLocation;
|
||||
import mc.core.network.NetChannel;
|
||||
import mc.core.world.World;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
public interface PlayerManager {
|
||||
Player createPlayer(String name, EntityLocation defaultLocation);
|
||||
Player createPlayer(String name, EntityLocation location, World world);
|
||||
void joinServer(Player player);
|
||||
void leftServer(Player player);
|
||||
Optional<Player> getPlayer(String name);
|
||||
Optional<Player> getPlayerById(int id);
|
||||
|
||||
Player getPlayer(String name);
|
||||
List<Player> getPlayers();
|
||||
int getCountOnlinePlayers();
|
||||
int getCountPlayers();
|
||||
NetChannel getBroadcastChannel();
|
||||
|
||||
Player getOfflinePlayer(String name);
|
||||
}
|
||||
|
||||
@@ -1,40 +0,0 @@
|
||||
/*
|
||||
* DmitriyMX <dimon550@gmail.com>
|
||||
* 2018-04-23
|
||||
*/
|
||||
package mc.core.player;
|
||||
|
||||
import lombok.Data;
|
||||
import mc.core.EntityLocation;
|
||||
import mc.core.network.NetChannel;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
@Data
|
||||
public class SimplePlayer implements Player {
|
||||
private int id;
|
||||
private UUID uuid;
|
||||
private String name;
|
||||
private boolean online = false;
|
||||
private NetChannel channel;
|
||||
private EntityLocation location = new EntityLocation(0d, 0d, 0d, 0f, 0f, null);
|
||||
private boolean flying = false;
|
||||
private PlayerSettings settings;
|
||||
private List<Integer> loadedChunks = new ArrayList<>();
|
||||
|
||||
public void setLocation(EntityLocation location) {
|
||||
this.location.setXYZ(location);
|
||||
this.location.setYawPitch(location);
|
||||
}
|
||||
|
||||
@Override
|
||||
public UUID getUUID() {
|
||||
return uuid;
|
||||
}
|
||||
|
||||
public void setUUID(UUID uuid) {
|
||||
this.uuid = uuid;
|
||||
}
|
||||
}
|
||||
@@ -1,20 +1,11 @@
|
||||
/*
|
||||
* DmitriyMX <dimon550@gmail.com>
|
||||
* 2018-06-11
|
||||
*/
|
||||
package mc.core.text;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.Getter;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.StringJoiner;
|
||||
import java.util.*;
|
||||
|
||||
@Getter
|
||||
@EqualsAndHashCode
|
||||
public class Text {
|
||||
private static final Text EMPTY = new Text();
|
||||
private static final Text NEW_LINE = new Text("\n", null, null, null);
|
||||
@@ -39,7 +30,7 @@ public class Text {
|
||||
}
|
||||
|
||||
public boolean isEmpty() {
|
||||
boolean result = content.isEmpty();
|
||||
boolean result = (content == null || content.isEmpty());
|
||||
|
||||
if (children != null && !children.isEmpty()) {
|
||||
for (Text child : children) {
|
||||
@@ -60,6 +51,19 @@ public class Text {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
Text text = (Text) o;
|
||||
return Objects.equals(toPlain(), text.toPlain());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(toPlain());
|
||||
}
|
||||
|
||||
public static class Builder {
|
||||
@Getter
|
||||
private String content;
|
||||
@@ -81,6 +85,8 @@ public class Text {
|
||||
}
|
||||
|
||||
public Builder(Object... objects) {
|
||||
this.children = new ArrayList<>();
|
||||
|
||||
for(Object obj : objects) {
|
||||
if (obj instanceof String) {
|
||||
if (this.content == null) {
|
||||
@@ -96,10 +102,10 @@ public class Text {
|
||||
}
|
||||
} else if (obj instanceof TextColor) {
|
||||
this.color = (TextColor) obj;
|
||||
} else if (obj instanceof Text) {
|
||||
children.add((Text) obj);
|
||||
}
|
||||
}
|
||||
|
||||
this.children = new ArrayList<>();
|
||||
}
|
||||
|
||||
public List<Text> getChildren() {
|
||||
@@ -133,8 +139,14 @@ public class Text {
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder append(String string) {
|
||||
return append(Text.of(string));
|
||||
}
|
||||
|
||||
public Builder append(Text child) {
|
||||
this.children.add(child);
|
||||
if (child != null) {
|
||||
this.children.add(child);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -144,16 +156,20 @@ public class Text {
|
||||
}
|
||||
|
||||
public Text build() {
|
||||
if (children.isEmpty()) {
|
||||
if (children.isEmpty() && (content == null || content.isEmpty())) {
|
||||
return Text.EMPTY;
|
||||
}
|
||||
|
||||
return new Text(
|
||||
content,
|
||||
color,
|
||||
style,
|
||||
ImmutableList.copyOf(children)
|
||||
);
|
||||
if (children.size() == 1 && children.get(0) != null) {
|
||||
return children.get(0);
|
||||
} else {
|
||||
return new Text(
|
||||
content,
|
||||
color,
|
||||
style,
|
||||
ImmutableList.copyOf(children)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -25,18 +25,4 @@ public class CompactedCoords {
|
||||
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?
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,9 +5,11 @@
|
||||
package mc.core.world;
|
||||
|
||||
import mc.core.EntityLocation;
|
||||
import mc.core.world.block.BlockLocation;
|
||||
import mc.core.world.chunk.Chunk;
|
||||
|
||||
public interface World {
|
||||
String getName();
|
||||
WorldType getWorldType();
|
||||
|
||||
EntityLocation getSpawn();
|
||||
@@ -18,4 +20,12 @@ public interface World {
|
||||
|
||||
Chunk getChunk(int x, int z);
|
||||
void setChunk(int x, int z, Chunk chunkSection);
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,6 @@ package mc.core.world.block;
|
||||
import com.flowpowered.nbt.Tag;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import mc.core.Location;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
@@ -12,7 +11,7 @@ import java.util.stream.Stream;
|
||||
public abstract class AbstractBlock implements Block {
|
||||
@Getter
|
||||
@Setter
|
||||
private Location location;
|
||||
private BlockLocation location;
|
||||
@Getter
|
||||
private int light = 0;
|
||||
@Getter
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
package mc.core.world.block;
|
||||
|
||||
import mc.core.Location;
|
||||
import mc.core.nbt.Taggable;
|
||||
|
||||
public interface Block extends Taggable{
|
||||
int getLight();
|
||||
void setLight(int light);
|
||||
BlockType getBlockType();
|
||||
Location getLocation();
|
||||
BlockLocation getLocation();
|
||||
}
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
package mc.core.world.block;
|
||||
|
||||
import mc.core.Location;
|
||||
import mc.core.world.World;
|
||||
|
||||
public class BlockFactory {
|
||||
|
||||
public Block create(BlockType blockType, int x, int y, int z) {
|
||||
@@ -13,7 +10,7 @@ public class BlockFactory {
|
||||
private class EmbeddedBlock extends AbstractBlock {
|
||||
EmbeddedBlock(BlockType type, int x, int y, int z) {
|
||||
super(type);
|
||||
setLocation(new Location(x, y, z));
|
||||
setLocation(new BlockLocation(x, y, z));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
30
core/src/main/java/mc/core/world/block/BlockLocation.java
Normal file
30
core/src/main/java/mc/core/world/block/BlockLocation.java
Normal file
@@ -0,0 +1,30 @@
|
||||
package mc.core.world.block;
|
||||
|
||||
import lombok.*;
|
||||
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Data
|
||||
public class BlockLocation implements Cloneable {
|
||||
private int x, y, z;
|
||||
|
||||
public static BlockLocation ZERO() {
|
||||
return new BlockLocation(0,0,0);
|
||||
}
|
||||
|
||||
public void setXYZ(int x, int y, int z) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.z = z;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockLocation clone() {
|
||||
try {
|
||||
return (BlockLocation) super.clone();
|
||||
} catch (CloneNotSupportedException e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user