diff --git a/src/main/java/mc/core/GameLoop.java b/src/main/java/mc/core/GameLoop.java index 66265e2..d50f7c9 100644 --- a/src/main/java/mc/core/GameLoop.java +++ b/src/main/java/mc/core/GameLoop.java @@ -8,20 +8,29 @@ import lombok.Setter; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; +import java.util.Calendar; + @Slf4j public class GameLoop extends Thread { @Autowired PlayerManager playerManager; + + /* TPS */ private int tps; private long pause; @Setter private boolean traceTPS = false; private int lowTps; + /* Time */ + private long gameTime; + private Runnable gameTimeUpdateFunc; + public GameLoop() { super(); setTps(20); setPercentWarnLowTps(5); + setStartGameTime(0); } public void setPercentWarnLowTps(int value) { @@ -42,6 +51,42 @@ public class GameLoop extends Thread { this.pause = (1000 / tps); } + public void setStartGameTime(long value) { + this.gameTime = value; + } + + public void setTimeMode(String mode) { + if (mode.equals("0") || mode.equalsIgnoreCase("idle")) { + gameTimeUpdateFunc = () -> {}; + } else if (mode.equalsIgnoreCase("realtime")) { + gameTimeUpdateFunc = () -> { + final long DIFF = 21600L; + final long HOUR24 = 86400L; + final long SYSTIME = System.currentTimeMillis(); + + Calendar calendar = Calendar.getInstance(); + calendar.setTimeInMillis(SYSTIME); + calendar.set(Calendar.HOUR_OF_DAY, 0); + calendar.set(Calendar.MINUTE, 0); + calendar.set(Calendar.SECOND, 0); + calendar.set(Calendar.MILLISECOND, 0); + + long time = (SYSTIME - calendar.getTimeInMillis())/1000; + if (time < DIFF) time += HOUR24; + + gameTime = (long) ((time - DIFF) / 3.6); + }; + } else { + if (!mode.equalsIgnoreCase("normal")) { + log.warn("Unknown time mode: {}. Set normal mode", mode); + } + gameTimeUpdateFunc = () -> { + gameTime++; + if (gameTime > 24000) gameTime = 0; + }; + } + } + @Override public void run() { log.info("Target TPS: {}; Low TPS: {}", tps, lowTps); @@ -61,11 +106,20 @@ public class GameLoop extends Thread { long futureTime = System.currentTimeMillis() + pause; - // code there // + /* --- --- --- */ + + gameTimeUpdateFunc.run(); + + /* --- --- --- */ + + playerManager.getBroadcastChannel().sendTimeUpdate(gameTime); + + /* --- --- --- */ factTps++; try { - Thread.sleep(futureTime - System.currentTimeMillis()); + long pause = futureTime - System.currentTimeMillis(); + Thread.sleep((pause <= 0 ? 0 : pause)); } catch (InterruptedException ignored) { } } diff --git a/src/main/java/mc/core/PlayerManager.java b/src/main/java/mc/core/PlayerManager.java index ad2a44b..ab28208 100644 --- a/src/main/java/mc/core/PlayerManager.java +++ b/src/main/java/mc/core/PlayerManager.java @@ -4,12 +4,12 @@ */ package mc.core; -import mc.core.network.SCPacket; +import mc.core.network.NetChannel; public interface PlayerManager { void addPlayer(Player player); Player getPlayer(String name); Player getPlayerById(int id); void removePlayer(Player player); - void bloadcastWrite(SCPacket packet); + NetChannel getBroadcastChannel(); } diff --git a/src/main/java/mc/core/embedded/InMemoryPlayerManager.java b/src/main/java/mc/core/embedded/InMemoryPlayerManager.java index 3b912b1..adf83d6 100644 --- a/src/main/java/mc/core/embedded/InMemoryPlayerManager.java +++ b/src/main/java/mc/core/embedded/InMemoryPlayerManager.java @@ -9,7 +9,8 @@ import lombok.extern.slf4j.Slf4j; import mc.core.Config; import mc.core.Player; import mc.core.PlayerManager; -import mc.core.network.SCPacket; +import mc.core.network.BroadcastNetChannel; +import mc.core.network.NetChannel; import org.springframework.beans.factory.annotation.Autowired; import java.util.ArrayList; @@ -62,8 +63,8 @@ public class InMemoryPlayerManager implements PlayerManager, Runnable { } @Override - public void bloadcastWrite(final SCPacket packet) { - players.forEach(player -> player.getChannel().writeAndFlush(packet)); + public NetChannel getBroadcastChannel() { + return new BroadcastNetChannel(players.stream()); } @Override diff --git a/src/main/java/mc/core/network/BroadcastNetChannel.java b/src/main/java/mc/core/network/BroadcastNetChannel.java new file mode 100644 index 0000000..4c6f8a4 --- /dev/null +++ b/src/main/java/mc/core/network/BroadcastNetChannel.java @@ -0,0 +1,30 @@ +/* + * DmitriyMX + * 2018-04-21 + */ +package mc.core.network; + +import lombok.RequiredArgsConstructor; +import mc.core.Player; + +import java.util.stream.Stream; + +@RequiredArgsConstructor +public class BroadcastNetChannel implements NetChannel { + private final Stream playerStream; + + @Override + public void sendKeepAlive() { + playerStream.forEach(player -> player.getChannel().sendKeepAlive()); + } + + @Override + public void sendTimeUpdate(final long value) { + playerStream.forEach(player -> player.getChannel().sendTimeUpdate(value)); + } + + @Override + public void writeAndFlush(final SCPacket pkt) { + playerStream.forEach(player -> player.getChannel().writeAndFlush(pkt)); + } +} diff --git a/src/main/java/mc/core/network/NetChannel.java b/src/main/java/mc/core/network/NetChannel.java index 34f560b..c3adbd2 100644 --- a/src/main/java/mc/core/network/NetChannel.java +++ b/src/main/java/mc/core/network/NetChannel.java @@ -6,6 +6,7 @@ package mc.core.network; public interface NetChannel { void sendKeepAlive(); + void sendTimeUpdate(long value); void writeAndFlush(SCPacket pkt); } diff --git a/src/main/java/mc/core/network/NetStream.java b/src/main/java/mc/core/network/NetStream.java index 7db7959..a2d7312 100644 --- a/src/main/java/mc/core/network/NetStream.java +++ b/src/main/java/mc/core/network/NetStream.java @@ -28,6 +28,7 @@ public abstract class NetStream { public abstract void writeBytes(byte[] buffer); public abstract void writeShort(int value); public abstract void writeInt(int value); + public abstract void writeLong(long value); public abstract void writeFloat(float value); public abstract void writeDouble(double value); public abstract void writeString(String value); diff --git a/src/main/java/mc/core/network/proto_125/ByteArrayOutputNetStream.java b/src/main/java/mc/core/network/proto_125/ByteArrayOutputNetStream.java index b3aff55..40c0644 100644 --- a/src/main/java/mc/core/network/proto_125/ByteArrayOutputNetStream.java +++ b/src/main/java/mc/core/network/proto_125/ByteArrayOutputNetStream.java @@ -88,6 +88,18 @@ public class ByteArrayOutputNetStream extends NetStream_p125 { baos.write((byte) value); } + @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))); + } + @Override public void writeFloat(float value) { writeInt(Float.floatToIntBits(value)); @@ -95,16 +107,7 @@ public class ByteArrayOutputNetStream extends NetStream_p125 { @Override public void writeDouble(double value) { - long v = Double.doubleToLongBits(value); - - baos.write((byte)((int)(v >>> 56))); - baos.write((byte)((int)(v >>> 48))); - baos.write((byte)((int)(v >>> 40))); - baos.write((byte)((int)(v >>> 32))); - baos.write((byte)((int)(v >>> 24))); - baos.write((byte)((int)(v >>> 16))); - baos.write((byte)((int)(v >>> 8))); - baos.write((byte)((int)(v))); + writeLong(Double.doubleToLongBits(value)); } @Override diff --git a/src/main/java/mc/core/network/proto_125/netty/wrappers/WrapperNetChannel.java b/src/main/java/mc/core/network/proto_125/netty/wrappers/WrapperNetChannel.java index 78525b4..0f52b96 100644 --- a/src/main/java/mc/core/network/proto_125/netty/wrappers/WrapperNetChannel.java +++ b/src/main/java/mc/core/network/proto_125/netty/wrappers/WrapperNetChannel.java @@ -10,6 +10,7 @@ import mc.core.network.NetChannel; import mc.core.network.SCPacket; import mc.core.network.proto_125.packets.KeepAlivePacket; import mc.core.network.proto_125.packets.PingPacket; +import mc.core.network.proto_125.packets.TimeUpdatePacket; @RequiredArgsConstructor public class WrapperNetChannel implements NetChannel { @@ -20,6 +21,11 @@ public class WrapperNetChannel implements NetChannel { channel.writeAndFlush(new KeepAlivePacket()); } + @Override + public void sendTimeUpdate(long value) { + channel.writeAndFlush(new TimeUpdatePacket(value)); + } + @Override public void writeAndFlush(SCPacket pkt) { channel.writeAndFlush(pkt); diff --git a/src/main/java/mc/core/network/proto_125/netty/wrappers/WrapperNetStream.java b/src/main/java/mc/core/network/proto_125/netty/wrappers/WrapperNetStream.java index c6c8380..9314558 100644 --- a/src/main/java/mc/core/network/proto_125/netty/wrappers/WrapperNetStream.java +++ b/src/main/java/mc/core/network/proto_125/netty/wrappers/WrapperNetStream.java @@ -86,6 +86,11 @@ public class WrapperNetStream extends NetStream_p125 { byteBuf.writeInt(value); } + @Override + public void writeLong(long value) { + byteBuf.writeLong(value); + } + @Override public void writeFloat(float value) { byteBuf.writeFloat(value); diff --git a/src/main/java/mc/core/network/proto_125/packets/PacketManager.java b/src/main/java/mc/core/network/proto_125/packets/PacketManager.java index b10eef5..eee19d0 100644 --- a/src/main/java/mc/core/network/proto_125/packets/PacketManager.java +++ b/src/main/java/mc/core/network/proto_125/packets/PacketManager.java @@ -15,6 +15,7 @@ public class PacketManager { .put(0x00, KeepAlivePacket.class) .put(0x01, LoginPacket.class) .put(0x02, HandshakePacket.class) + .put(0x04, TimeUpdatePacket.class) .put(0x06, SpawnPositionPacket.class) .put(0x0D, PositionAndLookPacket.class) .put(0x32, ChunkAllocationPacket.class) diff --git a/src/main/java/mc/core/network/proto_125/packets/TimeUpdatePacket.java b/src/main/java/mc/core/network/proto_125/packets/TimeUpdatePacket.java new file mode 100644 index 0000000..1a65329 --- /dev/null +++ b/src/main/java/mc/core/network/proto_125/packets/TimeUpdatePacket.java @@ -0,0 +1,28 @@ +/* + * DmitriyMX + * 2018-04-21 + */ +package mc.core.network.proto_125.packets; + +import lombok.AllArgsConstructor; +import lombok.NoArgsConstructor; +import lombok.Setter; +import lombok.ToString; +import mc.core.network.SCPacket; +import mc.core.network.proto_125.ByteArrayOutputNetStream; + +@NoArgsConstructor +@AllArgsConstructor +@Setter +@ToString +public class TimeUpdatePacket implements SCPacket { + private long time; + + @Override + public byte[] toByteArray() { + ByteArrayOutputNetStream netStream = new ByteArrayOutputNetStream(); + netStream.writeLong(time); + return netStream.toByteArray(); + } +} + diff --git a/src/main/resources/spring.xml b/src/main/resources/spring.xml index 951ba58..2356238 100644 --- a/src/main/resources/spring.xml +++ b/src/main/resources/spring.xml @@ -12,8 +12,8 @@ - - + +