Uploading Emulator

This commit is contained in:
duckietm
2024-03-13 11:28:48 +01:00
parent 9f061273ab
commit b017953b91
1824 changed files with 109921 additions and 0 deletions
@@ -0,0 +1,527 @@
package com.eu.habbo;
import ch.qos.logback.classic.Level;
import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.core.ConsoleAppender;
import com.eu.habbo.core.*;
import com.eu.habbo.core.consolecommands.ConsoleCommand;
import com.eu.habbo.database.Database;
import com.eu.habbo.habbohotel.GameEnvironment;
import com.eu.habbo.networking.camera.CameraClient;
import com.eu.habbo.networking.gameserver.GameServer;
import com.eu.habbo.networking.rconserver.RCONServer;
import com.eu.habbo.networking.websockets.NetworkChannelInitializer;
import com.eu.habbo.plugin.PluginManager;
import com.eu.habbo.plugin.events.emulator.EmulatorConfigUpdatedEvent;
import com.eu.habbo.plugin.events.emulator.EmulatorLoadedEvent;
import com.eu.habbo.plugin.events.emulator.EmulatorStartShutdownEvent;
import com.eu.habbo.plugin.events.emulator.EmulatorStoppedEvent;
import com.eu.habbo.plugin.events.users.UserGetIPAddressEvent;
import com.eu.habbo.threading.ThreadPooling;
import com.eu.habbo.util.imager.badges.BadgeImager;
import io.netty.channel.Channel;
import io.netty.util.AttributeKey;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.*;
import java.security.MessageDigest;
import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.ThreadLocalRandom;
import java.security.SecureRandom;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@Slf4j
public final class Emulator {
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 SecureRandom secureRandom = new SecureRandom();
public final static int MAJOR = 3;
public final static int MINOR = 6;
public final static int BUILD = 0;
public final static String PREVIEW = "";
public static final String version = "Arcturus Morningstar" + " " + MAJOR + "." + MINOR + "." + BUILD + " " + PREVIEW;
private static final String logo =
"\n" +
"███╗ ███╗ ██████╗ ██████╗ ███╗ ██╗██╗███╗ ██╗ ██████╗ ███████╗████████╗ █████╗ ██████╗ \n" +
"████╗ ████║██╔═══██╗██╔══██╗████╗ ██║██║████╗ ██║██╔════╝ ██╔════╝╚══██╔══╝██╔══██╗██╔══██╗\n" +
"██╔████╔██║██║ ██║██████╔╝██╔██╗ ██║██║██╔██╗ ██║██║ ███╗███████╗ ██║ ███████║██████╔╝\n" +
"██║╚██╔╝██║██║ ██║██╔══██╗██║╚██╗██║██║██║╚██╗██║██║ ██║╚════██║ ██║ ██╔══██║██╔══██╗\n" +
"██║ ╚═╝ ██║╚██████╔╝██║ ██║██║ ╚████║██║██║ ╚████║╚██████╔╝███████║ ██║ ██║ ██║██║ ██║\n" +
"╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝╚═╝ ╚═══╝╚═╝╚═╝ ╚═══╝ ╚═════╝ ╚══════╝ ╚═╝ ╚═╝ ╚═╝╚═╝ ╚═╝\n" +
" Extended version";
public static String build = "";
public static String debuglevel = "";
public static boolean isReady = false;
public static boolean isShuttingDown = false;
public static boolean stopped = false;
public static boolean debugging = false;
private static int timeStarted = 0;
private static Runtime runtime;
private static ConfigurationManager config;
private static CryptoConfig crypto;
private static TextsManager texts;
private static GameServer gameServer;
private static RCONServer rconServer;
private static CameraClient cameraClient;
private static Logging logging;
private static Database database;
private static DatabaseLogger databaseLogger;
private static ThreadPooling threading;
private static GameEnvironment gameEnvironment;
private static PluginManager pluginManager;
private static BadgeImager badgeImager;
public static final AttributeKey<String> WS_IP = AttributeKey.valueOf("WS_IP");
static {
Thread hook = new Thread(new Runnable() {
public synchronized void run() {
Emulator.dispose();
}
});
hook.setPriority(10);
Runtime.getRuntime().addShutdownHook(hook);
}
public static void main(String[] args) throws Exception {
try {
// Check if running on Windows and not in IntelliJ.
// If so, we need to reconfigure the console appender and enable Jansi for colors.
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();
}
Locale.setDefault(new Locale("en"));
setBuild();
Emulator.stopped = false;
ConsoleCommand.load();
Emulator.logging = new Logging();
System.out.println(logo);
log.info("Version: {}", version);
log.info("Build: {}", build);
long startTime = System.nanoTime();
Emulator.runtime = Runtime.getRuntime();
Emulator.config = new ConfigurationManager("config.ini");
Emulator.crypto = new CryptoConfig(
Emulator.getConfig().getBoolean("enc.enabled", false),
Emulator.getConfig().getValue("enc.e"),
Emulator.getConfig().getValue("enc.n"),
Emulator.getConfig().getValue("enc.d"));
Emulator.database = new Database(Emulator.getConfig());
Emulator.databaseLogger = new DatabaseLogger();
Emulator.config.loaded = true;
Emulator.config.loadFromDatabase();
Emulator.threading = new ThreadPooling(Emulator.getConfig().getInt("runtime.threads"));
Emulator.getDatabase().getDataSource().setMaximumPoolSize(Emulator.getConfig().getInt("runtime.threads") * 2);
Emulator.getDatabase().getDataSource().setMinimumIdle(10);
Emulator.pluginManager = new PluginManager();
Emulator.pluginManager.reload();
Emulator.getPluginManager().fireEvent(new EmulatorConfigUpdatedEvent());
Emulator.texts = new TextsManager();
new CleanerThread();
Emulator.gameServer = new GameServer(getConfig().getValue("game.host", "127.0.0.1"), getConfig().getInt("game.port", 30000));
Emulator.rconServer = new RCONServer(getConfig().getValue("rcon.host", "127.0.0.1"), getConfig().getInt("rcon.port", 30001));
Emulator.gameEnvironment = new GameEnvironment();
Emulator.gameEnvironment.load();
Emulator.gameServer.initializePipeline();
Emulator.gameServer.connect();
Emulator.rconServer.initializePipeline();
Emulator.rconServer.connect();
Emulator.badgeImager = new BadgeImager();
Emulator.getConfig().register("websockets.whitelist", "localhost");
Emulator.getConfig().register("ws.nitro.host", "0.0.0.0");
Emulator.getConfig().register("ws.nitro.port", "2096");
Emulator.getConfig().register("ws.nitro.ip.header", "");
NetworkChannelInitializer wsChannelHandler = new NetworkChannelInitializer();
Emulator.getGameServer().getServerBootstrap().childHandler(wsChannelHandler);
Emulator.getGameServer().getServerBootstrap().bind(Emulator.getConfig().getValue("ws.nitro.host", "0.0.0.0"), Emulator.getConfig().getInt("ws.nitro.port", 2096)).sync();
log.info("Websockets has started!");
log.info("Websockets Listening on " + (wsChannelHandler.isSSL() ? "wss://" : "ws://") + Emulator.getConfig().getValue("ws.nitro.host", "0.0.0.0") + ":" + Emulator.getConfig().getInt("ws.nitro.port", 2096));
log.info("Arcturus Morningstar has successfully loaded.");
log.info("System launched in: {}ms. Using {} threads!", (System.nanoTime() - startTime) / 1e6, Runtime.getRuntime().availableProcessors() * 2);
log.info("Memory: {}/{}MB", (runtime.totalMemory() - runtime.freeMemory()) / (1024 * 1024), (runtime.freeMemory()) / (1024 * 1024));
Emulator.debugging = Emulator.getConfig().getBoolean("debug.mode");
Emulator.debuglevel = Emulator.getConfig().getValue("debug.level", "DEBUG");
/* Debug level can be : INFO WARN DEBUG TRACE*/
if (debugging) {
ch.qos.logback.classic.Logger root = (ch.qos.logback.classic.Logger) LoggerFactory.getLogger(Logger.ROOT_LOGGER_NAME);
root.setLevel(Level.DEBUG);
log.debug("Debugging enabled.");
Level logLevel = Level.toLevel(Emulator.debuglevel);
root.setLevel(logLevel);
log.info("Debugging enabled.");
log.info("The loaded debug mode is {}", Emulator.debuglevel);
}
Emulator.getPluginManager().fireEvent(new EmulatorLoadedEvent());
Emulator.isReady = true;
Emulator.timeStarted = getIntUnixTimestamp();
if (Emulator.getConfig().getInt("runtime.threads") < (Runtime.getRuntime().availableProcessors() * 2)) {
log.warn("Emulator settings runtime.threads ({}) can be increased to ({}) to possibly increase performance.",
Emulator.getConfig().getInt("runtime.threads"),
Runtime.getRuntime().availableProcessors() * 2);
}
Emulator.getThreading().run(() -> {
}, 1500);
// Check if console mode is true or false, default is true
if (Emulator.getConfig().getBoolean("console.mode", true)) {
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
while (!isShuttingDown && isReady) {
try {
String line = reader.readLine();
if (line != null) {
ConsoleCommand.handle(line);
}
System.out.println("Waiting for command: ");
} catch (Exception e) {
if (!(e instanceof IOException && e.getMessage().equals("Bad file descriptor"))) {
log.error("Error while reading command", e);
}
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
private static void setBuild() {
if (Emulator.class.getProtectionDomain().getCodeSource() == null) {
build = "UNKNOWN";
return;
}
StringBuilder sb = new StringBuilder();
try {
String filepath = new File(Emulator.class.getProtectionDomain().getCodeSource().getLocation().getPath()).getAbsolutePath();
MessageDigest md = MessageDigest.getInstance("MD5");// MD5
FileInputStream fis = new FileInputStream(filepath);
byte[] dataBytes = new byte[1024];
int nread = 0;
while ((nread = fis.read(dataBytes)) != -1)
md.update(dataBytes, 0, nread);
byte[] mdbytes = md.digest();
for (int i = 0; i < mdbytes.length; i++)
sb.append(Integer.toString((mdbytes[i] & 0xff) + 0x100, 16).substring(1));
} catch (Exception e) {
build = "UNKNOWN";
return;
}
build = sb.toString();
}
private static void dispose() {
Emulator.getThreading().setCanAdd(false);
Emulator.isShuttingDown = true;
Emulator.isReady = false;
log.info("Stopping Arcturus Morningstar {}", version);
try {
if (Emulator.getPluginManager() != null)
Emulator.getPluginManager().fireEvent(new EmulatorStartShutdownEvent());
} catch (Exception e) {
}
try {
if (Emulator.cameraClient != null)
Emulator.cameraClient.disconnect();
} catch (Exception e) {
}
try {
if (Emulator.rconServer != null)
Emulator.rconServer.stop();
} catch (Exception e) {
}
try {
if (Emulator.gameEnvironment != null)
Emulator.gameEnvironment.dispose();
} catch (Exception e) {
}
try {
if (Emulator.getPluginManager() != null)
Emulator.getPluginManager().fireEvent(new EmulatorStoppedEvent());
} catch (Exception e) {
}
try {
if (Emulator.pluginManager != null)
Emulator.pluginManager.dispose();
} catch (Exception e) {
}
try {
if (Emulator.config != null) {
Emulator.config.saveToDatabase();
}
} catch (Exception e) {
}
try {
if (Emulator.gameServer != null)
Emulator.gameServer.stop();
} catch (Exception e) {
}
log.info("Stopped Arcturus Morningstar {}", version);
if (Emulator.database != null) {
Emulator.getDatabase().dispose();
}
Emulator.stopped = true;
// if (osName.startsWith("Windows") && (!classPath.contains("idea_rt.jar"))) {
// AnsiConsole.systemUninstall();
// }
try {
if (Emulator.threading != null)
Emulator.threading.shutDown();
} catch (Exception e) {
}
}
public static ConfigurationManager getConfig() {
return config;
}
public static CryptoConfig getCrypto() {
return crypto;
}
public static TextsManager getTexts() {
return texts;
}
public static Database getDatabase() {
return database;
}
public static DatabaseLogger getDatabaseLogger() {
return databaseLogger;
}
public static Runtime getRuntime() {
return runtime;
}
public static GameServer getGameServer() {
return gameServer;
}
public static RCONServer getRconServer() {
return rconServer;
}
public void onUserGetIPEvent(UserGetIPAddressEvent e) {
Channel channel = e.habbo.getClient().getChannel();
if(channel != null && channel.hasAttr(Emulator.WS_IP)) {
String ip = channel.attr(Emulator.WS_IP).get();
if(!ip.isEmpty()) {
e.setUpdatedIp(ip);
}
}
}
/**
* @deprecated Do not use. Please use LoggerFactory.getLogger(YourClass.class) to log.
*/
@Deprecated
public static Logging getLogging() {
return logging;
}
public static ThreadPooling getThreading() {
return threading;
}
public static GameEnvironment getGameEnvironment() {
return gameEnvironment;
}
public static PluginManager getPluginManager() {
return pluginManager;
}
public static Random getRandom() {
return ThreadLocalRandom.current();
}
public static SecureRandom getRandomDice() {
return secureRandom;
}
public static BadgeImager getBadgeImager() {
return badgeImager;
}
public static CameraClient getCameraClient() {
return cameraClient;
}
public static synchronized void setCameraClient(CameraClient client) {
cameraClient = client;
}
public static int getTimeStarted() {
return timeStarted;
}
public static int getOnlineTime() {
return getIntUnixTimestamp() - timeStarted;
}
public static void prepareShutdown() {
System.exit(0);
}
public static int timeStringToSeconds(String timeString) {
int totalSeconds = 0;
Matcher m = Pattern.compile("(([0-9]*) (second|minute|hour|day|week|month|year))").matcher(timeString);
Map<String,Integer> map = new HashMap<String,Integer>() {
{
put("second", 1);
put("minute", 60);
put("hour", 3600);
put("day", 86400);
put("week", 604800);
put("month", 2628000);
put("year", 31536000);
}
};
while (m.find()) {
try {
int amount = Integer.parseInt(m.group(2));
String what = m.group(3);
totalSeconds += amount * map.get(what);
}
catch (Exception ignored) { }
}
return totalSeconds;
}
public static Date modifyDate(Date date, String timeString) {
int totalSeconds = 0;
Calendar c = Calendar.getInstance();
c.setTime(date);
Matcher m = Pattern.compile("(([0-9]*) (second|minute|hour|day|week|month|year))").matcher(timeString);
Map<String, Integer> map = new HashMap<String, Integer>() {
{
put("second", Calendar.SECOND);
put("minute", Calendar.MINUTE);
put("hour", Calendar.HOUR);
put("day", Calendar.DAY_OF_MONTH);
put("week", Calendar.WEEK_OF_MONTH);
put("month", Calendar.MONTH);
put("year", Calendar.YEAR);
}
};
while (m.find()) {
try {
int amount = Integer.parseInt(m.group(2));
String what = m.group(3);
c.add(map.get(what), amount);
}
catch (Exception ignored) { }
}
return c.getTime();
}
private static String dateToUnixTimestamp(Date date) {
String res = "";
Date aux = stringToDate("1970-01-01 00:00:00");
Timestamp aux1 = dateToTimeStamp(aux);
Timestamp aux2 = dateToTimeStamp(date);
long difference = aux2.getTime() - aux1.getTime();
long seconds = difference / 1000L;
return res + seconds;
}
public static Date stringToDate(String date) {
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date res = null;
try {
res = format.parse(date);
} catch (Exception e) {
log.error("Error parsing date", e);
}
return res;
}
public static Timestamp dateToTimeStamp(Date date) {
return new Timestamp(date.getTime());
}
public static Date getDate() {
return new Date(System.currentTimeMillis());
}
public static String getUnixTimestamp() {
return dateToUnixTimestamp(getDate());
}
public static int getIntUnixTimestamp() {
return (int) (System.currentTimeMillis() / 1000);
}
public static boolean isNumeric(String string)
throws IllegalArgumentException {
boolean isnumeric = false;
if ((string != null) && (!string.equals(""))) {
isnumeric = true;
char[] chars = string.toCharArray();
for (char aChar : chars) {
isnumeric = Character.isDigit(aChar);
if (!isnumeric) {
break;
}
}
}
return isnumeric;
}
public int getUserCount() {
return gameEnvironment.getHabboManager().getOnlineCount();
}
public int getRoomCount() {
return gameEnvironment.getRoomManager().getActiveRooms().size();
}
}
@@ -0,0 +1,160 @@
package com.eu.habbo.core;
import com.eu.habbo.Emulator;
import com.eu.habbo.habbohotel.guilds.forums.ForumThread;
import com.eu.habbo.habbohotel.users.Habbo;
import com.eu.habbo.messages.incoming.friends.SearchUserEvent;
import com.eu.habbo.messages.incoming.navigator.SearchRoomsEvent;
import com.eu.habbo.messages.outgoing.users.UserDataComposer;
import com.eu.habbo.threading.runnables.AchievementUpdater;
import lombok.extern.slf4j.Slf4j;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Map;
@Slf4j
public class CleanerThread implements Runnable {
private static final int DELAY = 10000;
private static final int RELOAD_HALL_OF_FAME = 1800;
private static final int RELOAD_NEWS_LIST = 3600;
private static final int REMOVE_INACTIVE_ROOMS = 120;
private static final int REMOVE_INACTIVE_GUILDS = 60;
private static final int REMOVE_INACTIVE_TOURS = 600;
private static final int CLEAR_CACHED_VALUES = 60 * 60;
private static final int CALLBACK_TIME = 60 * 15;
private static int LAST_HOF_RELOAD = Emulator.getIntUnixTimestamp();
private static int LAST_NL_RELOAD = Emulator.getIntUnixTimestamp();
private static int LAST_INACTIVE_ROOMS_CLEARED = Emulator.getIntUnixTimestamp();
private static int LAST_INACTIVE_GUILDS_CLEARED = Emulator.getIntUnixTimestamp();
private static int LAST_INACTIVE_TOURS_CLEARED = Emulator.getIntUnixTimestamp();
private static int LAST_DAILY_REFILL = Emulator.getIntUnixTimestamp();
private static int LAST_CALLBACK = Emulator.getIntUnixTimestamp();
private static int LAST_HABBO_CACHE_CLEARED = Emulator.getIntUnixTimestamp();
public CleanerThread() {
this.databaseCleanup();
Emulator.getThreading().run(this, DELAY);
Emulator.getThreading().run(new AchievementUpdater());
// Emulator.getThreading().run(new HTTPVersionCheck(), 10000);
}
@Override
public void run() {
Emulator.getThreading().run(this, DELAY);
int time = Emulator.getIntUnixTimestamp();
if (time - LAST_HOF_RELOAD > RELOAD_HALL_OF_FAME) {
Emulator.getGameEnvironment().getHotelViewManager().getHallOfFame().reload();
LAST_HOF_RELOAD = time;
}
if (time - LAST_NL_RELOAD > RELOAD_NEWS_LIST) {
Emulator.getGameEnvironment().getHotelViewManager().getNewsList().reload();
LAST_NL_RELOAD = time;
}
if (time - LAST_INACTIVE_ROOMS_CLEARED > REMOVE_INACTIVE_ROOMS) {
Emulator.getGameEnvironment().getRoomManager().clearInactiveRooms();
LAST_INACTIVE_ROOMS_CLEARED = time;
}
if (time - LAST_INACTIVE_GUILDS_CLEARED > REMOVE_INACTIVE_GUILDS) {
Emulator.getGameEnvironment().getGuildManager().clearInactiveGuilds();
ForumThread.clearCache();
LAST_INACTIVE_GUILDS_CLEARED = time;
}
if (time - LAST_INACTIVE_TOURS_CLEARED > REMOVE_INACTIVE_TOURS) {
Emulator.getGameEnvironment().getGuideManager().cleanup();
LAST_INACTIVE_TOURS_CLEARED = time;
}
if (time - LAST_CALLBACK > CALLBACK_TIME) {
// Emulator.getThreading().run(new HTTPPostStatus());
LAST_CALLBACK = time;
}
if (time - LAST_DAILY_REFILL > Emulator.getConfig().getInt("hotel.refill.daily")) {
this.refillDailyRespects();
LAST_DAILY_REFILL = time;
}
if (time - LAST_HABBO_CACHE_CLEARED > CLEAR_CACHED_VALUES) {
this.clearCachedValues();
LAST_HABBO_CACHE_CLEARED = time;
}
SearchRoomsEvent.cachedResults.clear();
SearchUserEvent.cachedResults.clear();
}
void databaseCleanup() {
this.refillDailyRespects();
int time = Emulator.getIntUnixTimestamp();
try (Connection connection = Emulator.getDatabase().getDataSource().getConnection()) {
try (Statement statement = connection.createStatement()) {
statement.execute("UPDATE users SET online = '0' WHERE online = '1'");
statement.execute("UPDATE rooms SET users = '0' WHERE users > 0");
statement.execute("DELETE FROM room_mutes WHERE ends < " + time);
statement.execute("DELETE FROM room_bans WHERE ends < " + time);
statement.execute("DELETE users_favorite_rooms FROM users_favorite_rooms LEFT JOIN rooms ON room_id = rooms.id WHERE rooms.id IS NULL");
}
try (PreparedStatement statement = connection.prepareStatement("UPDATE users_effects SET total = total - 1 WHERE activation_timestamp + duration < ? AND activation_timestamp > 0 AND duration > 0")) {
statement.setInt(1, Emulator.getIntUnixTimestamp());
statement.execute();
}
try (Statement statement = connection.createStatement()) {
statement.execute("DELETE FROM users_effects WHERE total <= 0");
}
} catch (SQLException e) {
log.error("Caught SQL exception", e);
}
log.info("Database -> Cleaned!");
}
public void refillDailyRespects() {
try (Connection connection = Emulator.getDatabase().getDataSource().getConnection(); PreparedStatement statement = connection.prepareStatement("UPDATE users_settings SET daily_respect_points = ?, daily_pet_respect_points = ?")) {
statement.setInt(1, Emulator.getConfig().getInt("hotel.daily.respect"));
statement.setInt(2, Emulator.getConfig().getInt("hotel.daily.respect.pets"));
statement.executeUpdate();
} catch (SQLException e) {
log.error("Caught SQL exception", e);
}
if (Emulator.isReady) {
for (Habbo habbo : Emulator.getGameEnvironment().getHabboManager().getOnlineHabbos().values()) {
habbo.getHabboStats().respectPointsToGive = Emulator.getConfig().getInt("hotel.daily.respect");
habbo.getHabboStats().petRespectPointsToGive = Emulator.getConfig().getInt("hotel.daily.respect.pets");
habbo.getClient().sendResponse(new UserDataComposer(habbo));
}
}
}
private void clearCachedValues() {
Habbo habbo;
for (Map.Entry<Integer, Habbo> map : Emulator.getGameEnvironment().getHabboManager().getOnlineHabbos().entrySet()) {
habbo = map.getValue();
try {
if (habbo != null) {
habbo.clearCaches();
}
} catch (Exception e) {
log.error("Caught exception", e);
}
}
}
}
@@ -0,0 +1,41 @@
package com.eu.habbo.core;
import com.eu.habbo.Emulator;
import com.eu.habbo.habbohotel.commands.Command;
import java.sql.PreparedStatement;
import java.sql.SQLException;
public class CommandLog implements DatabaseLoggable {
private static final String INSERT_QUERY = "INSERT INTO commandlogs (`user_id`, `timestamp`, `command`, `params`, `succes`) VALUES (?, ?, ?, ?, ?)";
private final int userId;
private final int timestamp = Emulator.getIntUnixTimestamp();
private final Command command;
private final String params;
private final boolean success;
public CommandLog(int userId, Command command, String params, boolean success) {
this.userId = userId;
this.command = command;
this.params = params;
this.success = success;
}
@Override
public String getQuery() {
return CommandLog.INSERT_QUERY;
}
@Override
public void log(PreparedStatement statement) throws SQLException {
statement.setInt(1, this.userId);
statement.setInt(2, this.timestamp);
statement.setString(3, this.command.getClass().getSimpleName());
statement.setString(4, this.params);
statement.setString(5, this.success ? "yes" : "no");
statement.addBatch();
}
}
@@ -0,0 +1,226 @@
package com.eu.habbo.core;
import com.eu.habbo.Emulator;
import com.eu.habbo.plugin.events.emulator.EmulatorConfigUpdatedEvent;
import gnu.trove.map.hash.THashMap;
import lombok.extern.slf4j.Slf4j;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.sql.*;
import java.util.Map;
import java.util.Properties;
@Slf4j
public class ConfigurationManager {
private final Properties properties;
private final String configurationPath;
public boolean loaded = false;
public boolean isLoading = false;
public ConfigurationManager(String configurationPath) {
this.properties = new Properties();
this.configurationPath = configurationPath;
this.reload();
}
public void reload() {
this.isLoading = true;
this.properties.clear();
InputStream input = null;
String envDbHostname = System.getenv("DB_HOSTNAME");
boolean useEnvVarsForDbConnection = false;
if(envDbHostname != null)
{
useEnvVarsForDbConnection = envDbHostname.length() > 1;
}
if (!useEnvVarsForDbConnection) {
try {
File f = new File(this.configurationPath);
input = new FileInputStream(f);
this.properties.load(input);
} catch (IOException ex) {
log.error("Failed to load config file.", ex);
ex.printStackTrace();
} finally {
if (input != null) {
try {
input.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
} else {
Map<String, String> envMapping = new THashMap<>();
// Database section
envMapping.put("db.hostname", "DB_HOSTNAME");
envMapping.put("db.port", "DB_PORT");
envMapping.put("db.database", "DB_DATABASE");
envMapping.put("db.username", "DB_USERNAME");
envMapping.put("db.password", "DB_PASSWORD");
envMapping.put("db.params", "DB_PARAMS");
// Game Configuration
envMapping.put("game.host", "EMU_HOST");
envMapping.put("game.port", "EMU_PORT");
// RCON
envMapping.put("rcon.host", "RCON_HOST");
envMapping.put("rcon.port", "RCON_PORT");
envMapping.put("rcon.allowed", "RCON_ALLOWED");
// Runtime
envMapping.put("runtime.threads", "RT_THREADS");
envMapping.put("logging.errors.runtime", "RT_LOG_ERRORS");
for (Map.Entry<String, String> entry : envMapping.entrySet()) {
String envValue = System.getenv(entry.getValue());
if (envValue == null || envValue.length() == 0) {
log.info("Cannot find environment-value for variable `" + entry.getValue() + "`");
} else {
this.properties.setProperty(entry.getKey(), envValue);
}
}
}
if (this.loaded) {
this.loadFromDatabase();
}
this.isLoading = false;
log.info("Configuration Manager -> Loaded!");
if (Emulator.getPluginManager() != null) {
Emulator.getPluginManager().fireEvent(new EmulatorConfigUpdatedEvent());
}
}
public void loadFromDatabase() {
log.info("Loading configuration from database...");
long millis = System.currentTimeMillis();
try (Connection connection = Emulator.getDatabase().getDataSource().getConnection(); Statement statement = connection.createStatement()) {
if (statement.execute("SELECT * FROM emulator_settings")) {
try (ResultSet set = statement.getResultSet()) {
while (set.next()) {
this.properties.put(set.getString("key"), set.getString("value"));
}
}
}
} catch (SQLException e) {
log.error("Caught SQL exception", e);
}
log.info("Configuration -> loaded! (" + (System.currentTimeMillis() - millis) + " MS)");
}
public void saveToDatabase() {
try (Connection connection = Emulator.getDatabase().getDataSource().getConnection(); PreparedStatement statement = connection.prepareStatement("UPDATE emulator_settings SET `value` = ? WHERE `key` = ? LIMIT 1")) {
for (Map.Entry<Object, Object> entry : this.properties.entrySet()) {
statement.setString(1, entry.getValue().toString());
statement.setString(2, entry.getKey().toString());
statement.executeUpdate();
}
} catch (SQLException e) {
log.error("Caught SQL exception", e);
}
}
public String getValue(String key) {
return this.getValue(key, "");
}
public String getValue(String key, String defaultValue) {
if (this.isLoading)
return defaultValue;
if (!this.properties.containsKey(key)) {
log.error("Config key not found {}", key);
}
return this.properties.getProperty(key, defaultValue);
}
public boolean getBoolean(String key) {
return this.getBoolean(key, false);
}
public boolean getBoolean(String key, boolean defaultValue) {
if (this.isLoading)
return defaultValue;
try {
return (this.getValue(key, "0").equals("1")) || (this.getValue(key, "false").equals("true"));
} catch (Exception e) {
log.error("Failed to parse key {} with value '{}' to type boolean.", key, this.getValue(key));
}
return defaultValue;
}
public int getInt(String key) {
return this.getInt(key, 0);
}
public int getInt(String key, Integer defaultValue) {
if (this.isLoading)
return defaultValue;
try {
return Integer.parseInt(this.getValue(key, defaultValue.toString()));
} catch (Exception e) {
log.error("Failed to parse key {} with value '{}' to type integer.", key, this.getValue(key));
}
return defaultValue;
}
public double getDouble(String key) {
return this.getDouble(key, 0.0);
}
public double getDouble(String key, Double defaultValue) {
if (this.isLoading)
return defaultValue;
try {
return Double.parseDouble(this.getValue(key, defaultValue.toString()));
} catch (Exception e) {
log.error("Failed to parse key {} with value '{}' to type double.", key, this.getValue(key));
}
return defaultValue;
}
public void update(String key, String value) {
this.properties.setProperty(key, value);
}
public void register(String key, String value) {
if (this.properties.getProperty(key, null) != null)
return;
try (Connection connection = Emulator.getDatabase().getDataSource().getConnection(); PreparedStatement statement = connection.prepareStatement("INSERT INTO emulator_settings VALUES (?, ?)")) {
statement.setString(1, key);
statement.setString(2, value);
statement.execute();
} catch (SQLException e) {
log.error("Caught SQL exception", e);
}
this.update(key, value);
}
}
@@ -0,0 +1,66 @@
package com.eu.habbo.core;
import com.eu.habbo.Emulator;
import com.eu.habbo.habbohotel.users.Habbo;
import lombok.extern.slf4j.Slf4j;
import java.util.Map;
@Slf4j
public class CreditsScheduler extends Scheduler {
public static boolean IGNORE_HOTEL_VIEW;
public static boolean IGNORE_IDLED;
public static double HC_MODIFIER;
public CreditsScheduler() {
super(Emulator.getConfig().getInt("hotel.auto.credits.interval"));
this.reloadConfig();
}
public void reloadConfig() {
if (Emulator.getConfig().getBoolean("hotel.auto.credits.enabled")) {
IGNORE_HOTEL_VIEW = Emulator.getConfig().getBoolean("hotel.auto.credits.ignore.hotelview");
IGNORE_IDLED = Emulator.getConfig().getBoolean("hotel.auto.credits.ignore.idled");
HC_MODIFIER = Emulator.getConfig().getDouble("hotel.auto.credits.hc_modifier", 1.0);
if (this.disposed) {
this.disposed = false;
this.run();
}
} else {
this.disposed = true;
}
}
@Override
public void run() {
super.run();
Habbo habbo;
for (Map.Entry<Integer, Habbo> map : Emulator.getGameEnvironment().getHabboManager().getOnlineHabbos().entrySet()) {
habbo = map.getValue();
try {
if (habbo != null) {
if (habbo.getHabboInfo().getCurrentRoom() == null && IGNORE_HOTEL_VIEW)
continue;
if (habbo.getRoomUnit().isIdle() && IGNORE_IDLED)
continue;
habbo.giveCredits((int)(habbo.getHabboInfo().getRank().getCreditsTimerAmount() * (habbo.getHabboStats().hasActiveClub() ? HC_MODIFIER : 1.0)));
}
} catch (Exception e) {
log.error("Caught exception", e);
}
}
}
public boolean isDisposed() {
return this.disposed;
}
public void setDisposed(boolean disposed) {
this.disposed = disposed;
}
}
@@ -0,0 +1,33 @@
package com.eu.habbo.core;
public class CryptoConfig {
private final boolean enabled;
private final String exponent;
private final String modulus;
private final String privateExponent;
public CryptoConfig(boolean enabled, String exponent, String modulus, String privateExponent) {
this.enabled = enabled;
this.exponent = exponent;
this.modulus = modulus;
this.privateExponent = privateExponent;
}
public boolean isEnabled() {
return enabled;
}
public String getExponent() {
return exponent;
}
public String getModulus() {
return modulus;
}
public String getPrivateExponent() {
return privateExponent;
}
}
@@ -0,0 +1,12 @@
package com.eu.habbo.core;
import java.sql.PreparedStatement;
import java.sql.SQLException;
public interface DatabaseLoggable {
String getQuery();
void log(PreparedStatement statement) throws SQLException;
}
@@ -0,0 +1,25 @@
package com.eu.habbo.core;
import com.eu.habbo.Emulator;
import lombok.extern.slf4j.Slf4j;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
@Slf4j
public class DatabaseLogger {
public void store(final DatabaseLoggable loggable) {
Emulator.getThreading().run(() -> {
try (Connection connection = Emulator.getDatabase().getDataSource().getConnection()) {
try (PreparedStatement statement = connection.prepareStatement(loggable.getQuery())) {
loggable.log(statement);
statement.executeBatch();
}
} catch (SQLException e) {
log.error("Exception caught while saving loggable to database.", e);
}
});
}
}
@@ -0,0 +1,7 @@
package com.eu.habbo.core;
public interface Disposable {
void dispose();
boolean disposed();
}
@@ -0,0 +1,25 @@
package com.eu.habbo.core;
import com.eu.habbo.Emulator;
import com.eu.habbo.habbohotel.rooms.Room;
import com.eu.habbo.habbohotel.rooms.RoomChatMessage;
import com.eu.habbo.habbohotel.rooms.RoomChatMessageBubbles;
import com.eu.habbo.messages.outgoing.rooms.users.RoomUserRemoveComposer;
import com.eu.habbo.messages.outgoing.rooms.users.RoomUserWhisperComposer;
import com.eu.habbo.plugin.EventHandler;
import com.eu.habbo.plugin.events.users.UserSavedMottoEvent;
public class Easter {
@EventHandler
public static void onUserChangeMotto(UserSavedMottoEvent event) {
if (Emulator.getConfig().getBoolean("easter_eggs.enabled") && event.newMotto.equalsIgnoreCase("crickey!")) {
event.habbo.getClient().sendResponse(new RoomUserWhisperComposer(new RoomChatMessage(event.newMotto, event.habbo, event.habbo, RoomChatMessageBubbles.ALERT)));
Room room = event.habbo.getHabboInfo().getCurrentRoom();
room.sendComposer(new RoomUserRemoveComposer(event.habbo.getRoomUnit()).compose());
room.sendComposer(new RoomUserPetComposer(2, 1, "FFFFFF", event.habbo).compose());
}
}
}
@@ -0,0 +1,63 @@
package com.eu.habbo.core;
import com.eu.habbo.Emulator;
import lombok.extern.slf4j.Slf4j;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.sql.PreparedStatement;
import java.sql.SQLException;
@Slf4j
public class ErrorLog implements DatabaseLoggable {
private static final String QUERY = "INSERT INTO emulator_errors (timestamp, version, build_hash, type, stacktrace) VALUES (?, ?, ?, ?, ?)";
public final String version;
public final String buildHash;
public final int timeStamp;
public final String type;
public final String stackTrace;
public ErrorLog(String type, Throwable e) {
this.version = Emulator.version;
this.buildHash = Emulator.version;
this.timeStamp = Emulator.getIntUnixTimestamp();
this.type = type;
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
e.printStackTrace(pw);
this.stackTrace = sw.toString();
try {
pw.close();
sw.close();
} catch (IOException e1) {
log.error("Exception caught", e1);
}
}
public ErrorLog(String type, String message) {
this.version = Emulator.version;
this.buildHash = Emulator.build;
this.timeStamp = Emulator.getIntUnixTimestamp();
this.type = type;
this.stackTrace = message;
}
@Override
public String getQuery() {
return QUERY;
}
@Override
public void log(PreparedStatement statement) throws SQLException {
statement.setInt(1, this.timeStamp);
statement.setString(2, this.version);
statement.setString(3, this.buildHash);
statement.setString(4, this.type);
statement.setString(5, this.stackTrace);
statement.addBatch();
}
}
@@ -0,0 +1,79 @@
package com.eu.habbo.core;
import com.eu.habbo.Emulator;
import com.eu.habbo.habbohotel.users.Habbo;
import lombok.extern.slf4j.Slf4j;
import java.util.Map;
@Slf4j
public class GotwPointsScheduler extends Scheduler {
public static boolean IGNORE_HOTEL_VIEW;
public static boolean IGNORE_IDLED;
public static String GOTW_POINTS_NAME;
public static double HC_MODIFIER;
public GotwPointsScheduler() { //TODO MOVE TO A PLUGIN. IS NOT PART OF OFFICIAL HABBO.
super(Emulator.getConfig().getInt("hotel.auto.gotwpoints.interval"));
this.reloadConfig();
}
public void reloadConfig() {
if (Emulator.getConfig().getBoolean("hotel.auto.gotwpoints.enabled")) {
IGNORE_HOTEL_VIEW = Emulator.getConfig().getBoolean("hotel.auto.gotwpoints.ignore.hotelview");
IGNORE_IDLED = Emulator.getConfig().getBoolean("hotel.auto.gotwpoints.ignore.idled");
HC_MODIFIER = Emulator.getConfig().getDouble("hotel.auto.gotwpoints.hc_modifier", 1.0);
GOTW_POINTS_NAME = Emulator.getConfig().getValue("hotel.auto.gotwpoints.name");
if (this.disposed) {
this.disposed = false;
this.run();
}
} else {
this.disposed = true;
}
}
@Override
public void run() {
super.run();
Habbo habbo;
for (Map.Entry<Integer, Habbo> map : Emulator.getGameEnvironment().getHabboManager().getOnlineHabbos().entrySet()) {
habbo = map.getValue();
try {
if (habbo != null) {
if (habbo.getHabboInfo().getCurrentRoom() == null && IGNORE_HOTEL_VIEW)
continue;
if (habbo.getRoomUnit().isIdle() && IGNORE_IDLED)
continue;
int type;
boolean found = false;
for (String s : Emulator.getConfig().getValue("seasonal.currency.names").split(";")) {
if (s.equalsIgnoreCase(GOTW_POINTS_NAME) || (GOTW_POINTS_NAME.startsWith(s) && Math.abs(s.length() - GOTW_POINTS_NAME.length()) < 3)) {
found = true;
break;
}
}
type = Emulator.getConfig().getInt("seasonal.currency." + GOTW_POINTS_NAME, -1);
if (found || type != -1) {
habbo.givePoints(type, (int)(habbo.getHabboInfo().getRank().getGotwTimerAmount() * (habbo.getHabboStats().hasActiveClub() ? HC_MODIFIER : 1.0)));
}
}
} catch (Exception e) {
log.error("Caught exception", e);
}
}
}
public boolean isDisposed() {
return this.disposed;
}
public void setDisposed(boolean disposed) {
this.disposed = disposed;
}
}
@@ -0,0 +1,63 @@
package com.eu.habbo.core;
import com.eu.habbo.Emulator;
import lombok.extern.slf4j.Slf4j;
import java.sql.SQLException;
@Slf4j
public class Logging {
@Deprecated
public void logStart(Object line) {
log.info("[LOADING] {}", line);
}
@Deprecated
public void logShutdownLine(Object line) {
log.info("[SHUTDOWN] {}", line);
}
@Deprecated
public void logUserLine(Object line) {
log.info("[USER] {}", line);
}
@Deprecated
public void logDebugLine(Object line) {
log.debug("[DEBUG] {}", line);
}
@Deprecated
public void logPacketLine(Object line) {
if (Emulator.getConfig().getBoolean("debug.show.packets")) {
log.debug("[PACKET] {}", line);
}
}
@Deprecated
public void logUndefinedPacketLine(Object line) {
if (Emulator.getConfig().getBoolean("debug.show.packets.undefined")) {
log.debug("[PACKET] [UNDEFINED] {}", line);
}
}
@Deprecated
public void logErrorLine(Object line) {
log.error("[ERROR] {}", line);
}
@Deprecated
public void logSQLException(SQLException e) {
log.error("[ERROR] SQLException", e);
}
@Deprecated
public void logPacketError(Object e) {
log.error("[ERROR] PacketError {}", e);
}
@Deprecated
public void handleException(Exception e) {
log.error("[ERROR] Exception", e);
}
}
@@ -0,0 +1,63 @@
package com.eu.habbo.core;
import com.eu.habbo.Emulator;
import com.eu.habbo.habbohotel.users.Habbo;
import lombok.extern.slf4j.Slf4j;
import java.util.Map;
@Slf4j
public class PixelScheduler extends Scheduler {
public static boolean IGNORE_HOTEL_VIEW;
public static boolean IGNORE_IDLED;
public static double HC_MODIFIER;
public PixelScheduler() {
super(Emulator.getConfig().getInt("hotel.auto.pixels.interval"));
this.reloadConfig();
}
public void reloadConfig() {
if (Emulator.getConfig().getBoolean("hotel.auto.pixels.enabled")) {
IGNORE_HOTEL_VIEW = Emulator.getConfig().getBoolean("hotel.auto.pixels.ignore.hotelview");
IGNORE_IDLED = Emulator.getConfig().getBoolean("hotel.auto.pixels.ignore.idled");
HC_MODIFIER = Emulator.getConfig().getDouble("hotel.auto.pixels.hc_modifier", 1.0);
if (this.disposed) {
this.disposed = false;
this.run();
}
} else {
this.disposed = true;
}
}
@Override
public void run() {
super.run();
Habbo habbo;
for (Map.Entry<Integer, Habbo> map : Emulator.getGameEnvironment().getHabboManager().getOnlineHabbos().entrySet()) {
habbo = map.getValue();
try {
if (habbo != null) {
if (habbo.getHabboInfo().getCurrentRoom() == null && IGNORE_HOTEL_VIEW)
continue;
if (habbo.getRoomUnit().isIdle() && IGNORE_IDLED)
continue;
habbo.givePixels((int)(habbo.getHabboInfo().getRank().getPixelsTimerAmount() * (habbo.getHabboStats().hasActiveClub() ? HC_MODIFIER : 1.0)));
}
} catch (Exception e) {
log.error("Caught exception", e);
}
}
}
public boolean isDisposed() {
return this.disposed;
}
public void setDisposed(boolean disposed) {
this.disposed = disposed;
}
}
@@ -0,0 +1,66 @@
package com.eu.habbo.core;
import com.eu.habbo.Emulator;
import com.eu.habbo.habbohotel.users.Habbo;
import lombok.extern.slf4j.Slf4j;
import java.util.Map;
@Slf4j
public class PointsScheduler extends Scheduler {
public static boolean IGNORE_HOTEL_VIEW;
public static boolean IGNORE_IDLED;
public static double HC_MODIFIER;
public PointsScheduler() {
super(Emulator.getConfig().getInt("hotel.auto.points.interval"));
this.reloadConfig();
}
public void reloadConfig() {
if (Emulator.getConfig().getBoolean("hotel.auto.points.enabled")) {
IGNORE_HOTEL_VIEW = Emulator.getConfig().getBoolean("hotel.auto.points.ignore.hotelview");
IGNORE_IDLED = Emulator.getConfig().getBoolean("hotel.auto.points.ignore.idled");
HC_MODIFIER = Emulator.getConfig().getDouble("hotel.auto.points.hc_modifier", 1.0);
if (this.disposed) {
this.disposed = false;
this.run();
}
} else {
this.disposed = true;
}
}
@Override
public void run() {
super.run();
Habbo habbo;
for (Map.Entry<Integer, Habbo> map : Emulator.getGameEnvironment().getHabboManager().getOnlineHabbos().entrySet()) {
habbo = map.getValue();
try {
if (habbo != null) {
if (habbo.getHabboInfo().getCurrentRoom() == null && IGNORE_HOTEL_VIEW)
continue;
if (habbo.getRoomUnit().isIdle() && IGNORE_IDLED)
continue;
//habbo.givePoints(POINTS);
habbo.givePoints((int)(habbo.getHabboInfo().getRank().getDiamondsTimerAmount() * (habbo.getHabboStats().hasActiveClub() ? HC_MODIFIER : 1.0)));
}
} catch (Exception e) {
log.error("Caught exception", e);
}
}
}
public boolean isDisposed() {
return this.disposed;
}
public void setDisposed(boolean disposed) {
this.disposed = disposed;
}
}
@@ -0,0 +1,49 @@
package com.eu.habbo.core;
import com.eu.habbo.habbohotel.users.Habbo;
import com.eu.habbo.messages.ServerMessage;
import com.eu.habbo.messages.outgoing.MessageComposer;
import com.eu.habbo.messages.outgoing.Outgoing;
public class RoomUserPetComposer extends MessageComposer {
private final int petType;
private final int race;
private final String color;
private final Habbo habbo;
public RoomUserPetComposer(int petType, int race, String color, Habbo habbo) {
this.petType = petType;
this.race = race;
this.color = color;
this.habbo = habbo;
}
@Override
protected ServerMessage composeInternal() {
this.response.init(Outgoing.RoomUsersComposer);
this.response.appendInt(1);
this.response.appendInt(this.habbo.getHabboInfo().getId());
this.response.appendString(this.habbo.getHabboInfo().getUsername());
this.response.appendString("");
this.response.appendString(this.petType + " " + this.race + " " + this.color + " 2 2 -1 0 3 -1 0");
this.response.appendInt(this.habbo.getRoomUnit().getId());
this.response.appendInt(this.habbo.getRoomUnit().getX());
this.response.appendInt(this.habbo.getRoomUnit().getY());
this.response.appendString(this.habbo.getRoomUnit().getZ() + "");
this.response.appendInt(this.habbo.getRoomUnit().getBodyRotation().getValue());
this.response.appendInt(2);
this.response.appendInt(this.petType);
this.response.appendInt(this.habbo.getHabboInfo().getId());
this.response.appendString(this.habbo.getHabboInfo().getUsername());
this.response.appendInt(1);
this.response.appendBoolean(false);
this.response.appendBoolean(true);
this.response.appendBoolean(true); //Can toggle breeding permissions.
this.response.appendBoolean(true);
this.response.appendBoolean(true); //Can treat?
this.response.appendBoolean(true); //Can breed
this.response.appendInt(0);
this.response.appendString("");
return this.response;
}
}
@@ -0,0 +1,36 @@
package com.eu.habbo.core;
import com.eu.habbo.Emulator;
public class Scheduler implements Runnable {
protected boolean disposed;
protected int interval;
public Scheduler(int interval) {
this.interval = interval;
}
public boolean isDisposed() {
return this.disposed;
}
public void setDisposed(boolean disposed) {
this.disposed = disposed;
}
public int getInterval() {
return this.interval;
}
public void setInterval(int interval) {
this.interval = interval;
}
@Override
public void run() {
if (this.disposed)
return;
Emulator.getThreading().run(this, this.interval * 1000);
}
}
@@ -0,0 +1,97 @@
package com.eu.habbo.core;
import com.eu.habbo.Emulator;
import lombok.extern.slf4j.Slf4j;
import java.sql.*;
import java.util.Properties;
@Slf4j
public class TextsManager {
private final Properties texts;
public TextsManager() {
long millis = System.currentTimeMillis();
this.texts = new Properties();
try {
this.reload();
log.info("Texts Manager -> Loaded! (" + (System.currentTimeMillis() - millis) + " MS)");
} catch (Exception e) {
e.printStackTrace();
}
}
public void reload() throws Exception {
try (Connection connection = Emulator.getDatabase().getDataSource().getConnection(); Statement statement = connection.createStatement(); ResultSet set = statement.executeQuery("SELECT * FROM emulator_texts")) {
while (set.next()) {
if (this.texts.containsKey(set.getString("key"))) {
this.texts.setProperty(set.getString("key"), set.getString("value"));
} else {
this.texts.put(set.getString("key"), set.getString("value"));
}
}
} catch (SQLException e) {
log.error("Caught SQL exception", e);
}
}
public String getValue(String key) {
return this.getValue(key, "");
}
public String getValue(String key, String defaultValue) {
if (!this.texts.containsKey(key)) {
log.error("Text key not found: {}", key);
}
return this.texts.getProperty(key, defaultValue);
}
public boolean getBoolean(String key) {
return this.getBoolean(key, false);
}
public boolean getBoolean(String key, Boolean defaultValue) {
try {
return (this.getValue(key, "0").equals("1")) || (this.getValue(key, "false").equals("true"));
} catch (Exception e) {
log.error("Caught exception", e);
}
return defaultValue;
}
public int getInt(String key) {
return this.getInt(key, 0);
}
public int getInt(String key, Integer defaultValue) {
try {
return Integer.parseInt(this.getValue(key, defaultValue.toString()));
} catch (NumberFormatException e) {
log.error("Caught exception", e);
}
return defaultValue;
}
public void update(String key, String value) {
this.texts.setProperty(key, value);
}
public void register(String key, String value) {
if (this.texts.getProperty(key, null) != null)
return;
try (Connection connection = Emulator.getDatabase().getDataSource().getConnection(); PreparedStatement statement = connection.prepareStatement("INSERT INTO emulator_texts VALUES (?, ?)")) {
statement.setString(1, key);
statement.setString(2, value);
statement.execute();
} catch (SQLException e) {
log.error("Caught SQL exception", e);
}
this.update(key, value);
}
}
@@ -0,0 +1,62 @@
package com.eu.habbo.core.consolecommands;
import gnu.trove.map.hash.THashMap;
import lombok.extern.slf4j.Slf4j;
@Slf4j
public abstract class ConsoleCommand {
private static final THashMap<String, ConsoleCommand> commands = new THashMap<>();
public final String key;
public final String usage;
public ConsoleCommand(String key, String usage) {
this.key = key;
this.usage = usage;
}
public static void load() {
addCommand(new ConsoleShutdownCommand());
addCommand(new ConsoleInfoCommand());
addCommand(new ConsoleTestCommand());
addCommand(new ConsoleReconnectCameraCommand());
addCommand(new ShowInteractionsCommand());
addCommand(new ShowRCONCommands());
addCommand(new ThankyouArcturusCommand());
}
public static void addCommand(ConsoleCommand command) {
commands.put(command.key, command);
}
public static ConsoleCommand findCommand(String key) {
return commands.get(key);
}
public static boolean handle(String line) {
String[] message = line.split(" ");
if (message.length > 0) {
ConsoleCommand command = ConsoleCommand.findCommand(message[0]);
if (command != null) {
try {
command.handle(message);
return true;
} catch (Exception e) {
log.error("Caught exception", e);
}
} else {
log.info("Unknown Console Command " + message[0]);
log.info("Commands Available (" + commands.size() + "): ");
for (ConsoleCommand c : commands.values()) {
log.info(c.key + " - " + c.usage);
}
}
}
return false;
}
public abstract void handle(String[] args) throws Exception;
}
@@ -0,0 +1,40 @@
package com.eu.habbo.core.consolecommands;
import com.eu.habbo.Emulator;
import com.eu.habbo.habbohotel.catalog.CatalogManager;
import lombok.extern.slf4j.Slf4j;
import java.util.concurrent.TimeUnit;
@Slf4j
public class ConsoleInfoCommand extends ConsoleCommand {
public ConsoleInfoCommand() {
super("info", "Show current statistics.");
}
@Override
public void handle(String[] args) throws Exception {
int seconds = Emulator.getIntUnixTimestamp() - Emulator.getTimeStarted();
int day = (int) TimeUnit.SECONDS.toDays(seconds);
long hours = TimeUnit.SECONDS.toHours(seconds) - (day * 24);
long minute = TimeUnit.SECONDS.toMinutes(seconds) - (TimeUnit.SECONDS.toHours(seconds) * 60);
long second = TimeUnit.SECONDS.toSeconds(seconds) - (TimeUnit.SECONDS.toMinutes(seconds) * 60);
log.info("Emulator version: " + Emulator.version);
log.info("Emulator build: " + Emulator.build);
log.info("");
log.info("Hotel Statistics");
log.info("- Users: " + Emulator.getGameEnvironment().getHabboManager().getOnlineCount());
log.info("- Rooms: " + Emulator.getGameEnvironment().getRoomManager().getActiveRooms().size());
log.info("- Shop: " + Emulator.getGameEnvironment().getCatalogManager().catalogPages.size() + " pages and " + CatalogManager.catalogItemAmount + " items.");
log.info("- Furni: " + Emulator.getGameEnvironment().getItemManager().getItems().size() + " items.");
log.info("");
log.info("Server Statistics");
log.info("- Uptime: " + day + (day > 1 ? " days, " : " day, ") + hours + (hours > 1 ? " hours, " : " hour, ") + minute + (minute > 1 ? " minutes, " : " minute, ") + second + (second > 1 ? " seconds!" : " second!"));
log.info("- RAM Usage: " + (Emulator.getRuntime().totalMemory() - Emulator.getRuntime().freeMemory()) / (1024 * 1024) + "/" + (Emulator.getRuntime().freeMemory()) / (1024 * 1024) + "MB");
log.info("- CPU Cores: " + Emulator.getRuntime().availableProcessors());
log.info("- Total Memory: " + Emulator.getRuntime().maxMemory() / (1024 * 1024) + "MB");
}
}
@@ -0,0 +1,17 @@
package com.eu.habbo.core.consolecommands;
import com.eu.habbo.networking.camera.CameraClient;
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class ConsoleReconnectCameraCommand extends ConsoleCommand {
public ConsoleReconnectCameraCommand() {
super("camera", "Attempt to reconnect to the camera server.");
}
@Override
public void handle(String[] args) throws Exception {
log.info("Connecting to the camera...");
CameraClient.attemptReconnect = true;
}
}
@@ -0,0 +1,14 @@
package com.eu.habbo.core.consolecommands;
import com.eu.habbo.habbohotel.commands.ShutdownCommand;
public class ConsoleShutdownCommand extends ConsoleCommand {
public ConsoleShutdownCommand() {
super("stop", "Stop the emulator.");
}
@Override
public void handle(String[] args) throws Exception {
new ShutdownCommand().handle(null, args);
}
}
@@ -0,0 +1,22 @@
package com.eu.habbo.core.consolecommands;
import com.eu.habbo.Emulator;
import com.eu.habbo.habbohotel.users.Habbo;
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class ConsoleTestCommand extends ConsoleCommand {
public ConsoleTestCommand() {
super("test", "This is just a test.");
}
@Override
public void handle(String[] args) throws Exception {
if (Emulator.debugging) {
log.info("This is a test command for live debugging.");
//AchievementManager.progressAchievement(4, Emulator.getGameEnvironment().getAchievementManager().getAchievement("AllTimeHotelPresence"), 30);
Habbo habbo = Emulator.getGameEnvironment().getHabboManager().getHabbo(1);
habbo.getHabboInfo().getMachineID();
}
}
}
@@ -0,0 +1,19 @@
package com.eu.habbo.core.consolecommands;
import com.eu.habbo.Emulator;
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class ShowInteractionsCommand extends ConsoleCommand {
public ShowInteractionsCommand() {
super("interactions", "Show a list of available furniture interactions.");
}
@Override
public void handle(String[] args) throws Exception {
for (String interaction : Emulator.getGameEnvironment().getItemManager().getInteractionList()) {
log.info(interaction);
}
}
}
@@ -0,0 +1,19 @@
package com.eu.habbo.core.consolecommands;
import com.eu.habbo.Emulator;
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class ShowRCONCommands extends ConsoleCommand {
public ShowRCONCommands() {
super("rconcommands", "Show a list of all RCON commands");
}
@Override
public void handle(String[] args) throws Exception {
for (String command : Emulator.getRconServer().getCommands()) {
log.info(command);
}
}
}
@@ -0,0 +1,42 @@
package com.eu.habbo.core.consolecommands;
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class ThankyouArcturusCommand extends ConsoleCommand {
public ThankyouArcturusCommand() {
super("thankyou", "A thankyou message.");
}
@Override
public void handle(String[] args) throws Exception {
log.info("Arcturus Morningstar is an opensource community fork of Arcturus Emulator by TheGeneral");
log.info("Thankyou to the following people who have helped with it's development:");
log.info("TheGeneral - For Creating Arcturus.");
log.info("Capheus - Decompilation");
log.info("Beny - Lead Developer");
log.info("Alejandro - Lead Developer");
log.info("Harmonic - Developer");
log.info("ArpyAge - Developer");
log.info("Mike - Developer");
log.info("Skeletor - Developer");
log.info("zGrav - Developer");
log.info("Swirny - Developer");
log.info("Quadral - Developer");
log.info("Dome - Developer");
log.info("Necmi - Developer");
log.info("Oliver - Support");
log.info("Rasmus - Support");
log.info("Layne - Support");
log.info("Bill - Support");
log.info("Harmony - Support");
log.info("Ridge - Catalogue");
log.info("Tenshie - Catalogue");
log.info("Wulles - Catalogue");
log.info("Gizmo - Catalogue");
log.info("TheJava - Motivation");
log.info("The Entire Krews.org Community.");
}
}
@@ -0,0 +1,108 @@
package com.eu.habbo.crypto;
import com.eu.habbo.crypto.exceptions.HabboCryptoException;
import com.eu.habbo.crypto.utils.BigIntegerUtils;
import com.eu.habbo.util.HexUtils;
import java.math.BigInteger;
import java.nio.charset.StandardCharsets;
import java.util.concurrent.ThreadLocalRandom;
public class HabboDiffieHellman {
private static final int DH_PRIMES_BIT_SIZE = 128;
private static final int DH_KEY_BIT_SIZE = 128;
private final HabboRSACrypto crypto;
private BigInteger DHPrime;
private BigInteger DHGenerator;
private BigInteger DHPrivate;
private BigInteger DHPublic;
public HabboDiffieHellman(HabboRSACrypto crypto) {
this.crypto = crypto;
this.generateDHPrimes();
this.generateDHKeys();
}
public BigInteger getDHPrime() {
return DHPrime;
}
public BigInteger getDHGenerator() {
return DHGenerator;
}
private void generateDHPrimes() {
this.DHPrime = BigInteger.probablePrime(DH_PRIMES_BIT_SIZE, ThreadLocalRandom.current());
this.DHGenerator = BigInteger.probablePrime(DH_PRIMES_BIT_SIZE, ThreadLocalRandom.current());
if (this.DHGenerator.compareTo(this.DHPrime) > 0) {
BigInteger temp = this.DHPrime;
this.DHPrime = this.DHGenerator;
this.DHGenerator = temp;
}
}
private void generateDHKeys() {
this.DHPrivate = BigInteger.probablePrime(DH_KEY_BIT_SIZE, ThreadLocalRandom.current());
this.DHPublic = this.DHGenerator.modPow(this.DHPrivate, this.DHPrime);
}
private String encryptBigInteger(BigInteger integer) throws HabboCryptoException {
String str = integer.toString(10);
byte[] bytes = str.getBytes(StandardCharsets.UTF_8);
byte[] encrypted = this.crypto.Sign(bytes);
return HexUtils.toHex(encrypted).toLowerCase();
}
private BigInteger decryptBigInteger(String str) throws HabboCryptoException {
byte[] bytes = HexUtils.toBytes(str);
byte[] decrypted = this.crypto.Decrypt(bytes);
String intStr = new String(decrypted, StandardCharsets.UTF_8);
return new BigInteger(intStr, 10);
}
public String getPublicKey() throws HabboCryptoException {
return encryptBigInteger(this.DHPublic);
}
public String getSignedPrime() throws HabboCryptoException {
return encryptBigInteger(this.DHPrime);
}
public String getSignedGenerator() throws HabboCryptoException {
return encryptBigInteger(this.DHGenerator);
}
public void doHandshake(String signedPrime, String signedGenerator) throws HabboCryptoException {
this.DHPrime = decryptBigInteger(signedPrime);
this.DHGenerator = decryptBigInteger(signedGenerator);
if (this.DHPrime == null || this.DHGenerator == null) {
throw new HabboCryptoException("DHPrime or DHGenerator was null.");
}
if (this.DHPrime.compareTo(BigInteger.valueOf(2)) < 1) {
throw new HabboCryptoException("Prime cannot be <= 2!\nPrime: " + this.DHPrime.toString());
}
if (this.DHGenerator.compareTo(this.DHPrime) > -1) {
throw new HabboCryptoException("Generator cannot be >= Prime!\nPrime: " + this.DHPrime.toString() + "\nGenerator: " + this.DHGenerator.toString());
}
generateDHKeys();
}
public byte[] getSharedKey(String publicKeyStr) throws HabboCryptoException {
BigInteger publicKey = this.decryptBigInteger(publicKeyStr);
BigInteger sharedKey = publicKey.modPow(this.DHPrivate, this.DHPrime);
return BigIntegerUtils.toUnsignedByteArray(sharedKey);
}
}
@@ -0,0 +1,21 @@
package com.eu.habbo.crypto;
public class HabboEncryption {
private final HabboRSACrypto crypto;
private final HabboDiffieHellman diffie;
public HabboEncryption(String e, String n, String d) {
this.crypto = new HabboRSACrypto(e, n, d);
this.diffie = new HabboDiffieHellman(this.crypto);
}
public HabboRSACrypto getCrypto() {
return crypto;
}
public HabboDiffieHellman getDiffie() {
return diffie;
}
}
@@ -0,0 +1,46 @@
package com.eu.habbo.crypto;
public class HabboRC4 {
private int i;
private int j;
private final int[] table = new int[256];
public HabboRC4(byte[] key) {
int length = key.length;
while (this.i < 256) {
table[this.i] = this.i;
this.i++;
}
this.i = 0;
this.j = 0;
while (this.i < 256) {
this.j = ((this.j + this.table[this.i]) + (key[this.i % length] & 0xff)) % 256;
this.swap(this.i, this.j);
this.i++;
}
this.i = 0;
this.j = 0;
}
private void swap(int a, int b) {
int num = table[a];
table[a] = table[b];
table[b] = num;
}
public void parse(byte[] bytes) {
for (int index1 = 0; index1 < bytes.length; index1++) {
this.i = (this.i + 1) % 256;
this.j = (this.j + this.table[this.i]) % 256;
this.swap(this.i, this.j);
bytes[index1] = (byte) ((bytes[index1] & 0xFF) ^ this.table[(this.table[this.i] + this.table[this.j]) % 256]);
}
}
}
@@ -0,0 +1,168 @@
package com.eu.habbo.crypto;
import com.eu.habbo.crypto.exceptions.HabboCryptoException;
import com.eu.habbo.crypto.utils.BigIntegerUtils;
import org.apache.commons.lang3.mutable.MutableInt;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.math.BigInteger;
import java.util.concurrent.ThreadLocalRandom;
public class HabboRSACrypto {
private final BigInteger e;
private final BigInteger n;
private final BigInteger d;
private final int blockSize;
public HabboRSACrypto(String e, String n) {
this.e = new BigInteger(e, 16);
this.n = new BigInteger(n, 16);
this.d = null;
this.blockSize = (this.n.bitLength() + 7) / 8;
}
public HabboRSACrypto(String e, String n, String d) {
this.e = new BigInteger(e, 16);
this.n = new BigInteger(n, 16);
this.d = new BigInteger(d, 16);
this.blockSize = (this.n.bitLength() + 7) / 8;
}
public byte[] Encrypt(byte[] data) throws HabboCryptoException {
return DoEncrypt(data, true, 2);
}
public byte[] Decrypt(byte[] data) throws HabboCryptoException {
return DoDecrypt(data, false, 2);
}
public byte[] Sign(byte[] data) throws HabboCryptoException {
return DoEncrypt(data, false, 1);
}
public byte[] Verify(byte[] data) throws HabboCryptoException {
return DoDecrypt(data, true, 1);
}
private BigInteger DoPublic(BigInteger x) {
return x.modPow(this.e, this.n);
}
private BigInteger DoPrivate(BigInteger x) {
return x.modPow(this.d, this.n);
}
private byte[] DoEncrypt(byte[] data, boolean isPublic, int padType) throws HabboCryptoException {
try (ByteArrayOutputStream dst = new ByteArrayOutputStream()) {
int bl = this.blockSize;
int end = data.length;
MutableInt pos = new MutableInt(0);
while (pos.intValue() < end) {
byte[] padded = Pkcs1Pad(data, pos, end, bl, padType);
BigInteger block = new BigInteger(padded);
BigInteger chunk = isPublic ? DoPublic(block) : DoPrivate(block);
for (int b = (int) (bl - Math.ceil(chunk.bitLength() / 8.0)); b > 0; --b) {
dst.write(0x00);
}
dst.write(BigIntegerUtils.toUnsignedByteArray(chunk));
}
return dst.toByteArray();
} catch (IOException e) {
throw new HabboCryptoException(e);
}
}
private byte[] DoDecrypt(byte[] data, boolean isPublic, int padType) throws HabboCryptoException {
if (data.length % this.blockSize != 0) {
throw new HabboCryptoException("Decryption data was not in blocks of " + this.blockSize + " bytes, total " + data.length + ".");
}
try (ByteArrayOutputStream dst = new ByteArrayOutputStream()) {
int end = data.length;
int pos = 0;
while (pos < end) {
byte[] blockData = new byte[this.blockSize];
System.arraycopy(data, pos, blockData, 0, this.blockSize);
BigInteger block = new BigInteger(1, blockData);
BigInteger chunk = isPublic ? DoPublic(block) : DoPrivate(block);
byte[] unpadded = Pkcs1Unpad(chunk.toByteArray(), this.blockSize, padType);
pos += this.blockSize;
dst.write(unpadded);
}
return dst.toByteArray();
} catch (IOException e) {
throw new HabboCryptoException(e);
}
}
private static byte[] Pkcs1Pad(byte[] src, MutableInt pos, int end, int n, int padType) {
byte[] result = new byte[n];
int p = pos.intValue();
end = Math.min(end, Math.min(src.length, p + n - 11));
pos.setValue(end);
int i = end - 1;
while (i >= p && n > 11) {
result[--n] = src[i--];
}
result[--n] = 0;
if (padType == 2) {
while (n > 2) {
result[--n] = (byte) ThreadLocalRandom.current().nextInt(1, 256);
}
} else {
while (n > 2) {
result[--n] = (byte) 0xFF;
}
}
result[--n] = (byte) padType;
result[--n] = 0;
return result;
}
private static byte[] Pkcs1Unpad(byte[] b, int n, int padType) throws HabboCryptoException {
byte[] result = new byte[n];
int resultPos = 0;
int i = 0;
while (i < b.length && b[i] == 0) {
++i;
}
if (b.length - i != n - 1 || b[i] != padType) {
throw new HabboCryptoException("PKCS#1 unpad: i=" + i + ", expected b[i]==" + padType + ", got b[i]=" + b[i]);
}
++i;
while (b[i] != 0) {
if (++i >= b.length) {
throw new HabboCryptoException("PKCS#1 unpad: i=" + i + ", b[i-1]!=0 (=" + b[i-1] + ")");
}
}
while (++i < b.length) {
result[resultPos++] = b[i];
}
byte[] resultCopy = new byte[resultPos];
System.arraycopy(result, 0, resultCopy, 0, resultPos);
return resultCopy;
}
}
@@ -0,0 +1,17 @@
package com.eu.habbo.crypto.exceptions;
public class HabboCryptoException extends Exception {
public HabboCryptoException(String message) {
super(message);
}
public HabboCryptoException(String message, Throwable cause) {
super(message, cause);
}
public HabboCryptoException(Throwable cause) {
super(cause);
}
}
@@ -0,0 +1,17 @@
package com.eu.habbo.crypto.utils;
import java.math.BigInteger;
import java.util.Arrays;
public class BigIntegerUtils {
public static byte[] toUnsignedByteArray(BigInteger bigInteger) {
byte[] bytes = bigInteger.toByteArray();
if (bytes[0] == 0) {
bytes = Arrays.copyOfRange(bytes, 1, bytes.length);
}
return bytes;
}
}
@@ -0,0 +1,109 @@
package com.eu.habbo.database;
import com.eu.habbo.Emulator;
import com.eu.habbo.core.ConfigurationManager;
import com.zaxxer.hikari.HikariDataSource;
import gnu.trove.map.hash.THashMap;
import gnu.trove.set.hash.THashSet;
import lombok.extern.slf4j.Slf4j;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@Slf4j
public class Database {
private HikariDataSource dataSource;
private DatabasePool databasePool;
public Database(ConfigurationManager config) {
long millis = System.currentTimeMillis();
boolean SQLException = false;
try {
this.databasePool = new DatabasePool();
if (!this.databasePool.getStoragePooling(config)) {
log.info("Failed to connect to the database. Please check config.ini and make sure the MySQL process is running. Shutting down...");
SQLException = true;
return;
}
this.dataSource = this.databasePool.getDatabase();
} catch (Exception e) {
SQLException = true;
log.error("Failed to connect to your database.", e);
} finally {
if (SQLException) {
Emulator.prepareShutdown();
}
}
log.info("Database -> Connected! ({} MS)", System.currentTimeMillis() - millis);
}
public void dispose() {
if (this.databasePool != null) {
this.databasePool.getDatabase().close();
}
this.dataSource.close();
}
public HikariDataSource getDataSource() {
return this.dataSource;
}
public DatabasePool getDatabasePool() {
return this.databasePool;
}
public static PreparedStatement preparedStatementWithParams(Connection connection, String query, THashMap<String, Object> queryParams) throws SQLException {
THashMap<Integer, Object> params = new THashMap<Integer, Object>();
THashSet<String> quotedParams = new THashSet<>();
for(String key : queryParams.keySet()) {
quotedParams.add(Pattern.quote(key));
}
String regex = "(" + String.join("|", quotedParams) + ")";
Matcher m = Pattern.compile(regex).matcher(query);
int i = 1;
while (m.find()) {
try {
params.put(i, queryParams.get(m.group(1)));
i++;
}
catch (Exception ignored) { }
}
PreparedStatement statement = connection.prepareStatement(query.replaceAll(regex, "?"));
for(Map.Entry<Integer, Object> set : params.entrySet()) {
if(set.getValue().getClass() == String.class) {
statement.setString(set.getKey(), (String)set.getValue());
}
else if(set.getValue().getClass() == Integer.class) {
statement.setInt(set.getKey(), (Integer)set.getValue());
}
else if(set.getValue().getClass() == Double.class) {
statement.setDouble(set.getKey(), (Double)set.getValue());
}
else if(set.getValue().getClass() == Float.class) {
statement.setFloat(set.getKey(), (Float)set.getValue());
}
else if(set.getValue().getClass() == Long.class) {
statement.setLong(set.getKey(), (Long)set.getValue());
}
else {
statement.setObject(set.getKey(), set.getValue());
}
}
return statement;
}
}
@@ -0,0 +1,60 @@
package com.eu.habbo.database;
import com.eu.habbo.core.ConfigurationManager;
import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
import lombok.extern.slf4j.Slf4j;
@Slf4j
class DatabasePool {
private static final String DB_POOL_MAX_SIZE = "db.pool.maxsize";
private static final String DB_POOL_MIN_SIZE = "db.pool.minsize";
private static final String DB_HOSTNAME_KEY = "db.hostname";
private static final String DB_PORT_KEY = "db.port";
private static final String DB_PASSWORD_KEY = "db.password";
private static final String DB_NAME_KEY = "db.database";
private static final String DB_USER_KEY = "db.username";
private static final String DB_PARAMS_KEY = "db.params";
private HikariDataSource database;
private static DatabasePool instance;
DatabasePool() {
// Private constructor for singleton pattern
}
public static synchronized DatabasePool getInstance() {
if (instance == null) {
instance = new DatabasePool();
}
return instance;
}
public boolean getStoragePooling(ConfigurationManager config) {
try {
HikariConfig databaseConfiguration = new HikariConfig();
databaseConfiguration.setMaximumPoolSize(config.getInt(DB_POOL_MAX_SIZE, 50));
databaseConfiguration.setMinimumIdle(config.getInt(DB_POOL_MIN_SIZE, 10));
databaseConfiguration.setJdbcUrl("jdbc:mysql://" + config.getValue(DB_HOSTNAME_KEY, "localhost") + ":" + config.getValue(DB_PORT_KEY, "3306") + "/" + config.getValue(DB_NAME_KEY) + config.getValue(DB_PARAMS_KEY));
databaseConfiguration.addDataSourceProperty("serverName", config.getValue(DB_HOSTNAME_KEY, "localhost"));
databaseConfiguration.addDataSourceProperty("port", config.getValue(DB_PORT_KEY, "3306"));
databaseConfiguration.addDataSourceProperty("databaseName", config.getValue(DB_NAME_KEY));
databaseConfiguration.addDataSourceProperty("user", config.getValue(DB_USER_KEY));
databaseConfiguration.addDataSourceProperty("password", config.getValue(DB_PASSWORD_KEY));
log.info("INITIALIZING DATABASE SERVER: " + config.getValue(DB_HOSTNAME_KEY));
log.info("ON PORT: " + config.getValue(DB_PORT_KEY));
log.info("HABBO DATABASE: " + config.getValue(DB_NAME_KEY));
this.database = new HikariDataSource(databaseConfiguration);
} catch (Exception e) {
log.error("Error initializing database connection pool: {}", e.getMessage());
return false;
}
return true;
}
public HikariDataSource getDatabase() {
if (database == null) {
throw new IllegalStateException("Database connection pool is not initialized.");
}
return database;
}
}
@@ -0,0 +1,212 @@
package com.eu.habbo.habbohotel;
import com.eu.habbo.Emulator;
import com.eu.habbo.core.*;
import com.eu.habbo.habbohotel.achievements.AchievementManager;
import com.eu.habbo.habbohotel.bots.BotManager;
import com.eu.habbo.habbohotel.campaign.calendar.CalendarManager;
import com.eu.habbo.habbohotel.catalog.CatalogManager;
import com.eu.habbo.habbohotel.commands.CommandHandler;
import com.eu.habbo.habbohotel.crafting.CraftingManager;
import com.eu.habbo.habbohotel.guides.GuideManager;
import com.eu.habbo.habbohotel.guilds.GuildManager;
import com.eu.habbo.habbohotel.hotelview.HotelViewManager;
import com.eu.habbo.habbohotel.items.ItemManager;
import com.eu.habbo.habbohotel.modtool.ModToolManager;
import com.eu.habbo.habbohotel.modtool.ModToolSanctions;
import com.eu.habbo.habbohotel.modtool.WordFilter;
import com.eu.habbo.habbohotel.navigation.NavigatorManager;
import com.eu.habbo.habbohotel.permissions.PermissionsManager;
import com.eu.habbo.habbohotel.pets.PetManager;
import com.eu.habbo.habbohotel.polls.PollManager;
import com.eu.habbo.habbohotel.rooms.RoomManager;
import com.eu.habbo.habbohotel.users.HabboManager;
import com.eu.habbo.habbohotel.users.subscriptions.SubscriptionManager;
import com.eu.habbo.habbohotel.users.subscriptions.SubscriptionScheduler;
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class GameEnvironment {
public CreditsScheduler creditsScheduler;
public PixelScheduler pixelScheduler;
public PointsScheduler pointsScheduler;
public GotwPointsScheduler gotwPointsScheduler;
public SubscriptionScheduler subscriptionScheduler;
private HabboManager habboManager;
private NavigatorManager navigatorManager;
private GuildManager guildManager;
private ItemManager itemManager;
private CatalogManager catalogManager;
private HotelViewManager hotelViewManager;
private RoomManager roomManager;
private CommandHandler commandHandler;
private PermissionsManager permissionsManager;
private BotManager botManager;
private ModToolManager modToolManager;
private ModToolSanctions modToolSanctions;
private PetManager petManager;
private AchievementManager achievementManager;
private GuideManager guideManager;
private WordFilter wordFilter;
private CraftingManager craftingManager;
private PollManager pollManager;
private SubscriptionManager subscriptionManager;
private CalendarManager calendarManager;
public void load() throws Exception {
log.info("GameEnvironment -> Loading...");
this.permissionsManager = new PermissionsManager();
this.habboManager = new HabboManager();
this.hotelViewManager = new HotelViewManager();
this.itemManager = new ItemManager();
this.itemManager.load();
this.botManager = new BotManager();
this.petManager = new PetManager();
this.guildManager = new GuildManager();
this.catalogManager = new CatalogManager();
this.roomManager = new RoomManager();
this.navigatorManager = new NavigatorManager();
this.commandHandler = new CommandHandler();
this.modToolManager = new ModToolManager();
this.modToolSanctions = new ModToolSanctions();
this.achievementManager = new AchievementManager();
this.achievementManager.reload();
this.guideManager = new GuideManager();
this.wordFilter = new WordFilter();
this.craftingManager = new CraftingManager();
this.pollManager = new PollManager();
this.calendarManager = new CalendarManager();
this.roomManager.loadPublicRooms();
this.navigatorManager.loadNavigator();
this.creditsScheduler = new CreditsScheduler();
Emulator.getThreading().run(this.creditsScheduler);
this.pixelScheduler = new PixelScheduler();
Emulator.getThreading().run(this.pixelScheduler);
this.pointsScheduler = new PointsScheduler();
Emulator.getThreading().run(this.pointsScheduler);
this.gotwPointsScheduler = new GotwPointsScheduler();
Emulator.getThreading().run(this.gotwPointsScheduler);
this.subscriptionManager = new SubscriptionManager();
this.subscriptionManager.init();
this.subscriptionScheduler = new SubscriptionScheduler();
Emulator.getThreading().run(this.subscriptionScheduler);
log.info("GameEnvironment -> Loaded!");
}
public void dispose() {
this.pointsScheduler.setDisposed(true);
this.pixelScheduler.setDisposed(true);
this.creditsScheduler.setDisposed(true);
this.gotwPointsScheduler.setDisposed(true);
this.craftingManager.dispose();
this.habboManager.dispose();
this.commandHandler.dispose();
this.guildManager.dispose();
this.catalogManager.dispose();
this.roomManager.dispose();
this.itemManager.dispose();
this.hotelViewManager.dispose();
this.subscriptionManager.dispose();
this.calendarManager.dispose();
log.info("GameEnvironment -> Disposed!");
}
public HabboManager getHabboManager() {
return this.habboManager;
}
public NavigatorManager getNavigatorManager() {
return this.navigatorManager;
}
public GuildManager getGuildManager() {
return this.guildManager;
}
public ItemManager getItemManager() {
return this.itemManager;
}
public CatalogManager getCatalogManager() {
return this.catalogManager;
}
public HotelViewManager getHotelViewManager() {
return this.hotelViewManager;
}
public RoomManager getRoomManager() {
return this.roomManager;
}
public CommandHandler getCommandHandler() {
return this.commandHandler;
}
public PermissionsManager getPermissionsManager() {
return this.permissionsManager;
}
public BotManager getBotManager() {
return this.botManager;
}
public ModToolManager getModToolManager() {
return this.modToolManager;
}
public ModToolSanctions getModToolSanctions() {
return this.modToolSanctions;
}
public PetManager getPetManager() {
return this.petManager;
}
public AchievementManager getAchievementManager() {
return this.achievementManager;
}
public GuideManager getGuideManager() {
return this.guideManager;
}
public WordFilter getWordFilter() {
return this.wordFilter;
}
public CraftingManager getCraftingManager() {
return this.craftingManager;
}
public PollManager getPollManager() {
return this.pollManager;
}
public CreditsScheduler getCreditsScheduler() {
return this.creditsScheduler;
}
public PixelScheduler getPixelScheduler() {
return this.pixelScheduler;
}
public PointsScheduler getPointsScheduler() { return this.pointsScheduler;
}
public GotwPointsScheduler getGotwPointsScheduler() { return this.gotwPointsScheduler;
}
public SubscriptionManager getSubscriptionManager() {
return this.subscriptionManager;
}
public CalendarManager getCalendarManager() { return this.calendarManager; }
}
@@ -0,0 +1,47 @@
package com.eu.habbo.habbohotel;
import com.eu.habbo.habbohotel.gameclients.GameClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.concurrent.TimeUnit;
public class LatencyTracker {
private static final Logger LOGGER = LoggerFactory.getLogger(GameClient.class);
private boolean initialPing;
private long last;
private long average;
public LatencyTracker() {
this.initialPing = true;
this.average = 0;
}
public void update(long latencyInNano) {
this.last = latencyInNano;
if (this.initialPing) {
this.initialPing = false;
this.average = latencyInNano;
return;
}
this.average = (long) (this.average * .7f + latencyInNano * .3f);
}
public boolean hasInitialized() {
return !this.initialPing;
}
public long getLastMs() {
return TimeUnit.NANOSECONDS.toMillis(this.last);
}
public long getAverageMs() {
return TimeUnit.NANOSECONDS.toMillis(this.average);
}
}
@@ -0,0 +1,77 @@
package com.eu.habbo.habbohotel.achievements;
import gnu.trove.map.hash.THashMap;
import java.sql.ResultSet;
import java.sql.SQLException;
public class Achievement {
public final int id;
public final String name;
public final AchievementCategories category;
public final THashMap<Integer, AchievementLevel> levels;
public Achievement(ResultSet set) throws SQLException {
this.levels = new THashMap<>();
this.id = set.getInt("id");
this.name = set.getString("name");
this.category = AchievementCategories.valueOf(set.getString("category").toUpperCase());
this.addLevel(new AchievementLevel(set));
}
public void addLevel(AchievementLevel level) {
synchronized (this.levels) {
this.levels.put(level.level, level);
}
}
public AchievementLevel getLevelForProgress(int progress) {
AchievementLevel l = null;
if (progress > 0) {
for (AchievementLevel level : this.levels.values()) {
if (progress >= level.progress) {
if (l != null) {
if (l.level > level.level) {
continue;
}
}
l = level;
}
}
}
return l;
}
public AchievementLevel getNextLevel(int currentLevel) {
AchievementLevel l = null;
for (AchievementLevel level : this.levels.values()) {
if (level.level == (currentLevel + 1))
return level;
}
return null;
}
public AchievementLevel firstLevel() {
return this.levels.get(1);
}
public void clearLevels() {
this.levels.clear();
}
}
@@ -0,0 +1,39 @@
package com.eu.habbo.habbohotel.achievements;
public enum AchievementCategories {
IDENTITY,
EXPLORE,
MUSIC,
SOCIAL,
GAMES,
ROOM_BUILDER,
PETS,
TOOLS,
OTHER,
TEST,
INVISIBLE,
EVENTS
}
@@ -0,0 +1,29 @@
package com.eu.habbo.habbohotel.achievements;
import java.sql.ResultSet;
import java.sql.SQLException;
public class AchievementLevel {
public final int level;
public final int rewardAmount;
public final int rewardType;
public final int points;
public final int progress;
public AchievementLevel(ResultSet set) throws SQLException {
this.level = set.getInt("level");
this.rewardAmount = set.getInt("reward_amount");
this.rewardType = set.getInt("reward_type");
this.points = set.getInt("points");
this.progress = set.getInt("progress_needed");
}
}
@@ -0,0 +1,394 @@
package com.eu.habbo.habbohotel.achievements;
import com.eu.habbo.Emulator;
import com.eu.habbo.habbohotel.items.Item;
import com.eu.habbo.habbohotel.users.Habbo;
import com.eu.habbo.habbohotel.users.HabboBadge;
import com.eu.habbo.habbohotel.users.HabboItem;
import com.eu.habbo.messages.outgoing.achievements.AchievementProgressComposer;
import com.eu.habbo.messages.outgoing.achievements.AchievementUnlockedComposer;
import com.eu.habbo.messages.outgoing.achievements.talenttrack.TalentLevelUpdateComposer;
import com.eu.habbo.messages.outgoing.inventory.AddHabboItemComposer;
import com.eu.habbo.messages.outgoing.inventory.InventoryRefreshComposer;
import com.eu.habbo.messages.outgoing.rooms.users.RoomUserDataComposer;
import com.eu.habbo.messages.outgoing.users.AddUserBadgeComposer;
import com.eu.habbo.messages.outgoing.users.UserBadgesComposer;
import com.eu.habbo.plugin.Event;
import com.eu.habbo.plugin.events.users.achievements.UserAchievementLeveledEvent;
import com.eu.habbo.plugin.events.users.achievements.UserAchievementProgressEvent;
import gnu.trove.map.hash.THashMap;
import gnu.trove.procedure.TObjectIntProcedure;
import lombok.extern.slf4j.Slf4j;
import java.sql.*;
import java.util.LinkedHashMap;
import java.util.Map;
@Slf4j
public class AchievementManager {
public static boolean TALENTTRACK_ENABLED = false;
private final THashMap<String, Achievement> achievements;
private final THashMap<TalentTrackType, LinkedHashMap<Integer, TalentTrackLevel>> talentTrackLevels;
public AchievementManager() {
this.achievements = new THashMap<>();
this.talentTrackLevels = new THashMap<>();
}
public static void progressAchievement(int habboId, Achievement achievement) {
progressAchievement(habboId, achievement, 1);
}
public static void progressAchievement(int habboId, Achievement achievement, int amount) {
if (achievement != null) {
Habbo habbo = Emulator.getGameEnvironment().getHabboManager().getHabbo(habboId);
if (habbo != null) {
progressAchievement(habbo, achievement, amount);
} else {
try (Connection connection = Emulator.getDatabase().getDataSource().getConnection();
PreparedStatement statement = connection.prepareStatement("" +
"INSERT INTO users_achievements_queue (user_id, achievement_id, amount) VALUES (?, ?, ?) " +
"ON DUPLICATE KEY UPDATE amount = amount + ?")) {
statement.setInt(1, habboId);
statement.setInt(2, achievement.id);
statement.setInt(3, amount);
statement.setInt(4, amount);
statement.execute();
} catch (SQLException e) {
log.error("Caught SQL exception", e);
}
}
}
}
public static void progressAchievement(Habbo habbo, Achievement achievement) {
progressAchievement(habbo, achievement, 1);
}
public static void progressAchievement(Habbo habbo, Achievement achievement, int amount) {
if (achievement == null)
return;
if (habbo == null)
return;
if (!habbo.isOnline())
return;
int currentProgress = habbo.getHabboStats().getAchievementProgress(achievement);
if (currentProgress == -1) {
currentProgress = 0;
createUserEntry(habbo, achievement);
habbo.getHabboStats().setProgress(achievement, 0);
}
if (Emulator.getPluginManager().isRegistered(UserAchievementProgressEvent.class, true)) {
Event userAchievementProgressedEvent = new UserAchievementProgressEvent(habbo, achievement, amount);
Emulator.getPluginManager().fireEvent(userAchievementProgressedEvent);
if (userAchievementProgressedEvent.isCancelled())
return;
}
AchievementLevel oldLevel = achievement.getLevelForProgress(currentProgress);
if (oldLevel != null && (oldLevel.level == achievement.levels.size() && currentProgress >= oldLevel.progress)) //Maximum achievement gotten.
return;
habbo.getHabboStats().setProgress(achievement, currentProgress + amount);
AchievementLevel newLevel = achievement.getLevelForProgress(currentProgress + amount);
if (AchievementManager.TALENTTRACK_ENABLED) {
for (TalentTrackType type : TalentTrackType.values()) {
if (Emulator.getGameEnvironment().getAchievementManager().talentTrackLevels.containsKey(type)) {
for (Map.Entry<Integer, TalentTrackLevel> entry : Emulator.getGameEnvironment().getAchievementManager().talentTrackLevels.get(type).entrySet()) {
if (entry.getValue().achievements.containsKey(achievement)) {
Emulator.getGameEnvironment().getAchievementManager().handleTalentTrackAchievement(habbo, type, achievement);
break;
}
}
}
}
}
if (newLevel == null ||
(oldLevel != null && (oldLevel.level == newLevel.level && newLevel.level < achievement.levels.size()))) {
habbo.getClient().sendResponse(new AchievementProgressComposer(habbo, achievement));
} else {
if (Emulator.getPluginManager().isRegistered(UserAchievementLeveledEvent.class, true)) {
Event userAchievementLeveledEvent = new UserAchievementLeveledEvent(habbo, achievement, oldLevel, newLevel);
Emulator.getPluginManager().fireEvent(userAchievementLeveledEvent);
if (userAchievementLeveledEvent.isCancelled())
return;
}
habbo.getClient().sendResponse(new AchievementProgressComposer(habbo, achievement));
habbo.getClient().sendResponse(new AchievementUnlockedComposer(habbo, achievement));
//Exception could possibly arise when the user disconnects while being in tour.
//The achievement is then progressed but the user is already disposed so fetching
//the badge would result in an nullpointer exception. This is normal behaviour.
HabboBadge badge = null;
if (oldLevel != null) {
try {
badge = habbo.getInventory().getBadgesComponent().getBadge(("ACH_" + achievement.name + oldLevel.level).toLowerCase());
} catch (Exception e) {
log.error("Caught exception", e);
return;
}
}
String newBadgCode = "ACH_" + achievement.name + newLevel.level;
if (badge != null) {
badge.setCode(newBadgCode);
badge.needsInsert(false);
badge.needsUpdate(true);
} else {
if (habbo.getInventory().getBadgesComponent().hasBadge(newBadgCode))
return;
badge = new HabboBadge(0, newBadgCode, 0, habbo);
habbo.getClient().sendResponse(new AddUserBadgeComposer(badge));
badge.needsInsert(true);
badge.needsUpdate(true);
habbo.getInventory().getBadgesComponent().addBadge(badge);
}
Emulator.getThreading().run(badge);
if (badge.getSlot() > 0) {
if (habbo.getHabboInfo().getCurrentRoom() != null) {
habbo.getHabboInfo().getCurrentRoom().sendComposer(new UserBadgesComposer(habbo.getInventory().getBadgesComponent().getWearingBadges(), habbo.getHabboInfo().getId()).compose());
}
}
habbo.getClient().sendResponse(new AddHabboItemComposer(badge.getId(), AddHabboItemComposer.AddHabboItemCategory.BADGE));
habbo.getHabboStats().addAchievementScore(newLevel.points);
if (newLevel.rewardAmount > 0) {
habbo.givePoints(newLevel.rewardType, newLevel.rewardAmount);
}
if (habbo.getHabboInfo().getCurrentRoom() != null) {
habbo.getHabboInfo().getCurrentRoom().sendComposer(new RoomUserDataComposer(habbo).compose());
}
}
}
public static boolean hasAchieved(Habbo habbo, Achievement achievement) {
int currentProgress = habbo.getHabboStats().getAchievementProgress(achievement);
if (currentProgress == -1) {
return false;
}
AchievementLevel level = achievement.getLevelForProgress(currentProgress);
if (level == null)
return false;
AchievementLevel nextLevel = achievement.levels.get(level.level + 1);
return nextLevel == null && currentProgress >= level.progress;
}
public static void createUserEntry(Habbo habbo, Achievement achievement) {
try (Connection connection = Emulator.getDatabase().getDataSource().getConnection(); PreparedStatement statement = connection.prepareStatement("INSERT INTO users_achievements (user_id, achievement_name, progress) VALUES (?, ?, ?)")) {
statement.setInt(1, habbo.getHabboInfo().getId());
statement.setString(2, achievement.name);
statement.setInt(3, 1);
statement.execute();
} catch (SQLException e) {
log.error("Caught SQL exception", e);
}
}
public static void saveAchievements(Habbo habbo) {
try (Connection connection = Emulator.getDatabase().getDataSource().getConnection(); PreparedStatement statement = connection.prepareStatement("UPDATE users_achievements SET progress = ? WHERE achievement_name = ? AND user_id = ? LIMIT 1")) {
statement.setInt(3, habbo.getHabboInfo().getId());
for (Map.Entry<Achievement, Integer> map : habbo.getHabboStats().getAchievementProgress().entrySet()) {
statement.setInt(1, map.getValue());
statement.setString(2, map.getKey().name);
statement.addBatch();
}
statement.executeBatch();
} catch (SQLException e) {
log.error("Caught SQL exception", e);
}
}
public static int getAchievementProgressForHabbo(int userId, Achievement achievement) {
try (Connection connection = Emulator.getDatabase().getDataSource().getConnection(); PreparedStatement statement = connection.prepareStatement("SELECT progress FROM users_achievements WHERE user_id = ? AND achievement_name = ? LIMIT 1")) {
statement.setInt(1, userId);
statement.setString(2, achievement.name);
try (ResultSet set = statement.executeQuery()) {
if (set.next()) {
return set.getInt("progress");
}
}
} catch (SQLException e) {
log.error("Caught SQL exception", e);
}
return 0;
}
public void reload() {
long millis = System.currentTimeMillis();
synchronized (this.achievements) {
for (Achievement achievement : this.achievements.values()) {
achievement.clearLevels();
}
try (Connection connection = Emulator.getDatabase().getDataSource().getConnection()) {
try (Statement statement = connection.createStatement(); ResultSet set = statement.executeQuery("SELECT * FROM achievements")) {
while (set.next()) {
if (!this.achievements.containsKey(set.getString("name"))) {
this.achievements.put(set.getString("name"), new Achievement(set));
} else {
this.achievements.get(set.getString("name")).addLevel(new AchievementLevel(set));
}
}
} catch (SQLException e) {
log.error("Caught SQL exception", e);
} catch (Exception e) {
log.error("Caught exception", e);
}
synchronized (this.talentTrackLevels) {
this.talentTrackLevels.clear();
try (Statement statement = connection.createStatement(); ResultSet set = statement.executeQuery("SELECT * FROM achievements_talents ORDER BY level ASC")) {
while (set.next()) {
TalentTrackLevel level = new TalentTrackLevel(set);
if (!this.talentTrackLevels.containsKey(level.type)) {
this.talentTrackLevels.put(level.type, new LinkedHashMap<>());
}
this.talentTrackLevels.get(level.type).put(level.level, level);
}
}
}
} catch (SQLException e) {
log.error("Caught SQL exception", e);
log.error("Achievement Manager -> Failed to load!");
return;
}
}
log.info("Achievement Manager -> Loaded! (" + (System.currentTimeMillis() - millis) + " MS)");
}
public Achievement getAchievement(String name) {
return this.achievements.get(name);
}
public Achievement getAchievement(int id) {
synchronized (this.achievements) {
for (Map.Entry<String, Achievement> set : this.achievements.entrySet()) {
if (set.getValue().id == id) {
return set.getValue();
}
}
}
return null;
}
public THashMap<String, Achievement> getAchievements() {
return this.achievements;
}
public LinkedHashMap<Integer, TalentTrackLevel> getTalenTrackLevels(TalentTrackType type) {
return this.talentTrackLevels.get(type);
}
public TalentTrackLevel calculateTalenTrackLevel(Habbo habbo, TalentTrackType type) {
TalentTrackLevel level = null;
for (Map.Entry<Integer, TalentTrackLevel> entry : this.talentTrackLevels.get(type).entrySet()) {
final boolean[] allCompleted = {true};
entry.getValue().achievements.forEachEntry(new TObjectIntProcedure<Achievement>() {
@Override
public boolean execute(Achievement a, int b) {
if (habbo.getHabboStats().getAchievementProgress(a) < b) {
allCompleted[0] = false;
}
return allCompleted[0];
}
});
if (allCompleted[0]) {
if (level == null || level.level < entry.getValue().level) {
level = entry.getValue();
}
} else {
break;
}
}
return level;
}
public void handleTalentTrackAchievement(Habbo habbo, TalentTrackType type, Achievement achievement) {
TalentTrackLevel currentLevel = this.calculateTalenTrackLevel(habbo, type);
if (currentLevel != null) {
if (currentLevel.level > habbo.getHabboStats().talentTrackLevel(type)) {
for (int i = habbo.getHabboStats().talentTrackLevel(type); i <= currentLevel.level; i++) {
TalentTrackLevel level = this.getTalentTrackLevel(type, i);
if (level != null) {
if (level.items != null && !level.items.isEmpty()) {
for (Item item : level.items) {
HabboItem rewardItem = Emulator.getGameEnvironment().getItemManager().createItem(habbo.getHabboInfo().getId(), item, 0, 0, "");
habbo.getInventory().getItemsComponent().addItem(rewardItem);
habbo.getClient().sendResponse(new AddHabboItemComposer(rewardItem));
habbo.getClient().sendResponse(new InventoryRefreshComposer());
}
}
if (level.badges != null && level.badges.length > 0) {
for (String badge : level.badges) {
if (!badge.isEmpty()) {
if (!habbo.getInventory().getBadgesComponent().hasBadge(badge)) {
HabboBadge b = new HabboBadge(0, badge, 0, habbo);
Emulator.getThreading().run(b);
habbo.getInventory().getBadgesComponent().addBadge(b);
habbo.getClient().sendResponse(new AddUserBadgeComposer(b));
}
}
}
}
if (level.perks != null && level.perks.length > 0) {
for (String perk : level.perks) {
if (perk.equalsIgnoreCase("TRADE")) {
habbo.getHabboStats().perkTrade = true;
}
}
}
habbo.getClient().sendResponse(new TalentLevelUpdateComposer(type, level));
}
}
}
habbo.getHabboStats().setTalentLevel(type, currentLevel.level);
}
}
public TalentTrackLevel getTalentTrackLevel(TalentTrackType type, int level) {
return this.talentTrackLevels.get(type).get(level);
}
}
@@ -0,0 +1,64 @@
package com.eu.habbo.habbohotel.achievements;
import com.eu.habbo.Emulator;
import com.eu.habbo.habbohotel.items.Item;
import gnu.trove.map.TObjectIntMap;
import gnu.trove.map.hash.TObjectIntHashMap;
import gnu.trove.set.hash.THashSet;
import lombok.extern.slf4j.Slf4j;
import java.sql.ResultSet;
import java.sql.SQLException;
@Slf4j
public class TalentTrackLevel {
public TalentTrackType type;
public int level;
public TObjectIntMap<Achievement> achievements;
public THashSet<Item> items;
public String[] perks;
public String[] badges;
public TalentTrackLevel(ResultSet set) throws SQLException {
this.type = TalentTrackType.valueOf(set.getString("type").toUpperCase());
this.level = set.getInt("level");
this.achievements = new TObjectIntHashMap<>();
this.items = new THashSet<>();
String[] achievements = set.getString("achievement_ids").split(",");
String[] achievementLevels = set.getString("achievement_levels").split(",");
if (achievementLevels.length == achievements.length) {
for (int i = 0; i < achievements.length; i++) {
if (achievements[i].isEmpty() || achievementLevels[i].isEmpty())
continue;
Achievement achievement = Emulator.getGameEnvironment().getAchievementManager().getAchievement(Integer.valueOf(achievements[i]));
if (achievement != null) {
this.achievements.put(achievement, Integer.valueOf(achievementLevels[i]));
} else {
log.error("Could not find achievement with ID " + achievements[i] + " for talenttrack level " + this.level + " of type " + this.type);
}
}
}
for (String s : set.getString("reward_furni").split(",")) {
Item item = Emulator.getGameEnvironment().getItemManager().getItem(Integer.valueOf(s));
if (item != null) {
this.items.add(item);
} else {
log.error("Incorrect reward furni (ID: " + s + ") for talent track level " + this.level);
}
}
if (!set.getString("reward_perks").isEmpty()) {
this.perks = set.getString("reward_perks").split(",");
}
if (!set.getString("reward_badges").isEmpty()) {
this.badges = set.getString("reward_badges").split(",");
}
}
}
@@ -0,0 +1,9 @@
package com.eu.habbo.habbohotel.achievements;
public enum TalentTrackType {
CITIZENSHIP,
HELPER
}
@@ -0,0 +1,485 @@
package com.eu.habbo.habbohotel.bots;
import com.eu.habbo.Emulator;
import com.eu.habbo.habbohotel.rooms.*;
import com.eu.habbo.habbohotel.users.Habbo;
import com.eu.habbo.habbohotel.users.HabboGender;
import com.eu.habbo.habbohotel.wired.WiredHandler;
import com.eu.habbo.habbohotel.wired.WiredTriggerType;
import com.eu.habbo.messages.outgoing.rooms.users.*;
import com.eu.habbo.plugin.events.bots.BotChatEvent;
import com.eu.habbo.plugin.events.bots.BotShoutEvent;
import com.eu.habbo.plugin.events.bots.BotTalkEvent;
import com.eu.habbo.plugin.events.bots.BotWhisperEvent;
import com.eu.habbo.threading.runnables.BotFollowHabbo;
import lombok.extern.slf4j.Slf4j;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Arrays;
@Slf4j
public class Bot implements Runnable {
public static final String NO_CHAT_SET = "${bot.skill.chatter.configuration.text.placeholder}";
public static String[] PLACEMENT_MESSAGES = "Yo!;Hello I'm a real party animal!;Hello!".split(";");
private final ArrayList<String> chatLines;
private transient int id;
private String name;
private String motto;
private String figure;
private HabboGender gender;
private int ownerId;
private String ownerName;
private Room room;
private RoomUnit roomUnit;
private boolean chatAuto;
private boolean chatRandom;
private short chatDelay;
private int chatTimeOut;
private int chatTimestamp;
private short lastChatIndex;
private int bubble;
private String type;
private int effect;
private transient boolean canWalk = true;
private boolean needsUpdate;
private transient int followingHabboId;
public Bot(int id, String name, String motto, String figure, HabboGender gender, int ownerId, String ownerName) {
this.id = id;
this.name = name;
this.motto = motto;
this.figure = figure;
this.gender = gender;
this.ownerId = ownerId;
this.ownerName = ownerName;
this.chatAuto = false;
this.chatRandom = false;
this.chatDelay = 1000;
this.chatLines = new ArrayList<>();
this.type = "generic_bot";
this.room = null;
this.bubble = RoomChatMessageBubbles.BOT_RENTABLE.getType();
}
public Bot(ResultSet set) throws SQLException {
this.id = set.getInt("id");
this.name = set.getString("name");
this.motto = set.getString("motto");
this.figure = set.getString("figure");
this.gender = HabboGender.valueOf(set.getString("gender"));
this.ownerId = set.getInt("user_id");
this.ownerName = set.getString("owner_name");
this.chatAuto = set.getString("chat_auto").equals("1");
this.chatRandom = set.getString("chat_random").equals("1");
this.chatDelay = set.getShort("chat_delay");
this.chatLines = new ArrayList<>(Arrays.asList(set.getString("chat_lines").split("\r")));
this.type = set.getString("type");
this.effect = set.getInt("effect");
this.canWalk = set.getString("freeroam").equals("1");
this.room = null;
this.roomUnit = null;
this.chatTimeOut = Emulator.getIntUnixTimestamp() + this.chatDelay;
this.needsUpdate = false;
this.bubble = set.getInt("bubble_id");
}
public Bot(Bot bot) {
this.name = bot.getName();
this.motto = bot.getMotto();
this.figure = bot.getFigure();
this.gender = bot.getGender();
this.ownerId = bot.getOwnerId();
this.ownerName = bot.getOwnerName();
this.chatAuto = true;
this.chatRandom = false;
this.chatDelay = 10;
this.chatTimeOut = Emulator.getIntUnixTimestamp() + this.chatDelay;
this.chatLines = new ArrayList<>(Arrays.asList("Default Message :D"));
this.type = bot.getType();
this.effect = bot.getEffect();
this.bubble = bot.getBubbleId();
this.needsUpdate = false;
}
public static void initialise() {
}
public static void dispose() {
}
public void needsUpdate(boolean needsUpdate) {
this.needsUpdate = needsUpdate;
}
public boolean needsUpdate() {
return this.needsUpdate;
}
@Override
public void run() {
if (this.needsUpdate) {
try (Connection connection = Emulator.getDatabase().getDataSource().getConnection(); PreparedStatement statement = connection.prepareStatement("UPDATE bots SET name = ?, motto = ?, figure = ?, gender = ?, user_id = ?, room_id = ?, x = ?, y = ?, z = ?, rot = ?, dance = ?, freeroam = ?, chat_lines = ?, chat_auto = ?, chat_random = ?, chat_delay = ?, effect = ?, bubble_id = ? WHERE id = ?")) {
statement.setString(1, this.name);
statement.setString(2, this.motto);
statement.setString(3, this.figure);
statement.setString(4, this.gender.toString());
statement.setInt(5, this.ownerId);
statement.setInt(6, this.room == null ? 0 : this.room.getId());
statement.setInt(7, this.roomUnit == null ? 0 : this.roomUnit.getX());
statement.setInt(8, this.roomUnit == null ? 0 : this.roomUnit.getY());
statement.setDouble(9, this.roomUnit == null ? 0 : this.roomUnit.getZ());
statement.setInt(10, this.roomUnit == null ? 0 : this.roomUnit.getBodyRotation().getValue());
statement.setInt(11, this.roomUnit == null ? 0 : this.roomUnit.getDanceType().getType());
statement.setString(12, this.canWalk ? "1" : "0");
StringBuilder text = new StringBuilder();
for (String s : this.chatLines) {
text.append(s).append("\r");
}
statement.setString(13, text.toString());
statement.setString(14, this.chatAuto ? "1" : "0");
statement.setString(15, this.chatRandom ? "1" : "0");
statement.setInt(16, this.chatDelay);
statement.setInt(17, this.effect);
statement.setInt(18, this.bubble);
statement.setInt(19, this.id);
statement.execute();
this.needsUpdate = false;
} catch (SQLException e) {
log.error("Caught SQL exception", e);
}
}
}
public void cycle(boolean allowBotsWalk) {
if (this.roomUnit != null) {
if (allowBotsWalk && this.canWalk) {
if (!this.roomUnit.isWalking()) {
if (this.roomUnit.getWalkTimeOut() < Emulator.getIntUnixTimestamp() && this.followingHabboId == 0) {
this.roomUnit.setGoalLocation(this.room.getRandomWalkableTile());
int timeOut = Emulator.getRandom().nextInt(20) * 2;
this.roomUnit.setWalkTimeOut((timeOut < 10 ? 5 : timeOut) + Emulator.getIntUnixTimestamp());
}
}/* else {
for (RoomTile t : this.room.getLayout().getTilesAround(this.room.getLayout().getTile(this.getRoomUnit().getX(), this.getRoomUnit().getY()))) {
WiredHandler.handle(WiredTriggerType.BOT_REACHED_STF, this.roomUnit, this.room, this.room.getItemsAt(t).toArray());
}
}*/
}
if (!this.chatLines.isEmpty() && this.chatTimeOut <= Emulator.getIntUnixTimestamp() && this.chatAuto) {
if (this.room != null) {
this.lastChatIndex = (this.chatRandom ? (short) Emulator.getRandom().nextInt(this.chatLines.size()) : (this.lastChatIndex == (this.chatLines.size() - 1) ? 0 : this.lastChatIndex++));
if (this.lastChatIndex >= this.chatLines.size()) {
this.lastChatIndex = 0;
}
String message = this.chatLines.get(this.lastChatIndex)
.replace(Emulator.getTexts().getValue("wired.variable.owner", "%owner%"), this.room.getOwnerName())
.replace(Emulator.getTexts().getValue("wired.variable.item_count", "%item_count%"), this.room.itemCount() + "")
.replace(Emulator.getTexts().getValue("wired.variable.name", "%name%"), this.name)
.replace(Emulator.getTexts().getValue("wired.variable.roomname", "%roomname%"), this.room.getName())
.replace(Emulator.getTexts().getValue("wired.variable.user_count", "%user_count%"), this.room.getUserCount() + ""); // TODO: Should getUserCount be replaced with getUsersWithoutInvisibleHabbos?
if(!WiredHandler.handle(WiredTriggerType.SAY_SOMETHING, this.getRoomUnit(), room, new Object[]{ message })) {
this.talk(message);
}
this.chatTimeOut = Emulator.getIntUnixTimestamp() + this.chatDelay;
}
}
}
}
public void talk(String message) {
if (this.room != null) {
BotChatEvent event = new BotTalkEvent(this, message);
if (Emulator.getPluginManager().fireEvent(event).isCancelled())
return;
this.chatTimestamp = Emulator.getIntUnixTimestamp();
this.room.botChat(new RoomUserTalkComposer(new RoomChatMessage(event.message, this.roomUnit, RoomChatMessageBubbles.getBubble(this.getBubbleId()))).compose());
if (message.equals("o/") || message.equals("_o/")) {
this.room.sendComposer(new RoomUserActionComposer(this.roomUnit, RoomUserAction.WAVE).compose());
}
}
}
public void shout(String message) {
if (this.room != null) {
BotChatEvent event = new BotShoutEvent(this, message);
if (Emulator.getPluginManager().fireEvent(event).isCancelled())
return;
this.chatTimestamp = Emulator.getIntUnixTimestamp();
this.room.botChat(new RoomUserShoutComposer(new RoomChatMessage(event.message, this.roomUnit, RoomChatMessageBubbles.getBubble(this.getBubbleId()))).compose());
if (message.equals("o/") || message.equals("_o/")) {
this.room.sendComposer(new RoomUserActionComposer(this.roomUnit, RoomUserAction.WAVE).compose());
}
}
}
public void whisper(String message, Habbo habbo) {
if (this.room != null && habbo != null) {
BotWhisperEvent event = new BotWhisperEvent(this, message, habbo);
if (Emulator.getPluginManager().fireEvent(event).isCancelled())
return;
this.chatTimestamp = Emulator.getIntUnixTimestamp();
event.target.getClient().sendResponse(new RoomUserWhisperComposer(new RoomChatMessage(event.message, this.roomUnit, RoomChatMessageBubbles.getBubble(this.getBubbleId()))));
}
}
public void onPlace(Habbo habbo, Room room) {
if (this.roomUnit != null) {
room.giveEffect(this.roomUnit, this.effect, -1);
}
if(PLACEMENT_MESSAGES.length > 0) {
String message = PLACEMENT_MESSAGES[Emulator.getRandom().nextInt(PLACEMENT_MESSAGES.length)];
if (!WiredHandler.handle(WiredTriggerType.SAY_SOMETHING, this.getRoomUnit(), room, new Object[]{message})) {
this.talk(message);
}
}
}
public void onPickUp(Habbo habbo, Room room) {
}
public void onUserSay(final RoomChatMessage message) {
}
public int getId() {
return this.id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return this.name;
}
public int getBubbleId() {
return bubble;
}
public void setName(String name) {
this.name = name;
this.needsUpdate = true;
//if(this.room != null)
//this.room.sendComposer(new ChangeNameUpdatedComposer(this.getRoomUnit(), this.getName()).compose());
}
public String getMotto() {
return this.motto;
}
public void setMotto(String motto) {
this.motto = motto;
this.needsUpdate = true;
}
public String getFigure() {
return this.figure;
}
public void setFigure(String figure) {
this.figure = figure;
this.needsUpdate = true;
if (this.room != null)
this.room.sendComposer(new RoomUsersComposer(this).compose());
}
public HabboGender getGender() {
return this.gender;
}
public void setGender(HabboGender gender) {
this.gender = gender;
this.needsUpdate = true;
if (this.room != null)
this.room.sendComposer(new RoomUsersComposer(this).compose());
}
public int getOwnerId() {
return this.ownerId;
}
public void setOwnerId(int ownerId) {
this.ownerId = ownerId;
this.needsUpdate = true;
if (this.room != null)
this.room.sendComposer(new RoomUsersComposer(this).compose());
}
public String getOwnerName() {
return this.ownerName;
}
public void setOwnerName(String ownerName) {
this.ownerName = ownerName;
this.needsUpdate = true;
if (this.room != null)
this.room.sendComposer(new RoomUsersComposer(this).compose());
}
public Room getRoom() {
return this.room;
}
public void setRoom(Room room) {
this.room = room;
}
public RoomUnit getRoomUnit() {
return this.roomUnit;
}
public void setRoomUnit(RoomUnit roomUnit) {
this.roomUnit = roomUnit;
}
public boolean isChatAuto() {
return this.chatAuto;
}
public void setChatAuto(boolean chatAuto) {
this.chatAuto = chatAuto;
this.needsUpdate = true;
}
public boolean isChatRandom() {
return this.chatRandom;
}
public void setChatRandom(boolean chatRandom) {
this.chatRandom = chatRandom;
this.needsUpdate = true;
}
public boolean hasChat() {
return !this.chatLines.isEmpty();
}
public int getChatDelay() {
return this.chatDelay;
}
public void setChatDelay(short chatDelay) {
this.chatDelay = (short) Math.min(Math.max(chatDelay, BotManager.MINIMUM_CHAT_SPEED), BotManager.MAXIMUM_CHAT_SPEED);
this.needsUpdate = true;
this.chatTimeOut = Emulator.getIntUnixTimestamp() + this.chatDelay;
}
public int getChatTimestamp() {
return this.chatTimestamp;
}
public void clearChat() {
synchronized (this.chatLines) {
this.chatLines.clear();
this.needsUpdate = true;
}
}
public String getType() {
return this.type;
}
public int getEffect() {
return this.effect;
}
public void setEffect(int effect, int duration) {
this.effect = effect;
this.needsUpdate = true;
if (this.roomUnit != null) {
if (this.room != null) {
this.room.giveEffect(this.roomUnit, this.effect, duration);
}
}
}
public void addChatLines(ArrayList<String> chatLines) {
synchronized (this.chatLines) {
this.chatLines.addAll(chatLines);
this.needsUpdate = true;
}
}
public void addChatLine(String chatLine) {
synchronized (this.chatLines) {
this.chatLines.add(chatLine);
this.needsUpdate = true;
}
}
public ArrayList<String> getChatLines() {
return this.chatLines;
}
public int getFollowingHabboId() {
return this.followingHabboId;
}
public void startFollowingHabbo(Habbo habbo) {
this.followingHabboId = habbo.getHabboInfo().getId();
Emulator.getThreading().run(new BotFollowHabbo(this, habbo, habbo.getHabboInfo().getCurrentRoom()));
}
public void stopFollowingHabbo() {
this.followingHabboId = 0;
}
public boolean canWalk() {
return this.canWalk;
}
public void setCanWalk(boolean canWalk) {
this.canWalk = canWalk;
}
public void lookAt(Habbo habbo) {
this.lookAt(habbo.getRoomUnit().getCurrentLocation());
}
public void lookAt(RoomUnit roomUnit) {
this.lookAt(roomUnit.getCurrentLocation());
}
public void lookAt(RoomTile tile) {
this.roomUnit.lookAtPoint(tile);
this.roomUnit.statusUpdate(true);
}
}
@@ -0,0 +1,242 @@
package com.eu.habbo.habbohotel.bots;
import com.eu.habbo.Emulator;
import com.eu.habbo.habbohotel.items.Item;
import com.eu.habbo.habbohotel.permissions.Permission;
import com.eu.habbo.habbohotel.rooms.*;
import com.eu.habbo.habbohotel.users.Habbo;
import com.eu.habbo.habbohotel.users.HabboInfo;
import com.eu.habbo.habbohotel.users.HabboItem;
import com.eu.habbo.messages.outgoing.generic.alerts.BotErrorComposer;
import com.eu.habbo.messages.outgoing.generic.alerts.BubbleAlertComposer;
import com.eu.habbo.messages.outgoing.generic.alerts.BubbleAlertKeys;
import com.eu.habbo.messages.outgoing.inventory.AddBotComposer;
import com.eu.habbo.messages.outgoing.inventory.RemoveBotComposer;
import com.eu.habbo.messages.outgoing.rooms.users.RoomUserStatusComposer;
import com.eu.habbo.messages.outgoing.rooms.users.RoomUsersComposer;
import com.eu.habbo.plugin.events.bots.BotPickUpEvent;
import com.eu.habbo.plugin.events.bots.BotPlacedEvent;
import gnu.trove.map.hash.THashMap;
import lombok.extern.slf4j.Slf4j;
import java.lang.reflect.Method;
import java.sql.*;
import java.util.Map;
@Slf4j
public class BotManager {
final private static THashMap<String, Class<? extends Bot>> botDefenitions = new THashMap<>();
public static int MINIMUM_CHAT_SPEED = 7;
public static int MAXIMUM_CHAT_SPEED = 604800;
public static int MAXIMUM_CHAT_LENGTH = 120;
public static int MAXIMUM_NAME_LENGTH = 15;
public static int MAXIMUM_BOT_INVENTORY_SIZE = 25;
public BotManager() throws Exception {
long millis = System.currentTimeMillis();
addBotDefinition("generic", Bot.class);
addBotDefinition("bartender", ButlerBot.class);
addBotDefinition("visitor_log", VisitorBot.class);
this.reload();
log.info("Bot Manager -> Loaded! (" + (System.currentTimeMillis() - millis) + " MS)");
}
public static void addBotDefinition(String type, Class<? extends Bot> botClazz) throws Exception {
botClazz.getDeclaredConstructor(ResultSet.class).setAccessible(true);
botDefenitions.put(type, botClazz);
}
public boolean reload() {
for (Map.Entry<String, Class<? extends Bot>> set : botDefenitions.entrySet()) {
try {
Method m = set.getValue().getMethod("initialise");
m.setAccessible(true);
m.invoke(null);
} catch (NoSuchMethodException e) {
log.info("Bot Manager -> Failed to execute initialise method upon bot type '" + set.getKey() + "'. No Such Method!");
return false;
} catch (Exception e) {
log.info("Bot Manager -> Failed to execute initialise method upon bot type '" + set.getKey() + "'. Error: " + e.getMessage());
return false;
}
}
return true;
}
public Bot createBot(THashMap<String, String> data, String type) {
Bot bot = null;
try (Connection connection = Emulator.getDatabase().getDataSource().getConnection(); PreparedStatement statement = connection.prepareStatement("INSERT INTO bots (user_id, room_id, name, motto, figure, gender, type) VALUES (0, 0, ?, ?, ?, ?, ?)", Statement.RETURN_GENERATED_KEYS)) {
statement.setString(1, data.get("name"));
statement.setString(2, data.get("motto"));
statement.setString(3, data.get("figure"));
statement.setString(4, data.get("gender").toUpperCase());
statement.setString(5, type);
statement.execute();
try (ResultSet set = statement.getGeneratedKeys()) {
if (set.next()) {
try (PreparedStatement stmt = connection.prepareStatement("SELECT users.username AS owner_name, bots.* FROM bots LEFT JOIN users ON bots.user_id = users.id WHERE bots.id = ? LIMIT 1")) {
stmt.setInt(1, set.getInt(1));
try (ResultSet resultSet = stmt.executeQuery()) {
if (resultSet.next()) {
bot = this.loadBot(resultSet);
}
}
} catch (SQLException e) {
log.error("Caught SQL exception", e);
}
}
}
} catch (SQLException e) {
log.error("Caught SQL exception", e);
}
return bot;
}
public void placeBot(Bot bot, Habbo habbo, Room room, RoomTile location) {
BotPlacedEvent event = new BotPlacedEvent(bot, location, habbo);
Emulator.getPluginManager().fireEvent(event);
if (event.isCancelled())
return;
if (room != null && bot != null && habbo != null) {
if (room.getOwnerId() == habbo.getHabboInfo().getId() || habbo.hasPermission(Permission.ACC_ANYROOMOWNER) || habbo.hasPermission(Permission.ACC_PLACEFURNI)) {
if (room.getCurrentBots().size() >= Room.MAXIMUM_BOTS && !habbo.hasPermission(Permission.ACC_UNLIMITED_BOTS)) {
habbo.getClient().sendResponse(new BotErrorComposer(BotErrorComposer.ROOM_ERROR_MAX_BOTS));
return;
}
if (room.hasHabbosAt(location.x, location.y) || (!location.isWalkable() && location.state != RoomTileState.SIT && location.state != RoomTileState.LAY))
return;
if (room.hasBotsAt(location.x, location.y)) {
habbo.getClient().sendResponse(new BotErrorComposer(BotErrorComposer.ROOM_ERROR_BOTS_SELECTED_TILE_NOT_FREE));
return;
}
RoomUnit roomUnit = new RoomUnit();
roomUnit.setRotation(RoomUserRotation.SOUTH);
roomUnit.setLocation(location);
double stackHeight = location.getStackHeight();
roomUnit.setPreviousLocationZ(stackHeight);
roomUnit.setZ(stackHeight);
roomUnit.setPathFinderRoom(room);
roomUnit.setRoomUnitType(RoomUnitType.BOT);
roomUnit.setCanWalk(room.isAllowBotsWalk());
bot.setRoomUnit(roomUnit);
bot.setRoom(room);
bot.needsUpdate(true);
room.addBot(bot);
Emulator.getThreading().run(bot);
room.sendComposer(new RoomUsersComposer(bot).compose());
room.sendComposer(new RoomUserStatusComposer(bot.getRoomUnit()).compose());
habbo.getInventory().getBotsComponent().removeBot(bot);
habbo.getClient().sendResponse(new RemoveBotComposer(bot));
bot.onPlace(habbo, room);
HabboItem topItem = room.getTopItemAt(location.x, location.y);
if (topItem != null) {
try {
topItem.onWalkOn(bot.getRoomUnit(), room, null);
} catch (Exception e) {
log.error("Caught exception", e);
}
}
bot.cycle(false);
} else {
habbo.getClient().sendResponse(new BubbleAlertComposer(BubbleAlertKeys.FURNITURE_PLACEMENT_ERROR.key, FurnitureMovementError.NO_RIGHTS.errorCode));
}
}
}
public void pickUpBot(int botId, Habbo habbo) {
if (habbo.getHabboInfo().getCurrentRoom() != null) {
this.pickUpBot(habbo.getHabboInfo().getCurrentRoom().getBot(Math.abs(botId)), habbo);
}
}
public void pickUpBot(Bot bot, Habbo habbo) {
HabboInfo receiverInfo = habbo == null ? Emulator.getGameEnvironment().getHabboManager().getHabboInfo(bot.getOwnerId()) : habbo.getHabboInfo();
if (bot != null) {
BotPickUpEvent pickedUpEvent = new BotPickUpEvent(bot, habbo);
Emulator.getPluginManager().fireEvent(pickedUpEvent);
if (pickedUpEvent.isCancelled())
return;
if (habbo == null || (bot.getOwnerId() == habbo.getHabboInfo().getId() || habbo.hasPermission(Permission.ACC_ANYROOMOWNER))) {
if (habbo != null && !habbo.hasPermission(Permission.ACC_UNLIMITED_BOTS) && habbo.getInventory().getBotsComponent().getBots().size() >= BotManager.MAXIMUM_BOT_INVENTORY_SIZE) {
habbo.alert(Emulator.getTexts().getValue("error.bots.max.inventory").replace("%amount%", BotManager.MAXIMUM_BOT_INVENTORY_SIZE + ""));
return;
}
bot.onPickUp(habbo, receiverInfo.getCurrentRoom());
receiverInfo.getCurrentRoom().removeBot(bot);
bot.stopFollowingHabbo();
bot.setOwnerId(receiverInfo.getId());
bot.setOwnerName(receiverInfo.getUsername());
bot.needsUpdate(true);
Emulator.getThreading().run(bot);
Habbo receiver = habbo == null ? Emulator.getGameEnvironment().getHabboManager().getHabbo(receiverInfo.getId()) : habbo;
if (receiver != null) {
receiver.getInventory().getBotsComponent().addBot(bot);
receiver.getClient().sendResponse(new AddBotComposer(bot));
}
}
}
}
public Bot loadBot(ResultSet set) {
try {
String type = set.getString("type");
Class<? extends Bot> botClazz = botDefenitions.get(type);
if (botClazz != null)
return botClazz.getDeclaredConstructor(ResultSet.class).newInstance(set);
else
log.error("Unknown Bot Type: " + type);
} catch (SQLException e) {
log.error("Caught SQL exception", e);
} catch (Exception e) {
log.error("Caught exception", e);
}
return null;
}
public boolean deleteBot(Bot bot) {
try (Connection connection = Emulator.getDatabase().getDataSource().getConnection(); PreparedStatement statement = connection.prepareStatement("DELETE FROM bots WHERE id = ? LIMIT 1")) {
statement.setInt(1, bot.getId());
return statement.execute();
} catch (SQLException e) {
log.error("Caught SQL exception", e);
}
return false;
}
public void dispose() {
for (Map.Entry<String, Class<? extends Bot>> set : botDefenitions.entrySet()) {
try {
Method m = set.getValue().getMethod("dispose");
m.setAccessible(true);
m.invoke(null);
} catch (NoSuchMethodException e) {
log.info("Bot Manager -> Failed to execute dispose method upon bot type '" + set.getKey() + "'. No Such Method!");
} catch (Exception e) {
log.info("Bot Manager -> Failed to execute dispose method upon bot type '" + set.getKey() + "'. Error: " + e.getMessage());
}
}
}
}
@@ -0,0 +1,142 @@
package com.eu.habbo.habbohotel.bots;
import com.eu.habbo.Emulator;
import com.eu.habbo.habbohotel.rooms.RoomChatMessage;
import com.eu.habbo.habbohotel.rooms.RoomUnitStatus;
import com.eu.habbo.habbohotel.wired.WiredHandler;
import com.eu.habbo.habbohotel.wired.WiredTriggerType;
import com.eu.habbo.plugin.events.bots.BotServerItemEvent;
import com.eu.habbo.threading.runnables.RoomUnitGiveHanditem;
import com.eu.habbo.threading.runnables.RoomUnitWalkToRoomUnit;
import gnu.trove.map.hash.THashMap;
import gnu.trove.set.hash.THashSet;
import lombok.extern.slf4j.Slf4j;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
@Slf4j
public class ButlerBot extends Bot {
public static THashMap<THashSet<String>, Integer> serveItems = new THashMap<>();
public ButlerBot(ResultSet set) throws SQLException {
super(set);
}
public ButlerBot(Bot bot) {
super(bot);
}
public static void initialise() {
if (serveItems == null)
serveItems = new THashMap<>();
serveItems.clear();
try (Connection connection = Emulator.getDatabase().getDataSource().getConnection(); Statement statement = connection.createStatement(); ResultSet set = statement.executeQuery("SELECT * FROM bot_serves")) {
while (set.next()) {
String[] keys = set.getString("keys").split(";");
THashSet<String> ks = new THashSet<>();
Collections.addAll(ks, keys);
serveItems.put(ks, set.getInt("item"));
}
} catch (SQLException e) {
log.error("Caught SQL exception", e);
}
}
public static void dispose() {
serveItems.clear();
}
@Override
public void onUserSay(final RoomChatMessage message) {
if (this.getRoomUnit().hasStatus(RoomUnitStatus.MOVE) || this.getRoom() == null) {
return;
}
double distanceBetweenBotAndHabbo = this.getRoomUnit().getCurrentLocation().distance(message.getHabbo().getRoomUnit().getCurrentLocation());
if (distanceBetweenBotAndHabbo <= Emulator.getConfig().getInt("hotel.bot.butler.commanddistance")) {
if (message.getUnfilteredMessage() != null) {
for (Map.Entry<THashSet<String>, Integer> set : serveItems.entrySet()) {
for (String keyword : set.getKey()) {
// Check if the string contains a certain keyword using a regex.
// If keyword = tea, teapot wouldn't trigger it.
if (message.getUnfilteredMessage().toLowerCase().matches("\\b" + keyword + "\\b")) {
// Enable plugins to cancel this event
BotServerItemEvent serveEvent = new BotServerItemEvent(this, message.getHabbo(), set.getValue());
if (Emulator.getPluginManager().fireEvent(serveEvent).isCancelled()) {
return;
}
// Start give handitem process
if (this.getRoomUnit().canWalk()) {
final String key = keyword;
final Bot bot = this;
// Step 1: Look at Habbo
bot.lookAt(serveEvent.habbo);
// Step 2: Prepare tasks for when the Bot (carrying the handitem) reaches the Habbo
final List<Runnable> tasks = new ArrayList<>();
tasks.add(new RoomUnitGiveHanditem(serveEvent.habbo.getRoomUnit(), serveEvent.habbo.getHabboInfo().getCurrentRoom(), serveEvent.itemId));
tasks.add(new RoomUnitGiveHanditem(this.getRoomUnit(), serveEvent.habbo.getHabboInfo().getCurrentRoom(), 0));
tasks.add(() -> {
if(this.getRoom() != null) {
String botMessage = Emulator.getTexts()
.getValue("bots.butler.given")
.replace("%key%", key)
.replace("%username%", serveEvent.habbo.getHabboInfo().getUsername());
if (!WiredHandler.handle(WiredTriggerType.SAY_SOMETHING, this.getRoomUnit(), this.getRoom(), new Object[]{ botMessage })) {
bot.talk(botMessage);
}
}
});
List<Runnable> failedReached = new ArrayList<>();
failedReached.add(() -> {
if (distanceBetweenBotAndHabbo <= Emulator.getConfig().getInt("hotel.bot.butler.servedistance", 8)) {
for (Runnable task : tasks) {
task.run();
}
}
});
// Give bot the handitem that it's going to give the Habbo
Emulator.getThreading().run(new RoomUnitGiveHanditem(this.getRoomUnit(), serveEvent.habbo.getHabboInfo().getCurrentRoom(), serveEvent.itemId));
if (distanceBetweenBotAndHabbo > Emulator.getConfig().getInt("hotel.bot.butler.reachdistance", 3)) {
Emulator.getThreading().run(new RoomUnitWalkToRoomUnit(this.getRoomUnit(), serveEvent.habbo.getRoomUnit(), serveEvent.habbo.getHabboInfo().getCurrentRoom(), tasks, failedReached, Emulator.getConfig().getInt("hotel.bot.butler.reachdistance", 3)));
} else {
Emulator.getThreading().run(failedReached.get(0), 1000);
}
} else {
if(this.getRoom() != null) {
this.getRoom().giveHandItem(serveEvent.habbo, serveEvent.itemId);
String msg = Emulator.getTexts().getValue("bots.butler.given").replace("%key%", keyword).replace("%username%", serveEvent.habbo.getHabboInfo().getUsername());
if (!WiredHandler.handle(WiredTriggerType.SAY_SOMETHING, this.getRoomUnit(), this.getRoom(), new Object[]{msg})) {
this.talk(msg);
}
}
}
return;
}
}
}
}
}
}
}
@@ -0,0 +1,70 @@
package com.eu.habbo.habbohotel.bots;
import com.eu.habbo.Emulator;
import com.eu.habbo.habbohotel.modtool.ModToolRoomVisit;
import com.eu.habbo.habbohotel.rooms.RoomChatMessage;
import com.eu.habbo.habbohotel.users.Habbo;
import gnu.trove.set.hash.THashSet;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class VisitorBot extends Bot {
private static SimpleDateFormat DATE_FORMAT;
private boolean showedLog = false;
private THashSet<ModToolRoomVisit> visits = new THashSet<>(3);
public VisitorBot(ResultSet set) throws SQLException {
super(set);
}
public VisitorBot(Bot bot) {
super(bot);
}
public static void initialise() {
DATE_FORMAT = new SimpleDateFormat(Emulator.getConfig().getValue("bots.visitor.dateformat"));
}
@Override
public void onUserSay(final RoomChatMessage message) {
if (!this.showedLog) {
if (message.getMessage().equalsIgnoreCase(Emulator.getTexts().getValue("generic.yes"))) {
this.showedLog = true;
String visitMessage = Emulator.getTexts().getValue("bots.visitor.list").replace("%count%", this.visits.size() + "");
StringBuilder list = new StringBuilder();
for (ModToolRoomVisit visit : this.visits) {
list.append("\r");
list.append(visit.roomName).append(" ");
list.append(Emulator.getTexts().getValue("generic.time.at")).append(" ");
list.append(DATE_FORMAT.format(new Date((visit.timestamp * 1000L))));
}
visitMessage = visitMessage.replace("%list%", list.toString());
this.talk(visitMessage);
this.visits.clear();
}
}
}
public void onUserEnter(Habbo habbo) {
if (!this.showedLog) {
if (habbo.getHabboInfo().getCurrentRoom() != null) {
this.visits = Emulator.getGameEnvironment().getModToolManager().getVisitsForRoom(habbo.getHabboInfo().getCurrentRoom(), 10, true, habbo.getHabboInfo().getLastOnline(), Emulator.getIntUnixTimestamp(), habbo.getHabboInfo().getCurrentRoom().getOwnerName());
if (this.visits.isEmpty()) {
this.talk(Emulator.getTexts().getValue("bots.visitor.no_visits"));
} else {
this.talk(Emulator.getTexts().getValue("bots.visitor.visits").replace("%count%", this.visits.size() + "").replace("%positive%", Emulator.getTexts().getValue("generic.yes")));
}
}
}
}
}
@@ -0,0 +1,64 @@
package com.eu.habbo.habbohotel.campaign.calendar;
import gnu.trove.map.hash.THashMap;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.util.Map;
public class CalendarCampaign {
private int id;
private final String name;
private final String image;
private Map<Integer , CalendarRewardObject> rewards = new THashMap<>();
private final Integer start_timestamp;
private final int total_days;
private final boolean lock_expired;
public CalendarCampaign(ResultSet set) throws SQLException {
this.id = set.getInt("id");
this.name = set.getString("name");
this.image = set.getString("image");
this.start_timestamp = set.getInt("start_timestamp");
this.total_days = set.getInt("total_days");
this.lock_expired = set.getInt("lock_expired") == 1;
}
public CalendarCampaign(int id, String name, String image, Integer start_timestamp, int total_days, boolean lock_expired) {
this.id = id;
this.name = name;
this.image = image;
this.start_timestamp = start_timestamp;
this.total_days = total_days;
this.lock_expired = lock_expired;
}
public int getId() {
return this.id;
}
public String getName() {
return this.name;
}
public String getImage() {
return this.image;
}
public Integer getStartTimestamp() {
return this.start_timestamp;
}
public int getTotalDays() { return this.total_days; }
public boolean getLockExpired() { return this.lock_expired; }
public Map<Integer, CalendarRewardObject> getRewards() { return rewards; }
public void setId(int id) { this.id = id; }
public void setRewards(Map<Integer, CalendarRewardObject> rewards) { this.rewards = rewards; }
public void addReward(CalendarRewardObject reward) { this.rewards.put(reward.getId(), reward); }
}
@@ -0,0 +1,151 @@
package com.eu.habbo.habbohotel.campaign.calendar;
import com.eu.habbo.Emulator;
import com.eu.habbo.habbohotel.users.Habbo;
import com.eu.habbo.messages.outgoing.events.calendar.AdventCalendarProductComposer;
import com.eu.habbo.plugin.events.users.calendar.UserClaimRewardEvent;
import gnu.trove.map.hash.THashMap;
import lombok.extern.slf4j.Slf4j;
import java.sql.*;
import java.util.*;
import java.util.Date;
import static java.time.temporal.ChronoUnit.DAYS;
@Slf4j
public class CalendarManager {
final private static Map<Integer, CalendarCampaign> calendarCampaigns = new THashMap<>();
public static double HC_MODIFIER;
public CalendarManager() {
long millis = System.currentTimeMillis();
this.reload();
log.info("Calendar Manager -> Loaded! ({} MS)", (System.currentTimeMillis() - millis));
}
public void dispose(){
calendarCampaigns.clear();
}
public boolean reload() {
this.dispose();
try (Connection connection = Emulator.getDatabase().getDataSource().getConnection(); PreparedStatement statement = connection.prepareStatement("SELECT * FROM calendar_campaigns WHERE enabled = 1")) {
try (ResultSet set = statement.executeQuery()) {
while (set.next()) {
calendarCampaigns.put(set.getInt("id"), new CalendarCampaign(set));
}
}
} catch (SQLException e) {
log.error("Caught SQL exception", e);
return false;
}
try (Connection connection = Emulator.getDatabase().getDataSource().getConnection(); PreparedStatement statement = connection.prepareStatement("SELECT * FROM calendar_rewards")) {
try (ResultSet set = statement.executeQuery()) {
while (set.next()) {
CalendarCampaign campaign = calendarCampaigns.get(set.getInt("campaign_id"));
if(campaign != null){
campaign.addReward(new CalendarRewardObject(set));
}
}
}
} catch (SQLException e) {
log.error("Caught SQL exception", e);
return false;
}
HC_MODIFIER = Emulator.getConfig().getDouble("hotel.calendar.pixels.hc_modifier", 2.0);
return true;
}
public void addCampaign(CalendarCampaign campaign) {
try (Connection connection = Emulator.getDatabase().getDataSource().getConnection(); PreparedStatement statement = connection.prepareStatement("INSERT INTO calendar_campaigns ( name, image, start_timestamp, total_days, lock_expired) VALUES (?, ?, ?, ? , ?)", Statement.RETURN_GENERATED_KEYS)) {
statement.setString(1, campaign.getName());
statement.setString(2, campaign.getImage());
statement.setInt(3, campaign.getStartTimestamp());
statement.setInt(4, campaign.getTotalDays());
statement.setBoolean(5, campaign.getLockExpired());
int affectedRows = statement.executeUpdate();
if (affectedRows == 0) {
throw new SQLException("Creating calendar campaign failed, no rows affected.");
}
try (ResultSet generatedKeys = statement.getGeneratedKeys()) {
if (generatedKeys.next()) {
campaign.setId(generatedKeys.getInt(1));
} else {
throw new SQLException("Creating calendar campaign failed, no ID found.");
}
}
} catch (SQLException e) {
log.error("Caught SQL exception", e);
}
calendarCampaigns.put(campaign.getId(), campaign);
}
public boolean deleteCampaign(CalendarCampaign campaign) {
calendarCampaigns.remove(campaign.getId());
try (Connection connection = Emulator.getDatabase().getDataSource().getConnection(); PreparedStatement statement = connection.prepareStatement("DELETE FROM calendar_campaigns WHERE id = ? LIMIT 1")) {
statement.setInt(1, campaign.getId());
return statement.execute();
} catch (SQLException e) {
log.error("Caught SQL exception", e);
}
return false;
}
public CalendarCampaign getCalendarCampaign(String campaignName) {
return calendarCampaigns.values().stream().filter(cc -> Objects.equals(cc.getName(), campaignName)).findFirst().orElse(null);
}
public Map<Integer, CalendarCampaign> getCalendarCampaigns() {
return calendarCampaigns;
}
public void claimCalendarReward(Habbo habbo, String campaignName, int day, boolean force) {
CalendarCampaign campaign = calendarCampaigns.values().stream().filter(cc -> Objects.equals(cc.getName(), campaignName)).findFirst().orElse(null);
if(campaign == null) return;
if (habbo.getHabboStats().calendarRewardsClaimed.stream().noneMatch(claimed -> claimed.getCampaignId() == campaign.getId() && claimed.getDay() == day)) {
Set<Integer> keys = campaign.getRewards().keySet();
Map<Integer, Integer> rewards = new THashMap<>();
if(keys.isEmpty()) return;
keys.forEach(key -> rewards.put(rewards.size() + 1, key));
int rand = Emulator.getRandom().nextInt(rewards.size() - 1 + 1) + 1;
int random = rewards.get(rand);
CalendarRewardObject object = campaign.getRewards().get(random);
if (object == null) return;
int daysBetween = (int) DAYS.between(new Timestamp(campaign.getStartTimestamp() * 1000L).toInstant(), new Date().toInstant());
if(daysBetween >= 0 && daysBetween <= campaign.getTotalDays()) {
int diff = (daysBetween - day);
if ((((diff <= 2 || !campaign.getLockExpired()) && diff >= 0) || (force && habbo.hasPermission("acc_calendar_force")))) {
if (Emulator.getPluginManager().fireEvent(new UserClaimRewardEvent(habbo, campaign, day, object, force)).isCancelled()) {
return;
}
habbo.getHabboStats().calendarRewardsClaimed.add(new CalendarRewardClaimed(habbo.getHabboInfo().getId(), campaign.getId(), day, object.getId(), new Timestamp(System.currentTimeMillis())));
habbo.getClient().sendResponse(new AdventCalendarProductComposer(true, object, habbo));
object.give(habbo);
try (Connection connection = Emulator.getDatabase().getDataSource().getConnection(); PreparedStatement statement = connection.prepareStatement("INSERT INTO calendar_rewards_claimed (user_id, campaign_id, day, reward_id, timestamp) VALUES (?, ?, ?, ?, ?)")) {
statement.setInt(1, habbo.getHabboInfo().getId());
statement.setInt(2, campaign.getId());
statement.setInt(3, day);
statement.setInt(4, object.getId());
statement.setInt(5, Emulator.getIntUnixTimestamp());
statement.execute();
} catch (SQLException e) {
log.error("Caught SQL exception", e);
}
}
}
}
}
}
@@ -0,0 +1,50 @@
package com.eu.habbo.habbohotel.campaign.calendar;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Timestamp;
public class CalendarRewardClaimed {
private final int user_id;
private final int campaign;
private final int day;
private final int reward_id;
private final Timestamp timestamp;
public CalendarRewardClaimed(ResultSet set) throws SQLException {
this.user_id = set.getInt("user_id");
this.campaign = set.getInt("campaign_id");
this.day = set.getInt("day");
this.reward_id = set.getInt("reward_id");
this.timestamp = new Timestamp(set.getInt("timestamp") * 1000L);
}
public CalendarRewardClaimed(int user_id, int campaign, int day, int reward_id, Timestamp timestamp) {
this.user_id = user_id;
this.campaign = campaign;
this.day = day;
this.reward_id = reward_id;
this.timestamp = timestamp;
}
public int getUserId() {
return this.user_id;
}
public int getCampaignId() {
return this.campaign;
}
public int getDay() {
return this.day;
}
public int getRewardId() {
return this.reward_id;
}
public Timestamp getTimestamp() {
return this.timestamp;
}
}
@@ -0,0 +1,132 @@
package com.eu.habbo.habbohotel.campaign.calendar;
import com.eu.habbo.Emulator;
import com.eu.habbo.habbohotel.items.Item;
import com.eu.habbo.habbohotel.rooms.RoomChatMessageBubbles;
import com.eu.habbo.habbohotel.users.Habbo;
import com.eu.habbo.habbohotel.users.HabboItem;
import com.eu.habbo.habbohotel.users.subscriptions.Subscription;
import com.eu.habbo.habbohotel.users.subscriptions.SubscriptionHabboClub;
import com.eu.habbo.messages.outgoing.inventory.AddHabboItemComposer;
import com.eu.habbo.messages.outgoing.inventory.InventoryRefreshComposer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.sql.ResultSet;
import java.sql.SQLException;
public class CalendarRewardObject {
private static final Logger LOGGER = LoggerFactory.getLogger(CalendarRewardObject.class);
private final int id;
private final String productName;
private final String customImage;
private final int credits;
private final int pixels;
private final int points;
private final int pointsType;
private final String badge;
private final int itemId;
private final String subscription_type;
private final int subscription_days;
public CalendarRewardObject(ResultSet set) throws SQLException {
this.id = set.getInt("id");
this.productName = set.getString("product_name");
this.customImage = set.getString("custom_image");
this.credits = set.getInt("credits");
this.pixels = set.getInt("pixels");
this.points = set.getInt("points");
this.pointsType = set.getInt("points_type");
this.badge = set.getString("badge");
this.itemId = set.getInt("item_id");
this.subscription_type = set.getString("subscription_type");
this.subscription_days = set.getInt("subscription_days");
}
public void give(Habbo habbo) {
if (this.credits > 0) {
habbo.giveCredits(this.credits);
}
if (this.pixels > 0) {
habbo.givePixels((int)(this.pixels * (habbo.getHabboStats().hasActiveClub() ? CalendarManager.HC_MODIFIER : 1.0)));
}
if (this.points > 0) {
habbo.givePoints(this.pointsType, this.points);
}
if (!this.badge.isEmpty()) {
habbo.addBadge(this.badge);
}
if(this.subscription_type != null && !this.subscription_type.isEmpty()) {
if ("HABBO_CLUB".equals(this.subscription_type)) {
habbo.getHabboStats().createSubscription(SubscriptionHabboClub.HABBO_CLUB, this.subscription_days * 86400);
} else {
habbo.getHabboStats().createSubscription(this.subscription_type, this.subscription_days * 86400);
}
}
if (this.itemId > 0) {
Item item = getItem();
if (item != null) {
HabboItem habboItem = Emulator.getGameEnvironment().getItemManager().createItem(
habbo.getHabboInfo().getId(),
item,
0,
0,
"");
habbo.getInventory().getItemsComponent().addItem(habboItem);
habbo.getClient().sendResponse(new AddHabboItemComposer(habboItem));
habbo.getClient().sendResponse(new InventoryRefreshComposer());
}
}
}
public int getId() {
return this.id;
}
public String getCustomImage() {
return this.customImage;
}
public int getCredits() {
return this.credits;
}
public int getPixels() {
return this.pixels;
}
public int getPoints() {
return this.points;
}
public int getPointsType() {
return this.pointsType;
}
public String getProductName() {
return productName;
}
public String getSubscriptionType() {
return subscription_type;
}
public int getSubscriptionDays() {
return subscription_days;
}
public String getBadge() {
return this.badge;
}
public Item getItem() {
return Emulator.getGameEnvironment().getItemManager().getItem(this.itemId);
}
}
@@ -0,0 +1,58 @@
package com.eu.habbo.habbohotel.catalog;
import com.eu.habbo.Emulator;
import com.eu.habbo.messages.ISerialize;
import com.eu.habbo.messages.ServerMessage;
public class CatalogFeaturedPage implements ISerialize {
private final int slotId;
private final String caption;
private final String image;
private final Type type;
private final int expireTimestamp;
private final String pageName;
private final int pageId;
private final String productName;
public CatalogFeaturedPage(int slotId, String caption, String image, Type type, int expireTimestamp, String pageName, int pageId, String productName) {
this.slotId = slotId;
this.caption = caption;
this.image = image;
this.type = type;
this.expireTimestamp = expireTimestamp;
this.pageName = pageName;
this.pageId = pageId;
this.productName = productName;
}
@Override
public void serialize(ServerMessage message) {
message.appendInt(this.slotId);
message.appendString(this.caption);
message.appendString(this.image);
message.appendInt(this.type.type);
switch (this.type) {
case PAGE_NAME:
message.appendString(this.pageName);
break;
case PAGE_ID:
message.appendInt(this.pageId);
break;
case PRODUCT_NAME:
message.appendString(this.productName);
break;
}
message.appendInt(Emulator.getIntUnixTimestamp() - this.expireTimestamp);
}
public enum Type {
PAGE_NAME(0),
PAGE_ID(1),
PRODUCT_NAME(2);
public final int type;
Type(int type) {
this.type = type;
}
}
}
@@ -0,0 +1,354 @@
package com.eu.habbo.habbohotel.catalog;
import com.eu.habbo.Emulator;
import com.eu.habbo.habbohotel.items.FurnitureType;
import com.eu.habbo.habbohotel.items.Item;
import com.eu.habbo.habbohotel.users.HabboBadge;
import com.eu.habbo.messages.ISerialize;
import com.eu.habbo.messages.ServerMessage;
import gnu.trove.set.hash.THashSet;
import lombok.extern.slf4j.Slf4j;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.HashMap;
@Slf4j
public class CatalogItem implements ISerialize, Runnable, Comparable<CatalogItem> {
int id;
int limitedStack;
private int pageId;
private String itemId;
private String name;
private int credits;
private int points;
private short pointsType;
private int amount;
private boolean allowGift = false;
private int limitedSells;
private String extradata;
private boolean clubOnly;
private boolean haveOffer;
private int offerId;
private boolean needsUpdate;
private int orderNumber;
private HashMap<Integer, Integer> bundle;
public CatalogItem(ResultSet set) throws SQLException {
this.load(set);
this.needsUpdate = false;
}
public static boolean haveOffer(CatalogItem item) {
if (!item.haveOffer)
return false;
if (item.getAmount() != 1)
return false;
if (item.isLimited())
return false;
if (item.bundle.size() > 1)
return false;
if (item.getName().toLowerCase().startsWith("cf_") || item.getName().toLowerCase().startsWith("cfc_"))
return false;
for (Item i : item.getBaseItems()) {
if (i.getName().toLowerCase().startsWith("cf_") || i.getName().toLowerCase().startsWith("cfc_") || i.getName().toLowerCase().startsWith("rentable_bot"))
return false;
}
return !item.getName().toLowerCase().startsWith("rentable_bot_");
}
public void update(ResultSet set) throws SQLException {
this.load(set);
}
private void load(ResultSet set) throws SQLException {
this.id = set.getInt("id");
this.pageId = set.getInt("page_id");
this.itemId = set.getString("item_Ids");
this.name = set.getString("catalog_name");
this.credits = set.getInt("cost_credits");
this.points = set.getInt("cost_points");
this.pointsType = set.getShort("points_type");
this.amount = set.getInt("amount");
this.limitedStack = set.getInt("limited_stack");
this.limitedSells = set.getInt("limited_sells");
this.extradata = set.getString("extradata");
this.clubOnly = set.getBoolean("club_only");
this.haveOffer = set.getBoolean("have_offer");
this.offerId = set.getInt("offer_id");
this.orderNumber = set.getInt("order_number");
this.bundle = new HashMap<>();
this.loadBundle();
}
public int getId() {
return this.id;
}
public int getPageId() {
return this.pageId;
}
public void setPageId(int pageId) {
this.pageId = pageId;
}
public String getItemId() {
return this.itemId;
}
public void setItemId(String itemId) {
this.itemId = itemId;
}
public String getName() {
return this.name;
}
public int getCredits() {
return this.credits;
}
public int getPoints() {
return this.points;
}
public int getPointsType() {
return this.pointsType;
}
public int getAmount() {
return this.amount;
}
public int getLimitedStack() {
return this.limitedStack;
}
public int getLimitedSells() {
CatalogLimitedConfiguration ltdConfig = Emulator.getGameEnvironment().getCatalogManager().getLimitedConfig(this);
if (ltdConfig != null) {
return this.limitedStack - ltdConfig.available();
}
return this.limitedStack;
}
public String getExtradata() {
return this.extradata;
}
public boolean isClubOnly() {
return this.clubOnly;
}
public boolean isHaveOffer() {
return this.haveOffer;
}
public int getOfferId() {
return this.offerId;
}
public boolean isLimited() {
return this.limitedStack > 0;
}
private int getOrderNumber() {
return this.orderNumber;
}
public void setNeedsUpdate(boolean needsUpdate) {
this.needsUpdate = needsUpdate;
}
public synchronized void sellRare() {
this.limitedSells++;
this.needsUpdate = true;
if (this.limitedSells == this.limitedStack) {
Emulator.getGameEnvironment().getCatalogManager().moveCatalogItem(this, Emulator.getConfig().getInt("catalog.ltd.page.soldout"));
}
Emulator.getThreading().run(this);
}
public THashSet<Item> getBaseItems() {
THashSet<Item> items = new THashSet<>();
if (!this.itemId.isEmpty()) {
String[] itemIds = this.itemId.split(";");
for (String itemId : itemIds) {
if (itemId.isEmpty())
continue;
if (itemId.contains(":")) {
itemId = itemId.split(":")[0];
}
int identifier;
try {
identifier = Integer.parseInt(itemId);
} catch (Exception e) {
log.info("Invalid value (" + itemId + ") for items_base column for catalog_item id (" + this.id + "). Value must be integer or of the format of integer:amount;integer:amount");
continue;
}
if (identifier > 0) {
Item item = Emulator.getGameEnvironment().getItemManager().getItem(identifier);
if (item != null)
items.add(item);
}
}
}
return items;
}
public int getItemAmount(int id) {
if (this.bundle.containsKey(id))
return this.bundle.get(id);
else
return this.amount;
}
public HashMap<Integer, Integer> getBundle() {
return this.bundle;
}
public void loadBundle() {
int intItemId;
if (this.itemId.contains(";")) {
try {
String[] itemIds = this.itemId.split(";");
for (String itemId : itemIds) {
if (itemId.contains(":")) {
String[] data = itemId.split(":");
if (data.length > 1 && Integer.parseInt(data[0]) > 0 && Integer.parseInt(data[1]) > 0) {
this.bundle.put(Integer.parseInt(data[0]), Integer.parseInt(data[1]));
}
} else {
if (!itemId.isEmpty()) {
intItemId = (Integer.parseInt(itemId));
this.bundle.put(intItemId, 1);
}
}
}
} catch (Exception e) {
log.debug("Failed to load " + this.itemId);
log.error("Caught exception", e);
}
} else {
try {
Item item = Emulator.getGameEnvironment().getItemManager().getItem(Integer.valueOf(this.itemId));
if (item != null) {
this.allowGift = item.allowGift();
}
} catch (Exception e) {
}
}
}
@Override
public void serialize(ServerMessage message) {
message.appendInt(this.getId());
message.appendString(this.getName());
message.appendBoolean(false);
message.appendInt(this.getCredits());
message.appendInt(this.getPoints());
message.appendInt(this.getPointsType());
message.appendBoolean(this.allowGift); //Can gift
THashSet<Item> items = this.getBaseItems();
message.appendInt(items.size());
for (Item item : items) {
message.appendString(item.getType().code.toLowerCase());
if (item.getType() == FurnitureType.BADGE) {
message.appendString(item.getName());
} else {
message.appendInt(item.getSpriteId());
if (this.getName().contains("wallpaper_single") || this.getName().contains("floor_single") || this.getName().contains("landscape_single")) {
message.appendString(this.getName().split("_")[2]);
} else if (item.getName().contains("bot") && item.getType() == FurnitureType.ROBOT) {
boolean lookFound = false;
for (String s : this.getExtradata().split(";")) {
if (s.startsWith("figure:")) {
lookFound = true;
message.appendString(s.replace("figure:", ""));
break;
}
}
if (!lookFound) {
message.appendString(this.getExtradata());
}
} else if (item.getType() == FurnitureType.ROBOT) {
message.appendString(this.getExtradata());
} else if (item.getName().equalsIgnoreCase("poster")) {
message.appendString(this.getExtradata());
} else if (this.getName().startsWith("SONG ")) {
message.appendString(this.getExtradata());
} else {
message.appendString("");
}
message.appendInt(this.getItemAmount(item.getId()));
message.appendBoolean(this.isLimited());
if (this.isLimited()) {
message.appendInt(this.getLimitedStack());
message.appendInt(this.getLimitedStack() - this.getLimitedSells());
}
}
}
message.appendInt(this.clubOnly);
message.appendBoolean(haveOffer(this));
message.appendBoolean(false); //unknown
message.appendString(this.name + ".png");
}
@Override
public void run() {
if (this.needsUpdate) {
try (Connection connection = Emulator.getDatabase().getDataSource().getConnection(); PreparedStatement statement = connection.prepareStatement("UPDATE catalog_items SET limited_sells = ?, page_id = ? WHERE id = ?")) {
statement.setInt(1, this.getLimitedSells());
statement.setInt(2, this.pageId);
statement.setInt(3, this.getId());
statement.execute();
} catch (SQLException e) {
log.error("Caught SQL exception", e);
}
this.needsUpdate = false;
}
}
@SuppressWarnings("NullableProblems")
@Override
public int compareTo(CatalogItem catalogItem) {
if (CatalogManager.SORT_USING_ORDERNUM) {
return this.getOrderNumber() - catalogItem.getOrderNumber();
} else {
return this.getId() - catalogItem.getId();
}
}
}
@@ -0,0 +1,106 @@
package com.eu.habbo.habbohotel.catalog;
import com.eu.habbo.Emulator;
import com.eu.habbo.habbohotel.users.Habbo;
import com.eu.habbo.habbohotel.users.HabboItem;
import lombok.extern.slf4j.Slf4j;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.Collections;
import java.util.LinkedList;
@Slf4j
public class CatalogLimitedConfiguration implements Runnable {
private final int itemId;
private final LinkedList<Integer> limitedNumbers;
private int totalSet;
public CatalogLimitedConfiguration(int itemId, LinkedList<Integer> availableNumbers, int totalSet) {
this.itemId = itemId;
this.totalSet = totalSet;
this.limitedNumbers = availableNumbers;
if (Emulator.getConfig().getBoolean("catalog.ltd.random", true)) {
Collections.shuffle(this.limitedNumbers);
} else {
Collections.reverse(this.limitedNumbers);
}
}
public int getNumber() {
synchronized (this.limitedNumbers) {
int num = this.limitedNumbers.pop();
if (this.limitedNumbers.isEmpty()) {
Emulator.getGameEnvironment().getCatalogManager().moveCatalogItem(Emulator.getGameEnvironment().getCatalogManager().getCatalogItem(this.itemId), Emulator.getConfig().getInt("catalog.ltd.page.soldout"));
}
return num;
}
}
public void limitedSold(int catalogItemId, Habbo habbo, HabboItem item) {
synchronized (this.limitedNumbers) {
try (Connection connection = Emulator.getDatabase().getDataSource().getConnection(); PreparedStatement statement = connection.prepareStatement("UPDATE catalog_items_limited SET user_id = ?, timestamp = ?, item_id = ? WHERE catalog_item_id = ? AND number = ? AND user_id = 0 LIMIT 1")) {
statement.setInt(1, habbo.getHabboInfo().getId());
statement.setInt(2, Emulator.getIntUnixTimestamp());
statement.setInt(3, item.getId());
statement.setInt(4, catalogItemId);
statement.setInt(5, item.getLimitedSells());
statement.execute();
} catch (SQLException e) {
log.error("Caught SQL exception", e);
}
}
}
public void generateNumbers(int starting, int amount) {
synchronized (this.limitedNumbers) {
try (Connection connection = Emulator.getDatabase().getDataSource().getConnection(); PreparedStatement statement = connection.prepareStatement("INSERT INTO catalog_items_limited (catalog_item_id, number) VALUES (?, ?)")) {
statement.setInt(1, this.itemId);
for (int i = starting; i <= amount; i++) {
statement.setInt(2, i);
statement.addBatch();
this.limitedNumbers.push(i);
}
statement.executeBatch();
} catch (SQLException e) {
log.error("Caught SQL exception", e);
}
this.totalSet += amount;
if (Emulator.getConfig().getBoolean("catalog.ltd.random", true)) {
Collections.shuffle(this.limitedNumbers);
} else {
Collections.reverse(this.limitedNumbers);
}
}
}
public int available() {
return this.limitedNumbers.size();
}
public int getTotalSet() {
return this.totalSet;
}
public void setTotalSet(int totalSet) {
this.totalSet = totalSet;
}
@Override
public void run() {
try (Connection connection = Emulator.getDatabase().getDataSource().getConnection(); PreparedStatement statement = connection.prepareStatement("UPDATE catalog_items SET limited_stack = ?, limited_sells = ? WHERE id = ?")) {
statement.setInt(1, this.totalSet);
statement.setInt(2, this.totalSet - this.available());
statement.setInt(3, this.itemId);
statement.execute();
} catch (SQLException e) {
log.error("Caught SQL exception", e);
}
}
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,206 @@
package com.eu.habbo.habbohotel.catalog;
import com.eu.habbo.messages.ISerialize;
import com.eu.habbo.messages.ServerMessage;
import gnu.trove.TCollections;
import gnu.trove.list.array.TIntArrayList;
import gnu.trove.map.TIntObjectMap;
import gnu.trove.map.hash.THashMap;
import gnu.trove.map.hash.TIntObjectHashMap;
import lombok.extern.slf4j.Slf4j;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
@Slf4j
public abstract class CatalogPage implements Comparable<CatalogPage>, ISerialize {
protected final TIntArrayList offerIds = new TIntArrayList();
protected final THashMap<Integer, CatalogPage> childPages = new THashMap<>();
private final TIntObjectMap<CatalogItem> catalogItems = TCollections.synchronizedMap(new TIntObjectHashMap<>());
private final ArrayList<Integer> included = new ArrayList<>();
protected int id;
protected int parentId;
protected int rank;
protected String caption;
protected String pageName;
protected int iconColor;
protected int iconImage;
protected int orderNum;
protected boolean visible;
protected boolean enabled;
protected boolean clubOnly;
protected String layout;
protected String headerImage;
protected String teaserImage;
protected String specialImage;
protected String textOne;
protected String textTwo;
protected String textDetails;
protected String textTeaser;
public CatalogPage() {
}
public CatalogPage(ResultSet set) throws SQLException {
if (set == null)
return;
this.id = set.getInt("id");
this.parentId = set.getInt("parent_id");
this.rank = set.getInt("min_rank");
this.caption = set.getString("caption");
this.pageName = set.getString("caption_save");
this.iconColor = set.getInt("icon_color");
this.iconImage = set.getInt("icon_image");
this.orderNum = set.getInt("order_num");
this.visible = set.getBoolean("visible");
this.enabled = set.getBoolean("enabled");
this.clubOnly = set.getBoolean("club_only");
this.layout = set.getString("page_layout");
this.headerImage = set.getString("page_headline");
this.teaserImage = set.getString("page_teaser");
this.specialImage = set.getString("page_special");
this.textOne = set.getString("page_text1");
this.textTwo = set.getString("page_text2");
this.textDetails = set.getString("page_text_details");
this.textTeaser = set.getString("page_text_teaser");
if (!set.getString("includes").isEmpty()) {
for (String id : set.getString("includes").split(";")) {
try {
this.included.add(Integer.valueOf(id));
} catch (Exception e) {
log.error("Caught exception", e);
log.error("Failed to parse includes column value of (" + id + ") for catalog page (" + this.id + ")");
}
}
}
}
public int getId() {
return this.id;
}
public int getParentId() {
return this.parentId;
}
public int getRank() {
return this.rank;
}
public void setRank(int rank) {
this.rank = rank;
}
public String getCaption() {
return this.caption;
}
public String getPageName() {
return this.pageName;
}
public int getIconColor() {
return this.iconColor;
}
public int getIconImage() {
return this.iconImage;
}
public int getOrderNum() {
return this.orderNum;
}
public boolean isVisible() {
return this.visible;
}
public boolean isEnabled() {
return this.enabled;
}
public boolean isClubOnly() {
return this.clubOnly;
}
public String getLayout() {
return this.layout;
}
public String getHeaderImage() {
return this.headerImage;
}
public String getTeaserImage() {
return this.teaserImage;
}
public String getSpecialImage() {
return this.specialImage;
}
public String getTextOne() {
return this.textOne;
}
public String getTextTwo() {
return this.textTwo;
}
public String getTextDetails() {
return this.textDetails;
}
public String getTextTeaser() {
return this.textTeaser;
}
public TIntArrayList getOfferIds() {
return this.offerIds;
}
public void addOfferId(int offerId) {
this.offerIds.add(offerId);
}
public void addItem(CatalogItem item) {
this.catalogItems.put(item.getId(), item);
}
public TIntObjectMap<CatalogItem> getCatalogItems() {
return this.catalogItems;
}
public CatalogItem getCatalogItem(int id) {
return this.catalogItems.get(id);
}
public ArrayList<Integer> getIncluded() {
return this.included;
}
public THashMap<Integer, CatalogPage> getChildPages() {
return this.childPages;
}
public void addChildPage(CatalogPage page) {
this.childPages.put(page.getId(), page);
if (page.getRank() < this.getRank()) {
page.setRank(this.getRank());
}
}
@SuppressWarnings("NullableProblems")
@Override
public int compareTo(CatalogPage page) {
return this.getOrderNum() - page.getOrderNum();
}
@Override
public abstract void serialize(ServerMessage message);
}
@@ -0,0 +1,47 @@
package com.eu.habbo.habbohotel.catalog;
public enum CatalogPageLayouts {
default_3x3,
guild_furni,
guilds,
guild_forum,
info_duckets,
info_rentables,
info_loyalty,
loyalty_vip_buy,
bots,
pets,
pets2,
pets3,
club_gift,
frontpage,
badge_display,
spaces_new,
soundmachine,
info_pets,
club_buy,
roomads,
trophies,
single_bundle,
marketplace,
marketplace_own_items,
recycler,
recycler_info,
recycler_prizes,
sold_ltd_items,
plasto,
default_3x3_color_grouping,
recent_purchases,
room_bundle,
petcustomization,
root,
vip_buy,
frontpage_featured,
builders_club_addons,
builders_club_frontpage,
builders_club_loyalty,
monkey,
niko,
mad_money
}
@@ -0,0 +1,9 @@
package com.eu.habbo.habbohotel.catalog;
public enum CatalogPageType {
NORMAL,
BUILDER
}
@@ -0,0 +1,61 @@
package com.eu.habbo.habbohotel.catalog;
import com.eu.habbo.Emulator;
import com.eu.habbo.core.DatabaseLoggable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.sql.PreparedStatement;
import java.sql.SQLException;
public class CatalogPurchaseLogEntry implements Runnable, DatabaseLoggable {
private static final Logger LOGGER = LoggerFactory.getLogger(CatalogPurchaseLogEntry.class);
private static final String QUERY = "INSERT INTO `logs_shop_purchases` (timestamp, user_id, catalog_item_id, item_ids, catalog_name, cost_credits, cost_points, points_type, amount) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)";
private final int timestamp;
private final int userId;
private final int catalogItemId;
private final String itemIds;
private final String catalogName;
private final int costCredits;
private final int costPoints;
private final int pointsType;
private final int amount;
public CatalogPurchaseLogEntry(int timestamp, int userId, int catalogItemId, String itemIds, String catalogName, int costCredits, int costPoints, int pointsType, int amount) {
this.timestamp = timestamp;
this.userId = userId;
this.catalogItemId = catalogItemId;
this.itemIds = itemIds;
this.catalogName = catalogName;
this.costCredits = costCredits;
this.costPoints = costPoints;
this.pointsType = pointsType;
this.amount = amount;
}
@Override
public String getQuery() {
return QUERY;
}
@Override
public void log(PreparedStatement statement) throws SQLException {
statement.setInt(1, this.timestamp);
statement.setInt(2, this.userId);
statement.setInt(3, this.catalogItemId);
statement.setString(4, this.itemIds);
statement.setString(5, this.catalogName);
statement.setInt(6, this.costCredits);
statement.setInt(7, this.costPoints);
statement.setInt(8, this.pointsType);
statement.setInt(9, this.amount);
statement.addBatch();
}
@Override
public void run() {
Emulator.getDatabaseLogger().store(this);
}
}
@@ -0,0 +1,26 @@
package com.eu.habbo.habbohotel.catalog;
import java.sql.ResultSet;
import java.sql.SQLException;
public class ClothItem {
public int id;
public String name;
public int[] setId;
public ClothItem(ResultSet set) throws SQLException {
this.id = set.getInt("id");
this.name = set.getString("name");
String[] parts = set.getString("setid").split(",");
this.setId = new int[parts.length];
for (int i = 0; i < this.setId.length; i++) {
this.setId[i] = Integer.valueOf(parts[i]);
}
}
}
@@ -0,0 +1,122 @@
package com.eu.habbo.habbohotel.catalog;
import com.eu.habbo.Emulator;
import com.eu.habbo.messages.ISerialize;
import com.eu.habbo.messages.ServerMessage;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Calendar;
import java.util.TimeZone;
public class ClubOffer implements ISerialize {
private final int id;
private final String name;
private final int days;
private final int credits;
private final int points;
private final int pointsType;
private final boolean vip;
private final boolean deal;
public ClubOffer(ResultSet set) throws SQLException {
this.id = set.getInt("id");
this.name = set.getString("name");
this.days = set.getInt("days");
this.credits = set.getInt("credits");
this.points = set.getInt("points");
this.pointsType = set.getInt("points_type");
this.vip = set.getString("type").equalsIgnoreCase("vip");
this.deal = set.getString("deal").equals("1");
}
public int getId() {
return this.id;
}
public String getName() {
return this.name;
}
public int getDays() {
return this.days;
}
public int getCredits() {
return this.credits;
}
public int getPoints() {
return this.points;
}
public int getPointsType() {
return this.pointsType;
}
public boolean isVip() {
return this.vip;
}
public boolean isDeal() {
return this.deal;
}
@Override
public void serialize(ServerMessage message) {
serialize(message, Emulator.getIntUnixTimestamp());
}
public void serialize(ServerMessage message, int hcExpireTimestamp) {
hcExpireTimestamp = Math.max(Emulator.getIntUnixTimestamp(), hcExpireTimestamp);
message.appendInt(this.id);
message.appendString(this.name);
message.appendBoolean(false); //unused
message.appendInt(this.credits);
message.appendInt(this.points);
message.appendInt(this.pointsType);
message.appendBoolean(this.vip);
long seconds = this.days * 86400;
long secondsTotal = seconds;
int totalYears = (int) Math.floor((int) seconds / (86400.0 * 31 * 12));
seconds -= totalYears * (86400 * 31 * 12);
int totalMonths = (int) Math.floor((int) seconds / (86400.0 * 31));
seconds -= totalMonths * (86400 * 31);
int totalDays = (int) Math.floor((int) seconds / 86400.0);
seconds -= totalDays * 86400;
message.appendInt((int) secondsTotal / 86400 / 31);
message.appendInt((int) seconds);
message.appendBoolean(false); //giftable
message.appendInt((int) seconds);
hcExpireTimestamp += secondsTotal;
Calendar cal = Calendar.getInstance();
cal.setTimeZone(TimeZone.getTimeZone("UTC"));
cal.setTimeInMillis(hcExpireTimestamp * 1000L);
message.appendInt(cal.get(Calendar.YEAR));
message.appendInt(cal.get(Calendar.MONTH) + 1);
message.appendInt(cal.get(Calendar.DAY_OF_MONTH));
}
}
@@ -0,0 +1,116 @@
package com.eu.habbo.habbohotel.catalog;
import com.eu.habbo.Emulator;
import com.eu.habbo.habbohotel.users.cache.HabboOfferPurchase;
import com.eu.habbo.messages.ServerMessage;
import java.sql.ResultSet;
import java.sql.SQLException;
public class TargetOffer {
public static int ACTIVE_TARGET_OFFER_ID = 0;
private final int id;
private final int catalogItem;
private final String identifier;
private final int priceInCredits;
private final int priceInActivityPoints;
private final int activityPointsType;
private final int purchaseLimit;
private final int expirationTime;
private final String title;
private final String description;
private final String imageUrl;
private final String icon;
private final String[] vars;
public TargetOffer(ResultSet set) throws SQLException {
this.id = set.getInt("id");
this.identifier = set.getString("offer_code");
this.priceInCredits = set.getInt("credits");
this.priceInActivityPoints = set.getInt("points");
this.activityPointsType = set.getInt("points_type");
this.title = set.getString("title");
this.description = set.getString("description");
this.imageUrl = set.getString("image");
this.icon = set.getString("icon");
this.purchaseLimit = set.getInt("purchase_limit");
this.expirationTime = set.getInt("end_timestamp");
this.vars = set.getString("vars").split(";");
this.catalogItem = set.getInt("catalog_item");
}
public void serialize(ServerMessage message, HabboOfferPurchase purchase) {
message.appendInt(purchase.getState());
message.appendInt(this.id);
message.appendString(this.identifier);
message.appendString(this.identifier);
message.appendInt(this.priceInCredits);
message.appendInt(this.priceInActivityPoints);
message.appendInt(this.activityPointsType);
message.appendInt(Math.max(this.purchaseLimit - purchase.getAmount(), 0));
message.appendInt(Math.max(this.expirationTime - Emulator.getIntUnixTimestamp(), 0));
message.appendString(this.title);
message.appendString(this.description);
message.appendString(this.imageUrl);
message.appendString(this.icon);
message.appendInt(0);
message.appendInt(this.vars.length);
for (String variable : this.vars) {
message.appendString(variable);
}
}
public int getId() {
return this.id;
}
public String getIdentifier() {
return this.identifier;
}
public int getPriceInCredits() {
return this.priceInCredits;
}
public int getPriceInActivityPoints() {
return this.priceInActivityPoints;
}
public int getActivityPointsType() {
return this.activityPointsType;
}
public int getPurchaseLimit() {
return this.purchaseLimit;
}
public int getExpirationTime() {
return this.expirationTime;
}
public String getTitle() {
return this.title;
}
public String getDescription() {
return this.description;
}
public String getImageUrl() {
return this.imageUrl;
}
public String getIcon() {
return this.icon;
}
public String[] getVars() {
return this.vars;
}
public int getCatalogItem() {
return this.catalogItem;
}
}
@@ -0,0 +1,75 @@
package com.eu.habbo.habbohotel.catalog;
import com.eu.habbo.Emulator;
import lombok.extern.slf4j.Slf4j;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
@Slf4j
public class Voucher {
public final int id;
public final String code;
public final int credits;
public final int points;
public final int pointsType;
public final int catalogItemId;
public final int amount;
public final int limit;
private final List<VoucherHistoryEntry> history = new ArrayList<>();
public Voucher(ResultSet set) throws SQLException {
this.id = set.getInt("id");
this.code = set.getString("code");
this.credits = set.getInt("credits");
this.points = set.getInt("points");
this.pointsType = set.getInt("points_type");
this.catalogItemId = set.getInt("catalog_item_id");
this.amount = set.getInt("amount");
this.limit = set.getInt("limit");
this.loadHistory();
}
private void loadHistory() {
try (Connection connection = Emulator.getDatabase().getDataSource().getConnection(); PreparedStatement statement = connection.prepareStatement("SELECT * FROM voucher_history WHERE voucher_id = ?")) {
statement.setInt(1, this.id);
try (ResultSet set = statement.executeQuery()) {
while (set.next()) {
this.history.add(new VoucherHistoryEntry(set));
}
}
} catch (SQLException e) {
log.error("Caught SQL exception", e);
}
}
public boolean hasUserExhausted(int userId) {
return this.limit > 0 && Math.toIntExact(this.history.stream().filter(h -> h.getUserId() == userId).count()) >= this.limit;
}
public boolean isExhausted() {
return this.amount > 0 && this.history.size() >= this.amount;
}
public void addHistoryEntry(int userId) {
int timestamp = Emulator.getIntUnixTimestamp();
this.history.add(new VoucherHistoryEntry(this.id, userId, timestamp));
try (Connection connection = Emulator.getDatabase().getDataSource().getConnection(); PreparedStatement statement = connection.prepareStatement("INSERT INTO voucher_history (`voucher_id`, `user_id`, `timestamp`) VALUES (?, ?, ?)")) {
statement.setInt(1, this.id);
statement.setInt(2, userId);
statement.setInt(3, timestamp);
statement.execute();
} catch (SQLException e) {
log.error("Caught SQL exception", e);
}
}
}
@@ -0,0 +1,34 @@
package com.eu.habbo.habbohotel.catalog;
import java.sql.ResultSet;
import java.sql.SQLException;
public class VoucherHistoryEntry {
private final int voucherId;
private final int userId;
private final int timestamp;
public VoucherHistoryEntry(ResultSet set) throws SQLException {
this.voucherId = set.getInt("voucher_id");
this.userId = set.getInt("user_id");
this.timestamp = set.getInt("timestamp");
}
public VoucherHistoryEntry(int voucherId, int userId, int timestamp) {
this.voucherId = voucherId;
this.userId = userId;
this.timestamp = timestamp;
}
public int getVoucherId() {
return voucherId;
}
public int getUserId() {
return userId;
}
public int getTimestamp() {
return timestamp;
}
}
@@ -0,0 +1,27 @@
package com.eu.habbo.habbohotel.catalog.layouts;
import com.eu.habbo.habbohotel.catalog.CatalogPage;
import com.eu.habbo.messages.ServerMessage;
import java.sql.ResultSet;
import java.sql.SQLException;
public class BadgeDisplayLayout extends CatalogPage {
public BadgeDisplayLayout(ResultSet set) throws SQLException {
super(set);
}
@Override
public void serialize(ServerMessage message) {
message.appendString("badge_display");
message.appendInt(3);
message.appendString(super.getHeaderImage());
message.appendString(super.getTeaserImage());
message.appendString(super.getSpecialImage());
message.appendInt(3);
message.appendString(super.getTextOne());
message.appendString(super.getTextDetails());
message.appendString(super.getTextTeaser());
}
}
@@ -0,0 +1,26 @@
package com.eu.habbo.habbohotel.catalog.layouts;
import com.eu.habbo.habbohotel.catalog.CatalogPage;
import com.eu.habbo.messages.ServerMessage;
import java.sql.ResultSet;
import java.sql.SQLException;
public class BotsLayout extends CatalogPage {
public BotsLayout(ResultSet set) throws SQLException {
super(set);
}
@Override
public void serialize(ServerMessage message) {
message.appendString("bots");
message.appendInt(2);
message.appendString(super.getHeaderImage());
message.appendString(super.getTeaserImage());
message.appendInt(3);
message.appendString(super.getTextOne());
message.appendString(super.getTextDetails());
message.appendString(super.getTextTwo());
}
}
@@ -0,0 +1,27 @@
package com.eu.habbo.habbohotel.catalog.layouts;
import com.eu.habbo.habbohotel.catalog.CatalogPage;
import com.eu.habbo.messages.ServerMessage;
import java.sql.ResultSet;
import java.sql.SQLException;
public class BuildersClubAddonsLayout extends CatalogPage {
public BuildersClubAddonsLayout(ResultSet set) throws SQLException {
super(set);
}
@Override
public void serialize(ServerMessage message) {
message.appendString("builders_club_addons");
message.appendInt(3);
message.appendString(super.getHeaderImage());
message.appendString(super.getTeaserImage());
message.appendString(super.getSpecialImage());
message.appendInt(3);
message.appendString(super.getTextOne());
message.appendString(super.getTextDetails());
message.appendString(super.getTextTeaser());
}
}
@@ -0,0 +1,27 @@
package com.eu.habbo.habbohotel.catalog.layouts;
import com.eu.habbo.habbohotel.catalog.CatalogPage;
import com.eu.habbo.messages.ServerMessage;
import java.sql.ResultSet;
import java.sql.SQLException;
public class BuildersClubFrontPageLayout extends CatalogPage {
public BuildersClubFrontPageLayout(ResultSet set) throws SQLException {
super(set);
}
@Override
public void serialize(ServerMessage message) {
message.appendString("builders_club_frontpage");
message.appendInt(3);
message.appendString(super.getHeaderImage());
message.appendString(super.getTeaserImage());
message.appendString(super.getSpecialImage());
message.appendInt(3);
message.appendString(super.getTextOne());
message.appendString(super.getTextDetails());
message.appendString(super.getTextTeaser());
}
}
@@ -0,0 +1,27 @@
package com.eu.habbo.habbohotel.catalog.layouts;
import com.eu.habbo.habbohotel.catalog.CatalogPage;
import com.eu.habbo.messages.ServerMessage;
import java.sql.ResultSet;
import java.sql.SQLException;
public class BuildersClubLoyaltyLayout extends CatalogPage {
public BuildersClubLoyaltyLayout(ResultSet set) throws SQLException {
super(set);
}
@Override
public void serialize(ServerMessage message) {
message.appendString("builders_club_loyalty");
message.appendInt(3);
message.appendString(super.getHeaderImage());
message.appendString(super.getTeaserImage());
message.appendString(super.getSpecialImage());
message.appendInt(3);
message.appendString(super.getTextOne());
message.appendString(super.getTextDetails());
message.appendString(super.getTextTeaser());
}
}
@@ -0,0 +1,44 @@
package com.eu.habbo.habbohotel.catalog.layouts;
import com.eu.habbo.habbohotel.catalog.CatalogPage;
import com.eu.habbo.messages.ServerMessage;
import java.sql.ResultSet;
import java.sql.SQLException;
public class CatalogRootLayout extends CatalogPage {
public CatalogRootLayout() {
super();
this.id = -1;
this.parentId = -2;
this.rank = 0;
this.caption = "root";
this.pageName = "root";
this.iconColor = 0;
this.iconImage = 0;
this.orderNum = -10;
this.visible = true;
this.enabled = true;
}
public CatalogRootLayout(ResultSet set) throws SQLException {
super(null);
this.id = -1;
this.parentId = -2;
this.rank = 0;
this.caption = "root";
this.pageName = "root";
this.iconColor = 0;
this.iconImage = 0;
this.orderNum = -10;
this.visible = true;
this.enabled = true;
}
@Override
public void serialize(ServerMessage message) {
}
}
@@ -0,0 +1,22 @@
package com.eu.habbo.habbohotel.catalog.layouts;
import com.eu.habbo.habbohotel.catalog.CatalogPage;
import com.eu.habbo.messages.ServerMessage;
import java.sql.ResultSet;
import java.sql.SQLException;
public class ClubBuyLayout extends CatalogPage {
public ClubBuyLayout(ResultSet set) throws SQLException {
super(set);
}
@Override
public void serialize(ServerMessage message) {
message.appendString("club_buy");
message.appendInt(2);
message.appendString(super.getHeaderImage());
message.appendString(super.getTeaserImage());
message.appendInt(0);
}
}
@@ -0,0 +1,22 @@
package com.eu.habbo.habbohotel.catalog.layouts;
import com.eu.habbo.habbohotel.catalog.CatalogPage;
import com.eu.habbo.messages.ServerMessage;
import java.sql.ResultSet;
import java.sql.SQLException;
public class ClubGiftsLayout extends CatalogPage {
public ClubGiftsLayout(ResultSet set) throws SQLException {
super(set);
}
@Override
public void serialize(ServerMessage message) {
message.appendString("club_gifts");
message.appendInt(1);
message.appendString(super.getHeaderImage());
message.appendInt(1);
message.appendString(super.getTextOne());
}
}
@@ -0,0 +1,26 @@
package com.eu.habbo.habbohotel.catalog.layouts;
import com.eu.habbo.habbohotel.catalog.CatalogPage;
import com.eu.habbo.messages.ServerMessage;
import java.sql.ResultSet;
import java.sql.SQLException;
public class ColorGroupingLayout extends CatalogPage {
public ColorGroupingLayout(ResultSet set) throws SQLException {
super(set);
}
@Override
public void serialize(ServerMessage message) {
message.appendString("default_3x3_color_grouping");
message.appendInt(3);
message.appendString(super.getHeaderImage());
message.appendString(super.getTeaserImage());
message.appendString(super.getSpecialImage());
message.appendInt(3);
message.appendString(super.getTextOne());
message.appendString(super.getTextDetails());
message.appendString(super.getTextTeaser());
}
}
@@ -0,0 +1,27 @@
package com.eu.habbo.habbohotel.catalog.layouts;
import com.eu.habbo.habbohotel.catalog.CatalogPage;
import com.eu.habbo.messages.ServerMessage;
import java.sql.ResultSet;
import java.sql.SQLException;
public class Default_3x3Layout extends CatalogPage {
public Default_3x3Layout(ResultSet set) throws SQLException {
super(set);
}
@Override
public void serialize(ServerMessage message) {
message.appendString("default_3x3");
message.appendInt(3);
message.appendString(super.getHeaderImage());
message.appendString(super.getTeaserImage());
message.appendString(super.getSpecialImage());
message.appendInt(3);
message.appendString(super.getTextOne());
message.appendString(super.getTextDetails());
message.appendString(super.getTextTeaser());
}
}
@@ -0,0 +1,75 @@
package com.eu.habbo.habbohotel.catalog.layouts;
import com.eu.habbo.Emulator;
import com.eu.habbo.habbohotel.catalog.CatalogFeaturedPage;
import com.eu.habbo.habbohotel.catalog.CatalogPage;
import com.eu.habbo.messages.ServerMessage;
import java.sql.ResultSet;
import java.sql.SQLException;
public class FrontPageFeaturedLayout extends CatalogPage {
public FrontPageFeaturedLayout(ResultSet set) throws SQLException {
super(set);
}
@Override
public void serialize(ServerMessage message) {
message.appendString("frontpage_featured");
String[] teaserImages = super.getTeaserImage().split(";");
String[] specialImages = super.getSpecialImage().split(";");
message.appendInt(1 + teaserImages.length + specialImages.length);
message.appendString(super.getHeaderImage());
for (String s : teaserImages) {
message.appendString(s);
}
for (String s : specialImages) {
message.appendString(s);
}
message.appendInt(3);
message.appendString(super.getTextOne());
message.appendString(super.getTextDetails());
message.appendString(super.getTextTeaser());
}
public void serializeExtra(ServerMessage message) {
message.appendInt(Emulator.getGameEnvironment().getCatalogManager().getCatalogFeaturedPages().size());
for (CatalogFeaturedPage page : Emulator.getGameEnvironment().getCatalogManager().getCatalogFeaturedPages().valueCollection()) {
page.serialize(message);
}
message.appendInt(1); //Position
message.appendString("NUOVO: Affare Stanza di Rilassamento");
message.appendString("catalogue/feature_cata_vert_oly16bundle4.png");
message.appendInt(0); //Type
//0 : String //Page Name
//1 : Int //Page ID
//2 : String //Productdata
message.appendString("");
message.appendInt(-1);
message.appendInt(2);
message.appendString("Il RITORNO di Habburgers! (TUTTI furni nuovi)");
message.appendString("catalogue/feature_cata_hort_habbergerbundle.png");
message.appendInt(0);
message.appendString("");
message.appendInt(-1);
message.appendInt(3);
message.appendString("Habbolympics");
message.appendString("catalogue/feature_cata_hort_olympic16.png");
message.appendInt(0);
message.appendString("");
message.appendInt(-1);
message.appendInt(4);
message.appendString("Diventa un Membro HC");
message.appendString("catalogue/feature_cata_hort_HC_b.png");
message.appendInt(0);
message.appendString("habbo_club");
message.appendInt(-1);
}
}
@@ -0,0 +1,26 @@
package com.eu.habbo.habbohotel.catalog.layouts;
import com.eu.habbo.habbohotel.catalog.CatalogPage;
import com.eu.habbo.messages.ServerMessage;
import java.sql.ResultSet;
import java.sql.SQLException;
public class FrontpageLayout extends CatalogPage {
public FrontpageLayout(ResultSet set) throws SQLException {
super(set);
}
@Override
public void serialize(ServerMessage message) {
message.appendString("frontpage4");
message.appendInt(2);
message.appendString(super.getHeaderImage());
message.appendString(super.getTeaserImage());
message.appendInt(3);
message.appendString(super.getTextOne());
message.appendString(super.getTextTwo());
message.appendString(super.getTextTeaser());
}
}
@@ -0,0 +1,25 @@
package com.eu.habbo.habbohotel.catalog.layouts;
import com.eu.habbo.habbohotel.catalog.CatalogPage;
import com.eu.habbo.messages.ServerMessage;
import java.sql.ResultSet;
import java.sql.SQLException;
public class GuildForumLayout extends CatalogPage {
public GuildForumLayout(ResultSet set) throws SQLException {
super(set);
}
@Override
public void serialize(ServerMessage message) {
message.appendString("guild_forum");
message.appendInt(2);
message.appendString(super.getHeaderImage());
message.appendString(super.getTeaserImage());
message.appendInt(3);
message.appendString(super.getTextOne());
message.appendString(super.getTextDetails());
message.appendString(super.getTextTeaser());
}
}
@@ -0,0 +1,25 @@
package com.eu.habbo.habbohotel.catalog.layouts;
import com.eu.habbo.habbohotel.catalog.CatalogPage;
import com.eu.habbo.messages.ServerMessage;
import java.sql.ResultSet;
import java.sql.SQLException;
public class GuildFrontpageLayout extends CatalogPage {
public GuildFrontpageLayout(ResultSet set) throws SQLException {
super(set);
}
@Override
public void serialize(ServerMessage message) {
message.appendString("guild_frontpage");
message.appendInt(2);
message.appendString(super.getHeaderImage());
message.appendString(super.getTeaserImage());
message.appendInt(3);
message.appendString(super.getTextOne());
message.appendString(super.getTextDetails());
message.appendString(super.getTextTeaser());
}
}
@@ -0,0 +1,25 @@
package com.eu.habbo.habbohotel.catalog.layouts;
import com.eu.habbo.habbohotel.catalog.CatalogPage;
import com.eu.habbo.messages.ServerMessage;
import java.sql.ResultSet;
import java.sql.SQLException;
public class GuildFurnitureLayout extends CatalogPage {
public GuildFurnitureLayout(ResultSet set) throws SQLException {
super(set);
}
@Override
public void serialize(ServerMessage message) {
message.appendString("guild_custom_furni");
message.appendInt(2);
message.appendString(super.getHeaderImage());
message.appendString(super.getTeaserImage());
message.appendInt(3);
message.appendString(super.getTextOne());
message.appendString(super.getTextDetails());
message.appendString(super.getTextTeaser());
}
}
@@ -0,0 +1,23 @@
package com.eu.habbo.habbohotel.catalog.layouts;
import com.eu.habbo.habbohotel.catalog.CatalogPage;
import com.eu.habbo.messages.ServerMessage;
import java.sql.ResultSet;
import java.sql.SQLException;
public class InfoDucketsLayout extends CatalogPage {
public InfoDucketsLayout(ResultSet set) throws SQLException {
super(set);
}
@Override
public void serialize(ServerMessage message) {
message.appendString("info_duckets");
message.appendInt(1);
message.appendString(this.getHeaderImage());
message.appendInt(1);
message.appendString(this.getTextOne());
message.appendInt(0);
}
}
@@ -0,0 +1,23 @@
package com.eu.habbo.habbohotel.catalog.layouts;
import com.eu.habbo.habbohotel.catalog.CatalogPage;
import com.eu.habbo.messages.ServerMessage;
import java.sql.ResultSet;
import java.sql.SQLException;
public class InfoLoyaltyLayout extends CatalogPage {
public InfoLoyaltyLayout(ResultSet set) throws SQLException {
super(set);
}
@Override
public void serialize(ServerMessage message) {
message.appendString("info_loyalty");
message.appendInt(1);
message.appendString(this.getHeaderImage());
message.appendInt(1);
message.appendString(this.getTextOne());
message.appendInt(0);
}
}
@@ -0,0 +1,27 @@
package com.eu.habbo.habbohotel.catalog.layouts;
import com.eu.habbo.habbohotel.catalog.CatalogPage;
import com.eu.habbo.messages.ServerMessage;
import java.sql.ResultSet;
import java.sql.SQLException;
public class InfoMonkeyLayout extends CatalogPage {
public InfoMonkeyLayout(ResultSet set) throws SQLException {
super(set);
}
@Override
public void serialize(ServerMessage message) {
message.appendString("monkey");
message.appendInt(3);
message.appendString(super.getHeaderImage());
message.appendString(super.getTeaserImage());
message.appendString(super.getSpecialImage());
message.appendInt(3);
message.appendString(super.getTextOne());
message.appendString(super.getTextDetails());
message.appendString(super.getTextTeaser());
}
}
@@ -0,0 +1,27 @@
package com.eu.habbo.habbohotel.catalog.layouts;
import com.eu.habbo.habbohotel.catalog.CatalogPage;
import com.eu.habbo.messages.ServerMessage;
import java.sql.ResultSet;
import java.sql.SQLException;
public class InfoNikoLayout extends CatalogPage {
public InfoNikoLayout(ResultSet set) throws SQLException {
super(set);
}
@Override
public void serialize(ServerMessage message) {
message.appendString("monkey");
message.appendInt(3);
message.appendString(super.getHeaderImage());
message.appendString(super.getTeaserImage());
message.appendString(super.getSpecialImage());
message.appendInt(3);
message.appendString(super.getTextOne());
message.appendString(super.getTextDetails());
message.appendString(super.getTextTeaser());
}
}
@@ -0,0 +1,26 @@
package com.eu.habbo.habbohotel.catalog.layouts;
import com.eu.habbo.habbohotel.catalog.CatalogPage;
import com.eu.habbo.messages.ServerMessage;
import java.sql.ResultSet;
import java.sql.SQLException;
public class InfoPetsLayout extends CatalogPage {
public InfoPetsLayout(ResultSet set) throws SQLException {
super(set);
}
@Override
public void serialize(ServerMessage message) {
message.appendString("info_pets");
message.appendInt(2);
message.appendString(this.getHeaderImage());
message.appendString(this.getTeaserImage());
message.appendInt(3);
message.appendString(this.getTextOne());
message.appendString("");
message.appendString(this.getTextTeaser());
message.appendInt(0);
}
}
@@ -0,0 +1,26 @@
package com.eu.habbo.habbohotel.catalog.layouts;
import com.eu.habbo.habbohotel.catalog.CatalogPage;
import com.eu.habbo.messages.ServerMessage;
import java.sql.ResultSet;
import java.sql.SQLException;
public class InfoRentablesLayout extends CatalogPage {
public InfoRentablesLayout(ResultSet set) throws SQLException {
super(set);
}
@Override
public void serialize(ServerMessage message) {
String[] data = this.getTextOne().split("\\|\\|");
message.appendString("info_rentables");
message.appendInt(1);
message.appendString(this.getHeaderImage());
message.appendInt(data.length);
for (String d : data) {
message.appendString(d);
}
message.appendInt(0);
}
}
@@ -0,0 +1,26 @@
package com.eu.habbo.habbohotel.catalog.layouts;
import com.eu.habbo.habbohotel.catalog.CatalogPage;
import com.eu.habbo.messages.ServerMessage;
import java.sql.ResultSet;
import java.sql.SQLException;
public class LoyaltyVipBuyLayout extends CatalogPage {
public LoyaltyVipBuyLayout(ResultSet set) throws SQLException {
super(set);
}
@Override
public void serialize(ServerMessage message) {
message.appendString("loyalty_vip_buy");
message.appendInt(3);
message.appendString(super.getHeaderImage());
message.appendString(super.getTeaserImage());
message.appendString(super.getSpecialImage());
message.appendInt(3);
message.appendString(super.getTextOne());
message.appendString(super.getTextDetails());
message.appendString(super.getTextTeaser());
}
}
@@ -0,0 +1,27 @@
package com.eu.habbo.habbohotel.catalog.layouts;
import com.eu.habbo.habbohotel.catalog.CatalogPage;
import com.eu.habbo.messages.ServerMessage;
import java.sql.ResultSet;
import java.sql.SQLException;
public class MadMoneyLayout extends CatalogPage {
public MadMoneyLayout(ResultSet set) throws SQLException {
super(set);
}
@Override
public void serialize(ServerMessage message) {
message.appendString("mad_money");
message.appendInt(2);
message.appendString(super.getHeaderImage());
message.appendString(super.getTeaserImage());
message.appendInt(2);
message.appendString(super.getTextOne());
message.appendString(super.getTextTwo());
// message.appendString("MH");
message.appendInt(0);
}
}
@@ -0,0 +1,20 @@
package com.eu.habbo.habbohotel.catalog.layouts;
import com.eu.habbo.habbohotel.catalog.CatalogPage;
import com.eu.habbo.messages.ServerMessage;
import java.sql.ResultSet;
import java.sql.SQLException;
public class MarketplaceLayout extends CatalogPage {
public MarketplaceLayout(ResultSet set) throws SQLException {
super(set);
}
@Override
public void serialize(ServerMessage message) {
message.appendString("marketplace");
message.appendInt(0);
message.appendInt(0);
}
}
@@ -0,0 +1,21 @@
package com.eu.habbo.habbohotel.catalog.layouts;
import com.eu.habbo.habbohotel.catalog.CatalogPage;
import com.eu.habbo.messages.ServerMessage;
import java.sql.ResultSet;
import java.sql.SQLException;
public class MarketplaceOwnItems extends CatalogPage {
public MarketplaceOwnItems(ResultSet set) throws SQLException {
super(set);
}
@Override
public void serialize(ServerMessage message) {
message.appendString("marketplace_own_items");
message.appendInt(0);
message.appendInt(0);
}
}
@@ -0,0 +1,26 @@
package com.eu.habbo.habbohotel.catalog.layouts;
import com.eu.habbo.habbohotel.catalog.CatalogPage;
import com.eu.habbo.messages.ServerMessage;
import java.sql.ResultSet;
import java.sql.SQLException;
public class PetCustomizationLayout extends CatalogPage {
public PetCustomizationLayout(ResultSet set) throws SQLException {
super(set);
}
@Override
public void serialize(ServerMessage message) {
message.appendString("petcustomization");
message.appendInt(3);
message.appendString(super.getHeaderImage());
message.appendString(super.getTeaserImage());
message.appendString(super.getSpecialImage());
message.appendInt(3);
message.appendString(super.getTextOne());
message.appendString(super.getTextDetails());
message.appendString(super.getTextTeaser());
}
}
@@ -0,0 +1,26 @@
package com.eu.habbo.habbohotel.catalog.layouts;
import com.eu.habbo.habbohotel.catalog.CatalogPage;
import com.eu.habbo.messages.ServerMessage;
import java.sql.ResultSet;
import java.sql.SQLException;
public class Pets2Layout extends CatalogPage {
public Pets2Layout(ResultSet set) throws SQLException {
super(set);
}
@Override
public void serialize(ServerMessage message) {
message.appendString("pets2");
message.appendInt(2);
message.appendString(super.getHeaderImage());
message.appendString(super.getTeaserImage());
message.appendInt(4);
message.appendString(super.getTextOne());
message.appendString(super.getTextTwo());
message.appendString(super.getTextDetails());
message.appendString(super.getTextTeaser());
}
}
@@ -0,0 +1,26 @@
package com.eu.habbo.habbohotel.catalog.layouts;
import com.eu.habbo.habbohotel.catalog.CatalogPage;
import com.eu.habbo.messages.ServerMessage;
import java.sql.ResultSet;
import java.sql.SQLException;
public class Pets3Layout extends CatalogPage {
public Pets3Layout(ResultSet set) throws SQLException {
super(set);
}
@Override
public void serialize(ServerMessage message) {
message.appendString("pets3");
message.appendInt(2);
message.appendString(super.getHeaderImage());
message.appendString(super.getTeaserImage());
message.appendInt(4);
message.appendString(super.getTextOne());
message.appendString(super.getTextTwo());
message.appendString(super.getTextDetails());
message.appendString(super.getTextTeaser());
}
}
@@ -0,0 +1,26 @@
package com.eu.habbo.habbohotel.catalog.layouts;
import com.eu.habbo.habbohotel.catalog.CatalogPage;
import com.eu.habbo.messages.ServerMessage;
import java.sql.ResultSet;
import java.sql.SQLException;
public class PetsLayout extends CatalogPage {
public PetsLayout(ResultSet set) throws SQLException {
super(set);
}
@Override
public void serialize(ServerMessage message) {
message.appendString("pets");
message.appendInt(2);
message.appendString(super.getHeaderImage());
message.appendString(super.getTeaserImage());
message.appendInt(4);
message.appendString(super.getTextOne());
message.appendString(super.getTextTwo());
message.appendString(super.getTextDetails());
message.appendString(super.getTextTeaser());
}
}
@@ -0,0 +1,26 @@
package com.eu.habbo.habbohotel.catalog.layouts;
import com.eu.habbo.habbohotel.catalog.CatalogPage;
import com.eu.habbo.messages.ServerMessage;
import java.sql.ResultSet;
import java.sql.SQLException;
public class ProductPage1Layout extends CatalogPage {
public ProductPage1Layout(ResultSet set) throws SQLException {
super(set);
}
@Override
public void serialize(ServerMessage message) {
message.appendString("productpage1");
message.appendInt(2);
message.appendString(super.getHeaderImage());
message.appendString(super.getTeaserImage());
message.appendInt(4);
message.appendString(super.getTextOne());
message.appendString(super.getTextTwo());
message.appendString(super.getTextDetails());
message.appendString(super.getTextTeaser());
}
}
@@ -0,0 +1,26 @@
package com.eu.habbo.habbohotel.catalog.layouts;
import com.eu.habbo.habbohotel.catalog.CatalogPage;
import com.eu.habbo.messages.ServerMessage;
import java.sql.ResultSet;
import java.sql.SQLException;
public class RecentPurchasesLayout extends CatalogPage {
public RecentPurchasesLayout(ResultSet set) throws SQLException {
super(set);
}
@Override
public void serialize(ServerMessage message) {
message.appendString("default_3x3");
message.appendInt(3);
message.appendString(super.getHeaderImage());
message.appendString(super.getTeaserImage());
message.appendString(super.getSpecialImage());
message.appendInt(3);
message.appendString(super.getTextOne());
message.appendString(super.getTextDetails());
message.appendString(super.getTextTeaser());
}
}
@@ -0,0 +1,26 @@
package com.eu.habbo.habbohotel.catalog.layouts;
import com.eu.habbo.habbohotel.catalog.CatalogPage;
import com.eu.habbo.messages.ServerMessage;
import java.sql.ResultSet;
import java.sql.SQLException;
public class RecyclerInfoLayout extends CatalogPage {
public RecyclerInfoLayout(ResultSet set) throws SQLException {
super(set);
}
@Override
public void serialize(ServerMessage message) {
message.appendString("recycler_info");
message.appendInt(3);
message.appendString(super.getHeaderImage());
message.appendString(super.getTeaserImage());
message.appendString(super.getSpecialImage());
message.appendInt(3);
message.appendString(super.getTextOne());
message.appendString(super.getTextDetails());
message.appendString(super.getTextTeaser());
}
}
@@ -0,0 +1,25 @@
package com.eu.habbo.habbohotel.catalog.layouts;
import com.eu.habbo.habbohotel.catalog.CatalogPage;
import com.eu.habbo.messages.ServerMessage;
import java.sql.ResultSet;
import java.sql.SQLException;
public class RecyclerLayout extends CatalogPage {
public RecyclerLayout(ResultSet set) throws SQLException {
super(set);
}
@Override
public void serialize(ServerMessage message) {
message.appendString("recycler");
message.appendInt(2);
message.appendString(super.getHeaderImage());
message.appendString(super.getTeaserImage());
message.appendInt(1);
message.appendString(super.getTextOne());
message.appendInt(-1);
message.appendBoolean(false);
}
}
@@ -0,0 +1,26 @@
package com.eu.habbo.habbohotel.catalog.layouts;
import com.eu.habbo.habbohotel.catalog.CatalogPage;
import com.eu.habbo.messages.ServerMessage;
import java.sql.ResultSet;
import java.sql.SQLException;
public class RecyclerPrizesLayout extends CatalogPage {
public RecyclerPrizesLayout(ResultSet set) throws SQLException {
super(set);
}
@Override
public void serialize(ServerMessage message) {
message.appendString("recycler_prizes");
message.appendInt(3);
message.appendString(super.getHeaderImage());
message.appendString(super.getTeaserImage());
message.appendString(super.getSpecialImage());
message.appendInt(3);
message.appendString(super.getTextOne());
message.appendString(super.getTextDetails());
message.appendString(super.getTextTeaser());
}
}
@@ -0,0 +1,24 @@
package com.eu.habbo.habbohotel.catalog.layouts;
import com.eu.habbo.habbohotel.catalog.CatalogPage;
import com.eu.habbo.messages.ServerMessage;
import java.sql.ResultSet;
import java.sql.SQLException;
public class RoomAdsLayout extends CatalogPage {
public RoomAdsLayout(ResultSet set) throws SQLException {
super(set);
}
@Override
public void serialize(ServerMessage message) {
message.appendString("roomads");
message.appendInt(2);
message.appendString(super.getHeaderImage());
message.appendString(super.getTeaserImage());
message.appendInt(2);
message.appendString(super.getTextOne());
message.appendString(super.getTextTwo());
}
}
@@ -0,0 +1,246 @@
package com.eu.habbo.habbohotel.catalog.layouts;
import com.eu.habbo.Emulator;
import com.eu.habbo.habbohotel.bots.Bot;
import com.eu.habbo.habbohotel.catalog.CatalogItem;
import com.eu.habbo.habbohotel.items.Item;
import com.eu.habbo.habbohotel.rooms.Room;
import com.eu.habbo.habbohotel.rooms.RoomManager;
import com.eu.habbo.habbohotel.users.Habbo;
import com.eu.habbo.habbohotel.users.HabboItem;
import com.eu.habbo.messages.outgoing.generic.alerts.BubbleAlertComposer;
import com.eu.habbo.messages.outgoing.generic.alerts.BubbleAlertKeys;
import com.eu.habbo.messages.outgoing.navigator.CanCreateRoomComposer;
import gnu.trove.map.TIntObjectMap;
import gnu.trove.map.hash.THashMap;
import gnu.trove.procedure.TObjectProcedure;
import lombok.extern.slf4j.Slf4j;
import java.sql.*;
import java.util.Map;
@Slf4j
public class RoomBundleLayout extends SingleBundle {
public int roomId;
public Room room;
private int lastUpdate = 0;
private boolean loaded = false;
public RoomBundleLayout(ResultSet set) throws SQLException {
super(set);
this.roomId = set.getInt("room_id");
}
@Override
public TIntObjectMap<CatalogItem> getCatalogItems() {
if (Emulator.getIntUnixTimestamp() - this.lastUpdate < 120) {
this.lastUpdate = Emulator.getIntUnixTimestamp();
return super.getCatalogItems();
}
if (this.room == null) {
if (this.roomId > 0) {
this.room = Emulator.getGameEnvironment().getRoomManager().loadRoom(this.roomId);
if (this.room != null)
this.room.preventUnloading = true;
} else {
log.error("No room id specified for room bundle " + this.getPageName() + "(" + this.getId() + ")");
}
}
if (this.room == null) {
return super.getCatalogItems();
}
final CatalogItem[] item = {null};
super.getCatalogItems().forEachValue(new TObjectProcedure<CatalogItem>() {
@Override
public boolean execute(CatalogItem object) {
if (object == null)
return true;
item[0] = object;
return false;
}
});
if (this.room.isPreLoaded()) {
this.room.loadData();
this.room.preventUncaching = true;
this.room.preventUnloading = true;
}
if (item[0] != null) {
item[0].getBundle().clear();
THashMap<Item, Integer> items = new THashMap<>();
for (HabboItem i : this.room.getFloorItems()) {
if (!items.contains(i.getBaseItem())) {
items.put(i.getBaseItem(), 0);
}
items.put(i.getBaseItem(), items.get(i.getBaseItem()) + 1);
}
for (HabboItem i : this.room.getWallItems()) {
if (!items.contains(i.getBaseItem())) {
items.put(i.getBaseItem(), 0);
}
items.put(i.getBaseItem(), items.get(i.getBaseItem()) + 1);
}
if (!item[0].getExtradata().isEmpty()) {
items.put(Emulator.getGameEnvironment().getItemManager().getItem(Integer.valueOf(item[0].getExtradata())), 1);
}
StringBuilder data = new StringBuilder();
for (Map.Entry<Item, Integer> set : items.entrySet()) {
data.append(set.getKey().getId()).append(":").append(set.getValue()).append(";");
}
item[0].setItemId(data.toString());
item[0].loadBundle();
}
return super.getCatalogItems();
}
public void loadItems(Room room) {
if (this.room != null) {
this.room.preventUnloading = false;
}
this.room = room;
this.room.preventUnloading = true;
this.getCatalogItems();
this.loaded = true;
}
public void buyRoom(Habbo habbo) {
this.buyRoom(habbo, habbo.getHabboInfo().getId(), habbo.getHabboInfo().getUsername());
}
public void buyRoom(Habbo habbo, int userId, String userName) {
if (!this.loaded) {
this.loadItems(Emulator.getGameEnvironment().getRoomManager().loadRoom(this.roomId));
}
if (habbo != null) {
int count = Emulator.getGameEnvironment().getRoomManager().getRoomsForHabbo(habbo).size();
int max = habbo.getHabboStats().hasActiveClub() ? RoomManager.MAXIMUM_ROOMS_HC : RoomManager.MAXIMUM_ROOMS_USER;
if (count >= max) {
habbo.getClient().sendResponse(new CanCreateRoomComposer(count, max));
return;
}
}
if (this.room == null)
return;
this.room.save();
for (HabboItem item : this.room.getFloorItems()) {
item.run();
}
for (HabboItem item : this.room.getWallItems()) {
item.run();
}
this.getCatalogItems();
int roomId = 0;
try (Connection connection = Emulator.getDatabase().getDataSource().getConnection()) {
try (PreparedStatement statement = connection.prepareStatement("INSERT INTO rooms (owner_id, owner_name, name, description, model, password, state, users_max, category, paper_floor, paper_wall, paper_landscape, thickness_wall, thickness_floor, moodlight_data, override_model) (SELECT ?, ?, name, description, model, password, state, users_max, category, paper_floor, paper_wall, paper_landscape, thickness_wall, thickness_floor, moodlight_data, override_model FROM rooms WHERE id = ?)", Statement.RETURN_GENERATED_KEYS)) {
statement.setInt(1, userId);
statement.setString(2, userName);
statement.setInt(3, this.room.getId());
statement.execute();
try (ResultSet set = statement.getGeneratedKeys()) {
if (set.next()) {
roomId = set.getInt(1);
}
}
}
if (roomId == 0)
return;
try (PreparedStatement statement = connection.prepareStatement("INSERT INTO items (user_id, room_id, item_id, wall_pos, x, y, z, rot, extra_data, wired_data, limited_data, guild_id) (SELECT ?, ?, item_id, wall_pos, x, y, z, rot, extra_data, wired_data, ?, ? FROM items WHERE room_id = ?)", Statement.RETURN_GENERATED_KEYS)) {
statement.setInt(1, userId);
statement.setInt(2, roomId);
statement.setString(3, "0:0");
statement.setInt(4, 0);
statement.setInt(5, this.room.getId());
statement.execute();
}
if (this.room.hasCustomLayout()) {
try (PreparedStatement statement = connection.prepareStatement("INSERT INTO room_models_custom (id, name, door_x, door_y, door_dir, heightmap) (SELECT ?, ?, door_x, door_y, door_dir, heightmap FROM room_models_custom WHERE id = ? LIMIT 1)", Statement.RETURN_GENERATED_KEYS)) {
statement.setInt(1, roomId);
statement.setString(2, "custom_" + roomId);
statement.setInt(3, this.room.getId());
statement.execute();
} catch (SQLException e) {
log.error("Caught SQL exception", e);
}
}
if (Emulator.getConfig().getBoolean("bundle.bots.enabled")) {
try (PreparedStatement statement = connection.prepareStatement("INSERT INTO bots (user_id, room_id, name, motto, figure, gender, x, y, z, chat_lines, chat_auto, chat_random, chat_delay, dance, type) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", Statement.RETURN_GENERATED_KEYS)) {
synchronized (this.room.getCurrentBots()) {
statement.setInt(1, userId);
statement.setInt(2, roomId);
for (Bot bot : this.room.getCurrentBots().valueCollection()) {
statement.setString(3, bot.getName());
statement.setString(4, bot.getMotto());
statement.setString(5, bot.getFigure());
statement.setString(6, bot.getGender().name());
statement.setInt(7, bot.getRoomUnit().getX());
statement.setInt(8, bot.getRoomUnit().getY());
statement.setDouble(9, bot.getRoomUnit().getZ());
StringBuilder text = new StringBuilder();
for (String s : bot.getChatLines()) {
text.append(s).append("\r");
}
statement.setString(10, text.toString());
statement.setString(11, bot.isChatAuto() ? "1" : "0");
statement.setString(12, bot.isChatRandom() ? "1" : "0");
statement.setInt(13, bot.getChatDelay());
statement.setInt(14, bot.getRoomUnit().getDanceType().getType());
statement.setString(15, bot.getType());
statement.addBatch();
}
}
statement.executeBatch();
}
}
} catch (SQLException e) {
log.error("Caught SQL exception", e);
}
Room r = Emulator.getGameEnvironment().getRoomManager().loadRoom(roomId);
r.setWallHeight(this.room.getWallHeight());
r.setFloorSize(this.room.getFloorSize());
r.setWallPaint(this.room.getWallPaint());
r.setFloorPaint(this.room.getFloorPaint());
r.setScore(0);
r.setNeedsUpdate(true);
THashMap<String, String> keys = new THashMap<>();
keys.put("ROOMNAME", r.getName());
keys.put("ROOMID", r.getId() + "");
keys.put("OWNER", r.getOwnerName());
keys.put("image", "${image.library.url}/notifications/room_bundle_" + this.getId() + ".png");
if (habbo != null) {
habbo.getClient().sendResponse(new BubbleAlertComposer(BubbleAlertKeys.PURCHASING_ROOM.key, keys));
}
}
}
@@ -0,0 +1,27 @@
package com.eu.habbo.habbohotel.catalog.layouts;
import com.eu.habbo.habbohotel.catalog.CatalogPage;
import com.eu.habbo.messages.ServerMessage;
import java.sql.ResultSet;
import java.sql.SQLException;
public class SingleBundle extends CatalogPage {
public SingleBundle(ResultSet set) throws SQLException {
super(set);
}
@Override
public void serialize(ServerMessage message) {
message.appendString("single_bundle");
message.appendInt(3);
message.appendString(super.getHeaderImage());
message.appendString(super.getTeaserImage());
message.appendString("");
message.appendInt(4);
message.appendString(super.getTextOne());
message.appendString(super.getTextDetails());
message.appendString(super.getTextTeaser());
message.appendString(super.getTextTwo());
}
}

Some files were not shown because too many files have changed in this diff Show More