Purpose:
This tutorial will guide you to fix the notorious server-wide crash that every Winterlove-based server suffers from. This tutorial will eliminate the need for "server restarters" and other similar software.
Difficulty
Surprisingly, this tutorial is very easy to use. I would rate it about a 3/10.
Let's get started!
The main cause of crashes in Winterlove is a problem during the parsing process of incoming packets. Occasionally, a malformed packet will be received and this will cause a logic error to happen inside the PlayerHandler process() method. This will cause the main thread loop to exit, and the server shuts down. We will fix this by adding proper exception handling to the PlayerHandler class.
Step 1: Add exception handling to the packet-parsing phase
Find this block of code, inside PlayerHandler, in the process() method:
Code:
for(int i = 0; i < maxPlayers; i++) {
if(players[i] == null || !players[i].isActive) continue;
players[i].actionAmount--;
players[i].preProcessing();
while(players[i].process());
players[i].postProcessing();
players[i].getNextPlayerMovement();
if(players[i].playerName.equalsIgnoreCase(kickNick))
{
players[i].kick();
kickNick="";
}
if(players[i].disconnected) {
if(saveGame(players[i])){ System.out.println("Game saved for player "+players[i].playerName); } else { System.out.println("Could not save for "+players[i].playerName); };
removePlayer(players[i]);
players[i] = null;
}
}
Now, replace that chunk with the following chunk of code:
Code:
for(int i = 0; i < maxPlayers; i++) {
if(players[i] == null || !players[i].isActive) continue;
try {
players[i].actionAmount--;
players[i].preProcessing();
while(players[i].process());
players[i].postProcessing();
players[i].getNextPlayerMovement();
if(players[i].playerName.equalsIgnoreCase(kickNick))
{
players[i].kick();
kickNick="";
}
if(players[i].disconnected) {
if(saveGame(players[i])){ System.out.println("Game saved for player "+players[i].playerName); } else { System.out.println("Could not save for "+players[i].playerName); };
removePlayer(players[i]);
players[i] = null;
}
} catch (Exception ex) {
}
}
Step 2: Add exception handling to the player-updating phase:
Find this block of code, inside PlayerHandler, in the process() method:
Code:
for(int i = 0; i < maxPlayers; i++) {
if(players[i] == null || !players[i].isActive) continue;
if(players[i].disconnected) {
if(saveGame(players[i])){ System.out.println("Game saved for player "+players[i].playerName); } else { System.out.println("Could not save for "+players[i].playerName); };
removePlayer(players[i]);
players[i] = null;
}
else {
if(!players[i].initialized) {
players[i].initialize();
players[i].initialized = true;
}
else players[i].update();
}
}
Now, replace that block of code with this block of code:
Code:
for(int i = 0; i < maxPlayers; i++) {
try {
if(players[i] == null || !players[i].isActive) continue;
if(players[i].disconnected) {
if(saveGame(players[i])){ System.out.println("Game saved for player "+players[i].playerName); } else { System.out.println("Could not save for "+players[i].playerName); };
removePlayer(players[i]);
players[i] = null;
}
else {
if(!players[i].initialized) {
players[i].initialize();
players[i].initialized = true;
}
else players[i].update();
}
} catch (Exception ex) {
}
}
You have just properly added exception handling to your Winterlove server. Now, when a malformed packet or other stream error occurs for a player, the player will disconnect/reconnect, but the server will not shut down and no other players will suffer.
Enjoy.
Credits: blakeman8192