mirror of https://github.com/LOOHP/Limbo.git
Add support for transfers; closes #81
Signed-off-by: Joshua Castle <26531652+Kas-tle@users.noreply.github.com>
This commit is contained in:
parent
1bfe4cf7d4
commit
ec697a133f
2
pom.xml
2
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.15-ALPHA</version>
|
<version>0.7.16-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>
|
||||||
|
|
|
||||||
|
|
@ -41,6 +41,7 @@ import com.loohp.limbo.player.Player;
|
||||||
import com.loohp.limbo.plugins.LimboPlugin;
|
import com.loohp.limbo.plugins.LimboPlugin;
|
||||||
import com.loohp.limbo.plugins.PluginManager;
|
import com.loohp.limbo.plugins.PluginManager;
|
||||||
import com.loohp.limbo.scheduler.LimboScheduler;
|
import com.loohp.limbo.scheduler.LimboScheduler;
|
||||||
|
import com.loohp.limbo.scheduler.LimboTask;
|
||||||
import com.loohp.limbo.scheduler.Tick;
|
import com.loohp.limbo.scheduler.Tick;
|
||||||
import com.loohp.limbo.utils.CustomStringUtils;
|
import com.loohp.limbo.utils.CustomStringUtils;
|
||||||
import com.loohp.limbo.utils.ImageUtils;
|
import com.loohp.limbo.utils.ImageUtils;
|
||||||
|
|
@ -542,4 +543,31 @@ public final class Limbo {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void transferAll(String host, int port, int batchDelayTicks, int batchSize) {
|
||||||
|
if (batchDelayTicks <= 0 || batchSize <= 0) {
|
||||||
|
for (Player player : getPlayers()) {
|
||||||
|
player.transfer(host, port);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
long totalDelay = 0;
|
||||||
|
Set<Player> currentBatch = new HashSet<>();
|
||||||
|
List<Player> players = new ArrayList<>(getPlayers());
|
||||||
|
|
||||||
|
for (int i = 0; i < players.size(); i++) {
|
||||||
|
currentBatch.add(players.get(i));
|
||||||
|
if (currentBatch.size() < batchSize && i != players.size() - 1) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
Set<Player> batch = new HashSet<>(currentBatch);
|
||||||
|
LimboTask task = () -> {
|
||||||
|
for (Player p : batch) {
|
||||||
|
p.transfer(host, port);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
Limbo.getInstance().getScheduler().runTaskLater(null, task, totalDelay);
|
||||||
|
totalDelay += batchDelayTicks;
|
||||||
|
currentBatch.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -180,6 +180,77 @@ public class DefaultCommands implements CommandExecutor, TabCompletor {
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (args[0].equalsIgnoreCase("transfer")) {
|
||||||
|
if (sender.hasPermission("limboserver.transfer")) {
|
||||||
|
if (args.length == 4) {
|
||||||
|
Player player = Limbo.getInstance().getPlayer(args[1]);
|
||||||
|
if (player != null) {
|
||||||
|
String host = args[2];
|
||||||
|
int port;
|
||||||
|
try {
|
||||||
|
port = Integer.parseInt(args[3]);
|
||||||
|
} catch (NumberFormatException e) {
|
||||||
|
sender.sendMessage(ChatColor.RED + "Invalid port number!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
player.transfer(host, port);
|
||||||
|
sender.sendMessage(ChatColor.GOLD + "Transferred " + player.getName() + " to " + host + ":" + port);
|
||||||
|
} else {
|
||||||
|
sender.sendMessage(ChatColor.RED + "Player is not online!");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
sender.sendMessage(ChatColor.RED + "Invalid usage! Use: /transfer <player> <host> <port>");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
sender.sendMessage(ChatColor.RED + "You do not have permission to use that command!");
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (args[0].equalsIgnoreCase("transferall")) {
|
||||||
|
if (sender.hasPermission("limboserver.transfer")) {
|
||||||
|
if (args.length >= 3 && args.length <= 5) {
|
||||||
|
String host = args[1];
|
||||||
|
int port;
|
||||||
|
int batchDelay;
|
||||||
|
int batchSize;
|
||||||
|
try {
|
||||||
|
port = Integer.parseInt(args[2]);
|
||||||
|
} catch (NumberFormatException e) {
|
||||||
|
sender.sendMessage(ChatColor.RED + "Invalid port!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (args.length == 4) {
|
||||||
|
try {
|
||||||
|
batchDelay = Integer.parseInt(args[3]);
|
||||||
|
} catch (NumberFormatException e) {
|
||||||
|
sender.sendMessage(ChatColor.RED + "Invalid batch delay ticks!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
batchSize = 1;
|
||||||
|
} else if (args.length == 5) {
|
||||||
|
try {
|
||||||
|
batchDelay = Integer.parseInt(args[3]);
|
||||||
|
batchSize = Integer.parseInt(args[4]);
|
||||||
|
} catch (NumberFormatException e) {
|
||||||
|
sender.sendMessage(ChatColor.RED + "Invalid batch delay ticks or size!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
batchDelay = 1;
|
||||||
|
batchSize = 10;
|
||||||
|
}
|
||||||
|
Limbo.getInstance().transferAll(host, port, batchDelay, batchSize);
|
||||||
|
sender.sendMessage(ChatColor.GOLD + "Transferred all players to " + host + ":" + port);
|
||||||
|
} else {
|
||||||
|
sender.sendMessage(ChatColor.RED + "Invalid usage! Use: /transferall <host> <port> [<batchDelayTicks> <batchSize>]");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
sender.sendMessage(ChatColor.RED + "You do not have permission to use that command!");
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -202,6 +273,10 @@ public class DefaultCommands implements CommandExecutor, TabCompletor {
|
||||||
if (sender.hasPermission("limboserver.gamemode")) {
|
if (sender.hasPermission("limboserver.gamemode")) {
|
||||||
tab.add("gamemode");
|
tab.add("gamemode");
|
||||||
}
|
}
|
||||||
|
if (sender.hasPermission("limboserver.transfer")) {
|
||||||
|
tab.add("transfer");
|
||||||
|
tab.add("transferall");
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
if (sender.hasPermission("limboserver.spawn")) {
|
if (sender.hasPermission("limboserver.spawn")) {
|
||||||
|
|
@ -229,6 +304,14 @@ public class DefaultCommands implements CommandExecutor, TabCompletor {
|
||||||
tab.add("gamemode");
|
tab.add("gamemode");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (sender.hasPermission("limboserver.transfer")) {
|
||||||
|
if ("transfer".startsWith(args[0].toLowerCase())) {
|
||||||
|
tab.add("transfer");
|
||||||
|
}
|
||||||
|
if ("transferall".startsWith(args[0].toLowerCase())) {
|
||||||
|
tab.add("transferall");
|
||||||
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
if (sender.hasPermission("limboserver.kick")) {
|
if (sender.hasPermission("limboserver.kick")) {
|
||||||
|
|
@ -249,6 +332,15 @@ public class DefaultCommands implements CommandExecutor, TabCompletor {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (sender.hasPermission("limboserver.transfer")) {
|
||||||
|
if (args[0].equalsIgnoreCase("transfer")) {
|
||||||
|
for (Player player : Limbo.getInstance().getPlayers()) {
|
||||||
|
if (player.getName().toLowerCase().startsWith(args[1].toLowerCase())) {
|
||||||
|
tab.add(player.getName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
if (sender.hasPermission("limboserver.gamemode")) {
|
if (sender.hasPermission("limboserver.gamemode")) {
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,59 @@
|
||||||
|
/*
|
||||||
|
* 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 com.loohp.limbo.registry.PacketRegistry;
|
||||||
|
import com.loohp.limbo.utils.DataTypeIO;
|
||||||
|
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
|
import java.io.DataOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
|
||||||
|
public class ClientboundTransferPacket extends PacketOut {
|
||||||
|
|
||||||
|
private final String host;
|
||||||
|
private final int port;
|
||||||
|
|
||||||
|
public ClientboundTransferPacket(String host, int port) {
|
||||||
|
this.host = host;
|
||||||
|
this.port = port;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getHost() {
|
||||||
|
return host;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getPort() {
|
||||||
|
return port;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public byte[] serializePacket() throws IOException {
|
||||||
|
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
|
||||||
|
|
||||||
|
DataOutputStream output = new DataOutputStream(buffer);
|
||||||
|
output.writeByte(PacketRegistry.getPacketId(getClass()));
|
||||||
|
DataTypeIO.writeString(output, host, StandardCharsets.UTF_8);
|
||||||
|
DataTypeIO.writeVarInt(output, port);
|
||||||
|
|
||||||
|
return buffer.toByteArray();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -45,6 +45,7 @@ import com.loohp.limbo.network.protocol.packets.ClientboundSetSubtitleTextPacket
|
||||||
import com.loohp.limbo.network.protocol.packets.ClientboundSetTitleTextPacket;
|
import com.loohp.limbo.network.protocol.packets.ClientboundSetTitleTextPacket;
|
||||||
import com.loohp.limbo.network.protocol.packets.ClientboundSetTitlesAnimationPacket;
|
import com.loohp.limbo.network.protocol.packets.ClientboundSetTitlesAnimationPacket;
|
||||||
import com.loohp.limbo.network.protocol.packets.ClientboundSystemChatPacket;
|
import com.loohp.limbo.network.protocol.packets.ClientboundSystemChatPacket;
|
||||||
|
import com.loohp.limbo.network.protocol.packets.ClientboundTransferPacket;
|
||||||
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.PacketPlayOutGameStateChange;
|
import com.loohp.limbo.network.protocol.packets.PacketPlayOutGameStateChange;
|
||||||
|
|
@ -650,4 +651,13 @@ public class Player extends LivingEntity implements CommandSender, InventoryHold
|
||||||
public InventoryHolder getHolder() {
|
public InventoryHolder getHolder() {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void transfer(String host, int port) {
|
||||||
|
try {
|
||||||
|
ClientboundTransferPacket transferPacket = new ClientboundTransferPacket(host, port);
|
||||||
|
clientConnection.sendPacket(transferPacket);
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -35,6 +35,7 @@ import com.loohp.limbo.network.protocol.packets.ClientboundSetSubtitleTextPacket
|
||||||
import com.loohp.limbo.network.protocol.packets.ClientboundSetTitleTextPacket;
|
import com.loohp.limbo.network.protocol.packets.ClientboundSetTitleTextPacket;
|
||||||
import com.loohp.limbo.network.protocol.packets.ClientboundSetTitlesAnimationPacket;
|
import com.loohp.limbo.network.protocol.packets.ClientboundSetTitlesAnimationPacket;
|
||||||
import com.loohp.limbo.network.protocol.packets.ClientboundSystemChatPacket;
|
import com.loohp.limbo.network.protocol.packets.ClientboundSystemChatPacket;
|
||||||
|
import com.loohp.limbo.network.protocol.packets.ClientboundTransferPacket;
|
||||||
import com.loohp.limbo.network.protocol.packets.Packet;
|
import com.loohp.limbo.network.protocol.packets.Packet;
|
||||||
import com.loohp.limbo.network.protocol.packets.PacketHandshakingIn;
|
import com.loohp.limbo.network.protocol.packets.PacketHandshakingIn;
|
||||||
import com.loohp.limbo.network.protocol.packets.PacketLoginInLoginStart;
|
import com.loohp.limbo.network.protocol.packets.PacketLoginInLoginStart;
|
||||||
|
|
@ -220,6 +221,7 @@ public class PacketRegistry {
|
||||||
registerClass(PacketPlayOutWindowData.class, "minecraft:container_set_data", NetworkPhase.PLAY, PacketBound.CLIENTBOUND);
|
registerClass(PacketPlayOutWindowData.class, "minecraft:container_set_data", NetworkPhase.PLAY, PacketBound.CLIENTBOUND);
|
||||||
registerClass(ClientboundChunkBatchFinishedPacket.class, "minecraft:chunk_batch_finished", NetworkPhase.PLAY, PacketBound.CLIENTBOUND);
|
registerClass(ClientboundChunkBatchFinishedPacket.class, "minecraft:chunk_batch_finished", NetworkPhase.PLAY, PacketBound.CLIENTBOUND);
|
||||||
registerClass(ClientboundChunkBatchStartPacket.class, "minecraft:chunk_batch_start", NetworkPhase.PLAY, PacketBound.CLIENTBOUND);
|
registerClass(ClientboundChunkBatchStartPacket.class, "minecraft:chunk_batch_start", NetworkPhase.PLAY, PacketBound.CLIENTBOUND);
|
||||||
|
registerClass(ClientboundTransferPacket.class, "minecraft:transfer", NetworkPhase.PLAY, PacketBound.CLIENTBOUND);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void registerClass(Class<? extends Packet> packetClass, String key, NetworkPhase networkPhase, PacketBound packetBound) {
|
private static void registerClass(Class<? extends Packet> packetClass, String key, NetworkPhase networkPhase, PacketBound packetBound) {
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ groups:
|
||||||
- limboserver.kick
|
- limboserver.kick
|
||||||
- limboserver.say
|
- limboserver.say
|
||||||
- limboserver.gamemode
|
- limboserver.gamemode
|
||||||
|
- limboserver.transfer
|
||||||
default:
|
default:
|
||||||
- limboserver.spawn
|
- limboserver.spawn
|
||||||
- limboserver.chat
|
- limboserver.chat
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue