Converted some of the management server to kotlin

Added json configs for management server
Cleaned up some files
This commit is contained in:
Woah
2021-03-08 03:55:45 -05:00
parent ca2e5520b0
commit 439b2e9ef8
114 changed files with 820 additions and 1476 deletions
@@ -6,10 +6,12 @@ import ms.net.packet.WorldPacketRepository;
import ms.system.ShutdownSequence;
import ms.system.mysql.SQLManager;
import ms.system.util.Command;
import ms.system.util.ManagementConfigParser;
import ms.world.GameServer;
import ms.world.PlayerSession;
import ms.world.WorldDatabase;
import java.io.File;
import java.io.IOException;
import java.net.InetAddress;
import java.net.NetworkInterface;
@@ -128,6 +130,7 @@ public final class Management {
}
System.out.println("-------- 530 Management server --------");
System.out.println("Starting up...");
new ManagementConfigParser("managementprops" + File.separator + "properties.json");
SQLManager.init();
//NioReactor.configure(ServerConstants.PORT).start();
NioReactor.configure(5555).start();
@@ -8,16 +8,6 @@ import ms.system.OperatingSystem;
*
*/
public final class ServerConstants {
/**
* The port to be used for communications.
*/
public static final String SERVER_NAME = "2009Scape";
/**
* The port to be used for communications.
*/
public static final int PORT = 5555;
/**
* The maximum amount of worlds.
@@ -27,22 +17,12 @@ public final class ServerConstants {
/**
* The world switching delay in milliseconds.
*/
public static final long WORLD_SWITCH_DELAY = 20_000l;
public static final long WORLD_SWITCH_DELAY = 20_000L;
/**
* The address of the Management server.
*/
public static final String HOST_ADDRESS = "127.0.0.1";
/**
* The store path.
*/
public static final String STORE_PATH = "./store/";
/**
* The maximum amount of players per world.
*/
public static final int MAX_PLAYERS = (1 << 11) - 1;
/**
* The operating system of the management server
@@ -1,25 +1,23 @@
package ms.net.packet;
package ms.net.packet
/**
* Represents the types of packet headers.
* @author Emperor
*
*/
public enum PacketHeader {
enum class PacketHeader {
/**
* The normal packet header.
*/
NORMAL,
/**
* The byte packet header.
*/
BYTE,
/**
* The short packet header.
*/
SHORT;
/**
* The normal packet header.
*/
NORMAL,
/**
* The byte packet header.
*/
BYTE,
/**
* The short packet header.
*/
SHORT
}
@@ -1,587 +0,0 @@
package ms.net.packet;
import java.nio.ByteBuffer;
import java.util.List;
import ms.ServerConstants;
import ms.net.IoSession;
import ms.system.PunishmentStorage;
import ms.world.GameServer;
import ms.world.PlayerSession;
import ms.world.WorldDatabase;
import ms.system.communication.ClanRank;
import ms.system.communication.ClanRepository;
import ms.system.communication.CommunicationInfo;
import ms.world.info.Response;
import ms.world.info.UIDInfo;
/**
* Repository class for world packets.
* @author Emperor
*
*/
public final class WorldPacketRepository {
/**
* Sends the player registry response.
* @param server The game server.
* @param player The player session.
* @param response The registry response.
*/
public static void sendRegistryResponse(GameServer server, PlayerSession player, Response response) {
IoBuffer buffer = new IoBuffer(0, PacketHeader.BYTE);
buffer.putString(player.getUsername());
buffer.put((byte) response.opcode());
if (response == Response.MOVING_WORLD) {
long delay = ServerConstants.WORLD_SWITCH_DELAY - (System.currentTimeMillis() - player.getDisconnectionTime());
buffer.put((byte) (delay / 1000));
}
server.getSession().write(buffer);
}
/**
* Sends a message to the player.
* @param player The player.
* @param message The message to send.
*/
public static void sendPlayerMessage(PlayerSession player, String message) {
if (player == null) {
return;
}
IoBuffer buffer = new IoBuffer(2, PacketHeader.BYTE);
buffer.putString(player.getUsername());
buffer.putString(message);
player.getWorld().getSession().write(buffer);
}
public static void sendPlayerMessage(PlayerSession player, String[] messages) {
if (player == null) {
return;
}
for (String message : messages)
sendPlayerMessage(player, message);
}
/**
* Sends the contact information.
* @param player The player.
*/
public static void sendContactInformation(PlayerSession player) {
CommunicationInfo info = player.getCommunication();
IoBuffer buffer = new IoBuffer(3, PacketHeader.SHORT);
buffer.putString(player.getUsername());
buffer.put(info.getContacts().size());
for (String contact : info.getContacts().keySet()) {
buffer.putString(contact);
buffer.put(info.getRank(contact).ordinal());
buffer.put(CommunicationInfo.getWorldId(player, contact));
}
buffer.put(info.getBlocked().size());
for (String contact : info.getBlocked()) {
buffer.putString(contact);
}
if (info.getCurrentClan() == null) {
buffer.put(0);
} else {
buffer.put(1);
buffer.putString(info.getCurrentClan());
}
player.getWorld().getSession().write(buffer);
}
/**
* Sends a contact update.
* @param player The player who's contacts we're changing.
* @param contact The contact to update.
* @param block If we're updating the blocked list.
* @param remove If the contact should be removed.
* @param worldId The world id of the contact.
* @param rank The clan rank.
*/
public static void sendContactUpdate(PlayerSession player, String contact, boolean block, boolean remove, int worldId, ClanRank rank) {
IoBuffer buffer = new IoBuffer(4, PacketHeader.BYTE);
buffer.putString(player.getUsername());
buffer.putString(contact);
buffer.put((byte) (block ? 1 : 0));
if (rank != null) {
buffer.put((byte) (2 + rank.ordinal()));
} else {
buffer.put((byte) (remove ? 1 : 0));
if (!block && !remove) {
buffer.put((byte) worldId);
}
}
player.getWorld().getSession().write(buffer);
}
/**
* Sends a clan message.
* @param player The player to send the message to.
* @param p The player sending the message.
* @param message The message to send.
* @param type The message type.
*/
public static void sendMessage(PlayerSession player, PlayerSession p, int type, String message) {
IoBuffer buffer = new IoBuffer(5, PacketHeader.BYTE);
buffer.putString(player.getUsername());
buffer.putString(p.getUsername());
buffer.put((byte) type);
buffer.put((byte) p.getChatIcon());
buffer.putString(message);
player.getWorld().getSession().write(buffer);
}
/**
* Sends clan information to the server.
* @param server The server.
* @param clan The clan.
*/
public static void sendClanInformation(GameServer server, ClanRepository clan) {
IoBuffer buffer = new IoBuffer(6, PacketHeader.SHORT);
buffer.putString(clan.getOwner().getUsername());
buffer.putString(clan.getName());
int length = clan.getPlayers().size();
if (length > ClanRepository.MAX_MEMBERS) {
length = ClanRepository.MAX_MEMBERS;
}
buffer.put((byte) length);
for (int i = 0; i < length; i++) {
PlayerSession player = clan.getPlayers().get(i);
buffer.putString(player.getUsername());
buffer.put(player.getWorldId());
buffer.put((byte) clan.getRank(player).ordinal());
}
buffer.put((byte) clan.getJoinRequirement().ordinal());
buffer.put((byte) clan.getKickRequirement().ordinal());
buffer.put((byte) clan.getMessageRequirement().ordinal());
buffer.put((byte) clan.getLootRequirement().ordinal());
server.getSession().write(buffer);
}
/**
* Sends the leave clan packet.
* @param player The player leaving the clan.
*/
public static void sendLeaveClan(PlayerSession player) {
IoBuffer buffer = new IoBuffer(7, PacketHeader.BYTE);
buffer.putString(player.getUsername());
player.getWorld().getSession().write(buffer);
}
/**
* Sends the player login notification.
* @param server The server.
* @param player The player logging in.
* @param names The names.
*/
public static void notifyPlayers(GameServer server, PlayerSession player, List<String> names) {
IoBuffer buffer = new IoBuffer(8, PacketHeader.SHORT);
buffer.putString(player.getUsername());
buffer.put((byte) player.getWorldId());
buffer.put((byte) names.size());
for (String name : names) {
buffer.putString(name);
}
server.getSession().write(buffer);
}
/**
* Notifies the game server a player logged out.
* @param server The game server to notify.
* @param player The player logging out.
*/
public static void notifyLogout(GameServer server, PlayerSession player) {
IoBuffer buffer = new IoBuffer(9, PacketHeader.BYTE);
buffer.putString(player.getUsername());
server.getSession().write(buffer);
}
/**
* Sends the update countdown to the server.
* @param server The server.
* @param ticks The amount of ticks left.
*/
public static void sendUpdate(GameServer server, int ticks) {
IoBuffer buffer = new IoBuffer(10);
buffer.putInt(ticks);
server.getSession().write(buffer);
}
/**
* Sends the punishment update packet.
* @param world The world to send the packet to.
* @param key The punishment key.
* @param type The punishment type.
* @param duration The duration of the punishment.
*/
public static void sendPunishUpdate(GameServer world, String key, int type, long duration) {
IoBuffer buffer = new IoBuffer(11, PacketHeader.BYTE);
buffer.putString(key);
buffer.put((byte) type);
buffer.putLong(duration);
world.getSession().write(buffer);
}
/**
* Sends a configuration reload.
* @param world the world.
*/
public static void sendConfigReload(GameServer world) {
world.getSession().write(new IoBuffer(15, PacketHeader.BYTE));
}
/**
* Handles incoming world packets.
* @param session The I/O session.
* @param opcode The opcode.
* @param b The buffer to read from.
*/
public static void handleIncoming(IoSession session, int opcode, ByteBuffer b) {
IoBuffer buffer = new IoBuffer(opcode, PacketHeader.NORMAL, b);
GameServer server = session.getGameServer();
switch (opcode) {
case 0:
handlePlayerRegistration(server, buffer);
break;
case 1:
handlePlayerRemoval(server, buffer);
break;
case 2:
handlePunishment(server, buffer);
break;
case 3:
handleCommunicationRequest(server, buffer);
break;
case 4:
case 5:
handleContactUpdate(server, buffer, opcode == 5);
break;
case 6:
handleJoinClan(server, buffer);
break;
case 7:
handleClanRename(server, buffer);
break;
case 8:
handleClanSetting(server, buffer);
break;
case 9:
handleClanKick(server, buffer);
break;
case 10:
handleClanMessage(server, buffer);
break;
case 11:
handlePrivateMessage(server, buffer);
break;
case 12:
handleClanInfoRequest(server, buffer);
break;
case 13:
handleChatSetting(server, buffer);
break;
case 14:
handleInfoUpdate(server, buffer);
break;
default:
System.err.println("Handling incoming packet [opcode=" + opcode + ", size=" + b.limit() + "].");
}
}
/**
* Handles the info of a player update.
* @param server the server.
* @param buffer the buffer.
*/
private static void handleInfoUpdate(GameServer server, IoBuffer buffer) {
String username = buffer.getString();
PlayerSession player = server.getPlayers().get(username);
if (player != null) {
player.setChatIcon((int) buffer.get());
}
}
/**
* Handles a player registration.
* @param server The game server.
* @param buffer The buffer.
*/
private static void handlePlayerRegistration(GameServer server, IoBuffer buffer) {
String username = buffer.getString();
String password = buffer.getString();
String ipAddress = buffer.getString();
String macAddress = buffer.getString();
String compName = buffer.getString();
String serial = buffer.getString();
int rights = server.getInfo().getRevision() == 498 ? 0 : buffer.getInt();
int chatIcon = server.getInfo().getRevision() == 498 ? 0 : buffer.get();
UIDInfo uid = new UIDInfo(ipAddress, compName, macAddress, serial);
PlayerSession player = new PlayerSession(username, password, new UIDInfo(ipAddress, compName, macAddress, serial));
if (WorldDatabase.isActivePlayer(username)) {
sendRegistryResponse(server, player, Response.ALREADY_ONLINE);
return;
}
player.setUid(uid);
player.setRights(rights);
player.setChatIcon(chatIcon);
if (PunishmentStorage.isSystemBanned(uid)) {
sendRegistryResponse(server, player, Response.BANNED);
return;
}
player.parse();
if (player.isBanned()) {
sendRegistryResponse(server, player, Response.ACCOUNT_DISABLED);
return;
}
if (player.getLastWorld() != server.getInfo().getWorldId() && player.hasMovedWorld()) {
sendRegistryResponse(server, player, Response.MOVING_WORLD);
return;
}
server.register(player);
}
/**
* Handles the removal of a player.
* @param server The game server.
* @param buffer The buffer.
*/
private static void handlePlayerRemoval(GameServer server, IoBuffer buffer) {
String username = buffer.getString();
PlayerSession session = server.getPlayers().get(username);
if (session != null) {
session.setActive(false);
PlayerSession player = server.getPlayers().remove(username);
if (player != null) {
session.remove();
}
session.setWorldId(0);
}
}
/**
* Handles a player registration.
* @param server The game server.
* @param buffer The buffer.
*/
private static void handlePunishment(GameServer server, IoBuffer buffer) {
int type = buffer.get() & 0xFF;
String target = buffer.getString();
long duration = buffer.getLong();
String staff = buffer.getString();
PunishmentStorage.handlePunishment(staff, target, type, duration);
}
/**
* Handles the communication info request packet.
* @param server The game server.
* @param buffer The buffer.
*/
private static void handleCommunicationRequest(GameServer server, IoBuffer buffer) {
String username = buffer.getString();
PlayerSession player = server.getPlayers().get(username);
if (player == null) {
return;
}
sendContactInformation(player);
}
/**
* Handles a contact update packet.
* @param server The server.
* @param buffer The buffer to read from.
* @param block If the list is for blocked players.
*/
private static void handleContactUpdate(GameServer server, IoBuffer buffer, boolean block) {
String username = buffer.getString();
PlayerSession player = server.getPlayers().get(username);
if (player == null) {
return;
}
String contact = buffer.getString();
switch (buffer.get()) {
case 0:
if (block) {
player.getCommunication().block(contact);
break;
}
player.getCommunication().add(contact);
break;
case 1:
player.getCommunication().remove(contact, block);
break;
case 2:
player.getCommunication().updateClanRank(contact, ClanRank.values()[buffer.get()]);
break;
}
}
/**
* Handles a clan related packet.
* @param server The game server.
* @param buffer The buffer.
*/
private static void handleJoinClan(GameServer server, IoBuffer buffer) {
String name = buffer.getString();
String clanName = buffer.getString();
PlayerSession player = server.getPlayers().get(name);
if (player == null || !player.isActive()) {
System.err.println("Invalid player specified in clan packet!");
return;
}
if (player.getClan() != null) {
player.getClan().leave(player, true);
return;
}
if (clanName.length() < 1) {
sendLeaveClan(player);
return;
}
ClanRepository clan = ClanRepository.get(server, clanName);
if (clan == null) {
sendPlayerMessage(player, new String[]{ "The channel you tried to join does not exist.", "Try joining the main clan named '" + ServerConstants.SERVER_NAME + "'.:clan:" });
return;
}
clan.enter(player);
}
/**
* Handles renaming a clan.
* @param server The server.
* @param buffer The buffer.
*/
private static void handleClanRename(GameServer server, IoBuffer buffer) {
String username = buffer.getString();
String name = buffer.getString();
PlayerSession player = server.getPlayers().get(username);
if (player == null || !player.isActive()) {
return;
}
ClanRepository clan = ClanRepository.getClans().get(username);
player.getCommunication().setClanName(name);
if (clan != null) {
if (name.length() < 1) {
clan.clean(true);
} else {
clan.rename(name);
}
}
}
/**
* Handles changing clan settings packet.
* @param server The game server.
* @param buffer The buffer.
*/
private static void handleClanSetting(GameServer server, IoBuffer buffer) {
String username = buffer.getString();
int type = buffer.get();
ClanRank rank = type < 4 ? ClanRank.values()[buffer.get() & 0xFF] : null;
PlayerSession player = server.getPlayers().get(username);
if (player == null || !player.isActive()) {
return;
}
ClanRepository clan = ClanRepository.get(server,username);
switch (type) {
case 0:
player.getCommunication().setJoinRequirement(rank);
if (clan != null) {
clan.clean(false);
}
break;
case 1:
player.getCommunication().setMessageRequirement(rank);
break;
case 2:
player.getCommunication().setKickRequirement(rank);
if (clan != null) {
clan.update();
}
break;
case 3:
player.getCommunication().setLootRequirement(rank);
break;
}
}
/**
* Handles kicking a player from the clan.
* @param server The game server.
* @param buffer The buffer.
*/
private static void handleClanKick(GameServer server, IoBuffer buffer) {
String username = buffer.getString();
String playerName = buffer.getString();
PlayerSession player = server.getPlayers().get(username);
if (player == null || !player.isActive() || player.getClan() == null) {
return;
}
PlayerSession target = WorldDatabase.getPlayer(playerName);
if (target == null || !target.isActive()) {
return;
}
player.getClan().kick(player, target);
}
/**
* Handles a clan message.
* @param server The game server.
* @param buffer The buffer.
*/
private static void handleClanMessage(GameServer server, IoBuffer buffer) {
String username = buffer.getString();
String message = buffer.getString();
PlayerSession player = server.getPlayers().get(username);
if (player == null || !player.isActive() || player.getClan() == null) {
return;
}
player.getClan().message(player, message);
}
/**
* Handles a clan message.
* @param server The game server.
* @param buffer The buffer.
*/
private static void handlePrivateMessage(GameServer server, IoBuffer buffer) {
String username = buffer.getString();
String receiver = buffer.getString();
String message = buffer.getString();
PlayerSession player = server.getPlayers().get(username);
if (player == null || !player.isActive()) {
return;
}
player.getCommunication().sendMessage(receiver, message);
}
/**
* Handles a clan information request packet.
* @param server The server.
* @param buffer The buffer.
*/
private static void handleClanInfoRequest(GameServer server, IoBuffer buffer) {
String name = buffer.getString();
ClanRepository clan = ClanRepository.get(server, name);
if (clan == null) {
return;
}
sendClanInformation(server, clan);
}
/**
* Handles a chat setting update packet.
* @param server The server.
* @param buffer The buffer.
*/
private static void handleChatSetting(GameServer server, IoBuffer buffer) {
String name = buffer.getString();
int publicSetting = buffer.get();
int privateSetting = buffer.get();
int tradeSetting = buffer.get();
PlayerSession player = server.getPlayers().get(name);
if (player == null || !player.isActive()) {
return;
}
player.getCommunication().updateSettings(publicSetting, privateSetting, tradeSetting);
}
}
@@ -0,0 +1,555 @@
package ms.net.packet
import ms.net.IoSession
import ms.system.PunishmentStorage
import ms.system.communication.ClanRank
import ms.system.communication.ClanRepository
import ms.system.communication.CommunicationInfo
import ms.system.util.ManagementConstants.Companion.WORLD_HOP_DELAY
import ms.world.GameServer
import ms.world.PlayerSession
import ms.world.WorldDatabase
import ms.world.info.Response
import ms.world.info.UIDInfo
import java.nio.ByteBuffer
/**
* Repository class for world packets.
* @author Emperor
*/
object WorldPacketRepository {
/**
* Sends the player registry response.
* @param server The game server.
* @param player The player session.
* @param response The registry response.
*/
@JvmStatic
fun sendRegistryResponse(server: GameServer, player: PlayerSession, response: Response) {
val buffer = IoBuffer(0, PacketHeader.BYTE)
buffer.putString(player.username)
buffer.put(response.opcode())//byte
if (response == Response.MOVING_WORLD) {
val delay: Long = WORLD_HOP_DELAY - (System.currentTimeMillis() - player.disconnectionTime)
buffer.put((delay / 1000).toInt())
}
server.session.write(buffer)
}
/**
* Sends a message to the player.
* @param player The player.
* @param message The message to send.
*/
@JvmStatic
fun sendPlayerMessage(player: PlayerSession?, message: String?) {
if (player == null) {
return
}
val buffer = IoBuffer(2, PacketHeader.BYTE)
buffer.putString(player.username)
buffer.putString(message)
player.world.session.write(buffer)
}
fun sendPlayerMessage(player: PlayerSession?, messages: Array<String?>) {
if (player == null) {
return
}
for (message in messages) sendPlayerMessage(player, message)
}
/**
* Sends the contact information.
* @param player The player.
*/
fun sendContactInformation(player: PlayerSession) {
val info = player.communication
val buffer = IoBuffer(3, PacketHeader.SHORT)
buffer.putString(player.username)
buffer.put(info.contacts.size)
for (contact in info.contacts.keys) {
buffer.putString(contact)
buffer.put(info.getRank(contact).ordinal)
buffer.put(CommunicationInfo.getWorldId(player, contact))
}
buffer.put(info.blocked.size)
for (contact in info.blocked) {
buffer.putString(contact)
}
if (info.currentClan == null) {
buffer.put(0)
} else {
buffer.put(1)
buffer.putString(info.currentClan)
}
player.world.session.write(buffer)
}
/**
* Sends a contact update.
* @param player The player who's contacts we're changing.
* @param contact The contact to update.
* @param block If we're updating the blocked list.
* @param remove If the contact should be removed.
* @param worldId The world id of the contact.
* @param rank The clan rank.
*/
@JvmStatic
fun sendContactUpdate(
player: PlayerSession,
contact: String?,
block: Boolean,
remove: Boolean,
worldId: Int,
rank: ClanRank?
) {
val buffer = IoBuffer(4, PacketHeader.BYTE)
buffer.putString(player.username)
buffer.putString(contact)
buffer.put((if (block) 1 else 0))
if (rank != null) {
buffer.put((2 + rank.ordinal))
} else {
buffer.put((if (remove) 1 else 0))
if (!block && !remove) {
buffer.put(worldId)
}
}
player.world.session.write(buffer)
}
/**
* Sends a clan message.
* @param player The player to send the message to.
* @param p The player sending the message.
* @param message The message to send.
* @param type The message type.
*/
@JvmStatic
fun sendMessage(player: PlayerSession, p: PlayerSession, type: Int, message: String?) {
val buffer = IoBuffer(5, PacketHeader.BYTE)
buffer.putString(player.username)
buffer.putString(p.username)
buffer.put(type)
buffer.put(p.chatIcon)
buffer.putString(message)
println("Send Message: ${player.username} -> ${p.username} T: $type ICO: ${p.chatIcon} $message")
player.world.session.write(buffer)
}
/**
* Sends clan information to the server.
* @param server The server.
* @param clan The clan.
*/
@JvmStatic
fun sendClanInformation(server: GameServer, clan: ClanRepository) {
val buffer = IoBuffer(6, PacketHeader.SHORT)
buffer.putString(clan.owner.username)
buffer.putString(clan.name)
var length = clan.players.size
if (length > ClanRepository.MAX_MEMBERS) {
length = ClanRepository.MAX_MEMBERS
}
buffer.put(length)
for (i in 0 until length) {
val player = clan.players[i]
buffer.putString(player.username)
buffer.put(player.worldId)
buffer.put(clan.getRank(player).ordinal)
}
buffer.put(clan.joinRequirement.ordinal)
buffer.put(clan.kickRequirement.ordinal)
buffer.put(clan.messageRequirement.ordinal)
buffer.put(clan.lootRequirement.ordinal)
server.session.write(buffer)
}
/**
* Sends the leave clan packet.
* @param player The player leaving the clan.
*/
@JvmStatic
fun sendLeaveClan(player: PlayerSession) {
val buffer = IoBuffer(7, PacketHeader.BYTE)
buffer.putString(player.username)
player.world.session.write(buffer)
}
/**
* Sends the player login notification.
* @param server The server.
* @param player The player logging in.
* @param names The names.
*/
@JvmStatic
fun notifyPlayers(server: GameServer, player: PlayerSession, names: List<String?>) {
val buffer = IoBuffer(8, PacketHeader.SHORT)
buffer.putString(player.username)
buffer.put(player.worldId)
buffer.put(names.size)
for (name in names) {
buffer.putString(name)
}
server.session.write(buffer)
}
/**
* Notifies the game server a player logged out.
* @param server The game server to notify.
* @param player The player logging out.
*/
@JvmStatic
fun notifyLogout(server: GameServer, player: PlayerSession) {
val buffer = IoBuffer(9, PacketHeader.BYTE)
buffer.putString(player.username)
server.session.write(buffer)
}
/**
* Sends the update countdown to the server.
* @param server The server.
* @param ticks The amount of ticks left.
*/
@JvmStatic
fun sendUpdate(server: GameServer, ticks: Int) {
val buffer = IoBuffer(10)
buffer.putInt(ticks)
server.session.write(buffer)
}
/**
* Sends the punishment update packet.
* @param world The world to send the packet to.
* @param key The punishment key.
* @param type The punishment type.
* @param duration The duration of the punishment.
*/
@JvmStatic
fun sendPunishUpdate(world: GameServer, key: String?, type: Int, duration: Long) {
val buffer = IoBuffer(11, PacketHeader.BYTE)
buffer.putString(key)
buffer.put(type)
buffer.putLong(duration)
world.session.write(buffer)
}
/**
* Sends a configuration reload.
* @param world the world.
*/
@JvmStatic
fun sendConfigReload(world: GameServer) {
world.session.write(IoBuffer(15, PacketHeader.BYTE))
}
/**
* Handles incoming world packets.
* @param session The I/O session.
* @param opcode The opcode.
* @param b The buffer to read from.
*/
@JvmStatic
fun handleIncoming(session: IoSession, opcode: Int, b: ByteBuffer) {
val buffer = IoBuffer(opcode, PacketHeader.NORMAL, b)
val server = session.gameServer
when (opcode) {
0 -> handlePlayerRegistration(server, buffer)
1 -> handlePlayerRemoval(server, buffer)
2 -> handlePunishment(server, buffer)
3 -> handleCommunicationRequest(server, buffer)
4, 5 -> handleContactUpdate(server, buffer, opcode == 5)
6 -> handleJoinClan(server, buffer)
7 -> handleClanRename(server, buffer)
8 -> handleClanSetting(server, buffer)
9 -> handleClanKick(server, buffer)
10 -> handleClanMessage(server, buffer)
11 -> handlePrivateMessage(server, buffer)
12 -> handleClanInfoRequest(server, buffer)
13 -> handleChatSetting(server, buffer)
14 -> handleInfoUpdate(server, buffer)
else -> System.err.println("Handling incoming packet [opcode=" + opcode + ", size=" + b.limit() + "].")
}
}
/**
* Handles the info of a player update.
* @param server the server.
* @param buffer the buffer.
*/
private fun handleInfoUpdate(server: GameServer, buffer: IoBuffer) {
val username = buffer.string
val player = server.players[username]
if (player != null) {
player.chatIcon = buffer.get()
}
}
/**
* Handles a player registration.
* @param server The game server.
* @param buffer The buffer.
*/
private fun handlePlayerRegistration(server: GameServer, buffer: IoBuffer) {
val username = buffer.string
val password = buffer.string
val ipAddress = buffer.string
val macAddress = buffer.string
val compName = buffer.string
val serial = buffer.string
val rights = buffer.int
val chatIcon = buffer.get()
val uid = UIDInfo(ipAddress, compName, macAddress, serial)
val player = PlayerSession(username, password, UIDInfo(ipAddress, compName, macAddress, serial))
if (WorldDatabase.isActivePlayer(username)) {
sendRegistryResponse(server, player, Response.ALREADY_ONLINE)
return
}
player.uid = uid
player.rights = rights
player.chatIcon = chatIcon
if (PunishmentStorage.isSystemBanned(uid)) {
sendRegistryResponse(server, player, Response.BANNED)
return
}
player.parse()
if (player.isBanned) {
sendRegistryResponse(server, player, Response.ACCOUNT_DISABLED)
return
}
if (player.lastWorld != server.info.worldId && player.hasMovedWorld()) {
sendRegistryResponse(server, player, Response.MOVING_WORLD)
return
}
server.register(player)
}
/**
* Handles the removal of a player.
* @param server The game server.
* @param buffer The buffer.
*/
private fun handlePlayerRemoval(server: GameServer, buffer: IoBuffer) {
val username = buffer.string
val session = server.players[username]
if (session != null) {
session.isActive = false
val player = server.players.remove(username)
if (player != null) {
session.remove()
}
session.worldId = 0
}
}
/**
* Handles a player registration.
* @param server The game server.
* @param buffer The buffer.
*/
private fun handlePunishment(server: GameServer, buffer: IoBuffer) {
val type = buffer.get() and 0xFF
val target = buffer.string
val duration = buffer.long
val staff = buffer.string
PunishmentStorage.handlePunishment(staff, target, type, duration)
}
/**
* Handles the communication info request packet.
* @param server The game server.
* @param buffer The buffer.
*/
private fun handleCommunicationRequest(server: GameServer, buffer: IoBuffer) {
val username = buffer.string
val player = server.players[username] ?: return
sendContactInformation(player)
}
/**
* Handles a contact update packet.
* @param server The server.
* @param buffer The buffer to read from.
* @param block If the list is for blocked players.
*/
private fun handleContactUpdate(server: GameServer, buffer: IoBuffer, block: Boolean) {
val username = buffer.string
val player = server.players[username] ?: return
val contact = buffer.string
when (buffer.get()) {
0 -> {
if (block) {
player.communication.block(contact)
}
player.communication.add(contact)
}
1 -> player.communication.remove(contact, block)
2 -> player.communication.updateClanRank(contact, ClanRank.values()[buffer.get()])
}
}
/**
* Handles a clan related packet.
* @param server The game server.
* @param buffer The buffer.
*/
private fun handleJoinClan(server: GameServer, buffer: IoBuffer) {
val name = buffer.string
val clanName = buffer.string
val player = server.players[name]
if (player == null || !player.isActive) {
System.err.println("Invalid player specified in clan packet!")
return
}
if (player.clan != null) {
player.clan.leave(player, true)
return
}
if (clanName.length < 1) {
sendLeaveClan(player)
return
}
val clan = ClanRepository.get(server, clanName)
if (clan == null) {
sendPlayerMessage(
player,
arrayOf(
"The channel you tried to join does not exist.",
"Try joining the main clan named '2009Scape'.:clan:"
)
)
return
}
clan.enter(player)
}
/**
* Handles renaming a clan.
* @param server The server.
* @param buffer The buffer.
*/
private fun handleClanRename(server: GameServer, buffer: IoBuffer) {
val username = buffer.string
val name = buffer.string
val player = server.players[username]
if (player == null || !player.isActive) {
return
}
val clan = ClanRepository.getClans()[username]
player.communication.clanName = name
if (clan != null) {
if (name.isEmpty()) {
clan.clean(true)
} else {
clan.rename(name)
}
}
}
/**
* Handles changing clan settings packet.
* @param server The game server.
* @param buffer The buffer.
*/
private fun handleClanSetting(server: GameServer, buffer: IoBuffer) {
val username = buffer.string
val type = buffer.get()
val rank = if (type < 4) ClanRank.values()[buffer.get() and 0xFF] else null
val player = server.players[username]
if (player == null || !player.isActive) {
return
}
val clan = ClanRepository.get(server, username)
when (type) {
0 -> {
player.communication.joinRequirement = rank
clan?.clean(false)
}
1 -> player.communication.messageRequirement = rank
2 -> {
player.communication.kickRequirement = rank
clan?.update()
}
3 -> player.communication.lootRequirement = rank
}
}
/**
* Handles kicking a player from the clan.
* @param server The game server.
* @param buffer The buffer.
*/
private fun handleClanKick(server: GameServer, buffer: IoBuffer) {
val username = buffer.string
val playerName = buffer.string
val player = server.players[username]
if (player == null || !player.isActive || player.clan == null) {
return
}
val target = WorldDatabase.getPlayer(playerName)
if (target == null || !target.isActive) {
return
}
player.clan.kick(player, target)
}
/**
* Handles a clan message.
* @param server The game server.
* @param buffer The buffer.
*/
private fun handleClanMessage(server: GameServer, buffer: IoBuffer) {
val username = buffer.string
val message = buffer.string
val player = server.players[username]
if (player == null || !player.isActive || player.clan == null) {
return
}
player.clan.message(player, message)
}
/**
* Handles a clan message.
* @param server The game server.
* @param buffer The buffer.
*/
private fun handlePrivateMessage(server: GameServer, buffer: IoBuffer) {
val username = buffer.string
val receiver = buffer.string
val message = buffer.string
val player = server.players[username]
if (player == null || !player.isActive) {
return
}
player.communication.sendMessage(receiver, message)
}
/**
* Handles a clan information request packet.
* @param server The server.
* @param buffer The buffer.
*/
private fun handleClanInfoRequest(server: GameServer, buffer: IoBuffer) {
val name = buffer.string
val clan = ClanRepository.get(server, name) ?: return
sendClanInformation(server, clan)
}
/**
* Handles a chat setting update packet.
* @param server The server.
* @param buffer The buffer.
*/
private fun handleChatSetting(server: GameServer, buffer: IoBuffer) {
val name = buffer.string
val publicSetting = buffer.get()
val privateSetting = buffer.get()
val tradeSetting = buffer.get()
val player = server.players[name]
if (player == null || !player.isActive) {
return
}
player.communication.updateSettings(publicSetting, privateSetting, tradeSetting)
}
}
@@ -1,13 +1,9 @@
package ms.system;
package ms.system
/**
* The operating systems
* @author Clayton Williams
*
*/
public enum OperatingSystem {
UNIX,
WINDOWS
}
enum class OperatingSystem {
UNIX, WINDOWS
}
@@ -476,11 +476,6 @@ public final class CommunicationInfo {
* @return The rank.
*/
public ClanRank getRank(String contact) {
for (String name : ServerConstants.ADMINISTRATORS) {
if (contact.equals(name)) {
return ClanRank.ADMINISTRATOR;
}
}
return contacts.get(contact);
}
@@ -1,100 +0,0 @@
package ms.system.mysql;
import ms.ServerConstants;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
/**
* Manages the sql connections.
* @author Vexia
*
*/
public final class SQLManager {
/**
* If the sql manager is locally hosted.
*/
public static final boolean LOCAL = true;
/**
* The database URL.
*/
public static final String DATABASE_URL = (LOCAL ? "127.0.0.1" : "keldagrim.org") + ":3306/" + (SQLManager.LOCAL ? "global" : ServerConstants.DATABASE_NAMES[1]);
/**
* The username of the user.
*/
private static final String USERNAME = (LOCAL ? "root" : "keldagr1_user");
/**
* The password of the user.
*/
private static final String PASSWORD = (LOCAL ? "" : "2jf4wkz$");
/**
* IF the sql manager is initialized.
*/
private static boolean initialized;
/**
* Constructs a new {@code SQLManager} {@code Object}
*/
public SQLManager() {
/**
* empty.
*/
}
/**
* Initializes the sql manager.
*/
public static void init() {
initialized = true;
WorldListSQLHandler.clearWorldList();
}
/**
* Gets a connection from the pool.
* @return The connection.
*/
public static Connection getConnection() {
try {
return DriverManager.getConnection("jdbc:mysql://" + DATABASE_URL + "?useTimezone=true&serverTimezone=UTC", USERNAME, PASSWORD);
} catch (SQLException e) {
System.out.println("Error: Mysql error message=" + e.getMessage() + ".");
}
return null;
}
/**
* Releases the connection so it's available for usage.
* @param connection The connection.
*/
public static void close(Connection connection) {
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
/**
* Gets the initialized.
* @return the initialized
*/
public static boolean isInitialized() {
return initialized;
}
/**
* Sets the bainitialized.
* @param initialized the initialized to set.
*/
public static void setInitialized(boolean initialized) {
SQLManager.initialized = initialized;
}
}
@@ -0,0 +1,64 @@
package ms.system.mysql
import ms.system.util.ManagementConstants
import ms.system.util.ManagementConstants.Companion.DATABASE_HOST_ADDRESS
import ms.system.util.ManagementConstants.Companion.DATABASE_NAME
import ms.system.util.ManagementConstants.Companion.DATABASE_PASSWORD
import ms.system.util.ManagementConstants.Companion.DATABASE_PORT
import ms.system.util.ManagementConstants.Companion.DATABASE_USERNAME
import java.sql.Connection
import java.sql.DriverManager
import java.sql.SQLException
/**
* Manages the sql connections.
* @author Vexia
*/
object SQLManager {
/**
* IF the sql manager is initialized.
*/
var isInitialized = false
/**
* Initializes the sql manager.
*/
@JvmStatic
fun init() {
isInitialized = true
WorldListSQLHandler.clearWorldList()
}
/**
* Gets a connection from the pool.
* @return The connection.
*/
@JvmStatic
val connection: Connection?
get() {
try {
return DriverManager.getConnection(
"jdbc:mysql://$DATABASE_HOST_ADDRESS:$DATABASE_PORT/$DATABASE_NAME?useTimezone=true&serverTimezone=UTC",
DATABASE_USERNAME,
DATABASE_PASSWORD
)
} catch (e: SQLException) {
println("Error: Mysql error message=" + e.message + ".")
}
return null
}
/**
* Releases the connection so it's available for usage.
* @param connection The connection.
*/
@JvmStatic
fun close(connection: Connection) {
try {
connection.close()
} catch (e: SQLException) {
e.printStackTrace()
}
}
}
@@ -0,0 +1,70 @@
package ms.system.util
import org.json.simple.JSONObject
import org.json.simple.parser.JSONParser
import java.io.File
import java.io.FileReader
import kotlin.system.exitProcess
/**
* Class for parsing the server config, I.E default.json
* @param path the path to the JSON file to parse.
* @author Ceikry
*/
class ManagementConfigParser(path: String) {
val pathTo = parsePath(path)
val confFile = File(pathTo)
val parser = JSONParser()
var reader: FileReader? = null
var data: JSONObject? = null
init {
if(!confFile.canonicalFile.exists()){
println("Could not find ${confFile.canonicalFile} - Double check your working directory!")
exitProcess(0)
} else if(!pathTo.contains(".json")) {
println("Config file MUST be a JSON file!!")
println("(Got $pathTo)")
} else {
reader = FileReader(pathTo)
data = parser.parse(reader) as JSONObject
parseDatabaseInformation()
parseWorldTechnicalSettings()
}
}
private fun parseDatabaseInformation(){
data ?: return
val dbData = data!!["DatabaseInformation"] as JSONObject
ManagementConstants().parseDBProp(dbData)
}
private fun parseWorldTechnicalSettings(){
data ?: return
val wtiData = data!!["WorldTechnicalInformation"] as JSONObject
ManagementConstants().parseWTIProp(wtiData)
}
/**
* Parses a path string
* @author Ceikry
* @param pathString The string to parse
* @return a String with the proper file separators for the current OS.
*/
fun parsePath(pathString: String): String {
var pathTokens: List<String>? = null
if(pathString.contains("/"))
pathTokens = pathString.split("/")
else if(pathString.contains("\\"))
pathTokens = pathString.split("\\")
pathTokens ?: return pathString //return the initial pathString if path does not contain file separators.
var pathProduct = ""
for(token in pathTokens){
if(token != "")
pathProduct += "$token${File.separator}"
}
return pathProduct
}
}
@@ -0,0 +1,45 @@
package ms.system.util
import org.json.simple.JSONObject
class ManagementConstants {
companion object {
//MySQL main database name
var DATABASE_NAME: String = "global"
//MySQL database username
var DATABASE_USERNAME: String = "root"
//MySQL database password
var DATABASE_PASSWORD: String = ""
//MySQL host
var DATABASE_HOST_ADDRESS: String = "127.0.0.1"
//MySQL port
var DATABASE_PORT: Int = 3306
//Max amount of worlds supported on the world list
var MAX_WORLD_AMOUNT: Int = 10
//User world hop delay in seconds
var WORLD_HOP_DELAY: Long = 20_000L
}
fun parseDBProp(data: JSONObject) {
DATABASE_NAME = data["database_name"].toString()
DATABASE_USERNAME = data["database_username"].toString()
DATABASE_PASSWORD = data["database_password"].toString()
DATABASE_HOST_ADDRESS = data["database_host"].toString()
DATABASE_PORT = data["database_port"].toString().toInt()
}
fun parseWTIProp(data: JSONObject) {
MAX_WORLD_AMOUNT = data["world_limit"].toString().toInt()
WORLD_HOP_DELAY = data["worldhop_delay"].toString().toLong()
}
}
@@ -47,13 +47,13 @@ public class WorldDatabase {
buf.putShort((short) 0);
buf.put((byte) 1);
IoBuffer buffer = new IoBuffer();
if (updateStamp != (int) WorldDatabase.updateStamp) {
if (updateStamp == (int) WorldDatabase.updateStamp) {
buf.put((byte) 0);
} else {
buf.put((byte) 1); // Indicates an update occured.
putWorldListinfo(buffer);
} else {
buf.put((byte) 0);
}
putPlayerInfo(buffer);
putPlayerInfo(buffer);
if (buffer.toByteBuffer().position() > 0) {
buf.put((ByteBuffer) buffer.toByteBuffer().flip());
}
@@ -85,18 +85,21 @@ public class WorldDatabase {
buffer.putJagString(capitalize(country.name().toLowerCase()));
}
}
/*
* Stole this from a library so we don't need the dependency
*/
/**
* Converts a string to a capitalized string
* @param name
* @return
*/
private static String capitalize(String name) {
if (name != null && name.length() != 0) {
if (name == null || name.length() == 0) {
return name;
} else {
char[] chars = name.toCharArray();
chars[0] = Character.toUpperCase(chars[0]);
return new String(chars);
} else {
return name;
}
}
}
/**
* Adds the world configuration on the packet.