You've already forked Arcturus-Morningstar-Extended
mirror of
https://github.com/duckietm/Arcturus-Morningstar-Extended.git
synced 2026-06-20 15:36:17 +00:00
Merge pull request #177 from simoleo89/style/startup-console
style(startup): console banner/splash/colors
This commit is contained in:
@@ -18,6 +18,8 @@ import com.eu.habbo.plugin.events.emulator.EmulatorStartShutdownEvent;
|
||||
import com.eu.habbo.plugin.events.emulator.EmulatorStoppedEvent;
|
||||
import com.eu.habbo.threading.ThreadPooling;
|
||||
import com.eu.habbo.util.imager.badges.BadgeImager;
|
||||
import com.eu.habbo.util.logback.ConsoleStyle;
|
||||
import org.fusesource.jansi.AnsiConsole;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@@ -38,6 +40,12 @@ public final class Emulator {
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(Emulator.class);
|
||||
private static final String OS_NAME = (System.getProperty("os.name") != null ? System.getProperty("os.name") : "Unknown");
|
||||
private static final String CLASS_PATH = (System.getProperty("java.class.path") != null ? System.getProperty("java.class.path") : "Unknown");
|
||||
private static final String ANSI_RESET = "\u001B[0m";
|
||||
private static final String ANSI_BOLD = "\u001B[1m";
|
||||
private static final String ANSI_CYAN = "\u001B[36m";
|
||||
private static final String ANSI_GREEN = "\u001B[32m";
|
||||
private static final String ANSI_YELLOW = "\u001B[33m";
|
||||
private static final String ANSI_DIM = "\u001B[2m";
|
||||
|
||||
// Fallback version, only used when running outside a packaged jar (e.g. from
|
||||
// the IDE). In production the version comes from the jar manifest below.
|
||||
@@ -65,7 +73,6 @@ public final class Emulator {
|
||||
"██║ ╚═╝ ██║╚██████╔╝██║ ██║██║ ╚████║██║██║ ╚████║╚██████╔╝███████║ ██║ ██║ ██║██║ ██║\n" +
|
||||
"╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝╚═╝ ╚═══╝╚═╝╚═╝ ╚═══╝ ╚═════╝ ╚══════╝ ╚═╝ ╚═╝ ╚═╝╚═╝ ╚═╝\n" +
|
||||
"Still Rocking in 2026.\n";
|
||||
|
||||
public static String build = "";
|
||||
public static long buildTimestamp = -1L;
|
||||
|
||||
@@ -104,14 +111,12 @@ public final class Emulator {
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
try {
|
||||
if (OS_NAME.startsWith("Windows") && !CLASS_PATH.contains("idea_rt.jar")) {
|
||||
ch.qos.logback.classic.Logger root = (ch.qos.logback.classic.Logger) LoggerFactory.getLogger(Logger.ROOT_LOGGER_NAME);
|
||||
ConsoleAppender<ILoggingEvent> appender = (ConsoleAppender<ILoggingEvent>) root.getAppender("Console");
|
||||
|
||||
appender.stop();
|
||||
appender.setWithJansi(true);
|
||||
appender.start();
|
||||
}
|
||||
boolean styledConsole = shouldStyleConsole(
|
||||
System.getenv(),
|
||||
System.console() != null,
|
||||
OS_NAME,
|
||||
System.getProperty("habbo.console.style", "auto"));
|
||||
configureAnsiConsole(styledConsole);
|
||||
|
||||
Locale.setDefault(Locale.of("en"));
|
||||
setBuild();
|
||||
@@ -119,7 +124,7 @@ public final class Emulator {
|
||||
ConsoleCommand.load();
|
||||
Emulator.logging = new Logging();
|
||||
|
||||
System.out.println(logo);
|
||||
System.out.println(startupHero(styledConsole));
|
||||
|
||||
long startTime = System.nanoTime();
|
||||
|
||||
@@ -153,14 +158,10 @@ public final class Emulator {
|
||||
Emulator.config.register("camera.price.points.type", "5");
|
||||
Emulator.config.register("camera.render.delay", "5");
|
||||
Emulator.config.register("hotel.timezone", java.time.ZoneId.systemDefault().getId());
|
||||
Emulator.config.register("gui.enabled", "0");
|
||||
Emulator.config.register("gui.autostart.enabled", "0");
|
||||
String hotelTimezoneId = Emulator.getConfig().getValue("hotel.timezone", java.time.ZoneId.systemDefault().getId());
|
||||
System.out.println();
|
||||
LOGGER.info("https://github.com/duckietm/Arcturus-Morningstar-Extended, ");
|
||||
System.out.println();
|
||||
LOGGER.info("This project is for educational purposes only. This Emulator is an open-source fork of Arcturus created by TheGeneral.");
|
||||
LOGGER.info("Version: {}", version);
|
||||
LOGGER.info("Build: {}", build);
|
||||
LOGGER.info("Build Timestamp: {} [{}]", formatBuildTimestamp(buildTimestamp, hotelTimezoneId), hotelTimezoneId);
|
||||
System.out.println(startupCard(hotelTimezoneId));
|
||||
Emulator.texts.register("camera.permission", "You don't have permission to use the camera!");
|
||||
Emulator.texts.register("camera.wait", "Please wait %seconds% seconds before making another picture.");
|
||||
Emulator.texts.register("camera.error.creation", "Failed to create your picture. *sadpanda*");
|
||||
@@ -198,7 +199,7 @@ public final class Emulator {
|
||||
Emulator.isReady = true;
|
||||
Emulator.timeStarted = getIntUnixTimestamp();
|
||||
|
||||
if (Emulator.getConfig().getBoolean("gui.enabled", true)) {
|
||||
if (shouldLaunchGui()) {
|
||||
EmulatorDashboard.launch();
|
||||
}
|
||||
|
||||
@@ -310,6 +311,97 @@ public final class Emulator {
|
||||
return -1L;
|
||||
}
|
||||
|
||||
static String startupCard(String hotelTimezoneId) {
|
||||
return "\n" +
|
||||
"+----------------------------------------------------------------+\n" +
|
||||
"| Arcturus Morningstar Extended |\n" +
|
||||
"| Source : github.com/duckietm/Arcturus-Morningstar-Extended |\n" +
|
||||
"| Scope : Educational open-source fork by TheGeneral |\n" +
|
||||
"| Version: " + version + "\n" +
|
||||
"| Build : " + build + "\n" +
|
||||
"| Time : " + formatBuildTimestamp(buildTimestamp, hotelTimezoneId) + " [" + hotelTimezoneId + "]\n" +
|
||||
"+----------------------------------------------------------------+\n";
|
||||
}
|
||||
|
||||
static String startupHero() {
|
||||
return startupHero(false);
|
||||
}
|
||||
|
||||
static String startupHero(boolean styled) {
|
||||
if (styled) {
|
||||
return "\n" +
|
||||
ANSI_CYAN +
|
||||
" __ __ ___ ____ _ _ ___ _ _ ____ ____ _____ _ ____ \n" +
|
||||
" | \\/ |/ _ \\| _ \\| \\ | |_ _| \\ | |/ ___/ ___|_ _|/ \\ | _ \\ \n" +
|
||||
" | |\\/| | | | | |_) | \\| || || \\| | | _\\___ \\ | | / _ \\ | |_) |\n" +
|
||||
" | | | | |_| | _ <| |\\ || || |\\ | |_| |___) || |/ ___ \\| _ < \n" +
|
||||
" |_| |_|\\___/|_| \\_\\_| \\_|___|_| \\_|\\____|____/ |_/_/ \\_\\_| \\_\\\n" +
|
||||
ANSI_RESET +
|
||||
"\n" +
|
||||
ANSI_DIM + "+------------------------------------------------------------------------------+" + ANSI_RESET + "\n" +
|
||||
"| " + ANSI_BOLD + ANSI_GREEN + "[OK] MORNINGSTAR EXTENDED" + ANSI_RESET + fit("", 50) + " |\n" +
|
||||
"| " + ANSI_DIM + "Arcturus game server runtime" + ANSI_RESET + fit("", 48) + " |\n" +
|
||||
ANSI_DIM + "+------------------------------------------------------------------------------+" + ANSI_RESET + "\n" +
|
||||
"| " + ANSI_YELLOW + "[VER]" + ANSI_RESET + " Version : " + fit(version, 57) + " |\n" +
|
||||
"| " + ANSI_YELLOW + "[BLD]" + ANSI_RESET + " Build : " + fit(build.isBlank() ? "UNKNOWN" : build, 57) + " |\n" +
|
||||
"| " + ANSI_YELLOW + "[JVM]" + ANSI_RESET + " Runtime : " + fit("Java " + System.getProperty("java.version", "unknown") + " / styled console output", 57) + " |\n" +
|
||||
ANSI_DIM + "+------------------------------------------------------------------------------+" + ANSI_RESET + "\n";
|
||||
}
|
||||
|
||||
return "\n" +
|
||||
" __ __ ___ ____ _ _ ___ _ _ ____ ____ _____ _ ____ \n" +
|
||||
" | \\/ |/ _ \\| _ \\| \\ | |_ _| \\ | |/ ___/ ___|_ _|/ \\ | _ \\ \n" +
|
||||
" | |\\/| | | | | |_) | \\| || || \\| | | _\\___ \\ | | / _ \\ | |_) |\n" +
|
||||
" | | | | |_| | _ <| |\\ || || |\\ | |_| |___) || |/ ___ \\| _ < \n" +
|
||||
" |_| |_|\\___/|_| \\_\\_| \\_|___|_| \\_|\\____|____/ |_/_/ \\_\\_| \\_\\\n" +
|
||||
"\n" +
|
||||
"+------------------------------------------------------------------------------+\n" +
|
||||
"| MORNINGSTAR EXTENDED |\n" +
|
||||
"| Arcturus game server runtime |\n" +
|
||||
"+------------------------------------------------------------------------------+\n" +
|
||||
"| Version : " + fit(version, 63) + " |\n" +
|
||||
"| Build : " + fit(build.isBlank() ? "UNKNOWN" : build, 63) + " |\n" +
|
||||
"| Runtime : " + fit("Java " + System.getProperty("java.version", "unknown") + " / universal console output", 63) + " |\n" +
|
||||
"+------------------------------------------------------------------------------+\n";
|
||||
}
|
||||
|
||||
static boolean shouldStyleConsole(Map<String, String> environment, boolean interactiveConsole, String osName, String styleProperty) {
|
||||
return ConsoleStyle.isEnabled(environment, interactiveConsole, osName, styleProperty);
|
||||
}
|
||||
|
||||
static void configureAnsiConsole(boolean styledConsole) {
|
||||
if (!styledConsole || !OS_NAME.startsWith("Windows") || CLASS_PATH.contains("idea_rt.jar")) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
AnsiConsole.systemInstall();
|
||||
|
||||
ch.qos.logback.classic.Logger root = (ch.qos.logback.classic.Logger) LoggerFactory.getLogger(Logger.ROOT_LOGGER_NAME);
|
||||
ConsoleAppender<ILoggingEvent> appender = (ConsoleAppender<ILoggingEvent>) root.getAppender("Console");
|
||||
if (appender != null) {
|
||||
appender.stop();
|
||||
appender.setWithJansi(true);
|
||||
appender.start();
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
LOGGER.debug("Unable to install Jansi console bridge; continuing with raw console output.", e);
|
||||
}
|
||||
}
|
||||
|
||||
static boolean shouldLaunchGui() {
|
||||
return Emulator.getConfig() != null && Emulator.getConfig().getBoolean("gui.autostart.enabled", false);
|
||||
}
|
||||
|
||||
private static String fit(String value, int width) {
|
||||
String safe = value == null ? "" : value;
|
||||
if (safe.length() > width) {
|
||||
return safe.substring(0, Math.max(0, width - 3)) + "...";
|
||||
}
|
||||
|
||||
return String.format("%-" + width + "s", safe);
|
||||
}
|
||||
|
||||
private static String formatBuildTimestamp(long buildTimestamp, String timezoneId) {
|
||||
if (buildTimestamp <= 0) {
|
||||
return "UNKNOWN";
|
||||
|
||||
+12
-1
@@ -90,7 +90,13 @@ public class InfostandBackgroundManager {
|
||||
this.enforce = loaded > 0;
|
||||
|
||||
if (this.enforce) {
|
||||
LOGGER.info("InfostandBackgroundManager -> Loaded {} backgrounds, {} stands, {} overlays, {} cards, {} borders from infostand_backgrounds.",
|
||||
LOGGER.info(summary(
|
||||
this.entries.get(Category.BACKGROUND).size(),
|
||||
this.entries.get(Category.STAND).size(),
|
||||
this.entries.get(Category.OVERLAY).size(),
|
||||
this.entries.get(Category.CARD).size(),
|
||||
this.entries.get(Category.BORDER).size()));
|
||||
LOGGER.debug("Infostand Background Manager assets: {} bg, {} stands, {} overlays, {} cards, {} borders",
|
||||
this.entries.get(Category.BACKGROUND).size(),
|
||||
this.entries.get(Category.STAND).size(),
|
||||
this.entries.get(Category.OVERLAY).size(),
|
||||
@@ -101,6 +107,11 @@ public class InfostandBackgroundManager {
|
||||
}
|
||||
}
|
||||
|
||||
static String summary(int backgrounds, int stands, int overlays, int cards, int borders) {
|
||||
int total = backgrounds + stands + overlays + cards + borders;
|
||||
return String.format("Infostand Background Manager -> Loaded! (%d assets)", total);
|
||||
}
|
||||
|
||||
public boolean canUse(Habbo habbo, Category category, int id) {
|
||||
if (id == 0) return true;
|
||||
if (!this.enforce) return true;
|
||||
|
||||
@@ -85,10 +85,10 @@ public abstract class Server {
|
||||
}
|
||||
|
||||
if (!channelFuture.isSuccess()) {
|
||||
LOGGER.info("Failed to connect to the host ({}:{})@{}", this.host, this.port, this.name);
|
||||
LOGGER.info("Failed to start {} on {}:{}", this.name, this.host, this.port);
|
||||
System.exit(0);
|
||||
} else {
|
||||
LOGGER.info("Started GameServer on {}:{}@{}", this.host, this.port, this.name);
|
||||
LOGGER.info("Started {} on {}:{}", this.name, this.host, this.port);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -100,7 +100,7 @@ public abstract class Server {
|
||||
} catch(InterruptedException e) {
|
||||
LOGGER.error("Exception during {} shutdown... HARD STOP", this.name, e);
|
||||
}
|
||||
LOGGER.info("GameServer Stopped!");
|
||||
LOGGER.info("Stopped {}", this.name);
|
||||
}
|
||||
|
||||
public ServerBootstrap getServerBootstrap() {
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
package com.eu.habbo.util.logback;
|
||||
|
||||
import ch.qos.logback.classic.pattern.ClassicConverter;
|
||||
import ch.qos.logback.classic.spi.ILoggingEvent;
|
||||
|
||||
public class ConsoleLevelConverter extends ClassicConverter {
|
||||
@Override
|
||||
public String convert(ILoggingEvent event) {
|
||||
return ConsoleStyle.level(event == null ? null : event.getLevel(), ConsoleStyle.isRuntimeEnabled());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package com.eu.habbo.util.logback;
|
||||
|
||||
import ch.qos.logback.classic.pattern.ClassicConverter;
|
||||
import ch.qos.logback.classic.spi.ILoggingEvent;
|
||||
|
||||
public class ConsoleLoggerConverter extends ClassicConverter {
|
||||
@Override
|
||||
public String convert(ILoggingEvent event) {
|
||||
return ConsoleStyle.logger(event == null ? "" : event.getLoggerName(), ConsoleStyle.isRuntimeEnabled());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
package com.eu.habbo.util.logback;
|
||||
|
||||
import ch.qos.logback.classic.Level;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
|
||||
public final class ConsoleStyle {
|
||||
private static final String ANSI_RESET = "\u001B[0m";
|
||||
private static final String ANSI_BOLD = "\u001B[1m";
|
||||
private static final String ANSI_DIM = "\u001B[2m";
|
||||
private static final String ANSI_CYAN = "\u001B[36m";
|
||||
private static final String ANSI_GREEN = "\u001B[32m";
|
||||
private static final String ANSI_YELLOW = "\u001B[33m";
|
||||
private static final String ANSI_RED = "\u001B[31m";
|
||||
|
||||
private static final int LOGGER_WIDTH = 22;
|
||||
|
||||
private ConsoleStyle() {
|
||||
}
|
||||
|
||||
public static boolean isRuntimeEnabled() {
|
||||
return isEnabled(
|
||||
System.getenv(),
|
||||
System.console() != null,
|
||||
System.getProperty("os.name", "Unknown"),
|
||||
System.getProperty("habbo.console.style", "auto"));
|
||||
}
|
||||
|
||||
public static boolean isEnabled(Map<String, String> environment, boolean interactiveConsole, String osName, String styleProperty) {
|
||||
String style = styleProperty == null ? "auto" : styleProperty.trim().toLowerCase(Locale.ROOT);
|
||||
if (style.equals("ansi") || style.equals("color") || style.equals("colours") || style.equals("colors")) {
|
||||
return true;
|
||||
}
|
||||
if (style.equals("plain") || style.equals("none") || style.equals("false") || style.equals("off")) {
|
||||
return false;
|
||||
}
|
||||
if (!interactiveConsole) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Map<String, String> env = environment == null ? Collections.emptyMap() : environment;
|
||||
if (env.containsKey("NO_COLOR")) {
|
||||
return false;
|
||||
}
|
||||
if (env.containsKey("WT_SESSION") || env.containsKey("ANSICON") || "ON".equalsIgnoreCase(env.get("ConEmuANSI"))) {
|
||||
return true;
|
||||
}
|
||||
|
||||
String term = env.getOrDefault("TERM", "");
|
||||
if (term.equalsIgnoreCase("dumb")) {
|
||||
return false;
|
||||
}
|
||||
if (!term.isBlank() && (term.contains("xterm") || term.contains("ansi") || term.contains("screen") || term.contains("tmux"))) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return osName == null || !osName.toLowerCase(Locale.ROOT).startsWith("windows");
|
||||
}
|
||||
|
||||
public static String level(Level level, boolean styled) {
|
||||
String name = level == null ? "INFO" : level.toString();
|
||||
String plain = String.format("%-5s", name);
|
||||
|
||||
if (!styled) {
|
||||
return plain;
|
||||
}
|
||||
|
||||
if (Level.ERROR.equals(level)) {
|
||||
return ANSI_BOLD + ANSI_RED + "[x] " + plain + ANSI_RESET;
|
||||
}
|
||||
if (Level.WARN.equals(level)) {
|
||||
return ANSI_YELLOW + "[!] " + plain + ANSI_RESET;
|
||||
}
|
||||
if (Level.DEBUG.equals(level) || Level.TRACE.equals(level)) {
|
||||
return ANSI_DIM + "[.] " + plain + ANSI_RESET;
|
||||
}
|
||||
|
||||
return ANSI_GREEN + "[i] " + plain + ANSI_RESET;
|
||||
}
|
||||
|
||||
public static String logger(String loggerName, boolean styled) {
|
||||
String compact = compactLoggerName(loggerName);
|
||||
String plain = fit(compact, LOGGER_WIDTH);
|
||||
return styled ? ANSI_CYAN + plain + ANSI_RESET : plain;
|
||||
}
|
||||
|
||||
private static String compactLoggerName(String loggerName) {
|
||||
if (loggerName == null || loggerName.isBlank()) {
|
||||
return "";
|
||||
}
|
||||
|
||||
int lastDot = loggerName.lastIndexOf('.');
|
||||
return lastDot >= 0 ? loggerName.substring(lastDot + 1) : loggerName;
|
||||
}
|
||||
|
||||
private static String fit(String value, int width) {
|
||||
String safe = value == null ? "" : value;
|
||||
if (safe.length() > width) {
|
||||
return safe.substring(0, Math.max(0, width - 3)) + "...";
|
||||
}
|
||||
|
||||
return String.format("%-" + width + "s", safe);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user