mirror of
https://gitlab.bixilon.de/bixilon/minosoft.git
synced 2025-09-22 12:01:38 -04:00
Improvements, fixes, LogPrintStream
The server list cell now has a border according to its connection state: Connecting/Loading: Yellow, Disconnecting: Orange, Failed: Red, Playing: Green Some fixes with multithreading in the connection. MultiBlockChange with AIR will not throw a NullPointerException All calls to System.out and System.err will be logged with the logger
This commit is contained in:
parent
caad618d3f
commit
26f96a3504
@ -112,6 +112,9 @@ public class VersionTweaker {
|
||||
}
|
||||
|
||||
public static Block transformBlock(Block originalBlock, Chunk chunk, InChunkSectionLocation location, byte sectionHeight) {
|
||||
if (originalBlock == null) {
|
||||
return null;
|
||||
}
|
||||
switch (originalBlock.getFullIdentifier()) {
|
||||
case "minecraft:grass" -> {
|
||||
Block above = getBlockAbove(chunk, location, sectionHeight);
|
||||
|
@ -225,6 +225,7 @@ public class ServerListCell extends ListCell<Server> implements Initializable {
|
||||
// clear all cells
|
||||
setStyle(null);
|
||||
this.root.getStyleClass().removeAll("list-cell-connected");
|
||||
this.root.getStyleClass().removeAll("list-cell-connecting");
|
||||
this.motdField.getChildren().clear();
|
||||
this.brandField.setText("");
|
||||
this.brandField.setTooltip(null);
|
||||
@ -285,6 +286,7 @@ public class ServerListCell extends ListCell<Server> implements Initializable {
|
||||
if (!this.canConnect || this.server.getLastPing() == null) {
|
||||
return;
|
||||
}
|
||||
this.root.getStyleClass().add("list-cell-connecting");
|
||||
new Thread(() -> {
|
||||
Connection connection = new Connection(Connection.lastConnectionId++, this.server.getAddress(), new Player(Minosoft.getConfig().getSelectedAccount()));
|
||||
Version version;
|
||||
@ -314,19 +316,27 @@ public class ServerListCell extends ListCell<Server> implements Initializable {
|
||||
return;
|
||||
}
|
||||
Platform.runLater(() -> {
|
||||
this.root.getStyleClass().removeAll("list-cell-connecting");
|
||||
this.root.getStyleClass().removeAll("list-cell-connected");
|
||||
this.root.getStyleClass().removeAll("list-cell-disconnecting");
|
||||
this.root.getStyleClass().removeAll("list-cell-failed");
|
||||
this.root.getStyleClass().add(switch (connection.getConnectionState()) {
|
||||
case CONNECTING, HANDSHAKING, LOGIN -> "list-cell-connecting";
|
||||
case PLAY -> "list-cell-connected";
|
||||
case DISCONNECTING -> "list-cell-disconnecting";
|
||||
case FAILED, FAILED_NO_RETRY -> "list-cell-failed";
|
||||
default -> "";
|
||||
});
|
||||
|
||||
if (!connection.isConnected()) {
|
||||
// maybe we got disconnected
|
||||
if (!this.server.isConnected()) {
|
||||
setStyle(null);
|
||||
this.root.getStyleClass().removeAll("list-cell-connected");
|
||||
this.optionsSessions.setDisable(true);
|
||||
this.optionsConnect.setDisable(false);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
this.optionsConnect.setDisable(Minosoft.getConfig().getSelectedAccount() == connection.getPlayer().getAccount());
|
||||
this.root.getStyleClass().add("list-cell-connected");
|
||||
this.optionsSessions.setDisable(false);
|
||||
});
|
||||
}
|
||||
|
@ -168,7 +168,6 @@ public class Connection {
|
||||
}
|
||||
|
||||
public void disconnect() {
|
||||
setConnectionState(ConnectionStates.DISCONNECTING);
|
||||
this.network.disconnect();
|
||||
this.handleThread.interrupt();
|
||||
}
|
||||
@ -287,12 +286,14 @@ public class Connection {
|
||||
}
|
||||
|
||||
public void setConnectionState(ConnectionStates state) {
|
||||
if (this.state == state) {
|
||||
return;
|
||||
}
|
||||
Log.verbose("ConnectionState changed: " + state);
|
||||
ConnectionStates previousState = this.state;
|
||||
this.state = state;
|
||||
synchronized (state) {
|
||||
if (this.state == state) {
|
||||
return;
|
||||
}
|
||||
Log.verbose("ConnectionState changed: " + state);
|
||||
this.state = state;
|
||||
}
|
||||
switch (state) {
|
||||
case HANDSHAKING -> {
|
||||
// get and add all events, that are connection specific
|
||||
@ -435,8 +436,12 @@ public class Connection {
|
||||
this.pong = pong;
|
||||
}
|
||||
|
||||
public boolean shouldDisconnect() {
|
||||
return getConnectionState() == ConnectionStates.DISCONNECTING || getConnectionState() == ConnectionStates.DISCONNECTED || getConnectionState() == ConnectionStates.FAILED || getConnectionState() == ConnectionStates.FAILED_NO_RETRY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("(id=%d, address=%s, account=\"%s\")", getConnectionId(), getAddress(), getPlayer().getAccount());
|
||||
return String.format("(id=%d, address=%s, account=\"%s\")", getConnectionId(), getAddress(), ((this.player == null) ? null : getPlayer().getAccount()));
|
||||
}
|
||||
}
|
||||
|
@ -86,7 +86,7 @@ public abstract class Network {
|
||||
if (this.connection.getConnectionState() == ConnectionStates.PLAY) {
|
||||
throw new PacketParseException(e);
|
||||
}
|
||||
throw new RuntimeException(e);
|
||||
throw new UnknownPacketException(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -94,7 +94,7 @@ public class BlockingSocketNetwork extends Network {
|
||||
|
||||
initSendThread();
|
||||
|
||||
this.socketReceiveThread.setName(String.format("%d/SocketR", this.connection.getConnectionId()));
|
||||
this.socketReceiveThread.setName(String.format("%d/SocketReceive", this.connection.getConnectionId()));
|
||||
|
||||
|
||||
while (this.connection.getConnectionState() != ConnectionStates.DISCONNECTING) {
|
||||
@ -107,13 +107,15 @@ public class BlockingSocketNetwork extends Network {
|
||||
Log.printException(e, LogLevels.PROTOCOL);
|
||||
}
|
||||
}
|
||||
disconnect();
|
||||
this.connection.disconnect();
|
||||
} catch (Throwable e) {
|
||||
// Could not connect
|
||||
this.connection.setConnectionState(ConnectionStates.DISCONNECTING);
|
||||
if (this.socketSendThread != null) {
|
||||
this.socketSendThread.interrupt();
|
||||
}
|
||||
if (e instanceof SocketException && e.getMessage().equals("Socket closed")) {
|
||||
this.connection.setConnectionState(ConnectionStates.DISCONNECTED);
|
||||
return;
|
||||
}
|
||||
Log.printException(e, LogLevels.PROTOCOL);
|
||||
@ -131,7 +133,12 @@ public class BlockingSocketNetwork extends Network {
|
||||
|
||||
@Override
|
||||
public void disconnect() {
|
||||
if (this.connection.shouldDisconnect()) {
|
||||
// already trying
|
||||
return;
|
||||
}
|
||||
this.connection.setConnectionState(ConnectionStates.DISCONNECTING);
|
||||
this.queue.clear();
|
||||
try {
|
||||
this.socket.close();
|
||||
} catch (IOException e) {
|
||||
@ -180,7 +187,7 @@ public class BlockingSocketNetwork extends Network {
|
||||
}
|
||||
} catch (IOException | InterruptedException ignored) {
|
||||
}
|
||||
}, String.format("%d/SocketS", this.connection.getConnectionId()));
|
||||
}, String.format("%d/SocketSend", this.connection.getConnectionId()));
|
||||
this.socketSendThread.start();
|
||||
}
|
||||
|
||||
|
@ -176,6 +176,7 @@ public class NonBlockingSocketNetwork extends Network {
|
||||
return;
|
||||
}
|
||||
this.connection.setConnectionState(ConnectionStates.DISCONNECTING);
|
||||
this.queue.clear();
|
||||
try {
|
||||
this.socketChannel.close();
|
||||
} catch (IOException e) {
|
||||
|
@ -1,69 +0,0 @@
|
||||
/*
|
||||
* Minosoft
|
||||
* Copyright (C) 2020 Moritz Zwerger
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with this program.If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
|
||||
*/
|
||||
|
||||
package de.bixilon.minosoft.protocol.protocol;
|
||||
|
||||
import com.google.common.collect.HashBiMap;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public final class Protocol {
|
||||
private static final HashMap<ConnectionStates, HashBiMap<Packets.Serverbound, Integer>> SERVERBOUND_PACKET_MAPPING = new HashMap<>();
|
||||
private static final HashMap<ConnectionStates, HashBiMap<Packets.Clientbound, Integer>> CLIENTBOUND_PACKET_MAPPING = new HashMap<>();
|
||||
|
||||
static {
|
||||
SERVERBOUND_PACKET_MAPPING.put(ConnectionStates.HANDSHAKING, HashBiMap.create(Map.of(
|
||||
Packets.Serverbound.HANDSHAKING_HANDSHAKE, 0x00
|
||||
)));
|
||||
|
||||
SERVERBOUND_PACKET_MAPPING.put(ConnectionStates.STATUS, HashBiMap.create(Map.of(
|
||||
Packets.Serverbound.STATUS_REQUEST, 0x00,
|
||||
Packets.Serverbound.STATUS_PING, 0x01)
|
||||
));
|
||||
|
||||
SERVERBOUND_PACKET_MAPPING.put(ConnectionStates.LOGIN, HashBiMap.create(Map.of(
|
||||
Packets.Serverbound.LOGIN_LOGIN_START, 0x00,
|
||||
Packets.Serverbound.LOGIN_ENCRYPTION_RESPONSE, 0x01,
|
||||
Packets.Serverbound.LOGIN_PLUGIN_RESPONSE, 0x02
|
||||
)));
|
||||
|
||||
SERVERBOUND_PACKET_MAPPING.put(ConnectionStates.PLAY, HashBiMap.create());
|
||||
|
||||
// clientbound
|
||||
|
||||
CLIENTBOUND_PACKET_MAPPING.put(ConnectionStates.STATUS, HashBiMap.create(Map.of(
|
||||
Packets.Clientbound.STATUS_RESPONSE, 0x00,
|
||||
Packets.Clientbound.STATUS_PONG, 0x01
|
||||
)));
|
||||
|
||||
CLIENTBOUND_PACKET_MAPPING.put(ConnectionStates.LOGIN, HashBiMap.create(Map.of(
|
||||
Packets.Clientbound.LOGIN_DISCONNECT, 0x00,
|
||||
Packets.Clientbound.LOGIN_ENCRYPTION_REQUEST, 0x01,
|
||||
Packets.Clientbound.LOGIN_LOGIN_SUCCESS, 0x02,
|
||||
Packets.Clientbound.LOGIN_SET_COMPRESSION, 0x03,
|
||||
Packets.Clientbound.LOGIN_PLUGIN_REQUEST, 0x04
|
||||
)));
|
||||
|
||||
CLIENTBOUND_PACKET_MAPPING.put(ConnectionStates.PLAY, HashBiMap.create());
|
||||
}
|
||||
|
||||
@SuppressWarnings("ConstantConditions")
|
||||
public static int getPacketCommand(Packets.Serverbound packet) {
|
||||
return SERVERBOUND_PACKET_MAPPING.get(packet.getState()).get(packet);
|
||||
}
|
||||
|
||||
public static Packets.Clientbound getPacketByCommand(ConnectionStates state, int command) {
|
||||
return CLIENTBOUND_PACKET_MAPPING.get(state).inverse().get(command);
|
||||
}
|
||||
}
|
@ -0,0 +1,72 @@
|
||||
/*
|
||||
* Minosoft
|
||||
* Copyright (C) 2020 Moritz Zwerger
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with this program.If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
|
||||
*/
|
||||
package de.bixilon.minosoft.protocol.protocol
|
||||
|
||||
import com.google.common.collect.HashBiMap
|
||||
import de.bixilon.minosoft.protocol.protocol.Packets.Clientbound
|
||||
import de.bixilon.minosoft.protocol.protocol.Packets.Serverbound
|
||||
import java.util.*
|
||||
|
||||
object Protocol {
|
||||
private val SERVERBOUND_PACKET_MAPPING = HashMap<ConnectionStates, HashBiMap<Serverbound, Int>>()
|
||||
private val CLIENTBOUND_PACKET_MAPPING = HashMap<ConnectionStates, HashBiMap<Clientbound, Int>>()
|
||||
|
||||
@JvmStatic
|
||||
fun getPacketCommand(packet: Serverbound): Int {
|
||||
return SERVERBOUND_PACKET_MAPPING[packet.state]!![packet]!!
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun getPacketByCommand(state: ConnectionStates, command: Int): Clientbound? {
|
||||
return CLIENTBOUND_PACKET_MAPPING[state]?.inverse()?.get(command)
|
||||
}
|
||||
|
||||
init {
|
||||
SERVERBOUND_PACKET_MAPPING[ConnectionStates.HANDSHAKING] = HashBiMap.create(
|
||||
mapOf(
|
||||
Serverbound.HANDSHAKING_HANDSHAKE to 0x00
|
||||
)
|
||||
)
|
||||
SERVERBOUND_PACKET_MAPPING[ConnectionStates.STATUS] = HashBiMap.create(
|
||||
mapOf(
|
||||
Serverbound.STATUS_REQUEST to 0x00,
|
||||
Serverbound.STATUS_PING to 0x01
|
||||
)
|
||||
)
|
||||
SERVERBOUND_PACKET_MAPPING[ConnectionStates.LOGIN] = HashBiMap.create(
|
||||
mapOf(
|
||||
Serverbound.LOGIN_LOGIN_START to 0x00,
|
||||
Serverbound.LOGIN_ENCRYPTION_RESPONSE to 0x01,
|
||||
Serverbound.LOGIN_PLUGIN_RESPONSE to 0x02
|
||||
)
|
||||
)
|
||||
|
||||
// clientbound
|
||||
CLIENTBOUND_PACKET_MAPPING[ConnectionStates.STATUS] = HashBiMap.create(
|
||||
mapOf(
|
||||
Clientbound.STATUS_RESPONSE to 0x00,
|
||||
Clientbound.STATUS_PONG to 0x01
|
||||
)
|
||||
)
|
||||
CLIENTBOUND_PACKET_MAPPING[ConnectionStates.LOGIN] = HashBiMap.create(
|
||||
mapOf(
|
||||
Clientbound.LOGIN_DISCONNECT to 0x00,
|
||||
Clientbound.LOGIN_ENCRYPTION_REQUEST to 0x01,
|
||||
Clientbound.LOGIN_LOGIN_SUCCESS to 0x02,
|
||||
Clientbound.LOGIN_SET_COMPRESSION to 0x03,
|
||||
Clientbound.LOGIN_PLUGIN_REQUEST to 0x04
|
||||
)
|
||||
)
|
||||
CLIENTBOUND_PACKET_MAPPING[ConnectionStates.PLAY] = HashBiMap.create()
|
||||
}
|
||||
}
|
@ -18,6 +18,7 @@ import de.bixilon.minosoft.data.text.ChatColors;
|
||||
import de.bixilon.minosoft.data.text.PostChatFormattingCodes;
|
||||
import de.bixilon.minosoft.data.text.RGBColor;
|
||||
|
||||
import java.io.PrintStream;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
|
||||
@ -25,9 +26,15 @@ public class Log {
|
||||
public static final long MINOSOFT_START_TIME = System.currentTimeMillis();
|
||||
private static final SimpleDateFormat TIME_FORMAT = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
|
||||
private static final LinkedBlockingQueue<String> LOG_QUEUE = new LinkedBlockingQueue<>();
|
||||
private static final PrintStream SYSTEM_ERR_STREAM = System.err;
|
||||
private static final PrintStream SYSTEM_OUT_STREAM = System.out;
|
||||
private static final PrintStream ERROR_PRINT_STREAM = new LogPrintStream(LogLevels.WARNING);
|
||||
private static final PrintStream OUT_PRINT_STREAM = new LogPrintStream(LogLevels.INFO);
|
||||
private static LogLevels level = LogLevels.PROTOCOL;
|
||||
|
||||
static {
|
||||
System.setErr(ERROR_PRINT_STREAM);
|
||||
System.setOut(OUT_PRINT_STREAM);
|
||||
new Thread(() -> {
|
||||
while (true) {
|
||||
// something to print
|
||||
@ -38,8 +45,7 @@ public class Log {
|
||||
e.printStackTrace();
|
||||
continue;
|
||||
}
|
||||
System.out.println(message);
|
||||
System.out.flush();
|
||||
SYSTEM_OUT_STREAM.println(message);
|
||||
|
||||
// ToDo: log to file
|
||||
}
|
||||
@ -50,6 +56,19 @@ public class Log {
|
||||
log(level, "", color, message, format);
|
||||
}
|
||||
|
||||
public static void log(LogLevels level, Object message, Object... format) {
|
||||
log(level, "", switch (level) {
|
||||
case GAME -> ChatColors.GREEN;
|
||||
case FATAL -> ChatColors.DARK_RED;
|
||||
case WARNING -> ChatColors.RED;
|
||||
case DEBUG -> ChatColors.GRAY;
|
||||
case VERBOSE -> ChatColors.YELLOW;
|
||||
case PROTOCOL -> ChatColors.BLUE;
|
||||
case MOJANG -> ChatColors.AQUA;
|
||||
case INFO -> ChatColors.WHITE;
|
||||
}, message, format);
|
||||
}
|
||||
|
||||
public static void log(LogLevels level, String prefix, RGBColor color, Object message, Object... format) {
|
||||
if (level.ordinal() > Log.level.ordinal()) {
|
||||
// log level too low
|
||||
@ -96,7 +115,7 @@ public class Log {
|
||||
* @param message Raw message to log
|
||||
*/
|
||||
public static void game(Object message, Object... format) {
|
||||
log(LogLevels.GAME, ChatColors.GREEN, message, format);
|
||||
log(LogLevels.GAME, message, format);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -105,7 +124,7 @@ public class Log {
|
||||
* @param message Raw message to log
|
||||
*/
|
||||
public static void fatal(Object message, Object... format) {
|
||||
log(LogLevels.FATAL, ChatColors.DARK_RED, message, format);
|
||||
log(LogLevels.FATAL, message, format);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -114,7 +133,7 @@ public class Log {
|
||||
* @param message Raw message to log
|
||||
*/
|
||||
public static void warn(Object message, Object... format) {
|
||||
log(LogLevels.WARNING, ChatColors.RED, message, format);
|
||||
log(LogLevels.WARNING, message, format);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -123,7 +142,7 @@ public class Log {
|
||||
* @param message Raw message to log
|
||||
*/
|
||||
public static void debug(Object message, Object... format) {
|
||||
log(LogLevels.DEBUG, ChatColors.GRAY, message, format);
|
||||
log(LogLevels.DEBUG, message, format);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -132,7 +151,7 @@ public class Log {
|
||||
* @param message Raw message to log
|
||||
*/
|
||||
public static void verbose(Object message, Object... format) {
|
||||
log(LogLevels.VERBOSE, ChatColors.YELLOW, message, format);
|
||||
log(LogLevels.VERBOSE, message, format);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -141,7 +160,7 @@ public class Log {
|
||||
* @param message Raw message to log
|
||||
*/
|
||||
public static void protocol(Object message, Object... format) {
|
||||
log(LogLevels.PROTOCOL, ChatColors.BLUE, message, format);
|
||||
log(LogLevels.PROTOCOL, message, format);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -150,7 +169,7 @@ public class Log {
|
||||
* @param message Raw message to log
|
||||
*/
|
||||
public static void mojang(Object message, Object... format) {
|
||||
log(LogLevels.MOJANG, ChatColors.AQUA, message, format);
|
||||
log(LogLevels.MOJANG, message, format);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -159,7 +178,7 @@ public class Log {
|
||||
* @param message Raw message to log
|
||||
*/
|
||||
public static void info(Object message, Object... format) {
|
||||
log(LogLevels.INFO, ChatColors.WHITE, message, format);
|
||||
log(LogLevels.INFO, message, format);
|
||||
}
|
||||
|
||||
public static LogLevels getLevel() {
|
||||
|
@ -0,0 +1,19 @@
|
||||
package de.bixilon.minosoft.util.logging;
|
||||
|
||||
import java.io.OutputStream;
|
||||
import java.io.PrintStream;
|
||||
|
||||
public class LogPrintStream extends PrintStream {
|
||||
private final LogLevels level;
|
||||
|
||||
public LogPrintStream(LogLevels level) {
|
||||
super(OutputStream.nullOutputStream());
|
||||
this.level = level;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void print(String s) {
|
||||
Log.log(this.level, s);
|
||||
}
|
||||
}
|
@ -189,6 +189,21 @@
|
||||
-fx-border-width: 3px;
|
||||
}
|
||||
|
||||
.list-cell-connecting {
|
||||
-fx-border-color: yellow;
|
||||
-fx-border-width: 3px;
|
||||
}
|
||||
|
||||
.list-cell-disconnecting {
|
||||
-fx-border-color: orange;
|
||||
-fx-border-width: 3px;
|
||||
}
|
||||
|
||||
.list-cell-failed {
|
||||
-fx-border-color: red;
|
||||
-fx-border-width: 3px;
|
||||
}
|
||||
|
||||
.list-cell-selected {
|
||||
-fx-border-color: #00aa00;
|
||||
-fx-border-width: 3px;
|
||||
|
Loading…
x
Reference in New Issue
Block a user