mirror of https://github.com/LOOHP/Limbo.git
Clean up & Format
This commit is contained in:
parent
01d2a3e528
commit
8ec7d322d8
12
pom.xml
12
pom.xml
|
|
@ -24,7 +24,7 @@
|
||||||
<groupId>com.loohp</groupId>
|
<groupId>com.loohp</groupId>
|
||||||
<artifactId>Limbo</artifactId>
|
<artifactId>Limbo</artifactId>
|
||||||
<name>Limbo</name>
|
<name>Limbo</name>
|
||||||
<version>0.7.7-ALPHA</version>
|
<version>0.7.8-ALPHA</version>
|
||||||
|
|
||||||
<description>Standalone Limbo Minecraft Server.</description>
|
<description>Standalone Limbo Minecraft Server.</description>
|
||||||
<url>https://github.com/LOOHP/Limbo</url>
|
<url>https://github.com/LOOHP/Limbo</url>
|
||||||
|
|
@ -260,31 +260,31 @@
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>net.kyori</groupId>
|
<groupId>net.kyori</groupId>
|
||||||
<artifactId>adventure-text-serializer-gson</artifactId>
|
<artifactId>adventure-text-serializer-gson</artifactId>
|
||||||
<version>4.15.0-SNAPSHOT</version>
|
<version>4.17.0-SNAPSHOT</version>
|
||||||
<scope>compile</scope>
|
<scope>compile</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>net.kyori</groupId>
|
<groupId>net.kyori</groupId>
|
||||||
<artifactId>adventure-text-serializer-legacy</artifactId>
|
<artifactId>adventure-text-serializer-legacy</artifactId>
|
||||||
<version>4.15.0-SNAPSHOT</version>
|
<version>4.17.0-SNAPSHOT</version>
|
||||||
<scope>compile</scope>
|
<scope>compile</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>net.kyori</groupId>
|
<groupId>net.kyori</groupId>
|
||||||
<artifactId>adventure-text-serializer-plain</artifactId>
|
<artifactId>adventure-text-serializer-plain</artifactId>
|
||||||
<version>4.15.0-SNAPSHOT</version>
|
<version>4.17.0-SNAPSHOT</version>
|
||||||
<scope>compile</scope>
|
<scope>compile</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>net.kyori</groupId>
|
<groupId>net.kyori</groupId>
|
||||||
<artifactId>adventure-api</artifactId>
|
<artifactId>adventure-api</artifactId>
|
||||||
<version>4.15.0-SNAPSHOT</version>
|
<version>4.17.0-SNAPSHOT</version>
|
||||||
<scope>compile</scope>
|
<scope>compile</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>net.kyori</groupId>
|
<groupId>net.kyori</groupId>
|
||||||
<artifactId>adventure-nbt</artifactId>
|
<artifactId>adventure-nbt</artifactId>
|
||||||
<version>4.15.0-SNAPSHOT</version>
|
<version>4.17.0-SNAPSHOT</version>
|
||||||
<scope>compile</scope>
|
<scope>compile</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
|
|
|
||||||
|
|
@ -98,239 +98,231 @@ import java.util.stream.Collectors;
|
||||||
|
|
||||||
public final class Limbo {
|
public final class Limbo {
|
||||||
|
|
||||||
public static final String LIMBO_BRAND = "Limbo";
|
public static final String LIMBO_BRAND = "Limbo";
|
||||||
|
|
||||||
private static Limbo instance;
|
private static Limbo instance;
|
||||||
public static boolean noGui = false;
|
public static boolean noGui = false;
|
||||||
|
|
||||||
public static void main(String args[]) throws IOException, ParseException, NumberFormatException, ClassNotFoundException, InterruptedException {
|
public static void main(String args[]) throws IOException, ParseException, NumberFormatException, ClassNotFoundException, InterruptedException {
|
||||||
for (String flag : args) {
|
for (String flag : args) {
|
||||||
if (flag.equals("--nogui") || flag.equals("nogui")) {
|
if (flag.equals("--nogui") || flag.equals("nogui")) {
|
||||||
noGui = true;
|
noGui = true;
|
||||||
} else if (flag.equals("--help")) {
|
} else if (flag.equals("--help")) {
|
||||||
System.out.println("Accepted flags:");
|
System.out.println("Accepted flags:");
|
||||||
System.out.println(" --nogui <- Disable the GUI");
|
System.out.println(" --nogui <- Disable the GUI");
|
||||||
System.exit(0);
|
System.exit(0);
|
||||||
} else {
|
} else {
|
||||||
System.out.println("Unknown flag: \"" + flag + "\". Ignoring...");
|
System.out.println("Unknown flag: \"" + flag + "\". Ignoring...");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (GraphicsEnvironment.isHeadless()) {
|
if (GraphicsEnvironment.isHeadless()) {
|
||||||
noGui = true;
|
noGui = true;
|
||||||
}
|
}
|
||||||
if (!noGui) {
|
if (!noGui) {
|
||||||
System.out.println("Launching Server GUI.. Add \"--nogui\" in launch arguments to disable");
|
System.out.println("Launching Server GUI.. Add \"--nogui\" in launch arguments to disable");
|
||||||
Thread t1 = new Thread(() -> {
|
Thread t1 = new Thread(() -> {
|
||||||
try {
|
try {
|
||||||
GUI.main();
|
GUI.main();
|
||||||
} catch (UnsupportedLookAndFeelException | ClassNotFoundException | InstantiationException |
|
} catch (UnsupportedLookAndFeelException | ClassNotFoundException | InstantiationException | IllegalAccessException e) {
|
||||||
IllegalAccessException e) {
|
e.printStackTrace();
|
||||||
e.printStackTrace();
|
}
|
||||||
}
|
});
|
||||||
});
|
t1.start();
|
||||||
t1.start();
|
}
|
||||||
}
|
|
||||||
|
|
||||||
new Limbo();
|
new Limbo();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Limbo getInstance() {
|
public static Limbo getInstance() {
|
||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
//===========================
|
//===========================
|
||||||
|
|
||||||
public final String SERVER_IMPLEMENTATION_VERSION = "1.20.4";
|
public final String SERVER_IMPLEMENTATION_VERSION = "1.20.4";
|
||||||
public final int SERVER_IMPLEMENTATION_PROTOCOL = 765;
|
public final int SERVER_IMPLEMENTATION_PROTOCOL = 765;
|
||||||
public final String LIMBO_IMPLEMENTATION_VERSION;
|
public final String LIMBO_IMPLEMENTATION_VERSION;
|
||||||
|
|
||||||
private final AtomicBoolean isRunning;
|
private final AtomicBoolean isRunning;
|
||||||
|
|
||||||
private final ServerConnection server;
|
private final ServerConnection server;
|
||||||
private final Console console;
|
private final Console console;
|
||||||
|
|
||||||
private final List<World> worlds = new CopyOnWriteArrayList<>();
|
private final List<World> worlds = new CopyOnWriteArrayList<>();
|
||||||
final Map<String, Player> playersByName = new ConcurrentHashMap<>();
|
final Map<String, Player> playersByName = new ConcurrentHashMap<>();
|
||||||
final Map<UUID, Player> playersByUUID = new ConcurrentHashMap<>();
|
final Map<UUID, Player> playersByUUID = new ConcurrentHashMap<>();
|
||||||
private final Map<Key, KeyedBossBar> bossBars = new ConcurrentHashMap<>();
|
private final Map<Key, KeyedBossBar> bossBars = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
private final ServerProperties properties;
|
private final ServerProperties properties;
|
||||||
|
|
||||||
private final PluginManager pluginManager;
|
private final PluginManager pluginManager;
|
||||||
private final EventsManager eventsManager;
|
private final EventsManager eventsManager;
|
||||||
private final PermissionsManager permissionManager;
|
private final PermissionsManager permissionManager;
|
||||||
private final File pluginFolder;
|
private final File pluginFolder;
|
||||||
|
|
||||||
private final File internalDataFolder;
|
private final DimensionRegistry dimensionRegistry;
|
||||||
|
|
||||||
private final DimensionRegistry dimensionRegistry;
|
private final Tick tick;
|
||||||
|
private final LimboScheduler scheduler;
|
||||||
|
|
||||||
private final Tick tick;
|
private final Metrics metrics;
|
||||||
private final LimboScheduler scheduler;
|
|
||||||
|
|
||||||
private final Metrics metrics;
|
public final AtomicInteger entityIdCount = new AtomicInteger();
|
||||||
|
|
||||||
public final AtomicInteger entityIdCount = new AtomicInteger();
|
@SuppressWarnings("deprecation")
|
||||||
|
private Unsafe unsafe;
|
||||||
|
|
||||||
@SuppressWarnings("deprecation")
|
@SuppressWarnings("unchecked")
|
||||||
private Unsafe unsafe;
|
public Limbo() throws IOException, ParseException, NumberFormatException, ClassNotFoundException, InterruptedException {
|
||||||
|
instance = this;
|
||||||
|
unsafe = new Unsafe(this);
|
||||||
|
isRunning = new AtomicBoolean(true);
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
if (!noGui) {
|
||||||
public Limbo() throws IOException, ParseException, NumberFormatException, ClassNotFoundException, InterruptedException {
|
while (!GUI.loadFinish) {
|
||||||
instance = this;
|
TimeUnit.MILLISECONDS.sleep(500);
|
||||||
unsafe = new Unsafe(this);
|
}
|
||||||
isRunning = new AtomicBoolean(true);
|
console = new Console(null, System.out, System.err);
|
||||||
|
} else {
|
||||||
|
console = new Console(System.in, System.out, System.err);
|
||||||
|
}
|
||||||
|
|
||||||
if (!noGui) {
|
LIMBO_IMPLEMENTATION_VERSION = getLimboVersion();
|
||||||
while (!GUI.loadFinish) {
|
console.sendMessage("Loading Limbo Version " + LIMBO_IMPLEMENTATION_VERSION + " on Minecraft " + SERVER_IMPLEMENTATION_VERSION);
|
||||||
TimeUnit.MILLISECONDS.sleep(500);
|
|
||||||
}
|
|
||||||
console = new Console(null, System.out, System.err);
|
|
||||||
} else {
|
|
||||||
console = new Console(System.in, System.out, System.err);
|
|
||||||
}
|
|
||||||
|
|
||||||
LIMBO_IMPLEMENTATION_VERSION = getLimboVersion();
|
String spName = "server.properties";
|
||||||
console.sendMessage("Loading Limbo Version " + LIMBO_IMPLEMENTATION_VERSION + " on Minecraft " + SERVER_IMPLEMENTATION_VERSION);
|
|
||||||
|
|
||||||
String spName = "server.properties";
|
|
||||||
File sp = new File(spName);
|
File sp = new File(spName);
|
||||||
if (!sp.exists()) {
|
if (!sp.exists()) {
|
||||||
try (InputStream in = getClass().getClassLoader().getResourceAsStream(spName)) {
|
try (InputStream in = getClass().getClassLoader().getResourceAsStream(spName)) {
|
||||||
Files.copy(in, sp.toPath());
|
Files.copy(in, sp.toPath());
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
properties = new ServerProperties(sp);
|
properties = new ServerProperties(sp);
|
||||||
|
|
||||||
if (!properties.isBungeecord()) {
|
if (!properties.isBungeecord()) {
|
||||||
console.sendMessage("If you are using bungeecord, consider turning that on in the settings!");
|
console.sendMessage("If you are using bungeecord, consider turning that on in the settings!");
|
||||||
} else {
|
} else {
|
||||||
console.sendMessage("Starting Limbo server in bungeecord mode!");
|
console.sendMessage("Starting Limbo server in bungeecord mode!");
|
||||||
}
|
}
|
||||||
|
|
||||||
internalDataFolder = new File("internal_data");
|
String mappingName = "mapping.json";
|
||||||
if (!internalDataFolder.exists()) {
|
InputStream mappingStream = getClass().getClassLoader().getResourceAsStream(mappingName);
|
||||||
internalDataFolder.mkdirs();
|
if (mappingStream == null) {
|
||||||
}
|
throw new RuntimeException("Failed to load " + mappingName + " from jar!");
|
||||||
|
}
|
||||||
|
|
||||||
console.sendMessage("Loading packet id mappings from mapping.json ...");
|
console.sendMessage("Loading packet id mappings...");
|
||||||
|
|
||||||
InputStream mappingStream = getClass().getClassLoader().getResourceAsStream("mapping.json");
|
InputStreamReader reader = new InputStreamReader(mappingStream, StandardCharsets.UTF_8);
|
||||||
if (mappingStream == null) {
|
|
||||||
console.sendMessage("Failed to load mapping.json from jar!");
|
|
||||||
System.exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
InputStreamReader reader = new InputStreamReader(mappingStream, StandardCharsets.UTF_8);
|
|
||||||
JSONObject json = (JSONObject) new JSONParser().parse(reader);
|
JSONObject json = (JSONObject) new JSONParser().parse(reader);
|
||||||
reader.close();
|
reader.close();
|
||||||
|
|
||||||
String classPrefix = Packet.class.getName().substring(0, Packet.class.getName().lastIndexOf(".") + 1);
|
String classPrefix = Packet.class.getName().substring(0, Packet.class.getName().lastIndexOf(".") + 1);
|
||||||
int mappingsCount = 0;
|
int mappingsCount = 0;
|
||||||
|
|
||||||
Map<Integer, Class<? extends PacketIn>> HandshakeIn = new HashMap<>();
|
Map<Integer, Class<? extends PacketIn>> HandshakeIn = new HashMap<>();
|
||||||
for (Object key : ((JSONObject) json.get("HandshakeIn")).keySet()) {
|
for (Object key : ((JSONObject) json.get("HandshakeIn")).keySet()) {
|
||||||
int packetId = Integer.decode((String) key);
|
int packetId = Integer.decode((String) key);
|
||||||
HandshakeIn.put(packetId, (Class<? extends PacketIn>) Class.forName(classPrefix + ((JSONObject) json.get("HandshakeIn")).get(key)));
|
HandshakeIn.put(packetId, (Class<? extends PacketIn>) Class.forName(classPrefix + ((JSONObject) json.get("HandshakeIn")).get(key)));
|
||||||
}
|
}
|
||||||
Packet.setHandshakeIn(HandshakeIn);
|
Packet.setHandshakeIn(HandshakeIn);
|
||||||
mappingsCount += HandshakeIn.size();
|
mappingsCount += HandshakeIn.size();
|
||||||
|
|
||||||
Map<Integer, Class<? extends PacketIn>> StatusIn = new HashMap<>();
|
Map<Integer, Class<? extends PacketIn>> StatusIn = new HashMap<>();
|
||||||
for (Object key : ((JSONObject) json.get("StatusIn")).keySet()) {
|
for (Object key : ((JSONObject) json.get("StatusIn")).keySet()) {
|
||||||
int packetId = Integer.decode((String) key);
|
int packetId = Integer.decode((String) key);
|
||||||
StatusIn.put(packetId, (Class<? extends PacketIn>) Class.forName(classPrefix + ((JSONObject) json.get("StatusIn")).get(key)));
|
StatusIn.put(packetId, (Class<? extends PacketIn>) Class.forName(classPrefix + ((JSONObject) json.get("StatusIn")).get(key)));
|
||||||
}
|
}
|
||||||
Packet.setStatusIn(StatusIn);
|
Packet.setStatusIn(StatusIn);
|
||||||
mappingsCount += StatusIn.size();
|
mappingsCount += StatusIn.size();
|
||||||
|
|
||||||
Map<Class<? extends PacketOut>, Integer> StatusOut = new HashMap<>();
|
Map<Class<? extends PacketOut>, Integer> StatusOut = new HashMap<>();
|
||||||
for (Object key : ((JSONObject) json.get("StatusOut")).keySet()) {
|
for (Object key : ((JSONObject) json.get("StatusOut")).keySet()) {
|
||||||
Class<? extends PacketOut> packetClass = (Class<? extends PacketOut>) Class.forName(classPrefix + key);
|
Class<? extends PacketOut> packetClass = (Class<? extends PacketOut>) Class.forName(classPrefix + key);
|
||||||
StatusOut.put(packetClass, Integer.decode((String) ((JSONObject) json.get("StatusOut")).get(key)));
|
StatusOut.put(packetClass, Integer.decode((String) ((JSONObject) json.get("StatusOut")).get(key)));
|
||||||
}
|
}
|
||||||
Packet.setStatusOut(StatusOut);
|
Packet.setStatusOut(StatusOut);
|
||||||
mappingsCount += StatusOut.size();
|
mappingsCount += StatusOut.size();
|
||||||
|
|
||||||
Map<Integer, Class<? extends PacketIn>> LoginIn = new HashMap<>();
|
Map<Integer, Class<? extends PacketIn>> LoginIn = new HashMap<>();
|
||||||
for (Object key : ((JSONObject) json.get("LoginIn")).keySet()) {
|
for (Object key : ((JSONObject) json.get("LoginIn")).keySet()) {
|
||||||
int packetId = Integer.decode((String) key);
|
int packetId = Integer.decode((String) key);
|
||||||
LoginIn.put(packetId, (Class<? extends PacketIn>) Class.forName(classPrefix + ((JSONObject) json.get("LoginIn")).get(key)));
|
LoginIn.put(packetId, (Class<? extends PacketIn>) Class.forName(classPrefix + ((JSONObject) json.get("LoginIn")).get(key)));
|
||||||
}
|
}
|
||||||
Packet.setLoginIn(LoginIn);
|
Packet.setLoginIn(LoginIn);
|
||||||
mappingsCount += LoginIn.size();
|
mappingsCount += LoginIn.size();
|
||||||
|
|
||||||
Map<Class<? extends PacketOut>, Integer> LoginOut = new HashMap<>();
|
Map<Class<? extends PacketOut>, Integer> LoginOut = new HashMap<>();
|
||||||
for (Object key : ((JSONObject) json.get("LoginOut")).keySet()) {
|
for (Object key : ((JSONObject) json.get("LoginOut")).keySet()) {
|
||||||
Class<? extends PacketOut> packetClass = (Class<? extends PacketOut>) Class.forName(classPrefix + key);
|
Class<? extends PacketOut> packetClass = (Class<? extends PacketOut>) Class.forName(classPrefix + key);
|
||||||
LoginOut.put(packetClass, Integer.decode((String) ((JSONObject) json.get("LoginOut")).get(key)));
|
LoginOut.put(packetClass, Integer.decode((String) ((JSONObject) json.get("LoginOut")).get(key)));
|
||||||
}
|
}
|
||||||
Packet.setLoginOut(LoginOut);
|
Packet.setLoginOut(LoginOut);
|
||||||
mappingsCount += LoginOut.size();
|
mappingsCount += LoginOut.size();
|
||||||
|
|
||||||
Map<Integer, Class<? extends PacketIn>> ConfigurationIn = new HashMap<>();
|
Map<Integer, Class<? extends PacketIn>> ConfigurationIn = new HashMap<>();
|
||||||
for (Object key : ((JSONObject) json.get("ConfigurationIn")).keySet()) {
|
for (Object key : ((JSONObject) json.get("ConfigurationIn")).keySet()) {
|
||||||
int packetId = Integer.decode((String) key);
|
int packetId = Integer.decode((String) key);
|
||||||
ConfigurationIn.put(packetId, (Class<? extends PacketIn>) Class.forName(classPrefix + ((JSONObject) json.get("ConfigurationIn")).get(key)));
|
ConfigurationIn.put(packetId, (Class<? extends PacketIn>) Class.forName(classPrefix + ((JSONObject) json.get("ConfigurationIn")).get(key)));
|
||||||
}
|
}
|
||||||
Packet.setConfigurationIn(ConfigurationIn);
|
Packet.setConfigurationIn(ConfigurationIn);
|
||||||
mappingsCount += ConfigurationIn.size();
|
mappingsCount += ConfigurationIn.size();
|
||||||
|
|
||||||
Map<Class<? extends PacketOut>, Integer> ConfigurationOut = new HashMap<>();
|
Map<Class<? extends PacketOut>, Integer> ConfigurationOut = new HashMap<>();
|
||||||
for (Object key : ((JSONObject) json.get("ConfigurationOut")).keySet()) {
|
for (Object key : ((JSONObject) json.get("ConfigurationOut")).keySet()) {
|
||||||
Class<? extends PacketOut> packetClass = (Class<? extends PacketOut>) Class.forName(classPrefix + key);
|
Class<? extends PacketOut> packetClass = (Class<? extends PacketOut>) Class.forName(classPrefix + key);
|
||||||
ConfigurationOut.put(packetClass, Integer.decode((String) ((JSONObject) json.get("ConfigurationOut")).get(key)));
|
ConfigurationOut.put(packetClass, Integer.decode((String) ((JSONObject) json.get("ConfigurationOut")).get(key)));
|
||||||
}
|
}
|
||||||
Packet.setConfigurationOut(ConfigurationOut);
|
Packet.setConfigurationOut(ConfigurationOut);
|
||||||
mappingsCount += ConfigurationOut.size();
|
mappingsCount += ConfigurationOut.size();
|
||||||
|
|
||||||
Map<Integer, Class<? extends PacketIn>> PlayIn = new HashMap<>();
|
Map<Integer, Class<? extends PacketIn>> PlayIn = new HashMap<>();
|
||||||
for (Object key : ((JSONObject) json.get("PlayIn")).keySet()) {
|
for (Object key : ((JSONObject) json.get("PlayIn")).keySet()) {
|
||||||
int packetId = Integer.decode((String) key);
|
int packetId = Integer.decode((String) key);
|
||||||
PlayIn.put(packetId, (Class<? extends PacketIn>) Class.forName(classPrefix + ((JSONObject) json.get("PlayIn")).get(key)));
|
PlayIn.put(packetId, (Class<? extends PacketIn>) Class.forName(classPrefix + ((JSONObject) json.get("PlayIn")).get(key)));
|
||||||
}
|
}
|
||||||
Packet.setPlayIn(PlayIn);
|
Packet.setPlayIn(PlayIn);
|
||||||
mappingsCount += PlayIn.size();
|
mappingsCount += PlayIn.size();
|
||||||
|
|
||||||
Map<Class<? extends PacketOut>, Integer> PlayOut = new HashMap<>();
|
Map<Class<? extends PacketOut>, Integer> PlayOut = new HashMap<>();
|
||||||
for (Object key : ((JSONObject) json.get("PlayOut")).keySet()) {
|
for (Object key : ((JSONObject) json.get("PlayOut")).keySet()) {
|
||||||
Class<? extends PacketOut> packetClass = (Class<? extends PacketOut>) Class.forName(classPrefix + key);
|
Class<? extends PacketOut> packetClass = (Class<? extends PacketOut>) Class.forName(classPrefix + key);
|
||||||
PlayOut.put(packetClass, Integer.decode((String) ((JSONObject) json.get("PlayOut")).get(key)));
|
PlayOut.put(packetClass, Integer.decode((String) ((JSONObject) json.get("PlayOut")).get(key)));
|
||||||
}
|
}
|
||||||
Packet.setPlayOut(PlayOut);
|
Packet.setPlayOut(PlayOut);
|
||||||
mappingsCount += PlayOut.size();
|
mappingsCount += PlayOut.size();
|
||||||
|
|
||||||
console.sendMessage("Loaded all " + mappingsCount + " packet id mappings!");
|
console.sendMessage("Loaded all " + mappingsCount + " packet id mappings!");
|
||||||
|
|
||||||
dimensionRegistry = new DimensionRegistry();
|
dimensionRegistry = new DimensionRegistry();
|
||||||
|
|
||||||
worlds.add(loadDefaultWorld());
|
worlds.add(loadDefaultWorld());
|
||||||
Location spawn = properties.getWorldSpawn();
|
Location spawn = properties.getWorldSpawn();
|
||||||
properties.setWorldSpawn(new Location(getWorld(properties.getLevelName().value()), spawn.getX(), spawn.getY(), spawn.getZ(), spawn.getYaw(), spawn.getPitch()));
|
properties.setWorldSpawn(new Location(getWorld(properties.getLevelName().value()), spawn.getX(), spawn.getY(), spawn.getZ(), spawn.getYaw(), spawn.getPitch()));
|
||||||
|
|
||||||
if (!NetworkUtils.available(properties.getServerPort())) {
|
if (!NetworkUtils.available(properties.getServerPort())) {
|
||||||
console.sendMessage("");
|
console.sendMessage("");
|
||||||
console.sendMessage("*****FAILED TO BIND PORT [" + properties.getServerPort() + "]*****");
|
console.sendMessage("*****FAILED TO BIND PORT [" + properties.getServerPort() + "]*****");
|
||||||
console.sendMessage("*****PORT ALREADY IN USE*****");
|
console.sendMessage("*****PORT ALREADY IN USE*****");
|
||||||
console.sendMessage("*****PERHAPS ANOTHER INSTANCE OF THE SERVER IS ALREADY RUNNING?*****");
|
console.sendMessage("*****PERHAPS ANOTHER INSTANCE OF THE SERVER IS ALREADY RUNNING?*****");
|
||||||
console.sendMessage("");
|
console.sendMessage("");
|
||||||
System.exit(2);
|
System.exit(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
String permissionName = "permission.yml";
|
String permissionName = "permission.yml";
|
||||||
File permissionFile = new File(permissionName);
|
File permissionFile = new File(permissionName);
|
||||||
if (!permissionFile.exists()) {
|
if (!permissionFile.exists()) {
|
||||||
try (InputStream in = getClass().getClassLoader().getResourceAsStream(permissionName)) {
|
try (InputStream in = getClass().getClassLoader().getResourceAsStream(permissionName)) {
|
||||||
Files.copy(in, permissionFile.toPath());
|
Files.copy(in, permissionFile.toPath());
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
scheduler = new LimboScheduler();
|
scheduler = new LimboScheduler();
|
||||||
tick = new Tick(this);
|
tick = new Tick(this);
|
||||||
|
|
||||||
permissionManager = new PermissionsManager();
|
permissionManager = new PermissionsManager();
|
||||||
permissionManager.loadDefaultPermissionFile(permissionFile);
|
permissionManager.loadDefaultPermissionFile(permissionFile);
|
||||||
|
|
@ -340,324 +332,319 @@ public final class Limbo {
|
||||||
pluginFolder = new File("plugins");
|
pluginFolder = new File("plugins");
|
||||||
pluginFolder.mkdirs();
|
pluginFolder.mkdirs();
|
||||||
|
|
||||||
pluginManager = new PluginManager(new DefaultCommands(), pluginFolder);
|
pluginManager = new PluginManager(new DefaultCommands(), pluginFolder);
|
||||||
try {
|
try {
|
||||||
Method loadPluginsMethod = PluginManager.class.getDeclaredMethod("loadPlugins");
|
Method loadPluginsMethod = PluginManager.class.getDeclaredMethod("loadPlugins");
|
||||||
loadPluginsMethod.setAccessible(true);
|
loadPluginsMethod.setAccessible(true);
|
||||||
loadPluginsMethod.invoke(pluginManager);
|
loadPluginsMethod.invoke(pluginManager);
|
||||||
loadPluginsMethod.setAccessible(false);
|
loadPluginsMethod.setAccessible(false);
|
||||||
} catch (NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException |
|
} catch (NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
|
||||||
InvocationTargetException e) {
|
e.printStackTrace();
|
||||||
e.printStackTrace();
|
}
|
||||||
}
|
|
||||||
|
|
||||||
for (LimboPlugin plugin : Limbo.getInstance().getPluginManager().getPlugins()) {
|
for (LimboPlugin plugin : Limbo.getInstance().getPluginManager().getPlugins()) {
|
||||||
try {
|
try {
|
||||||
console.sendMessage("Enabling plugin " + plugin.getName() + " " + plugin.getInfo().getVersion());
|
console.sendMessage("Enabling plugin " + plugin.getName() + " " + plugin.getInfo().getVersion());
|
||||||
plugin.onEnable();
|
plugin.onEnable();
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
new RuntimeException("Error while enabling " + plugin.getName() + " " + plugin.getInfo().getVersion(), e).printStackTrace();
|
new RuntimeException("Error while enabling " + plugin.getName() + " " + plugin.getInfo().getVersion(), e).printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
server = new ServerConnection(properties.getServerIp(), properties.getServerPort());
|
server = new ServerConnection(properties.getServerIp(), properties.getServerPort());
|
||||||
|
|
||||||
metrics = new Metrics();
|
metrics = new Metrics();
|
||||||
|
|
||||||
Runtime.getRuntime().addShutdownHook(new Thread(() -> {
|
Runtime.getRuntime().addShutdownHook(new Thread(() -> {
|
||||||
Limbo.getInstance().terminate();
|
Limbo.getInstance().terminate();
|
||||||
}));
|
}));
|
||||||
|
|
||||||
console.run();
|
console.run();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public Unsafe getUnsafe() {
|
public Unsafe getUnsafe() {
|
||||||
return unsafe;
|
return unsafe;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Tick getHeartBeat() {
|
public Tick getHeartBeat() {
|
||||||
return tick;
|
return tick;
|
||||||
}
|
}
|
||||||
|
|
||||||
public LimboScheduler getScheduler() {
|
public LimboScheduler getScheduler() {
|
||||||
return scheduler;
|
return scheduler;
|
||||||
}
|
}
|
||||||
|
|
||||||
public DimensionRegistry getDimensionRegistry() {
|
public DimensionRegistry getDimensionRegistry() {
|
||||||
return dimensionRegistry;
|
return dimensionRegistry;
|
||||||
}
|
}
|
||||||
|
|
||||||
public PermissionsManager getPermissionsManager() {
|
public PermissionsManager getPermissionsManager() {
|
||||||
return permissionManager;
|
return permissionManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
public File getInternalDataFolder() {
|
public EventsManager getEventsManager() {
|
||||||
return internalDataFolder;
|
return eventsManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
public EventsManager getEventsManager() {
|
public File getPluginFolder() {
|
||||||
return eventsManager;
|
return pluginFolder;
|
||||||
}
|
}
|
||||||
|
|
||||||
public File getPluginFolder() {
|
public PluginManager getPluginManager() {
|
||||||
return pluginFolder;
|
return pluginManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
public PluginManager getPluginManager() {
|
private World loadDefaultWorld() throws IOException {
|
||||||
return pluginManager;
|
console.sendMessage("Loading world " + properties.getLevelName() + " with the schematic file " + properties.getSchemFileName() + " ...");
|
||||||
}
|
|
||||||
|
|
||||||
private World loadDefaultWorld() throws IOException {
|
File schem = new File(properties.getSchemFileName());
|
||||||
console.sendMessage("Loading world " + properties.getLevelName() + " with the schematic file " + properties.getSchemFileName() + " ...");
|
|
||||||
|
|
||||||
File schem = new File(properties.getSchemFileName());
|
if (!schem.exists()) {
|
||||||
|
console.sendMessage("Schemetic file " + properties.getSchemFileName() + " for world " + properties.getLevelName() + " not found!");
|
||||||
|
console.sendMessage("Creating default world...");
|
||||||
|
try (InputStream in = Limbo.class.getClassLoader().getResourceAsStream("spawn.schem")) {
|
||||||
|
Files.copy(in, schem.toPath());
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!schem.exists()) {
|
try {
|
||||||
console.sendMessage("Schemetic file " + properties.getSchemFileName() + " for world " + properties.getLevelName() + " not found!");
|
World world = Schematic.toWorld(properties.getLevelName().value(), Environment.fromKey(properties.getLevelDimension()), (CompoundTag) NBTUtil.read(schem).getTag());
|
||||||
console.sendMessage("Creating default world...");
|
console.sendMessage("Loaded world " + properties.getLevelName() + "!");
|
||||||
try (InputStream in = Limbo.class.getClassLoader().getResourceAsStream("spawn.schem")) {
|
return world;
|
||||||
Files.copy(in, schem.toPath());
|
} catch (Throwable e) {
|
||||||
} catch (IOException e) {
|
console.sendMessage("Unable to load world " + properties.getSchemFileName() + "!");
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
console.sendMessage("Server will exit!");
|
||||||
}
|
System.exit(1);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
public void registerWorld(World world) {
|
||||||
World world = Schematic.toWorld(properties.getLevelName().value(), Environment.fromKey(properties.getLevelDimension()), (CompoundTag) NBTUtil.read(schem).getTag());
|
if (!worlds.contains(world)) {
|
||||||
console.sendMessage("Loaded world " + properties.getLevelName() + "!");
|
worlds.add(world);
|
||||||
return world;
|
} else {
|
||||||
} catch (Throwable e) {
|
throw new RuntimeException("World already registered");
|
||||||
console.sendMessage("Unable to load world " + properties.getSchemFileName() + "!");
|
}
|
||||||
e.printStackTrace();
|
}
|
||||||
console.sendMessage("Server will exit!");
|
|
||||||
System.exit(1);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void registerWorld(World world) {
|
public void unregisterWorld(World world) {
|
||||||
if (!worlds.contains(world)) {
|
if (worlds.indexOf(world) == 0) {
|
||||||
worlds.add(world);
|
throw new RuntimeException("World already registered");
|
||||||
} else {
|
} else if (!worlds.contains(world)) {
|
||||||
throw new RuntimeException("World already registered");
|
throw new RuntimeException("World not registered");
|
||||||
}
|
} else {
|
||||||
}
|
for (Player player : world.getPlayers()) {
|
||||||
|
player.teleport(properties.getWorldSpawn());
|
||||||
|
}
|
||||||
|
worlds.remove(world);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void unregisterWorld(World world) {
|
public KeyedBossBar createBossBar(Key Key, Component name, float progress, BossBar.Color color, BossBar.Overlay overlay, BossBar.Flag... flags) {
|
||||||
if (worlds.indexOf(world) == 0) {
|
KeyedBossBar keyedBossBar = com.loohp.limbo.bossbar.Unsafe.a(Key, BossBar.bossBar(name, progress, color, overlay, new HashSet<>(Arrays.asList(flags))));
|
||||||
throw new RuntimeException("World already registered");
|
bossBars.put(Key, keyedBossBar);
|
||||||
} else if (!worlds.contains(world)) {
|
return keyedBossBar;
|
||||||
throw new RuntimeException("World not registered");
|
}
|
||||||
} else {
|
|
||||||
for (Player player : world.getPlayers()) {
|
|
||||||
player.teleport(properties.getWorldSpawn());
|
|
||||||
}
|
|
||||||
worlds.remove(world);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public KeyedBossBar createBossBar(Key Key, Component name, float progress, BossBar.Color color, BossBar.Overlay overlay, BossBar.Flag... flags) {
|
public void removeBossBar(Key Key) {
|
||||||
KeyedBossBar keyedBossBar = com.loohp.limbo.bossbar.Unsafe.a(Key, BossBar.bossBar(name, progress, color, overlay, new HashSet<>(Arrays.asList(flags))));
|
KeyedBossBar keyedBossBar = bossBars.remove(Key);
|
||||||
bossBars.put(Key, keyedBossBar);
|
keyedBossBar.getProperties().removeListener(keyedBossBar.getUnsafe().a());
|
||||||
return keyedBossBar;
|
keyedBossBar.getUnsafe().b();
|
||||||
}
|
PacketPlayOutBoss packetPlayOutBoss = new PacketPlayOutBoss(keyedBossBar, PacketPlayOutBoss.BossBarAction.REMOVE);
|
||||||
|
for (Player player : keyedBossBar.getPlayers()) {
|
||||||
|
try {
|
||||||
|
player.clientConnection.sendPacket(packetPlayOutBoss);
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void removeBossBar(Key Key) {
|
public Map<Key, KeyedBossBar> getBossBars() {
|
||||||
KeyedBossBar keyedBossBar = bossBars.remove(Key);
|
return Collections.unmodifiableMap(bossBars);
|
||||||
keyedBossBar.getProperties().removeListener(keyedBossBar.getUnsafe().a());
|
}
|
||||||
keyedBossBar.getUnsafe().b();
|
|
||||||
PacketPlayOutBoss packetPlayOutBoss = new PacketPlayOutBoss(keyedBossBar, PacketPlayOutBoss.BossBarAction.REMOVE);
|
|
||||||
for (Player player : keyedBossBar.getPlayers()) {
|
|
||||||
try {
|
|
||||||
player.clientConnection.sendPacket(packetPlayOutBoss);
|
|
||||||
} catch (IOException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public Map<Key, KeyedBossBar> getBossBars() {
|
public ServerProperties getServerProperties() {
|
||||||
return Collections.unmodifiableMap(bossBars);
|
return properties;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ServerProperties getServerProperties() {
|
public ServerConnection getServerConnection() {
|
||||||
return properties;
|
return server;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ServerConnection getServerConnection() {
|
public Console getConsole() {
|
||||||
return server;
|
return console;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Console getConsole() {
|
public Metrics getMetrics() {
|
||||||
return console;
|
return metrics;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Metrics getMetrics() {
|
public Set<Player> getPlayers() {
|
||||||
return metrics;
|
return new HashSet<>(playersByUUID.values());
|
||||||
}
|
}
|
||||||
|
|
||||||
public Set<Player> getPlayers() {
|
public Player getPlayer(String name) {
|
||||||
return new HashSet<>(playersByUUID.values());
|
return playersByName.get(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Player getPlayer(String name) {
|
public Player getPlayer(UUID uuid) {
|
||||||
return playersByName.get(name);
|
return playersByUUID.get(uuid);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Player getPlayer(UUID uuid) {
|
public List<World> getWorlds() {
|
||||||
return playersByUUID.get(uuid);
|
return new ArrayList<>(worlds);
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<World> getWorlds() {
|
public World getWorld(String name) {
|
||||||
return new ArrayList<>(worlds);
|
for (World world : worlds) {
|
||||||
}
|
if (world.getName().equalsIgnoreCase(name)) {
|
||||||
|
return world;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
public World getWorld(String name) {
|
@SuppressWarnings("unchecked")
|
||||||
for (World world : worlds) {
|
public String buildServerListResponseJson(String version, int protocol, Component motd, int maxPlayers, int playersOnline, BufferedImage favicon) throws IOException {
|
||||||
if (world.getName().equalsIgnoreCase(name)) {
|
JSONObject json = new JSONObject();
|
||||||
return world;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
JSONObject versionJson = new JSONObject();
|
||||||
public String buildServerListResponseJson(String version, int protocol, Component motd, int maxPlayers, int playersOnline, BufferedImage favicon) throws IOException {
|
versionJson.put("name", version);
|
||||||
JSONObject json = new JSONObject();
|
versionJson.put("protocol", protocol);
|
||||||
|
json.put("version", versionJson);
|
||||||
|
|
||||||
JSONObject versionJson = new JSONObject();
|
JSONObject playersJson = new JSONObject();
|
||||||
versionJson.put("name", version);
|
playersJson.put("max", maxPlayers);
|
||||||
versionJson.put("protocol", protocol);
|
playersJson.put("online", playersOnline);
|
||||||
json.put("version", versionJson);
|
json.put("players", playersJson);
|
||||||
|
|
||||||
JSONObject playersJson = new JSONObject();
|
json.put("description", "%MOTD%");
|
||||||
playersJson.put("max", maxPlayers);
|
|
||||||
playersJson.put("online", playersOnline);
|
|
||||||
json.put("players", playersJson);
|
|
||||||
|
|
||||||
json.put("description", "%MOTD%");
|
if (favicon != null) {
|
||||||
|
if (favicon.getWidth() == 64 && favicon.getHeight() == 64) {
|
||||||
|
String base64 = "data:image/png;base64," + ImageUtils.imgToBase64String(favicon, "png");
|
||||||
|
json.put("favicon", base64);
|
||||||
|
} else {
|
||||||
|
console.sendMessage("Server List Favicon must be 64 x 64 in size!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (favicon != null) {
|
JSONObject modInfoJson = new JSONObject();
|
||||||
if (favicon.getWidth() == 64 && favicon.getHeight() == 64) {
|
modInfoJson.put("type", "FML");
|
||||||
String base64 = "data:image/png;base64," + ImageUtils.imgToBase64String(favicon, "png");
|
modInfoJson.put("modList", new JSONArray());
|
||||||
json.put("favicon", base64);
|
json.put("modinfo", modInfoJson);
|
||||||
} else {
|
|
||||||
console.sendMessage("Server List Favicon must be 64 x 64 in size!");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
JSONObject modInfoJson = new JSONObject();
|
|
||||||
modInfoJson.put("type", "FML");
|
|
||||||
modInfoJson.put("modList", new JSONArray());
|
|
||||||
json.put("modinfo", modInfoJson);
|
|
||||||
|
|
||||||
|
|
||||||
TreeMap<String, Object> treeMap = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
|
TreeMap<String, Object> treeMap = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
|
||||||
treeMap.putAll(json);
|
treeMap.putAll(json);
|
||||||
|
|
||||||
Gson g = new GsonBuilder().create();
|
Gson g = new GsonBuilder().create();
|
||||||
|
|
||||||
return g.toJson(treeMap).replace("\"%MOTD%\"", GsonComponentSerializer.gson().serialize(motd));
|
return g.toJson(treeMap).replace("\"%MOTD%\"", GsonComponentSerializer.gson().serialize(motd));
|
||||||
}
|
}
|
||||||
|
|
||||||
public String buildLegacyPingResponse(String version, Component motd, int maxPlayers, int playersOnline) {
|
public String buildLegacyPingResponse(String version, Component motd, int maxPlayers, int playersOnline) {
|
||||||
String begin = "<EFBFBD>1";
|
String begin = "<EFBFBD>1";
|
||||||
return String.join("\00", begin, "127", version, String.join("", Arrays.asList(motd).stream().map(each -> LegacyComponentSerializer.legacySection().serialize(each)).collect(Collectors.toList())), String.valueOf(playersOnline), String.valueOf(maxPlayers));
|
return String.join("\00", begin, "127", version, String.join("", Arrays.asList(motd).stream().map(each -> LegacyComponentSerializer.legacySection().serialize(each)).collect(Collectors.toList())), String.valueOf(playersOnline), String.valueOf(maxPlayers));
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void terminate() {
|
protected void terminate() {
|
||||||
isRunning.set(false);
|
isRunning.set(false);
|
||||||
console.sendMessage("Stopping Server...");
|
console.sendMessage("Stopping Server...");
|
||||||
|
|
||||||
for (LimboPlugin plugin : Limbo.getInstance().getPluginManager().getPlugins()) {
|
for (LimboPlugin plugin : Limbo.getInstance().getPluginManager().getPlugins()) {
|
||||||
try {
|
try {
|
||||||
console.sendMessage("Disabling plugin " + plugin.getName() + " " + plugin.getInfo().getVersion());
|
console.sendMessage("Disabling plugin " + plugin.getName() + " " + plugin.getInfo().getVersion());
|
||||||
plugin.onDisable();
|
plugin.onDisable();
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
new RuntimeException("Error while disabling " + plugin.getName() + " " + plugin.getInfo().getVersion(), e).printStackTrace();
|
new RuntimeException("Error while disabling " + plugin.getName() + " " + plugin.getInfo().getVersion(), e).printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
tick.waitAndKillThreads(5000);
|
tick.waitAndKillThreads(5000);
|
||||||
|
|
||||||
for (Player player : getPlayers()) {
|
for (Player player : getPlayers()) {
|
||||||
player.disconnect("Server closed");
|
player.disconnect("Server closed");
|
||||||
}
|
}
|
||||||
while (!getPlayers().isEmpty()) {
|
while (!getPlayers().isEmpty()) {
|
||||||
try {
|
try {
|
||||||
TimeUnit.MILLISECONDS.sleep(500);
|
TimeUnit.MILLISECONDS.sleep(500);
|
||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
console.sendMessage("Server closed");
|
console.sendMessage("Server closed");
|
||||||
console.logs.close();
|
console.logs.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void stopServer() {
|
public void stopServer() {
|
||||||
System.exit(0);
|
System.exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isRunning() {
|
public boolean isRunning() {
|
||||||
return isRunning.get();
|
return isRunning.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getNextEntityId() {
|
public int getNextEntityId() {
|
||||||
return entityIdCount.getAndUpdate(i -> i == Integer.MAX_VALUE ? 0 : ++i);
|
return entityIdCount.getAndUpdate(i -> i == Integer.MAX_VALUE ? 0 : ++i);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void dispatchCommand(CommandSender sender, String str) {
|
public void dispatchCommand(CommandSender sender, String str) {
|
||||||
String[] command;
|
String[] command;
|
||||||
if (str.startsWith("/")) {
|
if (str.startsWith("/")) {
|
||||||
command = CustomStringUtils.splitStringToArgs(str.substring(1));
|
command = CustomStringUtils.splitStringToArgs(str.substring(1));
|
||||||
} else {
|
} else {
|
||||||
command = CustomStringUtils.splitStringToArgs(str);
|
command = CustomStringUtils.splitStringToArgs(str);
|
||||||
}
|
}
|
||||||
dispatchCommand(sender, command);
|
dispatchCommand(sender, command);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void dispatchCommand(CommandSender sender, String... args) {
|
public void dispatchCommand(CommandSender sender, String... args) {
|
||||||
try {
|
try {
|
||||||
Limbo.getInstance().getPluginManager().fireExecutors(sender, args);
|
Limbo.getInstance().getPluginManager().fireExecutors(sender, args);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getLimboVersion() throws IOException {
|
private String getLimboVersion() throws IOException {
|
||||||
Enumeration<URL> manifests = getClass().getClassLoader().getResources("META-INF/MANIFEST.MF");
|
Enumeration<URL> manifests = getClass().getClassLoader().getResources("META-INF/MANIFEST.MF");
|
||||||
while (manifests.hasMoreElements()) {
|
while (manifests.hasMoreElements()) {
|
||||||
URL url = manifests.nextElement();
|
URL url = manifests.nextElement();
|
||||||
try (BufferedReader br = new BufferedReader(new InputStreamReader(url.openStream()))) {
|
try (BufferedReader br = new BufferedReader(new InputStreamReader(url.openStream()))) {
|
||||||
Optional<String> line = br.lines().filter(each -> each.startsWith("Limbo-Version:")).findFirst();
|
Optional<String> line = br.lines().filter(each -> each.startsWith("Limbo-Version:")).findFirst();
|
||||||
if (line.isPresent()) {
|
if (line.isPresent()) {
|
||||||
return line.get().substring(14).trim();
|
return line.get().substring(14).trim();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return "Unknown";
|
return "Unknown";
|
||||||
}
|
}
|
||||||
|
|
||||||
public Inventory createInventory(Component title, int slots, InventoryHolder holder) {
|
public Inventory createInventory(Component title, int slots, InventoryHolder holder) {
|
||||||
return CustomInventory.create(title, slots, holder);
|
return CustomInventory.create(title, slots, holder);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Inventory createInventory(InventoryType type, InventoryHolder holder) {
|
public Inventory createInventory(InventoryType type, InventoryHolder holder) {
|
||||||
return createInventory(null, type, holder);
|
return createInventory(null, type, holder);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Inventory createInventory(Component title, InventoryType type, InventoryHolder holder) {
|
public Inventory createInventory(Component title, InventoryType type, InventoryHolder holder) {
|
||||||
if (!type.isCreatable()) {
|
if (!type.isCreatable()) {
|
||||||
throw new UnsupportedOperationException("This InventoryType cannot be created.");
|
throw new UnsupportedOperationException("This InventoryType cannot be created.");
|
||||||
}
|
}
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case ANVIL:
|
case ANVIL:
|
||||||
return new AnvilInventory(title, holder);
|
return new AnvilInventory(title, holder);
|
||||||
default:
|
default:
|
||||||
throw new UnsupportedOperationException("This InventoryType has not been implemented yet.");
|
throw new UnsupportedOperationException("This InventoryType has not been implemented yet.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -41,13 +41,61 @@ import com.loohp.limbo.inventory.AnvilInventory;
|
||||||
import com.loohp.limbo.inventory.Inventory;
|
import com.loohp.limbo.inventory.Inventory;
|
||||||
import com.loohp.limbo.inventory.ItemStack;
|
import com.loohp.limbo.inventory.ItemStack;
|
||||||
import com.loohp.limbo.location.Location;
|
import com.loohp.limbo.location.Location;
|
||||||
import com.loohp.limbo.network.protocol.packets.*;
|
import com.loohp.limbo.network.protocol.packets.ClientboundFinishConfigurationPacket;
|
||||||
|
import com.loohp.limbo.network.protocol.packets.ClientboundRegistryDataPacket;
|
||||||
|
import com.loohp.limbo.network.protocol.packets.Packet;
|
||||||
|
import com.loohp.limbo.network.protocol.packets.PacketHandshakingIn;
|
||||||
|
import com.loohp.limbo.network.protocol.packets.PacketIn;
|
||||||
|
import com.loohp.limbo.network.protocol.packets.PacketLoginInLoginStart;
|
||||||
|
import com.loohp.limbo.network.protocol.packets.PacketLoginInPluginMessaging;
|
||||||
|
import com.loohp.limbo.network.protocol.packets.PacketLoginOutDisconnect;
|
||||||
|
import com.loohp.limbo.network.protocol.packets.PacketLoginOutLoginSuccess;
|
||||||
|
import com.loohp.limbo.network.protocol.packets.PacketLoginOutPluginMessaging;
|
||||||
|
import com.loohp.limbo.network.protocol.packets.PacketOut;
|
||||||
|
import com.loohp.limbo.network.protocol.packets.PacketPlayInBlockDig;
|
||||||
|
import com.loohp.limbo.network.protocol.packets.PacketPlayInBlockPlace;
|
||||||
|
import com.loohp.limbo.network.protocol.packets.PacketPlayInChat;
|
||||||
|
import com.loohp.limbo.network.protocol.packets.PacketPlayInCloseWindow;
|
||||||
|
import com.loohp.limbo.network.protocol.packets.PacketPlayInHeldItemChange;
|
||||||
|
import com.loohp.limbo.network.protocol.packets.PacketPlayInItemName;
|
||||||
|
import com.loohp.limbo.network.protocol.packets.PacketPlayInKeepAlive;
|
||||||
|
import com.loohp.limbo.network.protocol.packets.PacketPlayInPickItem;
|
||||||
|
import com.loohp.limbo.network.protocol.packets.PacketPlayInPluginMessaging;
|
||||||
|
import com.loohp.limbo.network.protocol.packets.PacketPlayInPosition;
|
||||||
|
import com.loohp.limbo.network.protocol.packets.PacketPlayInPositionAndLook;
|
||||||
|
import com.loohp.limbo.network.protocol.packets.PacketPlayOutGameStateChange;
|
||||||
|
import com.loohp.limbo.network.protocol.packets.ServerboundResourcePackPacket;
|
||||||
import com.loohp.limbo.network.protocol.packets.ServerboundResourcePackPacket.Action;
|
import com.loohp.limbo.network.protocol.packets.ServerboundResourcePackPacket.Action;
|
||||||
|
import com.loohp.limbo.network.protocol.packets.PacketPlayInRotation;
|
||||||
|
import com.loohp.limbo.network.protocol.packets.PacketPlayInSetCreativeSlot;
|
||||||
|
import com.loohp.limbo.network.protocol.packets.PacketPlayInTabComplete;
|
||||||
|
import com.loohp.limbo.network.protocol.packets.PacketPlayInUseItem;
|
||||||
|
import com.loohp.limbo.network.protocol.packets.PacketPlayInWindowClick;
|
||||||
|
import com.loohp.limbo.network.protocol.packets.PacketPlayOutDeclareCommands;
|
||||||
|
import com.loohp.limbo.network.protocol.packets.PacketPlayOutDisconnect;
|
||||||
|
import com.loohp.limbo.network.protocol.packets.PacketPlayOutEntityMetadata;
|
||||||
|
import com.loohp.limbo.network.protocol.packets.PacketPlayOutHeldItemChange;
|
||||||
|
import com.loohp.limbo.network.protocol.packets.PacketPlayOutKeepAlive;
|
||||||
|
import com.loohp.limbo.network.protocol.packets.PacketPlayOutLogin;
|
||||||
|
import com.loohp.limbo.network.protocol.packets.PacketPlayOutPlayerAbilities;
|
||||||
import com.loohp.limbo.network.protocol.packets.PacketPlayOutPlayerAbilities.PlayerAbilityFlags;
|
import com.loohp.limbo.network.protocol.packets.PacketPlayOutPlayerAbilities.PlayerAbilityFlags;
|
||||||
|
import com.loohp.limbo.network.protocol.packets.PacketPlayOutPlayerInfo;
|
||||||
import com.loohp.limbo.network.protocol.packets.PacketPlayOutPlayerInfo.PlayerInfoAction;
|
import com.loohp.limbo.network.protocol.packets.PacketPlayOutPlayerInfo.PlayerInfoAction;
|
||||||
import com.loohp.limbo.network.protocol.packets.PacketPlayOutPlayerInfo.PlayerInfoData;
|
import com.loohp.limbo.network.protocol.packets.PacketPlayOutPlayerInfo.PlayerInfoData;
|
||||||
import com.loohp.limbo.network.protocol.packets.PacketPlayOutPlayerInfo.PlayerInfoData.PlayerInfoDataAddPlayer.PlayerSkinProperty;
|
import com.loohp.limbo.network.protocol.packets.PacketPlayOutPlayerInfo.PlayerInfoData.PlayerInfoDataAddPlayer.PlayerSkinProperty;
|
||||||
|
import com.loohp.limbo.network.protocol.packets.PacketPlayOutPluginMessaging;
|
||||||
|
import com.loohp.limbo.network.protocol.packets.PacketPlayOutPositionAndLook;
|
||||||
|
import com.loohp.limbo.network.protocol.packets.PacketPlayOutSpawnPosition;
|
||||||
|
import com.loohp.limbo.network.protocol.packets.PacketPlayOutTabComplete;
|
||||||
import com.loohp.limbo.network.protocol.packets.PacketPlayOutTabComplete.TabCompleteMatches;
|
import com.loohp.limbo.network.protocol.packets.PacketPlayOutTabComplete.TabCompleteMatches;
|
||||||
|
import com.loohp.limbo.network.protocol.packets.PacketPlayOutUpdateViewPosition;
|
||||||
|
import com.loohp.limbo.network.protocol.packets.PacketStatusInPing;
|
||||||
|
import com.loohp.limbo.network.protocol.packets.PacketStatusInRequest;
|
||||||
|
import com.loohp.limbo.network.protocol.packets.PacketStatusOutPong;
|
||||||
|
import com.loohp.limbo.network.protocol.packets.PacketStatusOutResponse;
|
||||||
|
import com.loohp.limbo.network.protocol.packets.ServerboundChatCommandPacket;
|
||||||
|
import com.loohp.limbo.network.protocol.packets.ServerboundFinishConfigurationPacket;
|
||||||
|
import com.loohp.limbo.network.protocol.packets.ServerboundLoginAcknowledgedPacket;
|
||||||
import com.loohp.limbo.player.Player;
|
import com.loohp.limbo.player.Player;
|
||||||
import com.loohp.limbo.player.PlayerInteractManager;
|
import com.loohp.limbo.player.PlayerInteractManager;
|
||||||
import com.loohp.limbo.player.PlayerInventory;
|
import com.loohp.limbo.player.PlayerInventory;
|
||||||
|
|
@ -565,6 +613,10 @@ public class ClientConnection extends Thread {
|
||||||
String str = (properties.isLogPlayerIPAddresses() ? inetAddress.getHostName() : "<ip address withheld>") + ":" + clientSocket.getPort() + "|" + player.getName() + "(" + player.getUniqueId() + ")";
|
String str = (properties.isLogPlayerIPAddresses() ? inetAddress.getHostName() : "<ip address withheld>") + ":" + clientSocket.getPort() + "|" + player.getName() + "(" + player.getUniqueId() + ")";
|
||||||
Limbo.getInstance().getConsole().sendMessage("[/" + str + "] <-> Player had connected to the Limbo server!");
|
Limbo.getInstance().getConsole().sendMessage("[/" + str + "] <-> Player had connected to the Limbo server!");
|
||||||
|
|
||||||
|
PacketPlayOutGameStateChange gameEvent = new PacketPlayOutGameStateChange(PacketPlayOutGameStateChange.GameStateChangeEvent.LEVEL_CHUNKS_LOAD_START, 0);
|
||||||
|
sendPacket(gameEvent);
|
||||||
|
player.playerInteractManager.update();
|
||||||
|
|
||||||
PacketPlayOutDeclareCommands declare = DeclareCommands.getDeclareCommandsPacket(player);
|
PacketPlayOutDeclareCommands declare = DeclareCommands.getDeclareCommandsPacket(player);
|
||||||
if (declare != null) {
|
if (declare != null) {
|
||||||
sendPacket(declare);
|
sendPacket(declare);
|
||||||
|
|
@ -584,7 +636,7 @@ public class ClientConnection extends Thread {
|
||||||
Limbo.getInstance().getEventsManager().callEvent(new PlayerJoinEvent(player));
|
Limbo.getInstance().getEventsManager().callEvent(new PlayerJoinEvent(player));
|
||||||
|
|
||||||
if (properties.isAllowFlight()) {
|
if (properties.isAllowFlight()) {
|
||||||
PacketPlayOutGameState state = new PacketPlayOutGameState(3, player.getGamemode().getId());
|
PacketPlayOutGameStateChange state = new PacketPlayOutGameStateChange(PacketPlayOutGameStateChange.GameStateChangeEvent.CHANGE_GAME_MODE, player.getGamemode().getId());
|
||||||
sendPacket(state);
|
sendPacket(state);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -604,12 +656,7 @@ public class ClientConnection extends Thread {
|
||||||
// PLAYER LIST HEADER AND FOOTER CODE CONRIBUTED BY GAMERDUCK123
|
// PLAYER LIST HEADER AND FOOTER CODE CONRIBUTED BY GAMERDUCK123
|
||||||
player.sendPlayerListHeaderAndFooter(properties.getTabHeader(), properties.getTabFooter());
|
player.sendPlayerListHeaderAndFooter(properties.getTabHeader(), properties.getTabFooter());
|
||||||
|
|
||||||
// Start waiting for level chunks
|
|
||||||
PacketPlayOutGameEvent gameEvent = new PacketPlayOutGameEvent((byte) 13, 0);
|
|
||||||
sendPacket(gameEvent);
|
|
||||||
|
|
||||||
ready = true;
|
ready = true;
|
||||||
player.playerInteractManager.update();
|
|
||||||
|
|
||||||
keepAliveTask = new TimerTask() {
|
keepAliveTask = new TimerTask() {
|
||||||
@Override
|
@Override
|
||||||
|
|
|
||||||
|
|
@ -1,56 +0,0 @@
|
||||||
/*
|
|
||||||
* This file is part of Limbo.
|
|
||||||
*
|
|
||||||
* Copyright (C) 2022. LoohpJames <jamesloohp@gmail.com>
|
|
||||||
* Copyright (C) 2022. Contributors
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.loohp.limbo.network.protocol.packets;
|
|
||||||
|
|
||||||
import java.io.ByteArrayOutputStream;
|
|
||||||
import java.io.DataOutputStream;
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
public class PacketPlayOutGameState extends PacketOut {
|
|
||||||
|
|
||||||
private final int reason;
|
|
||||||
private final float value;
|
|
||||||
|
|
||||||
public PacketPlayOutGameState(int reason, float value) {
|
|
||||||
this.reason = reason;
|
|
||||||
this.value = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getReason() {
|
|
||||||
return reason;
|
|
||||||
}
|
|
||||||
|
|
||||||
public float getValue() {
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public byte[] serializePacket() throws IOException {
|
|
||||||
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
|
|
||||||
|
|
||||||
DataOutputStream output = new DataOutputStream(buffer);
|
|
||||||
output.writeByte(Packet.getPlayOut().get(getClass()));
|
|
||||||
output.writeByte(reason);
|
|
||||||
output.writeFloat(value);
|
|
||||||
|
|
||||||
return buffer.toByteArray();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
/*
|
/*
|
||||||
* This file is part of Limbo.
|
* This file is part of Limbo.
|
||||||
*
|
*
|
||||||
* Copyright (C) 2022. LoohpJames <jamesloohp@gmail.com>
|
* Copyright (C) 2024. LoohpJames <jamesloohp@gmail.com>
|
||||||
* Copyright (C) 2022. Contributors
|
* Copyright (C) 2024. Contributors
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|
@ -23,17 +23,44 @@ import java.io.ByteArrayOutputStream;
|
||||||
import java.io.DataOutputStream;
|
import java.io.DataOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
public class PacketPlayOutGameEvent extends PacketOut {
|
public class PacketPlayOutGameStateChange extends PacketOut {
|
||||||
|
|
||||||
private byte event;
|
public enum GameStateChangeEvent {
|
||||||
|
NO_RESPAWN_BLOCK_AVAILABLE(0),
|
||||||
|
START_RAINING(1),
|
||||||
|
STOP_RAINING(2),
|
||||||
|
CHANGE_GAME_MODE(3),
|
||||||
|
WIN_GAME(4),
|
||||||
|
DEMO_EVENT(5),
|
||||||
|
ARROW_HIT_PLAYER(6),
|
||||||
|
RAIN_LEVEL_CHANGE(7),
|
||||||
|
THUNDER_LEVEL_CHANGE(8),
|
||||||
|
PUFFER_FISH_STING(9),
|
||||||
|
GUARDIAN_ELDER_EFFECT(10),
|
||||||
|
IMMEDIATE_RESPAWN(11),
|
||||||
|
LIMITED_CRAFTING(12),
|
||||||
|
LEVEL_CHUNKS_LOAD_START(13);
|
||||||
|
|
||||||
|
private final int id;
|
||||||
|
|
||||||
|
GameStateChangeEvent(int id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private GameStateChangeEvent event;
|
||||||
private float value;
|
private float value;
|
||||||
|
|
||||||
public PacketPlayOutGameEvent(byte event, float value) {
|
public PacketPlayOutGameStateChange(GameStateChangeEvent event, float value) {
|
||||||
this.event = event;
|
this.event = event;
|
||||||
this.value = value;
|
this.value = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getEvent() {
|
public GameStateChangeEvent getEvent() {
|
||||||
return event;
|
return event;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -46,7 +73,7 @@ public class PacketPlayOutGameEvent extends PacketOut {
|
||||||
|
|
||||||
DataOutputStream output = new DataOutputStream(buffer);
|
DataOutputStream output = new DataOutputStream(buffer);
|
||||||
output.writeByte(Packet.getPlayOut().get(getClass()));
|
output.writeByte(Packet.getPlayOut().get(getClass()));
|
||||||
output.writeByte(Byte.toUnsignedInt(event));
|
output.writeByte(event.getId());
|
||||||
output.writeFloat(value);
|
output.writeFloat(value);
|
||||||
|
|
||||||
return buffer.toByteArray();
|
return buffer.toByteArray();
|
||||||
|
|
@ -45,7 +45,7 @@ import com.loohp.limbo.network.protocol.packets.ClientboundSetTitlesAnimationPac
|
||||||
import com.loohp.limbo.network.protocol.packets.ClientboundSystemChatPacket;
|
import com.loohp.limbo.network.protocol.packets.ClientboundSystemChatPacket;
|
||||||
import com.loohp.limbo.network.protocol.packets.PacketOut;
|
import com.loohp.limbo.network.protocol.packets.PacketOut;
|
||||||
import com.loohp.limbo.network.protocol.packets.PacketPlayOutCloseWindow;
|
import com.loohp.limbo.network.protocol.packets.PacketPlayOutCloseWindow;
|
||||||
import com.loohp.limbo.network.protocol.packets.PacketPlayOutGameState;
|
import com.loohp.limbo.network.protocol.packets.PacketPlayOutGameStateChange;
|
||||||
import com.loohp.limbo.network.protocol.packets.PacketPlayOutHeldItemChange;
|
import com.loohp.limbo.network.protocol.packets.PacketPlayOutHeldItemChange;
|
||||||
import com.loohp.limbo.network.protocol.packets.PacketPlayOutNamedSoundEffect;
|
import com.loohp.limbo.network.protocol.packets.PacketPlayOutNamedSoundEffect;
|
||||||
import com.loohp.limbo.network.protocol.packets.PacketPlayOutOpenWindow;
|
import com.loohp.limbo.network.protocol.packets.PacketPlayOutOpenWindow;
|
||||||
|
|
@ -151,7 +151,7 @@ public class Player extends LivingEntity implements CommandSender, InventoryHold
|
||||||
public void setGamemode(GameMode gamemode) {
|
public void setGamemode(GameMode gamemode) {
|
||||||
if (!this.gamemode.equals(gamemode)) {
|
if (!this.gamemode.equals(gamemode)) {
|
||||||
try {
|
try {
|
||||||
PacketPlayOutGameState state = new PacketPlayOutGameState(3, gamemode.getId());
|
PacketPlayOutGameStateChange state = new PacketPlayOutGameStateChange(PacketPlayOutGameStateChange.GameStateChangeEvent.CHANGE_GAME_MODE, gamemode.getId());
|
||||||
clientConnection.sendPacket(state);
|
clientConnection.sendPacket(state);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
|
|
|
||||||
|
|
@ -30,7 +30,6 @@ import com.loohp.limbo.network.protocol.packets.PacketPlayOutEntityDestroy;
|
||||||
import com.loohp.limbo.network.protocol.packets.PacketPlayOutEntityMetadata;
|
import com.loohp.limbo.network.protocol.packets.PacketPlayOutEntityMetadata;
|
||||||
import com.loohp.limbo.network.protocol.packets.PacketPlayOutSpawnEntity;
|
import com.loohp.limbo.network.protocol.packets.PacketPlayOutSpawnEntity;
|
||||||
import com.loohp.limbo.network.protocol.packets.PacketPlayOutUnloadChunk;
|
import com.loohp.limbo.network.protocol.packets.PacketPlayOutUnloadChunk;
|
||||||
import com.loohp.limbo.utils.GameMode;
|
|
||||||
import com.loohp.limbo.world.ChunkPosition;
|
import com.loohp.limbo.world.ChunkPosition;
|
||||||
import com.loohp.limbo.world.World;
|
import com.loohp.limbo.world.World;
|
||||||
import net.querz.mca.Chunk;
|
import net.querz.mca.Chunk;
|
||||||
|
|
@ -48,130 +47,117 @@ import java.util.stream.Collectors;
|
||||||
|
|
||||||
public class PlayerInteractManager {
|
public class PlayerInteractManager {
|
||||||
|
|
||||||
private Player player;
|
private Player player;
|
||||||
|
|
||||||
private Set<Entity> entities;
|
private Set<Entity> entities;
|
||||||
private Map<ChunkPosition, Chunk> currentViewing;
|
private Map<ChunkPosition, Chunk> currentViewing;
|
||||||
private final Map<ChunkPosition, Chunk> chunkUpdates;
|
|
||||||
|
|
||||||
public PlayerInteractManager() {
|
public PlayerInteractManager() {
|
||||||
this.player = null;
|
this.player = null;
|
||||||
this.entities = new HashSet<>();
|
this.entities = new HashSet<>();
|
||||||
this.currentViewing = new HashMap<>();
|
this.currentViewing = new HashMap<>();
|
||||||
this.chunkUpdates = new HashMap<>();
|
}
|
||||||
}
|
|
||||||
|
|
||||||
protected void setPlayer(Player player) {
|
protected void setPlayer(Player player) {
|
||||||
if (this.player == null) {
|
if (this.player == null) {
|
||||||
this.player = player;
|
this.player = player;
|
||||||
} else {
|
} else {
|
||||||
throw new RuntimeException("Player in PlayerInteractManager cannot be changed once created");
|
throw new RuntimeException("Player in PlayerInteractManager cannot be changed once created");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Player getPlayer() {
|
public Player getPlayer() {
|
||||||
return player;
|
return player;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void update() throws IOException {
|
public void update() throws IOException {
|
||||||
if (player.clientConnection.getClientState() != ClientConnection.ClientState.PLAY && !player.clientConnection.isReady()) {
|
if (player.clientConnection.getClientState() != ClientConnection.ClientState.PLAY) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
int viewDistanceChunks = Limbo.getInstance().getServerProperties().getViewDistance();
|
int viewDistanceChunks = Limbo.getInstance().getServerProperties().getViewDistance();
|
||||||
int viewDistanceBlocks = viewDistanceChunks << 4;
|
int viewDistanceBlocks = viewDistanceChunks << 4;
|
||||||
Location location = player.getLocation();
|
Location location = player.getLocation();
|
||||||
Set<Entity> entitiesInRange = player.getWorld().getEntities().stream().filter(each -> each.getLocation().distanceSquared(location) < viewDistanceBlocks * viewDistanceBlocks).collect(Collectors.toSet());
|
Set<Entity> entitiesInRange = player.getWorld().getEntities().stream().filter(each -> each.getLocation().distanceSquared(location) < viewDistanceBlocks * viewDistanceBlocks).collect(Collectors.toSet());
|
||||||
for (Entity entity : entitiesInRange) {
|
for (Entity entity : entitiesInRange) {
|
||||||
if (!entities.contains(entity)) {
|
if (!entities.contains(entity)) {
|
||||||
PacketPlayOutSpawnEntity packet = new PacketPlayOutSpawnEntity(entity.getEntityId(), entity.getUniqueId(), entity.getType(), entity.getX(), entity.getY(), entity.getZ(), entity.getYaw(), entity.getPitch(), entity.getPitch(), 0, (short) 0, (short) 0, (short) 0);
|
PacketPlayOutSpawnEntity packet = new PacketPlayOutSpawnEntity(entity.getEntityId(), entity.getUniqueId(), entity.getType(), entity.getX(), entity.getY(), entity.getZ(), entity.getYaw(), entity.getPitch(), entity.getPitch(), 0, (short) 0, (short) 0, (short) 0);
|
||||||
player.clientConnection.sendPacket(packet);
|
player.clientConnection.sendPacket(packet);
|
||||||
|
|
||||||
PacketPlayOutEntityMetadata meta = new PacketPlayOutEntityMetadata(entity);
|
PacketPlayOutEntityMetadata meta = new PacketPlayOutEntityMetadata(entity);
|
||||||
player.clientConnection.sendPacket(meta);
|
player.clientConnection.sendPacket(meta);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
List<Integer> ids = new ArrayList<>();
|
List<Integer> ids = new ArrayList<>();
|
||||||
for (Entity entity : entities) {
|
for (Entity entity : entities) {
|
||||||
if (!entitiesInRange.contains(entity)) {
|
if (!entitiesInRange.contains(entity)) {
|
||||||
ids.add(entity.getEntityId());
|
ids.add(entity.getEntityId());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (int id : ids) {
|
for (int id : ids) {
|
||||||
PacketPlayOutEntityDestroy packet = new PacketPlayOutEntityDestroy(id);
|
PacketPlayOutEntityDestroy packet = new PacketPlayOutEntityDestroy(id);
|
||||||
player.clientConnection.sendPacket(packet);
|
player.clientConnection.sendPacket(packet);
|
||||||
}
|
}
|
||||||
|
|
||||||
entities = entitiesInRange;
|
entities = entitiesInRange;
|
||||||
|
|
||||||
int playerChunkX = (int) location.getX() >> 4;
|
int playerChunkX = (int) location.getX() >> 4;
|
||||||
int playerChunkZ = (int) location.getZ() >> 4;
|
int playerChunkZ = (int) location.getZ() >> 4;
|
||||||
World world = location.getWorld();
|
World world = location.getWorld();
|
||||||
|
|
||||||
Map<ChunkPosition, Chunk> chunksInRange = new HashMap<>();
|
Map<ChunkPosition, Chunk> chunksInRange = new HashMap<>();
|
||||||
|
|
||||||
for (int x = playerChunkX - viewDistanceChunks; x < playerChunkX + viewDistanceChunks; x++) {
|
for (int x = playerChunkX - viewDistanceChunks; x < playerChunkX + viewDistanceChunks; x++) {
|
||||||
for (int z = playerChunkZ - viewDistanceChunks; z < playerChunkZ + viewDistanceChunks; z++) {
|
for (int z = playerChunkZ - viewDistanceChunks; z < playerChunkZ + viewDistanceChunks; z++) {
|
||||||
Chunk chunk = world.getChunkAt(x, z);
|
Chunk chunk = world.getChunkAt(x, z);
|
||||||
if (chunk != null) {
|
if (chunk != null) {
|
||||||
chunksInRange.put(new ChunkPosition(world, x, z), chunk);
|
chunksInRange.put(new ChunkPosition(world, x, z), chunk);
|
||||||
|
} else {
|
||||||
|
chunksInRange.put(new ChunkPosition(world, x, z), World.EMPTY_CHUNK);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Entry<ChunkPosition, Chunk> entry : currentViewing.entrySet()) {
|
||||||
|
ChunkPosition chunkPos = entry.getKey();
|
||||||
|
if (!chunksInRange.containsKey(chunkPos)) {
|
||||||
|
PacketPlayOutUnloadChunk packet = new PacketPlayOutUnloadChunk(chunkPos.getChunkX(), chunkPos.getChunkZ());
|
||||||
|
player.clientConnection.sendPacket(packet);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int counter = 0;
|
||||||
|
ClientboundChunkBatchStartPacket chunkBatchStartPacket = new ClientboundChunkBatchStartPacket();
|
||||||
|
player.clientConnection.sendPacket(chunkBatchStartPacket);
|
||||||
|
for (Entry<ChunkPosition, Chunk> entry : chunksInRange.entrySet()) {
|
||||||
|
ChunkPosition chunkPos = entry.getKey();
|
||||||
|
if (!currentViewing.containsKey(chunkPos)) {
|
||||||
|
Chunk chunk = chunkPos.getWorld().getChunkAt(chunkPos.getChunkX(), chunkPos.getChunkZ());
|
||||||
|
if (chunk == null) {
|
||||||
|
ClientboundLevelChunkWithLightPacket chunkdata = new ClientboundLevelChunkWithLightPacket(chunkPos.getChunkX(), chunkPos.getChunkZ(), entry.getValue(), world.getEnvironment(), Collections.emptyList(), Collections.emptyList());
|
||||||
|
player.clientConnection.sendPacket(chunkdata);
|
||||||
} else {
|
} else {
|
||||||
chunksInRange.put(new ChunkPosition(world, x, z), World.EMPTY_CHUNK);
|
List<Byte[]> blockChunk = world.getLightEngineBlock().getBlockLightBitMask(chunkPos.getChunkX(), chunkPos.getChunkZ());
|
||||||
|
if (blockChunk == null) {
|
||||||
|
blockChunk = new ArrayList<>();
|
||||||
|
}
|
||||||
|
List<Byte[]> skyChunk = null;
|
||||||
|
if (world.hasSkyLight()) {
|
||||||
|
skyChunk = world.getLightEngineSky().getSkyLightBitMask(chunkPos.getChunkX(), chunkPos.getChunkZ());
|
||||||
|
}
|
||||||
|
if (skyChunk == null) {
|
||||||
|
skyChunk = new ArrayList<>();
|
||||||
|
}
|
||||||
|
ClientboundLevelChunkWithLightPacket chunkdata = new ClientboundLevelChunkWithLightPacket(chunkPos.getChunkX(), chunkPos.getChunkZ(), chunk, world.getEnvironment(), skyChunk, blockChunk);
|
||||||
|
player.clientConnection.sendPacket(chunkdata);
|
||||||
}
|
}
|
||||||
|
counter++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
ClientboundChunkBatchFinishedPacket chunkBatchFinishedPacket = new ClientboundChunkBatchFinishedPacket(counter);
|
||||||
|
player.clientConnection.sendPacket(chunkBatchFinishedPacket);
|
||||||
|
|
||||||
for (ChunkPosition chunkPos : currentViewing.keySet()) {
|
currentViewing = chunksInRange;
|
||||||
if (!chunksInRange.containsKey(chunkPos)) {
|
}
|
||||||
PacketPlayOutUnloadChunk packet = new PacketPlayOutUnloadChunk(chunkPos.getChunkX(), chunkPos.getChunkZ());
|
|
||||||
player.clientConnection.sendPacket(packet);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// add chunk candidates for updating
|
|
||||||
chunkUpdates.clear();
|
|
||||||
chunkUpdates.putAll(chunksInRange);
|
|
||||||
|
|
||||||
// blocks cannot be broken, so once we've sent all of them, don't update them anymore
|
|
||||||
if (getPlayer().getGamemode() == GameMode.ADVENTURE) {
|
|
||||||
for (ChunkPosition chunkPos : currentViewing.keySet()) {
|
|
||||||
chunkUpdates.remove(chunkPos);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// if we don't have any chunk updates, don't send any packets
|
|
||||||
if (chunkUpdates.isEmpty()) return;
|
|
||||||
|
|
||||||
int counter = 0;
|
|
||||||
ClientboundChunkBatchStartPacket chunkBatchStartPacket = new ClientboundChunkBatchStartPacket();
|
|
||||||
player.clientConnection.sendPacket(chunkBatchStartPacket);
|
|
||||||
for (Entry<ChunkPosition, Chunk> entry : chunkUpdates.entrySet()) {
|
|
||||||
ChunkPosition chunkPos = entry.getKey();
|
|
||||||
Chunk chunk = chunkPos.getWorld().getChunkAt(chunkPos.getChunkX(), chunkPos.getChunkZ());
|
|
||||||
if (chunk == null) {
|
|
||||||
ClientboundLevelChunkWithLightPacket chunkdata = new ClientboundLevelChunkWithLightPacket(chunkPos.getChunkX(), chunkPos.getChunkZ(), entry.getValue(), world.getEnvironment(), Collections.emptyList(), Collections.emptyList());
|
|
||||||
player.clientConnection.sendPacket(chunkdata);
|
|
||||||
} else {
|
|
||||||
List<Byte[]> blockChunk = world.getLightEngineBlock().getBlockLightBitMask(chunkPos.getChunkX(), chunkPos.getChunkZ());
|
|
||||||
if (blockChunk == null) {
|
|
||||||
blockChunk = new ArrayList<>();
|
|
||||||
}
|
|
||||||
List<Byte[]> skyChunk = null;
|
|
||||||
if (world.hasSkyLight()) {
|
|
||||||
skyChunk = world.getLightEngineSky().getSkyLightBitMask(chunkPos.getChunkX(), chunkPos.getChunkZ());
|
|
||||||
}
|
|
||||||
if (skyChunk == null) {
|
|
||||||
skyChunk = new ArrayList<>();
|
|
||||||
}
|
|
||||||
ClientboundLevelChunkWithLightPacket chunkdata = new ClientboundLevelChunkWithLightPacket(chunkPos.getChunkX(), chunkPos.getChunkZ(), chunk, world.getEnvironment(), skyChunk, blockChunk);
|
|
||||||
player.clientConnection.sendPacket(chunkdata);
|
|
||||||
}
|
|
||||||
counter++;
|
|
||||||
}
|
|
||||||
ClientboundChunkBatchFinishedPacket chunkBatchFinishedPacket = new ClientboundChunkBatchFinishedPacket(counter);
|
|
||||||
player.clientConnection.sendPacket(chunkBatchFinishedPacket);
|
|
||||||
|
|
||||||
currentViewing = chunksInRange;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -48,20 +48,17 @@ public class Registry {
|
||||||
|
|
||||||
static {
|
static {
|
||||||
String name = "registries.json";
|
String name = "registries.json";
|
||||||
File file = new File(Limbo.getInstance().getInternalDataFolder(), name);
|
|
||||||
if (!file.exists()) {
|
|
||||||
try (InputStream in = Limbo.class.getClassLoader().getResourceAsStream(name)) {
|
|
||||||
Files.copy(in, file.toPath());
|
|
||||||
} catch (IOException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Map<Key, Integer> blockEntityType = new HashMap<>();
|
Map<Key, Integer> blockEntityType = new HashMap<>();
|
||||||
Key defaultItemKey = null;
|
Key defaultItemKey = null;
|
||||||
BiMap<Key, Integer> itemIds = HashBiMap.create();
|
BiMap<Key, Integer> itemIds = HashBiMap.create();
|
||||||
Map<Key, Integer> menuIds = new HashMap<>();
|
Map<Key, Integer> menuIds = new HashMap<>();
|
||||||
try (InputStreamReader reader = new InputStreamReader(new FileInputStream(file), StandardCharsets.UTF_8)) {
|
|
||||||
|
InputStream inputStream = Limbo.class.getClassLoader().getResourceAsStream(name);
|
||||||
|
if (inputStream == null) {
|
||||||
|
throw new RuntimeException("Failed to load " + name + " from jar!");
|
||||||
|
}
|
||||||
|
try (InputStreamReader reader = new InputStreamReader(inputStream, StandardCharsets.UTF_8)) {
|
||||||
JSONObject json = (JSONObject) new JSONParser().parse(reader);
|
JSONObject json = (JSONObject) new JSONParser().parse(reader);
|
||||||
|
|
||||||
JSONObject blockEntityJson = (JSONObject) ((JSONObject) json.get("minecraft:block_entity_type")).get("entries");
|
JSONObject blockEntityJson = (JSONObject) ((JSONObject) json.get("minecraft:block_entity_type")).get("entries");
|
||||||
|
|
|
||||||
|
|
@ -37,24 +37,16 @@ public class DimensionRegistry {
|
||||||
|
|
||||||
private CompoundTag defaultTag;
|
private CompoundTag defaultTag;
|
||||||
private CompoundTag codec;
|
private CompoundTag codec;
|
||||||
private File reg;
|
|
||||||
|
|
||||||
public DimensionRegistry() {
|
public DimensionRegistry() {
|
||||||
this.defaultTag = new CompoundTag();
|
this.defaultTag = new CompoundTag();
|
||||||
|
|
||||||
String name = "dimension_registry.json";
|
String name = "dimension_registry.json";
|
||||||
File file = new File(Limbo.getInstance().getInternalDataFolder(), name);
|
|
||||||
if (!file.exists()) {
|
|
||||||
try (InputStream in = Limbo.class.getClassLoader().getResourceAsStream(name)) {
|
|
||||||
Files.copy(in, file.toPath());
|
|
||||||
} catch (IOException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
this.reg = file;
|
InputStream inputStream = Limbo.class.getClassLoader().getResourceAsStream(name);
|
||||||
|
if (inputStream == null) {
|
||||||
try (InputStreamReader reader = new InputStreamReader(Files.newInputStream(reg.toPath()), StandardCharsets.UTF_8)) {
|
throw new RuntimeException("Failed to load " + name + " from jar!");
|
||||||
|
}
|
||||||
|
try (InputStreamReader reader = new InputStreamReader(inputStream, StandardCharsets.UTF_8)) {
|
||||||
JSONObject json = (JSONObject) new JSONParser().parse(reader);
|
JSONObject json = (JSONObject) new JSONParser().parse(reader);
|
||||||
CompoundTag tag = CustomNBTUtils.getCompoundTagFromJson((JSONObject) json.get("value"));
|
CompoundTag tag = CustomNBTUtils.getCompoundTagFromJson((JSONObject) json.get("value"));
|
||||||
defaultTag = tag;
|
defaultTag = tag;
|
||||||
|
|
@ -64,10 +56,6 @@ public class DimensionRegistry {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public File getFile() {
|
|
||||||
return reg;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void resetCodec() {
|
public void resetCodec() {
|
||||||
codec = defaultTag.clone();
|
codec = defaultTag.clone();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,8 @@ import java.io.File;
|
||||||
import java.io.FileReader;
|
import java.io.FileReader;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
@ -41,17 +43,12 @@ public class GeneratedBlockDataMappings {
|
||||||
|
|
||||||
static {
|
static {
|
||||||
String block = "blocks.json";
|
String block = "blocks.json";
|
||||||
File file = new File(Limbo.getInstance().getInternalDataFolder(), block);
|
InputStream inputStream = Limbo.class.getClassLoader().getResourceAsStream(block);
|
||||||
if (!file.exists()) {
|
if (inputStream == null) {
|
||||||
try (InputStream in = Limbo.class.getClassLoader().getResourceAsStream(block)) {
|
throw new RuntimeException("Failed to load " + block + " from jar!");
|
||||||
Files.copy(in, file.toPath());
|
}
|
||||||
} catch (IOException e) {
|
try (InputStreamReader reader = new InputStreamReader(inputStream, StandardCharsets.UTF_8)) {
|
||||||
e.printStackTrace();
|
globalPalette = (JSONObject) new JSONParser().parse(reader);
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
globalPalette = (JSONObject) new JSONParser().parse(new FileReader(file));
|
|
||||||
} catch (IOException | ParseException e) {
|
} catch (IOException | ParseException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -43,12 +43,12 @@
|
||||||
"PacketPlayOutLogin": "0x29",
|
"PacketPlayOutLogin": "0x29",
|
||||||
"PacketPlayOutPositionAndLook": "0x3E",
|
"PacketPlayOutPositionAndLook": "0x3E",
|
||||||
"PacketPlayOutSpawnPosition": "0x54",
|
"PacketPlayOutSpawnPosition": "0x54",
|
||||||
"PacketPlayOutGameEvent": "0x20",
|
|
||||||
"ClientboundSystemChatPacket": "0x69",
|
"ClientboundSystemChatPacket": "0x69",
|
||||||
"PacketPlayOutPlayerAbilities": "0x36",
|
"PacketPlayOutPlayerAbilities": "0x36",
|
||||||
"ClientboundLevelChunkWithLightPacket": "0x25",
|
"ClientboundLevelChunkWithLightPacket": "0x25",
|
||||||
"PacketPlayOutUnloadChunk": "0x1F",
|
"PacketPlayOutUnloadChunk": "0x1F",
|
||||||
"PacketPlayOutKeepAlive": "0x15",
|
"PacketPlayOutKeepAlive": "0x15",
|
||||||
|
"PacketPlayOutGameStateChange": "0x20",
|
||||||
"PacketPlayOutPlayerInfo": "0x3C",
|
"PacketPlayOutPlayerInfo": "0x3C",
|
||||||
"PacketPlayOutUpdateViewPosition": "0x52",
|
"PacketPlayOutUpdateViewPosition": "0x52",
|
||||||
"PacketPlayOutDisconnect": "0x1B",
|
"PacketPlayOutDisconnect": "0x1B",
|
||||||
|
|
@ -56,7 +56,6 @@
|
||||||
"PacketPlayOutTabComplete": "0x10",
|
"PacketPlayOutTabComplete": "0x10",
|
||||||
"PacketPlayOutDeclareCommands": "0x11",
|
"PacketPlayOutDeclareCommands": "0x11",
|
||||||
"PacketPlayOutRespawn": "0x45",
|
"PacketPlayOutRespawn": "0x45",
|
||||||
"PacketPlayOutGameState": "0x20",
|
|
||||||
"PacketPlayOutEntityDestroy": "0x40",
|
"PacketPlayOutEntityDestroy": "0x40",
|
||||||
"PacketPlayOutEntityMetadata": "0x56",
|
"PacketPlayOutEntityMetadata": "0x56",
|
||||||
"PacketPlayOutSpawnEntity": "0x01",
|
"PacketPlayOutSpawnEntity": "0x01",
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue