You've already forked Arcturus-Morningstar-Extended
mirror of
https://github.com/duckietm/Arcturus-Morningstar-Extended.git
synced 2026-06-19 15:06:19 +00:00
Merge branch 'main' into dev
This commit is contained in:
@@ -0,0 +1,22 @@
|
||||
SET NAMES utf8mb4;
|
||||
|
||||
-- Create the hotel timezone setting if it does not exist yet.
|
||||
INSERT INTO `emulator_settings` (`key`, `value`)
|
||||
SELECT 'hotel.timezone', 'Europe/Rome'
|
||||
WHERE NOT EXISTS (
|
||||
SELECT 1
|
||||
FROM `emulator_settings`
|
||||
WHERE `key` = 'hotel.timezone'
|
||||
);
|
||||
|
||||
-- Keep the default/example value aligned for existing installs too.
|
||||
UPDATE `emulator_settings`
|
||||
SET `value` = 'Europe/Rome'
|
||||
WHERE `key` = 'hotel.timezone';
|
||||
|
||||
-- Helper query for a timezone selector.
|
||||
-- If MySQL/MariaDB timezone tables are populated, this returns the available timezone ids.
|
||||
SELECT `Name` AS `timezone_id`
|
||||
FROM `mysql`.`time_zone_name`
|
||||
WHERE `Name` IS NOT NULL
|
||||
ORDER BY `Name`;
|
||||
@@ -7,6 +7,7 @@ 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.habbohotel.gameclients.SessionResumeManager;
|
||||
import com.eu.habbo.networking.gameserver.GameServer;
|
||||
import com.eu.habbo.networking.rconserver.RCONServer;
|
||||
import com.eu.habbo.plugin.PluginManager;
|
||||
@@ -20,6 +21,8 @@ import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.*;
|
||||
import java.net.JarURLConnection;
|
||||
import java.net.URL;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.SecureRandom;
|
||||
import java.sql.Timestamp;
|
||||
@@ -52,6 +55,7 @@ public final class Emulator {
|
||||
"Still Rocking in 2026.\n";
|
||||
|
||||
public static String build = "";
|
||||
public static long buildTimestamp = -1L;
|
||||
public static boolean isReady = false;
|
||||
public static boolean isShuttingDown = false;
|
||||
public static boolean stopped = false;
|
||||
@@ -103,13 +107,6 @@ public final class Emulator {
|
||||
|
||||
System.out.println(logo);
|
||||
|
||||
System.out.println();
|
||||
LOGGER.info("https://github.com/duckietm/Arcturus-Morningstar-Extended, ");
|
||||
System.out.println();
|
||||
LOGGER.info("This project is for educational purposes only. This Emulator is an open-source fork of Arcturus created by TheGeneral.");
|
||||
LOGGER.info("Version: {}", version);
|
||||
LOGGER.info("Build: {}", build);
|
||||
|
||||
long startTime = System.nanoTime();
|
||||
|
||||
Emulator.runtime = Runtime.getRuntime();
|
||||
@@ -141,6 +138,15 @@ public final class Emulator {
|
||||
Emulator.config.register("camera.price.points", "0");
|
||||
Emulator.config.register("camera.price.points.type", "5");
|
||||
Emulator.config.register("camera.render.delay", "5");
|
||||
Emulator.config.register("hotel.timezone", java.time.ZoneId.systemDefault().getId());
|
||||
String hotelTimezoneId = Emulator.getConfig().getValue("hotel.timezone", java.time.ZoneId.systemDefault().getId());
|
||||
System.out.println();
|
||||
LOGGER.info("https://github.com/duckietm/Arcturus-Morningstar-Extended, ");
|
||||
System.out.println();
|
||||
LOGGER.info("This project is for educational purposes only. This Emulator is an open-source fork of Arcturus created by TheGeneral.");
|
||||
LOGGER.info("Version: {}", version);
|
||||
LOGGER.info("Build: {}", build);
|
||||
LOGGER.info("Build Timestamp: {} [{}]", formatBuildTimestamp(buildTimestamp, hotelTimezoneId), hotelTimezoneId);
|
||||
Emulator.texts.register("camera.permission", "You don't have permission to use the camera!");
|
||||
Emulator.texts.register("camera.wait", "Please wait %seconds% seconds before making another picture.");
|
||||
Emulator.texts.register("camera.error.creation", "Failed to create your picture. *sadpanda*");
|
||||
@@ -216,12 +222,21 @@ public final class Emulator {
|
||||
private static void setBuild() {
|
||||
if (Emulator.class.getProtectionDomain().getCodeSource() == null) {
|
||||
build = "UNKNOWN";
|
||||
buildTimestamp = -1L;
|
||||
return;
|
||||
}
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
try {
|
||||
String filepath = new File(Emulator.class.getProtectionDomain().getCodeSource().getLocation().getPath()).getAbsolutePath();
|
||||
File buildFile = new File(Emulator.class.getProtectionDomain().getCodeSource().getLocation().toURI());
|
||||
buildTimestamp = resolveBuildTimestamp(buildFile);
|
||||
|
||||
if (!buildFile.isFile()) {
|
||||
build = "DEV";
|
||||
return;
|
||||
}
|
||||
|
||||
String filepath = buildFile.getAbsolutePath();
|
||||
MessageDigest md = MessageDigest.getInstance("MD5");
|
||||
try (FileInputStream fis = new FileInputStream(filepath)) {
|
||||
byte[] dataBytes = new byte[1024];
|
||||
@@ -234,14 +249,69 @@ public final class Emulator {
|
||||
}
|
||||
} catch (Exception e) {
|
||||
build = "UNKNOWN";
|
||||
buildTimestamp = -1L;
|
||||
return;
|
||||
}
|
||||
|
||||
build = sb.toString();
|
||||
}
|
||||
|
||||
private static long resolveBuildTimestamp(File buildFile) {
|
||||
if (buildFile != null && buildFile.exists() && buildFile.isFile()) {
|
||||
return buildFile.lastModified();
|
||||
}
|
||||
|
||||
try {
|
||||
URL classUrl = Emulator.class.getResource("Emulator.class");
|
||||
|
||||
if (classUrl != null) {
|
||||
if ("file".equalsIgnoreCase(classUrl.getProtocol())) {
|
||||
File classFile = new File(classUrl.toURI());
|
||||
|
||||
if (classFile.exists()) {
|
||||
return classFile.lastModified();
|
||||
}
|
||||
}
|
||||
|
||||
if ("jar".equalsIgnoreCase(classUrl.getProtocol())) {
|
||||
JarURLConnection connection = (JarURLConnection) classUrl.openConnection();
|
||||
File jarFile = new File(connection.getJarFileURL().toURI());
|
||||
|
||||
if (jarFile.exists()) {
|
||||
return jarFile.lastModified();
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
|
||||
if (buildFile != null && buildFile.exists()) {
|
||||
return buildFile.lastModified();
|
||||
}
|
||||
|
||||
return -1L;
|
||||
}
|
||||
|
||||
private static String formatBuildTimestamp(long buildTimestamp, String timezoneId) {
|
||||
if (buildTimestamp <= 0) {
|
||||
return "UNKNOWN";
|
||||
}
|
||||
|
||||
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
||||
|
||||
try {
|
||||
format.setTimeZone(TimeZone.getTimeZone(java.time.ZoneId.of(timezoneId)));
|
||||
} catch (Exception ignored) {
|
||||
format.setTimeZone(TimeZone.getDefault());
|
||||
}
|
||||
|
||||
return format.format(new Timestamp(buildTimestamp));
|
||||
}
|
||||
|
||||
private static void dispose() {
|
||||
Emulator.getThreading().setCanAdd(false);
|
||||
if (Emulator.threading != null) {
|
||||
Emulator.threading.setCanAdd(false);
|
||||
}
|
||||
Emulator.isShuttingDown = true;
|
||||
Emulator.isReady = false;
|
||||
|
||||
@@ -250,6 +320,7 @@ public final class Emulator {
|
||||
if (Emulator.pluginManager != null)
|
||||
tryShutdown(() -> Emulator.pluginManager.fireEvent(new EmulatorStartShutdownEvent()));
|
||||
if (Emulator.rconServer != null) tryShutdown(() -> Emulator.rconServer.stop());
|
||||
tryShutdown(() -> SessionResumeManager.getInstance().disposeAll());
|
||||
if (Emulator.gameEnvironment != null) tryShutdown(() -> Emulator.gameEnvironment.dispose());
|
||||
if (Emulator.pluginManager != null)
|
||||
tryShutdown(() -> Emulator.pluginManager.fireEvent(new EmulatorStoppedEvent()));
|
||||
|
||||
@@ -87,6 +87,7 @@ public class ConfigurationManager {
|
||||
// Runtime
|
||||
envMapping.put("runtime.threads", "RT_THREADS");
|
||||
envMapping.put("logging.errors.runtime", "RT_LOG_ERRORS");
|
||||
envMapping.put("hotel.timezone", "HOTEL_TIMEZONE");
|
||||
|
||||
for (Map.Entry<String, String> entry : envMapping.entrySet()) {
|
||||
String envValue = System.getenv(entry.getValue());
|
||||
|
||||
@@ -301,7 +301,7 @@ public class CommandHandler {
|
||||
addCommand(new ListPrefixesCommand());
|
||||
addCommand(new RemovePrefixCommand());
|
||||
addCommand(new PrefixBlacklistCommand());
|
||||
|
||||
addCommand(new WiredCommand());
|
||||
addCommand(new TestCommand());
|
||||
}
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@ public class UnmuteCommand extends Command {
|
||||
}
|
||||
|
||||
if (habbo.getHabboInfo().getCurrentRoom() != null && habbo.getHabboInfo().getCurrentRoom().isMuted(habbo)) {
|
||||
habbo.getHabboInfo().getCurrentRoom().muteHabbo(habbo, 1);
|
||||
habbo.getHabboInfo().getCurrentRoom().unmuteHabbo(habbo);
|
||||
}
|
||||
|
||||
gameClient.getHabbo().whisper(Emulator.getTexts().getValue("commands.succes.cmd_unmute").replace("%user%", params[1]), RoomChatMessageBubbles.ALERT);
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
package com.eu.habbo.habbohotel.commands;
|
||||
|
||||
import com.eu.habbo.habbohotel.gameclients.GameClient;
|
||||
import com.eu.habbo.habbohotel.permissions.Permission;
|
||||
import com.eu.habbo.habbohotel.rooms.Room;
|
||||
import com.eu.habbo.habbohotel.rooms.RoomChatMessageBubbles;
|
||||
import com.eu.habbo.messages.outgoing.users.InClientLinkComposer;
|
||||
|
||||
public class WiredCommand extends Command {
|
||||
public WiredCommand() {
|
||||
super(Permission.ACC_PLACEFURNI, new String[]{"wired"});
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean handle(GameClient gameClient, String[] params) throws Exception {
|
||||
Room room = gameClient.getHabbo().getHabboInfo().getCurrentRoom();
|
||||
|
||||
if (room == null) {
|
||||
gameClient.getHabbo().whisper("You need to be inside a room to use :wired.", RoomChatMessageBubbles.ALERT);
|
||||
return true;
|
||||
}
|
||||
|
||||
boolean hasRights = room.hasRights(gameClient.getHabbo())
|
||||
|| room.isOwner(gameClient.getHabbo())
|
||||
|| gameClient.getHabbo().hasPermission(Permission.ACC_ANYROOMOWNER);
|
||||
|
||||
if (!hasRights) {
|
||||
gameClient.getHabbo().whisper("You need room rights to open the Wired Creator Tools.", RoomChatMessageBubbles.ALERT);
|
||||
return true;
|
||||
}
|
||||
|
||||
gameClient.sendResponse(new InClientLinkComposer("wired-tools/show"));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -26,6 +26,7 @@ public class GameClient {
|
||||
private Habbo habbo;
|
||||
private boolean handshakeFinished;
|
||||
private String machineId = "";
|
||||
private String ssoTicket = "";
|
||||
|
||||
public final ConcurrentHashMap<Integer, Integer> incomingPacketCounter = new ConcurrentHashMap<>(25);
|
||||
public final ConcurrentHashMap<Class<? extends MessageHandler>, Long> messageTimestamps = new ConcurrentHashMap<>();
|
||||
@@ -82,6 +83,14 @@ public class GameClient {
|
||||
this.machineId = machineId;
|
||||
}
|
||||
|
||||
public String getSsoTicket() {
|
||||
return this.ssoTicket;
|
||||
}
|
||||
|
||||
public void setSsoTicket(String ssoTicket) {
|
||||
this.ssoTicket = ssoTicket != null ? ssoTicket : "";
|
||||
}
|
||||
|
||||
public void sendResponse(MessageComposer composer) {
|
||||
this.sendResponse(composer.compose());
|
||||
}
|
||||
@@ -145,9 +154,16 @@ public class GameClient {
|
||||
|
||||
if (this.habbo != null) {
|
||||
if (this.habbo.isOnline()) {
|
||||
// Try to park the habbo in the grace period instead of immediate disconnect
|
||||
boolean parked = SessionResumeManager.getInstance().parkHabbo(this.habbo, this.ssoTicket);
|
||||
|
||||
if (!parked) {
|
||||
// No grace period configured — immediate disconnect as before
|
||||
this.habbo.getHabboInfo().setOnline(false);
|
||||
this.habbo.disconnect();
|
||||
}
|
||||
// If parked, do NOT call disconnect() — the habbo stays in the room
|
||||
}
|
||||
|
||||
this.habbo = null;
|
||||
}
|
||||
|
||||
@@ -116,6 +116,22 @@ public class GameClientManager {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Find an existing GameClient that authenticated with the given SSO ticket.
|
||||
* Used to detect reconnections where the old connection hasn't been closed yet.
|
||||
*/
|
||||
public GameClient findClientBySsoTicket(String ssoTicket) {
|
||||
if (ssoTicket == null || ssoTicket.isEmpty()) return null;
|
||||
|
||||
for (GameClient client : this.clients.values()) {
|
||||
if (ssoTicket.equals(client.getSsoTicket()) && client.getHabbo() != null) {
|
||||
return client;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
public List<Habbo> getHabbosWithMachineId(String machineId) {
|
||||
List<Habbo> habbos = new ArrayList<>();
|
||||
|
||||
|
||||
@@ -0,0 +1,173 @@
|
||||
package com.eu.habbo.habbohotel.gameclients;
|
||||
|
||||
import com.eu.habbo.Emulator;
|
||||
import com.eu.habbo.habbohotel.users.Habbo;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
|
||||
/**
|
||||
* Manages a grace period for disconnected users. Instead of immediately
|
||||
* disposing a Habbo when their WebSocket drops, the Habbo is held in
|
||||
* a "ghost" state for a configurable number of seconds. If the same
|
||||
* user reconnects (via SSO ticket) within the grace window, their
|
||||
* existing Habbo object is resumed on the new connection — keeping
|
||||
* them in their room, preserving inventory state, etc.
|
||||
*
|
||||
* Config key: session.reconnect.grace.seconds (default: 30)
|
||||
*/
|
||||
public class SessionResumeManager {
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(SessionResumeManager.class);
|
||||
|
||||
private static SessionResumeManager instance;
|
||||
|
||||
private final ConcurrentHashMap<Integer, GhostSession> ghostSessions = new ConcurrentHashMap<>();
|
||||
|
||||
public static SessionResumeManager getInstance() {
|
||||
if (instance == null) {
|
||||
instance = new SessionResumeManager();
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
public int getGracePeriodSeconds() {
|
||||
return Emulator.getConfig().getInt("session.reconnect.grace.seconds", 30);
|
||||
}
|
||||
|
||||
/**
|
||||
* Park a disconnected Habbo in ghost mode. Their room presence is
|
||||
* preserved, but the old GameClient channel is closed.
|
||||
*
|
||||
* @return true if the habbo was parked (grace period > 0), false if immediate dispose should happen
|
||||
*/
|
||||
public boolean parkHabbo(Habbo habbo, String ssoTicket) {
|
||||
int graceSeconds = getGracePeriodSeconds();
|
||||
if (graceSeconds <= 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int userId = habbo.getHabboInfo().getId();
|
||||
|
||||
// Cancel any existing ghost session for this user
|
||||
GhostSession existing = ghostSessions.remove(userId);
|
||||
if (existing != null && existing.disposeFuture != null) {
|
||||
existing.disposeFuture.cancel(false);
|
||||
}
|
||||
|
||||
LOGGER.info("[SessionResume] Parking {} (id={}) for {}s grace period",
|
||||
habbo.getHabboInfo().getUsername(), userId, graceSeconds);
|
||||
|
||||
// Restore the SSO ticket so the client can reconnect with the same ticket
|
||||
if (ssoTicket != null && !ssoTicket.isEmpty()) {
|
||||
restoreSsoTicket(userId, ssoTicket);
|
||||
}
|
||||
|
||||
// Schedule the final disconnect after the grace period
|
||||
ScheduledFuture<?> future = Emulator.getThreading().run(() -> {
|
||||
GhostSession ghost = ghostSessions.remove(userId);
|
||||
if (ghost != null) {
|
||||
LOGGER.info("[SessionResume] Grace period expired for {} (id={}) - performing full disconnect",
|
||||
ghost.habbo.getHabboInfo().getUsername(), userId);
|
||||
performFullDisconnect(ghost.habbo);
|
||||
}
|
||||
}, graceSeconds * 1000);
|
||||
|
||||
ghostSessions.put(userId, new GhostSession(habbo, ssoTicket, future));
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Try to resume a ghost session for the given user ID.
|
||||
*
|
||||
* @return the parked Habbo if found within grace period, null otherwise
|
||||
*/
|
||||
public Habbo resumeSession(int userId) {
|
||||
GhostSession ghost = ghostSessions.remove(userId);
|
||||
if (ghost == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Cancel the scheduled dispose
|
||||
if (ghost.disposeFuture != null) {
|
||||
ghost.disposeFuture.cancel(false);
|
||||
}
|
||||
|
||||
LOGGER.info("[SessionResume] Resuming session for {} (id={})",
|
||||
ghost.habbo.getHabboInfo().getUsername(), userId);
|
||||
|
||||
return ghost.habbo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a user has a ghost session (is in grace period).
|
||||
*/
|
||||
public boolean hasGhostSession(int userId) {
|
||||
return ghostSessions.containsKey(userId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Immediately expire all ghost sessions (e.g. on emulator shutdown).
|
||||
*/
|
||||
public void disposeAll() {
|
||||
for (GhostSession ghost : ghostSessions.values()) {
|
||||
if (ghost.disposeFuture != null) {
|
||||
ghost.disposeFuture.cancel(false);
|
||||
}
|
||||
performFullDisconnect(ghost.habbo);
|
||||
}
|
||||
ghostSessions.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform the actual full disconnect that normally happens in Habbo.disconnect().
|
||||
*/
|
||||
private void performFullDisconnect(Habbo habbo) {
|
||||
try {
|
||||
habbo.getHabboInfo().setOnline(false);
|
||||
habbo.disconnect();
|
||||
} catch (Exception e) {
|
||||
LOGGER.error("[SessionResume] Error during deferred disconnect", e);
|
||||
}
|
||||
|
||||
// Clear the SSO ticket now that the grace period is truly over
|
||||
clearSsoTicket(habbo.getHabboInfo().getId());
|
||||
}
|
||||
|
||||
private void restoreSsoTicket(int userId, String ssoTicket) {
|
||||
try (var connection = Emulator.getDatabase().getDataSource().getConnection();
|
||||
var statement = connection.prepareStatement("UPDATE users SET auth_ticket = ? WHERE id = ? LIMIT 1")) {
|
||||
statement.setString(1, ssoTicket);
|
||||
statement.setInt(2, userId);
|
||||
statement.execute();
|
||||
LOGGER.info("[SessionResume] Restored SSO ticket for user {} during grace period", userId);
|
||||
} catch (Exception e) {
|
||||
LOGGER.error("[SessionResume] Failed to restore SSO ticket for user " + userId, e);
|
||||
}
|
||||
}
|
||||
|
||||
private void clearSsoTicket(int userId) {
|
||||
try (var connection = Emulator.getDatabase().getDataSource().getConnection();
|
||||
var statement = connection.prepareStatement("UPDATE users SET auth_ticket = ? WHERE id = ? LIMIT 1")) {
|
||||
statement.setString(1, "");
|
||||
statement.setInt(2, userId);
|
||||
statement.execute();
|
||||
} catch (Exception e) {
|
||||
LOGGER.error("[SessionResume] Failed to clear SSO ticket for user " + userId, e);
|
||||
}
|
||||
}
|
||||
|
||||
private static class GhostSession {
|
||||
final Habbo habbo;
|
||||
final String ssoTicket;
|
||||
final ScheduledFuture<?> disposeFuture;
|
||||
|
||||
GhostSession(Habbo habbo, String ssoTicket, ScheduledFuture<?> disposeFuture) {
|
||||
this.habbo = habbo;
|
||||
this.ssoTicket = ssoTicket;
|
||||
this.disposeFuture = disposeFuture;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -48,15 +48,11 @@ import com.eu.habbo.habbohotel.items.interactions.totems.InteractionTotemLegs;
|
||||
import com.eu.habbo.habbohotel.items.interactions.totems.InteractionTotemPlanet;
|
||||
import com.eu.habbo.habbohotel.items.interactions.wired.conditions.*;
|
||||
import com.eu.habbo.habbohotel.items.interactions.wired.effects.*;
|
||||
import com.eu.habbo.habbohotel.items.interactions.wired.selector.WiredEffectFurniArea;
|
||||
import com.eu.habbo.habbohotel.items.interactions.wired.selector.WiredEffectUsersArea;
|
||||
import com.eu.habbo.habbohotel.items.interactions.wired.selector.WiredEffectUsersNeighborhood;
|
||||
import com.eu.habbo.habbohotel.items.interactions.wired.selector.WiredEffectFurniNeighborhood;
|
||||
import com.eu.habbo.habbohotel.items.interactions.wired.selector.WiredEffectFurniByType;
|
||||
import com.eu.habbo.habbohotel.items.interactions.wired.extra.WiredBlob;
|
||||
import com.eu.habbo.habbohotel.items.interactions.wired.extra.WiredExtraOrEval;
|
||||
import com.eu.habbo.habbohotel.items.interactions.wired.extra.WiredExtraRandom;
|
||||
import com.eu.habbo.habbohotel.items.interactions.wired.extra.WiredExtraUnseen;
|
||||
import com.eu.habbo.habbohotel.items.interactions.wired.selector.*;
|
||||
import com.eu.habbo.habbohotel.items.interactions.wired.triggers.*;
|
||||
import com.eu.habbo.habbohotel.users.Habbo;
|
||||
import com.eu.habbo.habbohotel.users.HabboItem;
|
||||
@@ -202,16 +198,25 @@ public class ItemManager {
|
||||
this.interactionsList.add(new ItemInteraction("random_state", InteractionRandomState.class));
|
||||
this.interactionsList.add(new ItemInteraction("vendingmachine_no_sides", InteractionNoSidesVendingMachine.class));
|
||||
this.interactionsList.add(new ItemInteraction("tile_walkmagic", InteractionTileWalkMagic.class));
|
||||
this.interactionsList.add(new ItemInteraction("antenna", InteractionDefault.class));
|
||||
this.interactionsList.add(new ItemInteraction("room_invisible_click_tile", InteractionDefault.class));
|
||||
|
||||
this.interactionsList.add(new ItemInteraction("game_timer", InteractionGameTimer.class));
|
||||
|
||||
this.interactionsList.add(new ItemInteraction("wf_trg_walks_on_furni", WiredTriggerHabboWalkOnFurni.class));
|
||||
this.interactionsList.add(new ItemInteraction("wf_trg_walks_off_furni", WiredTriggerHabboWalkOffFurni.class));
|
||||
this.interactionsList.add(new ItemInteraction("wf_trg_click_furni", WiredTriggerHabboClicksFurni.class));
|
||||
this.interactionsList.add(new ItemInteraction("wf_trg_click_tile", WiredTriggerHabboClicksTile.class));
|
||||
this.interactionsList.add(new ItemInteraction("wf_trg_click_user", WiredTriggerHabboClicksUser.class));
|
||||
this.interactionsList.add(new ItemInteraction("wf_trg_user_performs_action", WiredTriggerHabboPerformsAction.class));
|
||||
this.interactionsList.add(new ItemInteraction("wf_trg_enter_room", WiredTriggerHabboEntersRoom.class));
|
||||
this.interactionsList.add(new ItemInteraction("wf_trg_leave_room", WiredTriggerHabboLeavesRoom.class));
|
||||
this.interactionsList.add(new ItemInteraction("wf_trg_says_something", WiredTriggerHabboSaysKeyword.class));
|
||||
this.interactionsList.add(new ItemInteraction("wf_trg_periodically", WiredTriggerRepeater.class));
|
||||
this.interactionsList.add(new ItemInteraction("wf_trg_period_short", WiredTriggerRepeaterShort.class));
|
||||
this.interactionsList.add(new ItemInteraction("wf_trg_period_long", WiredTriggerRepeaterLong.class));
|
||||
this.interactionsList.add(new ItemInteraction("wf_trg_state_changed", WiredTriggerFurniStateToggled.class));
|
||||
this.interactionsList.add(new ItemInteraction("wf_trg_stuff_state", WiredTriggerFurniStateToggled.class));
|
||||
this.interactionsList.add(new ItemInteraction("wf_trg_at_given_time", WiredTriggerAtSetTime.class));
|
||||
this.interactionsList.add(new ItemInteraction("wf_trg_at_time_long", WiredTriggerAtTimeLong.class));
|
||||
this.interactionsList.add(new ItemInteraction("wf_trg_collision", WiredTriggerCollision.class));
|
||||
@@ -255,6 +260,13 @@ public class ItemManager {
|
||||
this.interactionsList.add(new ItemInteraction("wf_act_alert", WiredEffectAlert.class));
|
||||
this.interactionsList.add(new ItemInteraction("wf_act_give_handitem", WiredEffectGiveHandItem.class));
|
||||
this.interactionsList.add(new ItemInteraction("wf_act_give_effect", WiredEffectGiveEffect.class));
|
||||
this.interactionsList.add(new ItemInteraction("wf_act_freeze", WiredEffectFreeze.class));
|
||||
this.interactionsList.add(new ItemInteraction("wf_act_unfreeze", WiredEffectUnfreeze.class));
|
||||
this.interactionsList.add(new ItemInteraction("wf_act_furni_to_user", WiredEffectFurniToUser.class));
|
||||
this.interactionsList.add(new ItemInteraction("wf_act_user_to_furni", WiredEffectUserToFurni.class));
|
||||
this.interactionsList.add(new ItemInteraction("wf_act_furni_to_furni", WiredEffectFurniToFurni.class));
|
||||
this.interactionsList.add(new ItemInteraction("wf_act_set_altitude", WiredEffectSetAltitude.class));
|
||||
this.interactionsList.add(new ItemInteraction("wf_act_rel_mov", WiredEffectRelativeMove.class));
|
||||
this.interactionsList.add(new ItemInteraction("wf_slc_furni_area", WiredEffectFurniArea.class));
|
||||
this.interactionsList.add(new ItemInteraction("wf_slc_furni_neighborhood", WiredEffectFurniNeighborhood.class));
|
||||
this.interactionsList.add(new ItemInteraction("wf_slc_furni_bytype", WiredEffectFurniByType.class));
|
||||
@@ -285,8 +297,19 @@ public class ItemManager {
|
||||
this.interactionsList.add(new ItemInteraction("wf_cnd_actor_in_team", WiredConditionTeamMember.class));
|
||||
this.interactionsList.add(new ItemInteraction("wf_cnd_trggrer_on_frn", WiredConditionTriggerOnFurni.class));
|
||||
this.interactionsList.add(new ItemInteraction("wf_cnd_has_handitem", WiredConditionHabboHasHandItem.class));
|
||||
this.interactionsList.add(new ItemInteraction("wf_cnd_not_has_handitem", WiredConditionNotHabboHasHandItem.class));
|
||||
this.interactionsList.add(new ItemInteraction("wf_cnd_date_rng_active", WiredConditionDateRangeActive.class));
|
||||
this.interactionsList.add(new ItemInteraction("wf_cnd_valid_moves", WiredConditionMovementValidation.class));
|
||||
// this.interactionsList.add(new ItemInteraction("wf_cnd_counter_time_matches", WiredConditionCounterTimeMatches.class));
|
||||
this.interactionsList.add(new ItemInteraction("wf_cnd_match_time", WiredConditionMatchTime.class));
|
||||
this.interactionsList.add(new ItemInteraction("wf_cnd_match_date", WiredConditionMatchDate.class));
|
||||
this.interactionsList.add(new ItemInteraction("wf_cnd_user_performs_action", WiredConditionUserPerformsAction.class));
|
||||
this.interactionsList.add(new ItemInteraction("wf_cnd_not_user_performs_action", WiredConditionNotUserPerformsAction.class));
|
||||
this.interactionsList.add(new ItemInteraction("wf_cnd_has_altitude", WiredConditionHasAltitude.class));
|
||||
this.interactionsList.add(new ItemInteraction("wf_cnd_triggerer_match", WiredConditionTriggererMatch.class));
|
||||
this.interactionsList.add(new ItemInteraction("wf_cnd_not_triggerer_match", WiredConditionNotTriggererMatch.class));
|
||||
this.interactionsList.add(new ItemInteraction("wf_cnd_team_has_score", WiredConditionTeamHasScore.class));
|
||||
this.interactionsList.add(new ItemInteraction("wf_cnd_team_has_rank", WiredConditionTeamHasRank.class));
|
||||
|
||||
|
||||
this.interactionsList.add(new ItemInteraction("wf_xtra_random", WiredExtraRandom.class));
|
||||
|
||||
+8
@@ -115,6 +115,14 @@ public class WiredConditionHabboHasHandItem extends InteractionWiredCondition {
|
||||
this.userSource = WiredSourceUtil.SOURCE_TRIGGER;
|
||||
}
|
||||
|
||||
protected int getHandItem() {
|
||||
return this.handItem;
|
||||
}
|
||||
|
||||
protected int getUserSource() {
|
||||
return this.userSource;
|
||||
}
|
||||
|
||||
static class JsonData {
|
||||
int handItemId;
|
||||
int userSource;
|
||||
|
||||
+285
@@ -0,0 +1,285 @@
|
||||
package com.eu.habbo.habbohotel.items.interactions.wired.conditions;
|
||||
|
||||
import com.eu.habbo.Emulator;
|
||||
import com.eu.habbo.habbohotel.items.Item;
|
||||
import com.eu.habbo.habbohotel.items.interactions.InteractionWiredCondition;
|
||||
import com.eu.habbo.habbohotel.items.interactions.wired.WiredSettings;
|
||||
import com.eu.habbo.habbohotel.rooms.Room;
|
||||
import com.eu.habbo.habbohotel.rooms.RoomUnit;
|
||||
import com.eu.habbo.habbohotel.users.HabboItem;
|
||||
import com.eu.habbo.habbohotel.wired.WiredConditionType;
|
||||
import com.eu.habbo.habbohotel.wired.core.WiredContext;
|
||||
import com.eu.habbo.habbohotel.wired.core.WiredManager;
|
||||
import com.eu.habbo.habbohotel.wired.core.WiredSourceUtil;
|
||||
import com.eu.habbo.messages.ServerMessage;
|
||||
import gnu.trove.set.hash.THashSet;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.math.RoundingMode;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class WiredConditionHasAltitude extends InteractionWiredCondition {
|
||||
private static final int COMPARISON_LESS = 0;
|
||||
private static final int COMPARISON_EQUAL = 1;
|
||||
private static final int COMPARISON_GREATER = 2;
|
||||
private static final int QUANTIFIER_ALL = 0;
|
||||
private static final int QUANTIFIER_ANY = 1;
|
||||
|
||||
public static final WiredConditionType type = WiredConditionType.HAS_ALTITUDE;
|
||||
|
||||
private final THashSet<HabboItem> items;
|
||||
private int comparison = COMPARISON_EQUAL;
|
||||
private double altitude = 0.0D;
|
||||
private int furniSource = WiredSourceUtil.SOURCE_TRIGGER;
|
||||
private int quantifier = QUANTIFIER_ALL;
|
||||
|
||||
public WiredConditionHasAltitude(ResultSet set, Item baseItem) throws SQLException {
|
||||
super(set, baseItem);
|
||||
this.items = new THashSet<>();
|
||||
}
|
||||
|
||||
public WiredConditionHasAltitude(int id, int userId, Item item, String extradata, int limitedStack, int limitedSells) {
|
||||
super(id, userId, item, extradata, limitedStack, limitedSells);
|
||||
this.items = new THashSet<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean evaluate(WiredContext ctx) {
|
||||
Room room = ctx.room();
|
||||
if (room == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
this.refresh(room);
|
||||
|
||||
List<HabboItem> targets = WiredSourceUtil.resolveItems(ctx, this.furniSource, this.items);
|
||||
if (targets.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (this.quantifier == QUANTIFIER_ANY) {
|
||||
return targets.stream().anyMatch(this::matchesAltitude);
|
||||
}
|
||||
|
||||
return targets.stream().allMatch(this::matchesAltitude);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
@Override
|
||||
public boolean execute(RoomUnit roomUnit, Room room, Object[] stuff) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getWiredData() {
|
||||
return WiredManager.getGson().toJson(new JsonData(
|
||||
this.comparison,
|
||||
this.formatAltitude(this.altitude),
|
||||
this.furniSource,
|
||||
this.quantifier,
|
||||
this.items.stream().map(HabboItem::getId).collect(Collectors.toList())
|
||||
));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadWiredData(ResultSet set, Room room) throws SQLException {
|
||||
this.items.clear();
|
||||
this.comparison = COMPARISON_EQUAL;
|
||||
this.altitude = 0.0D;
|
||||
this.furniSource = WiredSourceUtil.SOURCE_TRIGGER;
|
||||
this.quantifier = QUANTIFIER_ALL;
|
||||
|
||||
String wiredData = set.getString("wired_data");
|
||||
if (wiredData == null || !wiredData.startsWith("{")) {
|
||||
return;
|
||||
}
|
||||
|
||||
JsonData data = WiredManager.getGson().fromJson(wiredData, JsonData.class);
|
||||
if (data == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.comparison = this.normalizeComparison(data.comparison);
|
||||
this.altitude = this.parseAltitudeOrDefault(data.altitude);
|
||||
this.furniSource = this.normalizeFurniSource(data.furniSource);
|
||||
this.quantifier = this.normalizeQuantifier(data.quantifier);
|
||||
|
||||
if (data.itemIds == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (Integer id : data.itemIds) {
|
||||
HabboItem item = room.getHabboItem(id);
|
||||
if (item != null) {
|
||||
this.items.add(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPickUp() {
|
||||
this.items.clear();
|
||||
this.comparison = COMPARISON_EQUAL;
|
||||
this.altitude = 0.0D;
|
||||
this.furniSource = WiredSourceUtil.SOURCE_TRIGGER;
|
||||
this.quantifier = QUANTIFIER_ALL;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WiredConditionType getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void serializeWiredData(ServerMessage message, Room room) {
|
||||
this.refresh(room);
|
||||
|
||||
message.appendBoolean(false);
|
||||
message.appendInt(WiredManager.MAXIMUM_FURNI_SELECTION);
|
||||
message.appendInt(this.items.size());
|
||||
|
||||
for (HabboItem item : this.items) {
|
||||
message.appendInt(item.getId());
|
||||
}
|
||||
|
||||
message.appendInt(this.getBaseItem().getSpriteId());
|
||||
message.appendInt(this.getId());
|
||||
message.appendString(this.formatAltitude(this.altitude));
|
||||
message.appendInt(3);
|
||||
message.appendInt(this.comparison);
|
||||
message.appendInt(this.furniSource);
|
||||
message.appendInt(this.quantifier);
|
||||
message.appendInt(0);
|
||||
message.appendInt(this.getType().code);
|
||||
message.appendInt(0);
|
||||
message.appendInt(0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean saveData(WiredSettings settings) {
|
||||
int[] params = settings.getIntParams();
|
||||
this.comparison = (params.length > 0) ? this.normalizeComparison(params[0]) : COMPARISON_EQUAL;
|
||||
this.furniSource = (params.length > 1) ? this.normalizeFurniSource(params[1]) : WiredSourceUtil.SOURCE_TRIGGER;
|
||||
this.quantifier = (params.length > 2) ? this.normalizeQuantifier(params[2]) : QUANTIFIER_ALL;
|
||||
this.altitude = this.parseAltitudeOrDefault(settings.getStringParam());
|
||||
|
||||
int count = settings.getFurniIds().length;
|
||||
if (count > Emulator.getConfig().getInt("hotel.wired.furni.selection.count")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
this.items.clear();
|
||||
|
||||
if (this.furniSource == WiredSourceUtil.SOURCE_SELECTED) {
|
||||
Room room = Emulator.getGameEnvironment().getRoomManager().getRoom(this.getRoomId());
|
||||
if (room == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int itemId : settings.getFurniIds()) {
|
||||
HabboItem item = room.getHabboItem(itemId);
|
||||
if (item != null) {
|
||||
this.items.add(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean matchesAltitude(HabboItem item) {
|
||||
if (item == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
double normalizedAltitude = this.normalizeAltitude(item.getZ());
|
||||
|
||||
switch (this.comparison) {
|
||||
case COMPARISON_LESS:
|
||||
return normalizedAltitude < this.altitude;
|
||||
case COMPARISON_GREATER:
|
||||
return normalizedAltitude > this.altitude;
|
||||
default:
|
||||
return BigDecimal.valueOf(normalizedAltitude).compareTo(BigDecimal.valueOf(this.altitude)) == 0;
|
||||
}
|
||||
}
|
||||
|
||||
private void refresh(Room room) {
|
||||
THashSet<HabboItem> remove = new THashSet<>();
|
||||
|
||||
for (HabboItem item : this.items) {
|
||||
if (room.getHabboItem(item.getId()) == null) {
|
||||
remove.add(item);
|
||||
}
|
||||
}
|
||||
|
||||
for (HabboItem item : remove) {
|
||||
this.items.remove(item);
|
||||
}
|
||||
}
|
||||
|
||||
private int normalizeComparison(int value) {
|
||||
if (value < COMPARISON_LESS || value > COMPARISON_GREATER) {
|
||||
return COMPARISON_EQUAL;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
private int normalizeQuantifier(int value) {
|
||||
return (value == QUANTIFIER_ANY) ? QUANTIFIER_ANY : QUANTIFIER_ALL;
|
||||
}
|
||||
|
||||
private int normalizeFurniSource(int value) {
|
||||
switch (value) {
|
||||
case WiredSourceUtil.SOURCE_SELECTED:
|
||||
case WiredSourceUtil.SOURCE_SELECTOR:
|
||||
case WiredSourceUtil.SOURCE_SIGNAL:
|
||||
case WiredSourceUtil.SOURCE_TRIGGER:
|
||||
return value;
|
||||
default:
|
||||
return WiredSourceUtil.SOURCE_TRIGGER;
|
||||
}
|
||||
}
|
||||
|
||||
private double normalizeAltitude(double value) {
|
||||
double clampedValue = Math.max(0.0D, Math.min(Room.MAXIMUM_FURNI_HEIGHT, value));
|
||||
return BigDecimal.valueOf(clampedValue).setScale(2, RoundingMode.HALF_UP).doubleValue();
|
||||
}
|
||||
|
||||
private double parseAltitudeOrDefault(String value) {
|
||||
if (value == null || value.trim().isEmpty()) {
|
||||
return 0.0D;
|
||||
}
|
||||
|
||||
try {
|
||||
return this.normalizeAltitude(new BigDecimal(value.trim()).doubleValue());
|
||||
} catch (NumberFormatException exception) {
|
||||
return 0.0D;
|
||||
}
|
||||
}
|
||||
|
||||
private String formatAltitude(double value) {
|
||||
BigDecimal decimal = BigDecimal.valueOf(this.normalizeAltitude(value)).stripTrailingZeros();
|
||||
return (decimal.scale() < 0 ? decimal.setScale(0, RoundingMode.DOWN) : decimal).toPlainString();
|
||||
}
|
||||
|
||||
static class JsonData {
|
||||
int comparison;
|
||||
String altitude;
|
||||
int furniSource;
|
||||
int quantifier;
|
||||
List<Integer> itemIds;
|
||||
|
||||
public JsonData(int comparison, String altitude, int furniSource, int quantifier, List<Integer> itemIds) {
|
||||
this.comparison = comparison;
|
||||
this.altitude = altitude;
|
||||
this.furniSource = furniSource;
|
||||
this.quantifier = quantifier;
|
||||
this.itemIds = itemIds;
|
||||
}
|
||||
}
|
||||
}
|
||||
+253
@@ -0,0 +1,253 @@
|
||||
package com.eu.habbo.habbohotel.items.interactions.wired.conditions;
|
||||
|
||||
import com.eu.habbo.habbohotel.items.Item;
|
||||
import com.eu.habbo.habbohotel.items.interactions.InteractionWiredCondition;
|
||||
import com.eu.habbo.habbohotel.items.interactions.wired.WiredSettings;
|
||||
import com.eu.habbo.habbohotel.rooms.Room;
|
||||
import com.eu.habbo.habbohotel.rooms.RoomUnit;
|
||||
import com.eu.habbo.habbohotel.wired.WiredConditionType;
|
||||
import com.eu.habbo.habbohotel.wired.core.WiredContext;
|
||||
import com.eu.habbo.habbohotel.wired.core.WiredManager;
|
||||
import com.eu.habbo.messages.ServerMessage;
|
||||
import com.eu.habbo.util.HotelDateTimeUtil;
|
||||
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.time.LocalDate;
|
||||
|
||||
public class WiredConditionMatchDate extends InteractionWiredCondition {
|
||||
private static final int MODE_SKIP = 0;
|
||||
private static final int MODE_EXACT = 1;
|
||||
private static final int MODE_RANGE = 2;
|
||||
private static final int ALL_WEEKDAYS_MASK = createMask(1, 7);
|
||||
private static final int ALL_MONTHS_MASK = createMask(1, 12);
|
||||
|
||||
public static final WiredConditionType type = WiredConditionType.MATCH_DATE;
|
||||
|
||||
private int weekdayMask = ALL_WEEKDAYS_MASK;
|
||||
private int dayMode = MODE_SKIP;
|
||||
private int dayFrom = 1;
|
||||
private int dayTo = 31;
|
||||
private int monthMask = ALL_MONTHS_MASK;
|
||||
private int yearMode = MODE_SKIP;
|
||||
private int yearFrom = HotelDateTimeUtil.localDateNow().getYear();
|
||||
private int yearTo = HotelDateTimeUtil.localDateNow().getYear();
|
||||
|
||||
public WiredConditionMatchDate(ResultSet set, Item baseItem) throws SQLException {
|
||||
super(set, baseItem);
|
||||
}
|
||||
|
||||
public WiredConditionMatchDate(int id, int userId, Item item, String extradata, int limitedStack, int limitedSells) {
|
||||
super(id, userId, item, extradata, limitedStack, limitedSells);
|
||||
}
|
||||
|
||||
@Override
|
||||
public WiredConditionType getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void serializeWiredData(ServerMessage message, Room room) {
|
||||
message.appendBoolean(false);
|
||||
message.appendInt(5);
|
||||
message.appendInt(0);
|
||||
message.appendInt(this.getBaseItem().getSpriteId());
|
||||
message.appendInt(this.getId());
|
||||
message.appendString("");
|
||||
message.appendInt(8);
|
||||
message.appendInt(this.weekdayMask);
|
||||
message.appendInt(this.dayMode);
|
||||
message.appendInt(this.dayFrom);
|
||||
message.appendInt(this.dayTo);
|
||||
message.appendInt(this.monthMask);
|
||||
message.appendInt(this.yearMode);
|
||||
message.appendInt(this.yearFrom);
|
||||
message.appendInt(this.yearTo);
|
||||
message.appendInt(0);
|
||||
message.appendInt(this.getType().code);
|
||||
message.appendInt(0);
|
||||
message.appendInt(0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean saveData(WiredSettings settings) {
|
||||
int[] params = settings.getIntParams();
|
||||
|
||||
this.weekdayMask = (params.length > 0) ? this.normalizeWeekdayMask(params[0]) : ALL_WEEKDAYS_MASK;
|
||||
this.dayMode = (params.length > 1) ? this.normalizeMode(params[1]) : MODE_SKIP;
|
||||
this.dayFrom = (params.length > 2) ? this.normalizeDay(params[2]) : 1;
|
||||
this.dayTo = (params.length > 3) ? this.normalizeDay(params[3]) : this.dayFrom;
|
||||
this.monthMask = (params.length > 4) ? this.normalizeMonthMask(params[4]) : ALL_MONTHS_MASK;
|
||||
this.yearMode = (params.length > 5) ? this.normalizeMode(params[5]) : MODE_SKIP;
|
||||
this.yearFrom = (params.length > 6) ? this.normalizeYear(params[6]) : HotelDateTimeUtil.localDateNow().getYear();
|
||||
this.yearTo = (params.length > 7) ? this.normalizeYear(params[7]) : this.yearFrom;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean evaluate(WiredContext ctx) {
|
||||
LocalDate now = HotelDateTimeUtil.localDateNow();
|
||||
|
||||
return this.matchesMask(now.getDayOfWeek().getValue(), this.weekdayMask)
|
||||
&& this.matchesMask(now.getMonthValue(), this.monthMask)
|
||||
&& this.matchesDatePart(now.getDayOfMonth(), this.dayMode, this.dayFrom, this.dayTo)
|
||||
&& this.matchesDatePart(now.getYear(), this.yearMode, this.yearFrom, this.yearTo);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
@Override
|
||||
public boolean execute(RoomUnit roomUnit, Room room, Object[] stuff) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getWiredData() {
|
||||
return WiredManager.getGson().toJson(new JsonData(
|
||||
this.weekdayMask,
|
||||
this.dayMode,
|
||||
this.dayFrom,
|
||||
this.dayTo,
|
||||
this.monthMask,
|
||||
this.yearMode,
|
||||
this.yearFrom,
|
||||
this.yearTo
|
||||
));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadWiredData(ResultSet set, Room room) throws SQLException {
|
||||
this.reset();
|
||||
|
||||
String wiredData = set.getString("wired_data");
|
||||
if (wiredData == null || wiredData.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (wiredData.startsWith("{")) {
|
||||
JsonData data = WiredManager.getGson().fromJson(wiredData, JsonData.class);
|
||||
if (data == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.weekdayMask = this.normalizeWeekdayMask(data.weekdayMask);
|
||||
this.dayMode = this.normalizeMode(data.dayMode);
|
||||
this.dayFrom = this.normalizeDay(data.dayFrom);
|
||||
this.dayTo = this.normalizeDay(data.dayTo);
|
||||
this.monthMask = this.normalizeMonthMask(data.monthMask);
|
||||
this.yearMode = this.normalizeMode(data.yearMode);
|
||||
this.yearFrom = this.normalizeYear(data.yearFrom);
|
||||
this.yearTo = this.normalizeYear(data.yearTo);
|
||||
return;
|
||||
}
|
||||
|
||||
String[] data = wiredData.split("\t");
|
||||
if (data.length != 8) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
this.weekdayMask = this.normalizeWeekdayMask(Integer.parseInt(data[0]));
|
||||
this.dayMode = this.normalizeMode(Integer.parseInt(data[1]));
|
||||
this.dayFrom = this.normalizeDay(Integer.parseInt(data[2]));
|
||||
this.dayTo = this.normalizeDay(Integer.parseInt(data[3]));
|
||||
this.monthMask = this.normalizeMonthMask(Integer.parseInt(data[4]));
|
||||
this.yearMode = this.normalizeMode(Integer.parseInt(data[5]));
|
||||
this.yearFrom = this.normalizeYear(Integer.parseInt(data[6]));
|
||||
this.yearTo = this.normalizeYear(Integer.parseInt(data[7]));
|
||||
} catch (NumberFormatException ignored) {
|
||||
this.reset();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPickUp() {
|
||||
this.reset();
|
||||
}
|
||||
|
||||
private void reset() {
|
||||
int currentYear = HotelDateTimeUtil.localDateNow().getYear();
|
||||
|
||||
this.weekdayMask = ALL_WEEKDAYS_MASK;
|
||||
this.dayMode = MODE_SKIP;
|
||||
this.dayFrom = 1;
|
||||
this.dayTo = 31;
|
||||
this.monthMask = ALL_MONTHS_MASK;
|
||||
this.yearMode = MODE_SKIP;
|
||||
this.yearFrom = currentYear;
|
||||
this.yearTo = currentYear;
|
||||
}
|
||||
|
||||
private boolean matchesMask(int value, int mask) {
|
||||
return (mask & (1 << value)) != 0;
|
||||
}
|
||||
|
||||
private boolean matchesDatePart(int currentValue, int mode, int fromValue, int toValue) {
|
||||
switch (mode) {
|
||||
case MODE_EXACT:
|
||||
return currentValue == fromValue;
|
||||
case MODE_RANGE:
|
||||
return currentValue >= Math.min(fromValue, toValue) && currentValue <= Math.max(fromValue, toValue);
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
private int normalizeMode(int value) {
|
||||
if (value < MODE_SKIP || value > MODE_RANGE) {
|
||||
return MODE_SKIP;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
private int normalizeDay(int value) {
|
||||
return Math.max(1, Math.min(31, value));
|
||||
}
|
||||
|
||||
private int normalizeYear(int value) {
|
||||
return Math.max(1, Math.min(9999, value));
|
||||
}
|
||||
|
||||
private int normalizeWeekdayMask(int value) {
|
||||
int normalized = value & ALL_WEEKDAYS_MASK;
|
||||
return (normalized == 0) ? ALL_WEEKDAYS_MASK : normalized;
|
||||
}
|
||||
|
||||
private int normalizeMonthMask(int value) {
|
||||
int normalized = value & ALL_MONTHS_MASK;
|
||||
return (normalized == 0) ? ALL_MONTHS_MASK : normalized;
|
||||
}
|
||||
|
||||
private static int createMask(int startValue, int endValue) {
|
||||
int mask = 0;
|
||||
|
||||
for (int value = startValue; value <= endValue; value++) {
|
||||
mask |= (1 << value);
|
||||
}
|
||||
|
||||
return mask;
|
||||
}
|
||||
|
||||
static class JsonData {
|
||||
int weekdayMask;
|
||||
int dayMode;
|
||||
int dayFrom;
|
||||
int dayTo;
|
||||
int monthMask;
|
||||
int yearMode;
|
||||
int yearFrom;
|
||||
int yearTo;
|
||||
|
||||
public JsonData(int weekdayMask, int dayMode, int dayFrom, int dayTo, int monthMask, int yearMode, int yearFrom, int yearTo) {
|
||||
this.weekdayMask = weekdayMask;
|
||||
this.dayMode = dayMode;
|
||||
this.dayFrom = dayFrom;
|
||||
this.dayTo = dayTo;
|
||||
this.monthMask = monthMask;
|
||||
this.yearMode = yearMode;
|
||||
this.yearFrom = yearFrom;
|
||||
this.yearTo = yearTo;
|
||||
}
|
||||
}
|
||||
}
|
||||
+48
-49
@@ -19,9 +19,7 @@ import gnu.trove.set.hash.THashSet;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
public class WiredConditionMatchStatePosition extends InteractionWiredCondition implements InteractionWiredMatchFurniSettings {
|
||||
public static final WiredConditionType type = WiredConditionType.MATCH_SSHOT;
|
||||
@@ -92,7 +90,6 @@ public class WiredConditionMatchStatePosition extends InteractionWiredCondition
|
||||
|
||||
this.settings.clear();
|
||||
|
||||
if (this.furniSource == WiredSourceUtil.SOURCE_SELECTED) {
|
||||
for (int i = 0; i < count; i++) {
|
||||
int itemId = settings.getFurniIds()[i];
|
||||
HabboItem item = room.getHabboItem(itemId);
|
||||
@@ -100,7 +97,6 @@ public class WiredConditionMatchStatePosition extends InteractionWiredCondition
|
||||
if (item != null)
|
||||
this.settings.add(new WiredMatchFurniSetting(item.getId(), item.getExtradata(), item.getRotation(), item.getX(), item.getY()));
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -108,65 +104,71 @@ public class WiredConditionMatchStatePosition extends InteractionWiredCondition
|
||||
@Override
|
||||
public boolean evaluate(WiredContext ctx) {
|
||||
Room room = ctx.room();
|
||||
this.refresh();
|
||||
|
||||
if (this.settings.isEmpty())
|
||||
return true;
|
||||
|
||||
List<HabboItem> targets = null;
|
||||
Set<Integer> targetIds = null;
|
||||
|
||||
if (this.furniSource != WiredSourceUtil.SOURCE_SELECTED) {
|
||||
targets = WiredSourceUtil.resolveItems(ctx, this.furniSource, null);
|
||||
List<HabboItem> targets = WiredSourceUtil.resolveItems(ctx, this.furniSource, null);
|
||||
if (targets.isEmpty()) return false;
|
||||
targetIds = new HashSet<>();
|
||||
|
||||
for (HabboItem item : targets) {
|
||||
if (item != null) targetIds.add(item.getId());
|
||||
}
|
||||
if (targetIds.isEmpty()) return false;
|
||||
}
|
||||
if (item == null) return false;
|
||||
|
||||
THashSet<WiredMatchFurniSetting> toRemove = new THashSet<>();
|
||||
Set<Integer> settingsIds = new HashSet<>();
|
||||
|
||||
for (WiredMatchFurniSetting setting : this.settings) {
|
||||
if (targetIds != null && !targetIds.contains(setting.item_id)) {
|
||||
continue;
|
||||
}
|
||||
HabboItem item = room.getHabboItem(setting.item_id);
|
||||
|
||||
if (item != null) {
|
||||
settingsIds.add(setting.item_id);
|
||||
if (this.state) {
|
||||
if (!item.getExtradata().equals(setting.state))
|
||||
WiredMatchFurniSetting setting = this.resolveSettingForTarget(room, item);
|
||||
if (setting == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (this.position) {
|
||||
if (!(setting.x == item.getX() && setting.y == item.getY()))
|
||||
if (!this.matchesSetting(item, setting)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (this.direction) {
|
||||
if (setting.rotation != item.getRotation())
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
toRemove.add(setting);
|
||||
}
|
||||
}
|
||||
|
||||
if (targetIds != null && !settingsIds.containsAll(targetIds)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!toRemove.isEmpty()) {
|
||||
for (WiredMatchFurniSetting setting : toRemove) {
|
||||
this.settings.remove(setting);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
for (WiredMatchFurniSetting setting : this.settings) {
|
||||
HabboItem item = room.getHabboItem(setting.item_id);
|
||||
if (item == null) continue;
|
||||
if (!this.matchesSetting(item, setting))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private WiredMatchFurniSetting resolveSettingForTarget(Room room, HabboItem target) {
|
||||
WiredMatchFurniSetting fallback = null;
|
||||
|
||||
for (WiredMatchFurniSetting setting : this.settings) {
|
||||
HabboItem sourceItem = room.getHabboItem(setting.item_id);
|
||||
if (sourceItem == null) continue;
|
||||
if (sourceItem.getBaseItem().getId() != target.getBaseItem().getId()) continue;
|
||||
|
||||
if (setting.state.equals(target.getExtradata())) {
|
||||
return setting;
|
||||
}
|
||||
|
||||
if (fallback == null) {
|
||||
fallback = setting;
|
||||
}
|
||||
}
|
||||
|
||||
return fallback;
|
||||
}
|
||||
|
||||
private boolean matchesSetting(HabboItem item, WiredMatchFurniSetting setting) {
|
||||
if (this.state && !item.getExtradata().equals(setting.state))
|
||||
return false;
|
||||
|
||||
if (this.position && !(setting.x == item.getX() && setting.y == item.getY()))
|
||||
return false;
|
||||
|
||||
return !this.direction || setting.rotation == item.getRotation();
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
@Override
|
||||
public boolean execute(RoomUnit roomUnit, Room room, Object[] stuff) {
|
||||
@@ -214,9 +216,6 @@ public class WiredConditionMatchStatePosition extends InteractionWiredCondition
|
||||
this.position = data[4].equals("1");
|
||||
this.furniSource = this.settings.isEmpty() ? WiredSourceUtil.SOURCE_TRIGGER : WiredSourceUtil.SOURCE_SELECTED;
|
||||
}
|
||||
if (this.furniSource == WiredSourceUtil.SOURCE_TRIGGER && !this.settings.isEmpty()) {
|
||||
this.furniSource = WiredSourceUtil.SOURCE_SELECTED;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+237
@@ -0,0 +1,237 @@
|
||||
package com.eu.habbo.habbohotel.items.interactions.wired.conditions;
|
||||
|
||||
import com.eu.habbo.habbohotel.items.Item;
|
||||
import com.eu.habbo.habbohotel.items.interactions.InteractionWiredCondition;
|
||||
import com.eu.habbo.habbohotel.items.interactions.wired.WiredSettings;
|
||||
import com.eu.habbo.habbohotel.rooms.Room;
|
||||
import com.eu.habbo.habbohotel.rooms.RoomUnit;
|
||||
import com.eu.habbo.habbohotel.wired.WiredConditionType;
|
||||
import com.eu.habbo.habbohotel.wired.core.WiredContext;
|
||||
import com.eu.habbo.habbohotel.wired.core.WiredManager;
|
||||
import com.eu.habbo.messages.ServerMessage;
|
||||
import com.eu.habbo.util.HotelDateTimeUtil;
|
||||
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.time.LocalTime;
|
||||
|
||||
public class WiredConditionMatchTime extends InteractionWiredCondition {
|
||||
private static final int MODE_SKIP = 0;
|
||||
private static final int MODE_EXACT = 1;
|
||||
private static final int MODE_RANGE = 2;
|
||||
|
||||
public static final WiredConditionType type = WiredConditionType.MATCH_TIME;
|
||||
|
||||
private int hourMode = MODE_SKIP;
|
||||
private int hourFrom = 0;
|
||||
private int hourTo = 0;
|
||||
private int minuteMode = MODE_SKIP;
|
||||
private int minuteFrom = 0;
|
||||
private int minuteTo = 0;
|
||||
private int secondMode = MODE_SKIP;
|
||||
private int secondFrom = 0;
|
||||
private int secondTo = 0;
|
||||
|
||||
public WiredConditionMatchTime(ResultSet set, Item baseItem) throws SQLException {
|
||||
super(set, baseItem);
|
||||
}
|
||||
|
||||
public WiredConditionMatchTime(int id, int userId, Item item, String extradata, int limitedStack, int limitedSells) {
|
||||
super(id, userId, item, extradata, limitedStack, limitedSells);
|
||||
}
|
||||
|
||||
@Override
|
||||
public WiredConditionType getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void serializeWiredData(ServerMessage message, Room room) {
|
||||
message.appendBoolean(false);
|
||||
message.appendInt(5);
|
||||
message.appendInt(0);
|
||||
message.appendInt(this.getBaseItem().getSpriteId());
|
||||
message.appendInt(this.getId());
|
||||
message.appendString("");
|
||||
message.appendInt(9);
|
||||
message.appendInt(this.hourMode);
|
||||
message.appendInt(this.hourFrom);
|
||||
message.appendInt(this.hourTo);
|
||||
message.appendInt(this.minuteMode);
|
||||
message.appendInt(this.minuteFrom);
|
||||
message.appendInt(this.minuteTo);
|
||||
message.appendInt(this.secondMode);
|
||||
message.appendInt(this.secondFrom);
|
||||
message.appendInt(this.secondTo);
|
||||
message.appendInt(0);
|
||||
message.appendInt(this.getType().code);
|
||||
message.appendInt(0);
|
||||
message.appendInt(0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean saveData(WiredSettings settings) {
|
||||
int[] params = settings.getIntParams();
|
||||
|
||||
this.hourMode = (params.length > 0) ? this.normalizeMode(params[0]) : MODE_SKIP;
|
||||
this.hourFrom = (params.length > 1) ? this.normalizeHour(params[1]) : 0;
|
||||
this.hourTo = (params.length > 2) ? this.normalizeHour(params[2]) : this.hourFrom;
|
||||
this.minuteMode = (params.length > 3) ? this.normalizeMode(params[3]) : MODE_SKIP;
|
||||
this.minuteFrom = (params.length > 4) ? this.normalizeMinuteOrSecond(params[4]) : 0;
|
||||
this.minuteTo = (params.length > 5) ? this.normalizeMinuteOrSecond(params[5]) : this.minuteFrom;
|
||||
this.secondMode = (params.length > 6) ? this.normalizeMode(params[6]) : MODE_SKIP;
|
||||
this.secondFrom = (params.length > 7) ? this.normalizeMinuteOrSecond(params[7]) : 0;
|
||||
this.secondTo = (params.length > 8) ? this.normalizeMinuteOrSecond(params[8]) : this.secondFrom;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean evaluate(WiredContext ctx) {
|
||||
LocalTime now = HotelDateTimeUtil.localTimeNow();
|
||||
|
||||
return this.matchesTimePart(now.getHour(), this.hourMode, this.hourFrom, this.hourTo)
|
||||
&& this.matchesTimePart(now.getMinute(), this.minuteMode, this.minuteFrom, this.minuteTo)
|
||||
&& this.matchesTimePart(now.getSecond(), this.secondMode, this.secondFrom, this.secondTo);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
@Override
|
||||
public boolean execute(RoomUnit roomUnit, Room room, Object[] stuff) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getWiredData() {
|
||||
return WiredManager.getGson().toJson(new JsonData(
|
||||
this.hourMode,
|
||||
this.hourFrom,
|
||||
this.hourTo,
|
||||
this.minuteMode,
|
||||
this.minuteFrom,
|
||||
this.minuteTo,
|
||||
this.secondMode,
|
||||
this.secondFrom,
|
||||
this.secondTo
|
||||
));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadWiredData(ResultSet set, Room room) throws SQLException {
|
||||
this.reset();
|
||||
|
||||
String wiredData = set.getString("wired_data");
|
||||
if (wiredData == null || wiredData.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (wiredData.startsWith("{")) {
|
||||
JsonData data = WiredManager.getGson().fromJson(wiredData, JsonData.class);
|
||||
if (data == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.hourMode = this.normalizeMode(data.hourMode);
|
||||
this.hourFrom = this.normalizeHour(data.hourFrom);
|
||||
this.hourTo = this.normalizeHour(data.hourTo);
|
||||
this.minuteMode = this.normalizeMode(data.minuteMode);
|
||||
this.minuteFrom = this.normalizeMinuteOrSecond(data.minuteFrom);
|
||||
this.minuteTo = this.normalizeMinuteOrSecond(data.minuteTo);
|
||||
this.secondMode = this.normalizeMode(data.secondMode);
|
||||
this.secondFrom = this.normalizeMinuteOrSecond(data.secondFrom);
|
||||
this.secondTo = this.normalizeMinuteOrSecond(data.secondTo);
|
||||
return;
|
||||
}
|
||||
|
||||
String[] data = wiredData.split("\t");
|
||||
if (data.length != 9) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
this.hourMode = this.normalizeMode(Integer.parseInt(data[0]));
|
||||
this.hourFrom = this.normalizeHour(Integer.parseInt(data[1]));
|
||||
this.hourTo = this.normalizeHour(Integer.parseInt(data[2]));
|
||||
this.minuteMode = this.normalizeMode(Integer.parseInt(data[3]));
|
||||
this.minuteFrom = this.normalizeMinuteOrSecond(Integer.parseInt(data[4]));
|
||||
this.minuteTo = this.normalizeMinuteOrSecond(Integer.parseInt(data[5]));
|
||||
this.secondMode = this.normalizeMode(Integer.parseInt(data[6]));
|
||||
this.secondFrom = this.normalizeMinuteOrSecond(Integer.parseInt(data[7]));
|
||||
this.secondTo = this.normalizeMinuteOrSecond(Integer.parseInt(data[8]));
|
||||
} catch (NumberFormatException ignored) {
|
||||
this.reset();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPickUp() {
|
||||
this.reset();
|
||||
}
|
||||
|
||||
private void reset() {
|
||||
this.hourMode = MODE_SKIP;
|
||||
this.hourFrom = 0;
|
||||
this.hourTo = 0;
|
||||
this.minuteMode = MODE_SKIP;
|
||||
this.minuteFrom = 0;
|
||||
this.minuteTo = 0;
|
||||
this.secondMode = MODE_SKIP;
|
||||
this.secondFrom = 0;
|
||||
this.secondTo = 0;
|
||||
}
|
||||
|
||||
private boolean matchesTimePart(int currentValue, int mode, int fromValue, int toValue) {
|
||||
switch (mode) {
|
||||
case MODE_EXACT:
|
||||
return currentValue == fromValue;
|
||||
case MODE_RANGE:
|
||||
if (fromValue <= toValue) {
|
||||
return currentValue >= fromValue && currentValue <= toValue;
|
||||
}
|
||||
|
||||
return currentValue >= fromValue || currentValue <= toValue;
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
private int normalizeMode(int value) {
|
||||
if (value < MODE_SKIP || value > MODE_RANGE) {
|
||||
return MODE_SKIP;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
private int normalizeHour(int value) {
|
||||
return Math.max(0, Math.min(23, value));
|
||||
}
|
||||
|
||||
private int normalizeMinuteOrSecond(int value) {
|
||||
return Math.max(0, Math.min(59, value));
|
||||
}
|
||||
|
||||
static class JsonData {
|
||||
int hourMode;
|
||||
int hourFrom;
|
||||
int hourTo;
|
||||
int minuteMode;
|
||||
int minuteFrom;
|
||||
int minuteTo;
|
||||
int secondMode;
|
||||
int secondFrom;
|
||||
int secondTo;
|
||||
|
||||
public JsonData(int hourMode, int hourFrom, int hourTo, int minuteMode, int minuteFrom, int minuteTo, int secondMode, int secondFrom, int secondTo) {
|
||||
this.hourMode = hourMode;
|
||||
this.hourFrom = hourFrom;
|
||||
this.hourTo = hourTo;
|
||||
this.minuteMode = minuteMode;
|
||||
this.minuteFrom = minuteFrom;
|
||||
this.minuteTo = minuteTo;
|
||||
this.secondMode = secondMode;
|
||||
this.secondFrom = secondFrom;
|
||||
this.secondTo = secondTo;
|
||||
}
|
||||
}
|
||||
}
|
||||
+42
@@ -0,0 +1,42 @@
|
||||
package com.eu.habbo.habbohotel.items.interactions.wired.conditions;
|
||||
|
||||
import com.eu.habbo.habbohotel.items.Item;
|
||||
import com.eu.habbo.habbohotel.rooms.RoomUnit;
|
||||
import com.eu.habbo.habbohotel.wired.WiredConditionType;
|
||||
import com.eu.habbo.habbohotel.wired.core.WiredContext;
|
||||
import com.eu.habbo.habbohotel.wired.core.WiredSourceUtil;
|
||||
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.List;
|
||||
|
||||
public class WiredConditionNotHabboHasHandItem extends WiredConditionHabboHasHandItem {
|
||||
public static final WiredConditionType type = WiredConditionType.NOT_ACTOR_HAS_HANDITEM;
|
||||
|
||||
public WiredConditionNotHabboHasHandItem(ResultSet set, Item baseItem) throws SQLException {
|
||||
super(set, baseItem);
|
||||
}
|
||||
|
||||
public WiredConditionNotHabboHasHandItem(int id, int userId, Item item, String extradata, int limitedStack, int limitedSells) {
|
||||
super(id, userId, item, extradata, limitedStack, limitedSells);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean evaluate(WiredContext ctx) {
|
||||
List<RoomUnit> targets = WiredSourceUtil.resolveUsers(ctx, this.getUserSource());
|
||||
if (targets.isEmpty()) return false;
|
||||
|
||||
for (RoomUnit roomUnit : targets) {
|
||||
if (roomUnit == null || roomUnit.getHandItem() == this.getHandItem()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WiredConditionType getType() {
|
||||
return type;
|
||||
}
|
||||
}
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
package com.eu.habbo.habbohotel.items.interactions.wired.conditions;
|
||||
|
||||
import com.eu.habbo.habbohotel.items.Item;
|
||||
import com.eu.habbo.habbohotel.wired.WiredConditionType;
|
||||
import com.eu.habbo.habbohotel.wired.core.WiredContext;
|
||||
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
|
||||
public class WiredConditionNotTriggererMatch extends WiredConditionTriggererMatch {
|
||||
public static final WiredConditionType type = WiredConditionType.NOT_TRIGGERER_MATCH;
|
||||
|
||||
public WiredConditionNotTriggererMatch(ResultSet set, Item baseItem) throws SQLException {
|
||||
super(set, baseItem);
|
||||
}
|
||||
|
||||
public WiredConditionNotTriggererMatch(int id, int userId, Item item, String extradata, int limitedStack, int limitedSells) {
|
||||
super(id, userId, item, extradata, limitedStack, limitedSells);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean evaluate(WiredContext ctx) {
|
||||
MatchResult result = this.evaluateMatch(ctx);
|
||||
return result.valid && !result.matched;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WiredConditionType getType() {
|
||||
return type;
|
||||
}
|
||||
}
|
||||
+46
@@ -0,0 +1,46 @@
|
||||
package com.eu.habbo.habbohotel.items.interactions.wired.conditions;
|
||||
|
||||
import com.eu.habbo.habbohotel.items.Item;
|
||||
import com.eu.habbo.habbohotel.rooms.Room;
|
||||
import com.eu.habbo.habbohotel.rooms.RoomUnit;
|
||||
import com.eu.habbo.habbohotel.wired.WiredConditionType;
|
||||
import com.eu.habbo.habbohotel.wired.core.WiredContext;
|
||||
import com.eu.habbo.habbohotel.wired.core.WiredSourceUtil;
|
||||
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.List;
|
||||
|
||||
public class WiredConditionNotUserPerformsAction extends WiredConditionUserPerformsAction {
|
||||
private static final int QUANTIFIER_ANY_NOT_MATCH = 0;
|
||||
private static final int QUANTIFIER_NONE_MATCH = 1;
|
||||
|
||||
public static final WiredConditionType type = WiredConditionType.NOT_USER_PERFORMS_ACTION;
|
||||
|
||||
public WiredConditionNotUserPerformsAction(ResultSet set, Item baseItem) throws SQLException {
|
||||
super(set, baseItem);
|
||||
}
|
||||
|
||||
public WiredConditionNotUserPerformsAction(int id, int userId, Item item, String extradata, int limitedStack, int limitedSells) {
|
||||
super(id, userId, item, extradata, limitedStack, limitedSells);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean evaluate(WiredContext ctx) {
|
||||
List<RoomUnit> targets = WiredSourceUtil.resolveUsers(ctx, this.getUserSource());
|
||||
if (targets.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (this.getQuantifier() == QUANTIFIER_NONE_MATCH) {
|
||||
return targets.stream().noneMatch(roomUnit -> this.matchesAction(ctx, roomUnit));
|
||||
}
|
||||
|
||||
return targets.stream().anyMatch(roomUnit -> !this.matchesAction(ctx, roomUnit));
|
||||
}
|
||||
|
||||
@Override
|
||||
public WiredConditionType getType() {
|
||||
return type;
|
||||
}
|
||||
}
|
||||
+197
@@ -0,0 +1,197 @@
|
||||
package com.eu.habbo.habbohotel.items.interactions.wired.conditions;
|
||||
|
||||
import com.eu.habbo.habbohotel.games.Game;
|
||||
import com.eu.habbo.habbohotel.games.GameState;
|
||||
import com.eu.habbo.habbohotel.games.GameTeam;
|
||||
import com.eu.habbo.habbohotel.games.GameTeamColors;
|
||||
import com.eu.habbo.habbohotel.games.battlebanzai.BattleBanzaiGame;
|
||||
import com.eu.habbo.habbohotel.games.freeze.FreezeGame;
|
||||
import com.eu.habbo.habbohotel.items.Item;
|
||||
import com.eu.habbo.habbohotel.items.interactions.InteractionWiredCondition;
|
||||
import com.eu.habbo.habbohotel.rooms.Room;
|
||||
import com.eu.habbo.habbohotel.rooms.RoomUnit;
|
||||
import com.eu.habbo.habbohotel.users.Habbo;
|
||||
import com.eu.habbo.habbohotel.wired.core.WiredContext;
|
||||
import com.eu.habbo.habbohotel.wired.core.WiredSourceUtil;
|
||||
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
abstract class WiredConditionTeamGameBase extends InteractionWiredCondition {
|
||||
protected static final int QUANTIFIER_ALL = 0;
|
||||
protected static final int QUANTIFIER_ANY = 1;
|
||||
protected static final int COMPARISON_LOWER = 0;
|
||||
protected static final int COMPARISON_EQUAL = 1;
|
||||
protected static final int COMPARISON_HIGHER = 2;
|
||||
protected static final int TEAM_TRIGGERER = 0;
|
||||
|
||||
private static final GameTeamColors[] SUPPORTED_TEAM_COLORS = new GameTeamColors[] {
|
||||
GameTeamColors.RED,
|
||||
GameTeamColors.GREEN,
|
||||
GameTeamColors.BLUE,
|
||||
GameTeamColors.YELLOW
|
||||
};
|
||||
|
||||
protected WiredConditionTeamGameBase(ResultSet set, Item baseItem) throws SQLException {
|
||||
super(set, baseItem);
|
||||
}
|
||||
|
||||
protected WiredConditionTeamGameBase(int id, int userId, Item item, String extradata, int limitedStack, int limitedSells) {
|
||||
super(id, userId, item, extradata, limitedStack, limitedSells);
|
||||
}
|
||||
|
||||
protected List<RoomUnit> resolveUsers(WiredContext ctx, int userSource) {
|
||||
Map<Integer, RoomUnit> deduplicated = new LinkedHashMap<>();
|
||||
|
||||
for (RoomUnit roomUnit : WiredSourceUtil.resolveUsers(ctx, userSource)) {
|
||||
if (roomUnit != null) {
|
||||
deduplicated.putIfAbsent(roomUnit.getId(), roomUnit);
|
||||
}
|
||||
}
|
||||
|
||||
return new ArrayList<>(deduplicated.values());
|
||||
}
|
||||
|
||||
protected boolean matchesQuantifier(List<RoomUnit> users, int quantifier, Predicate<RoomUnit> predicate) {
|
||||
if (users.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (quantifier == QUANTIFIER_ANY) {
|
||||
return users.stream().anyMatch(predicate);
|
||||
}
|
||||
|
||||
return users.stream().allMatch(predicate);
|
||||
}
|
||||
|
||||
protected int normalizeQuantifier(int value) {
|
||||
return (value == QUANTIFIER_ANY) ? QUANTIFIER_ANY : QUANTIFIER_ALL;
|
||||
}
|
||||
|
||||
protected int normalizeComparison(int value) {
|
||||
switch (value) {
|
||||
case COMPARISON_LOWER:
|
||||
case COMPARISON_HIGHER:
|
||||
return value;
|
||||
default:
|
||||
return COMPARISON_EQUAL;
|
||||
}
|
||||
}
|
||||
|
||||
protected int normalizeUserSource(int value) {
|
||||
switch (value) {
|
||||
case WiredSourceUtil.SOURCE_SELECTOR:
|
||||
case WiredSourceUtil.SOURCE_SIGNAL:
|
||||
case WiredSourceUtil.SOURCE_TRIGGER:
|
||||
return value;
|
||||
default:
|
||||
return WiredSourceUtil.SOURCE_TRIGGER;
|
||||
}
|
||||
}
|
||||
|
||||
protected int normalizePlacement(int value) {
|
||||
if (value < 1 || value > 4) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
protected int normalizeScore(int value) {
|
||||
return Math.max(0, value);
|
||||
}
|
||||
|
||||
protected int normalizeExplicitTeamType(int value) {
|
||||
GameTeamColors color = GameTeamColors.fromType(value);
|
||||
return (color.type >= GameTeamColors.RED.type && color.type <= GameTeamColors.YELLOW.type)
|
||||
? color.type
|
||||
: GameTeamColors.RED.type;
|
||||
}
|
||||
|
||||
protected int normalizeRankTeamType(int value) {
|
||||
if (value == TEAM_TRIGGERER) {
|
||||
return TEAM_TRIGGERER;
|
||||
}
|
||||
|
||||
return this.normalizeExplicitTeamType(value);
|
||||
}
|
||||
|
||||
protected GameTeamColors resolveConfiguredTeamColor(int value) {
|
||||
return GameTeamColors.fromType(this.normalizeExplicitTeamType(value));
|
||||
}
|
||||
|
||||
protected boolean compareValue(int actual, int expected, int comparison) {
|
||||
switch (comparison) {
|
||||
case COMPARISON_LOWER:
|
||||
return actual < expected;
|
||||
case COMPARISON_HIGHER:
|
||||
return actual > expected;
|
||||
default:
|
||||
return actual == expected;
|
||||
}
|
||||
}
|
||||
|
||||
protected UserGameContext resolveUserGameContext(Room room, RoomUnit roomUnit) {
|
||||
if (room == null || roomUnit == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Habbo habbo = room.getHabbo(roomUnit);
|
||||
if (habbo == null || habbo.getHabboInfo() == null || habbo.getHabboInfo().getCurrentGame() == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Game game = room.getGame(habbo.getHabboInfo().getCurrentGame());
|
||||
if (!this.isSupportedGame(game)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
GameTeam team = game.getTeamForHabbo(habbo);
|
||||
if (team == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return new UserGameContext(habbo, game, team);
|
||||
}
|
||||
|
||||
protected int getTeamRank(Game game, GameTeam team) {
|
||||
if (game == null || team == null) {
|
||||
return Integer.MAX_VALUE;
|
||||
}
|
||||
|
||||
int rank = 1;
|
||||
int targetScore = team.getTotalScore();
|
||||
|
||||
for (GameTeamColors teamColor : SUPPORTED_TEAM_COLORS) {
|
||||
GameTeam otherTeam = game.getTeam(teamColor);
|
||||
if (otherTeam != null && otherTeam != team && otherTeam.getTotalScore() > targetScore) {
|
||||
rank++;
|
||||
}
|
||||
}
|
||||
|
||||
return rank;
|
||||
}
|
||||
|
||||
private boolean isSupportedGame(Game game) {
|
||||
return game != null
|
||||
&& game.getState() != GameState.IDLE
|
||||
&& (game instanceof FreezeGame || game instanceof BattleBanzaiGame);
|
||||
}
|
||||
|
||||
protected static class UserGameContext {
|
||||
protected final Habbo habbo;
|
||||
protected final Game game;
|
||||
protected final GameTeam team;
|
||||
|
||||
protected UserGameContext(Habbo habbo, Game game, GameTeam team) {
|
||||
this.habbo = habbo;
|
||||
this.game = game;
|
||||
this.team = team;
|
||||
}
|
||||
}
|
||||
}
|
||||
+175
@@ -0,0 +1,175 @@
|
||||
package com.eu.habbo.habbohotel.items.interactions.wired.conditions;
|
||||
|
||||
import com.eu.habbo.habbohotel.games.GameTeam;
|
||||
import com.eu.habbo.habbohotel.games.GameTeamColors;
|
||||
import com.eu.habbo.habbohotel.items.Item;
|
||||
import com.eu.habbo.habbohotel.items.interactions.wired.WiredSettings;
|
||||
import com.eu.habbo.habbohotel.rooms.Room;
|
||||
import com.eu.habbo.habbohotel.rooms.RoomUnit;
|
||||
import com.eu.habbo.habbohotel.wired.WiredConditionType;
|
||||
import com.eu.habbo.habbohotel.wired.core.WiredContext;
|
||||
import com.eu.habbo.habbohotel.wired.core.WiredManager;
|
||||
import com.eu.habbo.habbohotel.wired.core.WiredSourceUtil;
|
||||
import com.eu.habbo.messages.ServerMessage;
|
||||
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.List;
|
||||
|
||||
public class WiredConditionTeamHasRank extends WiredConditionTeamGameBase {
|
||||
public static final WiredConditionType type = WiredConditionType.TEAM_HAS_RANK;
|
||||
|
||||
private int teamType = GameTeamColors.RED.type;
|
||||
private int placement = 1;
|
||||
private int userSource = WiredSourceUtil.SOURCE_TRIGGER;
|
||||
private int quantifier = QUANTIFIER_ALL;
|
||||
|
||||
public WiredConditionTeamHasRank(ResultSet set, Item baseItem) throws SQLException {
|
||||
super(set, baseItem);
|
||||
}
|
||||
|
||||
public WiredConditionTeamHasRank(int id, int userId, Item item, String extradata, int limitedStack, int limitedSells) {
|
||||
super(id, userId, item, extradata, limitedStack, limitedSells);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean evaluate(WiredContext ctx) {
|
||||
Room room = ctx.room();
|
||||
List<RoomUnit> users = this.resolveUsers(ctx, this.userSource);
|
||||
|
||||
return this.matchesQuantifier(users, this.quantifier, roomUnit -> this.matchesUser(ctx, room, roomUnit));
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
@Override
|
||||
public boolean execute(RoomUnit roomUnit, Room room, Object[] stuff) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getWiredData() {
|
||||
return WiredManager.getGson().toJson(new JsonData(
|
||||
this.teamType,
|
||||
this.placement,
|
||||
this.userSource,
|
||||
this.quantifier
|
||||
));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadWiredData(ResultSet set, Room room) throws SQLException {
|
||||
this.resetSettings();
|
||||
|
||||
String wiredData = set.getString("wired_data");
|
||||
if (wiredData == null || !wiredData.startsWith("{")) {
|
||||
return;
|
||||
}
|
||||
|
||||
JsonData data = WiredManager.getGson().fromJson(wiredData, JsonData.class);
|
||||
if (data == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.teamType = this.normalizeRankTeamType(data.teamType);
|
||||
this.placement = this.normalizePlacement(data.placement);
|
||||
this.userSource = this.normalizeUserSource(data.userSource);
|
||||
this.quantifier = this.normalizeQuantifier(data.quantifier);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPickUp() {
|
||||
this.resetSettings();
|
||||
}
|
||||
|
||||
@Override
|
||||
public WiredConditionType getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void serializeWiredData(ServerMessage message, Room room) {
|
||||
message.appendBoolean(false);
|
||||
message.appendInt(5);
|
||||
message.appendInt(0);
|
||||
message.appendInt(this.getBaseItem().getSpriteId());
|
||||
message.appendInt(this.getId());
|
||||
message.appendString("");
|
||||
message.appendInt(4);
|
||||
message.appendInt(this.teamType);
|
||||
message.appendInt(this.placement);
|
||||
message.appendInt(this.userSource);
|
||||
message.appendInt(this.quantifier);
|
||||
message.appendInt(0);
|
||||
message.appendInt(this.getType().code);
|
||||
message.appendInt(0);
|
||||
message.appendInt(0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean saveData(WiredSettings settings) {
|
||||
int[] params = settings.getIntParams();
|
||||
this.resetSettings();
|
||||
|
||||
if (params.length > 0) this.teamType = this.normalizeRankTeamType(params[0]);
|
||||
if (params.length > 1) this.placement = this.normalizePlacement(params[1]);
|
||||
if (params.length > 2) this.userSource = this.normalizeUserSource(params[2]);
|
||||
if (params.length > 3) this.quantifier = this.normalizeQuantifier(params[3]);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean matchesUser(WiredContext ctx, Room room, RoomUnit roomUnit) {
|
||||
UserGameContext context = this.resolveUserGameContext(room, roomUnit);
|
||||
if (context == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
GameTeamColors requiredTeam = this.resolveRequiredTeamColor(ctx, room, context.game);
|
||||
if (requiredTeam == GameTeamColors.NONE || context.team.teamColor != requiredTeam) {
|
||||
return false;
|
||||
}
|
||||
|
||||
GameTeam team = context.game.getTeam(requiredTeam);
|
||||
if (team == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return this.getTeamRank(context.game, team) == this.placement;
|
||||
}
|
||||
|
||||
private GameTeamColors resolveRequiredTeamColor(WiredContext ctx, Room room, com.eu.habbo.habbohotel.games.Game game) {
|
||||
if (this.teamType == TEAM_TRIGGERER) {
|
||||
RoomUnit actor = ctx.actor().orElse(null);
|
||||
UserGameContext triggererContext = this.resolveUserGameContext(room, actor);
|
||||
|
||||
if (triggererContext == null || triggererContext.game != game) {
|
||||
return GameTeamColors.NONE;
|
||||
}
|
||||
|
||||
return triggererContext.team.teamColor;
|
||||
}
|
||||
|
||||
return this.resolveConfiguredTeamColor(this.teamType);
|
||||
}
|
||||
|
||||
private void resetSettings() {
|
||||
this.teamType = GameTeamColors.RED.type;
|
||||
this.placement = 1;
|
||||
this.userSource = WiredSourceUtil.SOURCE_TRIGGER;
|
||||
this.quantifier = QUANTIFIER_ALL;
|
||||
}
|
||||
|
||||
static class JsonData {
|
||||
int teamType;
|
||||
int placement;
|
||||
int userSource;
|
||||
int quantifier;
|
||||
|
||||
public JsonData(int teamType, int placement, int userSource, int quantifier) {
|
||||
this.teamType = teamType;
|
||||
this.placement = placement;
|
||||
this.userSource = userSource;
|
||||
this.quantifier = quantifier;
|
||||
}
|
||||
}
|
||||
}
|
||||
+162
@@ -0,0 +1,162 @@
|
||||
package com.eu.habbo.habbohotel.items.interactions.wired.conditions;
|
||||
|
||||
import com.eu.habbo.habbohotel.games.GameTeamColors;
|
||||
import com.eu.habbo.habbohotel.items.Item;
|
||||
import com.eu.habbo.habbohotel.items.interactions.wired.WiredSettings;
|
||||
import com.eu.habbo.habbohotel.rooms.Room;
|
||||
import com.eu.habbo.habbohotel.rooms.RoomUnit;
|
||||
import com.eu.habbo.habbohotel.wired.WiredConditionType;
|
||||
import com.eu.habbo.habbohotel.wired.core.WiredContext;
|
||||
import com.eu.habbo.habbohotel.wired.core.WiredManager;
|
||||
import com.eu.habbo.habbohotel.wired.core.WiredSourceUtil;
|
||||
import com.eu.habbo.messages.ServerMessage;
|
||||
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.List;
|
||||
|
||||
public class WiredConditionTeamHasScore extends WiredConditionTeamGameBase {
|
||||
public static final WiredConditionType type = WiredConditionType.TEAM_HAS_SCORE;
|
||||
|
||||
private int teamType = GameTeamColors.RED.type;
|
||||
private int comparison = COMPARISON_EQUAL;
|
||||
private int score = 0;
|
||||
private int userSource = WiredSourceUtil.SOURCE_TRIGGER;
|
||||
private int quantifier = QUANTIFIER_ALL;
|
||||
|
||||
public WiredConditionTeamHasScore(ResultSet set, Item baseItem) throws SQLException {
|
||||
super(set, baseItem);
|
||||
}
|
||||
|
||||
public WiredConditionTeamHasScore(int id, int userId, Item item, String extradata, int limitedStack, int limitedSells) {
|
||||
super(id, userId, item, extradata, limitedStack, limitedSells);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean evaluate(WiredContext ctx) {
|
||||
Room room = ctx.room();
|
||||
List<RoomUnit> users = this.resolveUsers(ctx, this.userSource);
|
||||
|
||||
return this.matchesQuantifier(users, this.quantifier, roomUnit -> this.matchesUser(room, roomUnit));
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
@Override
|
||||
public boolean execute(RoomUnit roomUnit, Room room, Object[] stuff) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getWiredData() {
|
||||
return WiredManager.getGson().toJson(new JsonData(
|
||||
this.teamType,
|
||||
this.comparison,
|
||||
this.score,
|
||||
this.userSource,
|
||||
this.quantifier
|
||||
));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadWiredData(ResultSet set, Room room) throws SQLException {
|
||||
this.resetSettings();
|
||||
|
||||
String wiredData = set.getString("wired_data");
|
||||
if (wiredData == null || !wiredData.startsWith("{")) {
|
||||
return;
|
||||
}
|
||||
|
||||
JsonData data = WiredManager.getGson().fromJson(wiredData, JsonData.class);
|
||||
if (data == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.teamType = this.normalizeExplicitTeamType(data.teamType);
|
||||
this.comparison = this.normalizeComparison(data.comparison);
|
||||
this.score = this.normalizeScore(data.score);
|
||||
this.userSource = this.normalizeUserSource(data.userSource);
|
||||
this.quantifier = this.normalizeQuantifier(data.quantifier);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPickUp() {
|
||||
this.resetSettings();
|
||||
}
|
||||
|
||||
@Override
|
||||
public WiredConditionType getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void serializeWiredData(ServerMessage message, Room room) {
|
||||
message.appendBoolean(false);
|
||||
message.appendInt(5);
|
||||
message.appendInt(0);
|
||||
message.appendInt(this.getBaseItem().getSpriteId());
|
||||
message.appendInt(this.getId());
|
||||
message.appendString("");
|
||||
message.appendInt(5);
|
||||
message.appendInt(this.teamType);
|
||||
message.appendInt(this.comparison);
|
||||
message.appendInt(this.score);
|
||||
message.appendInt(this.userSource);
|
||||
message.appendInt(this.quantifier);
|
||||
message.appendInt(0);
|
||||
message.appendInt(this.getType().code);
|
||||
message.appendInt(0);
|
||||
message.appendInt(0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean saveData(WiredSettings settings) {
|
||||
int[] params = settings.getIntParams();
|
||||
this.resetSettings();
|
||||
|
||||
if (params.length > 0) this.teamType = this.normalizeExplicitTeamType(params[0]);
|
||||
if (params.length > 1) this.comparison = this.normalizeComparison(params[1]);
|
||||
if (params.length > 2) this.score = this.normalizeScore(params[2]);
|
||||
if (params.length > 3) this.userSource = this.normalizeUserSource(params[3]);
|
||||
if (params.length > 4) this.quantifier = this.normalizeQuantifier(params[4]);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean matchesUser(Room room, RoomUnit roomUnit) {
|
||||
UserGameContext context = this.resolveUserGameContext(room, roomUnit);
|
||||
if (context == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
GameTeamColors requiredTeam = this.resolveConfiguredTeamColor(this.teamType);
|
||||
if (context.team.teamColor != requiredTeam) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return this.compareValue(context.team.getTotalScore(), this.score, this.comparison);
|
||||
}
|
||||
|
||||
private void resetSettings() {
|
||||
this.teamType = GameTeamColors.RED.type;
|
||||
this.comparison = COMPARISON_EQUAL;
|
||||
this.score = 0;
|
||||
this.userSource = WiredSourceUtil.SOURCE_TRIGGER;
|
||||
this.quantifier = QUANTIFIER_ALL;
|
||||
}
|
||||
|
||||
static class JsonData {
|
||||
int teamType;
|
||||
int comparison;
|
||||
int score;
|
||||
int userSource;
|
||||
int quantifier;
|
||||
|
||||
public JsonData(int teamType, int comparison, int score, int userSource, int quantifier) {
|
||||
this.teamType = teamType;
|
||||
this.comparison = comparison;
|
||||
this.score = score;
|
||||
this.userSource = userSource;
|
||||
this.quantifier = quantifier;
|
||||
}
|
||||
}
|
||||
}
|
||||
+368
@@ -0,0 +1,368 @@
|
||||
package com.eu.habbo.habbohotel.items.interactions.wired.conditions;
|
||||
|
||||
import com.eu.habbo.habbohotel.bots.Bot;
|
||||
import com.eu.habbo.habbohotel.items.Item;
|
||||
import com.eu.habbo.habbohotel.items.interactions.InteractionWiredCondition;
|
||||
import com.eu.habbo.habbohotel.items.interactions.wired.WiredSettings;
|
||||
import com.eu.habbo.habbohotel.pets.Pet;
|
||||
import com.eu.habbo.habbohotel.rooms.Room;
|
||||
import com.eu.habbo.habbohotel.rooms.RoomUnit;
|
||||
import com.eu.habbo.habbohotel.rooms.RoomUnitType;
|
||||
import com.eu.habbo.habbohotel.users.Habbo;
|
||||
import com.eu.habbo.habbohotel.wired.WiredConditionType;
|
||||
import com.eu.habbo.habbohotel.wired.core.WiredContext;
|
||||
import com.eu.habbo.habbohotel.wired.core.WiredManager;
|
||||
import com.eu.habbo.habbohotel.wired.core.WiredSourceUtil;
|
||||
import com.eu.habbo.messages.ServerMessage;
|
||||
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class WiredConditionTriggererMatch extends InteractionWiredCondition {
|
||||
protected static final int ENTITY_HABBO = 1;
|
||||
protected static final int ENTITY_PET = 2;
|
||||
protected static final int ENTITY_BOT = 4;
|
||||
protected static final int AVATAR_MODE_ANY = 0;
|
||||
protected static final int AVATAR_MODE_CERTAIN = 1;
|
||||
protected static final int QUANTIFIER_ALL = 0;
|
||||
protected static final int QUANTIFIER_ANY = 1;
|
||||
protected static final int SOURCE_SPECIFIED_USERNAME = 101;
|
||||
|
||||
public static final WiredConditionType type = WiredConditionType.TRIGGERER_MATCH;
|
||||
|
||||
private int entityType = ENTITY_HABBO;
|
||||
private int avatarMode = AVATAR_MODE_ANY;
|
||||
private int matchUserSource = WiredSourceUtil.SOURCE_TRIGGER;
|
||||
private int compareUserSource = WiredSourceUtil.SOURCE_TRIGGER;
|
||||
private int quantifier = QUANTIFIER_ALL;
|
||||
private String username = "";
|
||||
|
||||
public WiredConditionTriggererMatch(ResultSet set, Item baseItem) throws SQLException {
|
||||
super(set, baseItem);
|
||||
}
|
||||
|
||||
public WiredConditionTriggererMatch(int id, int userId, Item item, String extradata, int limitedStack, int limitedSells) {
|
||||
super(id, userId, item, extradata, limitedStack, limitedSells);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean evaluate(WiredContext ctx) {
|
||||
MatchResult result = this.evaluateMatch(ctx);
|
||||
return result.valid && result.matched;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
@Override
|
||||
public boolean execute(RoomUnit roomUnit, Room room, Object[] stuff) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getWiredData() {
|
||||
return WiredManager.getGson().toJson(new JsonData(
|
||||
this.entityType,
|
||||
this.avatarMode,
|
||||
this.matchUserSource,
|
||||
this.compareUserSource,
|
||||
this.quantifier,
|
||||
this.username
|
||||
));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadWiredData(ResultSet set, Room room) throws SQLException {
|
||||
this.resetSettings();
|
||||
|
||||
String wiredData = set.getString("wired_data");
|
||||
if (wiredData == null || !wiredData.startsWith("{")) {
|
||||
return;
|
||||
}
|
||||
|
||||
JsonData data = WiredManager.getGson().fromJson(wiredData, JsonData.class);
|
||||
if (data == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.entityType = this.normalizeEntityType(data.entityType);
|
||||
this.avatarMode = this.normalizeAvatarMode(data.avatarMode);
|
||||
this.matchUserSource = this.normalizePrimaryUserSource(data.matchUserSource);
|
||||
this.compareUserSource = this.normalizeCompareUserSource(data.compareUserSource);
|
||||
this.quantifier = this.normalizeQuantifier(data.quantifier);
|
||||
this.username = this.normalizeUsername(data.username);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPickUp() {
|
||||
this.resetSettings();
|
||||
}
|
||||
|
||||
@Override
|
||||
public WiredConditionType getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void serializeWiredData(ServerMessage message, Room room) {
|
||||
message.appendBoolean(true);
|
||||
message.appendInt(5);
|
||||
message.appendInt(0);
|
||||
message.appendInt(this.getBaseItem().getSpriteId());
|
||||
message.appendInt(this.getId());
|
||||
message.appendString(this.username);
|
||||
message.appendInt(5);
|
||||
message.appendInt(this.entityType);
|
||||
message.appendInt(this.avatarMode);
|
||||
message.appendInt(this.matchUserSource);
|
||||
message.appendInt(this.compareUserSource);
|
||||
message.appendInt(this.quantifier);
|
||||
message.appendInt(0);
|
||||
message.appendInt(this.getType().code);
|
||||
message.appendInt(0);
|
||||
message.appendInt(0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean saveData(WiredSettings settings) {
|
||||
int[] params = settings.getIntParams();
|
||||
|
||||
this.resetSettings();
|
||||
|
||||
if (params.length > 0) this.entityType = this.normalizeEntityType(params[0]);
|
||||
if (params.length > 1) this.avatarMode = this.normalizeAvatarMode(params[1]);
|
||||
if (params.length > 2) this.matchUserSource = this.normalizePrimaryUserSource(params[2]);
|
||||
if (params.length > 3) this.compareUserSource = this.normalizeCompareUserSource(params[3]);
|
||||
if (params.length > 4) this.quantifier = this.normalizeQuantifier(params[4]);
|
||||
|
||||
this.username = this.normalizeUsername(settings.getStringParam());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
protected MatchResult evaluateMatch(WiredContext ctx) {
|
||||
List<RoomUnit> matchUsers = this.resolvePrimaryUsers(ctx);
|
||||
if (matchUsers.isEmpty()) {
|
||||
return MatchResult.invalid();
|
||||
}
|
||||
|
||||
List<RoomUnit> compareUsers = this.resolveCompareUsers(ctx);
|
||||
if (compareUsers.isEmpty()) {
|
||||
return MatchResult.valid(false);
|
||||
}
|
||||
|
||||
Set<Integer> compareUserIds = compareUsers.stream()
|
||||
.filter(this::matchesEntityType)
|
||||
.map(RoomUnit::getId)
|
||||
.collect(Collectors.toSet());
|
||||
|
||||
if (compareUserIds.isEmpty()) {
|
||||
return MatchResult.valid(false);
|
||||
}
|
||||
|
||||
boolean matched;
|
||||
if (this.quantifier == QUANTIFIER_ANY) {
|
||||
matched = matchUsers.stream().anyMatch(roomUnit -> this.matchesCandidate(roomUnit, compareUserIds));
|
||||
} else {
|
||||
matched = matchUsers.stream().allMatch(roomUnit -> this.matchesCandidate(roomUnit, compareUserIds));
|
||||
}
|
||||
|
||||
return MatchResult.valid(matched);
|
||||
}
|
||||
|
||||
protected int getQuantifier() {
|
||||
return this.quantifier;
|
||||
}
|
||||
|
||||
private void resetSettings() {
|
||||
this.entityType = ENTITY_HABBO;
|
||||
this.avatarMode = AVATAR_MODE_ANY;
|
||||
this.matchUserSource = WiredSourceUtil.SOURCE_TRIGGER;
|
||||
this.compareUserSource = WiredSourceUtil.SOURCE_TRIGGER;
|
||||
this.quantifier = QUANTIFIER_ALL;
|
||||
this.username = "";
|
||||
}
|
||||
|
||||
private List<RoomUnit> resolvePrimaryUsers(WiredContext ctx) {
|
||||
return this.deduplicate(WiredSourceUtil.resolveUsers(ctx, this.matchUserSource));
|
||||
}
|
||||
|
||||
private List<RoomUnit> resolveCompareUsers(WiredContext ctx) {
|
||||
List<RoomUnit> resolved;
|
||||
|
||||
if (this.compareUserSource == SOURCE_SPECIFIED_USERNAME) {
|
||||
resolved = this.resolveUsersByName(ctx.room(), this.username);
|
||||
} else {
|
||||
resolved = WiredSourceUtil.resolveUsers(ctx, this.compareUserSource);
|
||||
}
|
||||
|
||||
if (this.avatarMode == AVATAR_MODE_CERTAIN) {
|
||||
String normalizedName = this.normalizeUsername(this.username);
|
||||
if (normalizedName.isEmpty()) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
resolved = resolved.stream()
|
||||
.filter(roomUnit -> normalizedName.equalsIgnoreCase(this.getRoomUnitName(ctx.room(), roomUnit)))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
return this.deduplicate(resolved);
|
||||
}
|
||||
|
||||
private List<RoomUnit> resolveUsersByName(Room room, String username) {
|
||||
List<RoomUnit> result = new ArrayList<>();
|
||||
String normalizedName = this.normalizeUsername(username);
|
||||
if (room == null || normalizedName.isEmpty()) {
|
||||
return result;
|
||||
}
|
||||
|
||||
Habbo habbo = room.getHabbo(normalizedName);
|
||||
if (habbo != null && habbo.getRoomUnit() != null) {
|
||||
result.add(habbo.getRoomUnit());
|
||||
}
|
||||
|
||||
for (Bot bot : room.getBots(normalizedName)) {
|
||||
if (bot != null && bot.getRoomUnit() != null) {
|
||||
result.add(bot.getRoomUnit());
|
||||
}
|
||||
}
|
||||
|
||||
for (Pet pet : room.getUnitManager().getPets()) {
|
||||
if (pet != null && pet.getRoomUnit() != null && normalizedName.equalsIgnoreCase(pet.getName())) {
|
||||
result.add(pet.getRoomUnit());
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private List<RoomUnit> deduplicate(List<RoomUnit> users) {
|
||||
Map<Integer, RoomUnit> deduplicated = new LinkedHashMap<>();
|
||||
|
||||
for (RoomUnit user : users) {
|
||||
if (user != null) {
|
||||
deduplicated.putIfAbsent(user.getId(), user);
|
||||
}
|
||||
}
|
||||
|
||||
return new ArrayList<>(deduplicated.values());
|
||||
}
|
||||
|
||||
private boolean matchesCandidate(RoomUnit roomUnit, Set<Integer> compareUserIds) {
|
||||
return roomUnit != null && this.matchesEntityType(roomUnit) && compareUserIds.contains(roomUnit.getId());
|
||||
}
|
||||
|
||||
private boolean matchesEntityType(RoomUnit roomUnit) {
|
||||
return roomUnit != null && roomUnit.getRoomUnitType().getTypeId() == this.entityType;
|
||||
}
|
||||
|
||||
private String getRoomUnitName(Room room, RoomUnit roomUnit) {
|
||||
if (room == null || roomUnit == null) {
|
||||
return "";
|
||||
}
|
||||
|
||||
if (roomUnit.getRoomUnitType() == RoomUnitType.USER) {
|
||||
Habbo habbo = room.getHabbo(roomUnit);
|
||||
return (habbo != null && habbo.getHabboInfo() != null) ? habbo.getHabboInfo().getUsername() : "";
|
||||
}
|
||||
|
||||
if (roomUnit.getRoomUnitType() == RoomUnitType.BOT) {
|
||||
Bot bot = room.getBot(roomUnit);
|
||||
return (bot != null) ? bot.getName() : "";
|
||||
}
|
||||
|
||||
if (roomUnit.getRoomUnitType() == RoomUnitType.PET) {
|
||||
Pet pet = room.getPet(roomUnit);
|
||||
return (pet != null) ? pet.getName() : "";
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
private int normalizeEntityType(int value) {
|
||||
switch (value) {
|
||||
case ENTITY_HABBO:
|
||||
case ENTITY_PET:
|
||||
case ENTITY_BOT:
|
||||
return value;
|
||||
default:
|
||||
return ENTITY_HABBO;
|
||||
}
|
||||
}
|
||||
|
||||
private int normalizeAvatarMode(int value) {
|
||||
return (value == AVATAR_MODE_CERTAIN) ? AVATAR_MODE_CERTAIN : AVATAR_MODE_ANY;
|
||||
}
|
||||
|
||||
private int normalizeQuantifier(int value) {
|
||||
return (value == QUANTIFIER_ANY) ? QUANTIFIER_ANY : QUANTIFIER_ALL;
|
||||
}
|
||||
|
||||
private int normalizePrimaryUserSource(int value) {
|
||||
switch (value) {
|
||||
case WiredSourceUtil.SOURCE_SELECTOR:
|
||||
case WiredSourceUtil.SOURCE_SIGNAL:
|
||||
case WiredSourceUtil.SOURCE_TRIGGER:
|
||||
return value;
|
||||
default:
|
||||
return WiredSourceUtil.SOURCE_TRIGGER;
|
||||
}
|
||||
}
|
||||
|
||||
private int normalizeCompareUserSource(int value) {
|
||||
switch (value) {
|
||||
case WiredSourceUtil.SOURCE_SELECTOR:
|
||||
case WiredSourceUtil.SOURCE_SIGNAL:
|
||||
case WiredSourceUtil.SOURCE_TRIGGER:
|
||||
case SOURCE_SPECIFIED_USERNAME:
|
||||
return value;
|
||||
default:
|
||||
return WiredSourceUtil.SOURCE_TRIGGER;
|
||||
}
|
||||
}
|
||||
|
||||
private String normalizeUsername(String value) {
|
||||
return (value == null) ? "" : value.trim();
|
||||
}
|
||||
|
||||
protected static class MatchResult {
|
||||
protected final boolean valid;
|
||||
protected final boolean matched;
|
||||
|
||||
private MatchResult(boolean valid, boolean matched) {
|
||||
this.valid = valid;
|
||||
this.matched = matched;
|
||||
}
|
||||
|
||||
private static MatchResult invalid() {
|
||||
return new MatchResult(false, false);
|
||||
}
|
||||
|
||||
private static MatchResult valid(boolean matched) {
|
||||
return new MatchResult(true, matched);
|
||||
}
|
||||
}
|
||||
|
||||
static class JsonData {
|
||||
int entityType;
|
||||
int avatarMode;
|
||||
int matchUserSource;
|
||||
int compareUserSource;
|
||||
int quantifier;
|
||||
String username;
|
||||
|
||||
public JsonData(int entityType, int avatarMode, int matchUserSource, int compareUserSource, int quantifier, String username) {
|
||||
this.entityType = entityType;
|
||||
this.avatarMode = avatarMode;
|
||||
this.matchUserSource = matchUserSource;
|
||||
this.compareUserSource = compareUserSource;
|
||||
this.quantifier = quantifier;
|
||||
this.username = username;
|
||||
}
|
||||
}
|
||||
}
|
||||
+346
@@ -0,0 +1,346 @@
|
||||
package com.eu.habbo.habbohotel.items.interactions.wired.conditions;
|
||||
|
||||
import com.eu.habbo.habbohotel.items.Item;
|
||||
import com.eu.habbo.habbohotel.items.interactions.InteractionWiredCondition;
|
||||
import com.eu.habbo.habbohotel.items.interactions.wired.WiredSettings;
|
||||
import com.eu.habbo.habbohotel.rooms.Room;
|
||||
import com.eu.habbo.habbohotel.rooms.RoomUnit;
|
||||
import com.eu.habbo.habbohotel.rooms.RoomUnitStatus;
|
||||
import com.eu.habbo.habbohotel.wired.WiredConditionType;
|
||||
import com.eu.habbo.habbohotel.wired.WiredUserActionType;
|
||||
import com.eu.habbo.habbohotel.wired.core.WiredContext;
|
||||
import com.eu.habbo.habbohotel.wired.core.WiredManager;
|
||||
import com.eu.habbo.habbohotel.wired.core.WiredSourceUtil;
|
||||
import com.eu.habbo.messages.ServerMessage;
|
||||
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.List;
|
||||
|
||||
public class WiredConditionUserPerformsAction extends InteractionWiredCondition {
|
||||
private static final String CACHE_LAST_ACTION_ID = "wired.last_user_action.id";
|
||||
private static final String CACHE_LAST_ACTION_PARAMETER = "wired.last_user_action.parameter";
|
||||
private static final String CACHE_LAST_ACTION_TIMESTAMP = "wired.last_user_action.timestamp";
|
||||
private static final long TRANSIENT_ACTION_WINDOW_MS = 5_000L;
|
||||
protected static final int DEFAULT_ACTION = WiredUserActionType.WAVE;
|
||||
protected static final int QUANTIFIER_ALL = 0;
|
||||
protected static final int QUANTIFIER_ANY = 1;
|
||||
|
||||
public static final WiredConditionType type = WiredConditionType.USER_PERFORMS_ACTION;
|
||||
|
||||
private int selectedAction = DEFAULT_ACTION;
|
||||
private boolean signFilterEnabled = false;
|
||||
private int signId = 0;
|
||||
private boolean danceFilterEnabled = false;
|
||||
private int danceId = 1;
|
||||
private int userSource = WiredSourceUtil.SOURCE_TRIGGER;
|
||||
private int quantifier = QUANTIFIER_ALL;
|
||||
|
||||
public WiredConditionUserPerformsAction(ResultSet set, Item baseItem) throws SQLException {
|
||||
super(set, baseItem);
|
||||
}
|
||||
|
||||
public WiredConditionUserPerformsAction(int id, int userId, Item item, String extradata, int limitedStack, int limitedSells) {
|
||||
super(id, userId, item, extradata, limitedStack, limitedSells);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean evaluate(WiredContext ctx) {
|
||||
List<RoomUnit> targets = WiredSourceUtil.resolveUsers(ctx, this.userSource);
|
||||
if (targets.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (this.quantifier == QUANTIFIER_ANY) {
|
||||
return targets.stream().anyMatch(roomUnit -> this.matchesAction(ctx, roomUnit));
|
||||
}
|
||||
|
||||
return targets.stream().allMatch(roomUnit -> this.matchesAction(ctx, roomUnit));
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
@Override
|
||||
public boolean execute(RoomUnit roomUnit, Room room, Object[] stuff) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getWiredData() {
|
||||
return WiredManager.getGson().toJson(new JsonData(
|
||||
this.selectedAction,
|
||||
this.signFilterEnabled,
|
||||
this.signId,
|
||||
this.danceFilterEnabled,
|
||||
this.danceId,
|
||||
this.userSource,
|
||||
this.quantifier
|
||||
));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadWiredData(ResultSet set, Room room) throws SQLException {
|
||||
this.resetSettings();
|
||||
|
||||
String wiredData = set.getString("wired_data");
|
||||
|
||||
if (wiredData == null || !wiredData.startsWith("{")) {
|
||||
return;
|
||||
}
|
||||
|
||||
JsonData data = WiredManager.getGson().fromJson(wiredData, JsonData.class);
|
||||
|
||||
if (data == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.selectedAction = normalizeAction(data.selectedAction);
|
||||
this.signFilterEnabled = data.signFilterEnabled;
|
||||
this.signId = normalizeSignId(data.signId);
|
||||
this.danceFilterEnabled = data.danceFilterEnabled;
|
||||
this.danceId = normalizeDanceId(data.danceId);
|
||||
this.userSource = this.normalizeUserSource(data.userSource);
|
||||
this.quantifier = normalizeQuantifier(data.quantifier);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPickUp() {
|
||||
this.resetSettings();
|
||||
}
|
||||
|
||||
@Override
|
||||
public WiredConditionType getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void serializeWiredData(ServerMessage message, Room room) {
|
||||
message.appendBoolean(true);
|
||||
message.appendInt(5);
|
||||
message.appendInt(0);
|
||||
message.appendInt(this.getBaseItem().getSpriteId());
|
||||
message.appendInt(this.getId());
|
||||
message.appendString("");
|
||||
message.appendInt(7);
|
||||
message.appendInt(this.selectedAction);
|
||||
message.appendInt(this.signFilterEnabled ? 1 : 0);
|
||||
message.appendInt(this.signId);
|
||||
message.appendInt(this.danceFilterEnabled ? 1 : 0);
|
||||
message.appendInt(this.danceId);
|
||||
message.appendInt(this.userSource);
|
||||
message.appendInt(this.quantifier);
|
||||
message.appendInt(0);
|
||||
message.appendInt(this.getType().code);
|
||||
message.appendInt(0);
|
||||
message.appendInt(0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean saveData(WiredSettings settings) {
|
||||
int[] intParams = settings.getIntParams();
|
||||
|
||||
this.resetSettings();
|
||||
|
||||
if (intParams.length > 0) this.selectedAction = normalizeAction(intParams[0]);
|
||||
if (intParams.length > 1) this.signFilterEnabled = (intParams[1] == 1);
|
||||
if (intParams.length > 2) this.signId = normalizeSignId(intParams[2]);
|
||||
if (intParams.length > 3) this.danceFilterEnabled = (intParams[3] == 1);
|
||||
if (intParams.length > 4) this.danceId = normalizeDanceId(intParams[4]);
|
||||
if (intParams.length > 5) this.userSource = this.normalizeUserSource(intParams[5]);
|
||||
if (intParams.length > 6) this.quantifier = normalizeQuantifier(intParams[6]);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
protected void resetSettings() {
|
||||
this.selectedAction = DEFAULT_ACTION;
|
||||
this.signFilterEnabled = false;
|
||||
this.signId = 0;
|
||||
this.danceFilterEnabled = false;
|
||||
this.danceId = 1;
|
||||
this.userSource = WiredSourceUtil.SOURCE_TRIGGER;
|
||||
this.quantifier = QUANTIFIER_ALL;
|
||||
}
|
||||
|
||||
protected int normalizeAction(int action) {
|
||||
switch (action) {
|
||||
case WiredUserActionType.WAVE:
|
||||
case WiredUserActionType.BLOW_KISS:
|
||||
case WiredUserActionType.LAUGH:
|
||||
case WiredUserActionType.AWAKE:
|
||||
case WiredUserActionType.RELAX:
|
||||
case WiredUserActionType.SIT:
|
||||
case WiredUserActionType.STAND:
|
||||
case WiredUserActionType.LAY:
|
||||
case WiredUserActionType.SIGN:
|
||||
case WiredUserActionType.DANCE:
|
||||
case WiredUserActionType.THUMB_UP:
|
||||
return action;
|
||||
default:
|
||||
return DEFAULT_ACTION;
|
||||
}
|
||||
}
|
||||
|
||||
protected int normalizeQuantifier(int value) {
|
||||
return (value == QUANTIFIER_ANY) ? QUANTIFIER_ANY : QUANTIFIER_ALL;
|
||||
}
|
||||
|
||||
protected int normalizeUserSource(int value) {
|
||||
switch (value) {
|
||||
case WiredSourceUtil.SOURCE_SELECTOR:
|
||||
case WiredSourceUtil.SOURCE_SIGNAL:
|
||||
case WiredSourceUtil.SOURCE_TRIGGER:
|
||||
return value;
|
||||
default:
|
||||
return WiredSourceUtil.SOURCE_TRIGGER;
|
||||
}
|
||||
}
|
||||
|
||||
protected int normalizeSignId(int value) {
|
||||
return (value < 0 || value > 17) ? 0 : value;
|
||||
}
|
||||
|
||||
protected int normalizeDanceId(int value) {
|
||||
return (value < 1 || value > 4) ? 1 : value;
|
||||
}
|
||||
|
||||
protected boolean matchesAction(WiredContext ctx, RoomUnit roomUnit) {
|
||||
if (roomUnit == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (this.matchesEventAction(ctx, roomUnit)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (this.matchesCurrentState(roomUnit)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return this.matchesRecentAction(roomUnit);
|
||||
}
|
||||
|
||||
protected boolean matchesEventAction(WiredContext ctx, RoomUnit roomUnit) {
|
||||
RoomUnit actor = ctx.actor().orElse(null);
|
||||
|
||||
if (actor == null || actor.getId() != roomUnit.getId()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (ctx.eventType() != com.eu.habbo.habbohotel.wired.core.WiredEvent.Type.USER_PERFORMS_ACTION) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return this.matchesConfiguredAction(ctx.event().getActionId(), ctx.event().getActionParameter());
|
||||
}
|
||||
|
||||
protected boolean matchesCurrentState(RoomUnit roomUnit) {
|
||||
switch (this.selectedAction) {
|
||||
case WiredUserActionType.SIT:
|
||||
return roomUnit.hasStatus(RoomUnitStatus.SIT);
|
||||
case WiredUserActionType.LAY:
|
||||
return roomUnit.hasStatus(RoomUnitStatus.LAY);
|
||||
case WiredUserActionType.RELAX:
|
||||
return roomUnit.isIdle();
|
||||
case WiredUserActionType.SIGN:
|
||||
return this.matchesSignState(roomUnit);
|
||||
case WiredUserActionType.DANCE:
|
||||
return this.matchesDanceState(roomUnit);
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
protected boolean matchesRecentAction(RoomUnit roomUnit) {
|
||||
Object actionValue = roomUnit.getCacheable().get(CACHE_LAST_ACTION_ID);
|
||||
Object parameterValue = roomUnit.getCacheable().get(CACHE_LAST_ACTION_PARAMETER);
|
||||
Object timestampValue = roomUnit.getCacheable().get(CACHE_LAST_ACTION_TIMESTAMP);
|
||||
|
||||
if (!(actionValue instanceof Integer) || !(timestampValue instanceof Long)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
long timestamp = (Long) timestampValue;
|
||||
if ((System.currentTimeMillis() - timestamp) > TRANSIENT_ACTION_WINDOW_MS) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int actionId = (Integer) actionValue;
|
||||
int parameter = (parameterValue instanceof Integer) ? (Integer) parameterValue : -1;
|
||||
|
||||
return this.matchesConfiguredAction(actionId, parameter);
|
||||
}
|
||||
|
||||
protected boolean matchesConfiguredAction(int actionId, int actionParameter) {
|
||||
if (actionId != this.selectedAction) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (this.selectedAction == WiredUserActionType.SIGN && this.signFilterEnabled) {
|
||||
return actionParameter == this.signId;
|
||||
}
|
||||
|
||||
if (this.selectedAction == WiredUserActionType.DANCE && this.danceFilterEnabled) {
|
||||
return actionParameter == this.danceId;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
protected boolean matchesSignState(RoomUnit roomUnit) {
|
||||
String signStatus = roomUnit.getStatus(RoomUnitStatus.SIGN);
|
||||
if (signStatus == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!this.signFilterEnabled) {
|
||||
return true;
|
||||
}
|
||||
|
||||
try {
|
||||
return Integer.parseInt(signStatus) == this.signId;
|
||||
} catch (NumberFormatException ignored) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
protected boolean matchesDanceState(RoomUnit roomUnit) {
|
||||
int currentDance = roomUnit.getDanceType().getType();
|
||||
if (currentDance <= 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!this.danceFilterEnabled) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return currentDance == this.danceId;
|
||||
}
|
||||
|
||||
protected int getUserSource() {
|
||||
return this.userSource;
|
||||
}
|
||||
|
||||
protected int getQuantifier() {
|
||||
return this.quantifier;
|
||||
}
|
||||
|
||||
static class JsonData {
|
||||
int selectedAction;
|
||||
boolean signFilterEnabled;
|
||||
int signId;
|
||||
boolean danceFilterEnabled;
|
||||
int danceId;
|
||||
int userSource;
|
||||
int quantifier;
|
||||
|
||||
public JsonData(int selectedAction, boolean signFilterEnabled, int signId, boolean danceFilterEnabled, int danceId, int userSource, int quantifier) {
|
||||
this.selectedAction = selectedAction;
|
||||
this.signFilterEnabled = signFilterEnabled;
|
||||
this.signId = signId;
|
||||
this.danceFilterEnabled = danceFilterEnabled;
|
||||
this.danceId = danceId;
|
||||
this.userSource = userSource;
|
||||
this.quantifier = quantifier;
|
||||
}
|
||||
}
|
||||
}
|
||||
+175
@@ -0,0 +1,175 @@
|
||||
package com.eu.habbo.habbohotel.items.interactions.wired.effects;
|
||||
|
||||
import com.eu.habbo.Emulator;
|
||||
import com.eu.habbo.habbohotel.gameclients.GameClient;
|
||||
import com.eu.habbo.habbohotel.items.Item;
|
||||
import com.eu.habbo.habbohotel.items.interactions.InteractionWiredEffect;
|
||||
import com.eu.habbo.habbohotel.items.interactions.InteractionWiredTrigger;
|
||||
import com.eu.habbo.habbohotel.items.interactions.wired.WiredSettings;
|
||||
import com.eu.habbo.habbohotel.rooms.Room;
|
||||
import com.eu.habbo.habbohotel.rooms.RoomUnit;
|
||||
import com.eu.habbo.habbohotel.wired.WiredEffectType;
|
||||
import com.eu.habbo.habbohotel.wired.core.WiredContext;
|
||||
import com.eu.habbo.habbohotel.wired.core.WiredFreezeUtil;
|
||||
import com.eu.habbo.habbohotel.wired.core.WiredManager;
|
||||
import com.eu.habbo.habbohotel.wired.core.WiredSourceUtil;
|
||||
import com.eu.habbo.messages.ServerMessage;
|
||||
import com.eu.habbo.messages.incoming.wired.WiredSaveException;
|
||||
import gnu.trove.procedure.TObjectProcedure;
|
||||
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
public class WiredEffectFreeze extends InteractionWiredEffect {
|
||||
private static final Set<Integer> ALLOWED_EFFECT_IDS = Set.of(218, 12, 11, 53, 163);
|
||||
public static final WiredEffectType type = WiredEffectType.FREEZE;
|
||||
|
||||
private int effectId = 218;
|
||||
private boolean cancelOnTeleport = false;
|
||||
private int userSource = WiredSourceUtil.SOURCE_TRIGGER;
|
||||
|
||||
public WiredEffectFreeze(ResultSet set, Item baseItem) throws SQLException {
|
||||
super(set, baseItem);
|
||||
}
|
||||
|
||||
public WiredEffectFreeze(int id, int userId, Item item, String extradata, int limitedStack, int limitedSells) {
|
||||
super(id, userId, item, extradata, limitedStack, limitedSells);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(WiredContext ctx) {
|
||||
Room room = ctx.room();
|
||||
|
||||
for (RoomUnit roomUnit : WiredSourceUtil.resolveUsers(ctx, this.userSource)) {
|
||||
if (room.getHabbo(roomUnit) == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
WiredFreezeUtil.freeze(room, roomUnit, this.effectId, this.cancelOnTeleport);
|
||||
}
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
@Override
|
||||
public boolean execute(RoomUnit roomUnit, Room room, Object[] stuff) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getWiredData() {
|
||||
return WiredManager.getGson().toJson(new JsonData(this.effectId, this.cancelOnTeleport, this.getDelay(), this.userSource));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadWiredData(ResultSet set, Room room) throws SQLException {
|
||||
String wiredData = set.getString("wired_data");
|
||||
|
||||
if (wiredData.startsWith("{")) {
|
||||
JsonData data = WiredManager.getGson().fromJson(wiredData, JsonData.class);
|
||||
this.effectId = ALLOWED_EFFECT_IDS.contains(data.effectId) ? data.effectId : 218;
|
||||
this.cancelOnTeleport = data.cancelOnTeleport;
|
||||
this.setDelay(data.delay);
|
||||
this.userSource = data.userSource;
|
||||
} else {
|
||||
this.effectId = 218;
|
||||
this.cancelOnTeleport = false;
|
||||
this.setDelay(0);
|
||||
this.userSource = WiredSourceUtil.SOURCE_TRIGGER;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPickUp() {
|
||||
this.effectId = 218;
|
||||
this.cancelOnTeleport = false;
|
||||
this.setDelay(0);
|
||||
this.userSource = WiredSourceUtil.SOURCE_TRIGGER;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WiredEffectType getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void serializeWiredData(ServerMessage message, Room room) {
|
||||
message.appendBoolean(false);
|
||||
message.appendInt(5);
|
||||
message.appendInt(0);
|
||||
message.appendInt(this.getBaseItem().getSpriteId());
|
||||
message.appendInt(this.getId());
|
||||
message.appendString("");
|
||||
message.appendInt(3);
|
||||
message.appendInt(this.effectId);
|
||||
message.appendInt(this.cancelOnTeleport ? 1 : 0);
|
||||
message.appendInt(this.userSource);
|
||||
message.appendInt(0);
|
||||
message.appendInt(this.getType().code);
|
||||
message.appendInt(this.getDelay());
|
||||
|
||||
if (this.requiresTriggeringUser()) {
|
||||
List<Integer> invalidTriggers = new ArrayList<>();
|
||||
room.getRoomSpecialTypes().getTriggers(this.getX(), this.getY()).forEach(new TObjectProcedure<InteractionWiredTrigger>() {
|
||||
@Override
|
||||
public boolean execute(InteractionWiredTrigger object) {
|
||||
if (!object.isTriggeredByRoomUnit()) {
|
||||
invalidTriggers.add(object.getBaseItem().getSpriteId());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
});
|
||||
message.appendInt(invalidTriggers.size());
|
||||
for (Integer i : invalidTriggers) {
|
||||
message.appendInt(i);
|
||||
}
|
||||
} else {
|
||||
message.appendInt(0);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean saveData(WiredSettings settings, GameClient gameClient) throws WiredSaveException {
|
||||
if (settings.getIntParams().length < 3) {
|
||||
throw new WiredSaveException("Invalid data");
|
||||
}
|
||||
|
||||
int nextEffectId = settings.getIntParams()[0];
|
||||
if (!ALLOWED_EFFECT_IDS.contains(nextEffectId)) {
|
||||
throw new WiredSaveException("Invalid freeze effect");
|
||||
}
|
||||
|
||||
int delay = settings.getDelay();
|
||||
if (delay > Emulator.getConfig().getInt("hotel.wired.max_delay", 20)) {
|
||||
throw new WiredSaveException("Delay too long");
|
||||
}
|
||||
|
||||
this.effectId = nextEffectId;
|
||||
this.cancelOnTeleport = settings.getIntParams()[1] == 1;
|
||||
this.userSource = settings.getIntParams()[2];
|
||||
this.setDelay(delay);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean requiresTriggeringUser() {
|
||||
return this.userSource == WiredSourceUtil.SOURCE_TRIGGER;
|
||||
}
|
||||
|
||||
static class JsonData {
|
||||
int effectId;
|
||||
boolean cancelOnTeleport;
|
||||
int delay;
|
||||
int userSource;
|
||||
|
||||
public JsonData(int effectId, boolean cancelOnTeleport, int delay, int userSource) {
|
||||
this.effectId = effectId;
|
||||
this.cancelOnTeleport = cancelOnTeleport;
|
||||
this.delay = delay;
|
||||
this.userSource = userSource;
|
||||
}
|
||||
}
|
||||
}
|
||||
+354
@@ -0,0 +1,354 @@
|
||||
package com.eu.habbo.habbohotel.items.interactions.wired.effects;
|
||||
|
||||
import com.eu.habbo.Emulator;
|
||||
import com.eu.habbo.habbohotel.gameclients.GameClient;
|
||||
import com.eu.habbo.habbohotel.items.Item;
|
||||
import com.eu.habbo.habbohotel.items.interactions.InteractionWiredEffect;
|
||||
import com.eu.habbo.habbohotel.items.interactions.wired.WiredSettings;
|
||||
import com.eu.habbo.habbohotel.rooms.FurnitureMovementError;
|
||||
import com.eu.habbo.habbohotel.rooms.Room;
|
||||
import com.eu.habbo.habbohotel.rooms.RoomTile;
|
||||
import com.eu.habbo.habbohotel.users.HabboItem;
|
||||
import com.eu.habbo.habbohotel.wired.WiredEffectType;
|
||||
import com.eu.habbo.habbohotel.wired.core.WiredContext;
|
||||
import com.eu.habbo.habbohotel.wired.core.WiredManager;
|
||||
import com.eu.habbo.habbohotel.wired.core.WiredSourceUtil;
|
||||
import com.eu.habbo.messages.ServerMessage;
|
||||
import com.eu.habbo.messages.incoming.wired.WiredSaveException;
|
||||
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class WiredEffectFurniToFurni extends InteractionWiredEffect {
|
||||
private static final int SOURCE_SECONDARY_SELECTED = 101;
|
||||
private static final String FURNI_SPLIT_REGEX = "[;,\\t]";
|
||||
private static final String FURNI_DELIMITER = ";";
|
||||
|
||||
public static final WiredEffectType type = WiredEffectType.FURNI_TO_FURNI;
|
||||
|
||||
private final List<HabboItem> moveItems = new ArrayList<>();
|
||||
private final List<HabboItem> targetItems = new ArrayList<>();
|
||||
private int moveSource = WiredSourceUtil.SOURCE_TRIGGER;
|
||||
private int targetSource = WiredSourceUtil.SOURCE_TRIGGER;
|
||||
|
||||
public WiredEffectFurniToFurni(ResultSet set, Item baseItem) throws SQLException {
|
||||
super(set, baseItem);
|
||||
}
|
||||
|
||||
public WiredEffectFurniToFurni(int id, int userId, Item item, String extradata, int limitedStack, int limitedSells) {
|
||||
super(id, userId, item, extradata, limitedStack, limitedSells);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(WiredContext ctx) {
|
||||
Room room = ctx.room();
|
||||
|
||||
if (room == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
HabboItem moveItem = this.resolveLastMoveItem(ctx);
|
||||
HabboItem targetItem = this.resolveLastTargetItem(ctx);
|
||||
|
||||
if (moveItem == null || targetItem == null || moveItem.getId() == targetItem.getId()) {
|
||||
return;
|
||||
}
|
||||
|
||||
RoomTile targetTile = room.getLayout().getTile(targetItem.getX(), targetItem.getY());
|
||||
if (targetTile == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
FurnitureMovementError error = room.moveFurniTo(moveItem, targetTile, moveItem.getRotation(), null, true, false);
|
||||
if (error != FurnitureMovementError.NONE) {
|
||||
room.moveFurniTo(moveItem, targetTile, moveItem.getRotation(), targetItem.getZ(), null, true, false);
|
||||
}
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
@Override
|
||||
public boolean execute(com.eu.habbo.habbohotel.rooms.RoomUnit roomUnit, Room room, Object[] stuff) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getWiredData() {
|
||||
return WiredManager.getGson().toJson(new JsonData(
|
||||
this.getDelay(),
|
||||
this.moveItems.stream().map(HabboItem::getId).collect(Collectors.toList()),
|
||||
this.targetItems.stream().map(HabboItem::getId).collect(Collectors.toList()),
|
||||
this.moveSource,
|
||||
this.targetSource
|
||||
));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadWiredData(ResultSet set, Room room) throws SQLException {
|
||||
this.moveItems.clear();
|
||||
this.targetItems.clear();
|
||||
|
||||
String wiredData = set.getString("wired_data");
|
||||
|
||||
if (wiredData != null && wiredData.startsWith("{")) {
|
||||
JsonData data = WiredManager.getGson().fromJson(wiredData, JsonData.class);
|
||||
|
||||
this.setDelay(data.delay);
|
||||
this.moveSource = data.moveSource;
|
||||
this.targetSource = this.normalizeTargetSource(data.targetSource);
|
||||
|
||||
this.loadItems(room, data.itemIds, this.moveItems);
|
||||
this.loadItems(room, data.targetItemIds, this.targetItems);
|
||||
|
||||
if (this.moveSource == WiredSourceUtil.SOURCE_TRIGGER && !this.moveItems.isEmpty()) {
|
||||
this.moveSource = WiredSourceUtil.SOURCE_SELECTED;
|
||||
}
|
||||
|
||||
if (this.targetSource == WiredSourceUtil.SOURCE_TRIGGER && !this.targetItems.isEmpty()) {
|
||||
this.targetSource = SOURCE_SECONDARY_SELECTED;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (wiredData != null && !wiredData.isEmpty()) {
|
||||
String[] wiredDataOld = wiredData.split("\t");
|
||||
|
||||
if (wiredDataOld.length >= 1) {
|
||||
this.setDelay(Integer.parseInt(wiredDataOld[0]));
|
||||
}
|
||||
|
||||
if (wiredDataOld.length >= 2 && !wiredDataOld[1].trim().isEmpty()) {
|
||||
this.loadItems(room, this.parseIds(wiredDataOld[1], room), this.moveItems);
|
||||
}
|
||||
}
|
||||
|
||||
this.moveSource = this.moveItems.isEmpty() ? WiredSourceUtil.SOURCE_TRIGGER : WiredSourceUtil.SOURCE_SELECTED;
|
||||
this.targetSource = this.targetItems.isEmpty() ? WiredSourceUtil.SOURCE_TRIGGER : SOURCE_SECONDARY_SELECTED;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPickUp() {
|
||||
this.moveItems.clear();
|
||||
this.targetItems.clear();
|
||||
this.moveSource = WiredSourceUtil.SOURCE_TRIGGER;
|
||||
this.targetSource = WiredSourceUtil.SOURCE_TRIGGER;
|
||||
this.setDelay(0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void serializeWiredData(ServerMessage message, Room room) {
|
||||
this.validateItems(this.moveItems);
|
||||
this.validateItems(this.targetItems);
|
||||
|
||||
message.appendBoolean(false);
|
||||
message.appendInt(WiredManager.MAXIMUM_FURNI_SELECTION);
|
||||
message.appendInt(this.moveItems.size());
|
||||
|
||||
for (HabboItem item : this.moveItems) {
|
||||
message.appendInt(item.getId());
|
||||
}
|
||||
|
||||
message.appendInt(this.getBaseItem().getSpriteId());
|
||||
message.appendInt(this.getId());
|
||||
message.appendString(this.serializeIds(this.targetItems));
|
||||
message.appendInt(2);
|
||||
message.appendInt(this.moveSource);
|
||||
message.appendInt(this.targetSource);
|
||||
message.appendInt(0);
|
||||
message.appendInt(this.getType().code);
|
||||
message.appendInt(this.getDelay());
|
||||
message.appendInt(0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean saveData(WiredSettings settings, GameClient gameClient) throws WiredSaveException {
|
||||
this.moveSource = (settings.getIntParams().length > 0) ? settings.getIntParams()[0] : WiredSourceUtil.SOURCE_TRIGGER;
|
||||
this.targetSource = this.normalizeTargetSource((settings.getIntParams().length > 1) ? settings.getIntParams()[1] : WiredSourceUtil.SOURCE_TRIGGER);
|
||||
|
||||
Room room = this.getRoom();
|
||||
if (room == null) {
|
||||
throw new WiredSaveException("Room not found");
|
||||
}
|
||||
|
||||
List<HabboItem> newMoveItems = new ArrayList<>();
|
||||
if (this.moveSource == WiredSourceUtil.SOURCE_SELECTED) {
|
||||
for (int itemId : settings.getFurniIds()) {
|
||||
HabboItem item = room.getHabboItem(itemId);
|
||||
|
||||
if (item == null) {
|
||||
throw new WiredSaveException(String.format("Item %s not found", itemId));
|
||||
}
|
||||
|
||||
newMoveItems.add(item);
|
||||
}
|
||||
}
|
||||
|
||||
if (newMoveItems.size() > Emulator.getConfig().getInt("hotel.wired.furni.selection.count")) {
|
||||
throw new WiredSaveException("Too many furni selected");
|
||||
}
|
||||
|
||||
List<HabboItem> newTargetItems = new ArrayList<>();
|
||||
if (this.targetSource == SOURCE_SECONDARY_SELECTED) {
|
||||
newTargetItems.addAll(this.parseItems(settings.getStringParam(), room));
|
||||
}
|
||||
|
||||
if (newTargetItems.size() > Emulator.getConfig().getInt("hotel.wired.furni.selection.count")) {
|
||||
throw new WiredSaveException("Too many furni selected");
|
||||
}
|
||||
|
||||
int delay = settings.getDelay();
|
||||
if (delay > Emulator.getConfig().getInt("hotel.wired.max_delay", 20)) {
|
||||
throw new WiredSaveException("Delay too long");
|
||||
}
|
||||
|
||||
this.moveItems.clear();
|
||||
this.moveItems.addAll(newMoveItems);
|
||||
|
||||
this.targetItems.clear();
|
||||
this.targetItems.addAll(newTargetItems);
|
||||
|
||||
this.setDelay(delay);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WiredEffectType getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected long requiredCooldown() {
|
||||
return COOLDOWN_MOVEMENT;
|
||||
}
|
||||
|
||||
private HabboItem resolveLastMoveItem(WiredContext ctx) {
|
||||
return this.resolveLastItem(ctx, this.moveSource, this.moveItems);
|
||||
}
|
||||
|
||||
private HabboItem resolveLastTargetItem(WiredContext ctx) {
|
||||
int source = (this.targetSource == SOURCE_SECONDARY_SELECTED) ? WiredSourceUtil.SOURCE_SELECTED : this.targetSource;
|
||||
return this.resolveLastItem(ctx, source, this.targetItems);
|
||||
}
|
||||
|
||||
private HabboItem resolveLastItem(WiredContext ctx, int source, List<HabboItem> items) {
|
||||
if (source == WiredSourceUtil.SOURCE_SELECTED) {
|
||||
this.validateItems(items);
|
||||
}
|
||||
|
||||
List<HabboItem> resolvedItems = WiredSourceUtil.resolveItems(ctx, source, items);
|
||||
|
||||
if (resolvedItems.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
for (int index = resolvedItems.size() - 1; index >= 0; index--) {
|
||||
HabboItem item = resolvedItems.get(index);
|
||||
|
||||
if (item != null) {
|
||||
return item;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private List<HabboItem> parseItems(String data, Room room) throws WiredSaveException {
|
||||
List<HabboItem> items = new ArrayList<>();
|
||||
if (data == null || data.trim().isEmpty() || room == null) {
|
||||
return items;
|
||||
}
|
||||
|
||||
Set<Integer> seen = new HashSet<>();
|
||||
|
||||
for (String part : data.split(FURNI_SPLIT_REGEX)) {
|
||||
if (part == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
String trimmed = part.trim();
|
||||
if (trimmed.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
int itemId;
|
||||
try {
|
||||
itemId = Integer.parseInt(trimmed);
|
||||
} catch (NumberFormatException e) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (itemId <= 0 || !seen.add(itemId)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
HabboItem item = room.getHabboItem(itemId);
|
||||
if (item == null) {
|
||||
throw new WiredSaveException(String.format("Item %s not found", itemId));
|
||||
}
|
||||
|
||||
items.add(item);
|
||||
}
|
||||
|
||||
return items;
|
||||
}
|
||||
|
||||
private List<Integer> parseIds(String data, Room room) {
|
||||
try {
|
||||
return this.parseItems(data, room).stream().map(HabboItem::getId).collect(Collectors.toList());
|
||||
} catch (WiredSaveException e) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
}
|
||||
|
||||
private void loadItems(Room room, List<Integer> itemIds, List<HabboItem> target) {
|
||||
if (room == null || itemIds == null || itemIds.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (Integer itemId : itemIds) {
|
||||
HabboItem item = room.getHabboItem(itemId);
|
||||
|
||||
if (item != null) {
|
||||
target.add(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private int normalizeTargetSource(int source) {
|
||||
return (source == WiredSourceUtil.SOURCE_SELECTED) ? SOURCE_SECONDARY_SELECTED : source;
|
||||
}
|
||||
|
||||
private String serializeIds(List<HabboItem> items) {
|
||||
if (items == null || items.isEmpty()) {
|
||||
return "";
|
||||
}
|
||||
|
||||
return items.stream()
|
||||
.map(HabboItem::getId)
|
||||
.distinct()
|
||||
.map(String::valueOf)
|
||||
.collect(Collectors.joining(FURNI_DELIMITER));
|
||||
}
|
||||
|
||||
static class JsonData {
|
||||
int delay;
|
||||
List<Integer> itemIds;
|
||||
List<Integer> targetItemIds;
|
||||
int moveSource;
|
||||
int targetSource;
|
||||
|
||||
public JsonData(int delay, List<Integer> itemIds, List<Integer> targetItemIds, int moveSource, int targetSource) {
|
||||
this.delay = delay;
|
||||
this.itemIds = itemIds;
|
||||
this.targetItemIds = targetItemIds;
|
||||
this.moveSource = moveSource;
|
||||
this.targetSource = targetSource;
|
||||
}
|
||||
}
|
||||
}
|
||||
+57
@@ -0,0 +1,57 @@
|
||||
package com.eu.habbo.habbohotel.items.interactions.wired.effects;
|
||||
|
||||
import com.eu.habbo.habbohotel.items.Item;
|
||||
import com.eu.habbo.habbohotel.rooms.FurnitureMovementError;
|
||||
import com.eu.habbo.habbohotel.rooms.Room;
|
||||
import com.eu.habbo.habbohotel.rooms.RoomTile;
|
||||
import com.eu.habbo.habbohotel.users.Habbo;
|
||||
import com.eu.habbo.habbohotel.users.HabboItem;
|
||||
import com.eu.habbo.habbohotel.wired.WiredEffectType;
|
||||
import com.eu.habbo.habbohotel.wired.core.WiredContext;
|
||||
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
|
||||
public class WiredEffectFurniToUser extends WiredEffectUserFurniBase {
|
||||
public static final WiredEffectType type = WiredEffectType.FURNI_TO_USER;
|
||||
|
||||
public WiredEffectFurniToUser(ResultSet set, Item baseItem) throws SQLException {
|
||||
super(set, baseItem);
|
||||
}
|
||||
|
||||
public WiredEffectFurniToUser(int id, int userId, Item item, String extradata, int limitedStack, int limitedSells) {
|
||||
super(id, userId, item, extradata, limitedStack, limitedSells);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(WiredContext ctx) {
|
||||
Room room = ctx.room();
|
||||
HabboItem item = this.resolveLastItem(ctx);
|
||||
Habbo habbo = this.resolveLastHabbo(room, ctx);
|
||||
|
||||
if (room == null || item == null || habbo == null || habbo.getRoomUnit() == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
RoomTile targetTile = habbo.getRoomUnit().getCurrentLocation();
|
||||
if (targetTile == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
FurnitureMovementError error = room.moveFurniTo(item, targetTile, item.getRotation(), null, true, false);
|
||||
if (error != FurnitureMovementError.NONE && item.getBaseItem().getStateCount() > 0) {
|
||||
room.moveFurniTo(item, targetTile, item.getRotation(), item.getZ(), null, true, false);
|
||||
}
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
@Override
|
||||
public boolean execute(com.eu.habbo.habbohotel.rooms.RoomUnit roomUnit, Room room, Object[] stuff) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WiredEffectType getType() {
|
||||
return type;
|
||||
}
|
||||
}
|
||||
-9
@@ -140,15 +140,6 @@ public class WiredEffectGiveReward extends InteractionWiredEffect {
|
||||
return type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(GameClient client, Room room, Object[] objects) throws Exception {
|
||||
super.onClick(client, room, objects);
|
||||
|
||||
if (client.getHabbo().hasPermission(Permission.ACC_SUPERWIRED)) {
|
||||
client.getHabbo().whisper(Emulator.getTexts().getValue("hotel.wired.superwired.info"), RoomChatMessageBubbles.BOT);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void serializeWiredData(ServerMessage message, Room room) {
|
||||
message.appendBoolean(false);
|
||||
|
||||
+49
-27
@@ -50,6 +50,7 @@ public class WiredEffectMatchFurni extends InteractionWiredEffect implements Int
|
||||
@Override
|
||||
public void execute(WiredContext ctx) {
|
||||
Room room = ctx.room();
|
||||
this.refresh();
|
||||
|
||||
if(this.settings.isEmpty())
|
||||
return;
|
||||
@@ -57,33 +58,63 @@ public class WiredEffectMatchFurni extends InteractionWiredEffect implements Int
|
||||
if (room.getLayout() == null)
|
||||
return;
|
||||
|
||||
java.util.Set<Integer> allowedItemIds = null;
|
||||
if (this.furniSource != WiredSourceUtil.SOURCE_SELECTED) {
|
||||
allowedItemIds = new java.util.HashSet<>();
|
||||
for (HabboItem si : WiredSourceUtil.resolveItems(ctx, this.furniSource, null)) {
|
||||
if (si != null) {
|
||||
allowedItemIds.add(si.getId());
|
||||
}
|
||||
}
|
||||
if (allowedItemIds.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (this.furniSource == WiredSourceUtil.SOURCE_SELECTED) {
|
||||
for (WiredMatchFurniSetting setting : this.settings) {
|
||||
if (allowedItemIds != null && !allowedItemIds.contains(setting.item_id)) continue;
|
||||
|
||||
HabboItem item = room.getHabboItem(setting.item_id);
|
||||
if (item != null) {
|
||||
this.applySetting(room, item, setting);
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
List<HabboItem> targets = WiredSourceUtil.resolveItems(ctx, this.furniSource, null);
|
||||
if (targets.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (HabboItem item : targets) {
|
||||
if (item == null) continue;
|
||||
|
||||
WiredMatchFurniSetting setting = this.resolveSettingForTarget(room, item);
|
||||
if (setting == null) continue;
|
||||
|
||||
this.applySetting(room, item, setting);
|
||||
}
|
||||
}
|
||||
|
||||
private WiredMatchFurniSetting resolveSettingForTarget(Room room, HabboItem target) {
|
||||
WiredMatchFurniSetting fallback = null;
|
||||
|
||||
for (WiredMatchFurniSetting setting : this.settings) {
|
||||
HabboItem sourceItem = room.getHabboItem(setting.item_id);
|
||||
if (sourceItem == null) continue;
|
||||
if (sourceItem.getBaseItem().getId() != target.getBaseItem().getId()) continue;
|
||||
|
||||
if (setting.state.equals(target.getExtradata())) {
|
||||
return setting;
|
||||
}
|
||||
|
||||
if (fallback == null) {
|
||||
fallback = setting;
|
||||
}
|
||||
}
|
||||
|
||||
return fallback;
|
||||
}
|
||||
|
||||
private void applySetting(Room room, HabboItem item, WiredMatchFurniSetting setting) {
|
||||
if (this.state && (this.checkForWiredResetPermission && item.allowWiredResetState())) {
|
||||
if (!setting.state.equals(" ") && !item.getExtradata().equals(setting.state)) {
|
||||
item.setExtradata(setting.state);
|
||||
item.needsUpdate(true);
|
||||
room.updateItemState(item);
|
||||
}
|
||||
}
|
||||
|
||||
RoomTile oldLocation = room.getLayout().getTile(item.getX(), item.getY());
|
||||
if (oldLocation == null) continue;
|
||||
if (oldLocation == null) return;
|
||||
double oldZ = item.getZ();
|
||||
|
||||
if(this.direction && !this.position) {
|
||||
@@ -104,9 +135,6 @@ public class WiredEffectMatchFurni extends InteractionWiredEffect implements Int
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
@@ -134,9 +162,6 @@ public class WiredEffectMatchFurni extends InteractionWiredEffect implements Int
|
||||
this.settings.clear();
|
||||
this.settings.addAll(data.items);
|
||||
this.furniSource = data.furniSource;
|
||||
if (this.furniSource == WiredSourceUtil.SOURCE_TRIGGER && !this.settings.isEmpty()) {
|
||||
this.furniSource = WiredSourceUtil.SOURCE_SELECTED;
|
||||
}
|
||||
}
|
||||
else {
|
||||
String[] data = set.getString("wired_data").split(":");
|
||||
@@ -221,14 +246,14 @@ public class WiredEffectMatchFurni extends InteractionWiredEffect implements Int
|
||||
if (room == null)
|
||||
throw new WiredSaveException("Trying to save wired in unloaded room");
|
||||
|
||||
List<WiredMatchFurniSetting> newSettings = new ArrayList<>();
|
||||
if (this.furniSource == WiredSourceUtil.SOURCE_SELECTED) {
|
||||
int itemsCount = settings.getFurniIds().length;
|
||||
|
||||
if(itemsCount > Emulator.getConfig().getInt("hotel.wired.furni.selection.count")) {
|
||||
throw new WiredSaveException("Too many furni selected");
|
||||
}
|
||||
|
||||
List<WiredMatchFurniSetting> newSettings = new ArrayList<>();
|
||||
|
||||
for (int i = 0; i < itemsCount; i++) {
|
||||
int itemId = settings.getFurniIds()[i];
|
||||
HabboItem it = room.getHabboItem(itemId);
|
||||
@@ -238,7 +263,6 @@ public class WiredEffectMatchFurni extends InteractionWiredEffect implements Int
|
||||
|
||||
newSettings.add(new WiredMatchFurniSetting(it.getId(), this.checkForWiredResetPermission && it.allowWiredResetState() ? it.getExtradata() : " ", it.getRotation(), it.getX(), it.getY()));
|
||||
}
|
||||
}
|
||||
|
||||
int delay = settings.getDelay();
|
||||
|
||||
@@ -249,9 +273,7 @@ public class WiredEffectMatchFurni extends InteractionWiredEffect implements Int
|
||||
this.direction = setDirection;
|
||||
this.position = setPosition;
|
||||
this.settings.clear();
|
||||
if (this.furniSource == WiredSourceUtil.SOURCE_SELECTED) {
|
||||
this.settings.addAll(newSettings);
|
||||
}
|
||||
this.setDelay(delay);
|
||||
|
||||
return true;
|
||||
|
||||
+1
-1
@@ -76,7 +76,7 @@ public class WiredEffectMuteHabbo extends InteractionWiredEffect {
|
||||
|
||||
if (room.hasRights(habbo)) continue;
|
||||
|
||||
room.muteHabbo(habbo, 60);
|
||||
room.muteHabbo(habbo, Math.max(1, this.length));
|
||||
|
||||
habbo.getClient().sendResponse(new RoomUserWhisperComposer(new RoomChatMessage(this.message.replace("%user%", habbo.getHabboInfo().getUsername()).replace("%online_count%", Emulator.getGameEnvironment().getHabboManager().getOnlineCount() + "").replace("%room_count%", Emulator.getGameEnvironment().getRoomManager().getActiveRooms().size() + ""), habbo, habbo, RoomChatMessageBubbles.WIRED)));
|
||||
}
|
||||
|
||||
+283
@@ -0,0 +1,283 @@
|
||||
package com.eu.habbo.habbohotel.items.interactions.wired.effects;
|
||||
|
||||
import com.eu.habbo.Emulator;
|
||||
import com.eu.habbo.habbohotel.gameclients.GameClient;
|
||||
import com.eu.habbo.habbohotel.items.Item;
|
||||
import com.eu.habbo.habbohotel.items.interactions.InteractionWiredEffect;
|
||||
import com.eu.habbo.habbohotel.items.interactions.wired.WiredSettings;
|
||||
import com.eu.habbo.habbohotel.rooms.Room;
|
||||
import com.eu.habbo.habbohotel.rooms.RoomTile;
|
||||
import com.eu.habbo.habbohotel.rooms.RoomUnit;
|
||||
import com.eu.habbo.habbohotel.users.HabboItem;
|
||||
import com.eu.habbo.habbohotel.wired.WiredEffectType;
|
||||
import com.eu.habbo.habbohotel.wired.core.WiredContext;
|
||||
import com.eu.habbo.habbohotel.wired.core.WiredManager;
|
||||
import com.eu.habbo.habbohotel.wired.core.WiredSourceUtil;
|
||||
import com.eu.habbo.messages.ServerMessage;
|
||||
import com.eu.habbo.messages.incoming.wired.WiredSaveException;
|
||||
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class WiredEffectRelativeMove extends InteractionWiredEffect {
|
||||
private static final int HORIZONTAL_NEGATIVE = 0;
|
||||
private static final int HORIZONTAL_POSITIVE = 1;
|
||||
private static final int VERTICAL_NEGATIVE = 0;
|
||||
private static final int VERTICAL_POSITIVE = 1;
|
||||
private static final int MAX_DISTANCE = 20;
|
||||
|
||||
public static final WiredEffectType type = WiredEffectType.RELATIVE_MOVE;
|
||||
|
||||
private final List<HabboItem> items = new ArrayList<>();
|
||||
private int horizontalDirection = HORIZONTAL_POSITIVE;
|
||||
private int horizontalDistance = 0;
|
||||
private int verticalDirection = VERTICAL_POSITIVE;
|
||||
private int verticalDistance = 0;
|
||||
private int furniSource = WiredSourceUtil.SOURCE_TRIGGER;
|
||||
|
||||
public WiredEffectRelativeMove(ResultSet set, Item baseItem) throws SQLException {
|
||||
super(set, baseItem);
|
||||
}
|
||||
|
||||
public WiredEffectRelativeMove(int id, int userId, Item item, String extradata, int limitedStack, int limitedSells) {
|
||||
super(id, userId, item, extradata, limitedStack, limitedSells);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(WiredContext ctx) {
|
||||
Room room = ctx.room();
|
||||
if (room == null || room.getLayout() == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
List<HabboItem> effectiveItems = WiredSourceUtil.resolveItems(ctx, this.furniSource, this.items);
|
||||
|
||||
if (this.furniSource == WiredSourceUtil.SOURCE_SELECTED) {
|
||||
this.items.removeIf(item -> item == null
|
||||
|| item.getRoomId() != this.getRoomId()
|
||||
|| room.getHabboItem(item.getId()) == null);
|
||||
}
|
||||
|
||||
int deltaX = this.getHorizontalOffset();
|
||||
int deltaY = this.getVerticalOffset();
|
||||
|
||||
if (deltaX == 0 && deltaY == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (HabboItem item : effectiveItems) {
|
||||
if (item == null || item.getRoomId() != this.getRoomId()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
short targetX = (short) (item.getX() + deltaX);
|
||||
short targetY = (short) (item.getY() + deltaY);
|
||||
|
||||
RoomTile targetTile = room.getLayout().getTile(targetX, targetY);
|
||||
if (targetTile == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
room.moveFurniTo(item, targetTile, item.getRotation(), null, true, false);
|
||||
}
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
@Override
|
||||
public boolean execute(RoomUnit roomUnit, Room room, Object[] stuff) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getWiredData() {
|
||||
return WiredManager.getGson().toJson(new JsonData(
|
||||
this.getDelay(),
|
||||
this.items.stream().map(HabboItem::getId).collect(Collectors.toList()),
|
||||
this.horizontalDirection,
|
||||
this.horizontalDistance,
|
||||
this.verticalDirection,
|
||||
this.verticalDistance,
|
||||
this.furniSource
|
||||
));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadWiredData(ResultSet set, Room room) throws SQLException {
|
||||
this.items.clear();
|
||||
String wiredData = set.getString("wired_data");
|
||||
|
||||
if (wiredData != null && wiredData.startsWith("{")) {
|
||||
JsonData data = WiredManager.getGson().fromJson(wiredData, JsonData.class);
|
||||
this.setDelay(data.delay);
|
||||
this.horizontalDirection = this.normalizeBinary(data.horizontalDirection, HORIZONTAL_POSITIVE);
|
||||
this.horizontalDistance = this.normalizeDistance(data.horizontalDistance);
|
||||
this.verticalDirection = this.normalizeBinary(data.verticalDirection, VERTICAL_POSITIVE);
|
||||
this.verticalDistance = this.normalizeDistance(data.verticalDistance);
|
||||
this.furniSource = data.furniSource;
|
||||
|
||||
if (data.itemIds != null) {
|
||||
for (Integer id : data.itemIds) {
|
||||
HabboItem item = room.getHabboItem(id);
|
||||
|
||||
if (item != null) {
|
||||
this.items.add(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
this.horizontalDirection = HORIZONTAL_POSITIVE;
|
||||
this.horizontalDistance = 0;
|
||||
this.verticalDirection = VERTICAL_POSITIVE;
|
||||
this.verticalDistance = 0;
|
||||
this.furniSource = WiredSourceUtil.SOURCE_TRIGGER;
|
||||
this.setDelay(0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPickUp() {
|
||||
this.items.clear();
|
||||
this.horizontalDirection = HORIZONTAL_POSITIVE;
|
||||
this.horizontalDistance = 0;
|
||||
this.verticalDirection = VERTICAL_POSITIVE;
|
||||
this.verticalDistance = 0;
|
||||
this.furniSource = WiredSourceUtil.SOURCE_TRIGGER;
|
||||
this.setDelay(0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public WiredEffectType getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void serializeWiredData(ServerMessage message, Room room) {
|
||||
List<HabboItem> itemsSnapshot = new ArrayList<>(this.items);
|
||||
itemsSnapshot.removeIf(item -> item == null
|
||||
|| item.getRoomId() != this.getRoomId()
|
||||
|| room.getHabboItem(item.getId()) == null);
|
||||
|
||||
this.items.clear();
|
||||
this.items.addAll(itemsSnapshot);
|
||||
|
||||
message.appendBoolean(false);
|
||||
message.appendInt(WiredManager.MAXIMUM_FURNI_SELECTION);
|
||||
message.appendInt(itemsSnapshot.size());
|
||||
for (HabboItem item : itemsSnapshot) {
|
||||
message.appendInt(item.getId());
|
||||
}
|
||||
|
||||
message.appendInt(this.getBaseItem().getSpriteId());
|
||||
message.appendInt(this.getId());
|
||||
message.appendString("");
|
||||
message.appendInt(5);
|
||||
message.appendInt(this.horizontalDirection);
|
||||
message.appendInt(this.horizontalDistance);
|
||||
message.appendInt(this.verticalDirection);
|
||||
message.appendInt(this.verticalDistance);
|
||||
message.appendInt(this.furniSource);
|
||||
message.appendInt(0);
|
||||
message.appendInt(this.getType().code);
|
||||
message.appendInt(this.getDelay());
|
||||
message.appendInt(0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean saveData(WiredSettings settings, GameClient gameClient) throws WiredSaveException {
|
||||
int[] params = settings.getIntParams();
|
||||
|
||||
if (params.length < 5) {
|
||||
throw new WiredSaveException("Invalid data");
|
||||
}
|
||||
|
||||
this.horizontalDirection = this.normalizeBinary(params[0], HORIZONTAL_POSITIVE);
|
||||
this.horizontalDistance = this.normalizeDistance(params[1]);
|
||||
this.verticalDirection = this.normalizeBinary(params[2], VERTICAL_POSITIVE);
|
||||
this.verticalDistance = this.normalizeDistance(params[3]);
|
||||
this.furniSource = params[4];
|
||||
|
||||
int delay = settings.getDelay();
|
||||
if (delay > Emulator.getConfig().getInt("hotel.wired.max_delay", 20)) {
|
||||
throw new WiredSaveException("Delay too long");
|
||||
}
|
||||
|
||||
Room room = Emulator.getGameEnvironment().getRoomManager().getRoom(this.getRoomId());
|
||||
if (room == null) {
|
||||
throw new WiredSaveException("Room not found");
|
||||
}
|
||||
|
||||
if (settings.getFurniIds().length > Emulator.getConfig().getInt("hotel.wired.furni.selection.count")) {
|
||||
throw new WiredSaveException("Too many furni selected");
|
||||
}
|
||||
|
||||
List<HabboItem> newItems = new ArrayList<>();
|
||||
for (int itemId : settings.getFurniIds()) {
|
||||
HabboItem item = room.getHabboItem(itemId);
|
||||
|
||||
if (item == null) {
|
||||
throw new WiredSaveException(String.format("Item %s not found", itemId));
|
||||
}
|
||||
|
||||
newItems.add(item);
|
||||
}
|
||||
|
||||
this.items.clear();
|
||||
this.items.addAll(newItems);
|
||||
this.setDelay(delay);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private int getHorizontalOffset() {
|
||||
if (this.horizontalDistance <= 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return (this.horizontalDirection == HORIZONTAL_NEGATIVE) ? -this.horizontalDistance : this.horizontalDistance;
|
||||
}
|
||||
|
||||
private int getVerticalOffset() {
|
||||
if (this.verticalDistance <= 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return (this.verticalDirection == VERTICAL_NEGATIVE) ? -this.verticalDistance : this.verticalDistance;
|
||||
}
|
||||
|
||||
private int normalizeBinary(int value, int fallback) {
|
||||
if (value == 0 || value == 1) {
|
||||
return value;
|
||||
}
|
||||
|
||||
return fallback;
|
||||
}
|
||||
|
||||
private int normalizeDistance(int value) {
|
||||
return Math.max(0, Math.min(MAX_DISTANCE, value));
|
||||
}
|
||||
|
||||
static class JsonData {
|
||||
int delay;
|
||||
List<Integer> itemIds;
|
||||
int horizontalDirection;
|
||||
int horizontalDistance;
|
||||
int verticalDirection;
|
||||
int verticalDistance;
|
||||
int furniSource;
|
||||
|
||||
public JsonData(int delay, List<Integer> itemIds, int horizontalDirection, int horizontalDistance, int verticalDirection, int verticalDistance, int furniSource) {
|
||||
this.delay = delay;
|
||||
this.itemIds = itemIds;
|
||||
this.horizontalDirection = horizontalDirection;
|
||||
this.horizontalDistance = horizontalDistance;
|
||||
this.verticalDirection = verticalDirection;
|
||||
this.verticalDistance = verticalDistance;
|
||||
this.furniSource = furniSource;
|
||||
}
|
||||
}
|
||||
}
|
||||
+192
-63
@@ -24,6 +24,7 @@ import org.slf4j.LoggerFactory;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
|
||||
@@ -36,14 +37,16 @@ public class WiredEffectSendSignal extends InteractionWiredEffect {
|
||||
|
||||
private static final int ANTENNA_PICKED = 0;
|
||||
private static final int ANTENNA_TRIGGER = 1;
|
||||
|
||||
private static final int FORWARD_NONE = 0;
|
||||
private static final int FORWARD_TRIGGER = 1;
|
||||
private static final String ANTENNA_INTERACTION = "antenna";
|
||||
private static final String FORWARD_ITEM_SPLIT_REGEX = "[;,\\t]";
|
||||
private static final long ANTENNA_PULSE_MS = 300L;
|
||||
private static final ConcurrentHashMap<Integer, Long> ANTENNA_PULSE_TOKENS = new ConcurrentHashMap<>();
|
||||
|
||||
private THashSet<HabboItem> items;
|
||||
private THashSet<HabboItem> forwardItems;
|
||||
private int antennaSource = ANTENNA_PICKED;
|
||||
private int furniForward = FORWARD_NONE;
|
||||
private int userForward = FORWARD_NONE;
|
||||
private int furniForward = WiredSourceUtil.SOURCE_TRIGGER;
|
||||
private int userForward = WiredSourceUtil.SOURCE_TRIGGER;
|
||||
private boolean signalPerFurni = false;
|
||||
private boolean signalPerUser = false;
|
||||
private int channel = 0;
|
||||
@@ -51,11 +54,13 @@ public class WiredEffectSendSignal extends InteractionWiredEffect {
|
||||
public WiredEffectSendSignal(ResultSet set, Item baseItem) throws SQLException {
|
||||
super(set, baseItem);
|
||||
this.items = new THashSet<>();
|
||||
this.forwardItems = new THashSet<>();
|
||||
}
|
||||
|
||||
public WiredEffectSendSignal(int id, int userId, Item item, String extradata, int limitedStack, int limitedSells) {
|
||||
super(id, userId, item, extradata, limitedStack, limitedSells);
|
||||
this.items = new THashSet<>();
|
||||
this.forwardItems = new THashSet<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -77,73 +82,68 @@ public class WiredEffectSendSignal extends InteractionWiredEffect {
|
||||
.map(Collections::<HabboItem>singleton)
|
||||
.orElse(Collections.emptySet());
|
||||
} else {
|
||||
antennas = ctx.targets().isItemsModifiedBySelector()
|
||||
? new ArrayList<>(ctx.targets().items())
|
||||
: new ArrayList<>(this.items);
|
||||
Collection<HabboItem> baseAntennas = new ArrayList<>(this.items);
|
||||
|
||||
if (baseAntennas.isEmpty() && antennaSource > ANTENNA_TRIGGER) {
|
||||
HabboItem antenna = room.getHabboItem(antennaSource);
|
||||
antennas = (antenna != null) ? Collections.singleton(antenna) : Collections.emptySet();
|
||||
} else {
|
||||
antennas = baseAntennas;
|
||||
}
|
||||
}
|
||||
|
||||
if (antennas.isEmpty()) {
|
||||
List<HabboItem> resolvedAntennas = antennas.stream()
|
||||
.filter(Objects::nonNull)
|
||||
.filter(this::isAntennaItem)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
if (resolvedAntennas.isEmpty()) {
|
||||
LOGGER.debug("[SendSignal] No antennas resolved, aborting. antennaSource={}, selectorModified={}", antennaSource, ctx.targets().isItemsModifiedBySelector());
|
||||
return;
|
||||
}
|
||||
LOGGER.debug("[SendSignal] Resolved {} antenna(s), firing signals", antennas.size());
|
||||
LOGGER.debug("[SendSignal] Resolved {} antenna(s), firing signals", resolvedAntennas.size());
|
||||
|
||||
RoomUnit forwardedUser = null;
|
||||
if (userForward == FORWARD_TRIGGER) {
|
||||
forwardedUser = ctx.actor().orElse(null);
|
||||
}
|
||||
List<RoomUnit> forwardedUsers = WiredSourceUtil.resolveUsers(ctx, this.userForward);
|
||||
List<HabboItem> forwardedFurni = WiredSourceUtil.resolveItems(ctx, this.furniForward, this.forwardItems);
|
||||
|
||||
HabboItem forwardedFurni = null;
|
||||
if (furniForward == FORWARD_TRIGGER) {
|
||||
forwardedFurni = ctx.sourceItem().orElse(null);
|
||||
}
|
||||
RoomUnit defaultUser = forwardedUsers.isEmpty() ? null : forwardedUsers.get(0);
|
||||
HabboItem defaultFurni = forwardedFurni.isEmpty() ? null : forwardedFurni.get(0);
|
||||
|
||||
Set<String> visitedTiles = new HashSet<>();
|
||||
List<RoomTile> antennaTiles = new ArrayList<>();
|
||||
for (HabboItem antenna : antennas) {
|
||||
if (antenna == null) continue;
|
||||
String key = antenna.getX() + "," + antenna.getY();
|
||||
if (visitedTiles.add(key)) {
|
||||
RoomTile tile = room.getLayout().getTile(antenna.getX(), antenna.getY());
|
||||
if (tile != null) {
|
||||
antennaTiles.add(tile);
|
||||
}
|
||||
}
|
||||
}
|
||||
Collection<RoomUnit> usersToSend = (signalPerUser && !forwardedUsers.isEmpty())
|
||||
? forwardedUsers
|
||||
: Collections.singletonList(defaultUser);
|
||||
|
||||
Collection<HabboItem> furniToSend = (signalPerFurni && !forwardedFurni.isEmpty())
|
||||
? forwardedFurni
|
||||
: Collections.singletonList(defaultFurni);
|
||||
|
||||
int nextDepth = currentDepth + 1;
|
||||
|
||||
if (signalPerFurni || signalPerUser) {
|
||||
if (signalPerFurni) {
|
||||
for (RoomTile tile : antennaTiles) {
|
||||
fireSignalAtTile(room, tile, forwardedUser, forwardedFurni, nextDepth);
|
||||
for (RoomUnit user : usersToSend) {
|
||||
for (HabboItem sourceItem : furniToSend) {
|
||||
for (HabboItem antenna : resolvedAntennas) {
|
||||
fireSignalAtAntenna(room, antenna, user, sourceItem, nextDepth);
|
||||
}
|
||||
}
|
||||
if (signalPerUser && ctx.targets().hasUsers()) {
|
||||
for (RoomUnit user : ctx.targets().users()) {
|
||||
for (RoomTile tile : antennaTiles) {
|
||||
fireSignalAtTile(room, tile, user, forwardedFurni, nextDepth);
|
||||
}
|
||||
}
|
||||
} else if (!signalPerFurni) {
|
||||
for (RoomTile tile : antennaTiles) {
|
||||
fireSignalAtTile(room, tile, forwardedUser, forwardedFurni, nextDepth);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (RoomTile tile : antennaTiles) {
|
||||
fireSignalAtTile(room, tile, forwardedUser, forwardedFurni, nextDepth);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void fireSignalAtTile(Room room, RoomTile tile, RoomUnit actor, HabboItem sourceItem, int depth) {
|
||||
LOGGER.debug("[SendSignal] fireSignalAtTile: tile={},{} depth={} channel={} actor={} sourceItem={}", tile.x, tile.y, depth, channel, actor != null ? actor.getId() : "null", sourceItem != null ? sourceItem.getId() : "null");
|
||||
private void fireSignalAtAntenna(Room room, HabboItem antenna, RoomUnit actor, HabboItem sourceItem, int depth) {
|
||||
if (antenna == null) return;
|
||||
RoomTile tile = room.getLayout().getTile(antenna.getX(), antenna.getY());
|
||||
if (tile == null) return;
|
||||
|
||||
pulseAntenna(room, antenna);
|
||||
|
||||
int signalChannel = antenna.getId();
|
||||
|
||||
LOGGER.debug("[SendSignal] fireSignalAtAntenna: antennaId={} tile={},{} depth={} channel={} actor={} sourceItem={}",
|
||||
signalChannel, tile.x, tile.y, depth, signalChannel, actor != null ? actor.getId() : "null", sourceItem != null ? sourceItem.getId() : "null");
|
||||
|
||||
WiredEvent.Builder builder = WiredEvent.builder(WiredEvent.Type.SIGNAL_RECEIVED, room)
|
||||
.tile(tile)
|
||||
.callStackDepth(depth)
|
||||
.signalChannel(this.channel)
|
||||
.signalChannel(signalChannel)
|
||||
.triggeredByEffect(true);
|
||||
|
||||
if (actor != null) builder.actor(actor);
|
||||
@@ -153,6 +153,33 @@ public class WiredEffectSendSignal extends InteractionWiredEffect {
|
||||
LOGGER.debug("[SendSignal] handleEvent returned: {}", result);
|
||||
}
|
||||
|
||||
private void pulseAntenna(Room room, HabboItem antenna) {
|
||||
if (room == null || antenna == null || antenna.getBaseItem() == null) return;
|
||||
if (antenna.getBaseItem().getStateCount() <= 1) return;
|
||||
|
||||
final long token = System.currentTimeMillis();
|
||||
ANTENNA_PULSE_TOKENS.put(antenna.getId(), token);
|
||||
|
||||
if ("1".equals(antenna.getExtradata())) {
|
||||
antenna.setExtradata("0");
|
||||
room.updateItemState(antenna);
|
||||
}
|
||||
|
||||
antenna.setExtradata("1");
|
||||
room.updateItemState(antenna);
|
||||
|
||||
Emulator.getThreading().run(() -> {
|
||||
if (!room.isLoaded()) return;
|
||||
|
||||
Long currentToken = ANTENNA_PULSE_TOKENS.get(antenna.getId());
|
||||
if (currentToken == null || currentToken.longValue() != token) return;
|
||||
|
||||
antenna.setExtradata("0");
|
||||
room.updateItemState(antenna);
|
||||
ANTENNA_PULSE_TOKENS.remove(antenna.getId(), token);
|
||||
}, ANTENNA_PULSE_MS);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void serializeWiredData(ServerMessage message, Room room) {
|
||||
List<HabboItem> itemsSnapshot = new ArrayList<>(this.items);
|
||||
@@ -161,6 +188,16 @@ public class WiredEffectSendSignal extends InteractionWiredEffect {
|
||||
item.getRoomId() != this.getRoomId() || room.getHabboItem(item.getId()) == null);
|
||||
this.items.retainAll(itemsSnapshot);
|
||||
|
||||
List<HabboItem> forwardSnapshot = new ArrayList<>(this.forwardItems);
|
||||
forwardSnapshot.removeIf(item ->
|
||||
item.getRoomId() != this.getRoomId() || room.getHabboItem(item.getId()) == null);
|
||||
this.forwardItems.retainAll(forwardSnapshot);
|
||||
|
||||
String forwardString = forwardSnapshot.stream()
|
||||
.filter(Objects::nonNull)
|
||||
.map(item -> Integer.toString(item.getId()))
|
||||
.collect(Collectors.joining(";"));
|
||||
|
||||
message.appendBoolean(false);
|
||||
message.appendInt(WiredManager.MAXIMUM_FURNI_SELECTION);
|
||||
message.appendInt(itemsSnapshot.size());
|
||||
@@ -169,7 +206,7 @@ public class WiredEffectSendSignal extends InteractionWiredEffect {
|
||||
}
|
||||
message.appendInt(this.getBaseItem().getSpriteId());
|
||||
message.appendInt(this.getId());
|
||||
message.appendString("");
|
||||
message.appendString(forwardString);
|
||||
|
||||
message.appendInt(6);
|
||||
message.appendInt(antennaSource);
|
||||
@@ -219,6 +256,12 @@ public class WiredEffectSendSignal extends InteractionWiredEffect {
|
||||
newItems.add(it);
|
||||
}
|
||||
|
||||
for (HabboItem receiver : newItems) {
|
||||
if (!isAntennaItem(receiver)) {
|
||||
throw new WiredSaveException("Only antenna furni can be selected");
|
||||
}
|
||||
}
|
||||
|
||||
if (room != null && room.getRoomSpecialTypes() != null) {
|
||||
for (HabboItem receiver : newItems) {
|
||||
int count = room.getRoomSpecialTypes().countSendersTargetingReceiver(receiver.getId(), this);
|
||||
@@ -234,18 +277,36 @@ public class WiredEffectSendSignal extends InteractionWiredEffect {
|
||||
}
|
||||
|
||||
int[] params = settings.getIntParams();
|
||||
this.antennaSource = params.length > 0 ? params[0] : ANTENNA_PICKED;
|
||||
this.furniForward = params.length > 1 ? params[1] : FORWARD_NONE;
|
||||
this.userForward = params.length > 2 ? params[2] : FORWARD_NONE;
|
||||
int requestedAntennaSource = params.length > 0 ? params[0] : ANTENNA_PICKED;
|
||||
this.furniForward = normalizeSource(params.length > 1 ? params[1] : WiredSourceUtil.SOURCE_TRIGGER);
|
||||
this.userForward = normalizeSource(params.length > 2 ? params[2] : WiredSourceUtil.SOURCE_TRIGGER);
|
||||
this.signalPerFurni = params.length > 3 && params[3] == 1;
|
||||
this.signalPerUser = params.length > 4 && params[4] == 1;
|
||||
this.channel = params.length > 5 ? params[5] : 0;
|
||||
this.antennaSource = requestedAntennaSource;
|
||||
if (!newItems.isEmpty()) {
|
||||
this.antennaSource = newItems.get(0).getId();
|
||||
}
|
||||
|
||||
List<HabboItem> newForwardItems = new ArrayList<>();
|
||||
if (this.furniForward == WiredSourceUtil.SOURCE_SELECTED && room != null) {
|
||||
newForwardItems = parseForwardItems(settings.getStringParam(), room);
|
||||
}
|
||||
if (newForwardItems.size() > Emulator.getConfig().getInt("hotel.wired.furni.selection.count")) {
|
||||
throw new WiredSaveException("Too many furni selected");
|
||||
}
|
||||
|
||||
this.items.clear();
|
||||
this.items.addAll(newItems);
|
||||
|
||||
this.forwardItems.clear();
|
||||
if (this.furniForward == WiredSourceUtil.SOURCE_SELECTED) {
|
||||
this.forwardItems.addAll(newForwardItems);
|
||||
}
|
||||
this.setDelay(delay);
|
||||
|
||||
LOGGER.debug("[SendSignal] saveData: antennaSource={}, furniForward={}, userForward={}, signalPerFurni={}, signalPerUser={}, channel={}, items={}",
|
||||
antennaSource, furniForward, userForward, signalPerFurni, signalPerUser, channel, items.size());
|
||||
LOGGER.debug("[SendSignal] saveData: antennaSource={}, furniForward={}, userForward={}, signalPerFurni={}, signalPerUser={}, channel={}, items={}, forwardItems={}",
|
||||
antennaSource, furniForward, userForward, signalPerFurni, signalPerUser, channel, items.size(), forwardItems.size());
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -259,9 +320,11 @@ public class WiredEffectSendSignal extends InteractionWiredEffect {
|
||||
@Override
|
||||
public String getWiredData() {
|
||||
List<HabboItem> itemsSnapshot = new ArrayList<>(this.items);
|
||||
List<HabboItem> forwardSnapshot = new ArrayList<>(this.forwardItems);
|
||||
return WiredManager.getGson().toJson(new JsonData(
|
||||
this.getDelay(),
|
||||
itemsSnapshot.stream().map(HabboItem::getId).collect(Collectors.toList()),
|
||||
forwardSnapshot.stream().map(HabboItem::getId).collect(Collectors.toList()),
|
||||
antennaSource, furniForward, userForward, signalPerFurni, signalPerUser, channel
|
||||
));
|
||||
}
|
||||
@@ -269,14 +332,15 @@ public class WiredEffectSendSignal extends InteractionWiredEffect {
|
||||
@Override
|
||||
public void loadWiredData(ResultSet set, Room room) throws SQLException {
|
||||
this.items = new THashSet<>();
|
||||
this.forwardItems = new THashSet<>();
|
||||
String wiredData = set.getString("wired_data");
|
||||
|
||||
if (wiredData != null && wiredData.startsWith("{")) {
|
||||
JsonData data = WiredManager.getGson().fromJson(wiredData, JsonData.class);
|
||||
this.setDelay(data.delay);
|
||||
this.antennaSource = data.antennaSource;
|
||||
this.furniForward = data.furniForward;
|
||||
this.userForward = data.userForward;
|
||||
this.furniForward = normalizeSource(data.furniForward);
|
||||
this.userForward = normalizeSource(data.userForward);
|
||||
this.signalPerFurni = data.signalPerFurni;
|
||||
this.signalPerUser = data.signalPerUser;
|
||||
this.channel = data.channel;
|
||||
@@ -286,21 +350,84 @@ public class WiredEffectSendSignal extends InteractionWiredEffect {
|
||||
if (item != null) this.items.add(item);
|
||||
}
|
||||
}
|
||||
if (data.forwardItemIds != null) {
|
||||
for (Integer id : data.forwardItemIds) {
|
||||
HabboItem item = room.getHabboItem(id);
|
||||
if (item != null) this.forwardItems.add(item);
|
||||
}
|
||||
}
|
||||
|
||||
if (this.antennaSource <= ANTENNA_TRIGGER && !this.items.isEmpty()) {
|
||||
HabboItem first = this.items.iterator().next();
|
||||
if (first != null) this.antennaSource = first.getId();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPickUp() {
|
||||
this.items.clear();
|
||||
this.forwardItems.clear();
|
||||
this.antennaSource = ANTENNA_PICKED;
|
||||
this.furniForward = FORWARD_NONE;
|
||||
this.userForward = FORWARD_NONE;
|
||||
this.furniForward = WiredSourceUtil.SOURCE_TRIGGER;
|
||||
this.userForward = WiredSourceUtil.SOURCE_TRIGGER;
|
||||
this.signalPerFurni = false;
|
||||
this.signalPerUser = false;
|
||||
this.channel = 0;
|
||||
this.setDelay(0);
|
||||
}
|
||||
|
||||
private int normalizeSource(int source) {
|
||||
if (source == 1) return WiredSourceUtil.SOURCE_TRIGGER;
|
||||
if (source == WiredSourceUtil.SOURCE_TRIGGER
|
||||
|| source == WiredSourceUtil.SOURCE_SELECTED
|
||||
|| source == WiredSourceUtil.SOURCE_SELECTOR
|
||||
|| source == WiredSourceUtil.SOURCE_SIGNAL) {
|
||||
return source;
|
||||
}
|
||||
return WiredSourceUtil.SOURCE_TRIGGER;
|
||||
}
|
||||
|
||||
private List<HabboItem> parseForwardItems(String data, Room room) throws WiredSaveException {
|
||||
List<HabboItem> results = new ArrayList<>();
|
||||
if (data == null || data.trim().isEmpty() || room == null) return results;
|
||||
|
||||
Set<Integer> seen = new HashSet<>();
|
||||
String[] parts = data.split(FORWARD_ITEM_SPLIT_REGEX);
|
||||
|
||||
for (String part : parts) {
|
||||
if (part == null) continue;
|
||||
|
||||
String trimmed = part.trim();
|
||||
if (trimmed.isEmpty()) continue;
|
||||
|
||||
int itemId;
|
||||
try {
|
||||
itemId = Integer.parseInt(trimmed);
|
||||
} catch (NumberFormatException e) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (itemId <= 0 || !seen.add(itemId)) continue;
|
||||
|
||||
HabboItem item = room.getHabboItem(itemId);
|
||||
if (item == null) throw new WiredSaveException(String.format("Item %s not found", itemId));
|
||||
|
||||
results.add(item);
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
private boolean isAntennaItem(HabboItem item) {
|
||||
if (item == null || item.getBaseItem() == null || item.getBaseItem().getInteractionType() == null) return false;
|
||||
String interaction = item.getBaseItem().getInteractionType().getName();
|
||||
if (interaction == null) return false;
|
||||
|
||||
String normalized = interaction.toLowerCase();
|
||||
return normalized.equals(ANTENNA_INTERACTION);
|
||||
}
|
||||
|
||||
@Override
|
||||
public WiredEffectType getType() {
|
||||
return type;
|
||||
@@ -328,6 +455,7 @@ public class WiredEffectSendSignal extends InteractionWiredEffect {
|
||||
static class JsonData {
|
||||
int delay;
|
||||
List<Integer> itemIds;
|
||||
List<Integer> forwardItemIds;
|
||||
int antennaSource;
|
||||
int furniForward;
|
||||
int userForward;
|
||||
@@ -335,10 +463,11 @@ public class WiredEffectSendSignal extends InteractionWiredEffect {
|
||||
boolean signalPerUser;
|
||||
int channel;
|
||||
|
||||
public JsonData(int delay, List<Integer> itemIds, int antennaSource, int furniForward,
|
||||
public JsonData(int delay, List<Integer> itemIds, List<Integer> forwardItemIds, int antennaSource, int furniForward,
|
||||
int userForward, boolean signalPerFurni, boolean signalPerUser, int channel) {
|
||||
this.delay = delay;
|
||||
this.itemIds = itemIds;
|
||||
this.forwardItemIds = forwardItemIds;
|
||||
this.antennaSource = antennaSource;
|
||||
this.furniForward = furniForward;
|
||||
this.userForward = userForward;
|
||||
|
||||
+288
@@ -0,0 +1,288 @@
|
||||
package com.eu.habbo.habbohotel.items.interactions.wired.effects;
|
||||
|
||||
import com.eu.habbo.Emulator;
|
||||
import com.eu.habbo.habbohotel.gameclients.GameClient;
|
||||
import com.eu.habbo.habbohotel.items.Item;
|
||||
import com.eu.habbo.habbohotel.items.interactions.InteractionWiredEffect;
|
||||
import com.eu.habbo.habbohotel.items.interactions.wired.WiredSettings;
|
||||
import com.eu.habbo.habbohotel.rooms.Room;
|
||||
import com.eu.habbo.habbohotel.rooms.RoomTile;
|
||||
import com.eu.habbo.habbohotel.rooms.RoomUnit;
|
||||
import com.eu.habbo.habbohotel.users.HabboItem;
|
||||
import com.eu.habbo.habbohotel.wired.WiredEffectType;
|
||||
import com.eu.habbo.habbohotel.wired.core.WiredContext;
|
||||
import com.eu.habbo.habbohotel.wired.core.WiredManager;
|
||||
import com.eu.habbo.habbohotel.wired.core.WiredSourceUtil;
|
||||
import com.eu.habbo.messages.ServerMessage;
|
||||
import com.eu.habbo.messages.incoming.wired.WiredSaveException;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.math.RoundingMode;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class WiredEffectSetAltitude extends InteractionWiredEffect {
|
||||
private static final Pattern ALTITUDE_PATTERN = Pattern.compile("^\\d+(\\.\\d{1,2})?$");
|
||||
|
||||
private static final int OPERATOR_INCREASE = 0;
|
||||
private static final int OPERATOR_DECREASE = 1;
|
||||
private static final int OPERATOR_SET = 2;
|
||||
|
||||
public static final WiredEffectType type = WiredEffectType.SET_ALTITUDE;
|
||||
|
||||
private final List<HabboItem> items = new ArrayList<>();
|
||||
private int operator = OPERATOR_SET;
|
||||
private double altitude = 0.0D;
|
||||
private int furniSource = WiredSourceUtil.SOURCE_TRIGGER;
|
||||
|
||||
public WiredEffectSetAltitude(ResultSet set, Item baseItem) throws SQLException {
|
||||
super(set, baseItem);
|
||||
}
|
||||
|
||||
public WiredEffectSetAltitude(int id, int userId, Item item, String extradata, int limitedStack, int limitedSells) {
|
||||
super(id, userId, item, extradata, limitedStack, limitedSells);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(WiredContext ctx) {
|
||||
Room room = ctx.room();
|
||||
if (room == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
List<HabboItem> effectiveItems = WiredSourceUtil.resolveItems(ctx, this.furniSource, this.items);
|
||||
|
||||
if (this.furniSource == WiredSourceUtil.SOURCE_SELECTED) {
|
||||
this.items.removeIf(item -> item == null
|
||||
|| item.getRoomId() != this.getRoomId()
|
||||
|| room.getHabboItem(item.getId()) == null);
|
||||
}
|
||||
|
||||
for (HabboItem item : effectiveItems) {
|
||||
if (item == null || item.getRoomId() != this.getRoomId()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
RoomTile tile = room.getLayout().getTile(item.getX(), item.getY());
|
||||
if (tile == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
double nextAltitude = this.computeAltitude(item.getZ());
|
||||
room.moveFurniTo(item, tile, item.getRotation(), nextAltitude, null, true, false);
|
||||
}
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
@Override
|
||||
public boolean execute(RoomUnit roomUnit, Room room, Object[] stuff) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getWiredData() {
|
||||
return WiredManager.getGson().toJson(new JsonData(
|
||||
this.getDelay(),
|
||||
this.items.stream().map(HabboItem::getId).collect(Collectors.toList()),
|
||||
this.operator,
|
||||
this.formatAltitude(this.altitude),
|
||||
this.furniSource
|
||||
));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadWiredData(ResultSet set, Room room) throws SQLException {
|
||||
this.items.clear();
|
||||
String wiredData = set.getString("wired_data");
|
||||
|
||||
if (wiredData != null && wiredData.startsWith("{")) {
|
||||
JsonData data = WiredManager.getGson().fromJson(wiredData, JsonData.class);
|
||||
this.setDelay(data.delay);
|
||||
this.operator = this.normalizeOperator(data.operator);
|
||||
this.altitude = this.parseAltitudeOrDefault(data.altitude);
|
||||
this.furniSource = data.furniSource;
|
||||
|
||||
if (data.itemIds != null) {
|
||||
for (Integer id : data.itemIds) {
|
||||
HabboItem item = room.getHabboItem(id);
|
||||
|
||||
if (item != null) {
|
||||
this.items.add(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
this.operator = OPERATOR_SET;
|
||||
this.altitude = 0.0D;
|
||||
this.furniSource = WiredSourceUtil.SOURCE_TRIGGER;
|
||||
this.setDelay(0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPickUp() {
|
||||
this.items.clear();
|
||||
this.operator = OPERATOR_SET;
|
||||
this.altitude = 0.0D;
|
||||
this.furniSource = WiredSourceUtil.SOURCE_TRIGGER;
|
||||
this.setDelay(0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public WiredEffectType getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void serializeWiredData(ServerMessage message, Room room) {
|
||||
List<HabboItem> itemsSnapshot = new ArrayList<>(this.items);
|
||||
itemsSnapshot.removeIf(item -> item == null
|
||||
|| item.getRoomId() != this.getRoomId()
|
||||
|| room.getHabboItem(item.getId()) == null);
|
||||
|
||||
this.items.clear();
|
||||
this.items.addAll(itemsSnapshot);
|
||||
|
||||
message.appendBoolean(false);
|
||||
message.appendInt(WiredManager.MAXIMUM_FURNI_SELECTION);
|
||||
message.appendInt(itemsSnapshot.size());
|
||||
for (HabboItem item : itemsSnapshot) {
|
||||
message.appendInt(item.getId());
|
||||
}
|
||||
|
||||
message.appendInt(this.getBaseItem().getSpriteId());
|
||||
message.appendInt(this.getId());
|
||||
message.appendString(this.formatAltitude(this.altitude));
|
||||
message.appendInt(2);
|
||||
message.appendInt(this.operator);
|
||||
message.appendInt(this.furniSource);
|
||||
message.appendInt(0);
|
||||
message.appendInt(this.getType().code);
|
||||
message.appendInt(this.getDelay());
|
||||
message.appendInt(0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean saveData(WiredSettings settings, GameClient gameClient) throws WiredSaveException {
|
||||
int[] params = settings.getIntParams();
|
||||
this.operator = (params.length > 0) ? this.normalizeOperator(params[0]) : OPERATOR_SET;
|
||||
this.furniSource = (params.length > 1) ? params[1] : WiredSourceUtil.SOURCE_TRIGGER;
|
||||
|
||||
int delay = settings.getDelay();
|
||||
if (delay > Emulator.getConfig().getInt("hotel.wired.max_delay", 20)) {
|
||||
throw new WiredSaveException("Delay too long");
|
||||
}
|
||||
|
||||
Room room = Emulator.getGameEnvironment().getRoomManager().getRoom(this.getRoomId());
|
||||
if (room == null) {
|
||||
throw new WiredSaveException("Room not found");
|
||||
}
|
||||
|
||||
if (settings.getFurniIds().length > Emulator.getConfig().getInt("hotel.wired.furni.selection.count")) {
|
||||
throw new WiredSaveException("Too many furni selected");
|
||||
}
|
||||
|
||||
List<HabboItem> newItems = new ArrayList<>();
|
||||
for (int itemId : settings.getFurniIds()) {
|
||||
HabboItem item = room.getHabboItem(itemId);
|
||||
|
||||
if (item == null) {
|
||||
throw new WiredSaveException(String.format("Item %s not found", itemId));
|
||||
}
|
||||
|
||||
newItems.add(item);
|
||||
}
|
||||
|
||||
this.altitude = this.parseAltitude(settings.getStringParam());
|
||||
this.items.clear();
|
||||
this.items.addAll(newItems);
|
||||
this.setDelay(delay);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private int normalizeOperator(int value) {
|
||||
if (value < OPERATOR_INCREASE || value > OPERATOR_SET) {
|
||||
return OPERATOR_SET;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
private double computeAltitude(double currentAltitude) {
|
||||
double nextAltitude;
|
||||
|
||||
switch (this.operator) {
|
||||
case OPERATOR_INCREASE:
|
||||
nextAltitude = currentAltitude + this.altitude;
|
||||
break;
|
||||
case OPERATOR_DECREASE:
|
||||
nextAltitude = currentAltitude - this.altitude;
|
||||
break;
|
||||
case OPERATOR_SET:
|
||||
default:
|
||||
nextAltitude = this.altitude;
|
||||
break;
|
||||
}
|
||||
|
||||
return this.normalizeAltitude(nextAltitude);
|
||||
}
|
||||
|
||||
private double parseAltitude(String value) throws WiredSaveException {
|
||||
String normalized = (value != null) ? value.trim() : "";
|
||||
|
||||
if (normalized.isEmpty()) {
|
||||
return 0.0D;
|
||||
}
|
||||
|
||||
if (!ALTITUDE_PATTERN.matcher(normalized).matches()) {
|
||||
throw new WiredSaveException("Invalid altitude value");
|
||||
}
|
||||
|
||||
try {
|
||||
return this.normalizeAltitude(new BigDecimal(normalized).doubleValue());
|
||||
} catch (NumberFormatException exception) {
|
||||
throw new WiredSaveException("Invalid altitude value");
|
||||
}
|
||||
}
|
||||
|
||||
private double parseAltitudeOrDefault(String value) {
|
||||
try {
|
||||
return this.parseAltitude(value);
|
||||
} catch (WiredSaveException exception) {
|
||||
return 0.0D;
|
||||
}
|
||||
}
|
||||
|
||||
private double normalizeAltitude(double value) {
|
||||
double clampedValue = Math.max(0.0D, Math.min(Room.MAXIMUM_FURNI_HEIGHT, value));
|
||||
return BigDecimal.valueOf(clampedValue).setScale(2, RoundingMode.HALF_UP).doubleValue();
|
||||
}
|
||||
|
||||
private String formatAltitude(double value) {
|
||||
BigDecimal decimal = BigDecimal.valueOf(this.normalizeAltitude(value)).stripTrailingZeros();
|
||||
return (decimal.scale() < 0 ? decimal.setScale(0, RoundingMode.DOWN) : decimal).toPlainString();
|
||||
}
|
||||
|
||||
static class JsonData {
|
||||
int delay;
|
||||
List<Integer> itemIds;
|
||||
int operator;
|
||||
String altitude;
|
||||
int furniSource;
|
||||
|
||||
public JsonData(int delay, List<Integer> itemIds, int operator, String altitude, int furniSource) {
|
||||
this.delay = delay;
|
||||
this.itemIds = itemIds;
|
||||
this.operator = operator;
|
||||
this.altitude = altitude;
|
||||
this.furniSource = furniSource;
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
@@ -197,6 +197,7 @@ public class WiredEffectToggleRandom extends InteractionWiredEffect {
|
||||
|
||||
try {
|
||||
item.setExtradata(Emulator.getRandom().nextInt(item.getBaseItem().getStateCount() + 1) + "");
|
||||
item.needsUpdate(true);
|
||||
room.updateItem(item);
|
||||
} catch (Exception e) {
|
||||
LOGGER.error("Caught exception", e);
|
||||
|
||||
+149
@@ -0,0 +1,149 @@
|
||||
package com.eu.habbo.habbohotel.items.interactions.wired.effects;
|
||||
|
||||
import com.eu.habbo.Emulator;
|
||||
import com.eu.habbo.habbohotel.gameclients.GameClient;
|
||||
import com.eu.habbo.habbohotel.items.Item;
|
||||
import com.eu.habbo.habbohotel.items.interactions.InteractionWiredEffect;
|
||||
import com.eu.habbo.habbohotel.items.interactions.InteractionWiredTrigger;
|
||||
import com.eu.habbo.habbohotel.items.interactions.wired.WiredSettings;
|
||||
import com.eu.habbo.habbohotel.rooms.Room;
|
||||
import com.eu.habbo.habbohotel.rooms.RoomUnit;
|
||||
import com.eu.habbo.habbohotel.wired.WiredEffectType;
|
||||
import com.eu.habbo.habbohotel.wired.core.WiredContext;
|
||||
import com.eu.habbo.habbohotel.wired.core.WiredFreezeUtil;
|
||||
import com.eu.habbo.habbohotel.wired.core.WiredManager;
|
||||
import com.eu.habbo.habbohotel.wired.core.WiredSourceUtil;
|
||||
import com.eu.habbo.messages.ServerMessage;
|
||||
import com.eu.habbo.messages.incoming.wired.WiredSaveException;
|
||||
import gnu.trove.procedure.TObjectProcedure;
|
||||
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class WiredEffectUnfreeze extends InteractionWiredEffect {
|
||||
public static final WiredEffectType type = WiredEffectType.UNFREEZE;
|
||||
|
||||
private int userSource = WiredSourceUtil.SOURCE_TRIGGER;
|
||||
|
||||
public WiredEffectUnfreeze(ResultSet set, Item baseItem) throws SQLException {
|
||||
super(set, baseItem);
|
||||
}
|
||||
|
||||
public WiredEffectUnfreeze(int id, int userId, Item item, String extradata, int limitedStack, int limitedSells) {
|
||||
super(id, userId, item, extradata, limitedStack, limitedSells);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(WiredContext ctx) {
|
||||
Room room = ctx.room();
|
||||
|
||||
for (RoomUnit roomUnit : WiredSourceUtil.resolveUsers(ctx, this.userSource)) {
|
||||
if (room.getHabbo(roomUnit) == null || !WiredFreezeUtil.isFrozen(roomUnit)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
WiredFreezeUtil.unfreeze(room, roomUnit);
|
||||
}
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
@Override
|
||||
public boolean execute(RoomUnit roomUnit, Room room, Object[] stuff) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getWiredData() {
|
||||
return WiredManager.getGson().toJson(new JsonData(this.getDelay(), this.userSource));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadWiredData(ResultSet set, Room room) throws SQLException {
|
||||
String wiredData = set.getString("wired_data");
|
||||
|
||||
if (wiredData.startsWith("{")) {
|
||||
JsonData data = WiredManager.getGson().fromJson(wiredData, JsonData.class);
|
||||
this.setDelay(data.delay);
|
||||
this.userSource = data.userSource;
|
||||
} else {
|
||||
this.setDelay(0);
|
||||
this.userSource = WiredSourceUtil.SOURCE_TRIGGER;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPickUp() {
|
||||
this.setDelay(0);
|
||||
this.userSource = WiredSourceUtil.SOURCE_TRIGGER;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WiredEffectType getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void serializeWiredData(ServerMessage message, Room room) {
|
||||
message.appendBoolean(false);
|
||||
message.appendInt(5);
|
||||
message.appendInt(0);
|
||||
message.appendInt(this.getBaseItem().getSpriteId());
|
||||
message.appendInt(this.getId());
|
||||
message.appendString("");
|
||||
message.appendInt(1);
|
||||
message.appendInt(this.userSource);
|
||||
message.appendInt(0);
|
||||
message.appendInt(this.getType().code);
|
||||
message.appendInt(this.getDelay());
|
||||
|
||||
if (this.requiresTriggeringUser()) {
|
||||
List<Integer> invalidTriggers = new ArrayList<>();
|
||||
room.getRoomSpecialTypes().getTriggers(this.getX(), this.getY()).forEach(new TObjectProcedure<InteractionWiredTrigger>() {
|
||||
@Override
|
||||
public boolean execute(InteractionWiredTrigger object) {
|
||||
if (!object.isTriggeredByRoomUnit()) {
|
||||
invalidTriggers.add(object.getBaseItem().getSpriteId());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
});
|
||||
message.appendInt(invalidTriggers.size());
|
||||
for (Integer i : invalidTriggers) {
|
||||
message.appendInt(i);
|
||||
}
|
||||
} else {
|
||||
message.appendInt(0);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean saveData(WiredSettings settings, GameClient gameClient) throws WiredSaveException {
|
||||
int[] params = settings.getIntParams();
|
||||
this.userSource = (params.length > 0) ? params[0] : WiredSourceUtil.SOURCE_TRIGGER;
|
||||
|
||||
int delay = settings.getDelay();
|
||||
if (delay > Emulator.getConfig().getInt("hotel.wired.max_delay", 20)) {
|
||||
throw new WiredSaveException("Delay too long");
|
||||
}
|
||||
|
||||
this.setDelay(delay);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean requiresTriggeringUser() {
|
||||
return this.userSource == WiredSourceUtil.SOURCE_TRIGGER;
|
||||
}
|
||||
|
||||
static class JsonData {
|
||||
int delay;
|
||||
int userSource;
|
||||
|
||||
public JsonData(int delay, int userSource) {
|
||||
this.delay = delay;
|
||||
this.userSource = userSource;
|
||||
}
|
||||
}
|
||||
}
|
||||
+260
@@ -0,0 +1,260 @@
|
||||
package com.eu.habbo.habbohotel.items.interactions.wired.effects;
|
||||
|
||||
import com.eu.habbo.Emulator;
|
||||
import com.eu.habbo.habbohotel.gameclients.GameClient;
|
||||
import com.eu.habbo.habbohotel.items.Item;
|
||||
import com.eu.habbo.habbohotel.items.interactions.InteractionWiredEffect;
|
||||
import com.eu.habbo.habbohotel.items.interactions.InteractionWiredTrigger;
|
||||
import com.eu.habbo.habbohotel.items.interactions.wired.WiredSettings;
|
||||
import com.eu.habbo.habbohotel.rooms.Room;
|
||||
import com.eu.habbo.habbohotel.rooms.RoomUnit;
|
||||
import com.eu.habbo.habbohotel.users.Habbo;
|
||||
import com.eu.habbo.habbohotel.users.HabboItem;
|
||||
import com.eu.habbo.habbohotel.wired.WiredEffectType;
|
||||
import com.eu.habbo.habbohotel.wired.core.WiredContext;
|
||||
import com.eu.habbo.habbohotel.wired.core.WiredManager;
|
||||
import com.eu.habbo.habbohotel.wired.core.WiredSourceUtil;
|
||||
import com.eu.habbo.messages.ServerMessage;
|
||||
import com.eu.habbo.messages.incoming.wired.WiredSaveException;
|
||||
import gnu.trove.procedure.TObjectProcedure;
|
||||
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public abstract class WiredEffectUserFurniBase extends InteractionWiredEffect {
|
||||
protected final List<HabboItem> items = new ArrayList<>();
|
||||
protected int furniSource = WiredSourceUtil.SOURCE_TRIGGER;
|
||||
protected int userSource = WiredSourceUtil.SOURCE_TRIGGER;
|
||||
|
||||
public WiredEffectUserFurniBase(ResultSet set, Item baseItem) throws SQLException {
|
||||
super(set, baseItem);
|
||||
}
|
||||
|
||||
public WiredEffectUserFurniBase(int id, int userId, Item item, String extradata, int limitedStack, int limitedSells) {
|
||||
super(id, userId, item, extradata, limitedStack, limitedSells);
|
||||
}
|
||||
|
||||
protected HabboItem resolveLastItem(WiredContext ctx) {
|
||||
Room room = ctx.room();
|
||||
List<HabboItem> effectiveItems = WiredSourceUtil.resolveItems(ctx, this.furniSource, this.items);
|
||||
|
||||
if (this.furniSource == WiredSourceUtil.SOURCE_SELECTED && room != null) {
|
||||
this.items.removeIf(item -> item == null
|
||||
|| item.getRoomId() != this.getRoomId()
|
||||
|| room.getHabboItem(item.getId()) == null);
|
||||
}
|
||||
|
||||
if (effectiveItems.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
for (int index = effectiveItems.size() - 1; index >= 0; index--) {
|
||||
HabboItem item = effectiveItems.get(index);
|
||||
|
||||
if (item != null) {
|
||||
return item;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
protected Habbo resolveLastHabbo(Room room, WiredContext ctx) {
|
||||
Habbo targetHabbo = null;
|
||||
|
||||
for (RoomUnit unit : WiredSourceUtil.resolveUsers(ctx, this.userSource)) {
|
||||
Habbo habbo = room.getHabbo(unit);
|
||||
|
||||
if (habbo != null) {
|
||||
targetHabbo = habbo;
|
||||
}
|
||||
}
|
||||
|
||||
return targetHabbo;
|
||||
}
|
||||
|
||||
protected List<Habbo> resolveHabbos(Room room, WiredContext ctx) {
|
||||
List<Habbo> habbos = new ArrayList<>();
|
||||
|
||||
for (RoomUnit unit : WiredSourceUtil.resolveUsers(ctx, this.userSource)) {
|
||||
Habbo habbo = room.getHabbo(unit);
|
||||
|
||||
if (habbo != null) {
|
||||
habbos.add(habbo);
|
||||
}
|
||||
}
|
||||
|
||||
return habbos;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getWiredData() {
|
||||
return WiredManager.getGson().toJson(new JsonData(
|
||||
this.getDelay(),
|
||||
this.items.stream().map(HabboItem::getId).collect(Collectors.toList()),
|
||||
this.furniSource,
|
||||
this.userSource
|
||||
));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadWiredData(ResultSet set, Room room) throws SQLException {
|
||||
this.items.clear();
|
||||
String wiredData = set.getString("wired_data");
|
||||
|
||||
if (wiredData.startsWith("{")) {
|
||||
JsonData data = WiredManager.getGson().fromJson(wiredData, JsonData.class);
|
||||
this.setDelay(data.delay);
|
||||
this.furniSource = data.furniSource;
|
||||
this.userSource = data.userSource;
|
||||
|
||||
if (data.itemIds != null) {
|
||||
for (Integer id : data.itemIds) {
|
||||
HabboItem item = room.getHabboItem(id);
|
||||
|
||||
if (item != null) {
|
||||
this.items.add(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (this.furniSource == WiredSourceUtil.SOURCE_TRIGGER && !this.items.isEmpty()) {
|
||||
this.furniSource = WiredSourceUtil.SOURCE_SELECTED;
|
||||
}
|
||||
} else {
|
||||
String[] wiredDataOld = wiredData.split("\t");
|
||||
|
||||
if (wiredDataOld.length >= 1) {
|
||||
this.setDelay(Integer.parseInt(wiredDataOld[0]));
|
||||
}
|
||||
|
||||
if (wiredDataOld.length == 2 && wiredDataOld[1].contains(";")) {
|
||||
for (String s : wiredDataOld[1].split(";")) {
|
||||
HabboItem item = room.getHabboItem(Integer.parseInt(s));
|
||||
|
||||
if (item != null) {
|
||||
this.items.add(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.furniSource = this.items.isEmpty() ? WiredSourceUtil.SOURCE_TRIGGER : WiredSourceUtil.SOURCE_SELECTED;
|
||||
this.userSource = WiredSourceUtil.SOURCE_TRIGGER;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPickUp() {
|
||||
this.items.clear();
|
||||
this.furniSource = WiredSourceUtil.SOURCE_TRIGGER;
|
||||
this.userSource = WiredSourceUtil.SOURCE_TRIGGER;
|
||||
this.setDelay(0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void serializeWiredData(ServerMessage message, Room room) {
|
||||
List<HabboItem> itemsSnapshot = new ArrayList<>(this.items);
|
||||
itemsSnapshot.removeIf(item -> item == null
|
||||
|| item.getRoomId() != this.getRoomId()
|
||||
|| room.getHabboItem(item.getId()) == null);
|
||||
this.items.clear();
|
||||
this.items.addAll(itemsSnapshot);
|
||||
|
||||
message.appendBoolean(false);
|
||||
message.appendInt(WiredManager.MAXIMUM_FURNI_SELECTION);
|
||||
message.appendInt(itemsSnapshot.size());
|
||||
for (HabboItem item : itemsSnapshot) {
|
||||
message.appendInt(item.getId());
|
||||
}
|
||||
|
||||
message.appendInt(this.getBaseItem().getSpriteId());
|
||||
message.appendInt(this.getId());
|
||||
message.appendString("");
|
||||
message.appendInt(2);
|
||||
message.appendInt(this.furniSource);
|
||||
message.appendInt(this.userSource);
|
||||
message.appendInt(0);
|
||||
message.appendInt(this.getType().code);
|
||||
message.appendInt(this.getDelay());
|
||||
|
||||
if (this.requiresTriggeringUser()) {
|
||||
List<Integer> invalidTriggers = new ArrayList<>();
|
||||
room.getRoomSpecialTypes().getTriggers(this.getX(), this.getY()).forEach(new TObjectProcedure<InteractionWiredTrigger>() {
|
||||
@Override
|
||||
public boolean execute(InteractionWiredTrigger object) {
|
||||
if (!object.isTriggeredByRoomUnit()) {
|
||||
invalidTriggers.add(object.getId());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
});
|
||||
message.appendInt(invalidTriggers.size());
|
||||
for (Integer i : invalidTriggers) {
|
||||
message.appendInt(i);
|
||||
}
|
||||
} else {
|
||||
message.appendInt(0);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean saveData(WiredSettings settings, GameClient gameClient) throws WiredSaveException {
|
||||
this.furniSource = (settings.getIntParams().length > 0) ? settings.getIntParams()[0] : WiredSourceUtil.SOURCE_TRIGGER;
|
||||
this.userSource = (settings.getIntParams().length > 1) ? settings.getIntParams()[1] : WiredSourceUtil.SOURCE_TRIGGER;
|
||||
|
||||
if (settings.getFurniIds().length > Emulator.getConfig().getInt("hotel.wired.furni.selection.count")) {
|
||||
throw new WiredSaveException("Too many furni selected");
|
||||
}
|
||||
|
||||
Room room = Emulator.getGameEnvironment().getRoomManager().getRoom(this.getRoomId());
|
||||
if (room == null) {
|
||||
throw new WiredSaveException("Room not found");
|
||||
}
|
||||
|
||||
List<HabboItem> newItems = new ArrayList<>();
|
||||
if (this.furniSource == WiredSourceUtil.SOURCE_SELECTED) {
|
||||
for (int itemId : settings.getFurniIds()) {
|
||||
HabboItem item = room.getHabboItem(itemId);
|
||||
|
||||
if (item == null) {
|
||||
throw new WiredSaveException(String.format("Item %s not found", itemId));
|
||||
}
|
||||
|
||||
newItems.add(item);
|
||||
}
|
||||
}
|
||||
|
||||
int delay = settings.getDelay();
|
||||
if (delay > Emulator.getConfig().getInt("hotel.wired.max_delay", 20)) {
|
||||
throw new WiredSaveException("Delay too long");
|
||||
}
|
||||
|
||||
this.items.clear();
|
||||
this.items.addAll(newItems);
|
||||
this.setDelay(delay);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean requiresTriggeringUser() {
|
||||
return this.userSource == WiredSourceUtil.SOURCE_TRIGGER;
|
||||
}
|
||||
|
||||
static class JsonData {
|
||||
int delay;
|
||||
List<Integer> itemIds;
|
||||
int furniSource;
|
||||
int userSource;
|
||||
|
||||
public JsonData(int delay, List<Integer> itemIds, int furniSource, int userSource) {
|
||||
this.delay = delay;
|
||||
this.itemIds = itemIds;
|
||||
this.furniSource = furniSource;
|
||||
this.userSource = userSource;
|
||||
}
|
||||
}
|
||||
}
|
||||
+48
@@ -0,0 +1,48 @@
|
||||
package com.eu.habbo.habbohotel.items.interactions.wired.effects;
|
||||
|
||||
import com.eu.habbo.habbohotel.items.Item;
|
||||
import com.eu.habbo.habbohotel.rooms.Room;
|
||||
import com.eu.habbo.habbohotel.users.Habbo;
|
||||
import com.eu.habbo.habbohotel.users.HabboItem;
|
||||
import com.eu.habbo.habbohotel.wired.WiredEffectType;
|
||||
import com.eu.habbo.habbohotel.wired.core.WiredContext;
|
||||
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
|
||||
public class WiredEffectUserToFurni extends WiredEffectUserFurniBase {
|
||||
public static final WiredEffectType type = WiredEffectType.USER_TO_FURNI;
|
||||
|
||||
public WiredEffectUserToFurni(ResultSet set, Item baseItem) throws SQLException {
|
||||
super(set, baseItem);
|
||||
}
|
||||
|
||||
public WiredEffectUserToFurni(int id, int userId, Item item, String extradata, int limitedStack, int limitedSells) {
|
||||
super(id, userId, item, extradata, limitedStack, limitedSells);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(WiredContext ctx) {
|
||||
Room room = ctx.room();
|
||||
HabboItem item = this.resolveLastItem(ctx);
|
||||
|
||||
if (room == null || item == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (Habbo habbo : this.resolveHabbos(room, ctx)) {
|
||||
room.teleportHabboToItem(habbo, item);
|
||||
}
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
@Override
|
||||
public boolean execute(com.eu.habbo.habbohotel.rooms.RoomUnit roomUnit, Room room, Object[] stuff) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WiredEffectType getType() {
|
||||
return type;
|
||||
}
|
||||
}
|
||||
+8
-10
@@ -112,17 +112,17 @@ public class WiredEffectFurniByType extends InteractionWiredEffect {
|
||||
@Override
|
||||
public boolean saveData(WiredSettings settings, GameClient gameClient) throws WiredSaveException {
|
||||
int[] params = settings.getIntParams();
|
||||
if (params == null || params.length < 1) {
|
||||
throw new WiredSaveException("wf_slc_furni_bytype: intParams must have at least 1 element");
|
||||
if (params == null || params.length < 4) {
|
||||
throw new WiredSaveException("wf_slc_furni_bytype: intParams must have at least 4 elements");
|
||||
}
|
||||
|
||||
this.sourceType = params[0];
|
||||
this.sourceType = SOURCE_FURNI_PICKED;
|
||||
this.matchState = params.length > 1 && params[1] == 1;
|
||||
this.filterExisting = params.length > 2 && params[2] == 1;
|
||||
this.invert = params.length > 3 && params[3] == 1;
|
||||
|
||||
this.pickedFurniIds = new ArrayList<>();
|
||||
if (this.sourceType == SOURCE_FURNI_PICKED && settings.getFurniIds() != null) {
|
||||
if (settings.getFurniIds() != null) {
|
||||
for (int id : settings.getFurniIds()) {
|
||||
if (pickedFurniIds.size() >= MAX_PICKED_FURNI) break;
|
||||
pickedFurniIds.add(id);
|
||||
@@ -135,12 +135,10 @@ public class WiredEffectFurniByType extends InteractionWiredEffect {
|
||||
|
||||
@Override
|
||||
public void serializeWiredData(ServerMessage message, Room room) {
|
||||
boolean pickMode = (sourceType == SOURCE_FURNI_PICKED);
|
||||
message.appendBoolean(true);
|
||||
message.appendInt(MAX_PICKED_FURNI);
|
||||
|
||||
message.appendBoolean(pickMode);
|
||||
message.appendInt(pickMode ? MAX_PICKED_FURNI : 0);
|
||||
|
||||
if (pickMode && !pickedFurniIds.isEmpty()) {
|
||||
if (!pickedFurniIds.isEmpty()) {
|
||||
message.appendInt(pickedFurniIds.size());
|
||||
pickedFurniIds.forEach(message::appendInt);
|
||||
} else {
|
||||
@@ -152,7 +150,7 @@ public class WiredEffectFurniByType extends InteractionWiredEffect {
|
||||
message.appendString("");
|
||||
|
||||
message.appendInt(4);
|
||||
message.appendInt(sourceType);
|
||||
message.appendInt(SOURCE_FURNI_PICKED);
|
||||
message.appendInt(matchState ? 1 : 0);
|
||||
message.appendInt(filterExisting ? 1 : 0);
|
||||
message.appendInt(invert ? 1 : 0);
|
||||
|
||||
+132
-33
@@ -15,38 +15,50 @@ import gnu.trove.set.hash.THashSet;
|
||||
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class WiredTriggerFurniStateToggled extends InteractionWiredTrigger {
|
||||
private static final WiredTriggerType type = WiredTriggerType.STATE_CHANGED;
|
||||
private static final int MODE_ALL_STATES = 0;
|
||||
private static final int MODE_SAVED_STATE = 1;
|
||||
|
||||
private THashSet<HabboItem> items;
|
||||
private THashSet<StateSnapshot> snapshots;
|
||||
private int triggerMode = MODE_ALL_STATES;
|
||||
|
||||
public WiredTriggerFurniStateToggled(ResultSet set, Item baseItem) throws SQLException {
|
||||
super(set, baseItem);
|
||||
this.items = new THashSet<>();
|
||||
this.snapshots = new THashSet<>();
|
||||
}
|
||||
|
||||
public WiredTriggerFurniStateToggled(int id, int userId, Item item, String extradata, int limitedStack, int limitedSells) {
|
||||
super(id, userId, item, extradata, limitedStack, limitedSells);
|
||||
this.items = new THashSet<>();
|
||||
this.snapshots = new THashSet<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matches(HabboItem triggerItem, WiredEvent event) {
|
||||
// Reject if this was triggered by a wired effect (to prevent loops)
|
||||
if (event.isTriggeredByEffect()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
HabboItem sourceItem = event.getSourceItem().orElse(null);
|
||||
if (sourceItem != null) {
|
||||
return this.items.contains(sourceItem);
|
||||
}
|
||||
if (sourceItem == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
StateSnapshot snapshot = this.getSnapshot(sourceItem.getId());
|
||||
if (snapshot == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (this.triggerMode == MODE_SAVED_STATE) {
|
||||
return snapshot.state.equals(this.normalizeState(sourceItem.getExtradata()));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
@Override
|
||||
public boolean execute(RoomUnit roomUnit, Room room, Object[] stuff) {
|
||||
@@ -56,21 +68,36 @@ public class WiredTriggerFurniStateToggled extends InteractionWiredTrigger {
|
||||
@Override
|
||||
public String getWiredData() {
|
||||
return WiredManager.getGson().toJson(new JsonData(
|
||||
this.items.stream().map(HabboItem::getId).collect(Collectors.toList())
|
||||
this.triggerMode,
|
||||
new ArrayList<>(this.snapshots)
|
||||
));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadWiredData(ResultSet set, Room room) throws SQLException {
|
||||
this.items = new THashSet<>();
|
||||
this.snapshots = new THashSet<>();
|
||||
this.triggerMode = MODE_ALL_STATES;
|
||||
String wiredData = set.getString("wired_data");
|
||||
|
||||
if (wiredData.startsWith("{")) {
|
||||
if (wiredData != null && wiredData.startsWith("{")) {
|
||||
JsonData data = WiredManager.getGson().fromJson(wiredData, JsonData.class);
|
||||
for (Integer id: data.itemIds) {
|
||||
this.triggerMode = (data != null) ? data.triggerMode : MODE_ALL_STATES;
|
||||
|
||||
if (data != null && data.snapshots != null && !data.snapshots.isEmpty()) {
|
||||
for (StateSnapshot snapshot : data.snapshots) {
|
||||
if (snapshot == null) continue;
|
||||
|
||||
HabboItem item = room.getHabboItem(snapshot.itemId);
|
||||
if (item != null) {
|
||||
this.snapshots.add(new StateSnapshot(item.getId(), snapshot.state));
|
||||
}
|
||||
}
|
||||
} else if (data != null && data.itemIds != null) {
|
||||
for (Integer id : data.itemIds) {
|
||||
HabboItem item = room.getHabboItem(id);
|
||||
if (item != null) {
|
||||
this.items.add(item);
|
||||
this.snapshots.add(this.captureSnapshot(item));
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@@ -79,10 +106,15 @@ public class WiredTriggerFurniStateToggled extends InteractionWiredTrigger {
|
||||
|
||||
if (!wiredData.split(":")[2].equals("\t")) {
|
||||
for (String s : wiredData.split(":")[2].split(";")) {
|
||||
if (s.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
HabboItem item = room.getHabboItem(Integer.parseInt(s));
|
||||
|
||||
if (item != null)
|
||||
this.items.add(item);
|
||||
if (item != null) {
|
||||
this.snapshots.add(this.captureSnapshot(item));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -91,7 +123,8 @@ public class WiredTriggerFurniStateToggled extends InteractionWiredTrigger {
|
||||
|
||||
@Override
|
||||
public void onPickUp() {
|
||||
this.items.clear();
|
||||
this.snapshots.clear();
|
||||
this.triggerMode = MODE_ALL_STATES;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -101,33 +134,31 @@ public class WiredTriggerFurniStateToggled extends InteractionWiredTrigger {
|
||||
|
||||
@Override
|
||||
public void serializeWiredData(ServerMessage message, Room room) {
|
||||
THashSet<HabboItem> items = new THashSet<>();
|
||||
THashSet<StateSnapshot> snapshotsToRemove = new THashSet<>();
|
||||
|
||||
for (HabboItem item : this.items) {
|
||||
if (item.getRoomId() != this.getRoomId()) {
|
||||
items.add(item);
|
||||
for (StateSnapshot snapshot : this.snapshots) {
|
||||
HabboItem item = room.getHabboItem(snapshot.itemId);
|
||||
if (item == null || item.getRoomId() != this.getRoomId()) {
|
||||
snapshotsToRemove.add(snapshot);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (room.getHabboItem(item.getId()) == null) {
|
||||
items.add(item);
|
||||
}
|
||||
}
|
||||
|
||||
for (HabboItem item : items) {
|
||||
this.items.remove(item);
|
||||
for (StateSnapshot snapshot : snapshotsToRemove) {
|
||||
this.snapshots.remove(snapshot);
|
||||
}
|
||||
|
||||
message.appendBoolean(false);
|
||||
message.appendInt(WiredManager.MAXIMUM_FURNI_SELECTION);
|
||||
message.appendInt(this.items.size());
|
||||
for (HabboItem item : this.items) {
|
||||
message.appendInt(item.getId());
|
||||
message.appendInt(this.snapshots.size());
|
||||
for (StateSnapshot snapshot : this.snapshots) {
|
||||
message.appendInt(snapshot.itemId);
|
||||
}
|
||||
message.appendInt(this.getBaseItem().getSpriteId());
|
||||
message.appendInt(this.getId());
|
||||
message.appendString("");
|
||||
message.appendInt(0);
|
||||
message.appendInt(1);
|
||||
message.appendInt(this.triggerMode);
|
||||
message.appendInt(0);
|
||||
message.appendInt(this.getType().code);
|
||||
message.appendInt(0);
|
||||
@@ -135,14 +166,22 @@ public class WiredTriggerFurniStateToggled extends InteractionWiredTrigger {
|
||||
|
||||
@Override
|
||||
public boolean saveData(WiredSettings settings) {
|
||||
this.items.clear();
|
||||
this.snapshots.clear();
|
||||
this.triggerMode = (settings.getIntParams().length > 0 && settings.getIntParams()[0] == MODE_SAVED_STATE)
|
||||
? MODE_SAVED_STATE
|
||||
: MODE_ALL_STATES;
|
||||
|
||||
Room room = Emulator.getGameEnvironment().getRoomManager().getRoom(this.getRoomId());
|
||||
if (room == null) {
|
||||
return true;
|
||||
}
|
||||
|
||||
int count = settings.getFurniIds().length;
|
||||
|
||||
for (int i = 0; i < count; i++) {
|
||||
HabboItem item = Emulator.getGameEnvironment().getRoomManager().getRoom(this.getRoomId()).getHabboItem(settings.getFurniIds()[i]);
|
||||
HabboItem item = room.getHabboItem(settings.getFurniIds()[i]);
|
||||
if (item != null) {
|
||||
this.items.add(item);
|
||||
this.snapshots.add(this.captureSnapshot(item));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -154,11 +193,71 @@ public class WiredTriggerFurniStateToggled extends InteractionWiredTrigger {
|
||||
return true;
|
||||
}
|
||||
|
||||
private StateSnapshot captureSnapshot(HabboItem item) {
|
||||
return new StateSnapshot(item.getId(), this.normalizeState(item.getExtradata()));
|
||||
}
|
||||
|
||||
private StateSnapshot getSnapshot(int itemId) {
|
||||
for (StateSnapshot snapshot : this.snapshots) {
|
||||
if (snapshot.itemId == itemId) {
|
||||
return snapshot;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private String normalizeState(String state) {
|
||||
return (state == null) ? "" : state;
|
||||
}
|
||||
|
||||
static class JsonData {
|
||||
int triggerMode;
|
||||
List<StateSnapshot> snapshots;
|
||||
List<Integer> itemIds;
|
||||
|
||||
public JsonData() {
|
||||
}
|
||||
|
||||
public JsonData(List<Integer> itemIds) {
|
||||
this.itemIds = itemIds;
|
||||
}
|
||||
|
||||
public JsonData(int triggerMode, List<StateSnapshot> snapshots) {
|
||||
this.triggerMode = triggerMode;
|
||||
this.snapshots = snapshots;
|
||||
}
|
||||
}
|
||||
|
||||
static class StateSnapshot {
|
||||
int itemId;
|
||||
String state;
|
||||
|
||||
public StateSnapshot() {
|
||||
}
|
||||
|
||||
public StateSnapshot(int itemId, String state) {
|
||||
this.itemId = itemId;
|
||||
this.state = (state == null) ? "" : state;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Integer.hashCode(this.itemId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object object) {
|
||||
if (this == object) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!(object instanceof StateSnapshot)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
StateSnapshot that = (StateSnapshot) object;
|
||||
return this.itemId == that.itemId;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+164
@@ -0,0 +1,164 @@
|
||||
package com.eu.habbo.habbohotel.items.interactions.wired.triggers;
|
||||
|
||||
import com.eu.habbo.Emulator;
|
||||
import com.eu.habbo.habbohotel.items.Item;
|
||||
import com.eu.habbo.habbohotel.items.interactions.InteractionWiredTrigger;
|
||||
import com.eu.habbo.habbohotel.items.interactions.wired.WiredSettings;
|
||||
import com.eu.habbo.habbohotel.rooms.Room;
|
||||
import com.eu.habbo.habbohotel.rooms.RoomUnit;
|
||||
import com.eu.habbo.habbohotel.users.HabboItem;
|
||||
import com.eu.habbo.habbohotel.wired.WiredTriggerType;
|
||||
import com.eu.habbo.habbohotel.wired.core.WiredEvent;
|
||||
import com.eu.habbo.habbohotel.wired.core.WiredManager;
|
||||
import com.eu.habbo.messages.ServerMessage;
|
||||
import gnu.trove.set.hash.THashSet;
|
||||
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class WiredTriggerHabboClicksFurni extends InteractionWiredTrigger {
|
||||
public static final WiredTriggerType type = WiredTriggerType.CLICKS_FURNI;
|
||||
|
||||
private THashSet<HabboItem> items;
|
||||
|
||||
public WiredTriggerHabboClicksFurni(ResultSet set, Item baseItem) throws SQLException {
|
||||
super(set, baseItem);
|
||||
this.items = new THashSet<>();
|
||||
}
|
||||
|
||||
public WiredTriggerHabboClicksFurni(int id, int userId, Item item, String extradata, int limitedStack, int limitedSells) {
|
||||
super(id, userId, item, extradata, limitedStack, limitedSells);
|
||||
this.items = new THashSet<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matches(HabboItem triggerItem, WiredEvent event) {
|
||||
HabboItem sourceItem = event.getSourceItem().orElse(null);
|
||||
return sourceItem != null && this.items.contains(sourceItem);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
@Override
|
||||
public boolean execute(RoomUnit roomUnit, Room room, Object[] stuff) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WiredTriggerType getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void serializeWiredData(ServerMessage message, Room room) {
|
||||
THashSet<HabboItem> items = new THashSet<>();
|
||||
|
||||
if (Emulator.getGameEnvironment().getRoomManager().getRoom(this.getRoomId()) == null) {
|
||||
items.addAll(this.items);
|
||||
} else {
|
||||
for (HabboItem item : this.items) {
|
||||
if (Emulator.getGameEnvironment().getRoomManager().getRoom(this.getRoomId()).getHabboItem(item.getId()) == null) {
|
||||
items.add(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (HabboItem item : items) {
|
||||
this.items.remove(item);
|
||||
}
|
||||
|
||||
message.appendBoolean(false);
|
||||
message.appendInt(WiredManager.MAXIMUM_FURNI_SELECTION);
|
||||
message.appendInt(this.items.size());
|
||||
for (HabboItem item : this.items) {
|
||||
message.appendInt(item.getId());
|
||||
}
|
||||
message.appendInt(this.getBaseItem().getSpriteId());
|
||||
message.appendInt(this.getId());
|
||||
message.appendString("");
|
||||
message.appendInt(0);
|
||||
message.appendInt(0);
|
||||
message.appendInt(this.getType().code);
|
||||
message.appendInt(0);
|
||||
message.appendInt(0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean saveData(WiredSettings settings) {
|
||||
this.items.clear();
|
||||
|
||||
int count = settings.getFurniIds().length;
|
||||
|
||||
for (int i = 0; i < count; i++) {
|
||||
HabboItem item = Emulator.getGameEnvironment().getRoomManager().getRoom(this.getRoomId()).getHabboItem(settings.getFurniIds()[i]);
|
||||
if (item != null) {
|
||||
this.items.add(item);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getWiredData() {
|
||||
return WiredManager.getGson().toJson(new JsonData(
|
||||
this.items.stream().map(HabboItem::getId).collect(Collectors.toList())
|
||||
));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadWiredData(ResultSet set, Room room) throws SQLException {
|
||||
this.items.clear();
|
||||
String wiredData = set.getString("wired_data");
|
||||
|
||||
if (wiredData.startsWith("{")) {
|
||||
JsonData data = WiredManager.getGson().fromJson(wiredData, JsonData.class);
|
||||
for (Integer id : data.itemIds) {
|
||||
HabboItem item = room.getHabboItem(id);
|
||||
if (item != null) {
|
||||
this.items.add(item);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (wiredData.split(":").length >= 3) {
|
||||
super.setDelay(Integer.parseInt(wiredData.split(":")[0]));
|
||||
|
||||
if (!wiredData.split(":")[2].equals("\t")) {
|
||||
for (String s : wiredData.split(":")[2].split(";")) {
|
||||
if (s.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
HabboItem item = room.getHabboItem(Integer.parseInt(s));
|
||||
|
||||
if (item != null) {
|
||||
this.items.add(item);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPickUp() {
|
||||
this.items.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isTriggeredByRoomUnit() {
|
||||
return true;
|
||||
}
|
||||
|
||||
static class JsonData {
|
||||
List<Integer> itemIds;
|
||||
|
||||
public JsonData(List<Integer> itemIds) {
|
||||
this.itemIds = itemIds;
|
||||
}
|
||||
}
|
||||
}
|
||||
+47
@@ -0,0 +1,47 @@
|
||||
package com.eu.habbo.habbohotel.items.interactions.wired.triggers;
|
||||
|
||||
import com.eu.habbo.habbohotel.items.Item;
|
||||
import com.eu.habbo.habbohotel.users.HabboItem;
|
||||
import com.eu.habbo.habbohotel.wired.WiredTriggerType;
|
||||
import com.eu.habbo.habbohotel.wired.core.WiredEvent;
|
||||
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
|
||||
public class WiredTriggerHabboClicksTile extends WiredTriggerHabboClicksFurni {
|
||||
public static final WiredTriggerType type = WiredTriggerType.CLICKS_TILE;
|
||||
|
||||
private static final String CLICK_TILE_INTERACTION = "room_invisible_click_tile";
|
||||
|
||||
public WiredTriggerHabboClicksTile(ResultSet set, Item baseItem) throws SQLException {
|
||||
super(set, baseItem);
|
||||
}
|
||||
|
||||
public WiredTriggerHabboClicksTile(int id, int userId, Item item, String extradata, int limitedStack, int limitedSells) {
|
||||
super(id, userId, item, extradata, limitedStack, limitedSells);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matches(HabboItem triggerItem, WiredEvent event) {
|
||||
if (!super.matches(triggerItem, event)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
HabboItem sourceItem = event.getSourceItem().orElse(null);
|
||||
return isClickTileItem(sourceItem);
|
||||
}
|
||||
|
||||
@Override
|
||||
public WiredTriggerType getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
private boolean isClickTileItem(HabboItem item) {
|
||||
if (item == null || item.getBaseItem() == null || item.getBaseItem().getInteractionType() == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
String interaction = item.getBaseItem().getInteractionType().getName();
|
||||
return interaction != null && interaction.equalsIgnoreCase(CLICK_TILE_INTERACTION);
|
||||
}
|
||||
}
|
||||
+80
@@ -0,0 +1,80 @@
|
||||
package com.eu.habbo.habbohotel.items.interactions.wired.triggers;
|
||||
|
||||
import com.eu.habbo.habbohotel.items.Item;
|
||||
import com.eu.habbo.habbohotel.items.interactions.InteractionWiredTrigger;
|
||||
import com.eu.habbo.habbohotel.items.interactions.wired.WiredSettings;
|
||||
import com.eu.habbo.habbohotel.rooms.Room;
|
||||
import com.eu.habbo.habbohotel.rooms.RoomUnit;
|
||||
import com.eu.habbo.habbohotel.users.HabboItem;
|
||||
import com.eu.habbo.habbohotel.wired.WiredTriggerType;
|
||||
import com.eu.habbo.habbohotel.wired.core.WiredEvent;
|
||||
import com.eu.habbo.messages.ServerMessage;
|
||||
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
|
||||
public class WiredTriggerHabboClicksUser extends InteractionWiredTrigger {
|
||||
public static final WiredTriggerType type = WiredTriggerType.CLICKS_USER;
|
||||
|
||||
public WiredTriggerHabboClicksUser(ResultSet set, Item baseItem) throws SQLException {
|
||||
super(set, baseItem);
|
||||
}
|
||||
|
||||
public WiredTriggerHabboClicksUser(int id, int userId, Item item, String extradata, int limitedStack, int limitedSells) {
|
||||
super(id, userId, item, extradata, limitedStack, limitedSells);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matches(HabboItem triggerItem, WiredEvent event) {
|
||||
return event.getActor().isPresent();
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
@Override
|
||||
public boolean execute(RoomUnit roomUnit, Room room, Object[] stuff) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getWiredData() {
|
||||
return "";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadWiredData(ResultSet set, Room room) throws SQLException {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPickUp() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public WiredTriggerType getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void serializeWiredData(ServerMessage message, Room room) {
|
||||
message.appendBoolean(false);
|
||||
message.appendInt(5);
|
||||
message.appendInt(0);
|
||||
message.appendInt(this.getBaseItem().getSpriteId());
|
||||
message.appendInt(this.getId());
|
||||
message.appendString("");
|
||||
message.appendInt(0);
|
||||
message.appendInt(0);
|
||||
message.appendInt(this.getType().code);
|
||||
message.appendInt(0);
|
||||
message.appendInt(0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean saveData(WiredSettings settings) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isTriggeredByRoomUnit() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
+116
@@ -0,0 +1,116 @@
|
||||
package com.eu.habbo.habbohotel.items.interactions.wired.triggers;
|
||||
|
||||
import com.eu.habbo.habbohotel.items.Item;
|
||||
import com.eu.habbo.habbohotel.items.interactions.InteractionWiredTrigger;
|
||||
import com.eu.habbo.habbohotel.items.interactions.wired.WiredSettings;
|
||||
import com.eu.habbo.habbohotel.rooms.Room;
|
||||
import com.eu.habbo.habbohotel.rooms.RoomUnit;
|
||||
import com.eu.habbo.habbohotel.users.Habbo;
|
||||
import com.eu.habbo.habbohotel.users.HabboItem;
|
||||
import com.eu.habbo.habbohotel.wired.core.WiredManager;
|
||||
import com.eu.habbo.habbohotel.wired.WiredTriggerType;
|
||||
import com.eu.habbo.habbohotel.wired.core.WiredEvent;
|
||||
import com.eu.habbo.messages.ServerMessage;
|
||||
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
|
||||
public class WiredTriggerHabboLeavesRoom extends InteractionWiredTrigger {
|
||||
public static final WiredTriggerType type = WiredTriggerType.LEAVE_ROOM;
|
||||
|
||||
private String username = "";
|
||||
|
||||
public WiredTriggerHabboLeavesRoom(ResultSet set, Item baseItem) throws SQLException {
|
||||
super(set, baseItem);
|
||||
}
|
||||
|
||||
public WiredTriggerHabboLeavesRoom(int id, int userId, Item item, String extradata, int limitedStack, int limitedSells) {
|
||||
super(id, userId, item, extradata, limitedStack, limitedSells);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matches(HabboItem triggerItem, WiredEvent event) {
|
||||
RoomUnit roomUnit = event.getActor().orElse(null);
|
||||
Room room = event.getRoom();
|
||||
Habbo habbo = room.getHabbo(roomUnit);
|
||||
|
||||
if (habbo != null) {
|
||||
if (this.username.length() > 0) {
|
||||
return habbo.getHabboInfo().getUsername().equalsIgnoreCase(this.username);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
@Override
|
||||
public boolean execute(RoomUnit roomUnit, Room room, Object[] stuff) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getWiredData() {
|
||||
return WiredManager.getGson().toJson(new JsonData(
|
||||
this.username
|
||||
));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadWiredData(ResultSet set, Room room) throws SQLException {
|
||||
String wiredData = set.getString("wired_data");
|
||||
|
||||
if (wiredData.startsWith("{")) {
|
||||
JsonData data = WiredManager.getGson().fromJson(wiredData, JsonData.class);
|
||||
this.username = data.username;
|
||||
} else {
|
||||
this.username = wiredData;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPickUp() {
|
||||
this.username = "";
|
||||
}
|
||||
|
||||
@Override
|
||||
public WiredTriggerType getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void serializeWiredData(ServerMessage message, Room room) {
|
||||
message.appendBoolean(false);
|
||||
message.appendInt(5);
|
||||
message.appendInt(0);
|
||||
message.appendInt(this.getBaseItem().getSpriteId());
|
||||
message.appendInt(this.getId());
|
||||
message.appendString(this.username);
|
||||
message.appendInt(0);
|
||||
message.appendInt(0);
|
||||
message.appendInt(this.getType().code);
|
||||
message.appendInt(0);
|
||||
message.appendInt(0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean saveData(WiredSettings settings) {
|
||||
this.username = settings.getStringParam();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isTriggeredByRoomUnit() {
|
||||
return true;
|
||||
}
|
||||
|
||||
static class JsonData {
|
||||
String username;
|
||||
|
||||
public JsonData(String username) {
|
||||
this.username = username;
|
||||
}
|
||||
}
|
||||
}
|
||||
+217
@@ -0,0 +1,217 @@
|
||||
package com.eu.habbo.habbohotel.items.interactions.wired.triggers;
|
||||
|
||||
import com.eu.habbo.habbohotel.items.Item;
|
||||
import com.eu.habbo.habbohotel.items.interactions.InteractionWiredTrigger;
|
||||
import com.eu.habbo.habbohotel.items.interactions.wired.WiredSettings;
|
||||
import com.eu.habbo.habbohotel.rooms.Room;
|
||||
import com.eu.habbo.habbohotel.rooms.RoomUnit;
|
||||
import com.eu.habbo.habbohotel.users.HabboItem;
|
||||
import com.eu.habbo.habbohotel.wired.WiredTriggerType;
|
||||
import com.eu.habbo.habbohotel.wired.WiredUserActionType;
|
||||
import com.eu.habbo.habbohotel.wired.core.WiredEvent;
|
||||
import com.eu.habbo.habbohotel.wired.core.WiredManager;
|
||||
import com.eu.habbo.messages.ServerMessage;
|
||||
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
|
||||
public class WiredTriggerHabboPerformsAction extends InteractionWiredTrigger {
|
||||
private static final WiredTriggerType type = WiredTriggerType.USER_PERFORMS_ACTION;
|
||||
private static final int DEFAULT_ACTION = WiredUserActionType.WAVE;
|
||||
|
||||
private int selectedAction = DEFAULT_ACTION;
|
||||
private boolean signFilterEnabled = false;
|
||||
private int signId = 0;
|
||||
private boolean danceFilterEnabled = false;
|
||||
private int danceId = 1;
|
||||
|
||||
public WiredTriggerHabboPerformsAction(ResultSet set, Item baseItem) throws SQLException {
|
||||
super(set, baseItem);
|
||||
}
|
||||
|
||||
public WiredTriggerHabboPerformsAction(int id, int userId, Item item, String extradata, int limitedStack, int limitedSells) {
|
||||
super(id, userId, item, extradata, limitedStack, limitedSells);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matches(HabboItem triggerItem, WiredEvent event) {
|
||||
if (!event.getActor().isPresent()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (event.getActionId() != this.selectedAction) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (this.selectedAction == WiredUserActionType.SIGN && this.signFilterEnabled) {
|
||||
return event.getActionParameter() == this.signId;
|
||||
}
|
||||
|
||||
if (this.selectedAction == WiredUserActionType.DANCE && this.danceFilterEnabled) {
|
||||
return event.getActionParameter() == this.danceId;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
@Override
|
||||
public boolean execute(RoomUnit roomUnit, Room room, Object[] stuff) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getWiredData() {
|
||||
return WiredManager.getGson().toJson(new JsonData(
|
||||
this.selectedAction,
|
||||
this.signFilterEnabled,
|
||||
this.signId,
|
||||
this.danceFilterEnabled,
|
||||
this.danceId
|
||||
));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadWiredData(ResultSet set, Room room) throws SQLException {
|
||||
this.resetSettings();
|
||||
|
||||
String wiredData = set.getString("wired_data");
|
||||
|
||||
if (wiredData != null && wiredData.startsWith("{")) {
|
||||
JsonData data = WiredManager.getGson().fromJson(wiredData, JsonData.class);
|
||||
|
||||
if (data == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.selectedAction = normalizeAction(data.selectedAction);
|
||||
this.signFilterEnabled = data.signFilterEnabled;
|
||||
this.signId = normalizeSignId(data.signId);
|
||||
this.danceFilterEnabled = data.danceFilterEnabled;
|
||||
this.danceId = normalizeDanceId(data.danceId);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPickUp() {
|
||||
this.resetSettings();
|
||||
}
|
||||
|
||||
@Override
|
||||
public WiredTriggerType getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void serializeWiredData(ServerMessage message, Room room) {
|
||||
message.appendBoolean(false);
|
||||
message.appendInt(5);
|
||||
message.appendInt(0);
|
||||
message.appendInt(this.getBaseItem().getSpriteId());
|
||||
message.appendInt(this.getId());
|
||||
message.appendString("");
|
||||
message.appendInt(5);
|
||||
message.appendInt(this.selectedAction);
|
||||
message.appendInt(this.signFilterEnabled ? 1 : 0);
|
||||
message.appendInt(this.signId);
|
||||
message.appendInt(this.danceFilterEnabled ? 1 : 0);
|
||||
message.appendInt(this.danceId);
|
||||
message.appendInt(0);
|
||||
message.appendInt(this.getType().code);
|
||||
message.appendInt(0);
|
||||
message.appendInt(0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean saveData(WiredSettings settings) {
|
||||
int[] intParams = settings.getIntParams();
|
||||
|
||||
this.resetSettings();
|
||||
|
||||
if (intParams.length > 0) {
|
||||
this.selectedAction = normalizeAction(intParams[0]);
|
||||
}
|
||||
|
||||
if (intParams.length > 1) {
|
||||
this.signFilterEnabled = (intParams[1] == 1);
|
||||
}
|
||||
|
||||
if (intParams.length > 2) {
|
||||
this.signId = normalizeSignId(intParams[2]);
|
||||
}
|
||||
|
||||
if (intParams.length > 3) {
|
||||
this.danceFilterEnabled = (intParams[3] == 1);
|
||||
}
|
||||
|
||||
if (intParams.length > 4) {
|
||||
this.danceId = normalizeDanceId(intParams[4]);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isTriggeredByRoomUnit() {
|
||||
return true;
|
||||
}
|
||||
|
||||
private void resetSettings() {
|
||||
this.selectedAction = DEFAULT_ACTION;
|
||||
this.signFilterEnabled = false;
|
||||
this.signId = 0;
|
||||
this.danceFilterEnabled = false;
|
||||
this.danceId = 1;
|
||||
}
|
||||
|
||||
private int normalizeAction(int action) {
|
||||
switch (action) {
|
||||
case WiredUserActionType.WAVE:
|
||||
case WiredUserActionType.BLOW_KISS:
|
||||
case WiredUserActionType.LAUGH:
|
||||
case WiredUserActionType.AWAKE:
|
||||
case WiredUserActionType.RELAX:
|
||||
case WiredUserActionType.SIT:
|
||||
case WiredUserActionType.STAND:
|
||||
case WiredUserActionType.LAY:
|
||||
case WiredUserActionType.SIGN:
|
||||
case WiredUserActionType.DANCE:
|
||||
case WiredUserActionType.THUMB_UP:
|
||||
return action;
|
||||
default:
|
||||
return DEFAULT_ACTION;
|
||||
}
|
||||
}
|
||||
|
||||
private int normalizeSignId(int signId) {
|
||||
if (signId < 0 || signId > 17) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return signId;
|
||||
}
|
||||
|
||||
private int normalizeDanceId(int danceId) {
|
||||
if (danceId < 1 || danceId > 4) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
return danceId;
|
||||
}
|
||||
|
||||
static class JsonData {
|
||||
int selectedAction;
|
||||
boolean signFilterEnabled;
|
||||
int signId;
|
||||
boolean danceFilterEnabled;
|
||||
int danceId;
|
||||
|
||||
public JsonData(int selectedAction, boolean signFilterEnabled, int signId, boolean danceFilterEnabled, int danceId) {
|
||||
this.selectedAction = selectedAction;
|
||||
this.signFilterEnabled = signFilterEnabled;
|
||||
this.signId = signId;
|
||||
this.danceFilterEnabled = danceFilterEnabled;
|
||||
this.danceId = danceId;
|
||||
}
|
||||
}
|
||||
}
|
||||
+111
-6
@@ -1,5 +1,6 @@
|
||||
package com.eu.habbo.habbohotel.items.interactions.wired.triggers;
|
||||
|
||||
import com.eu.habbo.Emulator;
|
||||
import com.eu.habbo.habbohotel.items.Item;
|
||||
import com.eu.habbo.habbohotel.items.interactions.InteractionWiredTrigger;
|
||||
import com.eu.habbo.habbohotel.items.interactions.wired.WiredSettings;
|
||||
@@ -11,27 +12,49 @@ import com.eu.habbo.habbohotel.wired.WiredTriggerType;
|
||||
import com.eu.habbo.habbohotel.wired.core.WiredEvent;
|
||||
import com.eu.habbo.habbohotel.wired.core.WiredManager;
|
||||
import com.eu.habbo.messages.ServerMessage;
|
||||
import com.eu.habbo.messages.incoming.wired.WiredTriggerSaveException;
|
||||
import com.eu.habbo.messages.outgoing.rooms.items.ItemStateComposer;
|
||||
import gnu.trove.set.hash.THashSet;
|
||||
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class WiredTriggerReceiveSignal extends InteractionWiredTrigger {
|
||||
public static final WiredTriggerType type = WiredTriggerType.RECEIVE_SIGNAL;
|
||||
|
||||
private static final String ANTENNA_INTERACTION = "antenna";
|
||||
private static final long ACTIVATION_PULSE_MS = 300L;
|
||||
|
||||
private int channel = 0; // signal channel (0-based)
|
||||
private THashSet<HabboItem> items;
|
||||
private final AtomicLong activationToken = new AtomicLong();
|
||||
|
||||
public WiredTriggerReceiveSignal(ResultSet set, Item baseItem) throws SQLException {
|
||||
super(set, baseItem);
|
||||
this.items = new THashSet<>();
|
||||
}
|
||||
|
||||
public WiredTriggerReceiveSignal(int id, int userId, Item item, String extradata, int limitedStack, int limitedSells) {
|
||||
super(id, userId, item, extradata, limitedStack, limitedSells);
|
||||
this.items = new THashSet<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matches(HabboItem triggerItem, WiredEvent event) {
|
||||
return event.getType() == WiredEvent.Type.SIGNAL_RECEIVED
|
||||
&& event.getSignalChannel() == this.channel;
|
||||
if (event.getType() != WiredEvent.Type.SIGNAL_RECEIVED) return false;
|
||||
|
||||
if (!this.items.isEmpty()) {
|
||||
int signalChannel = event.getSignalChannel();
|
||||
for (HabboItem antenna : this.items) {
|
||||
if (antenna != null && antenna.getId() == signalChannel) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
return event.getSignalChannel() == this.channel;
|
||||
}
|
||||
|
||||
public int getChannel() {
|
||||
@@ -59,14 +82,33 @@ public class WiredTriggerReceiveSignal extends InteractionWiredTrigger {
|
||||
int senderCount = 0;
|
||||
try {
|
||||
if (room != null && room.getRoomSpecialTypes() != null) {
|
||||
if (!this.items.isEmpty()) {
|
||||
for (HabboItem item : this.items) {
|
||||
senderCount += room.getRoomSpecialTypes().countSendersTargetingReceiver(item.getId());
|
||||
}
|
||||
} else {
|
||||
senderCount = room.getRoomSpecialTypes().countSendersTargetingReceiver(this.getId());
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
}
|
||||
|
||||
THashSet<HabboItem> itemsToRemove = new THashSet<>();
|
||||
for (HabboItem item : this.items) {
|
||||
if (item.getRoomId() != this.getRoomId() || room.getHabboItem(item.getId()) == null) {
|
||||
itemsToRemove.add(item);
|
||||
}
|
||||
}
|
||||
for (HabboItem item : itemsToRemove) {
|
||||
this.items.remove(item);
|
||||
}
|
||||
|
||||
message.appendBoolean(false);
|
||||
message.appendInt(0);
|
||||
message.appendInt(0);
|
||||
message.appendInt(WiredManager.MAXIMUM_FURNI_SELECTION);
|
||||
message.appendInt(this.items.size());
|
||||
for (HabboItem item : this.items) {
|
||||
message.appendInt(item.getId());
|
||||
}
|
||||
message.appendInt(this.getBaseItem().getSpriteId());
|
||||
message.appendInt(this.getId());
|
||||
message.appendString("");
|
||||
@@ -82,37 +124,100 @@ public class WiredTriggerReceiveSignal extends InteractionWiredTrigger {
|
||||
|
||||
@Override
|
||||
public boolean saveData(WiredSettings settings) {
|
||||
this.items.clear();
|
||||
|
||||
Room room = Emulator.getGameEnvironment().getRoomManager().getRoom(this.getRoomId());
|
||||
int count = settings.getFurniIds().length;
|
||||
|
||||
for (int i = 0; i < count; i++) {
|
||||
HabboItem item = room.getHabboItem(settings.getFurniIds()[i]);
|
||||
if (item == null) continue;
|
||||
if (!isAntennaItem(item)) throw new WiredTriggerSaveException("wiredfurni.error.require_antenna_furni");
|
||||
this.items.add(item);
|
||||
}
|
||||
|
||||
int[] params = settings.getIntParams();
|
||||
this.channel = params.length > 0 ? params[0] : 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void activateBox(Room room, RoomUnit roomUnit, long millis) {
|
||||
if (roomUnit != null) {
|
||||
this.addUserExecutionCache(roomUnit.getId(), millis);
|
||||
}
|
||||
|
||||
if (room == null || room.isHideWired() || this.getBaseItem().getStateCount() <= 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
final long token = this.activationToken.incrementAndGet();
|
||||
|
||||
if ("1".equals(this.getExtradata())) {
|
||||
this.setExtradata("0");
|
||||
room.sendComposer(new ItemStateComposer(this).compose());
|
||||
}
|
||||
|
||||
this.setExtradata("1");
|
||||
room.sendComposer(new ItemStateComposer(this).compose());
|
||||
|
||||
Emulator.getThreading().run(() -> {
|
||||
if (!room.isLoaded()) return;
|
||||
if (this.activationToken.get() != token) return;
|
||||
|
||||
this.setExtradata("0");
|
||||
room.sendComposer(new ItemStateComposer(this).compose());
|
||||
}, ACTIVATION_PULSE_MS);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getWiredData() {
|
||||
return WiredManager.getGson().toJson(new JsonData(channel));
|
||||
return WiredManager.getGson().toJson(new JsonData(
|
||||
channel,
|
||||
this.items.stream().map(HabboItem::getId).collect(Collectors.toList())
|
||||
));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadWiredData(ResultSet set, Room room) throws SQLException {
|
||||
this.items = new THashSet<>();
|
||||
String wiredData = set.getString("wired_data");
|
||||
if (wiredData != null && wiredData.startsWith("{")) {
|
||||
JsonData data = WiredManager.getGson().fromJson(wiredData, JsonData.class);
|
||||
this.channel = data.channel;
|
||||
if (data.itemIds != null) {
|
||||
for (Integer id : data.itemIds) {
|
||||
HabboItem item = room.getHabboItem(id);
|
||||
if (item != null) this.items.add(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPickUp() {
|
||||
this.channel = 0;
|
||||
this.items.clear();
|
||||
}
|
||||
|
||||
private boolean isAntennaItem(HabboItem item) {
|
||||
if (item == null || item.getBaseItem() == null || item.getBaseItem().getInteractionType() == null) return false;
|
||||
String interaction = item.getBaseItem().getInteractionType().getName();
|
||||
if (interaction == null) return false;
|
||||
|
||||
String normalized = interaction.toLowerCase();
|
||||
return normalized.equals(ANTENNA_INTERACTION);
|
||||
}
|
||||
|
||||
static class JsonData {
|
||||
int channel;
|
||||
List<Integer> itemIds;
|
||||
|
||||
public JsonData() {}
|
||||
|
||||
public JsonData(int channel) {
|
||||
public JsonData(int channel, List<Integer> itemIds) {
|
||||
this.channel = channel;
|
||||
this.itemIds = itemIds;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -139,7 +139,7 @@ public class WiredTriggerRepeaterLong extends InteractionWiredTrigger implements
|
||||
// Fire when elapsed time is a multiple of repeat time
|
||||
if (elapsedMs % this.repeatTime == 0) {
|
||||
if (this.getRoomId() != 0 && room.isLoaded()) {
|
||||
WiredManager.triggerTimerRepeat(room, this);
|
||||
WiredManager.triggerTimerRepeatLong(room, this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+125
@@ -0,0 +1,125 @@
|
||||
package com.eu.habbo.habbohotel.items.interactions.wired.triggers;
|
||||
|
||||
import com.eu.habbo.habbohotel.items.Item;
|
||||
import com.eu.habbo.habbohotel.items.interactions.InteractionWiredEffect;
|
||||
import com.eu.habbo.habbohotel.items.interactions.wired.WiredSettings;
|
||||
import com.eu.habbo.habbohotel.rooms.Room;
|
||||
import com.eu.habbo.habbohotel.wired.WiredTriggerType;
|
||||
import com.eu.habbo.habbohotel.wired.core.WiredManager;
|
||||
import com.eu.habbo.messages.ServerMessage;
|
||||
import gnu.trove.procedure.TObjectProcedure;
|
||||
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class WiredTriggerRepeaterShort extends WiredTriggerRepeater {
|
||||
public static final WiredTriggerType type = WiredTriggerType.PERIODICALLY_SHORT;
|
||||
public static final int STEP_MS = 50;
|
||||
public static final int DEFAULT_DELAY = 10 * STEP_MS;
|
||||
public static final int MIN_DELAY = STEP_MS;
|
||||
public static final int MAX_DELAY = 10 * STEP_MS;
|
||||
|
||||
public WiredTriggerRepeaterShort(ResultSet set, Item baseItem) throws SQLException {
|
||||
super(set, baseItem);
|
||||
this.repeatTime = DEFAULT_DELAY;
|
||||
}
|
||||
|
||||
public WiredTriggerRepeaterShort(int id, int userId, Item item, String extradata, int limitedStack, int limitedSells) {
|
||||
super(id, userId, item, extradata, limitedStack, limitedSells);
|
||||
this.repeatTime = DEFAULT_DELAY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadWiredData(ResultSet set, Room room) throws SQLException {
|
||||
String wiredData = set.getString("wired_data");
|
||||
|
||||
if (wiredData != null && wiredData.startsWith("{")) {
|
||||
JsonData data = WiredManager.getGson().fromJson(wiredData, JsonData.class);
|
||||
this.repeatTime = (data != null) ? data.repeatTime : DEFAULT_DELAY;
|
||||
} else if (wiredData != null && wiredData.length() >= 1) {
|
||||
this.repeatTime = Integer.parseInt(wiredData);
|
||||
} else {
|
||||
this.repeatTime = DEFAULT_DELAY;
|
||||
}
|
||||
|
||||
this.repeatTime = clampRepeatTime(this.repeatTime);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPickUp() {
|
||||
this.repeatTime = DEFAULT_DELAY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WiredTriggerType getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void serializeWiredData(ServerMessage message, Room room) {
|
||||
message.appendBoolean(false);
|
||||
message.appendInt(5);
|
||||
message.appendInt(0);
|
||||
message.appendInt(this.getBaseItem().getSpriteId());
|
||||
message.appendInt(this.getId());
|
||||
message.appendString("");
|
||||
message.appendInt(1);
|
||||
message.appendInt(this.repeatTime / STEP_MS);
|
||||
message.appendInt(0);
|
||||
message.appendInt(this.getType().code);
|
||||
|
||||
if (!this.isTriggeredByRoomUnit()) {
|
||||
List<Integer> invalidTriggers = new ArrayList<>();
|
||||
room.getRoomSpecialTypes().getEffects(this.getX(), this.getY()).forEach(new TObjectProcedure<InteractionWiredEffect>() {
|
||||
@Override
|
||||
public boolean execute(InteractionWiredEffect object) {
|
||||
if (object.requiresTriggeringUser()) {
|
||||
invalidTriggers.add(object.getBaseItem().getSpriteId());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
});
|
||||
message.appendInt(invalidTriggers.size());
|
||||
for (Integer i : invalidTriggers) {
|
||||
message.appendInt(i);
|
||||
}
|
||||
} else {
|
||||
message.appendInt(0);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean saveData(WiredSettings settings) {
|
||||
if (settings.getIntParams().length < 1) return false;
|
||||
|
||||
int newRepeatTime = settings.getIntParams()[0] * STEP_MS;
|
||||
this.repeatTime = clampRepeatTime(newRepeatTime);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onWiredTick(Room room, long tickCount, int tickIntervalMs) {
|
||||
long elapsedMs = tickCount * tickIntervalMs;
|
||||
|
||||
if (elapsedMs % this.repeatTime == 0) {
|
||||
if (this.getRoomId() != 0 && room.isLoaded()) {
|
||||
WiredManager.triggerTimerRepeatShort(room, this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private int clampRepeatTime(int repeatTime) {
|
||||
if (repeatTime < MIN_DELAY) {
|
||||
return DEFAULT_DELAY;
|
||||
}
|
||||
|
||||
if (repeatTime > MAX_DELAY) {
|
||||
return MAX_DELAY;
|
||||
}
|
||||
|
||||
return repeatTime;
|
||||
}
|
||||
}
|
||||
@@ -15,6 +15,8 @@ import com.eu.habbo.habbohotel.pets.PetManager;
|
||||
import com.eu.habbo.habbohotel.users.DanceType;
|
||||
import com.eu.habbo.habbohotel.users.Habbo;
|
||||
import com.eu.habbo.habbohotel.users.HabboItem;
|
||||
import com.eu.habbo.habbohotel.wired.WiredUserActionType;
|
||||
import com.eu.habbo.habbohotel.wired.core.WiredManager;
|
||||
import com.eu.habbo.messages.ISerialize;
|
||||
import com.eu.habbo.messages.ServerMessage;
|
||||
import com.eu.habbo.messages.outgoing.guilds.GuildInfoComposer;
|
||||
@@ -1874,11 +1876,15 @@ public class Room implements Comparable<Room>, ISerialize, Runnable {
|
||||
}
|
||||
|
||||
public void muteHabbo(Habbo habbo, int minutes) {
|
||||
this.rightsManager.muteHabbo(habbo, minutes);
|
||||
this.chatManager.muteHabbo(habbo, minutes);
|
||||
}
|
||||
|
||||
public void unmuteHabbo(Habbo habbo) {
|
||||
this.chatManager.unmuteHabbo(habbo);
|
||||
}
|
||||
|
||||
public boolean isMuted(Habbo habbo) {
|
||||
return this.rightsManager.isMuted(habbo);
|
||||
return this.chatManager.isMuted(habbo);
|
||||
}
|
||||
|
||||
public void habboEntered(Habbo habbo) {
|
||||
@@ -2162,6 +2168,7 @@ public class Room implements Comparable<Room>, ISerialize, Runnable {
|
||||
- habbo.getRoomUnit().getBodyRotation().getValue() % 2]);
|
||||
habbo.getRoomUnit().setStatus(RoomUnitStatus.SIT, 0.5 + "");
|
||||
this.sendComposer(new RoomUserStatusComposer(habbo.getRoomUnit()).compose());
|
||||
WiredManager.triggerUserPerformsAction(this, habbo.getRoomUnit(), WiredUserActionType.SIT, -1);
|
||||
}
|
||||
|
||||
public void makeStand(Habbo habbo) {
|
||||
@@ -2171,12 +2178,19 @@ public class Room implements Comparable<Room>, ISerialize, Runnable {
|
||||
|
||||
HabboItem item = this.getTopItemAt(habbo.getRoomUnit().getX(), habbo.getRoomUnit().getY());
|
||||
if (item == null || !item.getBaseItem().allowSit() || !item.getBaseItem().allowLay()) {
|
||||
boolean wasSittingOrLaying = habbo.getRoomUnit().hasStatus(RoomUnitStatus.SIT)
|
||||
|| habbo.getRoomUnit().hasStatus(RoomUnitStatus.LAY);
|
||||
habbo.getRoomUnit().cmdStand = true;
|
||||
habbo.getRoomUnit().setBodyRotation(
|
||||
RoomUserRotation.values()[habbo.getRoomUnit().getBodyRotation().getValue()
|
||||
- habbo.getRoomUnit().getBodyRotation().getValue() % 2]);
|
||||
habbo.getRoomUnit().removeStatus(RoomUnitStatus.SIT);
|
||||
habbo.getRoomUnit().removeStatus(RoomUnitStatus.LAY);
|
||||
this.sendComposer(new RoomUserStatusComposer(habbo.getRoomUnit()).compose());
|
||||
|
||||
if (wasSittingOrLaying) {
|
||||
WiredManager.triggerUserPerformsAction(this, habbo.getRoomUnit(), WiredUserActionType.STAND, -1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -156,6 +156,15 @@ public class RoomChatManager {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a room mute from a Habbo.
|
||||
*/
|
||||
public void unmuteHabbo(Habbo habbo) {
|
||||
synchronized (this.mutedHabbos) {
|
||||
this.mutedHabbos.remove(habbo.getHabboInfo().getId());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a Habbo is muted.
|
||||
*/
|
||||
@@ -183,7 +192,8 @@ public class RoomChatManager {
|
||||
*/
|
||||
public int getMuteTimeRemaining(Habbo habbo) {
|
||||
if (this.mutedHabbos.containsKey(habbo.getHabboInfo().getId())) {
|
||||
return this.mutedHabbos.get(habbo.getHabboInfo().getId()) - Emulator.getIntUnixTimestamp();
|
||||
return Math.max(0,
|
||||
this.mutedHabbos.get(habbo.getHabboInfo().getId()) - Emulator.getIntUnixTimestamp());
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -298,7 +308,7 @@ public class RoomChatManager {
|
||||
|
||||
if (this.isMuted(habbo)) {
|
||||
habbo.getClient().sendResponse(new MutedWhisperComposer(
|
||||
this.mutedHabbos.get(habbo.getHabboInfo().getId()) - Emulator.getIntUnixTimestamp()));
|
||||
Math.max(1, this.getMuteTimeRemaining(habbo))));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -499,14 +499,18 @@ public class RoomManager {
|
||||
}
|
||||
|
||||
public void enterRoom(Habbo habbo, int roomId, String password) {
|
||||
this.enterRoom(habbo, roomId, password, false, null);
|
||||
this.enterRoom(habbo, roomId, password, false, null, false);
|
||||
}
|
||||
|
||||
public void enterRoom(Habbo habbo, int roomId, String password, boolean overrideChecks) {
|
||||
this.enterRoom(habbo, roomId, password, overrideChecks, null);
|
||||
this.enterRoom(habbo, roomId, password, overrideChecks, null, false);
|
||||
}
|
||||
|
||||
public void enterRoom(Habbo habbo, int roomId, String password, boolean overrideChecks, RoomTile doorLocation) {
|
||||
this.enterRoom(habbo, roomId, password, overrideChecks, doorLocation, false);
|
||||
}
|
||||
|
||||
public void enterRoom(Habbo habbo, int roomId, String password, boolean overrideChecks, RoomTile doorLocation, boolean isReconnectSpawn) {
|
||||
Room room = this.loadRoom(roomId, true);
|
||||
|
||||
if (room == null)
|
||||
@@ -547,7 +551,7 @@ public class RoomManager {
|
||||
room.hasRights(habbo) ||
|
||||
(room.getState().equals(RoomState.INVISIBLE) && room.hasRights(habbo)) ||
|
||||
(room.hasGuild() && room.getGuildRightLevel(habbo).isGreaterThan(RoomRightLevels.GUILD_RIGHTS))) {
|
||||
this.openRoom(habbo, room, doorLocation);
|
||||
this.openRoom(habbo, room, doorLocation, isReconnectSpawn);
|
||||
} else if (room.getState() == RoomState.LOCKED) {
|
||||
boolean rightsFound = false;
|
||||
|
||||
@@ -572,7 +576,7 @@ public class RoomManager {
|
||||
room.addToQueue(habbo);
|
||||
} else if (room.getState() == RoomState.PASSWORD) {
|
||||
if (room.getPassword().equalsIgnoreCase(password))
|
||||
this.openRoom(habbo, room, doorLocation);
|
||||
this.openRoom(habbo, room, doorLocation, isReconnectSpawn);
|
||||
else {
|
||||
habbo.getClient().sendResponse(new GenericErrorMessagesComposer(GenericErrorMessagesComposer.WRONG_PASSWORD_USED));
|
||||
habbo.getClient().sendResponse(new HotelViewComposer());
|
||||
@@ -585,6 +589,10 @@ public class RoomManager {
|
||||
}
|
||||
|
||||
void openRoom(Habbo habbo, Room room, RoomTile doorLocation) {
|
||||
this.openRoom(habbo, room, doorLocation, false);
|
||||
}
|
||||
|
||||
void openRoom(Habbo habbo, Room room, RoomTile doorLocation, boolean isReconnectSpawn) {
|
||||
if (room == null || room.getLayout() == null)
|
||||
return;
|
||||
|
||||
@@ -623,7 +631,13 @@ public class RoomManager {
|
||||
if (doorLocation == null) {
|
||||
habbo.getRoomUnit().setBodyRotation(RoomUserRotation.values()[room.getLayout().getDoorDirection()]);
|
||||
habbo.getRoomUnit().setHeadRotation(RoomUserRotation.values()[room.getLayout().getDoorDirection()]);
|
||||
} else if (isReconnectSpawn) {
|
||||
// Reconnect spawn: place at tile but keep normal room behavior
|
||||
// (user can still leave by door, no teleport flags)
|
||||
habbo.getRoomUnit().setBodyRotation(RoomUserRotation.values()[room.getLayout().getDoorDirection()]);
|
||||
habbo.getRoomUnit().setHeadRotation(RoomUserRotation.values()[room.getLayout().getDoorDirection()]);
|
||||
} else {
|
||||
// Furniture teleport spawn
|
||||
habbo.getRoomUnit().setCanLeaveRoomByDoor(false);
|
||||
habbo.getRoomUnit().isTeleporting = true;
|
||||
HabboItem topItem = room.getTopItemAt(doorLocation.x, doorLocation.y);
|
||||
|
||||
@@ -12,7 +12,9 @@ import com.eu.habbo.habbohotel.users.DanceType;
|
||||
import com.eu.habbo.habbohotel.users.Habbo;
|
||||
import com.eu.habbo.habbohotel.users.HabboGender;
|
||||
import com.eu.habbo.habbohotel.users.HabboItem;
|
||||
import com.eu.habbo.habbohotel.wired.core.WiredFreezeUtil;
|
||||
import com.eu.habbo.habbohotel.wired.core.WiredManager;
|
||||
import com.eu.habbo.habbohotel.wired.WiredUserActionType;
|
||||
import com.eu.habbo.messages.outgoing.generic.alerts.GenericErrorMessagesComposer;
|
||||
import com.eu.habbo.messages.outgoing.inventory.AddPetComposer;
|
||||
import com.eu.habbo.messages.outgoing.rooms.pets.RoomPetComposer;
|
||||
@@ -217,6 +219,10 @@ public class RoomUnitManager {
|
||||
return;
|
||||
}
|
||||
|
||||
if (habbo.getRoomUnit() != null) {
|
||||
WiredManager.triggerUserLeavesRoom(this.room, habbo.getRoomUnit());
|
||||
}
|
||||
|
||||
if (habbo.getRoomUnit() != null && habbo.getRoomUnit().getCurrentLocation() != null) {
|
||||
habbo.getRoomUnit().getCurrentLocation().removeUnit(habbo.getRoomUnit());
|
||||
}
|
||||
@@ -352,6 +358,7 @@ public class RoomUnitManager {
|
||||
}
|
||||
|
||||
double z = habbo.getRoomUnit().getCurrentLocation().getStackHeight();
|
||||
boolean hadLayStatus = habbo.getRoomUnit().hasStatus(RoomUnitStatus.LAY);
|
||||
|
||||
if (habbo.getRoomUnit().hasStatus(RoomUnitStatus.SIT)
|
||||
|| (topItem != null && topItem.getBaseItem().allowSit())) {
|
||||
@@ -413,6 +420,10 @@ public class RoomUnitManager {
|
||||
}
|
||||
|
||||
habbo.getRoomUnit().statusUpdate(true);
|
||||
|
||||
if (!hadLayStatus && habbo.getRoomUnit().hasStatus(RoomUnitStatus.LAY)) {
|
||||
WiredManager.triggerUserPerformsAction(this.room, habbo.getRoomUnit(), WiredUserActionType.LAY, -1);
|
||||
}
|
||||
}
|
||||
|
||||
if (!habbos.isEmpty()) {
|
||||
@@ -1299,6 +1310,8 @@ public class RoomUnitManager {
|
||||
*/
|
||||
public void teleportRoomUnitToLocation(RoomUnit roomUnit, short x, short y, double z) {
|
||||
if (this.room.isLoaded()) {
|
||||
WiredFreezeUtil.onTeleport(this.room, roomUnit);
|
||||
|
||||
RoomTile tile = this.room.getLayout().getTile(x, y);
|
||||
|
||||
if (z < tile.z) {
|
||||
@@ -1310,6 +1323,7 @@ public class RoomUnitManager {
|
||||
roomUnit.setZ(z);
|
||||
roomUnit.setPreviousLocationZ(z);
|
||||
this.room.updateRoomUnit(roomUnit);
|
||||
WiredFreezeUtil.restoreWalkState(roomUnit);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -25,7 +25,18 @@ public enum WiredConditionType {
|
||||
NOT_ACTOR_WEARS_EFFECT(23),
|
||||
DATE_RANGE(24),
|
||||
ACTOR_HAS_HANDITEM(25),
|
||||
MOVEMENT_VALIDATION(26); // i dont know what type it is but its needed
|
||||
MOVEMENT_VALIDATION(26), // i dont know what type it is but its needed
|
||||
COUNTER_TIME_MATCHES(27),
|
||||
USER_PERFORMS_ACTION(28),
|
||||
HAS_ALTITUDE(29),
|
||||
NOT_USER_PERFORMS_ACTION(30),
|
||||
NOT_ACTOR_HAS_HANDITEM(31),
|
||||
TRIGGERER_MATCH(32),
|
||||
NOT_TRIGGERER_MATCH(33),
|
||||
TEAM_HAS_SCORE(34),
|
||||
TEAM_HAS_RANK(35),
|
||||
MATCH_TIME(36),
|
||||
MATCH_DATE(37);
|
||||
|
||||
public final int code;
|
||||
|
||||
|
||||
@@ -32,7 +32,14 @@ public enum WiredEffectType {
|
||||
FURNI_BYTYPE_SELECTOR(30),
|
||||
USERS_AREA_SELECTOR(31),
|
||||
USERS_NEIGHBORHOOD_SELECTOR(32),
|
||||
SEND_SIGNAL(33);
|
||||
SEND_SIGNAL(33),
|
||||
FREEZE(34),
|
||||
UNFREEZE(35),
|
||||
FURNI_TO_USER(36),
|
||||
USER_TO_FURNI(37),
|
||||
FURNI_TO_FURNI(38),
|
||||
SET_ALTITUDE(39),
|
||||
RELATIVE_MOVE(40);
|
||||
|
||||
public final int code;
|
||||
|
||||
|
||||
@@ -285,53 +285,72 @@ public class WiredHandler {
|
||||
}
|
||||
}
|
||||
|
||||
private static void giveReward(Habbo habbo, WiredEffectGiveReward wiredBox, WiredGiveRewardItem reward) {
|
||||
if (wiredBox.limit > 0)
|
||||
wiredBox.given++;
|
||||
|
||||
private static void persistReward(int wiredId, int habboId, int rewardId, int timestamp) {
|
||||
try (Connection connection = Emulator.getDatabase().getDataSource().getConnection(); PreparedStatement statement = connection.prepareStatement("INSERT INTO wired_rewards_given (wired_item, user_id, reward_id, timestamp) VALUES ( ?, ?, ?, ?)")) {
|
||||
statement.setInt(1, wiredBox.getId());
|
||||
statement.setInt(2, habbo.getHabboInfo().getId());
|
||||
statement.setInt(3, reward.id);
|
||||
statement.setInt(4, Emulator.getIntUnixTimestamp());
|
||||
statement.setInt(1, wiredId);
|
||||
statement.setInt(2, habboId);
|
||||
statement.setInt(3, rewardId);
|
||||
statement.setInt(4, timestamp);
|
||||
statement.execute();
|
||||
} catch (SQLException e) {
|
||||
LOGGER.error("Caught SQL exception", e);
|
||||
}
|
||||
}
|
||||
|
||||
private static void completeReward(Habbo habbo, WiredEffectGiveReward wiredBox, WiredGiveRewardItem reward, int successCode) {
|
||||
if (wiredBox.limit > 0)
|
||||
wiredBox.given++;
|
||||
|
||||
persistReward(wiredBox.getId(), habbo.getHabboInfo().getId(), reward.id, Emulator.getIntUnixTimestamp());
|
||||
habbo.getClient().sendResponse(new WiredRewardAlertComposer(successCode));
|
||||
}
|
||||
|
||||
private static boolean giveReward(Habbo habbo, WiredEffectGiveReward wiredBox, WiredGiveRewardItem reward) {
|
||||
if (reward.badge) {
|
||||
UserWiredRewardReceived rewardReceived = new UserWiredRewardReceived(habbo, wiredBox, "badge", reward.data);
|
||||
if (Emulator.getPluginManager().fireEvent(rewardReceived).isCancelled())
|
||||
return;
|
||||
return false;
|
||||
|
||||
if (rewardReceived.value.isEmpty())
|
||||
return;
|
||||
return false;
|
||||
|
||||
if (habbo.getInventory().getBadgesComponent().hasBadge(rewardReceived.value))
|
||||
return;
|
||||
if (habbo.getInventory().getBadgesComponent().hasBadge(rewardReceived.value)) {
|
||||
habbo.getClient().sendResponse(new WiredRewardAlertComposer(WiredRewardAlertComposer.REWARD_ALREADY_RECEIVED));
|
||||
return false;
|
||||
}
|
||||
|
||||
HabboBadge badge = new HabboBadge(0, rewardReceived.value, 0, habbo);
|
||||
Emulator.getThreading().run(badge);
|
||||
habbo.getInventory().getBadgesComponent().addBadge(badge);
|
||||
habbo.getClient().sendResponse(new AddUserBadgeComposer(badge));
|
||||
habbo.getClient().sendResponse(new WiredRewardAlertComposer(WiredRewardAlertComposer.REWARD_RECEIVED_BADGE));
|
||||
} else {
|
||||
completeReward(habbo, wiredBox, reward, WiredRewardAlertComposer.REWARD_RECEIVED_BADGE);
|
||||
return true;
|
||||
}
|
||||
|
||||
String[] data = reward.data.split("#");
|
||||
|
||||
if (data.length == 2) {
|
||||
if (data.length != 2)
|
||||
return false;
|
||||
|
||||
UserWiredRewardReceived rewardReceived = new UserWiredRewardReceived(habbo, wiredBox, data[0], data[1]);
|
||||
if (Emulator.getPluginManager().fireEvent(rewardReceived).isCancelled())
|
||||
return;
|
||||
return false;
|
||||
|
||||
if (rewardReceived.value.isEmpty())
|
||||
return;
|
||||
return false;
|
||||
|
||||
if (rewardReceived.type.equalsIgnoreCase("credits")) {
|
||||
int credits = Integer.parseInt(rewardReceived.value);
|
||||
habbo.giveCredits(credits);
|
||||
habbo.giveCredits(Integer.parseInt(rewardReceived.value));
|
||||
completeReward(habbo, wiredBox, reward, WiredRewardAlertComposer.REWARD_RECEIVED_ITEM);
|
||||
return true;
|
||||
} else if (rewardReceived.type.equalsIgnoreCase("diamonds") || rewardReceived.type.equalsIgnoreCase("diamond")) {
|
||||
habbo.givePoints(5, Integer.parseInt(rewardReceived.value));
|
||||
completeReward(habbo, wiredBox, reward, WiredRewardAlertComposer.REWARD_RECEIVED_ITEM);
|
||||
return true;
|
||||
} else if (rewardReceived.type.equalsIgnoreCase("pixels")) {
|
||||
int pixels = Integer.parseInt(rewardReceived.value);
|
||||
habbo.givePixels(pixels);
|
||||
habbo.givePixels(Integer.parseInt(rewardReceived.value));
|
||||
completeReward(habbo, wiredBox, reward, WiredRewardAlertComposer.REWARD_RECEIVED_ITEM);
|
||||
return true;
|
||||
} else if (rewardReceived.type.startsWith("points")) {
|
||||
int points = Integer.parseInt(rewardReceived.value);
|
||||
int type = 5;
|
||||
@@ -342,31 +361,39 @@ public class WiredHandler {
|
||||
}
|
||||
|
||||
habbo.givePoints(type, points);
|
||||
completeReward(habbo, wiredBox, reward, WiredRewardAlertComposer.REWARD_RECEIVED_ITEM);
|
||||
return true;
|
||||
} else if (rewardReceived.type.equalsIgnoreCase("furni")) {
|
||||
Item baseItem = Emulator.getGameEnvironment().getItemManager().getItem(Integer.parseInt(rewardReceived.value));
|
||||
if (baseItem != null) {
|
||||
HabboItem item = Emulator.getGameEnvironment().getItemManager().createItem(habbo.getHabboInfo().getId(), baseItem, 0, 0, "");
|
||||
if (baseItem == null)
|
||||
return false;
|
||||
|
||||
HabboItem item = Emulator.getGameEnvironment().getItemManager().createItem(habbo.getHabboInfo().getId(), baseItem, 0, 0, "");
|
||||
if (item == null)
|
||||
return false;
|
||||
|
||||
if (item != null) {
|
||||
habbo.getClient().sendResponse(new AddHabboItemComposer(item));
|
||||
habbo.getClient().getHabbo().getInventory().getItemsComponent().addItem(item);
|
||||
habbo.getClient().sendResponse(new PurchaseOKComposer(null));
|
||||
habbo.getClient().sendResponse(new InventoryRefreshComposer());
|
||||
habbo.getClient().sendResponse(new WiredRewardAlertComposer(WiredRewardAlertComposer.REWARD_RECEIVED_ITEM));
|
||||
}
|
||||
}
|
||||
completeReward(habbo, wiredBox, reward, WiredRewardAlertComposer.REWARD_RECEIVED_ITEM);
|
||||
return true;
|
||||
} else if (rewardReceived.type.equalsIgnoreCase("respect")) {
|
||||
habbo.getHabboStats().respectPointsReceived += Integer.parseInt(rewardReceived.value);
|
||||
completeReward(habbo, wiredBox, reward, WiredRewardAlertComposer.REWARD_RECEIVED_ITEM);
|
||||
return true;
|
||||
} else if (rewardReceived.type.equalsIgnoreCase("cata")) {
|
||||
CatalogItem item = Emulator.getGameEnvironment().getCatalogManager().getCatalogItem(Integer.parseInt(rewardReceived.value));
|
||||
|
||||
if (item != null) {
|
||||
if (item == null)
|
||||
return false;
|
||||
|
||||
Emulator.getGameEnvironment().getCatalogManager().purchaseItem(null, item, habbo, 1, "", true);
|
||||
completeReward(habbo, wiredBox, reward, WiredRewardAlertComposer.REWARD_RECEIVED_ITEM);
|
||||
return true;
|
||||
}
|
||||
habbo.getClient().sendResponse(new WiredRewardAlertComposer(WiredRewardAlertComposer.REWARD_RECEIVED_ITEM));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static boolean getReward(Habbo habbo, WiredEffectGiveReward wiredBox) {
|
||||
@@ -433,22 +460,26 @@ public class WiredHandler {
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
giveReward(habbo, wiredBox, item);
|
||||
return true;
|
||||
return giveReward(habbo, wiredBox, item);
|
||||
}
|
||||
}
|
||||
|
||||
habbo.getClient().sendResponse(new WiredRewardAlertComposer(WiredRewardAlertComposer.REWARD_ALL_COLLECTED));
|
||||
return false;
|
||||
} else {
|
||||
int randomNumber = Emulator.getRandom().nextInt(101);
|
||||
|
||||
int count = 0;
|
||||
for (WiredGiveRewardItem item : wiredBox.rewardItems) {
|
||||
if (randomNumber >= count && randomNumber <= (count + item.probability)) {
|
||||
giveReward(habbo, wiredBox, item);
|
||||
return true;
|
||||
return giveReward(habbo, wiredBox, item);
|
||||
}
|
||||
|
||||
count += item.probability;
|
||||
}
|
||||
|
||||
habbo.getClient().sendResponse(new WiredRewardAlertComposer(WiredRewardAlertComposer.UNLUCKY_NO_REWARD));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -466,7 +497,7 @@ public class WiredHandler {
|
||||
room.getRoomSpecialTypes().getTriggers().forEach(t -> {
|
||||
if (t == null) return;
|
||||
|
||||
if (t.getType() == WiredTriggerType.AT_GIVEN_TIME || t.getType() == WiredTriggerType.PERIODICALLY || t.getType() == WiredTriggerType.PERIODICALLY_LONG) {
|
||||
if (t.getType() == WiredTriggerType.AT_GIVEN_TIME || t.getType() == WiredTriggerType.PERIODICALLY || t.getType() == WiredTriggerType.PERIODICALLY_LONG || t.getType() == WiredTriggerType.PERIODICALLY_SHORT) {
|
||||
((WiredTriggerReset) t).resetTimer();
|
||||
}
|
||||
});
|
||||
|
||||
@@ -15,6 +15,12 @@ public enum WiredTriggerType {
|
||||
PERIODICALLY_LONG(12),
|
||||
BOT_REACHED_STF(13),
|
||||
BOT_REACHED_AVTR(14),
|
||||
LEAVE_ROOM(16),
|
||||
PERIODICALLY_SHORT(17),
|
||||
CLICKS_FURNI(18),
|
||||
CLICKS_TILE(19),
|
||||
CLICKS_USER(20),
|
||||
USER_PERFORMS_ACTION(21),
|
||||
SAY_COMMAND(0),
|
||||
IDLES(11),
|
||||
UNIDLES(11),
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
package com.eu.habbo.habbohotel.wired;
|
||||
|
||||
public final class WiredUserActionType {
|
||||
public static final int WAVE = 1;
|
||||
public static final int BLOW_KISS = 2;
|
||||
public static final int LAUGH = 3;
|
||||
public static final int AWAKE = 4;
|
||||
public static final int RELAX = 5;
|
||||
public static final int SIT = 6;
|
||||
public static final int STAND = 7;
|
||||
public static final int LAY = 8;
|
||||
public static final int SIGN = 9;
|
||||
public static final int DANCE = 10;
|
||||
public static final int THUMB_UP = 11;
|
||||
|
||||
private WiredUserActionType() {
|
||||
}
|
||||
}
|
||||
@@ -214,24 +214,16 @@ public final class WiredEngine {
|
||||
// Initial step for trigger
|
||||
state.step();
|
||||
|
||||
// Activate the trigger box animation
|
||||
if (stack.triggerItem() instanceof InteractionWiredTrigger) {
|
||||
InteractionWiredTrigger trigger = (InteractionWiredTrigger) stack.triggerItem();
|
||||
trigger.activateBox(room, event.getActor().orElse(null), currentTime);
|
||||
}
|
||||
|
||||
debug(room, "Trigger matched: {} at item {} (conditions: {}, effects: {})",
|
||||
event.getType(),
|
||||
stack.triggerItem() != null ? stack.triggerItem().getId() : "null",
|
||||
stack.conditions().size(),
|
||||
stack.effects().size());
|
||||
|
||||
// Activate extras (for their animation)
|
||||
activateExtras(room, stack.triggerItem(), event.getActor().orElse(null), currentTime);
|
||||
|
||||
// Run selectors before conditions so targets are available
|
||||
List<InteractionWiredEffect> executedSelectors = Collections.emptyList();
|
||||
if (stack.hasEffects()) {
|
||||
executeSelectors(stack, ctx, currentTime);
|
||||
executedSelectors = executeSelectors(stack, ctx);
|
||||
}
|
||||
|
||||
// Evaluate conditions
|
||||
@@ -253,6 +245,17 @@ public final class WiredEngine {
|
||||
return false;
|
||||
}
|
||||
|
||||
RoomUnit actor = event.getActor().orElse(null);
|
||||
|
||||
// Only show the trigger/selector activation when the stack is actually allowed to continue.
|
||||
if (stack.triggerItem() instanceof InteractionWiredTrigger) {
|
||||
InteractionWiredTrigger trigger = (InteractionWiredTrigger) stack.triggerItem();
|
||||
trigger.activateBox(room, actor, currentTime);
|
||||
}
|
||||
|
||||
activateExtras(room, stack.triggerItem(), actor, currentTime);
|
||||
finalizeSelectors(executedSelectors, ctx, currentTime);
|
||||
|
||||
// Execute effects
|
||||
if (stack.hasEffects()) {
|
||||
executeEffects(stack, ctx, currentTime);
|
||||
@@ -420,9 +423,11 @@ public final class WiredEngine {
|
||||
/**
|
||||
* Execute selector effects before conditions so ctx.targets() is populated.
|
||||
*/
|
||||
private void executeSelectors(WiredStack stack, WiredContext ctx, long currentTime) {
|
||||
private List<InteractionWiredEffect> executeSelectors(WiredStack stack, WiredContext ctx) {
|
||||
List<IWiredEffect> effects = stack.effects();
|
||||
if (effects.isEmpty()) return;
|
||||
if (effects.isEmpty()) return Collections.emptyList();
|
||||
|
||||
List<InteractionWiredEffect> executedSelectors = new ArrayList<>();
|
||||
|
||||
for (IWiredEffect effect : effects) {
|
||||
if (!effect.isSelector()) continue;
|
||||
@@ -433,16 +438,29 @@ public final class WiredEngine {
|
||||
ctx.state().step();
|
||||
try {
|
||||
effect.execute(ctx);
|
||||
|
||||
if (effect instanceof InteractionWiredEffect) {
|
||||
InteractionWiredEffect wiredEffect = (InteractionWiredEffect) effect;
|
||||
wiredEffect.setCooldown(currentTime);
|
||||
wiredEffect.activateBox(ctx.room(), ctx.actor().orElse(null), currentTime);
|
||||
executedSelectors.add((InteractionWiredEffect) effect);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
LOGGER.warn("Error executing selector: {}", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
return executedSelectors;
|
||||
}
|
||||
|
||||
private void finalizeSelectors(List<InteractionWiredEffect> executedSelectors, WiredContext ctx, long currentTime) {
|
||||
if (executedSelectors == null || executedSelectors.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
Room room = ctx.room();
|
||||
RoomUnit actor = ctx.actor().orElse(null);
|
||||
|
||||
for (InteractionWiredEffect wiredEffect : executedSelectors) {
|
||||
wiredEffect.setCooldown(currentTime);
|
||||
wiredEffect.activateBox(room, actor, currentTime);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -43,6 +43,18 @@ public final class WiredEvent {
|
||||
/** User walks off furniture */
|
||||
USER_WALKS_OFF(WiredTriggerType.WALKS_OFF_FURNI),
|
||||
|
||||
/** User clicks furniture */
|
||||
USER_CLICKS_FURNI(WiredTriggerType.CLICKS_FURNI),
|
||||
|
||||
/** User clicks invisible click tile furniture */
|
||||
USER_CLICKS_TILE(WiredTriggerType.CLICKS_TILE),
|
||||
|
||||
/** User clicks another user */
|
||||
USER_CLICKS_USER(WiredTriggerType.CLICKS_USER),
|
||||
|
||||
/** User performs an avatar action */
|
||||
USER_PERFORMS_ACTION(WiredTriggerType.USER_PERFORMS_ACTION),
|
||||
|
||||
/** Furniture state is toggled/changed */
|
||||
FURNI_STATE_CHANGED(WiredTriggerType.STATE_CHANGED),
|
||||
|
||||
@@ -55,9 +67,15 @@ public final class WiredEvent {
|
||||
/** Long timer repeat */
|
||||
TIMER_REPEAT_LONG(WiredTriggerType.PERIODICALLY_LONG),
|
||||
|
||||
/** Short timer repeat */
|
||||
TIMER_REPEAT_SHORT(WiredTriggerType.PERIODICALLY_SHORT),
|
||||
|
||||
/** User enters the room */
|
||||
USER_ENTERS_ROOM(WiredTriggerType.ENTER_ROOM),
|
||||
|
||||
/** User leaves the room */
|
||||
USER_LEAVES_ROOM(WiredTriggerType.LEAVE_ROOM),
|
||||
|
||||
/** Game starts */
|
||||
GAME_STARTS(WiredTriggerType.GAME_STARTS),
|
||||
|
||||
@@ -141,6 +159,8 @@ public final class WiredEvent {
|
||||
private final boolean triggeredByEffect; // true if triggered by a wired effect (to prevent loops)
|
||||
private final int callStackDepth; // recursion depth for trigger stacks effect
|
||||
private final int signalChannel; // channel for signal routing (0-based)
|
||||
private final int actionId; // user action id for USER_PERFORMS_ACTION
|
||||
private final int actionParameter; // sign/dance parameter when relevant
|
||||
private final long createdAtMs;
|
||||
|
||||
private WiredEvent(Builder builder) {
|
||||
@@ -156,6 +176,8 @@ public final class WiredEvent {
|
||||
this.triggeredByEffect = builder.triggeredByEffect;
|
||||
this.callStackDepth = builder.callStackDepth;
|
||||
this.signalChannel = builder.signalChannel;
|
||||
this.actionId = builder.actionId;
|
||||
this.actionParameter = builder.actionParameter;
|
||||
this.createdAtMs = builder.createdAtMs;
|
||||
}
|
||||
|
||||
@@ -258,6 +280,14 @@ public final class WiredEvent {
|
||||
return signalChannel;
|
||||
}
|
||||
|
||||
public int getActionId() {
|
||||
return actionId;
|
||||
}
|
||||
|
||||
public int getActionParameter() {
|
||||
return actionParameter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the timestamp when this event was created.
|
||||
* @return milliseconds since epoch
|
||||
@@ -313,6 +343,8 @@ public final class WiredEvent {
|
||||
private boolean triggeredByEffect;
|
||||
private int callStackDepth;
|
||||
private int signalChannel;
|
||||
private int actionId;
|
||||
private int actionParameter = -1;
|
||||
private long createdAtMs = System.currentTimeMillis();
|
||||
|
||||
private Builder(Type type, Room room) {
|
||||
@@ -417,6 +449,16 @@ public final class WiredEvent {
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder actionId(int actionId) {
|
||||
this.actionId = actionId;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder actionParameter(int actionParameter) {
|
||||
this.actionParameter = actionParameter;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a custom creation timestamp.
|
||||
* @param createdAtMs milliseconds since epoch
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
package com.eu.habbo.habbohotel.wired.core;
|
||||
|
||||
import com.eu.habbo.habbohotel.rooms.Room;
|
||||
import com.eu.habbo.habbohotel.rooms.RoomUnit;
|
||||
import com.eu.habbo.messages.outgoing.rooms.users.RoomUserStatusComposer;
|
||||
|
||||
public final class WiredFreezeUtil {
|
||||
private static final String CACHE_ACTIVE = "wired.freeze.active";
|
||||
private static final String CACHE_EFFECT_ID = "wired.freeze.effect_id";
|
||||
private static final String CACHE_CANCEL_ON_TELEPORT = "wired.freeze.cancel_on_teleport";
|
||||
|
||||
private WiredFreezeUtil() {
|
||||
}
|
||||
|
||||
public static boolean isFrozen(RoomUnit roomUnit) {
|
||||
return roomUnit != null && Boolean.TRUE.equals(roomUnit.getCacheable().get(CACHE_ACTIVE));
|
||||
}
|
||||
|
||||
public static void freeze(Room room, RoomUnit roomUnit, int effectId, boolean cancelOnTeleport) {
|
||||
if (room == null || roomUnit == null || effectId <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
roomUnit.getCacheable().put(CACHE_ACTIVE, true);
|
||||
roomUnit.getCacheable().put(CACHE_EFFECT_ID, effectId);
|
||||
roomUnit.getCacheable().put(CACHE_CANCEL_ON_TELEPORT, cancelOnTeleport);
|
||||
|
||||
roomUnit.stopWalking();
|
||||
roomUnit.setCanWalk(false);
|
||||
roomUnit.statusUpdate(true);
|
||||
|
||||
room.giveEffect(roomUnit, effectId, Integer.MAX_VALUE);
|
||||
room.sendComposer(new RoomUserStatusComposer(roomUnit).compose());
|
||||
}
|
||||
|
||||
public static void unfreeze(Room room, RoomUnit roomUnit) {
|
||||
if (roomUnit == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
roomUnit.getCacheable().remove(CACHE_ACTIVE);
|
||||
roomUnit.getCacheable().remove(CACHE_EFFECT_ID);
|
||||
roomUnit.getCacheable().remove(CACHE_CANCEL_ON_TELEPORT);
|
||||
|
||||
roomUnit.stopWalking();
|
||||
roomUnit.setCanWalk(true);
|
||||
roomUnit.statusUpdate(true);
|
||||
|
||||
if (room != null) {
|
||||
room.giveEffect(roomUnit, 0, -1);
|
||||
room.sendComposer(new RoomUserStatusComposer(roomUnit).compose());
|
||||
} else {
|
||||
roomUnit.setEffectId(0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
public static void onTeleport(Room room, RoomUnit roomUnit) {
|
||||
if (!isFrozen(roomUnit)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (Boolean.TRUE.equals(roomUnit.getCacheable().get(CACHE_CANCEL_ON_TELEPORT))) {
|
||||
unfreeze(room, roomUnit);
|
||||
}
|
||||
}
|
||||
|
||||
public static void restoreWalkState(RoomUnit roomUnit) {
|
||||
if (roomUnit == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
roomUnit.setCanWalk(!isFrozen(roomUnit));
|
||||
}
|
||||
}
|
||||
@@ -64,6 +64,9 @@ import java.sql.SQLException;
|
||||
* @see WiredEvents
|
||||
*/
|
||||
public final class WiredManager {
|
||||
private static final String CACHE_LAST_ACTION_ID = "wired.last_user_action.id";
|
||||
private static final String CACHE_LAST_ACTION_PARAMETER = "wired.last_user_action.parameter";
|
||||
private static final String CACHE_LAST_ACTION_TIMESTAMP = "wired.last_user_action.timestamp";
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(WiredManager.class);
|
||||
|
||||
@@ -235,6 +238,58 @@ public final class WiredManager {
|
||||
return handleEvent(event);
|
||||
}
|
||||
|
||||
/**
|
||||
* Trigger when a user clicks furniture.
|
||||
*/
|
||||
public static boolean triggerUserClicksFurni(Room room, RoomUnit user, HabboItem item) {
|
||||
if (!isEnabled() || room == null || user == null || item == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
WiredEvent event = WiredEvents.userClicksFurni(room, user, item);
|
||||
return handleEvent(event);
|
||||
}
|
||||
|
||||
/**
|
||||
* Trigger when a user clicks invisible click tile furniture.
|
||||
*/
|
||||
public static boolean triggerUserClicksTile(Room room, RoomUnit user, HabboItem item) {
|
||||
if (!isEnabled() || room == null || user == null || item == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
WiredEvent event = WiredEvents.userClicksTile(room, user, item);
|
||||
return handleEvent(event);
|
||||
}
|
||||
|
||||
/**
|
||||
* Trigger when a user clicks another user.
|
||||
*/
|
||||
public static boolean triggerUserClicksUser(Room room, RoomUnit clickingUser, RoomUnit clickedUser) {
|
||||
if (!isEnabled() || room == null || clickingUser == null || clickedUser == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
WiredEvent event = WiredEvents.userClicksUser(room, clickingUser, clickedUser);
|
||||
return handleEvent(event);
|
||||
}
|
||||
|
||||
/**
|
||||
* Trigger when a user performs an avatar action.
|
||||
*/
|
||||
public static boolean triggerUserPerformsAction(Room room, RoomUnit user, int actionId, int actionParameter) {
|
||||
if (!isEnabled() || room == null || user == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
user.getCacheable().put(CACHE_LAST_ACTION_ID, actionId);
|
||||
user.getCacheable().put(CACHE_LAST_ACTION_PARAMETER, actionParameter);
|
||||
user.getCacheable().put(CACHE_LAST_ACTION_TIMESTAMP, System.currentTimeMillis());
|
||||
|
||||
WiredEvent event = WiredEvents.userPerformsAction(room, user, actionId, actionParameter);
|
||||
return handleEvent(event);
|
||||
}
|
||||
|
||||
/**
|
||||
* Trigger when a user says something.
|
||||
*/
|
||||
@@ -259,6 +314,18 @@ public final class WiredManager {
|
||||
return handleEvent(event);
|
||||
}
|
||||
|
||||
/**
|
||||
* Trigger when a user leaves the room.
|
||||
*/
|
||||
public static boolean triggerUserLeavesRoom(Room room, RoomUnit user) {
|
||||
if (!isEnabled() || room == null || user == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
WiredEvent event = WiredEvents.userLeavesRoom(room, user);
|
||||
return handleEvent(event);
|
||||
}
|
||||
|
||||
/**
|
||||
* Trigger when furniture state changes.
|
||||
*/
|
||||
@@ -295,6 +362,30 @@ public final class WiredManager {
|
||||
return handleEvent(event);
|
||||
}
|
||||
|
||||
/**
|
||||
* Trigger a long periodic timer.
|
||||
*/
|
||||
public static boolean triggerTimerRepeatLong(Room room, HabboItem timerItem) {
|
||||
if (!isEnabled() || room == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
WiredEvent event = WiredEvents.timerRepeatLong(room, timerItem);
|
||||
return handleEvent(event);
|
||||
}
|
||||
|
||||
/**
|
||||
* Trigger a short periodic timer.
|
||||
*/
|
||||
public static boolean triggerTimerRepeatShort(Room room, HabboItem timerItem) {
|
||||
if (!isEnabled() || room == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
WiredEvent event = WiredEvents.timerRepeatShort(room, timerItem);
|
||||
return handleEvent(event);
|
||||
}
|
||||
|
||||
/**
|
||||
* Trigger game start.
|
||||
*/
|
||||
@@ -687,15 +778,7 @@ public final class WiredManager {
|
||||
});
|
||||
}
|
||||
|
||||
private static void giveReward(Habbo habbo, WiredEffectGiveReward wiredBox, WiredGiveRewardItem reward) {
|
||||
if (wiredBox.getLimit() > 0)
|
||||
wiredBox.incrementGiven();
|
||||
|
||||
final int wiredId = wiredBox.getId();
|
||||
final int habboId = habbo.getHabboInfo().getId();
|
||||
final int rewardId = reward.id;
|
||||
final int timestamp = Emulator.getIntUnixTimestamp();
|
||||
|
||||
private static void persistReward(int wiredId, int habboId, int rewardId, int timestamp) {
|
||||
Emulator.getThreading().run(() -> {
|
||||
try (Connection connection = Emulator.getDatabase().getDataSource().getConnection();
|
||||
PreparedStatement statement = connection.prepareStatement("INSERT INTO wired_rewards_given (wired_item, user_id, reward_id, timestamp) VALUES ( ?, ?, ?, ?)")) {
|
||||
@@ -708,41 +791,75 @@ public final class WiredManager {
|
||||
LOGGER.error("Caught SQL exception", e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private static void completeReward(Habbo habbo, WiredEffectGiveReward wiredBox, WiredGiveRewardItem reward, int successCode) {
|
||||
if (wiredBox.getLimit() > 0) {
|
||||
wiredBox.incrementGiven();
|
||||
}
|
||||
|
||||
persistReward(wiredBox.getId(), habbo.getHabboInfo().getId(), reward.id, Emulator.getIntUnixTimestamp());
|
||||
habbo.getClient().sendResponse(new WiredRewardAlertComposer(successCode));
|
||||
}
|
||||
|
||||
private static boolean giveReward(Habbo habbo, WiredEffectGiveReward wiredBox, WiredGiveRewardItem reward) {
|
||||
if (reward.badge) {
|
||||
UserWiredRewardReceived rewardReceived = new UserWiredRewardReceived(habbo, wiredBox, "badge", reward.data);
|
||||
if (Emulator.getPluginManager().fireEvent(rewardReceived).isCancelled())
|
||||
return;
|
||||
if (Emulator.getPluginManager().fireEvent(rewardReceived).isCancelled()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (rewardReceived.value.isEmpty())
|
||||
return;
|
||||
if (rewardReceived.value.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (habbo.getInventory().getBadgesComponent().hasBadge(rewardReceived.value))
|
||||
return;
|
||||
if (habbo.getInventory().getBadgesComponent().hasBadge(rewardReceived.value)) {
|
||||
habbo.getClient().sendResponse(new WiredRewardAlertComposer(WiredRewardAlertComposer.REWARD_ALREADY_RECEIVED));
|
||||
return false;
|
||||
}
|
||||
|
||||
HabboBadge badge = new HabboBadge(0, rewardReceived.value, 0, habbo);
|
||||
Emulator.getThreading().run(badge);
|
||||
habbo.getInventory().getBadgesComponent().addBadge(badge);
|
||||
habbo.getClient().sendResponse(new AddUserBadgeComposer(badge));
|
||||
habbo.getClient().sendResponse(new WiredRewardAlertComposer(WiredRewardAlertComposer.REWARD_RECEIVED_BADGE));
|
||||
} else {
|
||||
completeReward(habbo, wiredBox, reward, WiredRewardAlertComposer.REWARD_RECEIVED_BADGE);
|
||||
return true;
|
||||
}
|
||||
|
||||
String[] data = reward.data.split("#");
|
||||
|
||||
if (data.length == 2) {
|
||||
UserWiredRewardReceived rewardReceived = new UserWiredRewardReceived(habbo, wiredBox, data[0], data[1]);
|
||||
if (Emulator.getPluginManager().fireEvent(rewardReceived).isCancelled())
|
||||
return;
|
||||
if (data.length != 2) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (rewardReceived.value.isEmpty())
|
||||
return;
|
||||
UserWiredRewardReceived rewardReceived = new UserWiredRewardReceived(habbo, wiredBox, data[0], data[1]);
|
||||
if (Emulator.getPluginManager().fireEvent(rewardReceived).isCancelled()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (rewardReceived.value.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (rewardReceived.type.equalsIgnoreCase("credits")) {
|
||||
int credits = Integer.parseInt(rewardReceived.value);
|
||||
habbo.giveCredits(credits);
|
||||
} else if (rewardReceived.type.equalsIgnoreCase("pixels")) {
|
||||
int pixels = Integer.parseInt(rewardReceived.value);
|
||||
habbo.givePixels(pixels);
|
||||
} else if (rewardReceived.type.startsWith("points")) {
|
||||
habbo.giveCredits(Integer.parseInt(rewardReceived.value));
|
||||
completeReward(habbo, wiredBox, reward, WiredRewardAlertComposer.REWARD_RECEIVED_ITEM);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (rewardReceived.type.equalsIgnoreCase("diamonds") || rewardReceived.type.equalsIgnoreCase("diamond")) {
|
||||
habbo.givePoints(5, Integer.parseInt(rewardReceived.value));
|
||||
completeReward(habbo, wiredBox, reward, WiredRewardAlertComposer.REWARD_RECEIVED_ITEM);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (rewardReceived.type.equalsIgnoreCase("pixels")) {
|
||||
habbo.givePixels(Integer.parseInt(rewardReceived.value));
|
||||
completeReward(habbo, wiredBox, reward, WiredRewardAlertComposer.REWARD_RECEIVED_ITEM);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (rewardReceived.type.startsWith("points")) {
|
||||
int points = Integer.parseInt(rewardReceived.value);
|
||||
int type = 5;
|
||||
|
||||
@@ -752,31 +869,47 @@ public final class WiredManager {
|
||||
}
|
||||
|
||||
habbo.givePoints(type, points);
|
||||
} else if (rewardReceived.type.equalsIgnoreCase("furni")) {
|
||||
Item baseItem = Emulator.getGameEnvironment().getItemManager().getItem(Integer.parseInt(rewardReceived.value));
|
||||
if (baseItem != null) {
|
||||
HabboItem item = Emulator.getGameEnvironment().getItemManager().createItem(habbo.getHabboInfo().getId(), baseItem, 0, 0, "");
|
||||
completeReward(habbo, wiredBox, reward, WiredRewardAlertComposer.REWARD_RECEIVED_ITEM);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (rewardReceived.type.equalsIgnoreCase("furni")) {
|
||||
Item baseItem = Emulator.getGameEnvironment().getItemManager().getItem(Integer.parseInt(rewardReceived.value));
|
||||
if (baseItem == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
HabboItem item = Emulator.getGameEnvironment().getItemManager().createItem(habbo.getHabboInfo().getId(), baseItem, 0, 0, "");
|
||||
if (item == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (item != null) {
|
||||
habbo.getClient().sendResponse(new AddHabboItemComposer(item));
|
||||
habbo.getClient().getHabbo().getInventory().getItemsComponent().addItem(item);
|
||||
habbo.getClient().sendResponse(new PurchaseOKComposer(null));
|
||||
habbo.getClient().sendResponse(new InventoryRefreshComposer());
|
||||
habbo.getClient().sendResponse(new WiredRewardAlertComposer(WiredRewardAlertComposer.REWARD_RECEIVED_ITEM));
|
||||
completeReward(habbo, wiredBox, reward, WiredRewardAlertComposer.REWARD_RECEIVED_ITEM);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (rewardReceived.type.equalsIgnoreCase("respect")) {
|
||||
habbo.getHabboStats().respectPointsReceived += Integer.parseInt(rewardReceived.value);
|
||||
completeReward(habbo, wiredBox, reward, WiredRewardAlertComposer.REWARD_RECEIVED_ITEM);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (rewardReceived.type.equalsIgnoreCase("cata")) {
|
||||
CatalogItem item = Emulator.getGameEnvironment().getCatalogManager().getCatalogItem(Integer.parseInt(rewardReceived.value));
|
||||
if (item == null) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} else if (rewardReceived.type.equalsIgnoreCase("respect")) {
|
||||
habbo.getHabboStats().respectPointsReceived += Integer.parseInt(rewardReceived.value);
|
||||
} else if (rewardReceived.type.equalsIgnoreCase("cata")) {
|
||||
CatalogItem item = Emulator.getGameEnvironment().getCatalogManager().getCatalogItem(Integer.parseInt(rewardReceived.value));
|
||||
|
||||
if (item != null) {
|
||||
Emulator.getGameEnvironment().getCatalogManager().purchaseItem(null, item, habbo, 1, "", true);
|
||||
completeReward(habbo, wiredBox, reward, WiredRewardAlertComposer.REWARD_RECEIVED_ITEM);
|
||||
return true;
|
||||
}
|
||||
habbo.getClient().sendResponse(new WiredRewardAlertComposer(WiredRewardAlertComposer.REWARD_RECEIVED_ITEM));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static boolean getReward(Habbo habbo, WiredEffectGiveReward wiredBox) {
|
||||
@@ -843,22 +976,26 @@ public final class WiredManager {
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
giveReward(habbo, wiredBox, item);
|
||||
return true;
|
||||
return giveReward(habbo, wiredBox, item);
|
||||
}
|
||||
}
|
||||
|
||||
habbo.getClient().sendResponse(new WiredRewardAlertComposer(WiredRewardAlertComposer.REWARD_ALL_COLLECTED));
|
||||
return false;
|
||||
} else {
|
||||
int randomNumber = Emulator.getRandom().nextInt(101);
|
||||
|
||||
int count = 0;
|
||||
for (WiredGiveRewardItem item : wiredBox.getRewardItems()) {
|
||||
if (randomNumber >= count && randomNumber <= (count + item.probability)) {
|
||||
giveReward(habbo, wiredBox, item);
|
||||
return true;
|
||||
return giveReward(habbo, wiredBox, item);
|
||||
}
|
||||
|
||||
count += item.probability;
|
||||
}
|
||||
|
||||
habbo.getClient().sendResponse(new WiredRewardAlertComposer(WiredRewardAlertComposer.UNLUCKY_NO_REWARD));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+7
-10
@@ -3,6 +3,7 @@ package com.eu.habbo.habbohotel.wired.highscores;
|
||||
import com.eu.habbo.Emulator;
|
||||
import com.eu.habbo.plugin.EventHandler;
|
||||
import com.eu.habbo.plugin.events.emulator.EmulatorLoadedEvent;
|
||||
import com.eu.habbo.util.HotelDateTimeUtil;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@@ -11,9 +12,7 @@ import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.time.DayOfWeek;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.LocalTime;
|
||||
import java.time.ZoneId;
|
||||
import java.time.temporal.TemporalAdjusters;
|
||||
import java.time.temporal.WeekFields;
|
||||
import java.util.*;
|
||||
@@ -31,8 +30,6 @@ public class WiredHighscoreManager {
|
||||
|
||||
private final static DayOfWeek firstDayOfWeek = WeekFields.of(Locale.of(locale, country)).getFirstDayOfWeek();
|
||||
private final static DayOfWeek lastDayOfWeek = DayOfWeek.of(((firstDayOfWeek.getValue() + 5) % DayOfWeek.values().length) + 1);
|
||||
private final static ZoneId zoneId = ZoneId.systemDefault();
|
||||
|
||||
public static ScheduledFuture<?> midnightUpdater = null;
|
||||
|
||||
public void load() {
|
||||
@@ -183,26 +180,26 @@ public class WiredHighscoreManager {
|
||||
}
|
||||
|
||||
private long getTodayStartTimestamp() {
|
||||
return LocalDateTime.now().with(LocalTime.MIDNIGHT).atZone(zoneId).toEpochSecond();
|
||||
return HotelDateTimeUtil.toEpochSecond(HotelDateTimeUtil.localDateTimeNow().with(LocalTime.MIDNIGHT));
|
||||
}
|
||||
|
||||
private long getTodayEndTimestamp() {
|
||||
return LocalDateTime.now().with(LocalTime.MIDNIGHT).plusDays(1).plusSeconds(-1).atZone(zoneId).toEpochSecond();
|
||||
return HotelDateTimeUtil.toEpochSecond(HotelDateTimeUtil.localDateTimeNow().with(LocalTime.MIDNIGHT).plusDays(1).plusSeconds(-1));
|
||||
}
|
||||
|
||||
private long getWeekStartTimestamp() {
|
||||
return LocalDateTime.now().with(LocalTime.MIDNIGHT).with(TemporalAdjusters.previousOrSame(firstDayOfWeek)).atZone(zoneId).toEpochSecond();
|
||||
return HotelDateTimeUtil.toEpochSecond(HotelDateTimeUtil.localDateTimeNow().with(LocalTime.MIDNIGHT).with(TemporalAdjusters.previousOrSame(firstDayOfWeek)));
|
||||
}
|
||||
|
||||
private long getWeekEndTimestamp() {
|
||||
return LocalDateTime.now().with(LocalTime.MIDNIGHT).plusDays(1).plusSeconds(-1).with(TemporalAdjusters.nextOrSame(lastDayOfWeek)).atZone(zoneId).toEpochSecond();
|
||||
return HotelDateTimeUtil.toEpochSecond(HotelDateTimeUtil.localDateTimeNow().with(LocalTime.MIDNIGHT).plusDays(1).plusSeconds(-1).with(TemporalAdjusters.nextOrSame(lastDayOfWeek)));
|
||||
}
|
||||
|
||||
private long getMonthStartTimestamp() {
|
||||
return LocalDateTime.now().with(LocalTime.MIDNIGHT).with(TemporalAdjusters.firstDayOfMonth()).atZone(zoneId).toEpochSecond();
|
||||
return HotelDateTimeUtil.toEpochSecond(HotelDateTimeUtil.localDateTimeNow().with(LocalTime.MIDNIGHT).with(TemporalAdjusters.firstDayOfMonth()));
|
||||
}
|
||||
|
||||
private long getMonthEndTimestamp() {
|
||||
return LocalDateTime.now().with(LocalTime.MIDNIGHT).plusDays(1).plusSeconds(-1).with(TemporalAdjusters.lastDayOfMonth()).atZone(zoneId).toEpochSecond();
|
||||
return HotelDateTimeUtil.toEpochSecond(HotelDateTimeUtil.localDateTimeNow().with(LocalTime.MIDNIGHT).plusDays(1).plusSeconds(-1).with(TemporalAdjusters.lastDayOfMonth()));
|
||||
}
|
||||
}
|
||||
|
||||
+3
-3
@@ -4,11 +4,10 @@ import com.eu.habbo.Emulator;
|
||||
import com.eu.habbo.habbohotel.items.interactions.InteractionWiredHighscore;
|
||||
import com.eu.habbo.habbohotel.rooms.Room;
|
||||
import com.eu.habbo.habbohotel.users.HabboItem;
|
||||
import com.eu.habbo.util.HotelDateTimeUtil;
|
||||
import gnu.trove.set.hash.THashSet;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.LocalTime;
|
||||
import java.time.ZoneId;
|
||||
import java.util.List;
|
||||
|
||||
public class WiredHighscoreMidnightUpdater implements Runnable {
|
||||
@@ -30,6 +29,7 @@ public class WiredHighscoreMidnightUpdater implements Runnable {
|
||||
}
|
||||
|
||||
public static int getNextUpdaterRun() {
|
||||
return Math.toIntExact(LocalDateTime.now().with(LocalTime.MIDNIGHT).plusDays(1).plusSeconds(-1).atZone(ZoneId.systemDefault()).toEpochSecond() - Emulator.getIntUnixTimestamp()) + 5;
|
||||
long nextRunTimestamp = HotelDateTimeUtil.toEpochSecond(HotelDateTimeUtil.localDateTimeNow().with(LocalTime.MIDNIGHT).plusDays(1).plusSeconds(-1));
|
||||
return Math.toIntExact(nextRunTimestamp - Emulator.getIntUnixTimestamp()) + 5;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -67,6 +67,70 @@ public final class WiredEvents {
|
||||
.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an event for when a user clicks furniture.
|
||||
* @param room the room
|
||||
* @param user the clicking user
|
||||
* @param item the clicked furniture
|
||||
* @return the event
|
||||
*/
|
||||
public static WiredEvent userClicksFurni(Room room, RoomUnit user, HabboItem item) {
|
||||
RoomTile tile = room.getLayout().getTile(item.getX(), item.getY());
|
||||
return WiredEvent.builder(WiredEvent.Type.USER_CLICKS_FURNI, room)
|
||||
.actor(user)
|
||||
.sourceItem(item)
|
||||
.tile(tile)
|
||||
.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an event for when a user clicks invisible click tile furniture.
|
||||
* @param room the room
|
||||
* @param user the clicking user
|
||||
* @param item the clicked furniture
|
||||
* @return the event
|
||||
*/
|
||||
public static WiredEvent userClicksTile(Room room, RoomUnit user, HabboItem item) {
|
||||
RoomTile tile = room.getLayout().getTile(item.getX(), item.getY());
|
||||
return WiredEvent.builder(WiredEvent.Type.USER_CLICKS_TILE, room)
|
||||
.actor(user)
|
||||
.sourceItem(item)
|
||||
.tile(tile)
|
||||
.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an event for when a user clicks another user.
|
||||
* @param room the room
|
||||
* @param clickingUser the user performing the click
|
||||
* @param clickedUser the user who was clicked
|
||||
* @return the event
|
||||
*/
|
||||
public static WiredEvent userClicksUser(Room room, RoomUnit clickingUser, RoomUnit clickedUser) {
|
||||
return WiredEvent.builder(WiredEvent.Type.USER_CLICKS_USER, room)
|
||||
.actor(clickedUser)
|
||||
.targetUnit(clickingUser)
|
||||
.tile(clickedUser.getCurrentLocation())
|
||||
.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an event for when a user performs an avatar action.
|
||||
* @param room the room
|
||||
* @param user the acting user
|
||||
* @param actionId the wired action id
|
||||
* @param actionParameter sign/dance parameter, or -1 when unused
|
||||
* @return the event
|
||||
*/
|
||||
public static WiredEvent userPerformsAction(Room room, RoomUnit user, int actionId, int actionParameter) {
|
||||
return WiredEvent.builder(WiredEvent.Type.USER_PERFORMS_ACTION, room)
|
||||
.actor(user)
|
||||
.tile(user.getCurrentLocation())
|
||||
.actionId(actionId)
|
||||
.actionParameter(actionParameter)
|
||||
.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an event for when a user enters the room.
|
||||
* @param room the room
|
||||
@@ -80,6 +144,19 @@ public final class WiredEvents {
|
||||
.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an event for when a user leaves the room.
|
||||
* @param room the room
|
||||
* @param user the user who left
|
||||
* @return the event
|
||||
*/
|
||||
public static WiredEvent userLeavesRoom(Room room, RoomUnit user) {
|
||||
return WiredEvent.builder(WiredEvent.Type.USER_LEAVES_ROOM, room)
|
||||
.actor(user)
|
||||
.tile(user.getCurrentLocation())
|
||||
.build();
|
||||
}
|
||||
|
||||
// ========== User Interaction Events ==========
|
||||
|
||||
/**
|
||||
@@ -153,6 +230,18 @@ public final class WiredEvents {
|
||||
.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an event for a short periodic timer.
|
||||
* @param room the room
|
||||
* @param timerItem the timer furniture
|
||||
* @return the event
|
||||
*/
|
||||
public static WiredEvent timerRepeatShort(Room room, HabboItem timerItem) {
|
||||
return WiredEvent.builder(WiredEvent.Type.TIMER_REPEAT_SHORT, room)
|
||||
.sourceItem(timerItem)
|
||||
.build();
|
||||
}
|
||||
|
||||
// ========== Game Events ==========
|
||||
|
||||
/**
|
||||
|
||||
@@ -394,6 +394,8 @@ public class PacketManager {
|
||||
this.registerHandler(Incoming.RoomPlacePaintEvent, RoomPlacePaintEvent.class);
|
||||
this.registerHandler(Incoming.RoomUserStartTypingEvent, RoomUserStartTypingEvent.class);
|
||||
this.registerHandler(Incoming.RoomUserStopTypingEvent, RoomUserStopTypingEvent.class);
|
||||
this.registerHandler(Incoming.ClickFurniEvent, ClickFurniEvent.class);
|
||||
this.registerHandler(Incoming.ClickUserEvent, ClickUserEvent.class);
|
||||
this.registerHandler(Incoming.ToggleFloorItemEvent, ToggleFloorItemEvent.class);
|
||||
this.registerHandler(Incoming.ToggleWallItemEvent, ToggleWallItemEvent.class);
|
||||
this.registerHandler(Incoming.RoomBackgroundEvent, RoomBackgroundEvent.class);
|
||||
|
||||
@@ -205,6 +205,7 @@ public class Incoming {
|
||||
public static final int RequestRoomDataEvent = 2230;
|
||||
public static final int RequestRoomHeightmapEvent = 2300;
|
||||
public static final int RequestGuildFurniWidgetEvent = 2651;
|
||||
public static final int ClickFurniEvent = 6002;
|
||||
public static final int RequestOwnItemsEvent = 2105;
|
||||
public static final int RequestReportRoomEvent = 3267;
|
||||
public static final int ReportEvent = 1691;
|
||||
@@ -379,7 +380,7 @@ public class Incoming {
|
||||
|
||||
public static final int UNKNOWN_SNOWSTORM_6000 = 6000;
|
||||
public static final int UNKNOWN_SNOWSTORM_6001 = 6001;
|
||||
public static final int UNKNOWN_SNOWSTORM_6002 = 6002;
|
||||
// public static final int UNKNOWN_SNOWSTORM_6002 = 6002;
|
||||
public static final int UNKNOWN_SNOWSTORM_6003 = 6003;
|
||||
public static final int UNKNOWN_SNOWSTORM_6004 = 6004;
|
||||
public static final int UNKNOWN_SNOWSTORM_6005 = 6005;
|
||||
@@ -407,6 +408,7 @@ public class Incoming {
|
||||
|
||||
// CUSTOM
|
||||
public static final int UpdateFurniturePositionEvent = 10019;
|
||||
public static final int ClickUserEvent = 10020;
|
||||
public static final int RequestInventoryPetDelete = 10030;
|
||||
public static final int RequestInventoryBadgeDelete = 10031;
|
||||
|
||||
|
||||
+82
-2
@@ -2,10 +2,13 @@ package com.eu.habbo.messages.incoming.handshake;
|
||||
|
||||
import com.eu.habbo.Emulator;
|
||||
import com.eu.habbo.habbohotel.messenger.Messenger;
|
||||
import com.eu.habbo.habbohotel.gameclients.GameClient;
|
||||
import com.eu.habbo.habbohotel.gameclients.SessionResumeManager;
|
||||
import com.eu.habbo.habbohotel.modtool.ModToolSanctionItem;
|
||||
import com.eu.habbo.habbohotel.modtool.ModToolSanctions;
|
||||
import com.eu.habbo.habbohotel.navigation.NavigatorSavedSearch;
|
||||
import com.eu.habbo.habbohotel.permissions.Permission;
|
||||
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.HabboManager;
|
||||
@@ -81,8 +84,70 @@ public class SecureLoginEvent extends MessageHandler {
|
||||
}
|
||||
|
||||
if (this.client.getHabbo() == null) {
|
||||
Habbo habbo = Emulator.getGameEnvironment().getHabboManager().loadHabbo(sso);
|
||||
// Store SSO ticket on client for grace period tracking
|
||||
this.client.setSsoTicket(sso);
|
||||
|
||||
// Race condition fix: if the old WebSocket connection is still alive on the
|
||||
// server when the client reconnects, the SSO ticket won't be in the DB yet
|
||||
// (it was cleared on first login, and parkHabbo hasn't run because the old
|
||||
// channel hasn't closed). Find the old client by SSO ticket and force-dispose
|
||||
// it, which parks the habbo and restores the ticket to the DB.
|
||||
GameClient existingClient = Emulator.getGameServer().getGameClientManager().findClientBySsoTicket(sso);
|
||||
if (existingClient != null && existingClient != this.client) {
|
||||
LOGGER.info("[SessionResume] Found existing client with same SSO ticket — disposing old connection to trigger parking");
|
||||
Emulator.getGameServer().getGameClientManager().disposeClient(existingClient);
|
||||
}
|
||||
|
||||
// First, look up the user ID to check for ghost sessions
|
||||
int lookupUserId = 0;
|
||||
try (java.sql.Connection conn = Emulator.getDatabase().getDataSource().getConnection();
|
||||
java.sql.PreparedStatement stmt = conn.prepareStatement("SELECT id FROM users WHERE auth_ticket = ? LIMIT 1")) {
|
||||
stmt.setString(1, sso);
|
||||
try (java.sql.ResultSet rs = stmt.executeQuery()) {
|
||||
if (rs.next()) {
|
||||
lookupUserId = rs.getInt("id");
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
LOGGER.error("Caught exception looking up user for session resume", e);
|
||||
}
|
||||
|
||||
// Check if this user has a ghost session (disconnected within grace period)
|
||||
Habbo habbo = null;
|
||||
boolean isSessionResume = false;
|
||||
|
||||
if (lookupUserId > 0) {
|
||||
habbo = SessionResumeManager.getInstance().resumeSession(lookupUserId);
|
||||
}
|
||||
|
||||
if (habbo != null) {
|
||||
// Session resume — reattach the existing Habbo to the new client
|
||||
isSessionResume = true;
|
||||
LOGGER.info("[SessionResume] Resuming session for {} (id={})",
|
||||
habbo.getHabboInfo().getUsername(), habbo.getHabboInfo().getId());
|
||||
|
||||
habbo.setClient(this.client);
|
||||
this.client.setHabbo(habbo);
|
||||
this.client.setMachineId(habbo.getHabboInfo().getMachineID());
|
||||
|
||||
// Clear the SSO ticket now that session is resumed (prevent reuse)
|
||||
if (!Emulator.debugging) {
|
||||
try (java.sql.Connection conn = Emulator.getDatabase().getDataSource().getConnection();
|
||||
java.sql.PreparedStatement stmt = conn.prepareStatement("UPDATE users SET auth_ticket = ? WHERE id = ? LIMIT 1")) {
|
||||
stmt.setString(1, "");
|
||||
stmt.setInt(2, habbo.getHabboInfo().getId());
|
||||
stmt.execute();
|
||||
} catch (Exception e) {
|
||||
LOGGER.error("Failed to clear SSO ticket after session resume", e);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Normal login — load from database
|
||||
habbo = Emulator.getGameEnvironment().getHabboManager().loadHabbo(sso);
|
||||
}
|
||||
|
||||
if (habbo != null) {
|
||||
if (!isSessionResume) {
|
||||
try {
|
||||
habbo.setClient(this.client);
|
||||
this.client.setHabbo(habbo);
|
||||
@@ -107,6 +172,7 @@ public class SecureLoginEvent extends MessageHandler {
|
||||
Emulator.getGameServer().getGameClientManager().disposeClient(this.client);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if(ClothingValidationManager.VALIDATE_ON_LOGIN) {
|
||||
String validated = ClothingValidationManager.validateLook(this.client.getHabbo());
|
||||
@@ -121,7 +187,18 @@ public class SecureLoginEvent extends MessageHandler {
|
||||
|
||||
int roomIdToEnter = 0;
|
||||
|
||||
if (!this.client.getHabbo().getHabboStats().nux || Emulator.getConfig().getBoolean("retro.style.homeroom") && this.client.getHabbo().getHabboInfo().getHomeRoom() != 0)
|
||||
if (isSessionResume) {
|
||||
// On session resume, DON'T set roomIdToEnter. The client keeps its
|
||||
// existing room view alive and the habbo is already in the room on
|
||||
// the server. Setting roomIdToEnter = 0 prevents UserHomeRoomComposer
|
||||
// from triggering a full room re-entry on the client (which would
|
||||
// tear down and rebuild the room view).
|
||||
Room currentRoom = habbo.getHabboInfo().getCurrentRoom();
|
||||
if (currentRoom != null) {
|
||||
LOGGER.info("[SessionResume] {} is still in room {} — client will resume in-place",
|
||||
habbo.getHabboInfo().getUsername(), currentRoom.getId());
|
||||
}
|
||||
} else if (!this.client.getHabbo().getHabboStats().nux || Emulator.getConfig().getBoolean("retro.style.homeroom") && this.client.getHabbo().getHabboInfo().getHomeRoom() != 0)
|
||||
roomIdToEnter = this.client.getHabbo().getHabboInfo().getHomeRoom();
|
||||
else if (!this.client.getHabbo().getHabboStats().nux || Emulator.getConfig().getBoolean("retro.style.homeroom") && RoomManager.HOME_ROOM_ID > 0)
|
||||
roomIdToEnter = RoomManager.HOME_ROOM_ID;
|
||||
@@ -189,6 +266,8 @@ public class SecureLoginEvent extends MessageHandler {
|
||||
}
|
||||
}
|
||||
|
||||
// Skip login-only events on session resume (welcome alerts, login events, etc.)
|
||||
if (!isSessionResume) {
|
||||
UserLoginEvent userLoginEvent = new UserLoginEvent(habbo, this.client.getHabbo().getHabboInfo().getIpLogin());
|
||||
Emulator.getPluginManager().fireEvent(userLoginEvent);
|
||||
|
||||
@@ -226,6 +305,7 @@ public class SecureLoginEvent extends MessageHandler {
|
||||
|
||||
this.client.sendResponse(new NewNavigatorSavedSearchesComposer(this.client.getHabbo().getHabboInfo().getSavedSearches()));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Emulator.getGameServer().getGameClientManager().disposeClient(this.client);
|
||||
LOGGER.warn("Someone tried to login with a non-existing SSO token! Closed connection...");
|
||||
|
||||
+2
-2
@@ -3,9 +3,9 @@ package com.eu.habbo.messages.incoming.hotelview;
|
||||
import com.eu.habbo.Emulator;
|
||||
import com.eu.habbo.messages.incoming.MessageHandler;
|
||||
import com.eu.habbo.messages.outgoing.hotelview.HotelViewSecondsUntilComposer;
|
||||
import com.eu.habbo.util.HotelDateTimeUtil;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.ZoneId;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.time.format.DateTimeParseException;
|
||||
|
||||
@@ -18,7 +18,7 @@ public class HotelViewRequestSecondsUntilEvent extends MessageHandler {
|
||||
|
||||
try {
|
||||
LocalDateTime dt = LocalDateTime.parse(date, formatter);
|
||||
int secondsUntil = Math.max(0, (int) dt.atZone(ZoneId.systemDefault()).toEpochSecond() - Emulator.getIntUnixTimestamp());
|
||||
int secondsUntil = Math.max(0, (int) HotelDateTimeUtil.toEpochSecond(dt) - Emulator.getIntUnixTimestamp());
|
||||
this.client.sendResponse(new HotelViewSecondsUntilComposer(date, secondsUntil));
|
||||
} catch (DateTimeParseException ignored) {
|
||||
}
|
||||
|
||||
+54
-1
@@ -2,15 +2,35 @@ package com.eu.habbo.messages.incoming.rooms;
|
||||
|
||||
import com.eu.habbo.Emulator;
|
||||
import com.eu.habbo.habbohotel.rooms.Room;
|
||||
import com.eu.habbo.habbohotel.rooms.RoomTile;
|
||||
import com.eu.habbo.messages.incoming.MessageHandler;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class RequestRoomLoadEvent extends MessageHandler {
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(RequestRoomLoadEvent.class);
|
||||
|
||||
@Override
|
||||
public void handle() throws Exception {
|
||||
int roomId = this.packet.readInt();
|
||||
String password = this.packet.readString();
|
||||
|
||||
// Optional spawn coordinates from the client (for future reconnection support).
|
||||
int spawnX = -1;
|
||||
int spawnY = -1;
|
||||
|
||||
try {
|
||||
int remaining = this.packet.getBuffer().readableBytes();
|
||||
if (remaining >= 8) {
|
||||
spawnX = this.packet.readInt();
|
||||
spawnY = this.packet.readInt();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
spawnX = -1;
|
||||
spawnY = -1;
|
||||
}
|
||||
|
||||
// Reset stale loadingRoom if timestamp has expired (indicates failed/stuck load)
|
||||
if (this.client.getHabbo().getHabboInfo().getLoadingRoom() != 0
|
||||
&& this.client.getHabbo().getHabboStats().roomEnterTimestamp + 5000 < System.currentTimeMillis()) {
|
||||
@@ -30,6 +50,18 @@ public class RequestRoomLoadEvent extends MessageHandler {
|
||||
|
||||
Room room = this.client.getHabbo().getHabboInfo().getCurrentRoom();
|
||||
if (room != null) {
|
||||
// If re-entering the same room (session resume / reconnect), capture
|
||||
// the user's current position before removal so we can respawn there.
|
||||
if (room.getId() == roomId && spawnX < 0 && spawnY < 0
|
||||
&& this.client.getHabbo().getRoomUnit() != null
|
||||
&& this.client.getHabbo().getRoomUnit().getCurrentLocation() != null) {
|
||||
RoomTile currentLoc = this.client.getHabbo().getRoomUnit().getCurrentLocation();
|
||||
spawnX = currentLoc.x;
|
||||
spawnY = currentLoc.y;
|
||||
LOGGER.info("[RequestRoomLoadEvent] Re-entering same room {} — preserving position ({}, {})",
|
||||
roomId, spawnX, spawnY);
|
||||
}
|
||||
|
||||
Emulator.getGameEnvironment().getRoomManager().logExit(this.client.getHabbo());
|
||||
|
||||
room.removeHabbo(this.client.getHabbo(), true);
|
||||
@@ -41,7 +73,28 @@ public class RequestRoomLoadEvent extends MessageHandler {
|
||||
this.client.getHabbo().getRoomUnit().isTeleporting = false;
|
||||
}
|
||||
|
||||
Emulator.getGameEnvironment().getRoomManager().enterRoom(this.client.getHabbo(), roomId, password);
|
||||
// Resolve spawn tile from coordinates (either from client or from saved position above)
|
||||
RoomTile spawnTile = null;
|
||||
|
||||
if (spawnX >= 0 && spawnY >= 0) {
|
||||
Room targetRoom = Emulator.getGameEnvironment().getRoomManager().getRoom(roomId);
|
||||
if (targetRoom == null) {
|
||||
targetRoom = Emulator.getGameEnvironment().getRoomManager().loadRoom(roomId);
|
||||
}
|
||||
if (targetRoom != null && targetRoom.getLayout() != null) {
|
||||
RoomTile tile = targetRoom.getLayout().getTile((short) spawnX, (short) spawnY);
|
||||
if (tile != null && tile.isWalkable()) {
|
||||
spawnTile = tile;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
boolean isReconnect = spawnTile != null;
|
||||
LOGGER.debug("[RequestRoomLoadEvent] Entering room {} (spawnTile={}, isReconnect={})",
|
||||
roomId,
|
||||
spawnTile != null ? "(" + spawnTile.x + "," + spawnTile.y + ")" : "door",
|
||||
isReconnect);
|
||||
Emulator.getGameEnvironment().getRoomManager().enterRoom(this.client.getHabbo(), roomId, password, false, spawnTile, isReconnect);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+43
@@ -0,0 +1,43 @@
|
||||
package com.eu.habbo.messages.incoming.rooms.items;
|
||||
|
||||
import com.eu.habbo.habbohotel.rooms.Room;
|
||||
import com.eu.habbo.habbohotel.users.HabboItem;
|
||||
import com.eu.habbo.habbohotel.wired.core.WiredManager;
|
||||
import com.eu.habbo.messages.incoming.MessageHandler;
|
||||
|
||||
public class ClickFurniEvent extends MessageHandler {
|
||||
private static final String CLICK_TILE_INTERACTION = "room_invisible_click_tile";
|
||||
|
||||
@Override
|
||||
public void handle() throws Exception {
|
||||
Room room = this.client.getHabbo().getHabboInfo().getCurrentRoom();
|
||||
|
||||
if (room == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
int itemId = Math.abs(this.packet.readInt());
|
||||
this.packet.readInt();
|
||||
|
||||
HabboItem item = room.getHabboItem(itemId);
|
||||
|
||||
if (item == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
WiredManager.triggerUserClicksFurni(room, this.client.getHabbo().getRoomUnit(), item);
|
||||
|
||||
if (isClickTileItem(item)) {
|
||||
WiredManager.triggerUserClicksTile(room, this.client.getHabbo().getRoomUnit(), item);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isClickTileItem(HabboItem item) {
|
||||
if (item == null || item.getBaseItem() == null || item.getBaseItem().getInteractionType() == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
String interaction = item.getBaseItem().getInteractionType().getName();
|
||||
return interaction != null && interaction.equalsIgnoreCase(CLICK_TILE_INTERACTION);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
package com.eu.habbo.messages.incoming.rooms.users;
|
||||
|
||||
import com.eu.habbo.habbohotel.rooms.Room;
|
||||
import com.eu.habbo.habbohotel.rooms.RoomUnit;
|
||||
import com.eu.habbo.habbohotel.users.Habbo;
|
||||
import com.eu.habbo.habbohotel.wired.core.WiredManager;
|
||||
import com.eu.habbo.messages.incoming.MessageHandler;
|
||||
|
||||
public class ClickUserEvent extends MessageHandler {
|
||||
@Override
|
||||
public void handle() throws Exception {
|
||||
Room room = this.client.getHabbo().getHabboInfo().getCurrentRoom();
|
||||
|
||||
if (room == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
RoomUnit clickingUser = this.client.getHabbo().getRoomUnit();
|
||||
|
||||
if (clickingUser == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
int roomUnitId = this.packet.readInt();
|
||||
Habbo clickedHabbo = room.getHabboByRoomUnitId(roomUnitId);
|
||||
|
||||
if (clickedHabbo == null || clickedHabbo.getRoomUnit() == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
WiredManager.triggerUserClicksUser(room, clickingUser, clickedHabbo.getRoomUnit());
|
||||
}
|
||||
}
|
||||
+28
@@ -4,6 +4,8 @@ import com.eu.habbo.Emulator;
|
||||
import com.eu.habbo.habbohotel.rooms.Room;
|
||||
import com.eu.habbo.habbohotel.rooms.RoomUserAction;
|
||||
import com.eu.habbo.habbohotel.users.Habbo;
|
||||
import com.eu.habbo.habbohotel.wired.WiredUserActionType;
|
||||
import com.eu.habbo.habbohotel.wired.core.WiredManager;
|
||||
import com.eu.habbo.messages.incoming.MessageHandler;
|
||||
import com.eu.habbo.messages.outgoing.rooms.users.RoomUserActionComposer;
|
||||
import com.eu.habbo.plugin.events.users.UserIdleEvent;
|
||||
@@ -26,6 +28,7 @@ public class RoomUserActionEvent extends MessageHandler {
|
||||
}
|
||||
|
||||
int action = this.packet.readInt();
|
||||
int wiredAction = 0;
|
||||
|
||||
if (action == 5) {
|
||||
UserIdleEvent event = new UserIdleEvent(this.client.getHabbo(), UserIdleEvent.IdleReason.ACTION, true);
|
||||
@@ -34,8 +37,10 @@ public class RoomUserActionEvent extends MessageHandler {
|
||||
if (!event.isCancelled()) {
|
||||
if (event.idle) {
|
||||
room.idle(habbo);
|
||||
wiredAction = WiredUserActionType.RELAX;
|
||||
} else {
|
||||
room.unIdle(habbo);
|
||||
wiredAction = WiredUserActionType.AWAKE;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@@ -51,6 +56,29 @@ public class RoomUserActionEvent extends MessageHandler {
|
||||
}
|
||||
|
||||
room.sendComposer(new RoomUserActionComposer(habbo.getRoomUnit(), RoomUserAction.fromValue(action)).compose());
|
||||
|
||||
if (wiredAction == 0) {
|
||||
switch (action) {
|
||||
case 1:
|
||||
wiredAction = WiredUserActionType.WAVE;
|
||||
break;
|
||||
case 2:
|
||||
wiredAction = WiredUserActionType.BLOW_KISS;
|
||||
break;
|
||||
case 3:
|
||||
wiredAction = WiredUserActionType.LAUGH;
|
||||
break;
|
||||
case 7:
|
||||
wiredAction = WiredUserActionType.THUMB_UP;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (wiredAction != 0) {
|
||||
WiredManager.triggerUserPerformsAction(room, habbo.getRoomUnit(), wiredAction, -1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+8
-5
@@ -3,8 +3,9 @@ package com.eu.habbo.messages.incoming.rooms.users;
|
||||
import com.eu.habbo.Emulator;
|
||||
import com.eu.habbo.habbohotel.users.DanceType;
|
||||
import com.eu.habbo.habbohotel.users.Habbo;
|
||||
import com.eu.habbo.habbohotel.wired.WiredUserActionType;
|
||||
import com.eu.habbo.habbohotel.wired.core.WiredManager;
|
||||
import com.eu.habbo.messages.incoming.MessageHandler;
|
||||
import com.eu.habbo.messages.outgoing.rooms.users.RoomUserDanceComposer;
|
||||
import com.eu.habbo.plugin.events.users.UserIdleEvent;
|
||||
|
||||
public class RoomUserDanceEvent extends MessageHandler {
|
||||
@@ -14,7 +15,7 @@ public class RoomUserDanceEvent extends MessageHandler {
|
||||
return;
|
||||
|
||||
int danceId = this.packet.readInt();
|
||||
if (danceId >= 0 && danceId <= 5) {
|
||||
if (danceId >= 0 && danceId <= 4) {
|
||||
if (this.client.getHabbo().getRoomUnit().isInRoom()) {
|
||||
|
||||
Habbo habbo = this.client.getHabbo();
|
||||
@@ -29,8 +30,6 @@ public class RoomUserDanceEvent extends MessageHandler {
|
||||
}
|
||||
}
|
||||
|
||||
habbo.getRoomUnit().setDanceType(DanceType.values()[danceId]);
|
||||
|
||||
UserIdleEvent event = new UserIdleEvent(this.client.getHabbo(), UserIdleEvent.IdleReason.DANCE, false);
|
||||
Emulator.getPluginManager().fireEvent(event);
|
||||
|
||||
@@ -40,7 +39,11 @@ public class RoomUserDanceEvent extends MessageHandler {
|
||||
}
|
||||
}
|
||||
|
||||
this.client.getHabbo().getHabboInfo().getCurrentRoom().sendComposer(new RoomUserDanceComposer(habbo.getRoomUnit()).compose());
|
||||
this.client.getHabbo().getHabboInfo().getCurrentRoom().dance(habbo, DanceType.values()[danceId]);
|
||||
|
||||
if (danceId > 0) {
|
||||
WiredManager.triggerUserPerformsAction(this.client.getHabbo().getHabboInfo().getCurrentRoom(), habbo.getRoomUnit(), WiredUserActionType.DANCE, danceId);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+3
@@ -5,6 +5,8 @@ import com.eu.habbo.habbohotel.items.interactions.InteractionVoteCounter;
|
||||
import com.eu.habbo.habbohotel.rooms.Room;
|
||||
import com.eu.habbo.habbohotel.rooms.RoomUnitStatus;
|
||||
import com.eu.habbo.habbohotel.users.HabboItem;
|
||||
import com.eu.habbo.habbohotel.wired.WiredUserActionType;
|
||||
import com.eu.habbo.habbohotel.wired.core.WiredManager;
|
||||
import com.eu.habbo.messages.incoming.MessageHandler;
|
||||
import com.eu.habbo.plugin.events.users.UserSignEvent;
|
||||
|
||||
@@ -22,6 +24,7 @@ public class RoomUserSignEvent extends MessageHandler {
|
||||
if (!Emulator.getPluginManager().fireEvent(event).isCancelled()) {
|
||||
this.client.getHabbo().getRoomUnit().setStatus(RoomUnitStatus.SIGN, event.sign + "");
|
||||
this.client.getHabbo().getHabboInfo().getCurrentRoom().unIdle(this.client.getHabbo());
|
||||
WiredManager.triggerUserPerformsAction(room, this.client.getHabbo().getRoomUnit(), WiredUserActionType.SIGN, event.sign);
|
||||
|
||||
if(signId <= 10) {
|
||||
|
||||
|
||||
+7
@@ -7,11 +7,18 @@ import com.eu.habbo.plugin.events.users.UserIdleEvent;
|
||||
public class RoomUserSitEvent extends MessageHandler {
|
||||
@Override
|
||||
public void handle() throws Exception {
|
||||
int posture = this.packet.readInt();
|
||||
|
||||
if (this.client.getHabbo().getHabboInfo().getCurrentRoom() != null) {
|
||||
if (this.client.getHabbo().getRoomUnit().isWalking()) {
|
||||
this.client.getHabbo().getRoomUnit().stopWalking();
|
||||
}
|
||||
|
||||
if (posture == 0) {
|
||||
this.client.getHabbo().getHabboInfo().getCurrentRoom().makeStand(this.client.getHabbo());
|
||||
} else {
|
||||
this.client.getHabbo().getHabboInfo().getCurrentRoom().makeSit(this.client.getHabbo());
|
||||
}
|
||||
|
||||
UserIdleEvent event = new UserIdleEvent(this.client.getHabbo(), UserIdleEvent.IdleReason.WALKED, false);
|
||||
Emulator.getPluginManager().fireEvent(event);
|
||||
|
||||
+2
-1
@@ -10,6 +10,7 @@ import com.eu.habbo.habbohotel.rooms.BedProfile;
|
||||
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.habbohotel.wired.core.WiredFreezeUtil;
|
||||
import com.eu.habbo.messages.incoming.MessageHandler;
|
||||
import com.eu.habbo.messages.outgoing.rooms.users.RoomUnitOnRollerComposer;
|
||||
import com.eu.habbo.plugin.events.users.UserIdleEvent;
|
||||
@@ -46,7 +47,7 @@ public class RoomUserWalkEvent extends MessageHandler {
|
||||
Room room = habboInfo.getCurrentRoom();
|
||||
|
||||
try {
|
||||
if (roomUnit != null && roomUnit.isInRoom() && roomUnit.canWalk()) {
|
||||
if (roomUnit != null && roomUnit.isInRoom() && roomUnit.canWalk() && !WiredFreezeUtil.isFrozen(roomUnit)) {
|
||||
if (roomUnit.cmdTeleport) {
|
||||
handleTeleport(room, (short) x, (short) y, roomUnit, habboInfo);
|
||||
return;
|
||||
|
||||
+4
@@ -34,6 +34,7 @@ public class WiredTriggerSaveDataEvent extends MessageHandler {
|
||||
if (saveMethod.get().getParameterTypes()[0] == WiredSettings.class) {
|
||||
WiredSettings settings = InteractionWired.readSettings(this.packet, false);
|
||||
|
||||
try {
|
||||
if (trigger.saveData(settings)) {
|
||||
this.client.sendResponse(new WiredSavedComposer());
|
||||
|
||||
@@ -46,6 +47,9 @@ public class WiredTriggerSaveDataEvent extends MessageHandler {
|
||||
} else {
|
||||
this.client.sendResponse(new UpdateFailedComposer("There was an error while saving that trigger"));
|
||||
}
|
||||
} catch (WiredTriggerSaveException e) {
|
||||
this.client.sendResponse(new UpdateFailedComposer(e.getMessage()));
|
||||
}
|
||||
} else {
|
||||
if ((boolean) saveMethod.get().invoke(trigger, this.packet)) {
|
||||
this.client.sendResponse(new WiredSavedComposer());
|
||||
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
package com.eu.habbo.messages.incoming.wired;
|
||||
|
||||
public class WiredTriggerSaveException extends RuntimeException {
|
||||
public WiredTriggerSaveException(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
||||
@@ -504,6 +504,7 @@ public class Outgoing {
|
||||
public final static int WiredOpenComposer = 1830;
|
||||
public final static int UnknownCatalogPageOfferComposer = 1889;
|
||||
public final static int NuxAlertComposer = 2023;
|
||||
public final static int InClientLinkComposer = 2023;
|
||||
public final static int HotelViewExpiringCatalogPageCommposer = 2515;
|
||||
public final static int UnknownHabboWayQuizComposer = 2772;
|
||||
public final static int PetLevelUpdatedComposer = 2824;
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
package com.eu.habbo.messages.outgoing.users;
|
||||
|
||||
import com.eu.habbo.messages.ServerMessage;
|
||||
import com.eu.habbo.messages.outgoing.MessageComposer;
|
||||
import com.eu.habbo.messages.outgoing.Outgoing;
|
||||
|
||||
public class InClientLinkComposer extends MessageComposer {
|
||||
private final String link;
|
||||
|
||||
public InClientLinkComposer(String link) {
|
||||
this.link = link;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ServerMessage composeInternal() {
|
||||
this.response.init(Outgoing.InClientLinkComposer);
|
||||
this.response.appendString(this.link);
|
||||
return this.response;
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -8,7 +8,7 @@ public class MutedWhisperComposer extends MessageComposer {
|
||||
private final int seconds;
|
||||
|
||||
public MutedWhisperComposer(int seconds) {
|
||||
this.seconds = seconds;
|
||||
this.seconds = Math.max(0, seconds);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -5,6 +5,7 @@ import com.eu.habbo.habbohotel.rooms.RoomTile;
|
||||
import com.eu.habbo.habbohotel.rooms.RoomUnit;
|
||||
import com.eu.habbo.habbohotel.rooms.RoomUnitStatus;
|
||||
import com.eu.habbo.habbohotel.users.HabboItem;
|
||||
import com.eu.habbo.habbohotel.wired.core.WiredFreezeUtil;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@@ -38,6 +39,8 @@ public class RoomUnitTeleport implements Runnable {
|
||||
return;
|
||||
}
|
||||
|
||||
WiredFreezeUtil.onTeleport(this.room, this.roomUnit);
|
||||
|
||||
RoomTile lastLocation = this.roomUnit.getCurrentLocation();
|
||||
RoomTile newLocation = this.room.getLayout().getTile((short) this.x, (short) this.y);
|
||||
|
||||
@@ -60,6 +63,7 @@ public class RoomUnitTeleport implements Runnable {
|
||||
//this.room.sendComposer(teleportMessage);
|
||||
this.roomUnit.statusUpdate(true);
|
||||
roomUnit.isWiredTeleporting = false;
|
||||
WiredFreezeUtil.restoreWalkState(this.roomUnit);
|
||||
|
||||
this.room.updateHabbosAt(newLocation.x, newLocation.y);
|
||||
this.room.updateBotsAt(newLocation.x, newLocation.y);
|
||||
|
||||
+4
@@ -5,6 +5,7 @@ import com.eu.habbo.habbohotel.gameclients.GameClient;
|
||||
import com.eu.habbo.habbohotel.items.interactions.InteractionTeleportTile;
|
||||
import com.eu.habbo.habbohotel.rooms.*;
|
||||
import com.eu.habbo.habbohotel.users.HabboItem;
|
||||
import com.eu.habbo.habbohotel.wired.core.WiredFreezeUtil;
|
||||
import com.eu.habbo.threading.runnables.HabboItemNewState;
|
||||
import com.eu.habbo.threading.runnables.RoomUnitWalkToLocation;
|
||||
|
||||
@@ -46,6 +47,7 @@ class TeleportActionFive implements Runnable {
|
||||
List<Runnable> onSuccess = new ArrayList<Runnable>();
|
||||
onSuccess.add(() -> {
|
||||
unit.setCanLeaveRoomByDoor(true);
|
||||
WiredFreezeUtil.restoreWalkState(unit);
|
||||
|
||||
Emulator.getThreading().run(() -> {
|
||||
unit.isLeavingTeleporter = false;
|
||||
@@ -57,6 +59,8 @@ class TeleportActionFive implements Runnable {
|
||||
unit.statusUpdate(true);
|
||||
unit.isLeavingTeleporter = true;
|
||||
Emulator.getThreading().run(new RoomUnitWalkToLocation(unit, tile, room, onSuccess, onSuccess));
|
||||
} else {
|
||||
WiredFreezeUtil.restoreWalkState(unit);
|
||||
}
|
||||
|
||||
this.currentTeleport.setExtradata("1");
|
||||
|
||||
+2
-1
@@ -4,6 +4,7 @@ import com.eu.habbo.Emulator;
|
||||
import com.eu.habbo.habbohotel.gameclients.GameClient;
|
||||
import com.eu.habbo.habbohotel.rooms.Room;
|
||||
import com.eu.habbo.habbohotel.users.HabboItem;
|
||||
import com.eu.habbo.habbohotel.wired.core.WiredFreezeUtil;
|
||||
|
||||
class TeleportActionFour implements Runnable {
|
||||
private final HabboItem currentTeleport;
|
||||
@@ -21,7 +22,7 @@ class TeleportActionFour implements Runnable {
|
||||
if (this.client.getHabbo().getHabboInfo().getCurrentRoom() != this.room) {
|
||||
this.client.getHabbo().getHabboInfo().setLoadingRoom(0);
|
||||
this.client.getHabbo().getRoomUnit().isTeleporting = false;
|
||||
this.client.getHabbo().getRoomUnit().setCanWalk(true);
|
||||
WiredFreezeUtil.restoreWalkState(this.client.getHabbo().getRoomUnit());
|
||||
this.currentTeleport.setExtradata("0");
|
||||
this.room.updateItem(this.currentTeleport);
|
||||
return;
|
||||
|
||||
+2
-1
@@ -7,6 +7,7 @@ import com.eu.habbo.habbohotel.rooms.Room;
|
||||
import com.eu.habbo.habbohotel.rooms.RoomUnitStatus;
|
||||
import com.eu.habbo.habbohotel.rooms.RoomUserRotation;
|
||||
import com.eu.habbo.habbohotel.users.HabboItem;
|
||||
import com.eu.habbo.habbohotel.wired.core.WiredFreezeUtil;
|
||||
import com.eu.habbo.messages.outgoing.rooms.users.RoomUserStatusComposer;
|
||||
|
||||
public class TeleportActionOne implements Runnable {
|
||||
@@ -25,7 +26,7 @@ public class TeleportActionOne implements Runnable {
|
||||
if (this.client.getHabbo().getHabboInfo().getCurrentRoom() != this.room) {
|
||||
this.client.getHabbo().getHabboInfo().setLoadingRoom(0);
|
||||
this.client.getHabbo().getRoomUnit().isTeleporting = false;
|
||||
this.client.getHabbo().getRoomUnit().setCanWalk(true);
|
||||
WiredFreezeUtil.restoreWalkState(this.client.getHabbo().getRoomUnit());
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
+2
-1
@@ -9,6 +9,7 @@ import com.eu.habbo.habbohotel.rooms.RoomTile;
|
||||
import com.eu.habbo.habbohotel.rooms.RoomUnitStatus;
|
||||
import com.eu.habbo.habbohotel.rooms.RoomUserRotation;
|
||||
import com.eu.habbo.habbohotel.users.HabboItem;
|
||||
import com.eu.habbo.habbohotel.wired.core.WiredFreezeUtil;
|
||||
|
||||
class TeleportActionThree implements Runnable {
|
||||
private final HabboItem currentTeleport;
|
||||
@@ -26,7 +27,7 @@ class TeleportActionThree implements Runnable {
|
||||
if (this.client.getHabbo().getHabboInfo().getCurrentRoom() != this.room) {
|
||||
this.client.getHabbo().getHabboInfo().setLoadingRoom(0);
|
||||
this.client.getHabbo().getRoomUnit().isTeleporting = false;
|
||||
this.client.getHabbo().getRoomUnit().setCanWalk(true);
|
||||
WiredFreezeUtil.restoreWalkState(this.client.getHabbo().getRoomUnit());
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
+2
-1
@@ -7,6 +7,7 @@ import com.eu.habbo.habbohotel.items.interactions.InteractionTeleportTile;
|
||||
import com.eu.habbo.habbohotel.rooms.Room;
|
||||
import com.eu.habbo.habbohotel.rooms.RoomUnitStatus;
|
||||
import com.eu.habbo.habbohotel.users.HabboItem;
|
||||
import com.eu.habbo.habbohotel.wired.core.WiredFreezeUtil;
|
||||
import com.eu.habbo.messages.outgoing.rooms.users.RoomUserStatusComposer;
|
||||
import com.eu.habbo.threading.runnables.HabboItemNewState;
|
||||
import org.slf4j.Logger;
|
||||
@@ -41,7 +42,7 @@ class TeleportActionTwo implements Runnable {
|
||||
if (this.client.getHabbo().getHabboInfo().getCurrentRoom() != this.room) {
|
||||
this.client.getHabbo().getHabboInfo().setLoadingRoom(0);
|
||||
this.client.getHabbo().getRoomUnit().isTeleporting = false;
|
||||
this.client.getHabbo().getRoomUnit().setCanWalk(true);
|
||||
WiredFreezeUtil.restoreWalkState(this.client.getHabbo().getRoomUnit());
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
package com.eu.habbo.util;
|
||||
|
||||
import com.eu.habbo.Emulator;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.LocalTime;
|
||||
import java.time.ZoneId;
|
||||
import java.time.ZonedDateTime;
|
||||
|
||||
public final class HotelDateTimeUtil {
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(HotelDateTimeUtil.class);
|
||||
private static final String CONFIG_KEY = "hotel.timezone";
|
||||
private static volatile String lastInvalidTimezoneId = null;
|
||||
|
||||
private HotelDateTimeUtil() {
|
||||
}
|
||||
|
||||
public static String getTimezoneId() {
|
||||
return getZoneId().getId();
|
||||
}
|
||||
|
||||
public static ZoneId getZoneId() {
|
||||
String configuredZoneId = Emulator.getConfig().getValue(CONFIG_KEY, ZoneId.systemDefault().getId());
|
||||
|
||||
try {
|
||||
lastInvalidTimezoneId = null;
|
||||
return ZoneId.of(configuredZoneId.trim());
|
||||
} catch (Exception e) {
|
||||
if (!configuredZoneId.equals(lastInvalidTimezoneId)) {
|
||||
LOGGER.warn("Invalid {} '{}', falling back to system timezone '{}'.", CONFIG_KEY, configuredZoneId, ZoneId.systemDefault().getId());
|
||||
lastInvalidTimezoneId = configuredZoneId;
|
||||
}
|
||||
return ZoneId.systemDefault();
|
||||
}
|
||||
}
|
||||
|
||||
public static ZonedDateTime now() {
|
||||
return ZonedDateTime.now(getZoneId());
|
||||
}
|
||||
|
||||
public static LocalDateTime localDateTimeNow() {
|
||||
return LocalDateTime.now(getZoneId());
|
||||
}
|
||||
|
||||
public static LocalDate localDateNow() {
|
||||
return LocalDate.now(getZoneId());
|
||||
}
|
||||
|
||||
public static LocalTime localTimeNow() {
|
||||
return LocalTime.now(getZoneId());
|
||||
}
|
||||
|
||||
public static long toEpochSecond(LocalDateTime dateTime) {
|
||||
return dateTime.atZone(getZoneId()).toEpochSecond();
|
||||
}
|
||||
}
|
||||
Binary file not shown.
Reference in New Issue
Block a user