diff --git a/Database Updates/21022026_user_prefixes.sql b/Database Updates/21022026_user_prefixes.sql
new file mode 100644
index 00000000..e0ee239f
--- /dev/null
+++ b/Database Updates/21022026_user_prefixes.sql
@@ -0,0 +1,12 @@
+CREATE TABLE IF NOT EXISTS `user_prefixes` (
+ `id` INT(11) NOT NULL AUTO_INCREMENT,
+ `user_id` INT(11) NOT NULL,
+ `text` VARCHAR(50) NOT NULL,
+ `color` VARCHAR(255) NOT NULL DEFAULT '#FFFFFF',
+ `icon` VARCHAR(50) NOT NULL DEFAULT '',
+ `effect` VARCHAR(50) NOT NULL DEFAULT '',
+ `active` TINYINT(1) NOT NULL DEFAULT 0,
+ PRIMARY KEY (`id`),
+ INDEX `idx_user_id` (`user_id`),
+ INDEX `idx_user_active` (`user_id`, `active`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
\ No newline at end of file
diff --git a/Emulator/.idea/misc.xml b/Emulator/.idea/misc.xml
index 5ddb3b31..6568344f 100644
--- a/Emulator/.idea/misc.xml
+++ b/Emulator/.idea/misc.xml
@@ -8,5 +8,5 @@
-
+
\ No newline at end of file
diff --git a/Emulator/plugins/NitroWebsockets-3.1.jar b/Emulator/NitroWebsockets-3.1.jar
similarity index 100%
rename from Emulator/plugins/NitroWebsockets-3.1.jar
rename to Emulator/NitroWebsockets-3.1.jar
diff --git a/Emulator/src/main/java/com/eu/habbo/Emulator.java b/Emulator/src/main/java/com/eu/habbo/Emulator.java
index 11f29086..edca543c 100644
--- a/Emulator/src/main/java/com/eu/habbo/Emulator.java
+++ b/Emulator/src/main/java/com/eu/habbo/Emulator.java
@@ -56,6 +56,8 @@ public final class Emulator {
public static String build = "";
public static long buildTimestamp = -1L;
+
+
public static boolean isReady = false;
public static boolean isShuttingDown = false;
public static boolean stopped = false;
diff --git a/Emulator/src/main/java/com/eu/habbo/habbohotel/games/GamePlayer.java b/Emulator/src/main/java/com/eu/habbo/habbohotel/games/GamePlayer.java
index a76f01dd..114aa86d 100644
--- a/Emulator/src/main/java/com/eu/habbo/habbohotel/games/GamePlayer.java
+++ b/Emulator/src/main/java/com/eu/habbo/habbohotel/games/GamePlayer.java
@@ -36,8 +36,16 @@ public class GamePlayer {
if (this.score < 0) this.score = 0;
- if(isWired && this.score > 0) {
+ if(isWired) {
this.wiredScore += amount;
+
+ if (this.wiredScore < 0) {
+ this.wiredScore = 0;
+ }
+
+ if (this.wiredScore > this.score) {
+ this.wiredScore = this.score;
+ }
}
WiredManager.triggerScoreAchieved(this.habbo.getHabboInfo().getCurrentRoom(), this.habbo.getRoomUnit(), this.score, amount);
diff --git a/Emulator/src/main/java/com/eu/habbo/habbohotel/games/wired/WiredGame.java b/Emulator/src/main/java/com/eu/habbo/habbohotel/games/wired/WiredGame.java
index 80fe874d..631345e2 100644
--- a/Emulator/src/main/java/com/eu/habbo/habbohotel/games/wired/WiredGame.java
+++ b/Emulator/src/main/java/com/eu/habbo/habbohotel/games/wired/WiredGame.java
@@ -6,6 +6,10 @@ import com.eu.habbo.habbohotel.rooms.Room;
import com.eu.habbo.habbohotel.users.Habbo;
public class WiredGame extends Game {
+ public static final int RED_EFFECT_ID = 223;
+ public static final int BLUE_EFFECT_ID = 224;
+ public static final int YELLOW_EFFECT_ID = 225;
+ public static final int GREEN_EFFECT_ID = 226;
public GameState state = GameState.RUNNING;
public WiredGame(Room room) {
@@ -28,7 +32,7 @@ public class WiredGame extends Game {
@Override
public boolean addHabbo(Habbo habbo, GameTeamColors teamColor) {
- this.room.giveEffect(habbo, FreezeGame.effectId + teamColor.type, -1);
+ this.room.giveEffect(habbo, this.getEffectId(teamColor), -1);
return super.addHabbo(habbo, teamColor);
}
@@ -47,4 +51,19 @@ public class WiredGame extends Game {
public GameState getState() {
return GameState.RUNNING;
}
-}
\ No newline at end of file
+
+ private int getEffectId(GameTeamColors teamColor) {
+ switch (teamColor) {
+ case RED:
+ return RED_EFFECT_ID;
+ case BLUE:
+ return BLUE_EFFECT_ID;
+ case YELLOW:
+ return YELLOW_EFFECT_ID;
+ case GREEN:
+ return GREEN_EFFECT_ID;
+ default:
+ return FreezeGame.effectId + teamColor.type;
+ }
+ }
+}
diff --git a/Emulator/src/main/java/com/eu/habbo/habbohotel/items/ItemManager.java b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/ItemManager.java
index ac2eab14..d4ac19c7 100644
--- a/Emulator/src/main/java/com/eu/habbo/habbohotel/items/ItemManager.java
+++ b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/ItemManager.java
@@ -3,6 +3,7 @@ package com.eu.habbo.habbohotel.items;
import com.eu.habbo.Emulator;
import com.eu.habbo.habbohotel.items.interactions.*;
import com.eu.habbo.habbohotel.items.interactions.games.InteractionGameTimer;
+import com.eu.habbo.habbohotel.items.interactions.games.InteractionGameUpCounter;
import com.eu.habbo.habbohotel.items.interactions.games.battlebanzai.InteractionBattleBanzaiPuck;
import com.eu.habbo.habbohotel.items.interactions.games.battlebanzai.InteractionBattleBanzaiSphere;
import com.eu.habbo.habbohotel.items.interactions.games.battlebanzai.InteractionBattleBanzaiTeleporter;
@@ -49,6 +50,12 @@ 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.extra.WiredBlob;
+import com.eu.habbo.habbohotel.items.interactions.wired.extra.WiredExtraAnimationTime;
+import com.eu.habbo.habbohotel.items.interactions.wired.extra.WiredExtraFilterFurni;
+import com.eu.habbo.habbohotel.items.interactions.wired.extra.WiredExtraFilterUser;
+import com.eu.habbo.habbohotel.items.interactions.wired.extra.WiredExtraMoveCarryUsers;
+import com.eu.habbo.habbohotel.items.interactions.wired.extra.WiredExtraMovePhysics;
+import com.eu.habbo.habbohotel.items.interactions.wired.extra.WiredExtraMoveNoAnimation;
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;
@@ -202,6 +209,7 @@ public class ItemManager {
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("game_upcounter", InteractionGameUpCounter.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));
@@ -212,6 +220,7 @@ public class ItemManager {
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_clock_counter", WiredTriggerClockCounter.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));
@@ -267,11 +276,26 @@ public class ItemManager {
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_act_control_clock", WiredEffectControlClock.class));
+ this.interactionsList.add(new ItemInteraction("wf_act_adjust_clock", WiredEffectAdjustClock.class));
+ this.interactionsList.add(new ItemInteraction("wf_act_move_rotate_user", WiredEffectMoveRotateUser.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));
+ this.interactionsList.add(new ItemInteraction("wf_slc_furni_altitude", WiredEffectFurniAltitude.class));
+ this.interactionsList.add(new ItemInteraction("wf_slc_furni_onfurni", WiredEffectFurniOnFurni.class));
+ this.interactionsList.add(new ItemInteraction("wf_slc_furni_picks", WiredEffectFurniPicks.class));
+ this.interactionsList.add(new ItemInteraction("wf_slc_furni_signal", WiredEffectFurniSignal.class));
this.interactionsList.add(new ItemInteraction("wf_slc_users_area", WiredEffectUsersArea.class));
this.interactionsList.add(new ItemInteraction("wf_slc_users_neighborhood", WiredEffectUsersNeighborhood.class));
+ this.interactionsList.add(new ItemInteraction("wf_slc_users_signal", WiredEffectUsersSignal.class));
+ this.interactionsList.add(new ItemInteraction("wf_slc_users_bytype", WiredEffectUsersByType.class));
+ this.interactionsList.add(new ItemInteraction("wf_slc_users_team", WiredEffectUsersTeam.class));
+ this.interactionsList.add(new ItemInteraction("wf_slc_users_byaction", WiredEffectUsersByAction.class));
+ this.interactionsList.add(new ItemInteraction("wf_slc_users_byname", WiredEffectUsersByName.class));
+ this.interactionsList.add(new ItemInteraction("wf_slc_users_handitem", WiredEffectUsersHandItem.class));
+ this.interactionsList.add(new ItemInteraction("wf_slc_users_onfurni", WiredEffectUsersOnFurni.class));
+ this.interactionsList.add(new ItemInteraction("wf_slc_users_group", WiredEffectUsersGroup.class));
this.interactionsList.add(new ItemInteraction("wf_act_send_signal", WiredEffectSendSignal.class));
this.interactionsList.add(new ItemInteraction("wf_cnd_has_furni_on", WiredConditionFurniHaveFurni.class));
@@ -300,9 +324,11 @@ public class ItemManager {
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_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_actor_dir", WiredConditionActorDir.class));
+ this.interactionsList.add(new ItemInteraction("wf_cnd_slc_quantity", WiredConditionSelectionQuantity.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));
@@ -316,6 +342,13 @@ public class ItemManager {
this.interactionsList.add(new ItemInteraction("wf_xtra_unseen", WiredExtraUnseen.class));
this.interactionsList.add(new ItemInteraction("wf_blob", WiredBlob.class));
this.interactionsList.add(new ItemInteraction("wf_xtra_or_eval", WiredExtraOrEval.class));
+ this.interactionsList.add(new ItemInteraction("wf_xtra_filter_furni", WiredExtraFilterFurni.class));
+ this.interactionsList.add(new ItemInteraction("wf_xtra_filter_user", WiredExtraFilterUser.class));
+ this.interactionsList.add(new ItemInteraction("wf_xtra_filter_users", WiredExtraFilterUser.class));
+ this.interactionsList.add(new ItemInteraction("wf_xtra_mov_carry_users", WiredExtraMoveCarryUsers.class));
+ this.interactionsList.add(new ItemInteraction("wf_xtra_mov_no_animation", WiredExtraMoveNoAnimation.class));
+ this.interactionsList.add(new ItemInteraction("wf_xtra_anim_time", WiredExtraAnimationTime.class));
+ this.interactionsList.add(new ItemInteraction("wf_xtra_mov_physics", WiredExtraMovePhysics.class));
this.interactionsList.add(new ItemInteraction("wf_highscore", InteractionWiredHighscore.class));
diff --git a/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/InteractionWiredEffect.java b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/InteractionWiredEffect.java
index d303291d..84c7453a 100644
--- a/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/InteractionWiredEffect.java
+++ b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/InteractionWiredEffect.java
@@ -16,6 +16,8 @@ import com.eu.habbo.messages.outgoing.wired.WiredEffectDataComposer;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Collection;
+import java.util.LinkedHashSet;
+import java.util.Set;
import java.util.function.Predicate;
/**
@@ -198,4 +200,56 @@ public abstract class InteractionWiredEffect extends InteractionWired implements
|| additionalRemoveCondition.test(item));
return sizeBefore - items.size();
}
+
+ protected LinkedHashSet applySelectorModifiers(Iterable matchedTargets,
+ Iterable availableTargets,
+ Iterable existingTargets,
+ boolean filterExisting,
+ boolean invert) {
+ LinkedHashSet matched = toLinkedHashSet(matchedTargets);
+ LinkedHashSet base = filterExisting
+ ? toLinkedHashSet(existingTargets)
+ : toLinkedHashSet(availableTargets);
+
+ if (invert) {
+ base.removeAll(matched);
+ return base;
+ }
+
+ if (filterExisting) {
+ matched.retainAll(base);
+ }
+
+ return matched;
+ }
+
+ protected LinkedHashSet getSelectableFloorItems(Room room) {
+ LinkedHashSet result = new LinkedHashSet<>();
+ if (room == null) {
+ return result;
+ }
+
+ room.getFloorItems().forEach(item -> {
+ if (item != null && !(item instanceof InteractionWired)) {
+ result.add(item);
+ }
+ });
+
+ return result;
+ }
+
+ protected LinkedHashSet toLinkedHashSet(Iterable values) {
+ LinkedHashSet result = new LinkedHashSet<>();
+ if (values == null) {
+ return result;
+ }
+
+ for (T value : values) {
+ if (value != null) {
+ result.add(value);
+ }
+ }
+
+ return result;
+ }
}
diff --git a/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/InteractionWiredExtra.java b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/InteractionWiredExtra.java
index b946d7d9..727684f8 100644
--- a/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/InteractionWiredExtra.java
+++ b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/InteractionWiredExtra.java
@@ -2,8 +2,11 @@ package com.eu.habbo.habbohotel.items.interactions;
import com.eu.habbo.habbohotel.gameclients.GameClient;
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.messages.incoming.wired.WiredSaveException;
+import com.eu.habbo.messages.outgoing.wired.WiredExtraDataComposer;
import java.sql.ResultSet;
import java.sql.SQLException;
@@ -21,6 +24,9 @@ public abstract class InteractionWiredExtra extends InteractionWired {
public void onClick(GameClient client, Room room, Object[] objects) throws Exception {
if (client != null) {
if (room.hasRights(client.getHabbo())) {
+ if (this.hasConfiguration()) {
+ client.sendResponse(new WiredExtraDataComposer(this, room));
+ }
this.activateBox(room);
}
}
@@ -35,4 +41,12 @@ public abstract class InteractionWiredExtra extends InteractionWired {
public boolean isWalkable() {
return true;
}
-}
\ No newline at end of file
+
+ public boolean saveData(WiredSettings settings, GameClient gameClient) throws WiredSaveException {
+ return true;
+ }
+
+ public boolean hasConfiguration() {
+ return false;
+ }
+}
diff --git a/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/InteractionWiredTrigger.java b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/InteractionWiredTrigger.java
index e6410040..16e5b4c8 100644
--- a/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/InteractionWiredTrigger.java
+++ b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/InteractionWiredTrigger.java
@@ -56,6 +56,10 @@ public abstract class InteractionWiredTrigger extends InteractionWired implement
public abstract boolean saveData(WiredSettings settings);
+ public boolean saveData(WiredSettings settings, GameClient gameClient) {
+ return this.saveData(settings);
+ }
+
protected int getDelay() {
return this.delay;
}
diff --git a/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/games/InteractionGameTimer.java b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/games/InteractionGameTimer.java
index e93d5308..62160f59 100644
--- a/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/games/InteractionGameTimer.java
+++ b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/games/InteractionGameTimer.java
@@ -24,13 +24,13 @@ import java.util.Arrays;
public class InteractionGameTimer extends HabboItem {
private static final Logger LOGGER = LoggerFactory.getLogger(InteractionGameTimer.class);
- private int[] TIMER_INTERVAL_STEPS = new int[] { 30, 60, 120, 180, 300, 600 };
+ protected int[] TIMER_INTERVAL_STEPS = new int[] { 30, 60, 120, 180, 300, 600 };
- private int baseTime = 0;
- private int timeNow = 0;
- private boolean isRunning = false;
- private boolean isPaused = false;
- private boolean threadActive = false;
+ protected int baseTime = 0;
+ protected int timeNow = 0;
+ protected boolean isRunning = false;
+ protected boolean isPaused = false;
+ protected boolean threadActive = false;
public enum InteractionGameTimerAction {
START_STOP(1),
@@ -83,7 +83,7 @@ public class InteractionGameTimer extends HabboItem {
parseCustomParams(item);
}
- private void parseCustomParams(Item baseItem) {
+ protected void parseCustomParams(Item baseItem) {
try {
TIMER_INTERVAL_STEPS = Arrays.stream(baseItem.getCustomParams().split(","))
.mapToInt(s -> {
@@ -114,7 +114,7 @@ public class InteractionGameTimer extends HabboItem {
}
}
- private void createNewGame(Room room) {
+ protected void createNewGame(Room room) {
for(Class extends Game> gameClass : Emulator.getGameEnvironment().getRoomManager().getGameTypes()) {
Game existingGame = room.getGame(gameClass);
@@ -132,13 +132,13 @@ public class InteractionGameTimer extends HabboItem {
}
}
- private void pause(Room room) {
+ protected void pause(Room room) {
for (Game game : room.getGames()) {
game.pause();
}
}
- private void unpause(Room room) {
+ protected void unpause(Room room) {
for (Game game : room.getGames()) {
game.unpause();
}
@@ -155,7 +155,8 @@ public class InteractionGameTimer extends HabboItem {
public void onPickUp(Room room) {
this.endGame(room);
- this.setExtradata(this.baseTime + "\t" + this.baseTime);
+ this.timeNow = this.getInitialTimeValue();
+ this.setExtradata(this.timeNow + "\t" + this.baseTime);
this.needsUpdate(true);
}
@@ -165,7 +166,7 @@ public class InteractionGameTimer extends HabboItem {
this.baseTime = this.TIMER_INTERVAL_STEPS[0];
}
- this.timeNow = this.baseTime;
+ this.timeNow = this.getInitialTimeValue();
this.setExtradata(this.timeNow + "\t" + this.baseTime);
room.updateItem(this);
@@ -212,7 +213,7 @@ public class InteractionGameTimer extends HabboItem {
this.createNewGame(room);
- this.timeNow = this.baseTime;
+ this.resetTimeForStart();
this.isRunning = true;
this.isPaused = false;
@@ -221,7 +222,7 @@ public class InteractionGameTimer extends HabboItem {
if (!this.threadActive) {
this.threadActive = true;
- Emulator.getThreading().run(new GameTimer(this), 1000);
+ this.scheduleTimerRunnable(this.getTimerStartDelayMs());
}
} else if (client != null) {
if (!(room.hasRights(client.getHabbo()) || client.getHabbo().hasPermission(Permission.ACC_ANYROOMOWNER)))
@@ -244,13 +245,13 @@ public class InteractionGameTimer extends HabboItem {
if (!this.threadActive) {
this.threadActive = true;
- Emulator.getThreading().run(new GameTimer(this));
+ this.scheduleTimerRunnable(this.getTimerResumeDelayMs());
}
}
} else {
this.isPaused = false;
this.isRunning = true;
- this.timeNow = this.baseTime;
+ this.resetTimeForStart();
room.updateItem(this);
this.createNewGame(room);
@@ -258,7 +259,7 @@ public class InteractionGameTimer extends HabboItem {
if (!this.threadActive) {
this.threadActive = true;
- Emulator.getThreading().run(new GameTimer(this), 1000);
+ this.scheduleTimerRunnable(this.getTimerStartDelayMs());
}
}
@@ -290,15 +291,15 @@ public class InteractionGameTimer extends HabboItem {
if (!isRunning) {
isRunning = true;
isPaused = false;
- if(timeNow <= 0) {
- timeNow = baseTime;
+ if (this.shouldResetTimeOnStart()) {
+ this.resetTimeForStart();
room.updateItem(this);
}
this.createNewGame(room);
WiredManager.triggerGameStarts(room);
if (!threadActive) {
threadActive = true;
- Emulator.getThreading().run(new GameTimer(this), 1000);
+ this.scheduleTimerRunnable(this.getTimerStartDelayMs());
}
}
}
@@ -322,12 +323,12 @@ public class InteractionGameTimer extends HabboItem {
if (!this.threadActive) {
this.threadActive = true;
- Emulator.getThreading().run(new GameTimer(this), 1000);
+ this.scheduleTimerRunnable(this.getTimerResumeDelayMs());
}
}
}
- private void increaseTimer(Room room) {
+ protected void increaseTimer(Room room) {
if (this.isRunning)
return;
@@ -347,13 +348,45 @@ public class InteractionGameTimer extends HabboItem {
}
this.baseTime = baseTime;
+ this.timeNow = this.getInitialTimeValue();
this.setExtradata(this.timeNow + "\t" + this.baseTime);
-
- this.timeNow = this.baseTime;
room.updateItem(this);
this.needsUpdate(true);
}
+ protected int getInitialTimeValue() {
+ return this.baseTime;
+ }
+
+ protected boolean shouldResetTimeOnStart() {
+ return this.timeNow <= 0;
+ }
+
+ protected void resetTimeForStart() {
+ this.timeNow = this.baseTime;
+ }
+
+ protected Runnable createTimerRunnable() {
+ return new GameTimer(this);
+ }
+
+ protected long getTimerStartDelayMs() {
+ return 1000L;
+ }
+
+ protected long getTimerResumeDelayMs() {
+ return 0L;
+ }
+
+ protected void scheduleTimerRunnable(long delayMs) {
+ if (delayMs <= 0) {
+ Emulator.getThreading().run(this.createTimerRunnable());
+ return;
+ }
+
+ Emulator.getThreading().run(this.createTimerRunnable(), delayMs);
+ }
+
@Override
public String getDatabaseExtraData() {
return this.getExtradata();
@@ -391,4 +424,8 @@ public class InteractionGameTimer extends HabboItem {
public void setTimeNow(int timeNow) {
this.timeNow = timeNow;
}
+
+ public int getBaseTime() {
+ return this.baseTime;
+ }
}
diff --git a/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/games/InteractionGameUpCounter.java b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/games/InteractionGameUpCounter.java
new file mode 100644
index 00000000..41e05a7a
--- /dev/null
+++ b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/games/InteractionGameUpCounter.java
@@ -0,0 +1,214 @@
+package com.eu.habbo.habbohotel.items.interactions.games;
+
+import com.eu.habbo.habbohotel.items.Item;
+import com.eu.habbo.habbohotel.rooms.Room;
+import com.eu.habbo.habbohotel.wired.core.WiredManager;
+import com.eu.habbo.threading.runnables.games.GameUpCounter;
+
+import java.sql.ResultSet;
+import java.sql.SQLException;
+
+public class InteractionGameUpCounter extends InteractionGameTimer {
+ private static final int ONE_SECOND_MS = 1000;
+ private static final int HALF_SECOND_MS = 500;
+ private static final int MAX_UPCOUNTER_TIME = ((99 * 60) + 59);
+ private int subSecondOffsetMs = 0;
+
+ public InteractionGameUpCounter(ResultSet set, Item baseItem) throws SQLException {
+ super(set, baseItem);
+ this.normalizeCounterState();
+ }
+
+ public InteractionGameUpCounter(int id, int userId, Item item, String extradata, int limitedStack, int limitedSells) {
+ super(id, userId, item, extradata, limitedStack, limitedSells);
+ this.normalizeCounterState();
+ }
+
+ @Override
+ protected void parseCustomParams(Item baseItem) {
+ this.TIMER_INTERVAL_STEPS = new int[] { MAX_UPCOUNTER_TIME };
+ }
+
+ private void normalizeCounterState() {
+ this.baseTime = MAX_UPCOUNTER_TIME;
+ this.setCurrentTimeInMs(this.parseStoredTime() * ONE_SECOND_MS);
+ this.setExtradata(this.timeNow + "\t" + this.baseTime);
+ }
+
+ private int parseStoredTime() {
+ try {
+ String[] data = this.getExtradata().split("\t");
+
+ if (data.length > 0) {
+ int storedTime = Integer.parseInt(data[0]);
+ return Math.max(0, Math.min(storedTime, this.baseTime));
+ }
+ } catch (Exception ignored) {
+ }
+
+ return Math.max(0, Math.min(this.timeNow, this.baseTime));
+ }
+
+ @Override
+ protected int getInitialTimeValue() {
+ return 0;
+ }
+
+ @Override
+ protected boolean shouldResetTimeOnStart() {
+ return this.timeNow >= this.baseTime;
+ }
+
+ @Override
+ protected void resetTimeForStart() {
+ this.setCurrentTimeInMs(0);
+ }
+
+ @Override
+ protected void increaseTimer(Room room) {
+ if (this.isRunning && !this.isPaused) {
+ return;
+ }
+
+ if (this.isRunning) {
+ this.endGame(room);
+ WiredManager.triggerGameEnds(room);
+ }
+
+ this.baseTime = MAX_UPCOUNTER_TIME;
+ this.setCurrentTimeInMs(0);
+ this.applyCounterState(room, true);
+ }
+
+ @Override
+ protected Runnable createTimerRunnable() {
+ return new GameUpCounter(this);
+ }
+
+ @Override
+ protected long getTimerStartDelayMs() {
+ return this.getNextTickDelayMs();
+ }
+
+ @Override
+ protected long getTimerResumeDelayMs() {
+ return this.getNextTickDelayMs();
+ }
+
+ public int getCurrentTimeInMs() {
+ return (this.timeNow * ONE_SECOND_MS) + this.subSecondOffsetMs;
+ }
+
+ public int getMaximumTimeInMs() {
+ return this.baseTime * ONE_SECOND_MS;
+ }
+
+ public long getNextTickDelayMs() {
+ return (this.subSecondOffsetMs > 0) ? HALF_SECOND_MS : ONE_SECOND_MS;
+ }
+
+ public void setCurrentTimeInMs(int totalMs) {
+ int clamped = Math.max(0, Math.min(totalMs, this.getMaximumTimeInMs()));
+ int remainder = clamped % ONE_SECOND_MS;
+
+ this.timeNow = (clamped / ONE_SECOND_MS);
+ this.subSecondOffsetMs = (remainder >= HALF_SECOND_MS) ? HALF_SECOND_MS : 0;
+ }
+
+ public void advanceCounterInMs(int deltaMs) {
+ this.setCurrentTimeInMs(this.getCurrentTimeInMs() + deltaMs);
+ }
+
+ private void applyCounterState(Room room, boolean updateRoom) {
+ this.setExtradata(this.timeNow + "\t" + this.baseTime);
+
+ if (updateRoom && room != null) {
+ room.updateItem(this);
+ }
+
+ this.needsUpdate(true);
+ }
+
+ public void restartFromZero(Room room) {
+ boolean wasActive = this.isRunning || this.isPaused;
+
+ if (wasActive) {
+ this.endGame(room);
+ WiredManager.triggerGameEnds(room);
+ }
+
+ this.setCurrentTimeInMs(0);
+ this.applyCounterState(room, true);
+
+ this.startTimer(room);
+ }
+
+ public void stopCounter(Room room) {
+ boolean wasActive = this.isRunning || this.isPaused;
+
+ this.endGame(room);
+ this.applyCounterState(room, true);
+
+ if (wasActive) {
+ WiredManager.triggerGameEnds(room);
+ }
+ }
+
+ public void resetCounter(Room room) {
+ boolean wasActive = this.isRunning || this.isPaused;
+
+ this.endGame(room);
+ this.setCurrentTimeInMs(0);
+ this.applyCounterState(room, true);
+
+ if (wasActive) {
+ WiredManager.triggerGameEnds(room);
+ }
+ }
+
+ public void pauseCounter(Room room) {
+ if (!this.isRunning || this.isPaused) {
+ return;
+ }
+
+ this.pauseTimer(room);
+ this.applyCounterState(room, true);
+ }
+
+ public void resumeCounter(Room room) {
+ if (!this.isPaused) {
+ return;
+ }
+
+ this.resumeTimer(room);
+ this.applyCounterState(room, true);
+ }
+
+ public void adjustCounter(Room room, int operator, int minutes, int halfSecondSteps) {
+ int deltaMs = (Math.max(0, minutes) * 60000) + (Math.max(0, halfSecondSteps) * HALF_SECOND_MS);
+ int nextTimeMs = this.getCurrentTimeInMs();
+
+ switch (operator) {
+ case 0:
+ nextTimeMs += deltaMs;
+ break;
+ case 1:
+ nextTimeMs -= deltaMs;
+ break;
+ case 2:
+ default:
+ nextTimeMs = deltaMs;
+ break;
+ }
+
+ this.setCurrentTimeInMs(nextTimeMs);
+ this.applyCounterState(room, true);
+ }
+
+ public void resetOnRoomUnload(Room room) {
+ this.endGame(room);
+ this.setThreadActive(false);
+ this.setCurrentTimeInMs(0);
+ this.applyCounterState(null, false);
+ }
+}
diff --git a/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionActorDir.java b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionActorDir.java
new file mode 100644
index 00000000..8c0e79af
--- /dev/null
+++ b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionActorDir.java
@@ -0,0 +1,200 @@
+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.habbohotel.wired.core.WiredSourceUtil;
+import com.eu.habbo.messages.ServerMessage;
+
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.List;
+
+public class WiredConditionActorDir extends InteractionWiredCondition {
+ private static final int QUANTIFIER_ALL = 0;
+ private static final int QUANTIFIER_ANY = 1;
+ private static final int ALL_DIRECTIONS_MASK = createDirectionMask();
+
+ public static final WiredConditionType type = WiredConditionType.ACTOR_DIR;
+
+ private int directionMask = 0;
+ private int userSource = WiredSourceUtil.SOURCE_TRIGGER;
+ private int quantifier = QUANTIFIER_ALL;
+
+ public WiredConditionActorDir(ResultSet set, Item baseItem) throws SQLException {
+ super(set, baseItem);
+ }
+
+ public WiredConditionActorDir(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(3);
+ message.appendInt(this.directionMask);
+ 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.directionMask = (params.length > 0) ? this.normalizeDirectionMask(params[0]) : 0;
+ this.userSource = (params.length > 1) ? this.normalizeUserSource(params[1]) : WiredSourceUtil.SOURCE_TRIGGER;
+ this.quantifier = (params.length > 2) ? this.normalizeQuantifier(params[2]) : QUANTIFIER_ALL;
+
+ return true;
+ }
+
+ @Override
+ public boolean evaluate(WiredContext ctx) {
+ if (this.directionMask == 0) {
+ return false;
+ }
+
+ List targets = WiredSourceUtil.resolveUsers(ctx, this.userSource);
+ if (targets.isEmpty()) {
+ return false;
+ }
+
+ if (this.quantifier == QUANTIFIER_ANY) {
+ return targets.stream().anyMatch(this::matchesDirection);
+ }
+
+ return targets.stream().allMatch(this::matchesDirection);
+ }
+
+ @Deprecated
+ @Override
+ public boolean execute(RoomUnit roomUnit, Room room, Object[] stuff) {
+ return false;
+ }
+
+ @Override
+ public String getWiredData() {
+ return WiredManager.getGson().toJson(new JsonData(
+ this.directionMask,
+ this.userSource,
+ this.quantifier
+ ));
+ }
+
+ @Override
+ public void loadWiredData(ResultSet set, Room room) throws SQLException {
+ this.onPickUp();
+
+ 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.directionMask = this.normalizeDirectionMask(data.directionMask);
+ this.userSource = this.normalizeUserSource(data.userSource);
+ this.quantifier = this.normalizeQuantifier(data.quantifier);
+ return;
+ }
+
+ String[] parts = wiredData.split("\t");
+
+ try {
+ if (parts.length > 0) {
+ this.directionMask = this.normalizeDirectionMask(Integer.parseInt(parts[0]));
+ }
+ if (parts.length > 1) {
+ this.userSource = this.normalizeUserSource(Integer.parseInt(parts[1]));
+ }
+ if (parts.length > 2) {
+ this.quantifier = this.normalizeQuantifier(Integer.parseInt(parts[2]));
+ }
+ } catch (NumberFormatException ignored) {
+ this.onPickUp();
+ }
+ }
+
+ @Override
+ public void onPickUp() {
+ this.directionMask = 0;
+ this.userSource = WiredSourceUtil.SOURCE_TRIGGER;
+ this.quantifier = QUANTIFIER_ALL;
+ }
+
+ private boolean matchesDirection(RoomUnit roomUnit) {
+ if (roomUnit == null || roomUnit.getBodyRotation() == null) {
+ return false;
+ }
+
+ int direction = roomUnit.getBodyRotation().getValue();
+
+ return (this.directionMask & (1 << direction)) != 0;
+ }
+
+ private int normalizeDirectionMask(int value) {
+ return value & ALL_DIRECTIONS_MASK;
+ }
+
+ private 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;
+ }
+ }
+
+ private int normalizeQuantifier(int value) {
+ return (value == QUANTIFIER_ANY) ? QUANTIFIER_ANY : QUANTIFIER_ALL;
+ }
+
+ private static int createDirectionMask() {
+ int mask = 0;
+
+ for (int direction = 0; direction < 8; direction++) {
+ mask |= (1 << direction);
+ }
+
+ return mask;
+ }
+
+ static class JsonData {
+ int directionMask;
+ int userSource;
+ int quantifier;
+
+ public JsonData(int directionMask, int userSource, int quantifier) {
+ this.directionMask = directionMask;
+ this.userSource = userSource;
+ this.quantifier = quantifier;
+ }
+ }
+}
diff --git a/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionCounterTimeMatches.java b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionCounterTimeMatches.java
new file mode 100644
index 00000000..a28ea00b
--- /dev/null
+++ b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionCounterTimeMatches.java
@@ -0,0 +1,296 @@
+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.games.InteractionGameUpCounter;
+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.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.List;
+import java.util.stream.Collectors;
+
+public class WiredConditionCounterTimeMatches 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;
+ private static final int MAX_MINUTES = 99;
+ private static final int MAX_HALF_SECOND_STEPS = 119;
+
+ public static final WiredConditionType type = WiredConditionType.COUNTER_TIME_MATCHES;
+
+ private final THashSet items;
+ private int comparison = COMPARISON_EQUAL;
+ private int minutes = 0;
+ private int halfSecondSteps = 0;
+ private int furniSource = WiredSourceUtil.SOURCE_TRIGGER;
+ private int quantifier = QUANTIFIER_ALL;
+
+ public WiredConditionCounterTimeMatches(ResultSet set, Item baseItem) throws SQLException {
+ super(set, baseItem);
+ this.items = new THashSet<>();
+ }
+
+ public WiredConditionCounterTimeMatches(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 targets = WiredSourceUtil.resolveItems(ctx, this.furniSource, this.items);
+ if (targets.isEmpty()) {
+ return false;
+ }
+
+ int targetTimeInMs = this.getTargetTimeInMs();
+
+ if (this.quantifier == QUANTIFIER_ANY) {
+ for (HabboItem item : targets) {
+ if (!(item instanceof InteractionGameUpCounter)) {
+ continue;
+ }
+
+ if (this.matchesCounter((InteractionGameUpCounter) item, targetTimeInMs)) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ for (HabboItem item : targets) {
+ if (!(item instanceof InteractionGameUpCounter)) {
+ return false;
+ }
+
+ if (!this.matchesCounter((InteractionGameUpCounter) item, targetTimeInMs)) {
+ return false;
+ }
+ }
+
+ 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.comparison,
+ this.minutes,
+ this.halfSecondSteps,
+ 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.minutes = 0;
+ this.halfSecondSteps = 0;
+ this.furniSource = WiredSourceUtil.SOURCE_TRIGGER;
+ this.quantifier = QUANTIFIER_ALL;
+
+ String wiredData = set.getString("wired_data");
+ if (wiredData == null || wiredData.isEmpty() || !wiredData.startsWith("{")) {
+ return;
+ }
+
+ JsonData data = WiredManager.getGson().fromJson(wiredData, JsonData.class);
+ if (data == null) {
+ return;
+ }
+
+ this.comparison = this.normalizeComparison(data.comparison);
+ this.minutes = this.normalizeMinutes(data.minutes);
+ this.halfSecondSteps = this.normalizeHalfSecondSteps(data.halfSecondSteps);
+ this.furniSource = 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 instanceof InteractionGameUpCounter) {
+ this.items.add(item);
+ }
+ }
+ }
+
+ @Override
+ public void onPickUp() {
+ this.items.clear();
+ this.comparison = COMPARISON_EQUAL;
+ this.minutes = 0;
+ this.halfSecondSteps = 0;
+ 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("");
+ message.appendInt(5);
+ message.appendInt(this.comparison);
+ message.appendInt(this.minutes);
+ message.appendInt(this.halfSecondSteps);
+ 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.minutes = (params.length > 1) ? this.normalizeMinutes(params[1]) : 0;
+ this.halfSecondSteps = (params.length > 2) ? this.normalizeHalfSecondSteps(params[2]) : 0;
+ this.furniSource = (params.length > 3) ? params[3] : WiredSourceUtil.SOURCE_TRIGGER;
+ this.quantifier = (params.length > 4) ? this.normalizeQuantifier(params[4]) : QUANTIFIER_ALL;
+
+ this.items.clear();
+
+ if (this.furniSource != WiredSourceUtil.SOURCE_SELECTED) {
+ return true;
+ }
+
+ Room room = Emulator.getGameEnvironment().getRoomManager().getRoom(this.getRoomId());
+ if (room == null) {
+ return false;
+ }
+
+ int count = settings.getFurniIds().length;
+ if (count > Emulator.getConfig().getInt("hotel.wired.furni.selection.count")) {
+ return false;
+ }
+
+ for (int itemId : settings.getFurniIds()) {
+ HabboItem item = room.getHabboItem(itemId);
+ if (item instanceof InteractionGameUpCounter) {
+ this.items.add(item);
+ }
+ }
+
+ return true;
+ }
+
+ private void refresh(Room room) {
+ THashSet remove = new THashSet<>();
+
+ for (HabboItem item : this.items) {
+ HabboItem roomItem = room.getHabboItem(item.getId());
+ if (!(roomItem instanceof InteractionGameUpCounter)) {
+ remove.add(item);
+ }
+ }
+
+ for (HabboItem item : remove) {
+ this.items.remove(item);
+ }
+ }
+
+ private int getTargetTimeInMs() {
+ return (this.minutes * 60_000) + (this.halfSecondSteps * 500);
+ }
+
+ private boolean matchesCounter(InteractionGameUpCounter counter, int targetTimeInMs) {
+ int currentTimeInMs = counter.getCurrentTimeInMs();
+
+ switch (this.comparison) {
+ case COMPARISON_LESS:
+ return currentTimeInMs < targetTimeInMs;
+ case COMPARISON_GREATER:
+ return currentTimeInMs > targetTimeInMs;
+ default:
+ return currentTimeInMs == targetTimeInMs;
+ }
+ }
+
+ private int normalizeComparison(int value) {
+ if (value < COMPARISON_LESS || value > COMPARISON_GREATER) {
+ return COMPARISON_EQUAL;
+ }
+
+ return value;
+ }
+
+ private int normalizeMinutes(int value) {
+ return Math.max(0, Math.min(MAX_MINUTES, value));
+ }
+
+ private int normalizeHalfSecondSteps(int value) {
+ return Math.max(0, Math.min(MAX_HALF_SECOND_STEPS, value));
+ }
+
+ private int normalizeQuantifier(int value) {
+ return (value == QUANTIFIER_ANY) ? QUANTIFIER_ANY : QUANTIFIER_ALL;
+ }
+
+ static class JsonData {
+ int comparison;
+ int minutes;
+ int halfSecondSteps;
+ int furniSource;
+ int quantifier;
+ List itemIds;
+
+ public JsonData(int comparison, int minutes, int halfSecondSteps, int furniSource, int quantifier, List itemIds) {
+ this.comparison = comparison;
+ this.minutes = minutes;
+ this.halfSecondSteps = halfSecondSteps;
+ this.furniSource = furniSource;
+ this.quantifier = quantifier;
+ this.itemIds = itemIds;
+ }
+ }
+}
diff --git a/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionFurniHaveHabbo.java b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionFurniHaveHabbo.java
index 1863c07c..a12c1874 100644
--- a/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionFurniHaveHabbo.java
+++ b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionFurniHaveHabbo.java
@@ -27,6 +27,7 @@ import java.util.stream.Collectors;
public class WiredConditionFurniHaveHabbo extends InteractionWiredCondition {
public static final WiredConditionType type = WiredConditionType.FURNI_HAVE_HABBO;
protected THashSet items;
+ protected boolean all;
private int furniSource = WiredSourceUtil.SOURCE_TRIGGER;
public WiredConditionFurniHaveHabbo(ResultSet set, Item baseItem) throws SQLException {
@@ -42,6 +43,7 @@ public class WiredConditionFurniHaveHabbo extends InteractionWiredCondition {
@Override
public void onPickUp() {
this.items.clear();
+ this.all = false;
this.furniSource = WiredSourceUtil.SOURCE_TRIGGER;
}
@@ -62,15 +64,11 @@ public class WiredConditionFurniHaveHabbo extends InteractionWiredCondition {
Collection bots = room.getCurrentBots().valueCollection();
Collection pets = room.getCurrentPets().valueCollection();
- return targets.stream().filter(item -> item != null).allMatch(item -> {
- RoomTile baseTile = room.getLayout().getTile(item.getX(), item.getY());
- if (baseTile == null) return false;
-
- THashSet occupiedTiles = room.getLayout().getTilesAt(baseTile, item.getBaseItem().getWidth(), item.getBaseItem().getLength(), item.getRotation());
- return habbos.stream().anyMatch(character -> character.getRoomUnit() != null && occupiedTiles.contains(character.getRoomUnit().getCurrentLocation())) ||
- bots.stream().anyMatch(character -> character.getRoomUnit() != null && occupiedTiles.contains(character.getRoomUnit().getCurrentLocation())) ||
- pets.stream().anyMatch(character -> character.getRoomUnit() != null && occupiedTiles.contains(character.getRoomUnit().getCurrentLocation()));
- });
+ if (this.all) {
+ return targets.stream().filter(item -> item != null).allMatch(item -> this.hasAvatarOnItem(item, room, habbos, bots, pets));
+ }
+
+ return targets.stream().filter(item -> item != null).anyMatch(item -> this.hasAvatarOnItem(item, room, habbos, bots, pets));
}
@Deprecated
@@ -84,7 +82,8 @@ public class WiredConditionFurniHaveHabbo extends InteractionWiredCondition {
this.refresh();
return WiredManager.getGson().toJson(new JsonData(
this.items.stream().map(HabboItem::getId).collect(Collectors.toList()),
- this.furniSource
+ this.furniSource,
+ this.all
));
}
@@ -96,6 +95,7 @@ public class WiredConditionFurniHaveHabbo extends InteractionWiredCondition {
if (wiredData.startsWith("{")) {
JsonData data = WiredManager.getGson().fromJson(wiredData, JsonData.class);
this.furniSource = data.furniSource;
+ this.all = data.all;
for(int id : data.itemIds) {
HabboItem item = room.getHabboItem(id);
@@ -119,6 +119,7 @@ public class WiredConditionFurniHaveHabbo extends InteractionWiredCondition {
}
}
this.furniSource = this.items.isEmpty() ? WiredSourceUtil.SOURCE_TRIGGER : WiredSourceUtil.SOURCE_SELECTED;
+ this.all = false;
}
if (this.furniSource == WiredSourceUtil.SOURCE_TRIGGER && !this.items.isEmpty()) {
this.furniSource = WiredSourceUtil.SOURCE_SELECTED;
@@ -144,7 +145,8 @@ public class WiredConditionFurniHaveHabbo extends InteractionWiredCondition {
message.appendInt(this.getBaseItem().getSpriteId());
message.appendInt(this.getId());
message.appendString("");
- message.appendInt(1);
+ message.appendInt(2);
+ message.appendInt(this.all ? 1 : 0);
message.appendInt(this.furniSource);
message.appendInt(0);
message.appendInt(this.getType().code);
@@ -159,7 +161,8 @@ public class WiredConditionFurniHaveHabbo extends InteractionWiredCondition {
if (count > Emulator.getConfig().getInt("hotel.wired.furni.selection.count")) return false;
int[] params = settings.getIntParams();
- this.furniSource = (params.length > 0) ? params[0] : WiredSourceUtil.SOURCE_TRIGGER;
+ this.all = (params.length > 0) && (params[0] == 1);
+ this.furniSource = (params.length > 1) ? params[1] : ((params.length > 0 && params[0] > 1) ? params[0] : WiredSourceUtil.SOURCE_TRIGGER);
this.items.clear();
@@ -179,6 +182,18 @@ public class WiredConditionFurniHaveHabbo extends InteractionWiredCondition {
return true;
}
+ protected boolean hasAvatarOnItem(HabboItem item, Room room, Collection habbos, Collection bots, Collection pets) {
+ RoomTile baseTile = room.getLayout().getTile(item.getX(), item.getY());
+ if (baseTile == null) return false;
+
+ THashSet occupiedTiles = room.getLayout().getTilesAt(baseTile, item.getBaseItem().getWidth(), item.getBaseItem().getLength(), item.getRotation());
+ return occupiedTiles != null && (
+ habbos.stream().anyMatch(character -> character.getRoomUnit() != null && occupiedTiles.contains(character.getRoomUnit().getCurrentLocation())) ||
+ bots.stream().anyMatch(character -> character.getRoomUnit() != null && occupiedTiles.contains(character.getRoomUnit().getCurrentLocation())) ||
+ pets.stream().anyMatch(character -> character.getRoomUnit() != null && occupiedTiles.contains(character.getRoomUnit().getCurrentLocation()))
+ );
+ }
+
private void refresh() {
THashSet items = new THashSet<>();
@@ -200,10 +215,12 @@ public class WiredConditionFurniHaveHabbo extends InteractionWiredCondition {
static class JsonData {
List itemIds;
int furniSource;
+ boolean all;
- public JsonData(List itemIds, int furniSource) {
+ public JsonData(List itemIds, int furniSource, boolean all) {
this.itemIds = itemIds;
this.furniSource = furniSource;
+ this.all = all;
}
}
}
diff --git a/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionFurniTypeMatch.java b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionFurniTypeMatch.java
index 72552354..0b91d791 100644
--- a/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionFurniTypeMatch.java
+++ b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionFurniTypeMatch.java
@@ -8,22 +8,30 @@ 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.WiredManager;
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.sql.ResultSet;
import java.sql.SQLException;
+import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
public class WiredConditionFurniTypeMatch extends InteractionWiredCondition {
+ protected static final int SOURCE_SECONDARY_SELECTED = 101;
+ protected static final int QUANTIFIER_ALL = 0;
+ protected static final int QUANTIFIER_ANY = 1;
+
public static final WiredConditionType type = WiredConditionType.STUFF_IS;
- private THashSet items = new THashSet<>();
- private int furniSource = WiredSourceUtil.SOURCE_TRIGGER;
+ protected THashSet items = new THashSet<>();
+ protected THashSet secondaryItems = new THashSet<>();
+ protected int furniSource = WiredSourceUtil.SOURCE_TRIGGER;
+ protected int compareFurniSource = WiredSourceUtil.SOURCE_TRIGGER;
+ protected int quantifier = QUANTIFIER_ALL;
public WiredConditionFurniTypeMatch(ResultSet set, Item baseItem) throws SQLException {
super(set, baseItem);
@@ -36,19 +44,90 @@ public class WiredConditionFurniTypeMatch extends InteractionWiredCondition {
@Override
public void onPickUp() {
this.items.clear();
+ this.secondaryItems.clear();
this.furniSource = WiredSourceUtil.SOURCE_TRIGGER;
+ this.compareFurniSource = WiredSourceUtil.SOURCE_TRIGGER;
+ this.quantifier = QUANTIFIER_ALL;
}
@Override
public boolean evaluate(WiredContext ctx) {
+ if (this.quantifier == QUANTIFIER_ANY) {
+ return this.evaluateAnyMatches(ctx);
+ }
+
+ return this.evaluateAllMatches(ctx);
+ }
+
+ protected boolean evaluateAllMatches(WiredContext ctx) {
+ List matchTargets = this.resolveMatchTargets(ctx);
+ if (matchTargets.isEmpty()) {
+ return false;
+ }
+
+ THashSet compareTypeIds = this.resolveCompareTypeIds(ctx);
+ if (compareTypeIds.isEmpty()) {
+ return false;
+ }
+
+ for (HabboItem item : matchTargets) {
+ if (!this.matchesType(item, compareTypeIds)) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ protected boolean evaluateAnyMatches(WiredContext ctx) {
+ List matchTargets = this.resolveMatchTargets(ctx);
+ if (matchTargets.isEmpty()) {
+ return false;
+ }
+
+ THashSet compareTypeIds = this.resolveCompareTypeIds(ctx);
+ if (compareTypeIds.isEmpty()) {
+ return false;
+ }
+
+ for (HabboItem item : matchTargets) {
+ if (this.matchesType(item, compareTypeIds)) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ protected List resolveMatchTargets(WiredContext ctx) {
+ this.refresh();
+ return this.resolveConfiguredItems(ctx, this.furniSource);
+ }
+
+ protected THashSet resolveCompareTypeIds(WiredContext ctx) {
this.refresh();
- if(items.isEmpty())
- return false;
+ THashSet compareTypeIds = new THashSet<>();
- List targets = WiredSourceUtil.resolveItems(ctx, this.furniSource, this.items);
- if (targets.isEmpty()) return false;
- return targets.stream().anyMatch(this.items::contains);
+ for (HabboItem item : this.resolveConfiguredItems(ctx, this.compareFurniSource)) {
+ if (item != null && item.getBaseItem() != null) {
+ compareTypeIds.add(item.getBaseItem().getId());
+ }
+ }
+
+ return compareTypeIds;
+ }
+
+ protected boolean matchesType(HabboItem item, THashSet compareTypeIds) {
+ return item != null && item.getBaseItem() != null && compareTypeIds.contains(item.getBaseItem().getId());
+ }
+
+ protected List resolveConfiguredItems(WiredContext ctx, int sourceType) {
+ if (sourceType == SOURCE_SECONDARY_SELECTED) {
+ return new ArrayList<>(this.secondaryItems);
+ }
+
+ return WiredSourceUtil.resolveItems(ctx, sourceType, this.items);
}
@Deprecated
@@ -62,41 +141,53 @@ public class WiredConditionFurniTypeMatch extends InteractionWiredCondition {
this.refresh();
return WiredManager.getGson().toJson(new JsonData(
this.items.stream().map(HabboItem::getId).collect(Collectors.toList()),
- this.furniSource
+ this.secondaryItems.stream().map(HabboItem::getId).collect(Collectors.toList()),
+ this.furniSource,
+ this.compareFurniSource,
+ this.quantifier
));
}
@Override
public void loadWiredData(ResultSet set, Room room) throws SQLException {
- this.items.clear();
+ this.onPickUp();
+
String wiredData = set.getString("wired_data");
+ if (wiredData == null || wiredData.isEmpty()) {
+ return;
+ }
if (wiredData.startsWith("{")) {
JsonData data = WiredManager.getGson().fromJson(wiredData, JsonData.class);
- this.furniSource = data.furniSource;
-
- for(int id : data.itemIds) {
- HabboItem item = room.getHabboItem(id);
-
- if (item != null) {
- this.items.add(item);
- }
+ if (data == null) {
+ return;
}
- } else {
- String[] data = wiredData.split(";");
- for (String s : data) {
- HabboItem item = room.getHabboItem(Integer.parseInt(s));
+ List primaryIds = (data.primaryItemIds != null) ? data.primaryItemIds : new ArrayList<>();
+ List compareIds = (data.secondaryItemIds != null) ? data.secondaryItemIds : ((data.itemIds != null) ? data.itemIds : new ArrayList<>());
- if (item != null) {
- this.items.add(item);
- }
+ this.furniSource = this.normalizeFurniSource((data.furniSource != null) ? data.furniSource : WiredSourceUtil.SOURCE_TRIGGER);
+ this.compareFurniSource = this.normalizeFurniSource((data.compareFurniSource != null) ? data.compareFurniSource : (compareIds.isEmpty() ? WiredSourceUtil.SOURCE_TRIGGER : SOURCE_SECONDARY_SELECTED));
+ this.quantifier = this.normalizeQuantifier((data.quantifier != null) ? data.quantifier : QUANTIFIER_ANY);
+
+ this.loadItems(room, primaryIds, this.items);
+ this.loadItems(room, compareIds, this.secondaryItems);
+ return;
+ }
+
+ String[] data = wiredData.split(";");
+ List compareIds = new ArrayList<>();
+
+ for (String value : data) {
+ try {
+ compareIds.add(Integer.parseInt(value));
+ } catch (NumberFormatException ignored) {
}
- this.furniSource = this.items.isEmpty() ? WiredSourceUtil.SOURCE_TRIGGER : WiredSourceUtil.SOURCE_SELECTED;
- }
- if (this.furniSource == WiredSourceUtil.SOURCE_TRIGGER && !this.items.isEmpty()) {
- this.furniSource = WiredSourceUtil.SOURCE_SELECTED;
}
+
+ this.loadItems(room, compareIds, this.secondaryItems);
+ this.compareFurniSource = this.secondaryItems.isEmpty() ? WiredSourceUtil.SOURCE_TRIGGER : SOURCE_SECONDARY_SELECTED;
+ this.quantifier = QUANTIFIER_ANY;
}
@Override
@@ -112,14 +203,17 @@ public class WiredConditionFurniTypeMatch extends InteractionWiredCondition {
message.appendInt(WiredManager.MAXIMUM_FURNI_SELECTION);
message.appendInt(this.items.size());
- for (HabboItem item : this.items)
+ for (HabboItem item : this.items) {
message.appendInt(item.getId());
+ }
message.appendInt(this.getBaseItem().getSpriteId());
message.appendInt(this.getId());
- message.appendString("");
- message.appendInt(1);
+ message.appendString(this.serializeIds(this.secondaryItems));
+ message.appendInt(3);
message.appendInt(this.furniSource);
+ message.appendInt(this.compareFurniSource);
+ message.appendInt(this.quantifier);
message.appendInt(0);
message.appendInt(this.getType().code);
message.appendInt(0);
@@ -132,16 +226,51 @@ public class WiredConditionFurniTypeMatch extends InteractionWiredCondition {
if (count > Emulator.getConfig().getInt("hotel.wired.furni.selection.count")) return false;
int[] params = settings.getIntParams();
- this.furniSource = (params.length > 0) ? params[0] : WiredSourceUtil.SOURCE_TRIGGER;
+ String stringParam = (settings.getStringParam() != null) ? settings.getStringParam().trim() : "";
+ boolean legacyData = (params.length <= 1) && stringParam.isEmpty();
- this.items.clear();
+ this.onPickUp();
+
+ if (legacyData) {
+ this.furniSource = (params.length > 0) ? this.normalizeFurniSource(params[0]) : WiredSourceUtil.SOURCE_TRIGGER;
+ this.quantifier = QUANTIFIER_ANY;
+ } else {
+ this.furniSource = (params.length > 0) ? this.normalizeFurniSource(params[0]) : WiredSourceUtil.SOURCE_TRIGGER;
+ this.compareFurniSource = (params.length > 1) ? this.normalizeFurniSource(params[1]) : WiredSourceUtil.SOURCE_TRIGGER;
+ this.quantifier = (params.length > 2) ? this.normalizeQuantifier(params[2]) : QUANTIFIER_ALL;
+ }
+
+ Room room = Emulator.getGameEnvironment().getRoomManager().getRoom(this.getRoomId());
+ if (room == null) {
+ return false;
+ }
+
+ if (legacyData) {
+ for (int itemId : settings.getFurniIds()) {
+ HabboItem item = room.getHabboItem(itemId);
+ if (item != null) {
+ this.secondaryItems.add(item);
+ }
+ }
+
+ this.compareFurniSource = this.secondaryItems.isEmpty() ? WiredSourceUtil.SOURCE_TRIGGER : SOURCE_SECONDARY_SELECTED;
+ return true;
+ }
if (this.furniSource == WiredSourceUtil.SOURCE_SELECTED) {
- Room room = Emulator.getGameEnvironment().getRoomManager().getRoom(this.getRoomId());
+ for (int itemId : settings.getFurniIds()) {
+ HabboItem item = room.getHabboItem(itemId);
+ if (item != null) {
+ this.items.add(item);
+ }
+ }
+ }
- if (room != null) {
- for (int i = 0; i < count; i++) {
- this.items.add(room.getHabboItem(settings.getFurniIds()[i]));
+ if (this.compareFurniSource == SOURCE_SECONDARY_SELECTED) {
+ for (Integer itemId : this.parseIds(stringParam)) {
+ HabboItem item = room.getHabboItem(itemId);
+ if (item != null) {
+ this.secondaryItems.add(item);
}
}
}
@@ -149,31 +278,110 @@ public class WiredConditionFurniTypeMatch extends InteractionWiredCondition {
return true;
}
- private void refresh() {
- THashSet items = new THashSet<>();
+ protected int getQuantifier() {
+ return this.quantifier;
+ }
+
+ protected void refresh() {
+ this.refreshSelection(this.items);
+ this.refreshSelection(this.secondaryItems);
+ }
+
+ private void refreshSelection(THashSet selection) {
+ THashSet remove = new THashSet<>();
Room room = Emulator.getGameEnvironment().getRoomManager().getRoom(this.getRoomId());
if (room == null) {
- items.addAll(this.items);
+ remove.addAll(selection);
} else {
- for (HabboItem item : this.items) {
- if (room.getHabboItem(item.getId()) == null)
- items.add(item);
+ for (HabboItem item : selection) {
+ if (room.getHabboItem(item.getId()) == null) {
+ remove.add(item);
+ }
}
}
- for (HabboItem item : items) {
- this.items.remove(item);
+ for (HabboItem item : remove) {
+ selection.remove(item);
}
}
+ private void loadItems(Room room, List itemIds, THashSet target) {
+ if (itemIds == null) {
+ return;
+ }
+
+ for (Integer id : itemIds) {
+ if (id == null) {
+ continue;
+ }
+
+ HabboItem item = room.getHabboItem(id);
+ if (item != null) {
+ target.add(item);
+ }
+ }
+ }
+
+ private String serializeIds(THashSet source) {
+ return source.stream()
+ .map(HabboItem::getId)
+ .filter(id -> id > 0)
+ .map(String::valueOf)
+ .collect(Collectors.joining(";"));
+ }
+
+ private List parseIds(String value) {
+ List result = new ArrayList<>();
+ if (value == null || value.isEmpty()) {
+ return result;
+ }
+
+ for (String part : value.split("[;,\\t]")) {
+ if (part == null || part.trim().isEmpty()) {
+ continue;
+ }
+
+ try {
+ result.add(Integer.parseInt(part.trim()));
+ } catch (NumberFormatException ignored) {
+ }
+ }
+
+ return result;
+ }
+
+ protected int normalizeFurniSource(int value) {
+ switch (value) {
+ case WiredSourceUtil.SOURCE_TRIGGER:
+ case WiredSourceUtil.SOURCE_SELECTED:
+ case SOURCE_SECONDARY_SELECTED:
+ case WiredSourceUtil.SOURCE_SELECTOR:
+ case WiredSourceUtil.SOURCE_SIGNAL:
+ return value;
+ default:
+ return WiredSourceUtil.SOURCE_TRIGGER;
+ }
+ }
+
+ protected int normalizeQuantifier(int value) {
+ return (value == QUANTIFIER_ANY) ? QUANTIFIER_ANY : QUANTIFIER_ALL;
+ }
+
static class JsonData {
+ List primaryItemIds;
+ List secondaryItemIds;
List itemIds;
- int furniSource;
+ Integer furniSource;
+ Integer compareFurniSource;
+ Integer quantifier;
- public JsonData(List itemIds, int furniSource) {
- this.itemIds = itemIds;
+ public JsonData(List primaryItemIds, List secondaryItemIds, int furniSource, int compareFurniSource, int quantifier) {
+ this.primaryItemIds = primaryItemIds;
+ this.secondaryItemIds = secondaryItemIds;
this.furniSource = furniSource;
+ this.compareFurniSource = compareFurniSource;
+ this.quantifier = quantifier;
}
}
}
diff --git a/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionGroupMember.java b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionGroupMember.java
index aa9631b5..d442add5 100644
--- a/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionGroupMember.java
+++ b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionGroupMember.java
@@ -8,6 +8,7 @@ import com.eu.habbo.habbohotel.rooms.RoomUnit;
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;
@@ -16,8 +17,16 @@ import java.sql.SQLException;
import java.util.List;
public class WiredConditionGroupMember extends InteractionWiredCondition {
+ private static final int GROUP_CURRENT_ROOM = 0;
+ private static final int GROUP_SELECTED = 1;
+ protected static final int QUANTIFIER_ALL = 0;
+ protected static final int QUANTIFIER_ANY = 1;
+
public static final WiredConditionType type = WiredConditionType.ACTOR_IN_GROUP;
private int userSource = WiredSourceUtil.SOURCE_TRIGGER;
+ private int groupType = GROUP_CURRENT_ROOM;
+ private int selectedGroupId = 0;
+ private int quantifier = QUANTIFIER_ALL;
public WiredConditionGroupMember(ResultSet set, Item baseItem) throws SQLException {
super(set, baseItem);
@@ -30,19 +39,32 @@ public class WiredConditionGroupMember extends InteractionWiredCondition {
@Override
public boolean evaluate(WiredContext ctx) {
Room room = ctx.room();
- if (room.getGuildId() == 0)
+ int targetGroupId = this.resolveTargetGroupId(room);
+ if (targetGroupId == 0)
return false;
List targets = WiredSourceUtil.resolveUsers(ctx, this.userSource);
if (targets.isEmpty()) return false;
+ if (this.quantifier == QUANTIFIER_ANY) {
+ for (RoomUnit roomUnit : targets) {
+ Habbo habbo = room.getHabbo(roomUnit);
+ if (habbo != null && habbo.getHabboStats().hasGuild(targetGroupId)) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
for (RoomUnit roomUnit : targets) {
Habbo habbo = room.getHabbo(roomUnit);
- if (habbo != null && habbo.getHabboStats().hasGuild(room.getGuildId())) {
- return true;
+ if (habbo == null || !habbo.getHabboStats().hasGuild(targetGroupId)) {
+ return false;
}
}
- return false;
+
+ return true;
}
@Deprecated
@@ -53,26 +75,45 @@ public class WiredConditionGroupMember extends InteractionWiredCondition {
@Override
public String getWiredData() {
- return String.valueOf(this.userSource);
+ return WiredManager.getGson().toJson(new JsonData(
+ this.userSource,
+ this.groupType,
+ this.selectedGroupId,
+ this.quantifier
+ ));
}
@Override
public void loadWiredData(ResultSet set, Room room) throws SQLException {
+ this.resetSettings();
+
String wiredData = set.getString("wired_data");
- if (wiredData != null && !wiredData.isEmpty()) {
- try {
- this.userSource = Integer.parseInt(wiredData);
- } catch (NumberFormatException ignored) {
- this.userSource = WiredSourceUtil.SOURCE_TRIGGER;
+ if (wiredData == null || wiredData.isEmpty()) {
+ return;
+ }
+
+ try {
+ if (wiredData.startsWith("{")) {
+ JsonData data = WiredManager.getGson().fromJson(wiredData, JsonData.class);
+ if (data == null) {
+ return;
+ }
+
+ this.userSource = this.normalizeUserSource(data.userSource);
+ this.groupType = this.normalizeGroupType(data.groupType);
+ this.selectedGroupId = this.normalizeSelectedGroupId(data.selectedGroupId);
+ this.quantifier = this.normalizeQuantifier(data.quantifier);
+ return;
}
- } else {
- this.userSource = WiredSourceUtil.SOURCE_TRIGGER;
+ this.userSource = this.normalizeUserSource(Integer.parseInt(wiredData));
+ } catch (Exception ignored) {
+ this.resetSettings();
}
}
@Override
public void onPickUp() {
- this.userSource = WiredSourceUtil.SOURCE_TRIGGER;
+ this.resetSettings();
}
@Override
@@ -88,8 +129,11 @@ public class WiredConditionGroupMember extends InteractionWiredCondition {
message.appendInt(this.getBaseItem().getSpriteId());
message.appendInt(this.getId());
message.appendString("");
- message.appendInt(1);
+ message.appendInt(4);
message.appendInt(this.userSource);
+ message.appendInt(this.groupType);
+ message.appendInt(this.selectedGroupId);
+ message.appendInt(this.quantifier);
message.appendInt(0);
message.appendInt(this.getType().code);
message.appendInt(0);
@@ -99,7 +143,70 @@ public class WiredConditionGroupMember extends InteractionWiredCondition {
@Override
public boolean saveData(WiredSettings settings) {
int[] params = settings.getIntParams();
- this.userSource = (params.length > 0) ? params[0] : WiredSourceUtil.SOURCE_TRIGGER;
+ this.userSource = (params.length > 0) ? this.normalizeUserSource(params[0]) : WiredSourceUtil.SOURCE_TRIGGER;
+ this.groupType = (params.length > 1) ? this.normalizeGroupType(params[1]) : GROUP_CURRENT_ROOM;
+ this.selectedGroupId = (params.length > 2) ? this.normalizeSelectedGroupId(params[2]) : 0;
+ this.quantifier = (params.length > 3) ? this.normalizeQuantifier(params[3]) : QUANTIFIER_ALL;
return true;
}
+
+ private void resetSettings() {
+ this.userSource = WiredSourceUtil.SOURCE_TRIGGER;
+ this.groupType = GROUP_CURRENT_ROOM;
+ this.selectedGroupId = 0;
+ this.quantifier = QUANTIFIER_ALL;
+ }
+
+ private int resolveTargetGroupId(Room room) {
+ if (room == null) {
+ return 0;
+ }
+
+ if (this.groupType == GROUP_SELECTED) {
+ return this.selectedGroupId;
+ }
+
+ return room.getGuildId();
+ }
+
+ private int normalizeUserSource(int value) {
+ switch (value) {
+ case WiredSourceUtil.SOURCE_TRIGGER:
+ case WiredSourceUtil.SOURCE_SELECTOR:
+ case WiredSourceUtil.SOURCE_SIGNAL:
+ return value;
+ default:
+ return WiredSourceUtil.SOURCE_TRIGGER;
+ }
+ }
+
+ private int normalizeGroupType(int value) {
+ return (value == GROUP_SELECTED) ? GROUP_SELECTED : GROUP_CURRENT_ROOM;
+ }
+
+ private int normalizeSelectedGroupId(int value) {
+ return Math.max(0, value);
+ }
+
+ protected int getQuantifier() {
+ return this.quantifier;
+ }
+
+ protected int normalizeQuantifier(int value) {
+ return (value == QUANTIFIER_ANY) ? QUANTIFIER_ANY : QUANTIFIER_ALL;
+ }
+
+ static class JsonData {
+ int userSource;
+ int groupType;
+ int selectedGroupId;
+ int quantifier;
+
+ public JsonData(int userSource, int groupType, int selectedGroupId, int quantifier) {
+ this.userSource = userSource;
+ this.groupType = groupType;
+ this.selectedGroupId = selectedGroupId;
+ this.quantifier = quantifier;
+ }
+ }
}
diff --git a/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionHabboHasEffect.java b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionHabboHasEffect.java
index a184beaf..2075513d 100644
--- a/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionHabboHasEffect.java
+++ b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionHabboHasEffect.java
@@ -16,10 +16,14 @@ import java.sql.SQLException;
import java.util.List;
public class WiredConditionHabboHasEffect extends InteractionWiredCondition {
+ protected static final int QUANTIFIER_ALL = 0;
+ protected static final int QUANTIFIER_ANY = 1;
+
public static final WiredConditionType type = WiredConditionType.ACTOR_WEARS_EFFECT;
protected int effectId = 0;
- private int userSource = WiredSourceUtil.SOURCE_TRIGGER;
+ protected int userSource = WiredSourceUtil.SOURCE_TRIGGER;
+ protected int quantifier = QUANTIFIER_ANY;
public WiredConditionHabboHasEffect(ResultSet set, Item baseItem) throws SQLException {
super(set, baseItem);
@@ -33,14 +37,38 @@ public class WiredConditionHabboHasEffect extends InteractionWiredCondition {
public boolean evaluate(WiredContext ctx) {
List targets = WiredSourceUtil.resolveUsers(ctx, this.userSource);
if (targets.isEmpty()) return false;
+
+ if (this.quantifier == QUANTIFIER_ALL) {
+ return this.matchesAllTargets(targets);
+ }
+
+ return this.matchesAnyTarget(targets);
+ }
+
+ protected boolean matchesAllTargets(List targets) {
for (RoomUnit roomUnit : targets) {
- if (roomUnit != null && roomUnit.getEffectId() == this.effectId) {
+ if (!this.matchesEffect(roomUnit)) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ protected boolean matchesAnyTarget(List targets) {
+ for (RoomUnit roomUnit : targets) {
+ if (this.matchesEffect(roomUnit)) {
return true;
}
}
+
return false;
}
+ protected boolean matchesEffect(RoomUnit roomUnit) {
+ return roomUnit != null && roomUnit.getEffectId() == this.effectId;
+ }
+
@Deprecated
@Override
public boolean execute(RoomUnit roomUnit, Room room, Object[] stuff) {
@@ -51,7 +79,8 @@ public class WiredConditionHabboHasEffect extends InteractionWiredCondition {
public String getWiredData() {
return WiredManager.getGson().toJson(new JsonData(
this.effectId,
- this.userSource
+ this.userSource,
+ this.quantifier
));
}
@@ -63,9 +92,11 @@ public class WiredConditionHabboHasEffect extends InteractionWiredCondition {
JsonData data = WiredManager.getGson().fromJson(wiredData, JsonData.class);
this.effectId = data.effectId;
this.userSource = data.userSource;
+ this.quantifier = this.normalizeQuantifier(data.quantifier, QUANTIFIER_ANY);
} else {
this.effectId = Integer.parseInt(wiredData);
this.userSource = WiredSourceUtil.SOURCE_TRIGGER;
+ this.quantifier = QUANTIFIER_ANY;
}
}
@@ -73,6 +104,7 @@ public class WiredConditionHabboHasEffect extends InteractionWiredCondition {
public void onPickUp() {
this.effectId = 0;
this.userSource = WiredSourceUtil.SOURCE_TRIGGER;
+ this.quantifier = QUANTIFIER_ANY;
}
@Override
@@ -88,9 +120,10 @@ public class WiredConditionHabboHasEffect extends InteractionWiredCondition {
message.appendInt(this.getBaseItem().getSpriteId());
message.appendInt(this.getId());
message.appendString("");
- message.appendInt(2);
+ message.appendInt(3);
message.appendInt(this.effectId);
message.appendInt(this.userSource);
+ message.appendInt(this.quantifier);
message.appendInt(0);
message.appendInt(this.getType().code);
message.appendInt(0);
@@ -100,20 +133,35 @@ public class WiredConditionHabboHasEffect extends InteractionWiredCondition {
@Override
public boolean saveData(WiredSettings settings) {
if(settings.getIntParams().length < 1) return false;
- this.effectId = settings.getIntParams()[0];
int[] params = settings.getIntParams();
+ this.effectId = params[0];
this.userSource = (params.length > 1) ? params[1] : WiredSourceUtil.SOURCE_TRIGGER;
+ this.quantifier = (params.length > 2) ? this.normalizeQuantifier(params[2], QUANTIFIER_ANY) : QUANTIFIER_ANY;
return true;
}
+ protected int getQuantifier() {
+ return this.quantifier;
+ }
+
+ protected int normalizeQuantifier(Integer value, int fallback) {
+ if (value == null) {
+ return fallback;
+ }
+
+ return (value == QUANTIFIER_ANY) ? QUANTIFIER_ANY : QUANTIFIER_ALL;
+ }
+
static class JsonData {
int effectId;
int userSource;
+ Integer quantifier;
- public JsonData(int effectId, int userSource) {
+ public JsonData(int effectId, int userSource, int quantifier) {
this.effectId = effectId;
this.userSource = userSource;
+ this.quantifier = quantifier;
}
}
}
diff --git a/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionHabboHasHandItem.java b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionHabboHasHandItem.java
index 64aade52..d949e4bd 100644
--- a/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionHabboHasHandItem.java
+++ b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionHabboHasHandItem.java
@@ -19,11 +19,14 @@ import java.util.List;
public class WiredConditionHabboHasHandItem extends InteractionWiredCondition {
private static final Logger LOGGER = LoggerFactory.getLogger(WiredConditionHabboHasHandItem.class);
+ protected static final int QUANTIFIER_ALL = 0;
+ protected static final int QUANTIFIER_ANY = 1;
public static final WiredConditionType type = WiredConditionType.ACTOR_HAS_HANDITEM;
private int handItem;
private int userSource = WiredSourceUtil.SOURCE_TRIGGER;
+ private int quantifier = QUANTIFIER_ALL;
public WiredConditionHabboHasHandItem(ResultSet set, Item baseItem) throws SQLException {
super(set, baseItem);
@@ -46,9 +49,10 @@ public class WiredConditionHabboHasHandItem extends InteractionWiredCondition {
message.appendInt(this.getBaseItem().getSpriteId());
message.appendInt(this.getId());
message.appendString("");
- message.appendInt(2);
+ message.appendInt(3);
message.appendInt(this.handItem);
message.appendInt(this.userSource);
+ message.appendInt(this.quantifier);
message.appendInt(0);
message.appendInt(this.getType().code);
message.appendInt(0);
@@ -58,9 +62,10 @@ public class WiredConditionHabboHasHandItem extends InteractionWiredCondition {
@Override
public boolean saveData(WiredSettings settings) {
if(settings.getIntParams().length < 1) return false;
- this.handItem = settings.getIntParams()[0];
+ this.handItem = this.normalizeHandItem(settings.getIntParams()[0]);
int[] params = settings.getIntParams();
this.userSource = (params.length > 1) ? params[1] : WiredSourceUtil.SOURCE_TRIGGER;
+ this.quantifier = (params.length > 2) ? this.normalizeQuantifier(params[2]) : QUANTIFIER_ALL;
return true;
}
@@ -69,12 +74,12 @@ public class WiredConditionHabboHasHandItem extends InteractionWiredCondition {
public boolean evaluate(WiredContext ctx) {
List targets = WiredSourceUtil.resolveUsers(ctx, this.userSource);
if (targets.isEmpty()) return false;
- for (RoomUnit roomUnit : targets) {
- if (roomUnit != null && roomUnit.getHandItem() == this.handItem) {
- return true;
- }
+
+ if (this.quantifier == QUANTIFIER_ANY) {
+ return this.matchesAnyTarget(targets);
}
- return false;
+
+ return this.matchesAllTargets(targets);
}
@Deprecated
@@ -87,7 +92,8 @@ public class WiredConditionHabboHasHandItem extends InteractionWiredCondition {
public String getWiredData() {
return WiredManager.getGson().toJson(new JsonData(
this.handItem,
- this.userSource
+ this.userSource,
+ this.quantifier
));
}
@@ -98,11 +104,13 @@ public class WiredConditionHabboHasHandItem extends InteractionWiredCondition {
if (wiredData.startsWith("{")) {
JsonData data = WiredManager.getGson().fromJson(wiredData, JsonData.class);
- this.handItem = data.handItemId;
+ this.handItem = this.normalizeHandItem(data.handItemId);
this.userSource = data.userSource;
+ this.quantifier = this.normalizeQuantifier(data.quantifier);
} else {
- this.handItem = Integer.parseInt(wiredData);
+ this.handItem = this.normalizeHandItem(Integer.parseInt(wiredData));
this.userSource = WiredSourceUtil.SOURCE_TRIGGER;
+ this.quantifier = QUANTIFIER_ALL;
}
} catch (Exception e) {
LOGGER.error("Caught exception", e);
@@ -113,6 +121,7 @@ public class WiredConditionHabboHasHandItem extends InteractionWiredCondition {
public void onPickUp() {
this.handItem = 0;
this.userSource = WiredSourceUtil.SOURCE_TRIGGER;
+ this.quantifier = QUANTIFIER_ALL;
}
protected int getHandItem() {
@@ -123,13 +132,47 @@ public class WiredConditionHabboHasHandItem extends InteractionWiredCondition {
return this.userSource;
}
+ protected int getQuantifier() {
+ return this.quantifier;
+ }
+
+ protected boolean matchesAnyTarget(List targets) {
+ for (RoomUnit roomUnit : targets) {
+ if (roomUnit != null && roomUnit.getHandItem() == this.handItem) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ protected boolean matchesAllTargets(List targets) {
+ for (RoomUnit roomUnit : targets) {
+ if (roomUnit == null || roomUnit.getHandItem() != this.handItem) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ protected int normalizeHandItem(int value) {
+ return Math.max(0, value);
+ }
+
+ protected int normalizeQuantifier(int value) {
+ return (value == QUANTIFIER_ANY) ? QUANTIFIER_ANY : QUANTIFIER_ALL;
+ }
+
static class JsonData {
int handItemId;
int userSource;
+ int quantifier;
- public JsonData(int handItemId, int userSource) {
+ public JsonData(int handItemId, int userSource, int quantifier) {
this.handItemId = handItemId;
this.userSource = userSource;
+ this.quantifier = quantifier;
}
}
}
diff --git a/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionHabboWearsBadge.java b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionHabboWearsBadge.java
index 844ef89c..83c85a8f 100644
--- a/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionHabboWearsBadge.java
+++ b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionHabboWearsBadge.java
@@ -18,10 +18,14 @@ import java.sql.SQLException;
import java.util.List;
public class WiredConditionHabboWearsBadge extends InteractionWiredCondition {
+ protected static final int QUANTIFIER_ALL = 0;
+ protected static final int QUANTIFIER_ANY = 1;
+
public static final WiredConditionType type = WiredConditionType.ACTOR_WEARS_BADGE;
protected String badge = "";
- private int userSource = WiredSourceUtil.SOURCE_TRIGGER;
+ protected int userSource = WiredSourceUtil.SOURCE_TRIGGER;
+ protected int quantifier = QUANTIFIER_ANY;
public WiredConditionHabboWearsBadge(ResultSet set, Item baseItem) throws SQLException {
super(set, baseItem);
@@ -37,18 +41,47 @@ public class WiredConditionHabboWearsBadge extends InteractionWiredCondition {
List targets = WiredSourceUtil.resolveUsers(ctx, this.userSource);
if (targets.isEmpty()) return false;
+ if (this.quantifier == QUANTIFIER_ALL) {
+ return this.matchesAllTargets(room, targets);
+ }
+
+ return this.matchesAnyTarget(room, targets);
+ }
+
+ protected boolean matchesAllTargets(Room room, List targets) {
for (RoomUnit roomUnit : targets) {
- Habbo habbo = room.getHabbo(roomUnit);
- if (habbo != null) {
- synchronized (habbo.getInventory().getBadgesComponent().getWearingBadges()) {
- for (HabboBadge badge : habbo.getInventory().getBadgesComponent().getWearingBadges()) {
- if (badge.getCode().equalsIgnoreCase(this.badge)) {
- return true;
- }
- }
+ if (!this.matchesBadge(room, roomUnit)) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ protected boolean matchesAnyTarget(Room room, List targets) {
+ for (RoomUnit roomUnit : targets) {
+ if (this.matchesBadge(room, roomUnit)) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ protected boolean matchesBadge(Room room, RoomUnit roomUnit) {
+ Habbo habbo = room.getHabbo(roomUnit);
+ if (habbo == null) {
+ return false;
+ }
+
+ synchronized (habbo.getInventory().getBadgesComponent().getWearingBadges()) {
+ for (HabboBadge badge : habbo.getInventory().getBadgesComponent().getWearingBadges()) {
+ if (badge.getCode().equalsIgnoreCase(this.badge)) {
+ return true;
}
}
}
+
return false;
}
@@ -62,7 +95,8 @@ public class WiredConditionHabboWearsBadge extends InteractionWiredCondition {
public String getWiredData() {
return WiredManager.getGson().toJson(new JsonData(
this.badge,
- this.userSource
+ this.userSource,
+ this.quantifier
));
}
@@ -74,9 +108,11 @@ public class WiredConditionHabboWearsBadge extends InteractionWiredCondition {
JsonData data = WiredManager.getGson().fromJson(wiredData, JsonData.class);
this.badge = data.badge;
this.userSource = data.userSource;
+ this.quantifier = this.normalizeQuantifier(data.quantifier, QUANTIFIER_ANY);
} else {
this.badge = wiredData;
this.userSource = WiredSourceUtil.SOURCE_TRIGGER;
+ this.quantifier = QUANTIFIER_ANY;
}
}
@@ -84,6 +120,7 @@ public class WiredConditionHabboWearsBadge extends InteractionWiredCondition {
public void onPickUp() {
this.badge = "";
this.userSource = WiredSourceUtil.SOURCE_TRIGGER;
+ this.quantifier = QUANTIFIER_ANY;
}
@Override
@@ -99,8 +136,9 @@ public class WiredConditionHabboWearsBadge extends InteractionWiredCondition {
message.appendInt(this.getBaseItem().getSpriteId());
message.appendInt(this.getId());
message.appendString(this.badge);
- message.appendInt(1);
+ message.appendInt(2);
message.appendInt(this.userSource);
+ message.appendInt(this.quantifier);
message.appendInt(0);
message.appendInt(this.getType().code);
message.appendInt(0);
@@ -112,17 +150,32 @@ public class WiredConditionHabboWearsBadge extends InteractionWiredCondition {
this.badge = settings.getStringParam();
int[] params = settings.getIntParams();
this.userSource = (params.length > 0) ? params[0] : WiredSourceUtil.SOURCE_TRIGGER;
+ this.quantifier = (params.length > 1) ? this.normalizeQuantifier(params[1], QUANTIFIER_ANY) : QUANTIFIER_ANY;
return true;
}
+ protected int getQuantifier() {
+ return this.quantifier;
+ }
+
+ protected int normalizeQuantifier(Integer value, int fallback) {
+ if (value == null) {
+ return fallback;
+ }
+
+ return (value == QUANTIFIER_ANY) ? QUANTIFIER_ANY : QUANTIFIER_ALL;
+ }
+
static class JsonData {
String badge;
int userSource;
+ Integer quantifier;
- public JsonData(String badge, int userSource) {
+ public JsonData(String badge, int userSource, int quantifier) {
this.badge = badge;
this.userSource = userSource;
+ this.quantifier = quantifier;
}
}
}
diff --git a/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionMatchStatePosition.java b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionMatchStatePosition.java
index 7966d563..ddc0477e 100644
--- a/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionMatchStatePosition.java
+++ b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionMatchStatePosition.java
@@ -20,8 +20,12 @@ import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
+import java.math.BigDecimal;
public class WiredConditionMatchStatePosition extends InteractionWiredCondition implements InteractionWiredMatchFurniSettings {
+ protected static final int QUANTIFIER_ALL = 0;
+ protected static final int QUANTIFIER_ANY = 1;
+
public static final WiredConditionType type = WiredConditionType.MATCH_SSHOT;
private THashSet settings;
@@ -29,7 +33,9 @@ public class WiredConditionMatchStatePosition extends InteractionWiredCondition
private boolean state;
private boolean position;
private boolean direction;
+ private boolean altitude;
private int furniSource = WiredSourceUtil.SOURCE_TRIGGER;
+ private int quantifier = QUANTIFIER_ALL;
public WiredConditionMatchStatePosition(ResultSet set, Item baseItem) throws SQLException {
super(set, baseItem);
@@ -60,11 +66,13 @@ public class WiredConditionMatchStatePosition extends InteractionWiredCondition
message.appendInt(this.getBaseItem().getSpriteId());
message.appendInt(this.getId());
message.appendString("");
- message.appendInt(4);
+ message.appendInt(6);
message.appendInt(this.state ? 1 : 0);
message.appendInt(this.direction ? 1 : 0);
message.appendInt(this.position ? 1 : 0);
+ message.appendInt(this.altitude ? 1 : 0);
message.appendInt(this.furniSource);
+ message.appendInt(this.quantifier);
message.appendInt(0);
message.appendInt(this.getType().code);
message.appendInt(0);
@@ -78,7 +86,9 @@ public class WiredConditionMatchStatePosition extends InteractionWiredCondition
this.state = params[0] == 1;
this.direction = params[1] == 1;
this.position = params[2] == 1;
- this.furniSource = (params.length > 3) ? params[3] : WiredSourceUtil.SOURCE_TRIGGER;
+ this.altitude = (params.length > 3) && (params[3] == 1);
+ this.furniSource = (params.length > 4) ? params[4] : ((params.length > 3 && params[3] > 1) ? params[3] : WiredSourceUtil.SOURCE_TRIGGER);
+ this.quantifier = (params.length > 5) ? this.normalizeQuantifier(params[5]) : QUANTIFIER_ALL;
Room room = Emulator.getGameEnvironment().getRoomManager().getRoom(this.getRoomId());
@@ -95,7 +105,7 @@ public class WiredConditionMatchStatePosition extends InteractionWiredCondition
HabboItem item = room.getHabboItem(itemId);
if (item != null)
- this.settings.add(new WiredMatchFurniSetting(item.getId(), item.getExtradata(), item.getRotation(), item.getX(), item.getY()));
+ this.settings.add(new WiredMatchFurniSetting(item.getId(), item.getExtradata(), item.getRotation(), item.getX(), item.getY(), item.getZ()));
}
return true;
@@ -103,12 +113,21 @@ public class WiredConditionMatchStatePosition extends InteractionWiredCondition
@Override
public boolean evaluate(WiredContext ctx) {
- Room room = ctx.room();
this.refresh();
if (this.settings.isEmpty())
return true;
+ if (this.quantifier == QUANTIFIER_ANY) {
+ return this.evaluateAnyTargetMatches(ctx);
+ }
+
+ return this.evaluateAllTargetsMatch(ctx);
+ }
+
+ protected boolean evaluateAllTargetsMatch(WiredContext ctx) {
+ Room room = ctx.room();
+
if (this.furniSource != WiredSourceUtil.SOURCE_SELECTED) {
List targets = WiredSourceUtil.resolveItems(ctx, this.furniSource, null);
if (targets.isEmpty()) return false;
@@ -139,6 +158,41 @@ public class WiredConditionMatchStatePosition extends InteractionWiredCondition
return true;
}
+ protected boolean evaluateAnyTargetMatches(WiredContext ctx) {
+ Room room = ctx.room();
+
+ if (this.furniSource != WiredSourceUtil.SOURCE_SELECTED) {
+ List targets = WiredSourceUtil.resolveItems(ctx, this.furniSource, null);
+ if (targets.isEmpty()) return false;
+
+ for (HabboItem item : targets) {
+ if (item == null) continue;
+
+ WiredMatchFurniSetting setting = this.resolveSettingForTarget(room, item);
+ if (setting != null && this.matchesSetting(item, setting)) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ for (WiredMatchFurniSetting setting : this.settings) {
+ HabboItem item = room.getHabboItem(setting.item_id);
+ if (item == null) continue;
+
+ if (this.matchesSetting(item, setting)) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ protected int getQuantifier() {
+ return this.quantifier;
+ }
+
private WiredMatchFurniSetting resolveSettingForTarget(Room room, HabboItem target) {
WiredMatchFurniSetting fallback = null;
@@ -166,6 +220,9 @@ public class WiredConditionMatchStatePosition extends InteractionWiredCondition
if (this.position && !(setting.x == item.getX() && setting.y == item.getY()))
return false;
+ if (this.altitude && BigDecimal.valueOf(item.getZ()).compareTo(BigDecimal.valueOf(setting.z)) != 0)
+ return false;
+
return !this.direction || setting.rotation == item.getRotation();
}
@@ -181,8 +238,10 @@ public class WiredConditionMatchStatePosition extends InteractionWiredCondition
this.state,
this.position,
this.direction,
+ this.altitude,
new ArrayList<>(this.settings),
- this.furniSource
+ this.furniSource,
+ this.quantifier
));
}
@@ -195,8 +254,12 @@ public class WiredConditionMatchStatePosition extends InteractionWiredCondition
this.state = data.state;
this.position = data.position;
this.direction = data.direction;
- this.settings.addAll(data.settings);
+ this.altitude = data.altitude;
+ if (data.settings != null) {
+ this.settings.addAll(data.settings);
+ }
this.furniSource = data.furniSource;
+ this.quantifier = this.normalizeQuantifier(data.quantifier);
} else {
String[] data = wiredData.split(":");
@@ -207,14 +270,18 @@ public class WiredConditionMatchStatePosition extends InteractionWiredCondition
for (int i = 0; i < itemCount; i++) {
String[] stuff = items[i].split("-");
- if (stuff.length >= 5)
+ if (stuff.length >= 6)
+ this.settings.add(new WiredMatchFurniSetting(Integer.parseInt(stuff[0]), stuff[1], Integer.parseInt(stuff[2]), Integer.parseInt(stuff[3]), Integer.parseInt(stuff[4]), Double.parseDouble(stuff[5])));
+ else if (stuff.length >= 5)
this.settings.add(new WiredMatchFurniSetting(Integer.parseInt(stuff[0]), stuff[1], Integer.parseInt(stuff[2]), Integer.parseInt(stuff[3]), Integer.parseInt(stuff[4])));
}
this.state = data[2].equals("1");
this.direction = data[3].equals("1");
this.position = data[4].equals("1");
+ this.altitude = false;
this.furniSource = this.settings.isEmpty() ? WiredSourceUtil.SOURCE_TRIGGER : WiredSourceUtil.SOURCE_SELECTED;
+ this.quantifier = QUANTIFIER_ALL;
}
}
@@ -224,10 +291,16 @@ public class WiredConditionMatchStatePosition extends InteractionWiredCondition
this.direction = false;
this.position = false;
this.state = false;
+ this.altitude = false;
this.furniSource = WiredSourceUtil.SOURCE_TRIGGER;
+ this.quantifier = QUANTIFIER_ALL;
}
- private void refresh() {
+ private int normalizeQuantifier(int value) {
+ return (value == QUANTIFIER_ANY) ? QUANTIFIER_ANY : QUANTIFIER_ALL;
+ }
+
+ protected void refresh() {
Room room = Emulator.getGameEnvironment().getRoomManager().getRoom(this.getRoomId());
if (room != null) {
@@ -266,19 +339,28 @@ public class WiredConditionMatchStatePosition extends InteractionWiredCondition
return this.position;
}
+ @Override
+ public boolean shouldMatchAltitude() {
+ return this.altitude;
+ }
+
static class JsonData {
boolean state;
boolean position;
boolean direction;
+ boolean altitude;
List settings;
int furniSource;
+ int quantifier;
- public JsonData(boolean state, boolean position, boolean direction, List settings, int furniSource) {
+ public JsonData(boolean state, boolean position, boolean direction, boolean altitude, List settings, int furniSource, int quantifier) {
this.state = state;
this.position = position;
this.direction = direction;
+ this.altitude = altitude;
this.settings = settings;
this.furniSource = furniSource;
+ this.quantifier = quantifier;
}
}
}
diff --git a/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionNotFurniHaveHabbo.java b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionNotFurniHaveHabbo.java
index dff23b8a..3aec0268 100644
--- a/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionNotFurniHaveHabbo.java
+++ b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionNotFurniHaveHabbo.java
@@ -28,6 +28,7 @@ public class WiredConditionNotFurniHaveHabbo extends InteractionWiredCondition {
public static final WiredConditionType type = WiredConditionType.NOT_FURNI_HAVE_HABBO;
protected THashSet items;
+ protected boolean all;
private int furniSource = WiredSourceUtil.SOURCE_TRIGGER;
public WiredConditionNotFurniHaveHabbo(ResultSet set, Item baseItem) throws SQLException {
@@ -43,6 +44,7 @@ public class WiredConditionNotFurniHaveHabbo extends InteractionWiredCondition {
@Override
public void onPickUp() {
this.items.clear();
+ this.all = false;
this.furniSource = WiredSourceUtil.SOURCE_TRIGGER;
}
@@ -63,15 +65,11 @@ public class WiredConditionNotFurniHaveHabbo extends InteractionWiredCondition {
Collection bots = room.getCurrentBots().valueCollection();
Collection pets = room.getCurrentPets().valueCollection();
- return targets.stream().filter(item -> item != null).noneMatch(item -> {
- RoomTile baseTile = room.getLayout().getTile(item.getX(), item.getY());
- if (baseTile == null) return false;
-
- THashSet occupiedTiles = room.getLayout().getTilesAt(baseTile, item.getBaseItem().getWidth(), item.getBaseItem().getLength(), item.getRotation());
- return habbos.stream().anyMatch(character -> character.getRoomUnit() != null && occupiedTiles.contains(character.getRoomUnit().getCurrentLocation())) ||
- bots.stream().anyMatch(character -> character.getRoomUnit() != null && occupiedTiles.contains(character.getRoomUnit().getCurrentLocation())) ||
- pets.stream().anyMatch(character -> character.getRoomUnit() != null && occupiedTiles.contains(character.getRoomUnit().getCurrentLocation()));
- });
+ if (this.all) {
+ return targets.stream().filter(item -> item != null).allMatch(item -> !this.hasAvatarOnItem(item, room, habbos, bots, pets));
+ }
+
+ return targets.stream().filter(item -> item != null).anyMatch(item -> !this.hasAvatarOnItem(item, room, habbos, bots, pets));
}
@Deprecated
@@ -85,7 +83,8 @@ public class WiredConditionNotFurniHaveHabbo extends InteractionWiredCondition {
this.refresh();
return WiredManager.getGson().toJson(new JsonData(
this.items.stream().map(HabboItem::getId).collect(Collectors.toList()),
- this.furniSource
+ this.furniSource,
+ this.all
));
}
@@ -97,6 +96,7 @@ public class WiredConditionNotFurniHaveHabbo extends InteractionWiredCondition {
if (wiredData.startsWith("{")) {
WiredConditionFurniHaveHabbo.JsonData data = WiredManager.getGson().fromJson(wiredData, WiredConditionFurniHaveHabbo.JsonData.class);
this.furniSource = data.furniSource;
+ this.all = data.all;
for(int id : data.itemIds) {
HabboItem item = room.getHabboItem(id);
@@ -119,6 +119,7 @@ public class WiredConditionNotFurniHaveHabbo extends InteractionWiredCondition {
}
}
this.furniSource = this.items.isEmpty() ? WiredSourceUtil.SOURCE_TRIGGER : WiredSourceUtil.SOURCE_SELECTED;
+ this.all = false;
}
if (this.furniSource == WiredSourceUtil.SOURCE_TRIGGER && !this.items.isEmpty()) {
this.furniSource = WiredSourceUtil.SOURCE_SELECTED;
@@ -144,7 +145,8 @@ public class WiredConditionNotFurniHaveHabbo extends InteractionWiredCondition {
message.appendInt(this.getBaseItem().getSpriteId());
message.appendInt(this.getId());
message.appendString("");
- message.appendInt(1);
+ message.appendInt(2);
+ message.appendInt(this.all ? 1 : 0);
message.appendInt(this.furniSource);
message.appendInt(0);
message.appendInt(this.getType().code);
@@ -158,7 +160,8 @@ public class WiredConditionNotFurniHaveHabbo extends InteractionWiredCondition {
if (count > Emulator.getConfig().getInt("hotel.wired.furni.selection.count")) return false;
int[] params = settings.getIntParams();
- this.furniSource = (params.length > 0) ? params[0] : WiredSourceUtil.SOURCE_TRIGGER;
+ this.all = (params.length > 0) && (params[0] == 1);
+ this.furniSource = (params.length > 1) ? params[1] : ((params.length > 0 && params[0] > 1) ? params[0] : WiredSourceUtil.SOURCE_TRIGGER);
this.items.clear();
@@ -178,6 +181,18 @@ public class WiredConditionNotFurniHaveHabbo extends InteractionWiredCondition {
return true;
}
+ protected boolean hasAvatarOnItem(HabboItem item, Room room, Collection habbos, Collection bots, Collection pets) {
+ RoomTile baseTile = room.getLayout().getTile(item.getX(), item.getY());
+ if (baseTile == null) return false;
+
+ THashSet occupiedTiles = room.getLayout().getTilesAt(baseTile, item.getBaseItem().getWidth(), item.getBaseItem().getLength(), item.getRotation());
+ return occupiedTiles != null && (
+ habbos.stream().anyMatch(character -> character.getRoomUnit() != null && occupiedTiles.contains(character.getRoomUnit().getCurrentLocation())) ||
+ bots.stream().anyMatch(character -> character.getRoomUnit() != null && occupiedTiles.contains(character.getRoomUnit().getCurrentLocation())) ||
+ pets.stream().anyMatch(character -> character.getRoomUnit() != null && occupiedTiles.contains(character.getRoomUnit().getCurrentLocation()))
+ );
+ }
+
private void refresh() {
THashSet items = new THashSet<>();
@@ -199,10 +214,12 @@ public class WiredConditionNotFurniHaveHabbo extends InteractionWiredCondition {
static class JsonData {
List itemIds;
int furniSource;
+ boolean all;
- public JsonData(List itemIds, int furniSource) {
+ public JsonData(List itemIds, int furniSource, boolean all) {
this.itemIds = itemIds;
this.furniSource = furniSource;
+ this.all = all;
}
}
}
diff --git a/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionNotFurniTypeMatch.java b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionNotFurniTypeMatch.java
index b9aaf539..49dc6775 100644
--- a/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionNotFurniTypeMatch.java
+++ b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionNotFurniTypeMatch.java
@@ -1,30 +1,15 @@
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.WiredManager;
import com.eu.habbo.habbohotel.wired.core.WiredContext;
-import com.eu.habbo.habbohotel.wired.core.WiredSourceUtil;
-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 WiredConditionNotFurniTypeMatch extends InteractionWiredCondition {
+public class WiredConditionNotFurniTypeMatch extends WiredConditionFurniTypeMatch {
public static final WiredConditionType type = WiredConditionType.NOT_STUFF_IS;
- private THashSet items = new THashSet<>();
- private int furniSource = WiredSourceUtil.SOURCE_TRIGGER;
-
public WiredConditionNotFurniTypeMatch(ResultSet set, Item baseItem) throws SQLException {
super(set, baseItem);
}
@@ -35,145 +20,15 @@ public class WiredConditionNotFurniTypeMatch extends InteractionWiredCondition {
@Override
public boolean evaluate(WiredContext ctx) {
- this.refresh();
-
- if(items.isEmpty())
- return true;
-
- List targets = WiredSourceUtil.resolveItems(ctx, this.furniSource, this.items);
- if (targets.isEmpty()) return true;
- return targets.stream().noneMatch(this.items::contains);
- }
-
- @Deprecated
- @Override
- public boolean execute(RoomUnit roomUnit, Room room, Object[] stuff) {
- return false;
- }
-
- @Override
- public String getWiredData() {
- this.refresh();
- return WiredManager.getGson().toJson(new JsonData(
- this.items.stream().map(HabboItem::getId).collect(Collectors.toList()),
- this.furniSource
- ));
- }
-
- @Override
- public void loadWiredData(ResultSet set, Room room) throws SQLException {
- this.items.clear();
- String wiredData = set.getString("wired_data");
-
- if (wiredData.startsWith("{")) {
- WiredConditionFurniTypeMatch.JsonData data = WiredManager.getGson().fromJson(wiredData, WiredConditionFurniTypeMatch.JsonData.class);
- this.furniSource = data.furniSource;
-
- for(int id : data.itemIds) {
- HabboItem item = room.getHabboItem(id);
-
- if (item != null) {
- this.items.add(item);
- }
- }
- } else {
- String[] data = set.getString("wired_data").split(";");
-
- for (String s : data) {
- 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;
+ if (this.getQuantifier() == QUANTIFIER_ANY) {
+ return !this.evaluateAllMatches(ctx);
}
- if (this.furniSource == WiredSourceUtil.SOURCE_TRIGGER && !this.items.isEmpty()) {
- this.furniSource = WiredSourceUtil.SOURCE_SELECTED;
- }
- }
- @Override
- public void onPickUp() {
- this.items.clear();
- this.furniSource = WiredSourceUtil.SOURCE_TRIGGER;
+ return !this.evaluateAnyMatches(ctx);
}
@Override
public WiredConditionType getType() {
return type;
}
-
- @Override
- public void serializeWiredData(ServerMessage message, Room room) {
- this.refresh();
-
- 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(1);
- message.appendInt(this.furniSource);
- message.appendInt(0);
- message.appendInt(this.getType().code);
- message.appendInt(0);
- message.appendInt(0);
- }
-
- @Override
- public boolean saveData(WiredSettings settings) {
- int count = settings.getFurniIds().length;
- if (count > Emulator.getConfig().getInt("hotel.wired.furni.selection.count")) return false;
-
- int[] params = settings.getIntParams();
- this.furniSource = (params.length > 0) ? params[0] : WiredSourceUtil.SOURCE_TRIGGER;
-
- this.items.clear();
-
- if (this.furniSource == WiredSourceUtil.SOURCE_SELECTED) {
- Room room = Emulator.getGameEnvironment().getRoomManager().getRoom(this.getRoomId());
-
- if (room != null) {
- for (int i = 0; i < count; i++) {
- this.items.add(room.getHabboItem(settings.getFurniIds()[i]));
- }
- }
- }
-
- return true;
- }
-
- private void refresh() {
- THashSet items = new THashSet<>();
-
- Room room = Emulator.getGameEnvironment().getRoomManager().getRoom(this.getRoomId());
- if (room == null) {
- items.addAll(this.items);
- } else {
- for (HabboItem item : this.items) {
- if (room.getHabboItem(item.getId()) == null)
- items.add(item);
- }
- }
-
- for (HabboItem item : items) {
- this.items.remove(item);
- }
- }
-
- static class JsonData {
- List itemIds;
- int furniSource;
-
- public JsonData(List itemIds, int furniSource) {
- this.itemIds = itemIds;
- this.furniSource = furniSource;
- }
- }
}
diff --git a/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionNotHabboHasEffect.java b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionNotHabboHasEffect.java
index d061c0a8..b7c72361 100644
--- a/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionNotHabboHasEffect.java
+++ b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionNotHabboHasEffect.java
@@ -1,26 +1,18 @@
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.WiredManager;
import com.eu.habbo.habbohotel.wired.core.WiredContext;
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 WiredConditionNotHabboHasEffect extends InteractionWiredCondition {
+public class WiredConditionNotHabboHasEffect extends WiredConditionHabboHasEffect {
private static final WiredConditionType type = WiredConditionType.NOT_ACTOR_WEARS_EFFECT;
- protected int effectId;
- private int userSource = WiredSourceUtil.SOURCE_TRIGGER;
-
public WiredConditionNotHabboHasEffect(ResultSet set, Item baseItem) throws SQLException {
super(set, baseItem);
}
@@ -33,88 +25,16 @@ public class WiredConditionNotHabboHasEffect extends InteractionWiredCondition {
public boolean evaluate(WiredContext ctx) {
List targets = WiredSourceUtil.resolveUsers(ctx, this.userSource);
if (targets.isEmpty()) return false;
- for (RoomUnit roomUnit : targets) {
- if (roomUnit == null) return false;
- if (roomUnit.getEffectId() == this.effectId) {
- return false;
- }
+
+ if (this.getQuantifier() == QUANTIFIER_ALL) {
+ return !this.matchesAllTargets(targets);
}
- 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.effectId,
- 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 = data.effectId;
- this.userSource = data.userSource;
- } else {
- this.effectId = Integer.parseInt(wiredData);
- this.userSource = WiredSourceUtil.SOURCE_TRIGGER;
- }
- }
-
- @Override
- public void onPickUp() {
- this.effectId = 0;
- this.userSource = WiredSourceUtil.SOURCE_TRIGGER;
+ return !this.matchesAnyTarget(targets);
}
@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(this.effectId + "");
- message.appendInt(2);
- message.appendInt(this.effectId);
- message.appendInt(this.userSource);
- message.appendInt(0);
- message.appendInt(this.getType().code);
- message.appendInt(0);
- message.appendInt(0);
- }
-
- @Override
- public boolean saveData(WiredSettings settings) {
- if(settings.getIntParams().length < 1) return false;
- this.effectId = settings.getIntParams()[0];
- int[] params = settings.getIntParams();
- this.userSource = (params.length > 1) ? params[1] : WiredSourceUtil.SOURCE_TRIGGER;
-
- return true;
- }
-
- static class JsonData {
- int effectId;
- int userSource;
-
- public JsonData(int effectId, int userSource) {
- this.effectId = effectId;
- this.userSource = userSource;
- }
- }
}
diff --git a/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionNotHabboHasHandItem.java b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionNotHabboHasHandItem.java
index 24421924..060b6089 100644
--- a/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionNotHabboHasHandItem.java
+++ b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionNotHabboHasHandItem.java
@@ -26,13 +26,11 @@ public class WiredConditionNotHabboHasHandItem extends WiredConditionHabboHasHan
List targets = WiredSourceUtil.resolveUsers(ctx, this.getUserSource());
if (targets.isEmpty()) return false;
- for (RoomUnit roomUnit : targets) {
- if (roomUnit == null || roomUnit.getHandItem() == this.getHandItem()) {
- return false;
- }
+ if (this.getQuantifier() == QUANTIFIER_ANY) {
+ return !this.matchesAnyTarget(targets);
}
- return true;
+ return !this.matchesAllTargets(targets);
}
@Override
diff --git a/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionNotHabboWearsBadge.java b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionNotHabboWearsBadge.java
index 5521d5d8..18a6c869 100644
--- a/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionNotHabboWearsBadge.java
+++ b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionNotHabboWearsBadge.java
@@ -1,28 +1,19 @@
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.users.Habbo;
-import com.eu.habbo.habbohotel.users.HabboBadge;
import com.eu.habbo.habbohotel.wired.WiredConditionType;
-import com.eu.habbo.habbohotel.wired.core.WiredManager;
import com.eu.habbo.habbohotel.wired.core.WiredContext;
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 WiredConditionNotHabboWearsBadge extends InteractionWiredCondition {
+public class WiredConditionNotHabboWearsBadge extends WiredConditionHabboWearsBadge {
public static final WiredConditionType type = WiredConditionType.NOT_ACTOR_WEARS_BADGE;
- protected String badge = "";
- private int userSource = WiredSourceUtil.SOURCE_TRIGGER;
-
public WiredConditionNotHabboWearsBadge(ResultSet set, Item baseItem) throws SQLException {
super(set, baseItem);
}
@@ -37,91 +28,15 @@ public class WiredConditionNotHabboWearsBadge extends InteractionWiredCondition
List targets = WiredSourceUtil.resolveUsers(ctx, this.userSource);
if (targets.isEmpty()) return true;
- for (RoomUnit roomUnit : targets) {
- Habbo habbo = room.getHabbo(roomUnit);
- if (habbo != null) {
- synchronized (habbo.getInventory().getBadgesComponent().getWearingBadges()) {
- for (HabboBadge b : habbo.getInventory().getBadgesComponent().getWearingBadges()) {
- if (b.getCode().equalsIgnoreCase(this.badge))
- return false;
- }
- }
- }
+ if (this.getQuantifier() == QUANTIFIER_ALL) {
+ return !this.matchesAllTargets(room, targets);
}
- 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.badge,
- 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.badge = data.badge;
- this.userSource = data.userSource;
- } else {
- this.badge = wiredData;
- this.userSource = WiredSourceUtil.SOURCE_TRIGGER;
- }
- }
-
- @Override
- public void onPickUp() {
- this.badge = "";
- this.userSource = WiredSourceUtil.SOURCE_TRIGGER;
+ return !this.matchesAnyTarget(room, targets);
}
@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(this.badge);
- message.appendInt(1);
- message.appendInt(this.userSource);
- message.appendInt(0);
- message.appendInt(this.getType().code);
- message.appendInt(0);
- message.appendInt(0);
- }
-
- @Override
- public boolean saveData(WiredSettings settings) {
- this.badge = settings.getStringParam();
- int[] params = settings.getIntParams();
- this.userSource = (params.length > 0) ? params[0] : WiredSourceUtil.SOURCE_TRIGGER;
-
- return true;
- }
-
- static class JsonData {
- String badge;
- int userSource;
-
- public JsonData(String badge, int userSource) {
- this.badge = badge;
- this.userSource = userSource;
- }
- }
}
diff --git a/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionNotInGroup.java b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionNotInGroup.java
index 237be63d..04bbe22c 100644
--- a/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionNotInGroup.java
+++ b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionNotInGroup.java
@@ -8,6 +8,7 @@ import com.eu.habbo.habbohotel.rooms.RoomUnit;
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;
@@ -16,8 +17,16 @@ import java.sql.SQLException;
import java.util.List;
public class WiredConditionNotInGroup extends InteractionWiredCondition {
+ private static final int GROUP_CURRENT_ROOM = 0;
+ private static final int GROUP_SELECTED = 1;
+ private static final int QUANTIFIER_ALL = 0;
+ private static final int QUANTIFIER_ANY = 1;
+
public static final WiredConditionType type = WiredConditionType.NOT_ACTOR_IN_GROUP;
private int userSource = WiredSourceUtil.SOURCE_TRIGGER;
+ private int groupType = GROUP_CURRENT_ROOM;
+ private int selectedGroupId = 0;
+ private int quantifier = QUANTIFIER_ALL;
public WiredConditionNotInGroup(ResultSet set, Item baseItem) throws SQLException {
super(set, baseItem);
@@ -30,18 +39,31 @@ public class WiredConditionNotInGroup extends InteractionWiredCondition {
@Override
public boolean evaluate(WiredContext ctx) {
Room room = ctx.room();
- if (room.getGuildId() == 0)
+ int targetGroupId = this.resolveTargetGroupId(room);
+ if (targetGroupId == 0)
return false;
List targets = WiredSourceUtil.resolveUsers(ctx, this.userSource);
- if (targets.isEmpty()) return true;
+ if (targets.isEmpty()) return false;
+
+ if (this.quantifier == QUANTIFIER_ANY) {
+ for (RoomUnit roomUnit : targets) {
+ Habbo habbo = room.getHabbo(roomUnit);
+ if (habbo == null || !habbo.getHabboStats().hasGuild(targetGroupId)) {
+ return true;
+ }
+ }
+
+ return false;
+ }
for (RoomUnit roomUnit : targets) {
Habbo habbo = room.getHabbo(roomUnit);
- if (habbo != null && habbo.getHabboStats().hasGuild(room.getGuildId())) {
+ if (habbo != null && habbo.getHabboStats().hasGuild(targetGroupId)) {
return false;
}
}
+
return true;
}
@@ -53,26 +75,45 @@ public class WiredConditionNotInGroup extends InteractionWiredCondition {
@Override
public String getWiredData() {
- return String.valueOf(this.userSource);
+ return WiredManager.getGson().toJson(new JsonData(
+ this.userSource,
+ this.groupType,
+ this.selectedGroupId,
+ this.quantifier
+ ));
}
@Override
public void loadWiredData(ResultSet set, Room room) throws SQLException {
+ this.resetSettings();
+
String wiredData = set.getString("wired_data");
- if (wiredData != null && !wiredData.isEmpty()) {
- try {
- this.userSource = Integer.parseInt(wiredData);
- } catch (NumberFormatException ignored) {
- this.userSource = WiredSourceUtil.SOURCE_TRIGGER;
+ if (wiredData == null || wiredData.isEmpty()) {
+ return;
+ }
+
+ try {
+ if (wiredData.startsWith("{")) {
+ JsonData data = WiredManager.getGson().fromJson(wiredData, JsonData.class);
+ if (data == null) {
+ return;
+ }
+
+ this.userSource = this.normalizeUserSource(data.userSource);
+ this.groupType = this.normalizeGroupType(data.groupType);
+ this.selectedGroupId = this.normalizeSelectedGroupId(data.selectedGroupId);
+ this.quantifier = this.normalizeQuantifier(data.quantifier);
+ return;
}
- } else {
- this.userSource = WiredSourceUtil.SOURCE_TRIGGER;
+ this.userSource = this.normalizeUserSource(Integer.parseInt(wiredData));
+ } catch (Exception ignored) {
+ this.resetSettings();
}
}
@Override
public void onPickUp() {
- this.userSource = WiredSourceUtil.SOURCE_TRIGGER;
+ this.resetSettings();
}
@Override
@@ -88,8 +129,11 @@ public class WiredConditionNotInGroup extends InteractionWiredCondition {
message.appendInt(this.getBaseItem().getSpriteId());
message.appendInt(this.getId());
message.appendString("");
- message.appendInt(1);
+ message.appendInt(4);
message.appendInt(this.userSource);
+ message.appendInt(this.groupType);
+ message.appendInt(this.selectedGroupId);
+ message.appendInt(this.quantifier);
message.appendInt(0);
message.appendInt(this.getType().code);
message.appendInt(0);
@@ -99,7 +143,66 @@ public class WiredConditionNotInGroup extends InteractionWiredCondition {
@Override
public boolean saveData(WiredSettings settings) {
int[] params = settings.getIntParams();
- this.userSource = (params.length > 0) ? params[0] : WiredSourceUtil.SOURCE_TRIGGER;
+ this.userSource = (params.length > 0) ? this.normalizeUserSource(params[0]) : WiredSourceUtil.SOURCE_TRIGGER;
+ this.groupType = (params.length > 1) ? this.normalizeGroupType(params[1]) : GROUP_CURRENT_ROOM;
+ this.selectedGroupId = (params.length > 2) ? this.normalizeSelectedGroupId(params[2]) : 0;
+ this.quantifier = (params.length > 3) ? this.normalizeQuantifier(params[3]) : QUANTIFIER_ALL;
return true;
}
+
+ private void resetSettings() {
+ this.userSource = WiredSourceUtil.SOURCE_TRIGGER;
+ this.groupType = GROUP_CURRENT_ROOM;
+ this.selectedGroupId = 0;
+ this.quantifier = QUANTIFIER_ALL;
+ }
+
+ private int resolveTargetGroupId(Room room) {
+ if (room == null) {
+ return 0;
+ }
+
+ if (this.groupType == GROUP_SELECTED) {
+ return this.selectedGroupId;
+ }
+
+ return room.getGuildId();
+ }
+
+ private int normalizeUserSource(int value) {
+ switch (value) {
+ case WiredSourceUtil.SOURCE_TRIGGER:
+ case WiredSourceUtil.SOURCE_SELECTOR:
+ case WiredSourceUtil.SOURCE_SIGNAL:
+ return value;
+ default:
+ return WiredSourceUtil.SOURCE_TRIGGER;
+ }
+ }
+
+ private int normalizeGroupType(int value) {
+ return (value == GROUP_SELECTED) ? GROUP_SELECTED : GROUP_CURRENT_ROOM;
+ }
+
+ private int normalizeSelectedGroupId(int value) {
+ return Math.max(0, value);
+ }
+
+ private int normalizeQuantifier(int value) {
+ return (value == QUANTIFIER_ANY) ? QUANTIFIER_ANY : QUANTIFIER_ALL;
+ }
+
+ static class JsonData {
+ int userSource;
+ int groupType;
+ int selectedGroupId;
+ int quantifier;
+
+ public JsonData(int userSource, int groupType, int selectedGroupId, int quantifier) {
+ this.userSource = userSource;
+ this.groupType = groupType;
+ this.selectedGroupId = selectedGroupId;
+ this.quantifier = quantifier;
+ }
+ }
}
diff --git a/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionNotInTeam.java b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionNotInTeam.java
index 9eead216..d2349c84 100644
--- a/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionNotInTeam.java
+++ b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionNotInTeam.java
@@ -1,28 +1,19 @@
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.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.Habbo;
-import com.eu.habbo.habbohotel.wired.core.WiredContext;
import com.eu.habbo.habbohotel.wired.WiredConditionType;
-import com.eu.habbo.habbohotel.wired.core.WiredManager;
+import com.eu.habbo.habbohotel.wired.core.WiredContext;
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 WiredConditionNotInTeam extends InteractionWiredCondition {
+public class WiredConditionNotInTeam extends WiredConditionTeamMember {
public static final WiredConditionType type = WiredConditionType.NOT_ACTOR_IN_TEAM;
- private GameTeamColors teamColor = GameTeamColors.RED;
- private int userSource = WiredSourceUtil.SOURCE_TRIGGER;
-
public WiredConditionNotInTeam(ResultSet set, Item baseItem) throws SQLException {
super(set, baseItem);
}
@@ -37,96 +28,15 @@ public class WiredConditionNotInTeam extends InteractionWiredCondition {
List targets = WiredSourceUtil.resolveUsers(ctx, this.userSource);
if (targets.isEmpty()) return true;
- for (RoomUnit roomUnit : targets) {
- Habbo habbo = room.getHabbo(roomUnit);
- if (habbo != null && habbo.getHabboInfo().getGamePlayer() != null) {
- if (habbo.getHabboInfo().getGamePlayer().getTeamColor().equals(this.teamColor)) {
- return false;
- }
- }
+ if (this.getQuantifier() == QUANTIFIER_ALL) {
+ return !this.evaluateAllTargetsMatch(room, targets);
}
- 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.teamColor,
- this.userSource
- ));
- }
-
- @Override
- public void loadWiredData(ResultSet set, Room room) throws SQLException {
- try {
- String wiredData = set.getString("wired_data");
-
- if (wiredData.startsWith("{")) {
- JsonData data = WiredManager.getGson().fromJson(wiredData, JsonData.class);
- this.teamColor = data.teamColor;
- this.userSource = data.userSource;
- } else {
- if (!wiredData.equals(""))
- this.teamColor = GameTeamColors.values()[Integer.parseInt(wiredData)];
- this.userSource = WiredSourceUtil.SOURCE_TRIGGER;
- }
- } catch (Exception e) {
- this.teamColor = GameTeamColors.RED;
- this.userSource = WiredSourceUtil.SOURCE_TRIGGER;
- }
- }
-
- @Override
- public void onPickUp() {
- this.teamColor = GameTeamColors.RED;
- this.userSource = WiredSourceUtil.SOURCE_TRIGGER;
+ return !this.evaluateAnyTargetMatches(room, targets);
}
@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(2);
- message.appendInt(this.teamColor.type);
- message.appendInt(this.userSource);
- message.appendInt(0);
- message.appendInt(this.getType().code);
- message.appendInt(0);
- message.appendInt(0);
- }
-
- @Override
- public boolean saveData(WiredSettings settings) {
- if(settings.getIntParams().length < 1) return false;
- this.teamColor = GameTeamColors.values()[settings.getIntParams()[0]];
- int[] params = settings.getIntParams();
- this.userSource = (params.length > 1) ? params[1] : WiredSourceUtil.SOURCE_TRIGGER;
-
- return true;
- }
-
- static class JsonData {
- GameTeamColors teamColor;
- int userSource;
-
- public JsonData(GameTeamColors teamColor, int userSource) {
- this.teamColor = teamColor;
- this.userSource = userSource;
- }
- }
}
diff --git a/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionNotMatchStatePosition.java b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionNotMatchStatePosition.java
index 2121bf97..e52315dc 100644
--- a/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionNotMatchStatePosition.java
+++ b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionNotMatchStatePosition.java
@@ -22,7 +22,17 @@ public class WiredConditionNotMatchStatePosition extends WiredConditionMatchStat
@Override
public boolean evaluate(WiredContext ctx) {
- return !super.evaluate(ctx);
+ this.refresh();
+
+ if (this.getMatchFurniSettings().isEmpty()) {
+ return false;
+ }
+
+ if (this.getQuantifier() == QUANTIFIER_ANY) {
+ return !this.evaluateAnyTargetMatches(ctx);
+ }
+
+ return !this.evaluateAllTargetsMatch(ctx);
}
@Deprecated
diff --git a/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionNotTriggerOnFurni.java b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionNotTriggerOnFurni.java
index 4fe1d474..7b726e80 100644
--- a/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionNotTriggerOnFurni.java
+++ b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionNotTriggerOnFurni.java
@@ -37,7 +37,11 @@ public class WiredConditionNotTriggerOnFurni extends WiredConditionTriggerOnFurn
if (itemTargets.isEmpty())
return true;
- return !isAnyUserOnFurni(userTargets, itemTargets, room);
+ if (this.getQuantifier() == QUANTIFIER_ANY) {
+ return !this.isAnyUserOnFurni(userTargets, itemTargets, room);
+ }
+
+ return !this.areAllUsersOnFurni(userTargets, itemTargets, room);
}
@Deprecated
diff --git a/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionSelectionQuantity.java b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionSelectionQuantity.java
new file mode 100644
index 00000000..87e09812
--- /dev/null
+++ b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionSelectionQuantity.java
@@ -0,0 +1,213 @@
+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.habbohotel.wired.core.WiredSourceUtil;
+import com.eu.habbo.habbohotel.users.HabboItem;
+import com.eu.habbo.messages.ServerMessage;
+
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.List;
+
+public class WiredConditionSelectionQuantity extends InteractionWiredCondition {
+ private static final int COMPARISON_LESS_THAN = 0;
+ private static final int COMPARISON_EQUAL = 1;
+ private static final int COMPARISON_GREATER_THAN = 2;
+
+ private static final int SOURCE_GROUP_USERS = 0;
+ private static final int SOURCE_GROUP_FURNI = 1;
+
+ public static final WiredConditionType type = WiredConditionType.SLC_QUANTITY;
+
+ private int comparison = COMPARISON_EQUAL;
+ private int quantity = 0;
+ private int sourceGroup = SOURCE_GROUP_USERS;
+ private int sourceType = WiredSourceUtil.SOURCE_TRIGGER;
+
+ public WiredConditionSelectionQuantity(ResultSet set, Item baseItem) throws SQLException {
+ super(set, baseItem);
+ }
+
+ public WiredConditionSelectionQuantity(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(4);
+ message.appendInt(this.comparison);
+ message.appendInt(this.quantity);
+ message.appendInt(this.sourceGroup);
+ message.appendInt(this.sourceType);
+ 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.quantity = (params.length > 1) ? this.normalizeQuantity(params[1]) : 0;
+ this.sourceGroup = (params.length > 2) ? this.normalizeSourceGroup(params[2]) : SOURCE_GROUP_USERS;
+ this.sourceType = (params.length > 3) ? this.normalizeSourceType(this.sourceGroup, params[3]) : WiredSourceUtil.SOURCE_TRIGGER;
+
+ return true;
+ }
+
+ @Override
+ public boolean evaluate(WiredContext ctx) {
+ int count = this.resolveCount(ctx);
+
+ switch (this.comparison) {
+ case COMPARISON_LESS_THAN:
+ return count < this.quantity;
+ case COMPARISON_GREATER_THAN:
+ return count > this.quantity;
+ default:
+ return count == this.quantity;
+ }
+ }
+
+ @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.quantity,
+ this.sourceGroup,
+ this.sourceType
+ ));
+ }
+
+ @Override
+ public void loadWiredData(ResultSet set, Room room) throws SQLException {
+ this.onPickUp();
+
+ 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.comparison = this.normalizeComparison(data.comparison);
+ this.quantity = this.normalizeQuantity(data.quantity);
+ this.sourceGroup = this.normalizeSourceGroup(data.sourceGroup);
+ this.sourceType = this.normalizeSourceType(this.sourceGroup, data.sourceType);
+ return;
+ }
+
+ String[] parts = wiredData.split("\t");
+
+ try {
+ if (parts.length > 0) {
+ this.comparison = this.normalizeComparison(Integer.parseInt(parts[0]));
+ }
+ if (parts.length > 1) {
+ this.quantity = this.normalizeQuantity(Integer.parseInt(parts[1]));
+ }
+ if (parts.length > 2) {
+ this.sourceGroup = this.normalizeSourceGroup(Integer.parseInt(parts[2]));
+ }
+ if (parts.length > 3) {
+ this.sourceType = this.normalizeSourceType(this.sourceGroup, Integer.parseInt(parts[3]));
+ }
+ } catch (NumberFormatException ignored) {
+ this.onPickUp();
+ }
+ }
+
+ @Override
+ public void onPickUp() {
+ this.comparison = COMPARISON_EQUAL;
+ this.quantity = 0;
+ this.sourceGroup = SOURCE_GROUP_USERS;
+ this.sourceType = WiredSourceUtil.SOURCE_TRIGGER;
+ }
+
+ private int resolveCount(WiredContext ctx) {
+ if (this.sourceGroup == SOURCE_GROUP_FURNI) {
+ List items = WiredSourceUtil.resolveItems(ctx, this.sourceType, null);
+
+ return items.size();
+ }
+
+ List users = WiredSourceUtil.resolveUsers(ctx, this.sourceType);
+
+ return users.size();
+ }
+
+ private int normalizeComparison(int value) {
+ switch (value) {
+ case COMPARISON_LESS_THAN:
+ case COMPARISON_GREATER_THAN:
+ return value;
+ default:
+ return COMPARISON_EQUAL;
+ }
+ }
+
+ private int normalizeQuantity(int value) {
+ return Math.max(0, Math.min(100, value));
+ }
+
+ private int normalizeSourceGroup(int value) {
+ return (value == SOURCE_GROUP_FURNI) ? SOURCE_GROUP_FURNI : SOURCE_GROUP_USERS;
+ }
+
+ private int normalizeSourceType(int group, int value) {
+ switch (value) {
+ case WiredSourceUtil.SOURCE_SELECTOR:
+ case WiredSourceUtil.SOURCE_SIGNAL:
+ case WiredSourceUtil.SOURCE_TRIGGER:
+ return value;
+ default:
+ return WiredSourceUtil.SOURCE_TRIGGER;
+ }
+ }
+
+ static class JsonData {
+ int comparison;
+ int quantity;
+ int sourceGroup;
+ int sourceType;
+
+ public JsonData(int comparison, int quantity, int sourceGroup, int sourceType) {
+ this.comparison = comparison;
+ this.quantity = quantity;
+ this.sourceGroup = sourceGroup;
+ this.sourceType = sourceType;
+ }
+ }
+}
diff --git a/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionTeamMember.java b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionTeamMember.java
index 658f8b7d..4ca7b4e1 100644
--- a/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionTeamMember.java
+++ b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionTeamMember.java
@@ -18,10 +18,14 @@ import java.sql.SQLException;
import java.util.List;
public class WiredConditionTeamMember extends InteractionWiredCondition {
+ protected static final int QUANTIFIER_ALL = 0;
+ protected static final int QUANTIFIER_ANY = 1;
+
public static final WiredConditionType type = WiredConditionType.ACTOR_IN_TEAM;
private GameTeamColors teamColor = GameTeamColors.RED;
- private int userSource = WiredSourceUtil.SOURCE_TRIGGER;
+ protected int userSource = WiredSourceUtil.SOURCE_TRIGGER;
+ protected int quantifier = QUANTIFIER_ALL;
public WiredConditionTeamMember(ResultSet set, Item baseItem) throws SQLException {
super(set, baseItem);
@@ -37,17 +41,40 @@ public class WiredConditionTeamMember extends InteractionWiredCondition {
List targets = WiredSourceUtil.resolveUsers(ctx, this.userSource);
if (targets.isEmpty()) return false;
+ if (this.quantifier == QUANTIFIER_ANY) {
+ return this.evaluateAnyTargetMatches(room, targets);
+ }
+
+ return this.evaluateAllTargetsMatch(room, targets);
+ }
+
+ protected boolean evaluateAllTargetsMatch(Room room, List targets) {
for (RoomUnit roomUnit : targets) {
- Habbo habbo = room.getHabbo(roomUnit);
- if (habbo != null && habbo.getHabboInfo().getGamePlayer() != null) {
- if (habbo.getHabboInfo().getGamePlayer().getTeamColor().equals(this.teamColor)) {
- return true;
- }
+ if (!this.matchesTeam(room, roomUnit)) {
+ return false;
}
}
+
+ return true;
+ }
+
+ protected boolean evaluateAnyTargetMatches(Room room, List targets) {
+ for (RoomUnit roomUnit : targets) {
+ if (this.matchesTeam(room, roomUnit)) {
+ return true;
+ }
+ }
+
return false;
}
+ protected boolean matchesTeam(Room room, RoomUnit roomUnit) {
+ Habbo habbo = room.getHabbo(roomUnit);
+ return habbo != null
+ && habbo.getHabboInfo().getGamePlayer() != null
+ && habbo.getHabboInfo().getGamePlayer().getTeamColor().equals(this.teamColor);
+ }
+
@Deprecated
@Override
public boolean execute(RoomUnit roomUnit, Room room, Object[] stuff) {
@@ -58,7 +85,8 @@ public class WiredConditionTeamMember extends InteractionWiredCondition {
public String getWiredData() {
return WiredManager.getGson().toJson(new JsonData(
this.teamColor,
- this.userSource
+ this.userSource,
+ this.quantifier
));
}
@@ -71,14 +99,17 @@ public class WiredConditionTeamMember extends InteractionWiredCondition {
JsonData data = WiredManager.getGson().fromJson(wiredData, JsonData.class);
this.teamColor = data.teamColor;
this.userSource = data.userSource;
+ this.quantifier = this.normalizeQuantifier(data.quantifier, QUANTIFIER_ANY);
} else {
if (!wiredData.equals(""))
this.teamColor = GameTeamColors.values()[Integer.parseInt(wiredData)];
this.userSource = WiredSourceUtil.SOURCE_TRIGGER;
+ this.quantifier = QUANTIFIER_ANY;
}
} catch (Exception e) {
this.teamColor = GameTeamColors.RED;
this.userSource = WiredSourceUtil.SOURCE_TRIGGER;
+ this.quantifier = QUANTIFIER_ALL;
}
}
@@ -86,6 +117,7 @@ public class WiredConditionTeamMember extends InteractionWiredCondition {
public void onPickUp() {
this.teamColor = GameTeamColors.RED;
this.userSource = WiredSourceUtil.SOURCE_TRIGGER;
+ this.quantifier = QUANTIFIER_ALL;
}
@Override
@@ -101,9 +133,10 @@ public class WiredConditionTeamMember extends InteractionWiredCondition {
message.appendInt(this.getBaseItem().getSpriteId());
message.appendInt(this.getId());
message.appendString("");
- message.appendInt(2);
+ message.appendInt(3);
message.appendInt(this.teamColor.type);
message.appendInt(this.userSource);
+ message.appendInt(this.quantifier);
message.appendInt(0);
message.appendInt(this.getType().code);
message.appendInt(0);
@@ -113,20 +146,35 @@ public class WiredConditionTeamMember extends InteractionWiredCondition {
@Override
public boolean saveData(WiredSettings settings) {
if(settings.getIntParams().length < 1) return false;
- this.teamColor = GameTeamColors.values()[settings.getIntParams()[0]];
int[] params = settings.getIntParams();
+ this.teamColor = GameTeamColors.values()[params[0]];
this.userSource = (params.length > 1) ? params[1] : WiredSourceUtil.SOURCE_TRIGGER;
+ this.quantifier = (params.length > 2) ? this.normalizeQuantifier(params[2], QUANTIFIER_ALL) : QUANTIFIER_ANY;
return true;
}
+ protected int getQuantifier() {
+ return this.quantifier;
+ }
+
+ protected int normalizeQuantifier(Integer value, int fallback) {
+ if (value == null) {
+ return fallback;
+ }
+
+ return (value == QUANTIFIER_ANY) ? QUANTIFIER_ANY : QUANTIFIER_ALL;
+ }
+
static class JsonData {
GameTeamColors teamColor;
int userSource;
+ Integer quantifier;
- public JsonData(GameTeamColors teamColor, int userSource) {
+ public JsonData(GameTeamColors teamColor, int userSource, int quantifier) {
this.teamColor = teamColor;
this.userSource = userSource;
+ this.quantifier = quantifier;
}
}
}
diff --git a/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionTriggerOnFurni.java b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionTriggerOnFurni.java
index 560ac2d8..bcc3fa5c 100644
--- a/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionTriggerOnFurni.java
+++ b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionTriggerOnFurni.java
@@ -22,11 +22,15 @@ import java.util.List;
import java.util.stream.Collectors;
public class WiredConditionTriggerOnFurni extends InteractionWiredCondition {
+ protected static final int QUANTIFIER_ALL = 0;
+ protected static final int QUANTIFIER_ANY = 1;
+
public static final WiredConditionType type = WiredConditionType.TRIGGER_ON_FURNI;
protected THashSet items = new THashSet<>();
protected int furniSource = WiredSourceUtil.SOURCE_TRIGGER;
protected int userSource = WiredSourceUtil.SOURCE_TRIGGER;
+ protected int quantifier = QUANTIFIER_ALL;
public WiredConditionTriggerOnFurni(ResultSet set, Item baseItem) throws SQLException {
super(set, baseItem);
@@ -38,8 +42,6 @@ public class WiredConditionTriggerOnFurni extends InteractionWiredCondition {
@Override
public boolean evaluate(WiredContext ctx) {
- Room room = ctx.room();
-
this.refresh();
List userTargets = WiredSourceUtil.resolveUsers(ctx, this.userSource);
@@ -50,7 +52,11 @@ public class WiredConditionTriggerOnFurni extends InteractionWiredCondition {
if (itemTargets.isEmpty())
return false;
- return isAnyUserOnFurni(userTargets, itemTargets, room);
+ if (this.quantifier == QUANTIFIER_ANY) {
+ return this.isAnyUserOnFurni(userTargets, itemTargets, ctx.room());
+ }
+
+ return this.areAllUsersOnFurni(userTargets, itemTargets, ctx.room());
}
@Deprecated
@@ -70,13 +76,29 @@ public class WiredConditionTriggerOnFurni extends InteractionWiredCondition {
return false;
}
+ protected boolean areAllUsersOnFurni(Collection users, Collection items, Room room) {
+ for (RoomUnit roomUnit : users) {
+ if (roomUnit == null) {
+ return false;
+ }
+
+ THashSet itemsAtUser = room.getItemsAt(roomUnit.getCurrentLocation());
+ if (itemsAtUser == null || items.stream().noneMatch(itemsAtUser::contains)) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
@Override
public String getWiredData() {
this.refresh();
return WiredManager.getGson().toJson(new JsonData(
this.items.stream().map(HabboItem::getId).collect(Collectors.toList()),
this.furniSource,
- this.userSource
+ this.userSource,
+ this.quantifier
));
}
@@ -89,6 +111,7 @@ public class WiredConditionTriggerOnFurni extends InteractionWiredCondition {
JsonData data = WiredManager.getGson().fromJson(wiredData, JsonData.class);
this.furniSource = data.furniSource;
this.userSource = data.userSource;
+ this.quantifier = this.normalizeQuantifier(data.quantifier);
for(int id : data.itemIds) {
HabboItem item = room.getHabboItem(id);
@@ -109,6 +132,7 @@ public class WiredConditionTriggerOnFurni extends InteractionWiredCondition {
}
this.furniSource = this.items.isEmpty() ? WiredSourceUtil.SOURCE_TRIGGER : WiredSourceUtil.SOURCE_SELECTED;
this.userSource = WiredSourceUtil.SOURCE_TRIGGER;
+ this.quantifier = QUANTIFIER_ALL;
}
if (this.furniSource == WiredSourceUtil.SOURCE_TRIGGER && !this.items.isEmpty()) {
this.furniSource = WiredSourceUtil.SOURCE_SELECTED;
@@ -120,6 +144,7 @@ public class WiredConditionTriggerOnFurni extends InteractionWiredCondition {
this.items.clear();
this.furniSource = WiredSourceUtil.SOURCE_TRIGGER;
this.userSource = WiredSourceUtil.SOURCE_TRIGGER;
+ this.quantifier = QUANTIFIER_ALL;
}
@Override
@@ -141,9 +166,10 @@ public class WiredConditionTriggerOnFurni extends InteractionWiredCondition {
message.appendInt(this.getBaseItem().getSpriteId());
message.appendInt(this.getId());
message.appendString("");
- message.appendInt(2);
+ message.appendInt(3);
message.appendInt(this.furniSource);
message.appendInt(this.userSource);
+ message.appendInt(this.quantifier);
message.appendInt(0);
message.appendInt(this.getType().code);
message.appendInt(0);
@@ -158,6 +184,7 @@ public class WiredConditionTriggerOnFurni extends InteractionWiredCondition {
int[] params = settings.getIntParams();
this.furniSource = (params.length > 0) ? params[0] : WiredSourceUtil.SOURCE_TRIGGER;
this.userSource = (params.length > 1) ? params[1] : WiredSourceUtil.SOURCE_TRIGGER;
+ this.quantifier = (params.length > 2) ? this.normalizeQuantifier(params[2]) : QUANTIFIER_ALL;
this.items.clear();
@@ -194,6 +221,14 @@ public class WiredConditionTriggerOnFurni extends InteractionWiredCondition {
this.items.removeAll(items);
}
+ protected int getQuantifier() {
+ return this.quantifier;
+ }
+
+ protected int normalizeQuantifier(int value) {
+ return (value == QUANTIFIER_ANY) ? QUANTIFIER_ANY : QUANTIFIER_ALL;
+ }
+
@Override
public WiredConditionOperator operator() {
return WiredConditionOperator.AND;
@@ -203,11 +238,13 @@ public class WiredConditionTriggerOnFurni extends InteractionWiredCondition {
List itemIds;
int furniSource;
int userSource;
+ int quantifier;
- public JsonData(List itemIds, int furniSource, int userSource) {
+ public JsonData(List itemIds, int furniSource, int userSource, int quantifier) {
this.itemIds = itemIds;
this.furniSource = furniSource;
this.userSource = userSource;
+ this.quantifier = quantifier;
}
}
}
diff --git a/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectAdjustClock.java b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectAdjustClock.java
new file mode 100644
index 00000000..183eec7d
--- /dev/null
+++ b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectAdjustClock.java
@@ -0,0 +1,252 @@
+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.games.InteractionGameUpCounter;
+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.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 WiredEffectAdjustClock extends InteractionWiredEffect {
+ private static final int OPERATOR_INCREASE = 0;
+ private static final int OPERATOR_DECREASE = 1;
+ private static final int OPERATOR_SET = 2;
+ private static final int MAX_MINUTES = 99;
+ private static final int MAX_HALF_SECOND_STEPS = 119;
+
+ public static final WiredEffectType type = WiredEffectType.ADJUST_CLOCK;
+
+ private final List items = new ArrayList<>();
+ private int operator = OPERATOR_SET;
+ private int furniSource = WiredSourceUtil.SOURCE_TRIGGER;
+ private int minutes = 0;
+ private int halfSecondSteps = 0;
+
+ public WiredEffectAdjustClock(ResultSet set, Item baseItem) throws SQLException {
+ super(set, baseItem);
+ }
+
+ public WiredEffectAdjustClock(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 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 instanceof InteractionGameUpCounter)) {
+ continue;
+ }
+
+ ((InteractionGameUpCounter) item).adjustCounter(room, this.operator, this.minutes, this.halfSecondSteps);
+ }
+ }
+
+ @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.furniSource,
+ this.minutes,
+ this.halfSecondSteps
+ ));
+ }
+
+ @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.furniSource = data.furniSource;
+ this.minutes = this.normalizeMinutes(data.minutes);
+ this.halfSecondSteps = this.normalizeHalfSecondSteps(data.halfSecondSteps);
+
+ 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.furniSource = WiredSourceUtil.SOURCE_TRIGGER;
+ this.minutes = 0;
+ this.halfSecondSteps = 0;
+ this.setDelay(0);
+ }
+
+ @Override
+ public void onPickUp() {
+ this.items.clear();
+ this.operator = OPERATOR_SET;
+ this.furniSource = WiredSourceUtil.SOURCE_TRIGGER;
+ this.minutes = 0;
+ this.halfSecondSteps = 0;
+ this.setDelay(0);
+ }
+
+ @Override
+ public WiredEffectType getType() {
+ return type;
+ }
+
+ @Override
+ public void serializeWiredData(ServerMessage message, Room room) {
+ List 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(4);
+ message.appendInt(this.operator);
+ message.appendInt(this.furniSource);
+ message.appendInt(this.minutes);
+ message.appendInt(this.halfSecondSteps);
+ 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 < 4) {
+ throw new WiredSaveException("Invalid data");
+ }
+
+ this.operator = this.normalizeOperator(params[0]);
+ this.furniSource = params[1];
+ this.minutes = this.normalizeMinutes(params[2]);
+ this.halfSecondSteps = this.normalizeHalfSecondSteps(params[3]);
+
+ 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 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));
+ }
+
+ if (!(item instanceof InteractionGameUpCounter)) {
+ throw new WiredSaveException("wiredfurni.error.require_counter_furni");
+ }
+
+ newItems.add(item);
+ }
+
+ 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 int normalizeMinutes(int value) {
+ return Math.max(0, Math.min(MAX_MINUTES, value));
+ }
+
+ private int normalizeHalfSecondSteps(int value) {
+ return Math.max(0, Math.min(MAX_HALF_SECOND_STEPS, value));
+ }
+
+ static class JsonData {
+ int delay;
+ List itemIds;
+ int operator;
+ int furniSource;
+ int minutes;
+ int halfSecondSteps;
+
+ public JsonData(int delay, List itemIds, int operator, int furniSource, int minutes, int halfSecondSteps) {
+ this.delay = delay;
+ this.itemIds = itemIds;
+ this.operator = operator;
+ this.furniSource = furniSource;
+ this.minutes = minutes;
+ this.halfSecondSteps = halfSecondSteps;
+ }
+ }
+}
diff --git a/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectBotClothes.java b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectBotClothes.java
index 6cc5af2b..345fbb0c 100644
--- a/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectBotClothes.java
+++ b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectBotClothes.java
@@ -9,6 +9,7 @@ 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.WiredBotSourceUtil;
import com.eu.habbo.habbohotel.wired.core.WiredContext;
import com.eu.habbo.habbohotel.wired.core.WiredManager;
import com.eu.habbo.messages.ServerMessage;
@@ -24,6 +25,7 @@ public class WiredEffectBotClothes extends InteractionWiredEffect {
private String botName = "";
private String botLook = "";
+ private int botSource = WiredBotSourceUtil.SOURCE_BOT_NAME;
public WiredEffectBotClothes(ResultSet set, Item baseItem) throws SQLException {
super(set, baseItem);
@@ -41,7 +43,8 @@ public class WiredEffectBotClothes extends InteractionWiredEffect {
message.appendInt(this.getBaseItem().getSpriteId());
message.appendInt(this.getId());
message.appendString(this.botName + ((char) 9) + "" + this.botLook);
- message.appendInt(0);
+ message.appendInt(1);
+ message.appendInt(this.botSource);
message.appendInt(0);
message.appendInt(this.getType().code);
message.appendInt(this.getDelay());
@@ -65,6 +68,7 @@ public class WiredEffectBotClothes extends InteractionWiredEffect {
if (data.length != 2)
throw new WiredSaveException("Malformed data string. Invalid data length");
+ this.botSource = (settings.getIntParams().length > 0) ? WiredBotSourceUtil.normalizeBotSource(settings.getIntParams()[0]) : WiredBotSourceUtil.SOURCE_BOT_NAME;
this.botName = data[0].substring(0, Math.min(data[0].length(), Emulator.getConfig().getInt("hotel.wired.message.max_length", 100)));
this.botLook = data[1];
this.setDelay(delay);
@@ -80,10 +84,9 @@ public class WiredEffectBotClothes extends InteractionWiredEffect {
@Override
public void execute(WiredContext ctx) {
Room room = ctx.room();
- List bots = room.getBots(this.botName);
+ List bots = WiredBotSourceUtil.resolveBots(ctx, room, this.botSource, this.botName);
- if (bots.size() == 1) {
- Bot bot = bots.get(0);
+ for (Bot bot : bots) {
bot.setFigure(this.botLook);
}
}
@@ -96,7 +99,7 @@ public class WiredEffectBotClothes extends InteractionWiredEffect {
@Override
public String getWiredData() {
- return WiredManager.getGson().toJson(new JsonData(this.botName, this.botLook, this.getDelay()));
+ return WiredManager.getGson().toJson(new JsonData(this.botName, this.botLook, this.getDelay(), this.botSource));
}
@Override
@@ -108,6 +111,9 @@ public class WiredEffectBotClothes extends InteractionWiredEffect {
this.setDelay(data.delay);
this.botName = data.bot_name;
this.botLook = data.look;
+ this.botSource = (data.botSource != null)
+ ? WiredBotSourceUtil.normalizeBotSource(data.botSource)
+ : WiredBotSourceUtil.SOURCE_BOT_NAME;
}
else {
String[] data = wiredData.split(((char) 9) + "");
@@ -119,6 +125,7 @@ public class WiredEffectBotClothes extends InteractionWiredEffect {
}
this.needsUpdate(true);
+ this.botSource = WiredBotSourceUtil.SOURCE_BOT_NAME;
}
}
@@ -126,9 +133,15 @@ public class WiredEffectBotClothes extends InteractionWiredEffect {
public void onPickUp() {
this.botLook = "";
this.botName = "";
+ this.botSource = WiredBotSourceUtil.SOURCE_BOT_NAME;
this.setDelay(0);
}
+ @Override
+ public boolean requiresTriggeringUser() {
+ return WiredBotSourceUtil.requiresTriggeringUser(this.botSource);
+ }
+
public String getBotName() {
return this.botName;
}
@@ -149,11 +162,13 @@ public class WiredEffectBotClothes extends InteractionWiredEffect {
String bot_name;
String look;
int delay;
+ Integer botSource;
- public JsonData(String bot_name, String look, int delay) {
+ public JsonData(String bot_name, String look, int delay, int botSource) {
this.bot_name = bot_name;
this.look = look;
this.delay = delay;
+ this.botSource = botSource;
}
}
}
diff --git a/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectBotFollowHabbo.java b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectBotFollowHabbo.java
index 6bdb028d..a1a80fe7 100644
--- a/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectBotFollowHabbo.java
+++ b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectBotFollowHabbo.java
@@ -11,6 +11,7 @@ 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.WiredEffectType;
+import com.eu.habbo.habbohotel.wired.core.WiredBotSourceUtil;
import com.eu.habbo.habbohotel.wired.core.WiredContext;
import com.eu.habbo.habbohotel.wired.core.WiredManager;
import com.eu.habbo.habbohotel.wired.core.WiredSourceUtil;
@@ -29,6 +30,7 @@ public class WiredEffectBotFollowHabbo extends InteractionWiredEffect {
private String botName = "";
private int mode = 0;
private int userSource = WiredSourceUtil.SOURCE_TRIGGER;
+ private int botSource = WiredBotSourceUtil.SOURCE_BOT_NAME;
public WiredEffectBotFollowHabbo(ResultSet set, Item baseItem) throws SQLException {
super(set, baseItem);
@@ -46,9 +48,10 @@ public class WiredEffectBotFollowHabbo extends InteractionWiredEffect {
message.appendInt(this.getBaseItem().getSpriteId());
message.appendInt(this.getId());
message.appendString(this.botName);
- message.appendInt(2);
+ message.appendInt(3);
message.appendInt(this.mode);
message.appendInt(this.userSource);
+ message.appendInt(this.botSource);
message.appendInt(1);
message.appendInt(this.getType().code);
message.appendInt(this.getDelay());
@@ -79,6 +82,7 @@ public class WiredEffectBotFollowHabbo extends InteractionWiredEffect {
int mode = settings.getIntParams()[0];
this.userSource = settings.getIntParams()[1];
+ this.botSource = (settings.getIntParams().length > 2) ? WiredBotSourceUtil.normalizeBotSource(settings.getIntParams()[2]) : WiredBotSourceUtil.SOURCE_BOT_NAME;
if(mode != 0 && mode != 1)
throw new WiredSaveException("Mode is invalid");
@@ -111,15 +115,15 @@ public class WiredEffectBotFollowHabbo extends InteractionWiredEffect {
RoomUnit roomUnit = targets.get(0);
Habbo habbo = room.getHabbo(roomUnit);
- List bots = room.getBots(this.botName);
+ List bots = WiredBotSourceUtil.resolveBots(ctx, room, this.botSource, this.botName);
- if (habbo != null && bots.size() == 1) {
- Bot bot = bots.get(0);
-
- if (this.mode == 1) {
- bot.startFollowingHabbo(habbo);
- } else {
- bot.stopFollowingHabbo();
+ if (habbo != null && !bots.isEmpty()) {
+ for (Bot bot : bots) {
+ if (this.mode == 1) {
+ bot.startFollowingHabbo(habbo);
+ } else {
+ bot.stopFollowingHabbo();
+ }
}
}
}
@@ -132,7 +136,7 @@ public class WiredEffectBotFollowHabbo extends InteractionWiredEffect {
@Override
public String getWiredData() {
- return WiredManager.getGson().toJson(new JsonData(this.botName, this.mode, this.getDelay(), this.userSource));
+ return WiredManager.getGson().toJson(new JsonData(this.botName, this.mode, this.getDelay(), this.userSource, this.botSource));
}
@Override
@@ -145,6 +149,9 @@ public class WiredEffectBotFollowHabbo extends InteractionWiredEffect {
this.mode = data.mode;
this.botName = data.bot_name;
this.userSource = data.userSource;
+ this.botSource = (data.botSource != null)
+ ? WiredBotSourceUtil.normalizeBotSource(data.botSource)
+ : WiredBotSourceUtil.SOURCE_BOT_NAME;
}
else {
String[] data = wiredData.split(((char) 9) + "");
@@ -157,6 +164,7 @@ public class WiredEffectBotFollowHabbo extends InteractionWiredEffect {
this.needsUpdate(true);
this.userSource = WiredSourceUtil.SOURCE_TRIGGER;
+ this.botSource = WiredBotSourceUtil.SOURCE_BOT_NAME;
}
}
@@ -165,12 +173,13 @@ public class WiredEffectBotFollowHabbo extends InteractionWiredEffect {
this.botName = "";
this.mode = 0;
this.userSource = WiredSourceUtil.SOURCE_TRIGGER;
+ this.botSource = WiredBotSourceUtil.SOURCE_BOT_NAME;
this.setDelay(0);
}
@Override
public boolean requiresTriggeringUser() {
- return this.userSource == WiredSourceUtil.SOURCE_TRIGGER;
+ return this.userSource == WiredSourceUtil.SOURCE_TRIGGER || WiredBotSourceUtil.requiresTriggeringUser(this.botSource);
}
static class JsonData {
@@ -178,12 +187,14 @@ public class WiredEffectBotFollowHabbo extends InteractionWiredEffect {
int mode;
int delay;
int userSource;
+ Integer botSource;
- public JsonData(String bot_name, int mode, int delay, int userSource) {
+ public JsonData(String bot_name, int mode, int delay, int userSource, int botSource) {
this.bot_name = bot_name;
this.mode = mode;
this.delay = delay;
this.userSource = userSource;
+ this.botSource = botSource;
}
}
}
diff --git a/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectBotGiveHandItem.java b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectBotGiveHandItem.java
index c5350555..62fef4e0 100644
--- a/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectBotGiveHandItem.java
+++ b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectBotGiveHandItem.java
@@ -28,10 +28,12 @@ import java.util.List;
public class WiredEffectBotGiveHandItem extends InteractionWiredEffect {
public static final WiredEffectType type = WiredEffectType.BOT_GIVE_HANDITEM;
+ private static final int BOT_SOURCE_NAME = 100;
private String botName = "";
private int itemId;
private int userSource = WiredSourceUtil.SOURCE_TRIGGER;
+ private int botSource = BOT_SOURCE_NAME;
public WiredEffectBotGiveHandItem(ResultSet set, Item baseItem) throws SQLException {
super(set, baseItem);
@@ -49,9 +51,10 @@ public class WiredEffectBotGiveHandItem extends InteractionWiredEffect {
message.appendInt(this.getBaseItem().getSpriteId());
message.appendInt(this.getId());
message.appendString(this.botName);
- message.appendInt(2);
+ message.appendInt(3);
message.appendInt(this.itemId);
message.appendInt(this.userSource);
+ message.appendInt(this.botSource);
message.appendInt(0);
message.appendInt(this.getType().code);
message.appendInt(this.getDelay());
@@ -80,11 +83,9 @@ public class WiredEffectBotGiveHandItem extends InteractionWiredEffect {
public boolean saveData(WiredSettings settings, GameClient gameClient) throws WiredSaveException {
if(settings.getIntParams().length < 2) throw new WiredSaveException("Missing item id");
- int itemId = settings.getIntParams()[0];
- this.userSource = settings.getIntParams()[1];
-
- if(itemId < 0)
- itemId = 0;
+ int itemId = this.normalizeHandItem(settings.getIntParams()[0]);
+ this.userSource = this.normalizeUserSource(settings.getIntParams()[1]);
+ this.botSource = (settings.getIntParams().length > 2) ? this.normalizeBotSource(settings.getIntParams()[2]) : BOT_SOURCE_NAME;
String botName = settings.getStringParam();
@@ -113,10 +114,9 @@ public class WiredEffectBotGiveHandItem extends InteractionWiredEffect {
RoomUnit roomUnit = targets.get(0);
Habbo habbo = room.getHabbo(roomUnit);
- List bots = room.getBots(this.botName);
+ Bot bot = this.resolveBot(ctx, room);
- if (habbo != null && bots.size() == 1) {
- Bot bot = bots.get(0);
+ if (habbo != null && bot != null) {
List tasks = new ArrayList<>();
tasks.add(new RoomUnitGiveHanditem(roomUnit, room, this.itemId));
@@ -146,7 +146,7 @@ public class WiredEffectBotGiveHandItem extends InteractionWiredEffect {
@Override
public String getWiredData() {
- return WiredManager.getGson().toJson(new JsonData(this.botName, this.itemId, this.getDelay(), this.userSource));
+ return WiredManager.getGson().toJson(new JsonData(this.botName, this.itemId, this.getDelay(), this.userSource, this.botSource));
}
@Override
@@ -156,21 +156,25 @@ public class WiredEffectBotGiveHandItem extends InteractionWiredEffect {
if(wiredData.startsWith("{")) {
JsonData data = WiredManager.getGson().fromJson(wiredData, JsonData.class);
this.setDelay(data.delay);
- this.itemId = data.item_id;
+ this.itemId = this.normalizeHandItem(data.item_id);
this.botName = data.bot_name;
- this.userSource = data.userSource;
+ this.userSource = this.normalizeUserSource(data.userSource);
+ this.botSource = ((data.botSource == WiredSourceUtil.SOURCE_TRIGGER) && this.botName != null && !this.botName.isEmpty())
+ ? BOT_SOURCE_NAME
+ : this.normalizeBotSource(data.botSource);
}
else {
String[] data = wiredData.split(((char) 9) + "");
if (data.length == 3) {
this.setDelay(Integer.parseInt(data[0]));
- this.itemId = Integer.parseInt(data[1]);
+ this.itemId = this.normalizeHandItem(Integer.parseInt(data[1]));
this.botName = data[2];
}
this.needsUpdate(true);
this.userSource = WiredSourceUtil.SOURCE_TRIGGER;
+ this.botSource = BOT_SOURCE_NAME;
}
}
@@ -179,12 +183,13 @@ public class WiredEffectBotGiveHandItem extends InteractionWiredEffect {
this.botName = "";
this.itemId = 0;
this.userSource = WiredSourceUtil.SOURCE_TRIGGER;
+ this.botSource = BOT_SOURCE_NAME;
this.setDelay(0);
}
@Override
public boolean requiresTriggeringUser() {
- return this.userSource == WiredSourceUtil.SOURCE_TRIGGER;
+ return (this.userSource == WiredSourceUtil.SOURCE_TRIGGER) || (this.botSource == WiredSourceUtil.SOURCE_TRIGGER);
}
static class JsonData {
@@ -192,12 +197,58 @@ public class WiredEffectBotGiveHandItem extends InteractionWiredEffect {
int item_id;
int delay;
int userSource;
+ int botSource;
- public JsonData(String bot_name, int item_id, int delay, int userSource) {
+ public JsonData(String bot_name, int item_id, int delay, int userSource, int botSource) {
this.bot_name = bot_name;
this.item_id = item_id;
this.delay = delay;
this.userSource = userSource;
+ this.botSource = botSource;
}
}
+
+ private int normalizeHandItem(int value) {
+ return Math.max(0, value);
+ }
+
+ private 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;
+ }
+ }
+
+ private int normalizeBotSource(int value) {
+ switch (value) {
+ case WiredSourceUtil.SOURCE_TRIGGER:
+ case BOT_SOURCE_NAME:
+ case WiredSourceUtil.SOURCE_SELECTOR:
+ case WiredSourceUtil.SOURCE_SIGNAL:
+ return value;
+ default:
+ return BOT_SOURCE_NAME;
+ }
+ }
+
+ private Bot resolveBot(WiredContext ctx, Room room) {
+ if (this.botSource == BOT_SOURCE_NAME) {
+ List bots = room.getBots(this.botName);
+ return (bots.size() == 1) ? bots.get(0) : null;
+ }
+
+ for (RoomUnit roomUnit : WiredSourceUtil.resolveUsers(ctx, this.botSource)) {
+ Bot bot = room.getBot(roomUnit);
+
+ if (bot != null) {
+ return bot;
+ }
+ }
+
+ return null;
+ }
}
diff --git a/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectBotTalk.java b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectBotTalk.java
index 8301f508..dfb0aa88 100644
--- a/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectBotTalk.java
+++ b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectBotTalk.java
@@ -10,6 +10,7 @@ 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.WiredEffectType;
+import com.eu.habbo.habbohotel.wired.core.WiredBotSourceUtil;
import com.eu.habbo.habbohotel.wired.core.WiredManager;
import com.eu.habbo.habbohotel.wired.core.WiredContext;
import com.eu.habbo.messages.ServerMessage;
@@ -26,6 +27,7 @@ public class WiredEffectBotTalk extends InteractionWiredEffect {
private int mode;
private String botName = "";
private String message = "";
+ private int botSource = WiredBotSourceUtil.SOURCE_BOT_NAME;
public WiredEffectBotTalk(ResultSet set, Item baseItem) throws SQLException {
super(set, baseItem);
@@ -43,8 +45,9 @@ public class WiredEffectBotTalk extends InteractionWiredEffect {
message.appendInt(this.getBaseItem().getSpriteId());
message.appendInt(this.getId());
message.appendString(this.botName + "" + ((char) 9) + "" + this.message);
- message.appendInt(1);
+ message.appendInt(2);
message.appendInt(this.mode);
+ message.appendInt(this.botSource);
message.appendInt(0);
message.appendInt(this.getType().code);
message.appendInt(this.getDelay());
@@ -55,6 +58,7 @@ public class WiredEffectBotTalk extends InteractionWiredEffect {
public boolean saveData(WiredSettings settings, GameClient gameClient) throws WiredSaveException {
if(settings.getIntParams().length < 1) throw new WiredSaveException("Mode is invalid");
int mode = settings.getIntParams()[0];
+ this.botSource = (settings.getIntParams().length > 1) ? WiredBotSourceUtil.normalizeBotSource(settings.getIntParams()[1]) : WiredBotSourceUtil.SOURCE_BOT_NAME;
if(mode != 0 && mode != 1)
throw new WiredSaveException("Mode is invalid");
@@ -103,21 +107,20 @@ public class WiredEffectBotTalk extends InteractionWiredEffect {
.replace(Emulator.getTexts().getValue("wired.variable.points", "%points%"), habbo.getHabboInfo().getCurrencyAmount(Emulator.getConfig().getInt("seasonal.primary.type")) + "")
.replace(Emulator.getTexts().getValue("wired.variable.owner", "%owner%"), room.getOwnerName())
.replace(Emulator.getTexts().getValue("wired.variable.item_count", "%item_count%"), room.itemCount() + "")
- .replace(Emulator.getTexts().getValue("wired.variable.name", "%name%"), this.botName)
.replace(Emulator.getTexts().getValue("wired.variable.roomname", "%roomname%"), room.getName())
.replace(Emulator.getTexts().getValue("wired.variable.user_count", "%user_count%"), room.getUserCount() + "");
}
- List bots = room.getBots(this.botName);
+ List bots = WiredBotSourceUtil.resolveBots(ctx, room, this.botSource, this.botName);
- if (bots.size() == 1) {
- Bot bot = bots.get(0);
+ for (Bot bot : bots) {
+ String botMessage = message.replace(Emulator.getTexts().getValue("wired.variable.name", "%name%"), bot.getName());
- if(!WiredManager.triggerUserSays(room, bot.getRoomUnit(), message)) {
+ if(!WiredManager.triggerUserSays(room, bot.getRoomUnit(), botMessage)) {
if (this.mode == 1) {
- bot.shout(message);
+ bot.shout(botMessage);
} else {
- bot.talk(message);
+ bot.talk(botMessage);
}
}
}
@@ -131,7 +134,7 @@ public class WiredEffectBotTalk extends InteractionWiredEffect {
@Override
public String getWiredData() {
- return WiredManager.getGson().toJson(new JsonData(this.botName, this.mode, this.message, this.getDelay()));
+ return WiredManager.getGson().toJson(new JsonData(this.botName, this.mode, this.message, this.getDelay(), this.botSource));
}
@Override
@@ -144,6 +147,9 @@ public class WiredEffectBotTalk extends InteractionWiredEffect {
this.mode = data.mode;
this.botName = data.bot_name;
this.message = data.message;
+ this.botSource = (data.botSource != null)
+ ? WiredBotSourceUtil.normalizeBotSource(data.botSource)
+ : WiredBotSourceUtil.SOURCE_BOT_NAME;
}
else {
String[] data = wiredData.split(((char) 9) + "");
@@ -156,6 +162,7 @@ public class WiredEffectBotTalk extends InteractionWiredEffect {
}
this.needsUpdate(true);
+ this.botSource = WiredBotSourceUtil.SOURCE_BOT_NAME;
}
}
@@ -164,9 +171,15 @@ public class WiredEffectBotTalk extends InteractionWiredEffect {
this.mode = 0;
this.botName = "";
this.message = "";
+ this.botSource = WiredBotSourceUtil.SOURCE_BOT_NAME;
this.setDelay(0);
}
+ @Override
+ public boolean requiresTriggeringUser() {
+ return WiredBotSourceUtil.requiresTriggeringUser(this.botSource);
+ }
+
public int getMode() {
return this.mode;
}
@@ -201,12 +214,14 @@ public class WiredEffectBotTalk extends InteractionWiredEffect {
int mode;
String message;
int delay;
+ Integer botSource;
- public JsonData(String bot_name, int mode, String message, int delay) {
+ public JsonData(String bot_name, int mode, String message, int delay, int botSource) {
this.bot_name = bot_name;
this.mode = mode;
this.message = message;
this.delay = delay;
+ this.botSource = botSource;
}
}
}
diff --git a/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectBotTalkToHabbo.java b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectBotTalkToHabbo.java
index c7dc2eb5..3532b276 100644
--- a/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectBotTalkToHabbo.java
+++ b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectBotTalkToHabbo.java
@@ -11,6 +11,7 @@ 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.WiredEffectType;
+import com.eu.habbo.habbohotel.wired.core.WiredBotSourceUtil;
import com.eu.habbo.habbohotel.wired.core.WiredManager;
import com.eu.habbo.habbohotel.wired.core.WiredContext;
import com.eu.habbo.habbohotel.wired.core.WiredSourceUtil;
@@ -31,6 +32,7 @@ public class WiredEffectBotTalkToHabbo extends InteractionWiredEffect {
private String botName = "";
private String message = "";
private int userSource = WiredSourceUtil.SOURCE_TRIGGER;
+ private int botSource = WiredBotSourceUtil.SOURCE_BOT_NAME;
public WiredEffectBotTalkToHabbo(ResultSet set, Item baseItem) throws SQLException {
super(set, baseItem);
@@ -48,9 +50,10 @@ public class WiredEffectBotTalkToHabbo extends InteractionWiredEffect {
message.appendInt(this.getBaseItem().getSpriteId());
message.appendInt(this.getId());
message.appendString(this.botName + "" + ((char) 9) + "" + this.message);
- message.appendInt(2);
+ message.appendInt(3);
message.appendInt(this.mode);
message.appendInt(this.userSource);
+ message.appendInt(this.botSource);
message.appendInt(0);
message.appendInt(this.getType().code);
message.appendInt(this.getDelay());
@@ -80,6 +83,7 @@ public class WiredEffectBotTalkToHabbo extends InteractionWiredEffect {
if(settings.getIntParams().length < 2) throw new WiredSaveException("Missing mode");
int mode = settings.getIntParams()[0];
this.userSource = settings.getIntParams()[1];
+ this.botSource = (settings.getIntParams().length > 2) ? WiredBotSourceUtil.normalizeBotSource(settings.getIntParams()[2]) : WiredBotSourceUtil.SOURCE_BOT_NAME;
if(mode != 0 && mode != 1)
throw new WiredSaveException("Mode is invalid");
@@ -116,9 +120,8 @@ public class WiredEffectBotTalkToHabbo extends InteractionWiredEffect {
public void execute(WiredContext ctx) {
Room room = ctx.room();
- List bots = room.getBots(this.botName);
- if (bots.size() != 1) return;
- Bot bot = bots.get(0);
+ List bots = WiredBotSourceUtil.resolveBots(ctx, room, this.botSource, this.botName);
+ if (bots.isEmpty()) return;
for (RoomUnit roomUnit : WiredSourceUtil.resolveUsers(ctx, this.userSource)) {
Habbo habbo = room.getHabbo(roomUnit);
@@ -131,15 +134,18 @@ public class WiredEffectBotTalkToHabbo extends InteractionWiredEffect {
.replace(Emulator.getTexts().getValue("wired.variable.points", "%points%"), habbo.getHabboInfo().getCurrencyAmount(Emulator.getConfig().getInt("seasonal.primary.type")) + "")
.replace(Emulator.getTexts().getValue("wired.variable.owner", "%owner%"), room.getOwnerName())
.replace(Emulator.getTexts().getValue("wired.variable.item_count", "%item_count%"), room.itemCount() + "")
- .replace(Emulator.getTexts().getValue("wired.variable.name", "%name%"), this.botName)
.replace(Emulator.getTexts().getValue("wired.variable.roomname", "%roomname%"), room.getName())
.replace(Emulator.getTexts().getValue("wired.variable.user_count", "%user_count%"), room.getUserCount() + "");
- if (!WiredManager.triggerUserSays(room, bot.getRoomUnit(), m)) {
- if (this.mode == 1) {
- bot.whisper(m, habbo);
- } else {
- bot.talk(habbo.getHabboInfo().getUsername() + ": " + m);
+ for (Bot bot : bots) {
+ String botMessage = m.replace(Emulator.getTexts().getValue("wired.variable.name", "%name%"), bot.getName());
+
+ if (!WiredManager.triggerUserSays(room, bot.getRoomUnit(), botMessage)) {
+ if (this.mode == 1) {
+ bot.whisper(botMessage, habbo);
+ } else {
+ bot.talk(habbo.getHabboInfo().getUsername() + ": " + botMessage);
+ }
}
}
}
@@ -153,7 +159,7 @@ public class WiredEffectBotTalkToHabbo extends InteractionWiredEffect {
@Override
public String getWiredData() {
- return WiredManager.getGson().toJson(new JsonData(this.botName, this.mode, this.message, this.getDelay(), this.userSource));
+ return WiredManager.getGson().toJson(new JsonData(this.botName, this.mode, this.message, this.getDelay(), this.userSource, this.botSource));
}
@Override
@@ -167,6 +173,7 @@ public class WiredEffectBotTalkToHabbo extends InteractionWiredEffect {
this.botName = data.bot_name;
this.message = data.message;
this.userSource = data.userSource;
+ this.botSource = (data.botSource != null) ? WiredBotSourceUtil.normalizeBotSource(data.botSource) : WiredBotSourceUtil.SOURCE_BOT_NAME;
}
else {
String[] data = wiredData.split(((char) 9) + "");
@@ -180,6 +187,7 @@ public class WiredEffectBotTalkToHabbo extends InteractionWiredEffect {
this.needsUpdate(true);
this.userSource = WiredSourceUtil.SOURCE_TRIGGER;
+ this.botSource = WiredBotSourceUtil.SOURCE_BOT_NAME;
}
}
@@ -189,12 +197,13 @@ public class WiredEffectBotTalkToHabbo extends InteractionWiredEffect {
this.message = "";
this.mode = 0;
this.userSource = WiredSourceUtil.SOURCE_TRIGGER;
+ this.botSource = WiredBotSourceUtil.SOURCE_BOT_NAME;
this.setDelay(0);
}
@Override
public boolean requiresTriggeringUser() {
- return this.userSource == WiredSourceUtil.SOURCE_TRIGGER;
+ return this.userSource == WiredSourceUtil.SOURCE_TRIGGER || WiredBotSourceUtil.requiresTriggeringUser(this.botSource);
}
static class JsonData {
@@ -203,13 +212,15 @@ public class WiredEffectBotTalkToHabbo extends InteractionWiredEffect {
String message;
int delay;
int userSource;
+ Integer botSource;
- public JsonData(String bot_name, int mode, String message, int delay, int userSource) {
+ public JsonData(String bot_name, int mode, String message, int delay, int userSource, int botSource) {
this.bot_name = bot_name;
this.mode = mode;
this.message = message;
this.delay = delay;
this.userSource = userSource;
+ this.botSource = botSource;
}
}
}
diff --git a/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectBotTeleport.java b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectBotTeleport.java
index 650877d7..582a8f19 100644
--- a/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectBotTeleport.java
+++ b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectBotTeleport.java
@@ -12,6 +12,7 @@ import com.eu.habbo.habbohotel.rooms.RoomTileState;
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.WiredBotSourceUtil;
import com.eu.habbo.habbohotel.wired.core.WiredContext;
import com.eu.habbo.habbohotel.wired.core.WiredManager;
import com.eu.habbo.habbohotel.wired.core.WiredSourceUtil;
@@ -34,6 +35,7 @@ public class WiredEffectBotTeleport extends InteractionWiredEffect {
private THashSet items;
private String botName = "";
private int furniSource = WiredSourceUtil.SOURCE_TRIGGER;
+ private int botSource = WiredBotSourceUtil.SOURCE_BOT_NAME;
public WiredEffectBotTeleport(ResultSet set, Item baseItem) throws SQLException {
super(set, baseItem);
@@ -110,8 +112,9 @@ public class WiredEffectBotTeleport extends InteractionWiredEffect {
message.appendInt(this.getBaseItem().getSpriteId());
message.appendInt(this.getId());
message.appendString(this.botName);
- message.appendInt(1);
+ message.appendInt(2);
message.appendInt(this.furniSource);
+ message.appendInt(this.botSource);
message.appendInt(0);
message.appendInt(this.getType().code);
message.appendInt(this.getDelay());
@@ -123,6 +126,7 @@ public class WiredEffectBotTeleport extends InteractionWiredEffect {
String botName = settings.getStringParam();
int[] params = settings.getIntParams();
this.furniSource = (params.length > 0) ? params[0] : WiredSourceUtil.SOURCE_TRIGGER;
+ this.botSource = (params.length > 1) ? WiredBotSourceUtil.normalizeBotSource(params[1]) : WiredBotSourceUtil.SOURCE_BOT_NAME;
int itemsCount = settings.getFurniIds().length;
if(itemsCount > Emulator.getConfig().getInt("hotel.wired.furni.selection.count")) {
@@ -177,20 +181,20 @@ public class WiredEffectBotTeleport extends InteractionWiredEffect {
if (validItems.isEmpty()) return;
if (room.getLayout() == null) return;
- List bots = room.getBots(this.botName);
+ List bots = WiredBotSourceUtil.resolveBots(ctx, room, this.botSource, this.botName);
- if (bots.size() != 1) {
+ if (bots.isEmpty()) {
return;
}
- Bot bot = bots.get(0);
+ for (Bot bot : bots) {
+ HabboItem targetItem = validItems.get(Emulator.getRandom().nextInt(validItems.size()));
- HabboItem targetItem = validItems.get(Emulator.getRandom().nextInt(validItems.size()));
-
- if (targetItem.getRoomId() == bot.getRoom().getId()) {
- RoomTile tile = room.getLayout().getTile(targetItem.getX(), targetItem.getY());
- if (tile != null) {
- teleportUnitToTile(bot.getRoomUnit(), tile);
+ if (targetItem.getRoomId() == bot.getRoom().getId()) {
+ RoomTile tile = room.getLayout().getTile(targetItem.getX(), targetItem.getY());
+ if (tile != null) {
+ teleportUnitToTile(bot.getRoomUnit(), tile);
+ }
}
}
}
@@ -214,7 +218,7 @@ public class WiredEffectBotTeleport extends InteractionWiredEffect {
}
}
- return WiredManager.getGson().toJson(new JsonData(this.botName, itemIds, this.getDelay(), this.furniSource));
+ return WiredManager.getGson().toJson(new JsonData(this.botName, itemIds, this.getDelay(), this.furniSource, this.botSource));
}
@Override
@@ -228,6 +232,9 @@ public class WiredEffectBotTeleport extends InteractionWiredEffect {
this.setDelay(data.delay);
this.botName = data.bot_name;
this.furniSource = data.furniSource;
+ this.botSource = (data.botSource != null)
+ ? WiredBotSourceUtil.normalizeBotSource(data.botSource)
+ : WiredBotSourceUtil.SOURCE_BOT_NAME;
for(int itemId : data.items) {
HabboItem item = room.getHabboItem(itemId);
@@ -260,6 +267,7 @@ public class WiredEffectBotTeleport extends InteractionWiredEffect {
this.needsUpdate(true);
this.furniSource = this.items.isEmpty() ? WiredSourceUtil.SOURCE_TRIGGER : WiredSourceUtil.SOURCE_SELECTED;
+ this.botSource = WiredBotSourceUtil.SOURCE_BOT_NAME;
}
}
@@ -268,20 +276,28 @@ public class WiredEffectBotTeleport extends InteractionWiredEffect {
this.botName = "";
this.items.clear();
this.furniSource = WiredSourceUtil.SOURCE_TRIGGER;
+ this.botSource = WiredBotSourceUtil.SOURCE_BOT_NAME;
this.setDelay(0);
}
+ @Override
+ public boolean requiresTriggeringUser() {
+ return WiredBotSourceUtil.requiresTriggeringUser(this.botSource);
+ }
+
static class JsonData {
String bot_name;
List items;
int delay;
int furniSource;
+ Integer botSource;
- public JsonData(String bot_name, List items, int delay, int furniSource) {
+ public JsonData(String bot_name, List items, int delay, int furniSource, int botSource) {
this.bot_name = bot_name;
this.items = items;
this.delay = delay;
this.furniSource = furniSource;
+ this.botSource = botSource;
}
}
}
diff --git a/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectBotWalkToFurni.java b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectBotWalkToFurni.java
index b8a2f059..bb345e12 100644
--- a/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectBotWalkToFurni.java
+++ b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectBotWalkToFurni.java
@@ -10,6 +10,7 @@ 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.WiredEffectType;
+import com.eu.habbo.habbohotel.wired.core.WiredBotSourceUtil;
import com.eu.habbo.habbohotel.wired.core.WiredContext;
import com.eu.habbo.habbohotel.wired.core.WiredManager;
import com.eu.habbo.habbohotel.wired.core.WiredSourceUtil;
@@ -29,6 +30,7 @@ public class WiredEffectBotWalkToFurni extends InteractionWiredEffect {
private List items;
private String botName = "";
private int furniSource = WiredSourceUtil.SOURCE_TRIGGER;
+ private int botSource = WiredBotSourceUtil.SOURCE_BOT_NAME;
public WiredEffectBotWalkToFurni(ResultSet set, Item baseItem) throws SQLException {
super(set, baseItem);
@@ -62,8 +64,9 @@ public class WiredEffectBotWalkToFurni extends InteractionWiredEffect {
message.appendInt(this.getBaseItem().getSpriteId());
message.appendInt(this.getId());
message.appendString(this.botName);
- message.appendInt(1);
+ message.appendInt(2);
message.appendInt(this.furniSource);
+ message.appendInt(this.botSource);
message.appendInt(0);
message.appendInt(this.getType().code);
message.appendInt(this.getDelay());
@@ -75,6 +78,7 @@ public class WiredEffectBotWalkToFurni extends InteractionWiredEffect {
String botName = settings.getStringParam();
int[] params = settings.getIntParams();
this.furniSource = (params.length > 0) ? params[0] : WiredSourceUtil.SOURCE_TRIGGER;
+ this.botSource = (params.length > 1) ? WiredBotSourceUtil.normalizeBotSource(params[1]) : WiredBotSourceUtil.SOURCE_BOT_NAME;
int itemsCount = settings.getFurniIds().length;
if(itemsCount > Emulator.getConfig().getInt("hotel.wired.furni.selection.count")) {
@@ -118,32 +122,30 @@ public class WiredEffectBotWalkToFurni extends InteractionWiredEffect {
@Override
public void execute(WiredContext ctx) {
Room room = ctx.room();
- List bots = room.getBots(this.botName);
+ List bots = WiredBotSourceUtil.resolveBots(ctx, room, this.botSource, this.botName);
List effectiveItems = WiredSourceUtil.resolveItems(ctx, this.furniSource, this.items);
if (this.furniSource == WiredSourceUtil.SOURCE_SELECTED) {
this.items.removeIf(item -> item == null || item.getRoomId() != this.getRoomId() || Emulator.getGameEnvironment().getRoomManager().getRoom(this.getRoomId()).getHabboItem(item.getId()) == null);
}
- if (effectiveItems.isEmpty() || bots.size() != 1) {
+ if (effectiveItems.isEmpty() || bots.isEmpty()) {
return;
}
- Bot bot = bots.get(0);
+ for (Bot bot : bots) {
+ List possibleItems = effectiveItems.stream()
+ .filter(item -> !room.getBotsOnItem(item).contains(bot))
+ .collect(Collectors.toList());
- // Bots shouldn't walk to the tile they are already standing on
- List possibleItems = effectiveItems.stream()
- .filter(item -> !room.getBotsOnItem(item).contains(bot))
- .collect(Collectors.toList());
+ if (possibleItems.isEmpty()) {
+ continue;
+ }
- // Get a random tile of possible tiles to walk to
- if (possibleItems.size() > 0) {
HabboItem item = possibleItems.get(Emulator.getRandom().nextInt(possibleItems.size()));
- if (item.getRoomId() != 0 && item.getRoomId() == bot.getRoom().getId()) {
- if (room.getLayout() != null) {
- bot.getRoomUnit().setGoalLocation(room.getLayout().getTile(item.getX(), item.getY()));
- }
+ if (item.getRoomId() != 0 && item.getRoomId() == bot.getRoom().getId() && room.getLayout() != null) {
+ bot.getRoomUnit().setGoalLocation(room.getLayout().getTile(item.getX(), item.getY()));
}
}
}
@@ -166,7 +168,7 @@ public class WiredEffectBotWalkToFurni extends InteractionWiredEffect {
}
}
- return WiredManager.getGson().toJson(new JsonData(this.botName, itemIds, this.getDelay(), this.furniSource));
+ return WiredManager.getGson().toJson(new JsonData(this.botName, itemIds, this.getDelay(), this.furniSource, this.botSource));
}
@Override
@@ -180,6 +182,9 @@ public class WiredEffectBotWalkToFurni extends InteractionWiredEffect {
this.setDelay(data.delay);
this.botName = data.bot_name;
this.furniSource = data.furniSource;
+ this.botSource = (data.botSource != null)
+ ? WiredBotSourceUtil.normalizeBotSource(data.botSource)
+ : WiredBotSourceUtil.SOURCE_BOT_NAME;
for(int itemId : data.items) {
HabboItem item = room.getHabboItem(itemId);
@@ -212,6 +217,7 @@ public class WiredEffectBotWalkToFurni extends InteractionWiredEffect {
this.needsUpdate(true);
this.furniSource = this.items.isEmpty() ? WiredSourceUtil.SOURCE_TRIGGER : WiredSourceUtil.SOURCE_SELECTED;
+ this.botSource = WiredBotSourceUtil.SOURCE_BOT_NAME;
}
}
@@ -220,20 +226,28 @@ public class WiredEffectBotWalkToFurni extends InteractionWiredEffect {
this.items.clear();
this.botName = "";
this.furniSource = WiredSourceUtil.SOURCE_TRIGGER;
+ this.botSource = WiredBotSourceUtil.SOURCE_BOT_NAME;
this.setDelay(0);
}
+ @Override
+ public boolean requiresTriggeringUser() {
+ return WiredBotSourceUtil.requiresTriggeringUser(this.botSource);
+ }
+
static class JsonData {
String bot_name;
List items;
int delay;
int furniSource;
+ Integer botSource;
- public JsonData(String bot_name, List items, int delay, int furniSource) {
+ public JsonData(String bot_name, List items, int delay, int furniSource, int botSource) {
this.bot_name = bot_name;
this.items = items;
this.delay = delay;
this.furniSource = furniSource;
+ this.botSource = botSource;
}
}
}
diff --git a/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectChangeFurniDirection.java b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectChangeFurniDirection.java
index 529f206b..611b06d1 100644
--- a/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectChangeFurniDirection.java
+++ b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectChangeFurniDirection.java
@@ -10,10 +10,10 @@ import com.eu.habbo.habbohotel.users.HabboItem;
import com.eu.habbo.habbohotel.wired.*;
import com.eu.habbo.habbohotel.wired.core.WiredContext;
import com.eu.habbo.habbohotel.wired.core.WiredManager;
+import com.eu.habbo.habbohotel.wired.core.WiredMoveCarryHelper;
import com.eu.habbo.habbohotel.wired.core.WiredSourceUtil;
import com.eu.habbo.messages.ServerMessage;
import com.eu.habbo.messages.incoming.wired.WiredSaveException;
-import com.eu.habbo.messages.outgoing.rooms.items.FloorItemOnRollerComposer;
import gnu.trove.map.hash.THashMap;
import gnu.trove.set.hash.THashSet;
@@ -22,6 +22,7 @@ import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
public class WiredEffectChangeFurniDirection extends InteractionWiredEffect {
public static final int ACTION_WAIT = 0;
@@ -35,9 +36,11 @@ public class WiredEffectChangeFurniDirection extends InteractionWiredEffect {
public static final WiredEffectType type = WiredEffectType.MOVE_DIRECTION;
private final THashMap items = new THashMap<>(0);
+ private final ConcurrentHashMap runtimeItems = new ConcurrentHashMap<>();
private RoomUserRotation startRotation = RoomUserRotation.NORTH;
private int blockedAction = 0;
private int furniSource = WiredSourceUtil.SOURCE_TRIGGER;
+ private boolean blockOnUserCollision = false;
public WiredEffectChangeFurniDirection(ResultSet set, Item baseItem) throws SQLException {
super(set, baseItem);
@@ -56,6 +59,7 @@ public class WiredEffectChangeFurniDirection extends InteractionWiredEffect {
THashMap effectiveItems;
if (this.furniSource == WiredSourceUtil.SOURCE_SELECTED) {
+ this.runtimeItems.clear();
THashSet toRemove = new THashSet<>();
for (HabboItem item : this.items.keySet()) {
if (item == null || Emulator.getGameEnvironment().getRoomManager().getRoom(this.getRoomId()).getHabboItem(item.getId()) == null)
@@ -66,10 +70,13 @@ public class WiredEffectChangeFurniDirection extends InteractionWiredEffect {
}
effectiveItems = this.items;
} else {
+ this.pruneRuntimeItems(room);
effectiveItems = new THashMap<>();
for (HabboItem item : resolvedItems) {
if (item != null) {
- WiredChangeDirectionSetting setting = this.items.get(item);
+ WiredChangeDirectionSetting setting = this.runtimeItems.computeIfAbsent(
+ item.getId(),
+ key -> new WiredChangeDirectionSetting(item.getId(), item.getRotation(), this.startRotation));
if (setting == null) {
setting = new WiredChangeDirectionSetting(item.getId(), item.getRotation(), this.startRotation);
}
@@ -90,7 +97,7 @@ public class WiredEffectChangeFurniDirection extends InteractionWiredEffect {
RoomTile targetTile = room.getLayout().getTileInFront(itemTile, entry.getValue().direction.getValue());
int count = 1;
- while ((targetTile == null || targetTile.state == RoomTileState.INVALID || room.furnitureFitsAt(targetTile, item, item.getRotation(), false) != FurnitureMovementError.NONE) && count < 8) {
+ while (this.shouldSearchNextDirection(room, item, targetTile, ctx) && count < 8) {
entry.getValue().direction = this.nextRotation(entry.getValue().direction);
RoomTile tile = room.getLayout().getTileInFront(itemTile, entry.getValue().direction.getValue());
@@ -114,35 +121,30 @@ public class WiredEffectChangeFurniDirection extends InteractionWiredEffect {
RoomTile targetTile = room.getLayout().getTileInFront(itemTile, newDirection);
if(item.getRotation() != entry.getValue().rotation) {
- if(targetTile == null || room.furnitureFitsAt(targetTile, item, entry.getValue().rotation, false) != FurnitureMovementError.NONE)
+ if (targetTile == null || room.furnitureFitsAt(targetTile, item, entry.getValue().rotation, false) != FurnitureMovementError.NONE)
continue;
- room.moveFurniTo(entry.getKey(), targetTile, entry.getValue().rotation, null, true);
+ WiredMoveCarryHelper.moveFurni(room, this, entry.getKey(), targetTile, entry.getValue().rotation, null, true, ctx);
}
if (targetTile == null) continue;
- boolean hasRoomUnits = false;
- THashSet newOccupiedTiles = room.getLayout().getTilesAt(targetTile, item.getBaseItem().getWidth(), item.getBaseItem().getLength(), item.getRotation());
- for(RoomTile tile : newOccupiedTiles) {
- for (RoomUnit _roomUnit : room.getRoomUnits(tile)) {
- hasRoomUnits = true;
- if(_roomUnit.getCurrentLocation() == targetTile) {
- Emulator.getThreading().run(() -> {
- WiredManager.triggerBotCollision(room, _roomUnit);
- });
+ FurnitureMovementError movementError = WiredMoveCarryHelper.getMovementError(room, this, entry.getKey(), targetTile, item.getRotation(), ctx);
+
+ if (movementError == FurnitureMovementError.TILE_HAS_HABBOS
+ || movementError == FurnitureMovementError.TILE_HAS_BOTS
+ || movementError == FurnitureMovementError.TILE_HAS_PETS) {
+ Emulator.getThreading().run(() -> {
+ for (RoomUnit roomUnit : room.getRoomUnits(targetTile)) {
+ WiredManager.triggerBotCollision(room, roomUnit);
break;
}
- }
+ });
}
- if (targetTile.state != RoomTileState.INVALID && room.furnitureFitsAt(targetTile, item, item.getRotation(), false) == FurnitureMovementError.NONE) {
- if (!hasRoomUnits) {
- RoomTile oldLocation = room.getLayout().getTile(entry.getKey().getX(), entry.getKey().getY());
- double oldZ = entry.getKey().getZ();
- if(oldLocation != null && room.moveFurniTo(entry.getKey(), targetTile, item.getRotation(), null, false) == FurnitureMovementError.NONE) {
- room.sendComposer(new FloorItemOnRollerComposer(entry.getKey(), null, oldLocation, oldZ, targetTile, entry.getKey().getZ(), 0, room).compose());
- }
+ if (targetTile.state != RoomTileState.INVALID && movementError == FurnitureMovementError.NONE) {
+ RoomTile oldLocation = room.getLayout().getTile(entry.getKey().getX(), entry.getKey().getY());
+ if (oldLocation != null && WiredMoveCarryHelper.moveFurni(room, this, entry.getKey(), targetTile, item.getRotation(), null, false, ctx) == FurnitureMovementError.NONE) {
}
}
}
@@ -157,13 +159,14 @@ public class WiredEffectChangeFurniDirection extends InteractionWiredEffect {
@Override
public String getWiredData() {
ArrayList settings = new ArrayList<>(this.items.values());
- return WiredManager.getGson().toJson(new JsonData(this.startRotation, this.blockedAction, settings, this.getDelay(), this.furniSource));
+ return WiredManager.getGson().toJson(new JsonData(this.startRotation, this.blockedAction, settings, this.getDelay(), this.furniSource, this.blockOnUserCollision));
}
@Override
public void loadWiredData(ResultSet set, Room room) throws SQLException {
this.items.clear();
+ this.runtimeItems.clear();
String wiredData = set.getString("wired_data");
@@ -173,6 +176,7 @@ public class WiredEffectChangeFurniDirection extends InteractionWiredEffect {
this.startRotation = data.start_direction;
this.blockedAction = data.blocked_action;
this.furniSource = data.furniSource;
+ this.blockOnUserCollision = data.blockOnUserCollision;
for(WiredChangeDirectionSetting setting : data.items) {
HabboItem item = room.getHabboItem(setting.item_id);
@@ -217,6 +221,7 @@ public class WiredEffectChangeFurniDirection extends InteractionWiredEffect {
}
this.furniSource = this.items.isEmpty() ? WiredSourceUtil.SOURCE_TRIGGER : WiredSourceUtil.SOURCE_SELECTED;
+ this.blockOnUserCollision = false;
this.needsUpdate(true);
}
}
@@ -225,9 +230,11 @@ public class WiredEffectChangeFurniDirection extends InteractionWiredEffect {
public void onPickUp() {
this.setDelay(0);
this.items.clear();
+ this.runtimeItems.clear();
this.blockedAction = 0;
this.startRotation = RoomUserRotation.NORTH;
this.furniSource = WiredSourceUtil.SOURCE_TRIGGER;
+ this.blockOnUserCollision = false;
}
@Override
@@ -246,10 +253,11 @@ public class WiredEffectChangeFurniDirection extends InteractionWiredEffect {
message.appendInt(this.getBaseItem().getSpriteId());
message.appendInt(this.getId());
message.appendString("");
- message.appendInt(3);
+ message.appendInt(4);
message.appendInt(this.startRotation != null ? this.startRotation.getValue() : 0);
message.appendInt(this.blockedAction);
message.appendInt(this.furniSource);
+ message.appendInt(this.blockOnUserCollision ? 1 : 0);
message.appendInt(0);
message.appendInt(this.getType().code);
message.appendInt(this.getDelay());
@@ -262,7 +270,7 @@ public class WiredEffectChangeFurniDirection extends InteractionWiredEffect {
int startDirectionInt = settings.getIntParams()[0];
- if(startDirectionInt < 0 || startDirectionInt > 7 || (startDirectionInt % 2) != 0) {
+ if(startDirectionInt < 0 || startDirectionInt > 7) {
throw new WiredSaveException("Start direction is invalid");
}
@@ -270,6 +278,7 @@ public class WiredEffectChangeFurniDirection extends InteractionWiredEffect {
int blockedActionInt = settings.getIntParams()[1];
this.furniSource = settings.getIntParams()[2];
+ this.blockOnUserCollision = settings.getIntParams().length > 3 && settings.getIntParams()[3] == 1;
if(blockedActionInt < 0 || blockedActionInt > 6) {
throw new WiredSaveException("Blocked action is invalid");
@@ -299,6 +308,7 @@ public class WiredEffectChangeFurniDirection extends InteractionWiredEffect {
throw new WiredSaveException("Delay too long");
this.items.clear();
+ this.runtimeItems.clear();
if (this.furniSource == WiredSourceUtil.SOURCE_SELECTED) {
this.items.putAll(newItems);
}
@@ -309,6 +319,31 @@ public class WiredEffectChangeFurniDirection extends InteractionWiredEffect {
return true;
}
+ private void pruneRuntimeItems(Room room) {
+ if (room == null || this.runtimeItems.isEmpty()) {
+ return;
+ }
+
+ this.runtimeItems.entrySet().removeIf(entry -> room.getHabboItem(entry.getKey()) == null);
+ }
+
+ private boolean shouldSearchNextDirection(Room room, HabboItem item, RoomTile targetTile, WiredContext ctx) {
+ if (targetTile == null || targetTile.state == RoomTileState.INVALID) {
+ return true;
+ }
+
+ if (room.furnitureFitsAt(targetTile, item, item.getRotation(), false) != FurnitureMovementError.NONE) {
+ return true;
+ }
+
+ if (this.blockOnUserCollision) {
+ return false;
+ }
+
+ FurnitureMovementError unitCollision = WiredMoveCarryHelper.getMovementError(room, this, item, targetTile, item.getRotation(), ctx);
+ return unitCollision == FurnitureMovementError.TILE_HAS_HABBOS;
+ }
+
private RoomUserRotation nextRotation(RoomUserRotation currentRotation) {
switch (this.blockedAction) {
case ACTION_TURN_BACK:
@@ -340,13 +375,15 @@ public class WiredEffectChangeFurniDirection extends InteractionWiredEffect {
List items;
int delay;
int furniSource;
+ boolean blockOnUserCollision;
- public JsonData(RoomUserRotation start_direction, int blocked_action, List items, int delay, int furniSource) {
+ public JsonData(RoomUserRotation start_direction, int blocked_action, List items, int delay, int furniSource, boolean blockOnUserCollision) {
this.start_direction = start_direction;
this.blocked_action = blocked_action;
this.items = items;
this.delay = delay;
this.furniSource = furniSource;
+ this.blockOnUserCollision = blockOnUserCollision;
}
}
}
diff --git a/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectControlClock.java b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectControlClock.java
new file mode 100644
index 00000000..b4f55831
--- /dev/null
+++ b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectControlClock.java
@@ -0,0 +1,244 @@
+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.games.InteractionGameUpCounter;
+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.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 WiredEffectControlClock extends InteractionWiredEffect {
+ private static final int ACTION_START = 0;
+ private static final int ACTION_STOP = 1;
+ private static final int ACTION_RESET = 2;
+ private static final int ACTION_PAUSE = 3;
+ private static final int ACTION_RESUME = 4;
+
+ public static final WiredEffectType type = WiredEffectType.CONTROL_CLOCK;
+
+ private final List items = new ArrayList<>();
+ private int action = ACTION_START;
+ private int furniSource = WiredSourceUtil.SOURCE_TRIGGER;
+
+ public WiredEffectControlClock(ResultSet set, Item baseItem) throws SQLException {
+ super(set, baseItem);
+ }
+
+ public WiredEffectControlClock(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 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 instanceof InteractionGameUpCounter)) {
+ continue;
+ }
+
+ InteractionGameUpCounter counter = (InteractionGameUpCounter) item;
+
+ switch (this.action) {
+ case ACTION_START:
+ counter.restartFromZero(room);
+ break;
+ case ACTION_STOP:
+ counter.stopCounter(room);
+ break;
+ case ACTION_RESET:
+ counter.resetCounter(room);
+ break;
+ case ACTION_PAUSE:
+ counter.pauseCounter(room);
+ break;
+ case ACTION_RESUME:
+ counter.resumeCounter(room);
+ break;
+ }
+ }
+ }
+
+ @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.action,
+ 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.action = this.normalizeAction(data.action);
+ 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.action = ACTION_START;
+ this.furniSource = WiredSourceUtil.SOURCE_TRIGGER;
+ this.setDelay(0);
+ }
+
+ @Override
+ public void onPickUp() {
+ this.items.clear();
+ this.action = ACTION_START;
+ this.furniSource = WiredSourceUtil.SOURCE_TRIGGER;
+ this.setDelay(0);
+ }
+
+ @Override
+ public WiredEffectType getType() {
+ return type;
+ }
+
+ @Override
+ public void serializeWiredData(ServerMessage message, Room room) {
+ List 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.action);
+ 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 < 2) {
+ throw new WiredSaveException("Invalid data");
+ }
+
+ this.action = this.normalizeAction(params[0]);
+ this.furniSource = params[1];
+
+ 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 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));
+ }
+
+ if (!(item instanceof InteractionGameUpCounter)) {
+ throw new WiredSaveException("wiredfurni.error.require_counter_furni");
+ }
+
+ newItems.add(item);
+ }
+
+ this.items.clear();
+ this.items.addAll(newItems);
+ this.setDelay(delay);
+
+ return true;
+ }
+
+ private int normalizeAction(int value) {
+ if (value < ACTION_START || value > ACTION_RESUME) {
+ return ACTION_START;
+ }
+
+ return value;
+ }
+
+ static class JsonData {
+ int delay;
+ List itemIds;
+ int action;
+ int furniSource;
+
+ public JsonData(int delay, List itemIds, int action, int furniSource) {
+ this.delay = delay;
+ this.itemIds = itemIds;
+ this.action = action;
+ this.furniSource = furniSource;
+ }
+ }
+}
diff --git a/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectFurniToFurni.java b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectFurniToFurni.java
index bdaa461b..ed8bf0a9 100644
--- a/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectFurniToFurni.java
+++ b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectFurniToFurni.java
@@ -12,6 +12,7 @@ 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.WiredMoveCarryHelper;
import com.eu.habbo.habbohotel.wired.core.WiredSourceUtil;
import com.eu.habbo.messages.ServerMessage;
import com.eu.habbo.messages.incoming.wired.WiredSaveException;
@@ -64,9 +65,14 @@ public class WiredEffectFurniToFurni extends InteractionWiredEffect {
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);
+ FurnitureMovementError error = WiredMoveCarryHelper.moveFurni(room, this, moveItem, targetTile, moveItem.getRotation(), null, false, ctx);
+ if (error == FurnitureMovementError.NONE) {
+ return;
+ }
+
+ error = WiredMoveCarryHelper.moveFurni(room, this, moveItem, targetTile, moveItem.getRotation(), targetItem.getZ(), null, false, ctx);
+ if (error == FurnitureMovementError.NONE) {
+ return;
}
}
diff --git a/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectFurniToUser.java b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectFurniToUser.java
index 62df4762..9d4fad7d 100644
--- a/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectFurniToUser.java
+++ b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectFurniToUser.java
@@ -8,6 +8,7 @@ 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.WiredMoveCarryHelper;
import java.sql.ResultSet;
import java.sql.SQLException;
@@ -38,9 +39,16 @@ public class WiredEffectFurniToUser extends WiredEffectUserFurniBase {
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);
+ FurnitureMovementError error = WiredMoveCarryHelper.moveFurni(room, this, item, targetTile, item.getRotation(), null, false, ctx);
+ if (error == FurnitureMovementError.NONE) {
+ return;
+ }
+
+ if (item.getBaseItem().getStateCount() > 0) {
+ error = WiredMoveCarryHelper.moveFurni(room, this, item, targetTile, item.getRotation(), item.getZ(), null, false, ctx);
+ if (error == FurnitureMovementError.NONE) {
+ return;
+ }
}
}
@@ -54,4 +62,5 @@ public class WiredEffectFurniToUser extends WiredEffectUserFurniBase {
public WiredEffectType getType() {
return type;
}
+
}
diff --git a/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectGiveHandItem.java b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectGiveHandItem.java
index b8d1ceaa..e249a9ac 100644
--- a/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectGiveHandItem.java
+++ b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectGiveHandItem.java
@@ -20,7 +20,7 @@ public class WiredEffectGiveHandItem extends WiredEffectWhisper {
@Override
public void execute(WiredContext ctx) {
try {
- int itemId = Integer.parseInt(this.message);
+ int itemId = Math.max(0, Integer.parseInt(this.message));
Room room = ctx.room();
diff --git a/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectGiveScore.java b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectGiveScore.java
index b2b07b4d..546f721d 100644
--- a/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectGiveScore.java
+++ b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectGiveScore.java
@@ -16,27 +16,22 @@ import com.eu.habbo.habbohotel.wired.core.WiredContext;
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.iterator.TObjectIntIterator;
-import gnu.trove.map.TObjectIntMap;
-import gnu.trove.map.hash.TObjectIntHashMap;
import gnu.trove.procedure.TObjectProcedure;
import java.sql.ResultSet;
import java.sql.SQLException;
-import java.util.AbstractMap;
import java.util.ArrayList;
import java.util.List;
-import java.util.Map;
public class WiredEffectGiveScore extends InteractionWiredEffect {
+ private static final int OPERATION_ADD = 0;
+ private static final int OPERATION_REMOVE = 1;
public static final WiredEffectType type = WiredEffectType.GIVE_SCORE;
private int score;
- private int count;
+ private int operation = OPERATION_ADD;
private int userSource = WiredSourceUtil.SOURCE_TRIGGER;
- private TObjectIntMap> data = new TObjectIntHashMap<>();
-
public WiredEffectGiveScore(ResultSet set, Item baseItem) throws SQLException {
super(set, baseItem);
}
@@ -58,45 +53,8 @@ public class WiredEffectGiveScore extends InteractionWiredEffect {
if (game == null)
continue;
- int gameStartTime = game.getStartTime();
-
- TObjectIntMap> dataClone = new TObjectIntHashMap<>(this.data);
-
- TObjectIntIterator> iterator = dataClone.iterator();
-
- boolean alreadyCounted = false;
- for (int i = dataClone.size(); i-- > 0; ) {
- iterator.advance();
-
- Map.Entry map = iterator.key();
-
- if (map.getValue() == habbo.getHabboInfo().getId()) {
- if (map.getKey() == gameStartTime) {
- if (iterator.value() < this.count) {
- iterator.setValue(iterator.value() + 1);
-
- habbo.getHabboInfo().getGamePlayer().addScore(this.score, true);
-
- alreadyCounted = true;
- break;
- }
- } else {
- iterator.remove();
- }
- }
- }
-
- if (!alreadyCounted) {
- try {
- this.data.put(new AbstractMap.SimpleEntry<>(gameStartTime, habbo.getHabboInfo().getId()), 1);
- }
- catch(IllegalArgumentException e) {
-
- }
-
- if (habbo.getHabboInfo().getGamePlayer() != null) {
- habbo.getHabboInfo().getGamePlayer().addScore(this.score, true);
- }
+ if (habbo.getHabboInfo().getGamePlayer() != null) {
+ habbo.getHabboInfo().getGamePlayer().addScore(this.getAppliedAmount(), true);
}
}
}
@@ -109,7 +67,7 @@ public class WiredEffectGiveScore extends InteractionWiredEffect {
@Override
public String getWiredData() {
- return WiredManager.getGson().toJson(new JsonData(this.score, this.count, this.getDelay(), this.userSource));
+ return WiredManager.getGson().toJson(new JsonData(this.score, this.operation, this.getDelay(), this.userSource));
}
@Override
@@ -119,7 +77,7 @@ public class WiredEffectGiveScore extends InteractionWiredEffect {
if(wiredData.startsWith("{")) {
JsonData data = WiredManager.getGson().fromJson(wiredData, JsonData.class);
this.score = data.score;
- this.count = data.count;
+ this.operation = this.normalizeOperation(data.operation);
this.setDelay(data.delay);
this.userSource = data.userSource;
}
@@ -128,7 +86,7 @@ public class WiredEffectGiveScore extends InteractionWiredEffect {
if (data.length == 3) {
this.score = Integer.parseInt(data[0]);
- this.count = Integer.parseInt(data[1]);
+ this.operation = OPERATION_ADD;
this.setDelay(Integer.parseInt(data[2]));
}
@@ -140,7 +98,7 @@ public class WiredEffectGiveScore extends InteractionWiredEffect {
@Override
public void onPickUp() {
this.score = 0;
- this.count = 0;
+ this.operation = OPERATION_ADD;
this.setDelay(0);
this.userSource = WiredSourceUtil.SOURCE_TRIGGER;
}
@@ -160,7 +118,7 @@ public class WiredEffectGiveScore extends InteractionWiredEffect {
message.appendString("");
message.appendInt(3);
message.appendInt(this.score);
- message.appendInt(this.count);
+ message.appendInt(this.operation);
message.appendInt(this.userSource);
message.appendInt(0);
message.appendInt(this.getType().code);
@@ -195,10 +153,7 @@ public class WiredEffectGiveScore extends InteractionWiredEffect {
if(score < 1 || score > 100)
throw new WiredSaveException("Score is invalid");
- int timesPerGame = settings.getIntParams()[1];
-
- if(timesPerGame < 1 || timesPerGame > 10)
- throw new WiredSaveException("Times per game is invalid");
+ int operation = this.normalizeOperation(settings.getIntParams()[1]);
this.userSource = settings.getIntParams()[2];
int delay = settings.getDelay();
@@ -207,7 +162,7 @@ public class WiredEffectGiveScore extends InteractionWiredEffect {
throw new WiredSaveException("Delay too long");
this.score = score;
- this.count = timesPerGame;
+ this.operation = operation;
this.setDelay(delay);
return true;
@@ -218,15 +173,23 @@ public class WiredEffectGiveScore extends InteractionWiredEffect {
return this.userSource == WiredSourceUtil.SOURCE_TRIGGER;
}
+ private int normalizeOperation(int value) {
+ return (value == OPERATION_REMOVE) ? OPERATION_REMOVE : OPERATION_ADD;
+ }
+
+ private int getAppliedAmount() {
+ return (this.operation == OPERATION_REMOVE) ? -this.score : this.score;
+ }
+
static class JsonData {
int score;
- int count;
+ int operation;
int delay;
int userSource;
- public JsonData(int score, int count, int delay, int userSource) {
+ public JsonData(int score, int operation, int delay, int userSource) {
this.score = score;
- this.count = count;
+ this.operation = operation;
this.delay = delay;
this.userSource = userSource;
}
diff --git a/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectGiveScoreToTeam.java b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectGiveScoreToTeam.java
index 7b2c0efd..e9ff423a 100644
--- a/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectGiveScoreToTeam.java
+++ b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectGiveScoreToTeam.java
@@ -16,20 +16,19 @@ import com.eu.habbo.habbohotel.wired.core.WiredManager;
import com.eu.habbo.habbohotel.wired.core.WiredContext;
import com.eu.habbo.messages.ServerMessage;
import com.eu.habbo.messages.incoming.wired.WiredSaveException;
-import gnu.trove.map.hash.TIntIntHashMap;
import java.sql.ResultSet;
import java.sql.SQLException;
public class WiredEffectGiveScoreToTeam extends InteractionWiredEffect {
+ private static final int OPERATION_ADD = 0;
+ private static final int OPERATION_REMOVE = 1;
public static final WiredEffectType type = WiredEffectType.GIVE_SCORE_TEAM;
private int points;
- private int count;
+ private int operation = OPERATION_ADD;
private GameTeamColors teamColor = GameTeamColors.RED;
- private TIntIntHashMap startTimes = new TIntIntHashMap();
-
public WiredEffectGiveScoreToTeam(int id, int userId, Item item, String extradata, int limitedStack, int limitedSells) {
super(id, userId, item, extradata, limitedStack, limitedSells);
}
@@ -43,16 +42,10 @@ public class WiredEffectGiveScoreToTeam extends InteractionWiredEffect {
Room room = ctx.room();
for (Game game : room.getGames()) {
if (game != null && game.state.equals(GameState.RUNNING)) {
- int c = this.startTimes.get(game.getStartTime());
+ GameTeam team = game.getTeam(this.teamColor);
- if (c < this.count) {
- GameTeam team = game.getTeam(this.teamColor);
-
- if (team != null) {
- team.addTeamScore(this.points);
-
- this.startTimes.put(game.getStartTime(), c + 1);
- }
+ if (team != null) {
+ team.addTeamScore(this.getAppliedAmount(team));
}
}
}
@@ -66,7 +59,7 @@ public class WiredEffectGiveScoreToTeam extends InteractionWiredEffect {
@Override
public String getWiredData() {
- return WiredManager.getGson().toJson(new JsonData(this.points, this.count, this.teamColor, this.getDelay()));
+ return WiredManager.getGson().toJson(new JsonData(this.points, this.operation, this.teamColor, this.getDelay()));
}
@Override
@@ -76,7 +69,7 @@ public class WiredEffectGiveScoreToTeam extends InteractionWiredEffect {
if(wiredData.startsWith("{")) {
JsonData data = WiredManager.getGson().fromJson(wiredData, JsonData.class);
this.points = data.score;
- this.count = data.count;
+ this.operation = this.normalizeOperation(data.operation);
this.teamColor = data.team;
this.setDelay(data.delay);
}
@@ -85,8 +78,8 @@ public class WiredEffectGiveScoreToTeam extends InteractionWiredEffect {
if (data.length == 4) {
this.points = Integer.parseInt(data[0]);
- this.count = Integer.parseInt(data[1]);
- this.teamColor = GameTeamColors.values()[Integer.parseInt(data[2])];
+ this.operation = OPERATION_ADD;
+ this.teamColor = GameTeamColors.fromType(Integer.parseInt(data[2]));
this.setDelay(Integer.parseInt(data[3]));
}
@@ -96,9 +89,8 @@ public class WiredEffectGiveScoreToTeam extends InteractionWiredEffect {
@Override
public void onPickUp() {
- this.startTimes.clear();
this.points = 0;
- this.count = 0;
+ this.operation = OPERATION_ADD;
this.teamColor = GameTeamColors.RED;
this.setDelay(0);
}
@@ -118,7 +110,7 @@ public class WiredEffectGiveScoreToTeam extends InteractionWiredEffect {
message.appendString("");
message.appendInt(3);
message.appendInt(this.points);
- message.appendInt(this.count);
+ message.appendInt(this.operation);
message.appendInt(this.teamColor.type);
message.appendInt(0);
message.appendInt(this.getType().code);
@@ -135,10 +127,7 @@ public class WiredEffectGiveScoreToTeam extends InteractionWiredEffect {
if(points < 1 || points > 100)
throw new WiredSaveException("Points is invalid");
- int timesPerGame = settings.getIntParams()[1];
-
- if(timesPerGame < 1 || timesPerGame > 10)
- throw new WiredSaveException("Times per game is invalid");
+ int operation = this.normalizeOperation(settings.getIntParams()[1]);
int team = settings.getIntParams()[2];
@@ -151,22 +140,34 @@ public class WiredEffectGiveScoreToTeam extends InteractionWiredEffect {
throw new WiredSaveException("Delay too long");
this.points = points;
- this.count = timesPerGame;
- this.teamColor = GameTeamColors.values()[team];
+ this.operation = operation;
+ this.teamColor = GameTeamColors.fromType(team);
this.setDelay(delay);
return true;
}
+ private int normalizeOperation(int value) {
+ return (value == OPERATION_REMOVE) ? OPERATION_REMOVE : OPERATION_ADD;
+ }
+
+ private int getAppliedAmount(GameTeam team) {
+ if (this.operation != OPERATION_REMOVE) {
+ return this.points;
+ }
+
+ return -Math.min(this.points, team.getTeamScore());
+ }
+
static class JsonData {
int score;
- int count;
+ int operation;
GameTeamColors team;
int delay;
- public JsonData(int score, int count, GameTeamColors team, int delay) {
+ public JsonData(int score, int operation, GameTeamColors team, int delay) {
this.score = score;
- this.count = count;
+ this.operation = operation;
this.team = team;
this.delay = delay;
}
diff --git a/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectJoinTeam.java b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectJoinTeam.java
index 82b94846..525f0fc5 100644
--- a/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectJoinTeam.java
+++ b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectJoinTeam.java
@@ -2,6 +2,8 @@ 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.games.battlebanzai.BattleBanzaiGame;
+import com.eu.habbo.habbohotel.games.freeze.FreezeGame;
import com.eu.habbo.habbohotel.games.Game;
import com.eu.habbo.habbohotel.games.GameTeamColors;
import com.eu.habbo.habbohotel.games.wired.WiredGame;
@@ -26,9 +28,13 @@ import java.util.ArrayList;
import java.util.List;
public class WiredEffectJoinTeam extends InteractionWiredEffect {
+ private static final int TEAM_TYPE_WIRED = 0;
+ private static final int TEAM_TYPE_BANZAI = 1;
+ private static final int TEAM_TYPE_FREEZE = 2;
public static final WiredEffectType type = WiredEffectType.JOIN_TEAM;
private GameTeamColors teamColor = GameTeamColors.RED;
+ private int teamType = TEAM_TYPE_WIRED;
private int userSource = WiredSourceUtil.SOURCE_TRIGGER;
public WiredEffectJoinTeam(ResultSet set, Item baseItem) throws SQLException {
@@ -42,20 +48,30 @@ public class WiredEffectJoinTeam extends InteractionWiredEffect {
@Override
public void execute(WiredContext ctx) {
Room room = ctx.room();
+ Class extends Game> targetGameType = this.resolveGameType();
for (RoomUnit unit : WiredSourceUtil.resolveUsers(ctx, this.userSource)) {
Habbo habbo = room.getHabbo(unit);
if (habbo == null) continue;
- WiredGame game = (WiredGame) room.getGameOrCreate(WiredGame.class);
+ Game currentGame = null;
+ if (habbo.getHabboInfo().getCurrentGame() != null) {
+ currentGame = room.getGame(habbo.getHabboInfo().getCurrentGame());
+ }
- if (habbo.getHabboInfo().getGamePlayer() != null && habbo.getHabboInfo().getCurrentGame() != null && (habbo.getHabboInfo().getCurrentGame() != WiredGame.class || (habbo.getHabboInfo().getCurrentGame() == WiredGame.class && habbo.getHabboInfo().getGamePlayer().getTeamColor() != this.teamColor))) {
- // remove from current game
- Game currentGame = room.getGame(habbo.getHabboInfo().getCurrentGame());
+ if (habbo.getHabboInfo().getGamePlayer() != null
+ && habbo.getHabboInfo().getCurrentGame() != null
+ && (habbo.getHabboInfo().getCurrentGame() != targetGameType
+ || habbo.getHabboInfo().getGamePlayer().getTeamColor() != this.teamColor)
+ && currentGame != null) {
currentGame.removeHabbo(habbo);
}
if(habbo.getHabboInfo().getGamePlayer() == null) {
+ Game game = room.getGameOrCreate(targetGameType);
+ if (game == null) {
+ continue;
+ }
game.addHabbo(habbo, this.teamColor);
}
}
@@ -69,7 +85,7 @@ public class WiredEffectJoinTeam extends InteractionWiredEffect {
@Override
public String getWiredData() {
- return WiredManager.getGson().toJson(new JsonData(this.teamColor, this.getDelay(), this.userSource));
+ return WiredManager.getGson().toJson(new JsonData(this.teamColor, this.teamType, this.getDelay(), this.userSource));
}
@Override
@@ -80,6 +96,7 @@ public class WiredEffectJoinTeam extends InteractionWiredEffect {
JsonData data = WiredManager.getGson().fromJson(wiredData, JsonData.class);
this.setDelay(data.delay);
this.teamColor = data.team;
+ this.teamType = this.normalizeTeamType(data.teamType);
this.userSource = data.userSource;
}
else {
@@ -89,11 +106,12 @@ public class WiredEffectJoinTeam extends InteractionWiredEffect {
this.setDelay(Integer.parseInt(data[0]));
if (data.length >= 2) {
- this.teamColor = GameTeamColors.values()[Integer.parseInt(data[1])];
+ this.teamColor = GameTeamColors.fromType(Integer.parseInt(data[1]));
}
}
this.needsUpdate(true);
+ this.teamType = TEAM_TYPE_WIRED;
this.userSource = WiredSourceUtil.SOURCE_TRIGGER;
}
}
@@ -101,6 +119,7 @@ public class WiredEffectJoinTeam extends InteractionWiredEffect {
@Override
public void onPickUp() {
this.teamColor = GameTeamColors.RED;
+ this.teamType = TEAM_TYPE_WIRED;
this.userSource = WiredSourceUtil.SOURCE_TRIGGER;
this.setDelay(0);
}
@@ -118,7 +137,8 @@ public class WiredEffectJoinTeam extends InteractionWiredEffect {
message.appendInt(this.getBaseItem().getSpriteId());
message.appendInt(this.getId());
message.appendString("");
- message.appendInt(2);
+ message.appendInt(3);
+ message.appendInt(this.teamType);
message.appendInt(this.teamColor.type);
message.appendInt(this.userSource);
message.appendInt(0);
@@ -149,8 +169,15 @@ public class WiredEffectJoinTeam extends InteractionWiredEffect {
public boolean saveData(WiredSettings settings, GameClient gameClient) throws WiredSaveException {
if(settings.getIntParams().length < 2) throw new WiredSaveException("invalid data");
- int team = settings.getIntParams()[0];
- this.userSource = settings.getIntParams()[1];
+ if (settings.getIntParams().length > 2) {
+ this.teamType = this.normalizeTeamType(settings.getIntParams()[0]);
+ this.userSource = settings.getIntParams()[2];
+ } else {
+ this.teamType = TEAM_TYPE_WIRED;
+ this.userSource = settings.getIntParams()[1];
+ }
+
+ int team = (settings.getIntParams().length > 2) ? settings.getIntParams()[1] : settings.getIntParams()[0];
if(team < 1 || team > 4)
throw new WiredSaveException("Team is invalid");
@@ -160,7 +187,7 @@ public class WiredEffectJoinTeam extends InteractionWiredEffect {
if(delay > Emulator.getConfig().getInt("hotel.wired.max_delay", 20))
throw new WiredSaveException("Delay too long");
- this.teamColor = GameTeamColors.values()[team];
+ this.teamColor = GameTeamColors.fromType(team);
this.setDelay(delay);
return true;
@@ -171,13 +198,34 @@ public class WiredEffectJoinTeam extends InteractionWiredEffect {
return this.userSource == WiredSourceUtil.SOURCE_TRIGGER;
}
+ private int normalizeTeamType(int value) {
+ if (value == TEAM_TYPE_BANZAI || value == TEAM_TYPE_FREEZE) {
+ return value;
+ }
+
+ return TEAM_TYPE_WIRED;
+ }
+
+ private Class extends Game> resolveGameType() {
+ switch (this.teamType) {
+ case TEAM_TYPE_BANZAI:
+ return BattleBanzaiGame.class;
+ case TEAM_TYPE_FREEZE:
+ return FreezeGame.class;
+ default:
+ return WiredGame.class;
+ }
+ }
+
static class JsonData {
GameTeamColors team;
+ int teamType;
int delay;
int userSource;
- public JsonData(GameTeamColors team, int delay, int userSource) {
+ public JsonData(GameTeamColors team, int teamType, int delay, int userSource) {
this.team = team;
+ this.teamType = teamType;
this.delay = delay;
this.userSource = userSource;
}
diff --git a/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectMatchFurni.java b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectMatchFurni.java
index e075f486..dd616217 100644
--- a/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectMatchFurni.java
+++ b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectMatchFurni.java
@@ -12,10 +12,10 @@ import com.eu.habbo.habbohotel.wired.core.WiredContext;
import com.eu.habbo.habbohotel.wired.WiredEffectType;
import com.eu.habbo.habbohotel.wired.core.WiredManager;
import com.eu.habbo.habbohotel.wired.WiredMatchFurniSetting;
+import com.eu.habbo.habbohotel.wired.core.WiredMoveCarryHelper;
import com.eu.habbo.habbohotel.wired.core.WiredSourceUtil;
import com.eu.habbo.messages.ServerMessage;
import com.eu.habbo.messages.incoming.wired.WiredSaveException;
-import com.eu.habbo.messages.outgoing.rooms.items.FloorItemOnRollerComposer;
import gnu.trove.set.hash.THashSet;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -25,6 +25,7 @@ import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Pattern;
+import java.math.BigDecimal;
public class WiredEffectMatchFurni extends InteractionWiredEffect implements InteractionWiredMatchFurniSettings {
private static final Logger LOGGER = LoggerFactory.getLogger(WiredEffectMatchFurni.class);
@@ -35,6 +36,7 @@ public class WiredEffectMatchFurni extends InteractionWiredEffect implements Int
private boolean state = false;
private boolean direction = false;
private boolean position = false;
+ private boolean altitude = false;
private int furniSource = WiredSourceUtil.SOURCE_TRIGGER;
public WiredEffectMatchFurni(ResultSet set, Item baseItem) throws SQLException {
@@ -62,7 +64,7 @@ public class WiredEffectMatchFurni extends InteractionWiredEffect implements Int
for (WiredMatchFurniSetting setting : this.settings) {
HabboItem item = room.getHabboItem(setting.item_id);
if (item != null) {
- this.applySetting(room, item, setting);
+ this.applySetting(room, item, setting, ctx);
}
}
@@ -80,7 +82,7 @@ public class WiredEffectMatchFurni extends InteractionWiredEffect implements Int
WiredMatchFurniSetting setting = this.resolveSettingForTarget(room, item);
if (setting == null) continue;
- this.applySetting(room, item, setting);
+ this.applySetting(room, item, setting, ctx);
}
}
@@ -104,7 +106,7 @@ public class WiredEffectMatchFurni extends InteractionWiredEffect implements Int
return fallback;
}
- private void applySetting(Room room, HabboItem item, WiredMatchFurniSetting setting) {
+ private void applySetting(Room room, HabboItem item, WiredMatchFurniSetting setting, WiredContext ctx) {
if (this.state && (this.checkForWiredResetPermission && item.allowWiredResetState())) {
if (!setting.state.equals(" ") && !item.getExtradata().equals(setting.state)) {
item.setExtradata(setting.state);
@@ -115,23 +117,28 @@ public class WiredEffectMatchFurni extends InteractionWiredEffect implements Int
RoomTile oldLocation = room.getLayout().getTile(item.getX(), item.getY());
if (oldLocation == null) return;
- double oldZ = item.getZ();
if(this.direction && !this.position) {
if(item.getRotation() != setting.rotation && room.furnitureFitsAt(oldLocation, item, setting.rotation, false) == FurnitureMovementError.NONE) {
- room.moveFurniTo(item, oldLocation, setting.rotation, null, true);
+ WiredMoveCarryHelper.moveFurni(room, this, item, oldLocation, setting.rotation, null, true, ctx);
+ }
+ }
+ else if(this.altitude && !this.position) {
+ int newRotation = this.direction ? setting.rotation : item.getRotation();
+ if(BigDecimal.valueOf(item.getZ()).compareTo(BigDecimal.valueOf(setting.z)) != 0 || newRotation != item.getRotation()) {
+ WiredMoveCarryHelper.moveFurni(room, this, item, oldLocation, newRotation, setting.z, null, true, ctx);
}
}
else if(this.position) {
boolean slideAnimation = !this.direction || item.getRotation() == setting.rotation;
RoomTile newLocation = room.getLayout().getTile((short) setting.x, (short) setting.y);
int newRotation = this.direction ? setting.rotation : item.getRotation();
+ double newZ = this.altitude ? setting.z : item.getZ();
- if(newLocation != null && newLocation.state != RoomTileState.INVALID && (newLocation != oldLocation || newRotation != item.getRotation()) && room.furnitureFitsAt(newLocation, item, newRotation, true) == FurnitureMovementError.NONE) {
- if(room.moveFurniTo(item, newLocation, newRotation, null, !slideAnimation) == FurnitureMovementError.NONE) {
- if(slideAnimation) {
- room.sendComposer(new FloorItemOnRollerComposer(item, null, oldLocation, oldZ, newLocation, item.getZ(), 0, room).compose());
- }
+ if (newLocation != null && newLocation.state != RoomTileState.INVALID
+ && (newLocation != oldLocation || newRotation != item.getRotation())
+ && WiredMoveCarryHelper.getMovementError(room, this, item, newLocation, newRotation, ctx) == FurnitureMovementError.NONE) {
+ if (WiredMoveCarryHelper.moveFurni(room, this, item, newLocation, newRotation, newZ, null, !slideAnimation, ctx) == FurnitureMovementError.NONE) {
}
}
}
@@ -146,7 +153,7 @@ public class WiredEffectMatchFurni extends InteractionWiredEffect implements Int
@Override
public String getWiredData() {
this.refresh();
- return WiredManager.getGson().toJson(new JsonData(this.state, this.direction, this.position, new ArrayList(this.settings), this.getDelay(), this.furniSource));
+ return WiredManager.getGson().toJson(new JsonData(this.state, this.direction, this.position, this.altitude, new ArrayList(this.settings), this.getDelay(), this.furniSource));
}
@Override
@@ -159,6 +166,7 @@ public class WiredEffectMatchFurni extends InteractionWiredEffect implements Int
this.state = data.state;
this.direction = data.direction;
this.position = data.position;
+ this.altitude = data.altitude;
this.settings.clear();
this.settings.addAll(data.items);
this.furniSource = data.furniSource;
@@ -175,7 +183,9 @@ public class WiredEffectMatchFurni extends InteractionWiredEffect implements Int
String[] stuff = items[i].split(Pattern.quote("-"));
- if (stuff.length >= 5) {
+ if (stuff.length >= 6) {
+ this.settings.add(new WiredMatchFurniSetting(Integer.parseInt(stuff[0]), stuff[1], Integer.parseInt(stuff[2]), Integer.parseInt(stuff[3]), Integer.parseInt(stuff[4]), Double.parseDouble(stuff[5])));
+ } else if (stuff.length >= 5) {
this.settings.add(new WiredMatchFurniSetting(Integer.parseInt(stuff[0]), stuff[1], Integer.parseInt(stuff[2]), Integer.parseInt(stuff[3]), Integer.parseInt(stuff[4])));
}
@@ -187,6 +197,7 @@ public class WiredEffectMatchFurni extends InteractionWiredEffect implements Int
this.state = data[2].equals("1");
this.direction = data[3].equals("1");
this.position = data[4].equals("1");
+ this.altitude = false;
this.setDelay(Integer.parseInt(data[5]));
this.furniSource = this.settings.isEmpty() ? WiredSourceUtil.SOURCE_TRIGGER : WiredSourceUtil.SOURCE_SELECTED;
this.needsUpdate(true);
@@ -199,6 +210,7 @@ public class WiredEffectMatchFurni extends InteractionWiredEffect implements Int
this.state = false;
this.direction = false;
this.position = false;
+ this.altitude = false;
this.furniSource = WiredSourceUtil.SOURCE_TRIGGER;
this.setDelay(0);
}
@@ -222,10 +234,11 @@ public class WiredEffectMatchFurni extends InteractionWiredEffect implements Int
message.appendInt(this.getBaseItem().getSpriteId());
message.appendInt(this.getId());
message.appendString("");
- message.appendInt(4);
+ message.appendInt(5);
message.appendInt(this.state ? 1 : 0);
message.appendInt(this.direction ? 1 : 0);
message.appendInt(this.position ? 1 : 0);
+ message.appendInt(this.altitude ? 1 : 0);
message.appendInt(this.furniSource);
message.appendInt(0);
message.appendInt(this.getType().code);
@@ -239,7 +252,8 @@ public class WiredEffectMatchFurni extends InteractionWiredEffect implements Int
boolean setState = settings.getIntParams()[0] == 1;
boolean setDirection = settings.getIntParams()[1] == 1;
boolean setPosition = settings.getIntParams()[2] == 1;
- this.furniSource = settings.getIntParams()[3];
+ boolean setAltitude = (settings.getIntParams().length > 4) ? (settings.getIntParams()[3] == 1) : false;
+ this.furniSource = (settings.getIntParams().length > 4) ? settings.getIntParams()[4] : settings.getIntParams()[3];
Room room = Emulator.getGameEnvironment().getRoomManager().getRoom(this.getRoomId());
@@ -261,7 +275,7 @@ public class WiredEffectMatchFurni extends InteractionWiredEffect implements Int
if(it == null)
throw new WiredSaveException(String.format("Item %s not found", itemId));
- newSettings.add(new WiredMatchFurniSetting(it.getId(), this.checkForWiredResetPermission && it.allowWiredResetState() ? it.getExtradata() : " ", it.getRotation(), it.getX(), it.getY()));
+ newSettings.add(new WiredMatchFurniSetting(it.getId(), this.checkForWiredResetPermission && it.allowWiredResetState() ? it.getExtradata() : " ", it.getRotation(), it.getX(), it.getY(), it.getZ()));
}
int delay = settings.getDelay();
@@ -272,6 +286,7 @@ public class WiredEffectMatchFurni extends InteractionWiredEffect implements Int
this.state = setState;
this.direction = setDirection;
this.position = setPosition;
+ this.altitude = setAltitude;
this.settings.clear();
this.settings.addAll(newSettings);
this.setDelay(delay);
@@ -308,18 +323,25 @@ public class WiredEffectMatchFurni extends InteractionWiredEffect implements Int
return this.position;
}
+ @Override
+ public boolean shouldMatchAltitude() {
+ return this.altitude;
+ }
+
static class JsonData {
boolean state;
boolean direction;
boolean position;
+ boolean altitude;
List items;
int delay;
int furniSource;
- public JsonData(boolean state, boolean direction, boolean position, List items, int delay, int furniSource) {
+ public JsonData(boolean state, boolean direction, boolean position, boolean altitude, List items, int delay, int furniSource) {
this.state = state;
this.direction = direction;
this.position = position;
+ this.altitude = altitude;
this.items = items;
this.delay = delay;
this.furniSource = furniSource;
diff --git a/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectMoveFurniAway.java b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectMoveFurniAway.java
index 3cd56464..63d01717 100644
--- a/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectMoveFurniAway.java
+++ b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectMoveFurniAway.java
@@ -10,11 +10,11 @@ import com.eu.habbo.habbohotel.users.HabboItem;
import com.eu.habbo.habbohotel.wired.WiredEffectType;
import com.eu.habbo.habbohotel.wired.core.WiredManager;
import com.eu.habbo.habbohotel.wired.core.WiredContext;
+import com.eu.habbo.habbohotel.wired.core.WiredMoveCarryHelper;
import com.eu.habbo.habbohotel.wired.core.WiredSimulation;
import com.eu.habbo.habbohotel.wired.core.WiredSourceUtil;
import com.eu.habbo.messages.ServerMessage;
import com.eu.habbo.messages.incoming.wired.WiredSaveException;
-import com.eu.habbo.messages.outgoing.rooms.items.FloorItemOnRollerComposer;
import gnu.trove.set.hash.THashSet;
import java.sql.ResultSet;
@@ -98,11 +98,10 @@ public class WiredEffectMoveFurniAway extends InteractionWiredEffect {
RoomTile newLocation = room.getLayout().getTile((short) (item.getX() + x), (short) (item.getY() + y));
RoomTile oldLocation = room.getLayout().getTile(item.getX(), item.getY());
- double oldZ = item.getZ();
- if(newLocation != null && newLocation.state != RoomTileState.INVALID && newLocation != oldLocation && room.furnitureFitsAt(newLocation, item, item.getRotation(), true) == FurnitureMovementError.NONE) {
- if(room.moveFurniTo(item, newLocation, item.getRotation(), null, false) == FurnitureMovementError.NONE) {
- room.sendComposer(new FloorItemOnRollerComposer(item, null, oldLocation, oldZ, newLocation, item.getZ(), 0, room).compose());
+ if (newLocation != null && newLocation.state != RoomTileState.INVALID && newLocation != oldLocation
+ && WiredMoveCarryHelper.getMovementError(room, this, item, newLocation, item.getRotation(), ctx) == FurnitureMovementError.NONE) {
+ if (WiredMoveCarryHelper.moveFurni(room, this, item, newLocation, item.getRotation(), null, false, ctx) == FurnitureMovementError.NONE) {
}
}
}
diff --git a/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectMoveFurniTo.java b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectMoveFurniTo.java
index d2087c9f..ecdc90a7 100644
--- a/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectMoveFurniTo.java
+++ b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectMoveFurniTo.java
@@ -5,6 +5,7 @@ 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.rooms.RoomUnit;
@@ -12,13 +13,12 @@ import com.eu.habbo.habbohotel.users.HabboItem;
import com.eu.habbo.habbohotel.wired.WiredEffectType;
import com.eu.habbo.habbohotel.wired.core.WiredManager;
import com.eu.habbo.habbohotel.wired.core.WiredContext;
+import com.eu.habbo.habbohotel.wired.core.WiredMoveCarryHelper;
import com.eu.habbo.habbohotel.wired.core.WiredSimulation;
import com.eu.habbo.habbohotel.wired.core.WiredSourceUtil;
import com.eu.habbo.messages.ServerMessage;
import com.eu.habbo.messages.incoming.wired.WiredSaveException;
-import com.eu.habbo.messages.outgoing.rooms.items.FloorItemOnRollerComposer;
import gnu.trove.set.hash.THashSet;
-
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
@@ -112,11 +112,6 @@ public class WiredEffectMoveFurniTo extends InteractionWiredEffect {
RoomTile objectTile = room.getLayout().getTile(targetItem.getX(), targetItem.getY());
if (objectTile != null) {
- RoomTile sourceTile = room.getLayout().getTile(((HabboItem) object).getX(), ((HabboItem) object).getY());
- if (sourceTile == null) continue;
-
- THashSet refreshTiles = room.getLayout().getTilesAt(sourceTile, ((HabboItem) object).getBaseItem().getWidth(), ((HabboItem) object).getBaseItem().getLength(), ((HabboItem) object).getRotation());
-
RoomTile tile = room.getLayout().getTileInFront(objectTile, this.direction, indexOffset);
if (tile == null || !tile.getAllowStack()) {
indexOffset = 0;
@@ -127,13 +122,18 @@ public class WiredEffectMoveFurniTo extends InteractionWiredEffect {
continue;
}
- room.sendComposer(new FloorItemOnRollerComposer((HabboItem) object, null, tile, tile.getStackHeight() - ((HabboItem) object).getZ(), room).compose());
-
- RoomTile newSourceTile = room.getLayout().getTile(((HabboItem) object).getX(), ((HabboItem) object).getY());
- if (newSourceTile != null) {
- refreshTiles.addAll(room.getLayout().getTilesAt(newSourceTile, ((HabboItem) object).getBaseItem().getWidth(), ((HabboItem) object).getBaseItem().getLength(), ((HabboItem) object).getRotation()));
+ HabboItem movingItem = (HabboItem) object;
+ RoomTile oldLocation = room.getLayout().getTile(movingItem.getX(), movingItem.getY());
+ if (oldLocation == null) {
+ continue;
}
- room.updateTiles(refreshTiles);
+
+ FurnitureMovementError movementError = WiredMoveCarryHelper.moveFurni(room, this, movingItem, tile, movingItem.getRotation(), null, false, ctx);
+
+ if (movementError != FurnitureMovementError.NONE) {
+ continue;
+ }
+
this.indexOffset.put(targetItem.getId(), indexOffset);
}
}
diff --git a/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectMoveFurniTowards.java b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectMoveFurniTowards.java
index d01a9fc5..be02d463 100644
--- a/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectMoveFurniTowards.java
+++ b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectMoveFurniTowards.java
@@ -10,11 +10,11 @@ import com.eu.habbo.habbohotel.users.HabboItem;
import com.eu.habbo.habbohotel.wired.WiredEffectType;
import com.eu.habbo.habbohotel.wired.core.WiredManager;
import com.eu.habbo.habbohotel.wired.core.WiredContext;
+import com.eu.habbo.habbohotel.wired.core.WiredMoveCarryHelper;
import com.eu.habbo.habbohotel.wired.core.WiredSimulation;
import com.eu.habbo.habbohotel.wired.core.WiredSourceUtil;
import com.eu.habbo.messages.ServerMessage;
import com.eu.habbo.messages.incoming.wired.WiredSaveException;
-import com.eu.habbo.messages.outgoing.rooms.items.FloorItemOnRollerComposer;
import com.eu.habbo.threading.runnables.WiredCollissionRunnable;
import gnu.trove.map.hash.THashMap;
import gnu.trove.set.hash.THashSet;
@@ -53,7 +53,7 @@ public class WiredEffectMoveFurniTowards extends InteractionWiredEffect {
this.lastDirections = new THashMap<>();
}
- public List getAvailableDirections(HabboItem item, Room room) {
+ public List getAvailableDirections(HabboItem item, Room room, WiredContext ctx) {
List availableDirections = new ArrayList<>();
RoomLayout layout = room.getLayout();
@@ -73,7 +73,7 @@ public class WiredEffectMoveFurniTowards extends InteractionWiredEffect {
if (!layout.tileExists(tile.x, tile.y))
continue;
- if (room.furnitureFitsAt(tile, item, item.getRotation()) == FurnitureMovementError.INVALID_MOVE)
+ if (WiredMoveCarryHelper.getMovementError(room, this, item, tile, item.getRotation(), ctx) != FurnitureMovementError.NONE)
continue;
HabboItem topItem = room.getTopItemAt(tile.x, tile.y);
@@ -192,7 +192,7 @@ public class WiredEffectMoveFurniTowards extends InteractionWiredEffect {
3+ available - move in random direction, but never the opposite
*/
- List availableDirections = this.getAvailableDirections(item, room);
+ List availableDirections = this.getAvailableDirections(item, room, ctx);
if (moveDirection != null && !availableDirections.contains(moveDirection))
moveDirection = null;
@@ -228,13 +228,11 @@ public class WiredEffectMoveFurniTowards extends InteractionWiredEffect {
RoomTile newTile = room.getLayout().getTileInFront(oldLocation, moveDirection.getValue());
- double oldZ = item.getZ();
-
if(newTile != null) {
lastDirections.put(item.getId(), moveDirection);
- if(newTile.state != RoomTileState.INVALID && newTile != oldLocation && room.furnitureFitsAt(newTile, item, item.getRotation(), true) == FurnitureMovementError.NONE) {
- if (room.moveFurniTo(item, newTile, item.getRotation(), null, false) == FurnitureMovementError.NONE) {
- room.sendComposer(new FloorItemOnRollerComposer(item, null, oldLocation, oldZ, newTile, item.getZ(), 0, room).compose());
+ if (newTile.state != RoomTileState.INVALID && newTile != oldLocation
+ && WiredMoveCarryHelper.getMovementError(room, this, item, newTile, item.getRotation(), ctx) == FurnitureMovementError.NONE) {
+ if (WiredMoveCarryHelper.moveFurni(room, this, item, newTile, item.getRotation(), null, false, ctx) == FurnitureMovementError.NONE) {
}
}
}
diff --git a/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectMoveRotateFurni.java b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectMoveRotateFurni.java
index 0b4cbb55..26bbe3ab 100644
--- a/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectMoveRotateFurni.java
+++ b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectMoveRotateFurni.java
@@ -11,11 +11,11 @@ import com.eu.habbo.habbohotel.users.HabboItem;
import com.eu.habbo.habbohotel.wired.WiredEffectType;
import com.eu.habbo.habbohotel.wired.core.WiredManager;
import com.eu.habbo.habbohotel.wired.core.WiredContext;
+import com.eu.habbo.habbohotel.wired.core.WiredMoveCarryHelper;
import com.eu.habbo.habbohotel.wired.core.WiredSimulation;
import com.eu.habbo.habbohotel.wired.core.WiredSourceUtil;
import com.eu.habbo.messages.ServerMessage;
import com.eu.habbo.messages.incoming.wired.WiredSaveException;
-import com.eu.habbo.messages.outgoing.rooms.items.FloorItemOnRollerComposer;
import gnu.trove.set.hash.THashSet;
import java.sql.ResultSet;
@@ -61,7 +61,6 @@ public class WiredEffectMoveRotateFurni extends InteractionWiredEffect implement
int newRotation = this.rotation > 0 ? this.getNewRotation(item) : item.getRotation();
RoomTile newLocation = room.getLayout().getTile(item.getX(), item.getY());
RoomTile oldLocation = room.getLayout().getTile(item.getX(), item.getY());
- double oldZ = item.getZ();
if(this.direction > 0) {
// Use pre-selected direction if available, otherwise pick random
@@ -77,13 +76,14 @@ public class WiredEffectMoveRotateFurni extends InteractionWiredEffect implement
boolean slideAnimation = item.getRotation() == newRotation;
- FurnitureMovementError furniMoveTest = room.furnitureFitsAt(newLocation, item, newRotation, true);
- if(newLocation != null && newLocation.state != RoomTileState.INVALID && (newLocation != oldLocation || newRotation != item.getRotation()) && (furniMoveTest == FurnitureMovementError.NONE || ((furniMoveTest == FurnitureMovementError.TILE_HAS_BOTS || furniMoveTest == FurnitureMovementError.TILE_HAS_HABBOS || furniMoveTest == FurnitureMovementError.TILE_HAS_PETS) && newLocation == oldLocation))) {
- if(room.furnitureFitsAt(newLocation, item, newRotation, false) == FurnitureMovementError.NONE && room.moveFurniTo(item, newLocation, newRotation, null, !slideAnimation) == FurnitureMovementError.NONE) {
+ FurnitureMovementError furniMoveTest = WiredMoveCarryHelper.getMovementError(room, this, item, newLocation, newRotation, ctx);
+ if (newLocation != null && newLocation.state != RoomTileState.INVALID && (newLocation != oldLocation || newRotation != item.getRotation())
+ && (furniMoveTest == FurnitureMovementError.NONE
+ || ((furniMoveTest == FurnitureMovementError.TILE_HAS_BOTS
+ || furniMoveTest == FurnitureMovementError.TILE_HAS_HABBOS
+ || furniMoveTest == FurnitureMovementError.TILE_HAS_PETS) && newLocation == oldLocation))) {
+ if (WiredMoveCarryHelper.moveFurni(room, this, item, newLocation, newRotation, null, !slideAnimation, ctx) == FurnitureMovementError.NONE) {
this.itemCooldowns.add(item);
- if(slideAnimation) {
- room.sendComposer(new FloorItemOnRollerComposer(item, null, oldLocation, oldZ, newLocation, item.getZ(), 0, room).compose());
- }
}
}
}
@@ -352,27 +352,32 @@ public class WiredEffectMoveRotateFurni extends InteractionWiredEffect implement
* @return direction
*/
private RoomUserRotation getMovementDirection() {
- RoomUserRotation movemementDirection = RoomUserRotation.NORTH;
- if (this.direction == 1) {
- movemementDirection = RoomUserRotation.values()[Emulator.getRandom().nextInt(RoomUserRotation.values().length / 2) * 2];
- } else if (this.direction == 2) {
- if (Emulator.getRandom().nextInt(2) == 1) {
- movemementDirection = RoomUserRotation.EAST;
- } else {
- movemementDirection = RoomUserRotation.WEST;
- }
- } else if (this.direction == 3) {
- if (Emulator.getRandom().nextInt(2) != 1) {
- movemementDirection = RoomUserRotation.SOUTH;
- }
- } else if (this.direction == 4) {
- movemementDirection = RoomUserRotation.SOUTH;
- } else if (this.direction == 5) {
- movemementDirection = RoomUserRotation.EAST;
- } else if (this.direction == 7) {
- movemementDirection = RoomUserRotation.WEST;
+ switch (this.direction) {
+ case 1:
+ return RoomUserRotation.values()[Emulator.getRandom().nextInt(RoomUserRotation.values().length / 2) * 2];
+ case 2:
+ return Emulator.getRandom().nextInt(2) == 1 ? RoomUserRotation.EAST : RoomUserRotation.WEST;
+ case 3:
+ return Emulator.getRandom().nextInt(2) == 1 ? RoomUserRotation.NORTH : RoomUserRotation.SOUTH;
+ case 4:
+ return RoomUserRotation.SOUTH;
+ case 5:
+ return RoomUserRotation.EAST;
+ case 6:
+ return RoomUserRotation.NORTH;
+ case 7:
+ return RoomUserRotation.WEST;
+ case 8:
+ return RoomUserRotation.NORTH_EAST;
+ case 9:
+ return RoomUserRotation.SOUTH_EAST;
+ case 10:
+ return RoomUserRotation.SOUTH_WEST;
+ case 11:
+ return RoomUserRotation.NORTH_WEST;
+ default:
+ return RoomUserRotation.NORTH;
}
- return movemementDirection;
}
@Override
diff --git a/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectMoveRotateUser.java b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectMoveRotateUser.java
new file mode 100644
index 00000000..c08487fb
--- /dev/null
+++ b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectMoveRotateUser.java
@@ -0,0 +1,291 @@
+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.RoomTile;
+import com.eu.habbo.habbohotel.rooms.RoomTileState;
+import com.eu.habbo.habbohotel.rooms.RoomUnit;
+import com.eu.habbo.habbohotel.rooms.RoomUserRotation;
+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.WiredMoveCarryHelper;
+import com.eu.habbo.habbohotel.wired.core.WiredSourceUtil;
+import com.eu.habbo.habbohotel.wired.core.WiredUserMovementHelper;
+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 WiredEffectMoveRotateUser extends InteractionWiredEffect {
+ private static final int ROTATION_CLOCKWISE = 8;
+ private static final int ROTATION_COUNTER_CLOCKWISE = 9;
+
+ public static final WiredEffectType type = WiredEffectType.MOVE_ROTATE_USER;
+
+ private int movementDirection = -1;
+ private int rotationDirection = -1;
+ private int userSource = WiredSourceUtil.SOURCE_TRIGGER;
+
+ public WiredEffectMoveRotateUser(ResultSet set, Item baseItem) throws SQLException {
+ super(set, baseItem);
+ }
+
+ public WiredEffectMoveRotateUser(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 (roomUnit == null || roomUnit.getRoom() != room) {
+ continue;
+ }
+
+ boolean hasRotation = this.rotationDirection >= 0;
+ RoomUserRotation targetBodyRotation = hasRotation ? this.getTargetRotation(roomUnit) : roomUnit.getBodyRotation();
+ RoomUserRotation targetHeadRotation = hasRotation ? targetBodyRotation : roomUnit.getHeadRotation();
+ RoomTile targetTile = (this.movementDirection >= 0) ? this.getTargetTile(room, roomUnit, this.movementDirection) : null;
+ boolean canMove = this.canMoveTo(room, roomUnit, targetTile);
+ boolean noAnimation = WiredMoveCarryHelper.hasNoAnimationExtra(room, this);
+
+ if (canMove) {
+ double targetZ = targetTile.getStackHeight() + ((targetTile.state == RoomTileState.SIT) ? -0.5 : 0);
+ int animationDuration = noAnimation ? 0 : WiredMoveCarryHelper.getAnimationDuration(room, this, WiredUserMovementHelper.DEFAULT_ANIMATION_DURATION);
+ if (!WiredUserMovementHelper.moveUser(room, roomUnit, targetTile, targetZ, targetBodyRotation, targetHeadRotation,
+ animationDuration, noAnimation)) {
+ if (hasRotation) {
+ WiredUserMovementHelper.updateUserDirection(room, roomUnit, targetBodyRotation, targetHeadRotation);
+ }
+ }
+ continue;
+ }
+
+ if (hasRotation) {
+ WiredUserMovementHelper.updateUserDirection(room, roomUnit, targetBodyRotation, targetHeadRotation);
+ }
+ }
+ }
+
+ @Override
+ public String getWiredData() {
+ return WiredManager.getGson().toJson(new JsonData(
+ this.getDelay(),
+ this.movementDirection,
+ this.rotationDirection,
+ 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.movementDirection = this.normalizeDirection(data.movementDirection);
+ this.rotationDirection = this.normalizeRotation(data.rotationDirection);
+ this.userSource = data.userSource;
+ return;
+ }
+
+ this.setDelay(0);
+ this.movementDirection = -1;
+ this.rotationDirection = -1;
+ this.userSource = WiredSourceUtil.SOURCE_TRIGGER;
+ }
+
+ @Override
+ public void onPickUp() {
+ this.setDelay(0);
+ this.movementDirection = -1;
+ this.rotationDirection = -1;
+ 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.movementDirection);
+ message.appendInt(this.rotationDirection);
+ message.appendInt(this.userSource);
+ message.appendInt(0);
+ message.appendInt(this.getType().code);
+ message.appendInt(this.getDelay());
+
+ if (this.requiresTriggeringUser()) {
+ List invalidTriggers = new ArrayList<>();
+ room.getRoomSpecialTypes().getTriggers(this.getX(), this.getY()).forEach(new TObjectProcedure() {
+ @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 delay = settings.getDelay();
+ if (delay > Emulator.getConfig().getInt("hotel.wired.max_delay", 20)) {
+ throw new WiredSaveException("Delay too long");
+ }
+
+ this.movementDirection = this.normalizeDirection(settings.getIntParams()[0]);
+ this.rotationDirection = this.normalizeRotation(settings.getIntParams()[1]);
+ this.userSource = settings.getIntParams()[2];
+ this.setDelay(delay);
+
+ return true;
+ }
+
+ @Override
+ public boolean requiresTriggeringUser() {
+ return this.userSource == WiredSourceUtil.SOURCE_TRIGGER;
+ }
+
+ @Override
+ protected long requiredCooldown() {
+ return COOLDOWN_MOVEMENT;
+ }
+
+ @Deprecated
+ @Override
+ public boolean execute(RoomUnit roomUnit, Room room, Object[] stuff) {
+ return false;
+ }
+
+ private int normalizeDirection(int direction) {
+ return (direction >= 0 && direction <= 7) ? direction : -1;
+ }
+
+ private int normalizeRotation(int rotation) {
+ return ((rotation >= 0 && rotation <= 7) || rotation == ROTATION_CLOCKWISE || rotation == ROTATION_COUNTER_CLOCKWISE) ? rotation : -1;
+ }
+
+ private RoomUserRotation getTargetRotation(RoomUnit roomUnit) {
+ RoomUserRotation currentRotation = (roomUnit != null && roomUnit.getBodyRotation() != null) ? roomUnit.getBodyRotation() : RoomUserRotation.NORTH;
+
+ if (this.rotationDirection == ROTATION_CLOCKWISE) {
+ return RoomUserRotation.clockwise(currentRotation);
+ }
+
+ if (this.rotationDirection == ROTATION_COUNTER_CLOCKWISE) {
+ return RoomUserRotation.counterClockwise(currentRotation);
+ }
+
+ return RoomUserRotation.fromValue(this.rotationDirection);
+ }
+
+ private RoomTile getTargetTile(Room room, RoomUnit roomUnit, int direction) {
+ RoomTile currentTile = roomUnit.getCurrentLocation();
+
+ if (currentTile == null) {
+ return null;
+ }
+
+ int deltaX = 0;
+ int deltaY = 0;
+
+ switch (RoomUserRotation.fromValue(direction)) {
+ case NORTH:
+ deltaY = 1;
+ break;
+ case NORTH_EAST:
+ deltaX = 1;
+ deltaY = 1;
+ break;
+ case EAST:
+ deltaX = 1;
+ break;
+ case SOUTH_EAST:
+ deltaX = 1;
+ deltaY = -1;
+ break;
+ case SOUTH:
+ deltaY = -1;
+ break;
+ case SOUTH_WEST:
+ deltaX = -1;
+ deltaY = -1;
+ break;
+ case WEST:
+ deltaX = -1;
+ break;
+ case NORTH_WEST:
+ deltaX = -1;
+ deltaY = 1;
+ break;
+ }
+
+ return room.getLayout().getTile((short) (currentTile.x + deltaX), (short) (currentTile.y + deltaY));
+ }
+
+ private boolean canMoveTo(Room room, RoomUnit roomUnit, RoomTile targetTile) {
+ if (targetTile == null || targetTile.state == RoomTileState.INVALID || targetTile.state == RoomTileState.BLOCKED) {
+ return false;
+ }
+
+ if (!room.tileWalkable(targetTile)) {
+ return false;
+ }
+
+ for (RoomUnit unit : room.getRoomUnitsAt(targetTile)) {
+ if (unit != null && unit != roomUnit) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ static class JsonData {
+ int delay;
+ int movementDirection;
+ int rotationDirection;
+ int userSource;
+
+ public JsonData(int delay, int movementDirection, int rotationDirection, int userSource) {
+ this.delay = delay;
+ this.movementDirection = movementDirection;
+ this.rotationDirection = rotationDirection;
+ this.userSource = userSource;
+ }
+ }
+}
diff --git a/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectRelativeMove.java b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectRelativeMove.java
index e2fcf249..9ba042d5 100644
--- a/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectRelativeMove.java
+++ b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectRelativeMove.java
@@ -12,6 +12,7 @@ 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.WiredMoveCarryHelper;
import com.eu.habbo.habbohotel.wired.core.WiredSourceUtil;
import com.eu.habbo.messages.ServerMessage;
import com.eu.habbo.messages.incoming.wired.WiredSaveException;
@@ -81,7 +82,7 @@ public class WiredEffectRelativeMove extends InteractionWiredEffect {
continue;
}
- room.moveFurniTo(item, targetTile, item.getRotation(), null, true, false);
+ WiredMoveCarryHelper.moveFurni(room, this, item, targetTile, item.getRotation(), null, true, ctx);
}
}
diff --git a/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectSetAltitude.java b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectSetAltitude.java
index e43a4a68..9233daed 100644
--- a/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectSetAltitude.java
+++ b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectSetAltitude.java
@@ -12,6 +12,7 @@ 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.WiredMoveCarryHelper;
import com.eu.habbo.habbohotel.wired.core.WiredSourceUtil;
import com.eu.habbo.messages.ServerMessage;
import com.eu.habbo.messages.incoming.wired.WiredSaveException;
@@ -73,7 +74,7 @@ public class WiredEffectSetAltitude extends InteractionWiredEffect {
}
double nextAltitude = this.computeAltitude(item.getZ());
- room.moveFurniTo(item, tile, item.getRotation(), nextAltitude, null, true, false);
+ WiredMoveCarryHelper.moveFurni(room, this, item, tile, item.getRotation(), nextAltitude, null, true, ctx);
}
}
diff --git a/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectTeleport.java b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectTeleport.java
index 03ecbf13..591880ac 100644
--- a/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectTeleport.java
+++ b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectTeleport.java
@@ -39,6 +39,7 @@ public class WiredEffectTeleport extends InteractionWiredEffect {
public static final WiredEffectType type = WiredEffectType.TELEPORT;
protected List items;
+ private boolean fastTeleport = false;
private int furniSource = WiredSourceUtil.SOURCE_TRIGGER;
private int userSource = WiredSourceUtil.SOURCE_TRIGGER;
@@ -53,6 +54,10 @@ public class WiredEffectTeleport extends InteractionWiredEffect {
}
public static void teleportUnitToTile(RoomUnit roomUnit, RoomTile tile) {
+ teleportUnitToTile(roomUnit, tile, false);
+ }
+
+ public static void teleportUnitToTile(RoomUnit roomUnit, RoomTile tile, boolean fastTeleport) {
if (roomUnit == null || tile == null || roomUnit.isWiredTeleporting)
return;
@@ -85,9 +90,10 @@ public class WiredEffectTeleport extends InteractionWiredEffect {
// makes a temporary effect
+ int teleportDelay = getTeleportDelay(fastTeleport);
+
roomUnit.getRoom().unIdle(roomUnit.getRoom().getHabbo(roomUnit));
- room.sendComposer(new RoomUserEffectComposer(roomUnit, 4).compose());
- Emulator.getThreading().run(new SendRoomUnitEffectComposer(room, roomUnit), WiredManager.TELEPORT_DELAY + 1000);
+ sendTeleportEffect(room, roomUnit, fastTeleport);
if (tile == roomUnit.getCurrentLocation()) {
return;
@@ -110,8 +116,8 @@ public class WiredEffectTeleport extends InteractionWiredEffect {
}
}
- Emulator.getThreading().run(() -> { roomUnit.isWiredTeleporting = true; }, Math.max(0, WiredManager.TELEPORT_DELAY - 500));
- Emulator.getThreading().run(new RoomUnitTeleport(roomUnit, room, tile.x, tile.y, tile.getStackHeight() + (tile.state == RoomTileState.SIT ? -0.5 : 0), roomUnit.getEffectId()), WiredManager.TELEPORT_DELAY);
+ Emulator.getThreading().run(() -> { roomUnit.isWiredTeleporting = true; }, Math.max(0, teleportDelay - 500));
+ Emulator.getThreading().run(new RoomUnitTeleport(roomUnit, room, tile.x, tile.y, tile.getStackHeight() + (tile.state == RoomTileState.SIT ? -0.5 : 0), roomUnit.getEffectId()), teleportDelay);
}
@Override
@@ -137,7 +143,8 @@ public class WiredEffectTeleport extends InteractionWiredEffect {
message.appendInt(this.getBaseItem().getSpriteId());
message.appendInt(this.getId());
message.appendString("");
- message.appendInt(2);
+ message.appendInt(3);
+ message.appendInt(this.fastTeleport ? 1 : 0);
message.appendInt(this.furniSource);
message.appendInt(this.userSource);
message.appendInt(0);
@@ -166,8 +173,15 @@ public class WiredEffectTeleport extends InteractionWiredEffect {
@Override
public boolean saveData(WiredSettings settings, GameClient gameClient) throws WiredSaveException {
int[] params = settings.getIntParams();
- this.furniSource = (params.length > 0) ? params[0] : WiredSourceUtil.SOURCE_TRIGGER;
- this.userSource = (params.length > 1) ? params[1] : WiredSourceUtil.SOURCE_TRIGGER;
+ if (params.length > 2) {
+ this.fastTeleport = params[0] == 1;
+ this.furniSource = params[1];
+ this.userSource = params[2];
+ } else {
+ this.fastTeleport = false;
+ this.furniSource = (params.length > 0) ? params[0] : WiredSourceUtil.SOURCE_TRIGGER;
+ this.userSource = (params.length > 1) ? params[1] : WiredSourceUtil.SOURCE_TRIGGER;
+ }
int itemsCount = settings.getFurniIds().length;
@@ -227,7 +241,7 @@ public class WiredEffectTeleport extends InteractionWiredEffect {
RoomTile tile = room.getLayout().getTile(item.getX(), item.getY());
if (tile != null) {
- teleportUnitToTile(roomUnit, tile);
+ teleportUnitToTile(roomUnit, tile, this.fastTeleport);
}
}
}
@@ -244,6 +258,7 @@ public class WiredEffectTeleport extends InteractionWiredEffect {
return WiredManager.getGson().toJson(new JsonData(
this.getDelay(),
itemsSnapshot.stream().map(HabboItem::getId).collect(Collectors.toList()),
+ this.fastTeleport,
this.furniSource,
this.userSource
));
@@ -257,6 +272,7 @@ public class WiredEffectTeleport extends InteractionWiredEffect {
if (wiredData.startsWith("{")) {
JsonData data = WiredManager.getGson().fromJson(wiredData, JsonData.class);
this.setDelay(data.delay);
+ this.fastTeleport = data.fastTeleport;
this.furniSource = data.furniSource;
this.userSource = data.userSource;
for (Integer id: data.itemIds) {
@@ -284,6 +300,7 @@ public class WiredEffectTeleport extends InteractionWiredEffect {
}
}
}
+ this.fastTeleport = false;
this.furniSource = this.items.isEmpty() ? WiredSourceUtil.SOURCE_TRIGGER : WiredSourceUtil.SOURCE_SELECTED;
this.userSource = WiredSourceUtil.SOURCE_TRIGGER;
}
@@ -292,6 +309,7 @@ public class WiredEffectTeleport extends InteractionWiredEffect {
@Override
public void onPickUp() {
this.items.clear();
+ this.fastTeleport = false;
this.furniSource = WiredSourceUtil.SOURCE_TRIGGER;
this.userSource = WiredSourceUtil.SOURCE_TRIGGER;
this.setDelay(0);
@@ -312,15 +330,30 @@ public class WiredEffectTeleport extends InteractionWiredEffect {
return COOLDOWN_DEFAULT;
}
+ private static int getTeleportDelay(boolean fastTeleport) {
+ return fastTeleport ? Math.max(75, WiredManager.TELEPORT_DELAY / 5) : WiredManager.TELEPORT_DELAY;
+ }
+
+ private static int getTeleportEffectDuration(boolean fastTeleport) {
+ return fastTeleport ? Math.max(300, (WiredManager.TELEPORT_DELAY + 1000) / 3) : (WiredManager.TELEPORT_DELAY + 1000);
+ }
+
+ private static void sendTeleportEffect(Room room, RoomUnit roomUnit, boolean fastTeleport) {
+ room.sendComposer(new RoomUserEffectComposer(roomUnit, 4).compose());
+ Emulator.getThreading().run(new SendRoomUnitEffectComposer(room, roomUnit), getTeleportEffectDuration(fastTeleport));
+ }
+
static class JsonData {
int delay;
List itemIds;
+ boolean fastTeleport;
int furniSource;
int userSource;
- public JsonData(int delay, List itemIds, int furniSource, int userSource) {
+ public JsonData(int delay, List itemIds, boolean fastTeleport, int furniSource, int userSource) {
this.delay = delay;
this.itemIds = itemIds;
+ this.fastTeleport = fastTeleport;
this.furniSource = furniSource;
this.userSource = userSource;
}
diff --git a/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectToggleFurni.java b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectToggleFurni.java
index 09a14d67..5c4e4489 100644
--- a/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectToggleFurni.java
+++ b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectToggleFurni.java
@@ -39,10 +39,13 @@ import java.util.stream.Collectors;
public class WiredEffectToggleFurni extends InteractionWiredEffect {
private static final Logger LOGGER = LoggerFactory.getLogger(WiredEffectToggleFurni.class);
+ private static final int TOGGLE_TYPE_NEXT = 0;
+ private static final int TOGGLE_TYPE_PREVIOUS = 1;
public static final WiredEffectType type = WiredEffectType.TOGGLE_STATE;
private final THashSet items;
+ private int toggleType = TOGGLE_TYPE_NEXT;
private int furniSource = WiredSourceUtil.SOURCE_TRIGGER;
private static final List> FORBIDDEN_TYPES = new ArrayList>() {
@@ -122,7 +125,8 @@ public class WiredEffectToggleFurni extends InteractionWiredEffect {
message.appendInt(this.getBaseItem().getSpriteId());
message.appendInt(this.getId());
message.appendString("");
- message.appendInt(1);
+ message.appendInt(2);
+ message.appendInt(this.toggleType);
message.appendInt(this.furniSource);
message.appendInt(0);
message.appendInt(this.getType().code);
@@ -151,7 +155,13 @@ public class WiredEffectToggleFurni extends InteractionWiredEffect {
@Override
public boolean saveData(WiredSettings settings, GameClient gameClient) throws WiredSaveException {
int[] params = settings.getIntParams();
- this.furniSource = (params.length > 0) ? params[0] : WiredSourceUtil.SOURCE_TRIGGER;
+ if (params.length > 1) {
+ this.toggleType = normalizeToggleType(params[0]);
+ this.furniSource = params[1];
+ } else {
+ this.toggleType = TOGGLE_TYPE_NEXT;
+ this.furniSource = (params.length > 0) ? params[0] : WiredSourceUtil.SOURCE_TRIGGER;
+ }
int itemsCount = settings.getFurniIds().length;
@@ -204,15 +214,7 @@ public class WiredEffectToggleFurni extends InteractionWiredEffect {
try {
if (item.getBaseItem().getStateCount() > 1 || item instanceof InteractionGameTimer) {
- int state = 0;
- if (!item.getExtradata().isEmpty()) {
- try {
- state = Integer.parseInt(item.getExtradata()); // assumes that extradata is state, could be something else for trophies etc.
- } catch (NumberFormatException ignored) {
-
- }
- }
- item.onClick(habbo != null && !(item instanceof InteractionGameTimer) ? habbo.getClient() : null, room, new Object[]{state, this.getType()});
+ this.toggleItemState(room, habbo, item);
}
} catch (Exception e) {
LOGGER.error("Caught exception", e);
@@ -235,6 +237,7 @@ public class WiredEffectToggleFurni extends InteractionWiredEffect {
return WiredManager.getGson().toJson(new JsonData(
this.getDelay(),
new ArrayList<>(this.items).stream().map(HabboItem::getId).collect(Collectors.toList()),
+ this.toggleType,
this.furniSource
));
}
@@ -247,6 +250,7 @@ public class WiredEffectToggleFurni extends InteractionWiredEffect {
if (wiredData.startsWith("{")) {
JsonData data = WiredManager.getGson().fromJson(wiredData, JsonData.class);
this.setDelay(data.delay);
+ this.toggleType = normalizeToggleType(data.toggleType);
this.furniSource = data.furniSource;
for (Integer id: data.itemIds) {
HabboItem item = room.getHabboItem(id);
@@ -281,6 +285,7 @@ public class WiredEffectToggleFurni extends InteractionWiredEffect {
}
}
}
+ this.toggleType = TOGGLE_TYPE_NEXT;
this.furniSource = this.items.isEmpty() ? WiredSourceUtil.SOURCE_TRIGGER : WiredSourceUtil.SOURCE_SELECTED;
}
}
@@ -288,6 +293,7 @@ public class WiredEffectToggleFurni extends InteractionWiredEffect {
@Override
public void onPickUp() {
this.items.clear();
+ this.toggleType = TOGGLE_TYPE_NEXT;
this.furniSource = WiredSourceUtil.SOURCE_TRIGGER;
this.setDelay(0);
}
@@ -297,14 +303,52 @@ public class WiredEffectToggleFurni extends InteractionWiredEffect {
return type;
}
+ private int normalizeToggleType(int value) {
+ return (value == TOGGLE_TYPE_PREVIOUS) ? TOGGLE_TYPE_PREVIOUS : TOGGLE_TYPE_NEXT;
+ }
+
+ private void toggleItemState(Room room, Habbo habbo, HabboItem item) throws Exception {
+ if (item.getBaseItem().getStateCount() <= 1) {
+ return;
+ }
+
+ int stateCount = item.getBaseItem().getStateCount();
+ int currentState = 0;
+
+ if (!item.getExtradata().isEmpty()) {
+ try {
+ currentState = Integer.parseInt(item.getExtradata());
+ } catch (NumberFormatException ignored) {
+ if (this.toggleType == TOGGLE_TYPE_NEXT) {
+ item.onClick(habbo != null ? habbo.getClient() : null, room, new Object[]{0, this.getType()});
+ }
+ return;
+ }
+ }
+
+ int nextState = (this.toggleType == TOGGLE_TYPE_PREVIOUS)
+ ? ((currentState - 1 + stateCount) % stateCount)
+ : ((currentState + 1) % stateCount);
+
+ if (currentState == nextState) {
+ return;
+ }
+
+ item.setExtradata(Integer.toString(nextState));
+ item.needsUpdate(true);
+ room.updateItemState(item);
+ }
+
static class JsonData {
int delay;
List itemIds;
+ int toggleType;
int furniSource;
- public JsonData(int delay, List itemIds, int furniSource) {
+ public JsonData(int delay, List itemIds, int toggleType, int furniSource) {
this.delay = delay;
this.itemIds = itemIds;
+ this.toggleType = toggleType;
this.furniSource = furniSource;
}
}
diff --git a/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectUserToFurni.java b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectUserToFurni.java
index b5d50cc3..2d2491d5 100644
--- a/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectUserToFurni.java
+++ b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectUserToFurni.java
@@ -1,17 +1,39 @@
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.InteractionWiredTrigger;
+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.rooms.RoomUnitStatus;
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.WiredMoveCarryHelper;
+import com.eu.habbo.habbohotel.wired.core.WiredSourceUtil;
+import com.eu.habbo.habbohotel.wired.core.WiredUserMovementHelper;
+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 class WiredEffectUserToFurni extends WiredEffectUserFurniBase {
+ private static final int WALKMODE_IF_CLOSER = 0;
+ private static final int WALKMODE_CONTINUE = 1;
+ private static final int WALKMODE_STOP = 2;
+
public static final WiredEffectType type = WiredEffectType.USER_TO_FURNI;
+ private int walkMode = WALKMODE_CONTINUE;
public WiredEffectUserToFurni(ResultSet set, Item baseItem) throws SQLException {
super(set, baseItem);
@@ -30,8 +52,13 @@ public class WiredEffectUserToFurni extends WiredEffectUserFurniBase {
return;
}
+ RoomTile targetTile = room.getLayout().getTile(item.getX(), item.getY());
+ if (targetTile == null) {
+ return;
+ }
+
for (Habbo habbo : this.resolveHabbos(room, ctx)) {
- room.teleportHabboToItem(habbo, item);
+ this.moveHabboSmooth(room, habbo, item, targetTile);
}
}
@@ -45,4 +72,259 @@ public class WiredEffectUserToFurni extends WiredEffectUserFurniBase {
public WiredEffectType getType() {
return type;
}
+
+ @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,
+ this.walkMode
+ ));
+ }
+
+ @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;
+ this.walkMode = this.normalizeWalkMode((data.walkMode != null) ? data.walkMode : WALKMODE_CONTINUE);
+
+ 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;
+ }
+
+ return;
+ }
+
+ 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;
+ this.walkMode = WALKMODE_CONTINUE;
+ }
+
+ @Override
+ public void onPickUp() {
+ super.onPickUp();
+ this.walkMode = WALKMODE_CONTINUE;
+ }
+
+ @Override
+ public void serializeWiredData(ServerMessage message, Room room) {
+ List 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(3);
+ message.appendInt(this.furniSource);
+ message.appendInt(this.userSource);
+ message.appendInt(this.walkMode);
+ message.appendInt(0);
+ message.appendInt(this.getType().code);
+ message.appendInt(this.getDelay());
+
+ if (this.requiresTriggeringUser()) {
+ List invalidTriggers = new ArrayList<>();
+ room.getRoomSpecialTypes().getTriggers(this.getX(), this.getY()).forEach(new TObjectProcedure() {
+ @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 {
+ this.furniSource = (settings.getIntParams().length > 0) ? settings.getIntParams()[0] : WiredSourceUtil.SOURCE_TRIGGER;
+ this.userSource = (settings.getIntParams().length > 1) ? settings.getIntParams()[1] : WiredSourceUtil.SOURCE_TRIGGER;
+ this.walkMode = this.normalizeWalkMode((settings.getIntParams().length > 2) ? settings.getIntParams()[2] : WALKMODE_CONTINUE);
+
+ 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 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;
+ }
+
+ private void moveHabboSmooth(Room room, Habbo habbo, HabboItem item, RoomTile targetTile) {
+ if (room == null || habbo == null || item == null || targetTile == null || habbo.getRoomUnit() == null) {
+ return;
+ }
+
+ RoomUnit roomUnit = habbo.getRoomUnit();
+ RoomTile oldLocation = roomUnit.getCurrentLocation();
+ RoomTile previousGoal = roomUnit.getGoal();
+ boolean wasWalking = roomUnit.isWalking();
+ boolean noAnimation = WiredMoveCarryHelper.hasNoAnimationExtra(room, this);
+
+ if (oldLocation == null) {
+ return;
+ }
+
+ double newZ = item.getZ() + Item.getCurrentHeight(item);
+ int animationDuration = noAnimation ? 0 : WiredMoveCarryHelper.getAnimationDuration(room, this, WiredUserMovementHelper.DEFAULT_ANIMATION_DURATION);
+ if (!WiredUserMovementHelper.moveUser(room, roomUnit, targetTile, newZ,
+ roomUnit.getBodyRotation(), roomUnit.getHeadRotation(), animationDuration, noAnimation)) {
+ return;
+ }
+
+ this.applyWalkMode(roomUnit, oldLocation, previousGoal, targetTile, wasWalking,
+ animationDuration);
+ roomUnit.setPreviousLocationZ(roomUnit.getZ());
+ }
+
+ private void applyWalkMode(RoomUnit roomUnit, RoomTile oldLocation, RoomTile previousGoal, RoomTile targetTile, boolean wasWalking, int delay) {
+ if (roomUnit == null || targetTile == null) {
+ return;
+ }
+
+ Runnable applyGoal = () -> {
+ if (roomUnit.getCurrentLocation() == null
+ || roomUnit.isWalking()
+ || roomUnit.hasStatus(RoomUnitStatus.SIT)
+ || roomUnit.hasStatus(RoomUnitStatus.LAY)
+ || roomUnit.getCurrentLocation().x != targetTile.x
+ || roomUnit.getCurrentLocation().y != targetTile.y) {
+ return;
+ }
+
+ if (this.walkMode == WALKMODE_STOP || !wasWalking || previousGoal == null) {
+ roomUnit.setGoalLocation(targetTile);
+ return;
+ }
+
+ if (this.walkMode == WALKMODE_IF_CLOSER && !this.isCloserToGoal(oldLocation, targetTile, previousGoal)) {
+ roomUnit.setGoalLocation(targetTile);
+ return;
+ }
+
+ roomUnit.setGoalLocation(previousGoal);
+ };
+
+ if (delay > 0) {
+ Emulator.getThreading().run(applyGoal, delay);
+ return;
+ }
+
+ applyGoal.run();
+ }
+
+ private boolean isCloserToGoal(RoomTile oldLocation, RoomTile newLocation, RoomTile goalLocation) {
+ if (oldLocation == null || newLocation == null || goalLocation == null) {
+ return false;
+ }
+
+ return this.distanceSquared(newLocation, goalLocation) < this.distanceSquared(oldLocation, goalLocation);
+ }
+
+ private int distanceSquared(RoomTile first, RoomTile second) {
+ int dx = first.x - second.x;
+ int dy = first.y - second.y;
+ return (dx * dx) + (dy * dy);
+ }
+
+ private int normalizeWalkMode(int walkMode) {
+ if (walkMode < WALKMODE_IF_CLOSER || walkMode > WALKMODE_STOP) {
+ return WALKMODE_CONTINUE;
+ }
+
+ return walkMode;
+ }
+
+ static class JsonData {
+ int delay;
+ List itemIds;
+ int furniSource;
+ int userSource;
+ Integer walkMode;
+
+ public JsonData(int delay, List itemIds, int furniSource, int userSource, int walkMode) {
+ this.delay = delay;
+ this.itemIds = itemIds;
+ this.furniSource = furniSource;
+ this.userSource = userSource;
+ this.walkMode = walkMode;
+ }
+ }
}
diff --git a/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/extra/WiredExtraAnimationTime.java b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/extra/WiredExtraAnimationTime.java
new file mode 100644
index 00000000..2c9a1def
--- /dev/null
+++ b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/extra/WiredExtraAnimationTime.java
@@ -0,0 +1,125 @@
+package com.eu.habbo.habbohotel.items.interactions.wired.extra;
+
+import com.eu.habbo.habbohotel.gameclients.GameClient;
+import com.eu.habbo.habbohotel.items.Item;
+import com.eu.habbo.habbohotel.items.interactions.InteractionWiredExtra;
+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.core.WiredManager;
+import com.eu.habbo.messages.ServerMessage;
+import com.eu.habbo.messages.outgoing.rooms.WiredMovementsComposer;
+
+import java.sql.ResultSet;
+import java.sql.SQLException;
+
+public class WiredExtraAnimationTime extends InteractionWiredExtra {
+ public static final int CODE = 60;
+ public static final int MIN_DURATION_MS = 50;
+ public static final int MAX_DURATION_MS = 2000;
+
+ private int durationMs = WiredMovementsComposer.DEFAULT_DURATION;
+
+ public WiredExtraAnimationTime(ResultSet set, Item baseItem) throws SQLException {
+ super(set, baseItem);
+ }
+
+ public WiredExtraAnimationTime(int id, int userId, Item item, String extradata, int limitedStack, int limitedSells) {
+ super(id, userId, item, extradata, limitedStack, limitedSells);
+ }
+
+ @Override
+ public boolean execute(RoomUnit roomUnit, Room room, Object[] stuff) {
+ return false;
+ }
+
+ @Override
+ public boolean saveData(WiredSettings settings, GameClient gameClient) {
+ int value = (settings.getIntParams().length > 0) ? settings.getIntParams()[0] : this.durationMs;
+
+ if (value == this.durationMs && settings.getStringParam() != null && !settings.getStringParam().isEmpty()) {
+ try {
+ value = Integer.parseInt(settings.getStringParam());
+ } catch (NumberFormatException ignored) {
+ value = this.durationMs;
+ }
+ }
+
+ this.durationMs = normalizeDuration(value);
+ return true;
+ }
+
+ @Override
+ public String getWiredData() {
+ return WiredManager.getGson().toJson(new JsonData(this.durationMs));
+ }
+
+ @Override
+ public void serializeWiredData(ServerMessage message, Room room) {
+ message.appendBoolean(false);
+ message.appendInt(0);
+ message.appendInt(0);
+ message.appendInt(this.getBaseItem().getSpriteId());
+ message.appendInt(this.getId());
+ message.appendString("");
+ message.appendInt(1);
+ message.appendInt(this.durationMs);
+ message.appendInt(0);
+ message.appendInt(CODE);
+ message.appendInt(0);
+ message.appendInt(0);
+ }
+
+ @Override
+ public void loadWiredData(ResultSet set, Room room) throws SQLException {
+ this.onPickUp();
+
+ String wiredData = set.getString("wired_data");
+ if (wiredData == null || wiredData.isEmpty()) {
+ return;
+ }
+
+ if (wiredData.startsWith("{")) {
+ JsonData data = WiredManager.getGson().fromJson(wiredData, JsonData.class);
+ this.durationMs = normalizeDuration((data != null) ? data.durationMs : WiredMovementsComposer.DEFAULT_DURATION);
+ return;
+ }
+
+ try {
+ this.durationMs = normalizeDuration(Integer.parseInt(wiredData));
+ } catch (NumberFormatException ignored) {
+ this.durationMs = WiredMovementsComposer.DEFAULT_DURATION;
+ }
+ }
+
+ @Override
+ public void onPickUp() {
+ this.durationMs = WiredMovementsComposer.DEFAULT_DURATION;
+ }
+
+ @Override
+ public void onWalk(RoomUnit roomUnit, Room room, Object[] objects) throws Exception {
+
+ }
+
+ @Override
+ public boolean hasConfiguration() {
+ return true;
+ }
+
+ public int getDurationMs() {
+ return this.durationMs;
+ }
+
+ private static int normalizeDuration(int value) {
+ return Math.max(MIN_DURATION_MS, Math.min(MAX_DURATION_MS, value));
+ }
+
+ static class JsonData {
+ int durationMs;
+
+ JsonData(int durationMs) {
+ this.durationMs = durationMs;
+ }
+ }
+}
diff --git a/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/extra/WiredExtraFilterFurni.java b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/extra/WiredExtraFilterFurni.java
new file mode 100644
index 00000000..293b5fbf
--- /dev/null
+++ b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/extra/WiredExtraFilterFurni.java
@@ -0,0 +1,123 @@
+package com.eu.habbo.habbohotel.items.interactions.wired.extra;
+
+import com.eu.habbo.habbohotel.gameclients.GameClient;
+import com.eu.habbo.habbohotel.items.Item;
+import com.eu.habbo.habbohotel.items.interactions.InteractionWiredExtra;
+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.core.WiredManager;
+import com.eu.habbo.messages.ServerMessage;
+
+import java.sql.ResultSet;
+import java.sql.SQLException;
+
+public class WiredExtraFilterFurni extends InteractionWiredExtra {
+ public static final int CODE = 56;
+ private static final int MAX_FILTER_AMOUNT = 10000;
+
+ private int amount = 0;
+
+ public WiredExtraFilterFurni(ResultSet set, Item baseItem) throws SQLException {
+ super(set, baseItem);
+ }
+
+ public WiredExtraFilterFurni(int id, int userId, Item item, String extradata, int limitedStack, int limitedSells) {
+ super(id, userId, item, extradata, limitedStack, limitedSells);
+ }
+
+ @Override
+ public boolean execute(RoomUnit roomUnit, Room room, Object[] stuff) {
+ return false;
+ }
+
+ @Override
+ public boolean saveData(WiredSettings settings, GameClient gameClient) {
+ int value = (settings.getIntParams().length > 0) ? settings.getIntParams()[0] : 0;
+
+ if (value == 0 && settings.getStringParam() != null && !settings.getStringParam().isEmpty()) {
+ try {
+ value = Integer.parseInt(settings.getStringParam());
+ } catch (NumberFormatException ignored) {
+ value = 0;
+ }
+ }
+
+ this.amount = normalizeAmount(value);
+ return true;
+ }
+
+ @Override
+ public String getWiredData() {
+ return WiredManager.getGson().toJson(new JsonData(this.amount));
+ }
+
+ @Override
+ public void serializeWiredData(ServerMessage message, Room room) {
+ message.appendBoolean(false);
+ message.appendInt(0);
+ message.appendInt(0);
+ message.appendInt(this.getBaseItem().getSpriteId());
+ message.appendInt(this.getId());
+ message.appendString("");
+ message.appendInt(1);
+ message.appendInt(this.amount);
+ message.appendInt(0);
+ message.appendInt(CODE);
+ message.appendInt(0);
+ message.appendInt(0);
+ }
+
+ @Override
+ public void loadWiredData(ResultSet set, Room room) throws SQLException {
+ this.onPickUp();
+
+ String wiredData = set.getString("wired_data");
+ if (wiredData == null || wiredData.isEmpty()) {
+ return;
+ }
+
+ if (wiredData.startsWith("{")) {
+ JsonData data = WiredManager.getGson().fromJson(wiredData, JsonData.class);
+ this.amount = normalizeAmount((data != null) ? data.amount : 0);
+ return;
+ }
+
+ try {
+ this.amount = normalizeAmount(Integer.parseInt(wiredData));
+ } catch (NumberFormatException ignored) {
+ this.amount = 0;
+ }
+ }
+
+ @Override
+ public void onPickUp() {
+ this.amount = 0;
+ }
+
+ @Override
+ public void onWalk(RoomUnit roomUnit, Room room, Object[] objects) throws Exception {
+
+ }
+
+ @Override
+ public boolean hasConfiguration() {
+ return true;
+ }
+
+ public int getAmount() {
+ return this.amount;
+ }
+
+ private static int normalizeAmount(int value) {
+ return Math.max(0, Math.min(MAX_FILTER_AMOUNT, value));
+ }
+
+ static class JsonData {
+ int amount;
+
+ JsonData(int amount) {
+ this.amount = amount;
+ }
+ }
+}
diff --git a/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/extra/WiredExtraFilterUser.java b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/extra/WiredExtraFilterUser.java
new file mode 100644
index 00000000..bdc9c6c6
--- /dev/null
+++ b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/extra/WiredExtraFilterUser.java
@@ -0,0 +1,123 @@
+package com.eu.habbo.habbohotel.items.interactions.wired.extra;
+
+import com.eu.habbo.habbohotel.gameclients.GameClient;
+import com.eu.habbo.habbohotel.items.Item;
+import com.eu.habbo.habbohotel.items.interactions.InteractionWiredExtra;
+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.core.WiredManager;
+import com.eu.habbo.messages.ServerMessage;
+
+import java.sql.ResultSet;
+import java.sql.SQLException;
+
+public class WiredExtraFilterUser extends InteractionWiredExtra {
+ public static final int CODE = 57;
+ private static final int MAX_FILTER_AMOUNT = 10000;
+
+ private int amount = 0;
+
+ public WiredExtraFilterUser(ResultSet set, Item baseItem) throws SQLException {
+ super(set, baseItem);
+ }
+
+ public WiredExtraFilterUser(int id, int userId, Item item, String extradata, int limitedStack, int limitedSells) {
+ super(id, userId, item, extradata, limitedStack, limitedSells);
+ }
+
+ @Override
+ public boolean execute(RoomUnit roomUnit, Room room, Object[] stuff) {
+ return false;
+ }
+
+ @Override
+ public boolean saveData(WiredSettings settings, GameClient gameClient) {
+ int value = (settings.getIntParams().length > 0) ? settings.getIntParams()[0] : 0;
+
+ if (value == 0 && settings.getStringParam() != null && !settings.getStringParam().isEmpty()) {
+ try {
+ value = Integer.parseInt(settings.getStringParam());
+ } catch (NumberFormatException ignored) {
+ value = 0;
+ }
+ }
+
+ this.amount = normalizeAmount(value);
+ return true;
+ }
+
+ @Override
+ public String getWiredData() {
+ return WiredManager.getGson().toJson(new JsonData(this.amount));
+ }
+
+ @Override
+ public void serializeWiredData(ServerMessage message, Room room) {
+ message.appendBoolean(false);
+ message.appendInt(0);
+ message.appendInt(0);
+ message.appendInt(this.getBaseItem().getSpriteId());
+ message.appendInt(this.getId());
+ message.appendString("");
+ message.appendInt(1);
+ message.appendInt(this.amount);
+ message.appendInt(0);
+ message.appendInt(CODE);
+ message.appendInt(0);
+ message.appendInt(0);
+ }
+
+ @Override
+ public void loadWiredData(ResultSet set, Room room) throws SQLException {
+ this.onPickUp();
+
+ String wiredData = set.getString("wired_data");
+ if (wiredData == null || wiredData.isEmpty()) {
+ return;
+ }
+
+ if (wiredData.startsWith("{")) {
+ JsonData data = WiredManager.getGson().fromJson(wiredData, JsonData.class);
+ this.amount = normalizeAmount((data != null) ? data.amount : 0);
+ return;
+ }
+
+ try {
+ this.amount = normalizeAmount(Integer.parseInt(wiredData));
+ } catch (NumberFormatException ignored) {
+ this.amount = 0;
+ }
+ }
+
+ @Override
+ public void onPickUp() {
+ this.amount = 0;
+ }
+
+ @Override
+ public void onWalk(RoomUnit roomUnit, Room room, Object[] objects) throws Exception {
+
+ }
+
+ @Override
+ public boolean hasConfiguration() {
+ return true;
+ }
+
+ public int getAmount() {
+ return this.amount;
+ }
+
+ private static int normalizeAmount(int value) {
+ return Math.max(0, Math.min(MAX_FILTER_AMOUNT, value));
+ }
+
+ static class JsonData {
+ int amount;
+
+ JsonData(int amount) {
+ this.amount = amount;
+ }
+ }
+}
diff --git a/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/extra/WiredExtraMoveCarryUsers.java b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/extra/WiredExtraMoveCarryUsers.java
new file mode 100644
index 00000000..401f5cb4
--- /dev/null
+++ b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/extra/WiredExtraMoveCarryUsers.java
@@ -0,0 +1,157 @@
+package com.eu.habbo.habbohotel.items.interactions.wired.extra;
+
+import com.eu.habbo.habbohotel.gameclients.GameClient;
+import com.eu.habbo.habbohotel.items.Item;
+import com.eu.habbo.habbohotel.items.interactions.InteractionWiredExtra;
+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.core.WiredManager;
+import com.eu.habbo.habbohotel.wired.core.WiredSourceUtil;
+import com.eu.habbo.messages.ServerMessage;
+
+import java.sql.ResultSet;
+import java.sql.SQLException;
+
+public class WiredExtraMoveCarryUsers extends InteractionWiredExtra {
+ public static final int CODE = 58;
+ public static final int MODE_DIRECTLY_ON_FURNI = 0;
+ public static final int MODE_SAME_TILE = 1;
+ public static final int SOURCE_ALL_ROOM_USERS = 900;
+
+ private int carryMode = MODE_DIRECTLY_ON_FURNI;
+ private int userSource = WiredSourceUtil.SOURCE_TRIGGER;
+
+ public WiredExtraMoveCarryUsers(ResultSet set, Item baseItem) throws SQLException {
+ super(set, baseItem);
+ }
+
+ public WiredExtraMoveCarryUsers(int id, int userId, Item item, String extradata, int limitedStack, int limitedSells) {
+ super(id, userId, item, extradata, limitedStack, limitedSells);
+ }
+
+ @Override
+ public boolean execute(RoomUnit roomUnit, Room room, Object[] stuff) {
+ return false;
+ }
+
+ @Override
+ public boolean saveData(WiredSettings settings, GameClient gameClient) {
+ int[] params = settings.getIntParams();
+
+ this.carryMode = this.normalizeCarryMode((params.length > 0) ? params[0] : MODE_DIRECTLY_ON_FURNI);
+ this.userSource = this.normalizeUserSource((params.length > 1) ? params[1] : WiredSourceUtil.SOURCE_TRIGGER);
+
+ return true;
+ }
+
+ @Override
+ public String getWiredData() {
+ return WiredManager.getGson().toJson(new JsonData(this.carryMode, this.userSource));
+ }
+
+ @Override
+ public void serializeWiredData(ServerMessage message, Room room) {
+ message.appendBoolean(false);
+ message.appendInt(0);
+ message.appendInt(0);
+ message.appendInt(this.getBaseItem().getSpriteId());
+ message.appendInt(this.getId());
+ message.appendString("");
+ message.appendInt(2);
+ message.appendInt(this.carryMode);
+ message.appendInt(this.userSource);
+ message.appendInt(0);
+ message.appendInt(CODE);
+ message.appendInt(0);
+ message.appendInt(0);
+ }
+
+ @Override
+ public void loadWiredData(ResultSet set, Room room) throws SQLException {
+ this.onPickUp();
+
+ 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) {
+ this.carryMode = this.normalizeCarryMode(data.carryMode);
+ this.userSource = this.normalizeUserSource(data.userSource);
+ }
+
+ return;
+ }
+
+ String[] legacyData = wiredData.split("\t");
+ if (legacyData.length > 0) {
+ try {
+ this.carryMode = this.normalizeCarryMode(Integer.parseInt(legacyData[0]));
+ } catch (NumberFormatException ignored) {
+ this.carryMode = MODE_DIRECTLY_ON_FURNI;
+ }
+ }
+
+ if (legacyData.length > 1) {
+ try {
+ this.userSource = this.normalizeUserSource(Integer.parseInt(legacyData[1]));
+ } catch (NumberFormatException ignored) {
+ this.userSource = WiredSourceUtil.SOURCE_TRIGGER;
+ }
+ }
+ }
+
+ @Override
+ public void onPickUp() {
+ this.carryMode = MODE_DIRECTLY_ON_FURNI;
+ this.userSource = WiredSourceUtil.SOURCE_TRIGGER;
+ }
+
+ @Override
+ public void onWalk(RoomUnit roomUnit, Room room, Object[] objects) throws Exception {
+
+ }
+
+ @Override
+ public boolean hasConfiguration() {
+ return true;
+ }
+
+ public int getCarryMode() {
+ return this.carryMode;
+ }
+
+ public int getUserSource() {
+ return this.userSource;
+ }
+
+ private int normalizeCarryMode(int value) {
+ return (value == MODE_SAME_TILE) ? MODE_SAME_TILE : MODE_DIRECTLY_ON_FURNI;
+ }
+
+ private int normalizeUserSource(int value) {
+ switch (value) {
+ case SOURCE_ALL_ROOM_USERS:
+ case WiredSourceUtil.SOURCE_SELECTOR:
+ case WiredSourceUtil.SOURCE_SIGNAL:
+ case WiredSourceUtil.SOURCE_TRIGGER:
+ return value;
+ default:
+ return WiredSourceUtil.SOURCE_TRIGGER;
+ }
+ }
+
+ static class JsonData {
+ int carryMode;
+ int userSource;
+
+ JsonData(int carryMode, int userSource) {
+ this.carryMode = carryMode;
+ this.userSource = userSource;
+ }
+ }
+}
diff --git a/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/extra/WiredExtraMoveNoAnimation.java b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/extra/WiredExtraMoveNoAnimation.java
new file mode 100644
index 00000000..3149aae3
--- /dev/null
+++ b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/extra/WiredExtraMoveNoAnimation.java
@@ -0,0 +1,78 @@
+package com.eu.habbo.habbohotel.items.interactions.wired.extra;
+
+import com.eu.habbo.habbohotel.gameclients.GameClient;
+import com.eu.habbo.habbohotel.items.Item;
+import com.eu.habbo.habbohotel.items.interactions.InteractionWiredExtra;
+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.core.WiredManager;
+import com.eu.habbo.messages.ServerMessage;
+
+import java.sql.ResultSet;
+import java.sql.SQLException;
+
+public class WiredExtraMoveNoAnimation extends InteractionWiredExtra {
+ public static final int CODE = 59;
+
+ public WiredExtraMoveNoAnimation(ResultSet set, Item baseItem) throws SQLException {
+ super(set, baseItem);
+ }
+
+ public WiredExtraMoveNoAnimation(int id, int userId, Item item, String extradata, int limitedStack, int limitedSells) {
+ super(id, userId, item, extradata, limitedStack, limitedSells);
+ }
+
+ @Override
+ public boolean execute(RoomUnit roomUnit, Room room, Object[] stuff) {
+ return false;
+ }
+
+ @Override
+ public boolean saveData(WiredSettings settings, GameClient gameClient) {
+ return true;
+ }
+
+ @Override
+ public String getWiredData() {
+ return WiredManager.getGson().toJson(new JsonData());
+ }
+
+ @Override
+ public void serializeWiredData(ServerMessage message, Room room) {
+ message.appendBoolean(false);
+ message.appendInt(0);
+ message.appendInt(0);
+ message.appendInt(this.getBaseItem().getSpriteId());
+ message.appendInt(this.getId());
+ message.appendString("");
+ message.appendInt(0);
+ message.appendInt(0);
+ message.appendInt(CODE);
+ message.appendInt(0);
+ message.appendInt(0);
+ }
+
+ @Override
+ public void loadWiredData(ResultSet set, Room room) throws SQLException {
+ this.onPickUp();
+ }
+
+ @Override
+ public void onPickUp() {
+
+ }
+
+ @Override
+ public void onWalk(RoomUnit roomUnit, Room room, Object[] objects) throws Exception {
+
+ }
+
+ @Override
+ public boolean hasConfiguration() {
+ return true;
+ }
+
+ static class JsonData {
+ }
+}
diff --git a/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/extra/WiredExtraMovePhysics.java b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/extra/WiredExtraMovePhysics.java
new file mode 100644
index 00000000..cd890418
--- /dev/null
+++ b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/extra/WiredExtraMovePhysics.java
@@ -0,0 +1,229 @@
+package com.eu.habbo.habbohotel.items.interactions.wired.extra;
+
+import com.eu.habbo.habbohotel.gameclients.GameClient;
+import com.eu.habbo.habbohotel.items.Item;
+import com.eu.habbo.habbohotel.items.interactions.InteractionWiredExtra;
+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.core.WiredManager;
+import com.eu.habbo.habbohotel.wired.core.WiredSourceUtil;
+import com.eu.habbo.messages.ServerMessage;
+
+import java.sql.ResultSet;
+import java.sql.SQLException;
+
+public class WiredExtraMovePhysics extends InteractionWiredExtra {
+ public static final int CODE = 61;
+ public static final int SOURCE_ALL_ROOM = 900;
+
+ private boolean keepAltitude = false;
+ private boolean moveThroughFurni = false;
+ private boolean moveThroughUsers = false;
+ private boolean blockByFurni = false;
+ private int moveThroughFurniSource = WiredSourceUtil.SOURCE_TRIGGER;
+ private int moveThroughUsersSource = WiredSourceUtil.SOURCE_TRIGGER;
+ private int blockByFurniSource = WiredSourceUtil.SOURCE_TRIGGER;
+
+ public WiredExtraMovePhysics(ResultSet set, Item baseItem) throws SQLException {
+ super(set, baseItem);
+ }
+
+ public WiredExtraMovePhysics(int id, int userId, Item item, String extradata, int limitedStack, int limitedSells) {
+ super(id, userId, item, extradata, limitedStack, limitedSells);
+ }
+
+ @Override
+ public boolean execute(RoomUnit roomUnit, Room room, Object[] stuff) {
+ return false;
+ }
+
+ @Override
+ public boolean saveData(WiredSettings settings, GameClient gameClient) {
+ int[] params = settings.getIntParams();
+
+ this.keepAltitude = readFlag(params, 0);
+ this.moveThroughFurni = readFlag(params, 1);
+ this.moveThroughUsers = readFlag(params, 2);
+ this.blockByFurni = readFlag(params, 3);
+ this.moveThroughFurniSource = normalizeSource(readInt(params, 4, WiredSourceUtil.SOURCE_TRIGGER));
+ this.blockByFurniSource = normalizeSource(readInt(params, 5, WiredSourceUtil.SOURCE_TRIGGER));
+ this.moveThroughUsersSource = normalizeSource(readInt(params, 6, WiredSourceUtil.SOURCE_TRIGGER));
+
+ return true;
+ }
+
+ @Override
+ public String getWiredData() {
+ return WiredManager.getGson().toJson(new JsonData(
+ this.keepAltitude,
+ this.moveThroughFurni,
+ this.moveThroughUsers,
+ this.blockByFurni,
+ this.moveThroughFurniSource,
+ this.blockByFurniSource,
+ this.moveThroughUsersSource));
+ }
+
+ @Override
+ public void serializeWiredData(ServerMessage message, Room room) {
+ message.appendBoolean(false);
+ message.appendInt(0);
+ message.appendInt(0);
+ message.appendInt(this.getBaseItem().getSpriteId());
+ message.appendInt(this.getId());
+ message.appendString("");
+ message.appendInt(7);
+ message.appendInt(this.keepAltitude ? 1 : 0);
+ message.appendInt(this.moveThroughFurni ? 1 : 0);
+ message.appendInt(this.moveThroughUsers ? 1 : 0);
+ message.appendInt(this.blockByFurni ? 1 : 0);
+ message.appendInt(this.moveThroughFurniSource);
+ message.appendInt(this.blockByFurniSource);
+ message.appendInt(this.moveThroughUsersSource);
+ message.appendInt(0);
+ message.appendInt(CODE);
+ message.appendInt(0);
+ message.appendInt(0);
+ }
+
+ @Override
+ public void loadWiredData(ResultSet set, Room room) throws SQLException {
+ this.onPickUp();
+
+ 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) {
+ this.keepAltitude = data.keepAltitude;
+ this.moveThroughFurni = data.moveThroughFurni;
+ this.moveThroughUsers = data.moveThroughUsers;
+ this.blockByFurni = data.blockByFurni;
+ this.moveThroughFurniSource = normalizeSource(data.moveThroughFurniSource);
+ this.blockByFurniSource = normalizeSource(data.blockByFurniSource);
+ this.moveThroughUsersSource = normalizeSource(data.moveThroughUsersSource);
+ }
+
+ return;
+ }
+
+ String[] legacyData = wiredData.split("\t");
+ this.keepAltitude = readLegacyFlag(legacyData, 0);
+ this.moveThroughFurni = readLegacyFlag(legacyData, 1);
+ this.moveThroughUsers = readLegacyFlag(legacyData, 2);
+ this.blockByFurni = readLegacyFlag(legacyData, 3);
+ this.moveThroughFurniSource = normalizeSource(readLegacyInt(legacyData, 4, WiredSourceUtil.SOURCE_TRIGGER));
+ this.blockByFurniSource = normalizeSource(readLegacyInt(legacyData, 5, WiredSourceUtil.SOURCE_TRIGGER));
+ this.moveThroughUsersSource = normalizeSource(readLegacyInt(legacyData, 6, WiredSourceUtil.SOURCE_TRIGGER));
+ }
+
+ @Override
+ public void onPickUp() {
+ this.keepAltitude = false;
+ this.moveThroughFurni = false;
+ this.moveThroughUsers = false;
+ this.blockByFurni = false;
+ this.moveThroughFurniSource = WiredSourceUtil.SOURCE_TRIGGER;
+ this.moveThroughUsersSource = WiredSourceUtil.SOURCE_TRIGGER;
+ this.blockByFurniSource = WiredSourceUtil.SOURCE_TRIGGER;
+ }
+
+ @Override
+ public void onWalk(RoomUnit roomUnit, Room room, Object[] objects) throws Exception {
+
+ }
+
+ @Override
+ public boolean hasConfiguration() {
+ return true;
+ }
+
+ public boolean isKeepAltitude() {
+ return this.keepAltitude;
+ }
+
+ public boolean isMoveThroughFurni() {
+ return this.moveThroughFurni;
+ }
+
+ public boolean isMoveThroughUsers() {
+ return this.moveThroughUsers;
+ }
+
+ public boolean isBlockByFurni() {
+ return this.blockByFurni;
+ }
+
+ public int getMoveThroughFurniSource() {
+ return this.moveThroughFurniSource;
+ }
+
+ public int getMoveThroughUsersSource() {
+ return this.moveThroughUsersSource;
+ }
+
+ public int getBlockByFurniSource() {
+ return this.blockByFurniSource;
+ }
+
+ private static boolean readFlag(int[] params, int index) {
+ return readInt(params, index, 0) == 1;
+ }
+
+ private static int readInt(int[] params, int index, int fallback) {
+ return (params.length > index) ? params[index] : fallback;
+ }
+
+ private static boolean readLegacyFlag(String[] data, int index) {
+ return readLegacyInt(data, index, 0) == 1;
+ }
+
+ private static int readLegacyInt(String[] data, int index, int fallback) {
+ if (data.length <= index) {
+ return fallback;
+ }
+
+ try {
+ return Integer.parseInt(data[index]);
+ } catch (NumberFormatException ignored) {
+ return fallback;
+ }
+ }
+
+ private static int normalizeSource(int value) {
+ switch (value) {
+ case SOURCE_ALL_ROOM:
+ case WiredSourceUtil.SOURCE_TRIGGER:
+ case WiredSourceUtil.SOURCE_SELECTOR:
+ case WiredSourceUtil.SOURCE_SIGNAL:
+ return value;
+ default:
+ return WiredSourceUtil.SOURCE_TRIGGER;
+ }
+ }
+
+ static class JsonData {
+ boolean keepAltitude;
+ boolean moveThroughFurni;
+ boolean moveThroughUsers;
+ boolean blockByFurni;
+ int moveThroughFurniSource;
+ int blockByFurniSource;
+ int moveThroughUsersSource;
+
+ JsonData(boolean keepAltitude, boolean moveThroughFurni, boolean moveThroughUsers, boolean blockByFurni, int moveThroughFurniSource, int blockByFurniSource, int moveThroughUsersSource) {
+ this.keepAltitude = keepAltitude;
+ this.moveThroughFurni = moveThroughFurni;
+ this.moveThroughUsers = moveThroughUsers;
+ this.blockByFurni = blockByFurni;
+ this.moveThroughFurniSource = moveThroughFurniSource;
+ this.blockByFurniSource = blockByFurniSource;
+ this.moveThroughUsersSource = moveThroughUsersSource;
+ }
+ }
+}
diff --git a/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/interfaces/InteractionWiredMatchFurniSettings.java b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/interfaces/InteractionWiredMatchFurniSettings.java
index 6db447f7..25bbb7b4 100644
--- a/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/interfaces/InteractionWiredMatchFurniSettings.java
+++ b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/interfaces/InteractionWiredMatchFurniSettings.java
@@ -8,4 +8,5 @@ public interface InteractionWiredMatchFurniSettings {
public boolean shouldMatchState();
public boolean shouldMatchRotation();
public boolean shouldMatchPosition();
+ public boolean shouldMatchAltitude();
}
diff --git a/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/selector/WiredEffectFurniAltitude.java b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/selector/WiredEffectFurniAltitude.java
new file mode 100644
index 00000000..a2b6473a
--- /dev/null
+++ b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/selector/WiredEffectFurniAltitude.java
@@ -0,0 +1,223 @@
+package com.eu.habbo.habbohotel.items.interactions.wired.selector;
+
+import com.eu.habbo.habbohotel.gameclients.GameClient;
+import com.eu.habbo.habbohotel.items.Item;
+import com.eu.habbo.habbohotel.items.interactions.InteractionWired;
+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.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.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.LinkedHashSet;
+import java.util.Set;
+
+public class WiredEffectFurniAltitude extends InteractionWiredEffect {
+ private static final int COMPARISON_LESS = 0;
+ private static final int COMPARISON_EQUAL = 1;
+ private static final int COMPARISON_GREATER = 2;
+
+ public static final WiredEffectType type = WiredEffectType.FURNI_ALTITUDE_SELECTOR;
+
+ private int comparison = COMPARISON_EQUAL;
+ private double altitude = 0.0D;
+ private boolean filterExisting = false;
+ private boolean invert = false;
+
+ public WiredEffectFurniAltitude(ResultSet set, Item baseItem) throws SQLException {
+ super(set, baseItem);
+ }
+
+ public WiredEffectFurniAltitude(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;
+ }
+
+ Set matchingItems = new LinkedHashSet<>();
+
+ room.getFloorItems().forEach(item -> {
+ if (item == null || item instanceof InteractionWired) {
+ return;
+ }
+
+ if (this.matchesAltitude(item)) {
+ matchingItems.add(item);
+ }
+ });
+
+ Set result = new LinkedHashSet<>(matchingItems);
+
+ result = this.applySelectorModifiers(result, this.getSelectableFloorItems(room), ctx.targets().items(), this.filterExisting, this.invert);
+
+ ctx.targets().setItems(result);
+ }
+
+ @Override
+ public boolean saveData(WiredSettings settings, GameClient gameClient) throws WiredSaveException {
+ int[] params = settings.getIntParams();
+ if (params == null || params.length < 3) {
+ throw new WiredSaveException("wf_slc_furni_altitude requires 3 int params: comparison, filterExisting, invert");
+ }
+
+ this.comparison = this.normalizeComparison(params[0]);
+ this.filterExisting = params[1] == 1;
+ this.invert = params[2] == 1;
+ this.altitude = this.parseAltitudeOrDefault(settings.getStringParam());
+ this.setDelay(settings.getDelay());
+
+ return true;
+ }
+
+ @Override
+ public WiredEffectType getType() {
+ return type;
+ }
+
+ @Override
+ public boolean isSelector() {
+ return true;
+ }
+
+ @Override
+ public String getWiredData() {
+ return WiredManager.getGson().toJson(new JsonData(
+ this.comparison,
+ this.formatAltitude(this.altitude),
+ this.filterExisting,
+ this.invert,
+ this.getDelay()
+ ));
+ }
+
+ @Override
+ public void loadWiredData(ResultSet set, Room room) throws SQLException {
+ this.onPickUp();
+
+ 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.filterExisting = data.filterExisting;
+ this.invert = data.invert;
+ this.setDelay(data.delay);
+ }
+
+ @Override
+ public void onPickUp() {
+ this.comparison = COMPARISON_EQUAL;
+ this.altitude = 0.0D;
+ this.filterExisting = false;
+ this.invert = false;
+ this.setDelay(0);
+ }
+
+ @Override
+ public void serializeWiredData(ServerMessage message, Room room) {
+ message.appendBoolean(false);
+ message.appendInt(0);
+ message.appendInt(0);
+
+ 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.filterExisting ? 1 : 0);
+ message.appendInt(this.invert ? 1 : 0);
+ message.appendInt(0);
+ message.appendInt(this.getType().code);
+ message.appendInt(this.getDelay());
+ message.appendInt(0);
+ }
+
+ @Override
+ public boolean execute(RoomUnit roomUnit, Room room, Object[] stuff) {
+ return false;
+ }
+
+ 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 int normalizeComparison(int value) {
+ if (value < COMPARISON_LESS || value > COMPARISON_GREATER) {
+ return COMPARISON_EQUAL;
+ }
+
+ return value;
+ }
+
+ 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;
+ boolean filterExisting;
+ boolean invert;
+ int delay;
+
+ JsonData(int comparison, String altitude, boolean filterExisting, boolean invert, int delay) {
+ this.comparison = comparison;
+ this.altitude = altitude;
+ this.filterExisting = filterExisting;
+ this.invert = invert;
+ this.delay = delay;
+ }
+ }
+}
diff --git a/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/selector/WiredEffectFurniArea.java b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/selector/WiredEffectFurniArea.java
index 30db5f3d..8b223fe5 100644
--- a/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/selector/WiredEffectFurniArea.java
+++ b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/selector/WiredEffectFurniArea.java
@@ -28,6 +28,8 @@ public class WiredEffectFurniArea extends InteractionWiredEffect {
private int rootY = 0;
private int areaWidth = 0;
private int areaHeight = 0;
+ private boolean filterExisting = false;
+ private boolean invert = false;
public WiredEffectFurniArea(ResultSet set, Item baseItem) throws SQLException {
super(set, baseItem);
@@ -43,9 +45,12 @@ public class WiredEffectFurniArea extends InteractionWiredEffect {
if (room == null || areaWidth <= 0 || areaHeight <= 0) return;
List furniInArea = getFurniInArea(room);
- if (!furniInArea.isEmpty()) {
- ctx.targets().setItems(furniInArea);
- }
+ ctx.targets().setItems(this.applySelectorModifiers(
+ furniInArea,
+ this.getSelectableFloorItems(room),
+ ctx.targets().items(),
+ this.filterExisting,
+ this.invert));
}
private List getFurniInArea(Room room) {
@@ -78,6 +83,8 @@ public class WiredEffectFurniArea extends InteractionWiredEffect {
this.rootY = params[1];
this.areaWidth = params[2];
this.areaHeight = params[3];
+ this.filterExisting = params.length >= 5 && params[4] == 1;
+ this.invert = params.length >= 6 && params[5] == 1;
this.setDelay(settings.getDelay());
return true;
@@ -95,7 +102,7 @@ public class WiredEffectFurniArea extends InteractionWiredEffect {
@Override
public String getWiredData() {
- return WiredManager.getGson().toJson(new JsonData(rootX, rootY, areaWidth, areaHeight, getDelay()));
+ return WiredManager.getGson().toJson(new JsonData(rootX, rootY, areaWidth, areaHeight, filterExisting, invert, getDelay()));
}
@Override
@@ -108,6 +115,8 @@ public class WiredEffectFurniArea extends InteractionWiredEffect {
this.rootY = data.rootY;
this.areaWidth = data.width;
this.areaHeight = data.height;
+ this.filterExisting = data.filterExisting;
+ this.invert = data.invert;
this.setDelay(data.delay);
}
}
@@ -118,6 +127,8 @@ public class WiredEffectFurniArea extends InteractionWiredEffect {
this.rootY = 0;
this.areaWidth = 0;
this.areaHeight = 0;
+ this.filterExisting = false;
+ this.invert = false;
this.setDelay(0);
}
@@ -131,11 +142,13 @@ public class WiredEffectFurniArea extends InteractionWiredEffect {
message.appendInt(this.getBaseItem().getSpriteId());
message.appendInt(this.getId());
message.appendString("");
- message.appendInt(4);
+ message.appendInt(6);
message.appendInt(this.rootX);
message.appendInt(this.rootY);
message.appendInt(this.areaWidth);
message.appendInt(this.areaHeight);
+ message.appendInt(this.filterExisting ? 1 : 0);
+ message.appendInt(this.invert ? 1 : 0);
message.appendInt(0);
message.appendInt(this.getType().code);
@@ -153,13 +166,17 @@ public class WiredEffectFurniArea extends InteractionWiredEffect {
int rootY;
int width;
int height;
+ boolean filterExisting;
+ boolean invert;
int delay;
- JsonData(int rootX, int rootY, int width, int height, int delay) {
+ JsonData(int rootX, int rootY, int width, int height, boolean filterExisting, boolean invert, int delay) {
this.rootX = rootX;
this.rootY = rootY;
this.width = width;
this.height = height;
+ this.filterExisting = filterExisting;
+ this.invert = invert;
this.delay = delay;
}
}
diff --git a/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/selector/WiredEffectFurniByType.java b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/selector/WiredEffectFurniByType.java
index 14bae162..e936fabe 100644
--- a/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/selector/WiredEffectFurniByType.java
+++ b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/selector/WiredEffectFurniByType.java
@@ -59,33 +59,19 @@ public class WiredEffectFurniByType extends InteractionWiredEffect {
matchKeys.add(key);
}
- Set result = new LinkedHashSet<>();
+ Set matched = new LinkedHashSet<>();
room.getFloorItems().forEach(item -> {
if (item instanceof InteractionWired) return;
String key = matchState
? item.getBaseItem().getId() + ":" + item.getExtradata()
: String.valueOf(item.getBaseItem().getId());
if (matchKeys.contains(key)) {
- result.add(item);
+ matched.add(item);
}
});
- if (filterExisting) {
- result.retainAll(ctx.targets().items());
- }
-
- if (invert) {
- Set all = new LinkedHashSet<>();
- room.getFloorItems().forEach(item -> {
- if (!(item instanceof InteractionWired)) all.add(item);
- });
- all.removeAll(result);
- if (!all.isEmpty()) {
- ctx.targets().setItems(all);
- }
- } else if (!result.isEmpty()) {
- ctx.targets().setItems(result);
- }
+ Set result = this.applySelectorModifiers(matched, this.getSelectableFloorItems(room), ctx.targets().items(), filterExisting, invert);
+ ctx.targets().setItems(result);
}
private List resolveSourceFurni(WiredContext ctx, Room room) {
diff --git a/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/selector/WiredEffectFurniNeighborhood.java b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/selector/WiredEffectFurniNeighborhood.java
index f3439707..2dd2c5b5 100644
--- a/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/selector/WiredEffectFurniNeighborhood.java
+++ b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/selector/WiredEffectFurniNeighborhood.java
@@ -42,6 +42,8 @@ public class WiredEffectFurniNeighborhood extends InteractionWiredEffect {
private int sourceType = SOURCE_USER_TRIGGER;
private boolean filterExisting = false;
private boolean invert = false;
+ private int targetOffsetX = 0;
+ private int targetOffsetY = 0;
private List tileOffsets = new ArrayList<>();
private List pickedFurniIds = new ArrayList<>();
@@ -68,8 +70,8 @@ public class WiredEffectFurniNeighborhood extends InteractionWiredEffect {
for (int[] src : sourcePositions) {
LOGGER.info("[FurniNeighborhood] Source: ({},{}), offsets: {}", src[0], src[1], tileOffsets.size());
for (int[] offset : tileOffsets) {
- int tx = src[0] + offset[0];
- int ty = src[1] + offset[1];
+ int tx = src[0] + (offset[0] - this.targetOffsetX);
+ int ty = src[1] + (offset[1] - this.targetOffsetY);
for (HabboItem item : room.getItemsAt(tx, ty)) {
if (item == null) continue;
totalRaw++;
@@ -87,18 +89,7 @@ public class WiredEffectFurniNeighborhood extends InteractionWiredEffect {
}
LOGGER.info("[FurniNeighborhood] Raw={}, wiredSkipped={}, kept={}", totalRaw, wiredSkipped, result.size());
- if (filterExisting) {
- result.retainAll(ctx.targets().items());
- }
-
- if (invert) {
- Set all = new LinkedHashSet<>();
- room.getFloorItems().forEach(item -> {
- if (!(item instanceof InteractionWired)) all.add(item);
- });
- all.removeAll(result);
- result = all;
- }
+ result = this.applySelectorModifiers(result, this.getSelectableFloorItems(room), ctx.targets().items(), filterExisting, invert);
// Always set the selector result — even if empty.
// An empty result means no items matched the neighborhood, so downstream
@@ -158,12 +149,14 @@ public class WiredEffectFurniNeighborhood extends InteractionWiredEffect {
this.sourceType = params[0];
this.filterExisting = params.length > 1 && params[1] == 1;
this.invert = params.length > 2 && params[2] == 1;
+ this.targetOffsetX = params.length > 3 ? params[3] : 0;
+ this.targetOffsetY = params.length > 4 ? params[4] : 0;
this.tileOffsets = new ArrayList<>();
- if (params.length > 3) {
- int n = params[3];
+ if (params.length > 5) {
+ int n = params[5];
for (int i = 0; i < n && i < MAX_TILE_OFFSETS; i++) {
- int xi = 4 + i * 2;
+ int xi = 6 + i * 2;
if (xi + 1 < params.length) {
tileOffsets.add(new int[]{ params[xi], params[xi + 1] });
}
@@ -180,8 +173,8 @@ public class WiredEffectFurniNeighborhood extends InteractionWiredEffect {
this.setDelay(settings.getDelay());
- LOGGER.info("[FurniNeighborhood] saveData: sourceType={}, filterExisting={}, invert={}, offsets={}, pickedFurniIds={}",
- sourceType, filterExisting, invert, tileOffsets.size(), pickedFurniIds);
+ LOGGER.info("[FurniNeighborhood] saveData: sourceType={}, filterExisting={}, invert={}, target=({},{}), offsets={}, pickedFurniIds={}",
+ sourceType, filterExisting, invert, targetOffsetX, targetOffsetY, tileOffsets.size(), pickedFurniIds);
for (int[] o : tileOffsets) {
LOGGER.info("[FurniNeighborhood] offset: ({}, {})", o[0], o[1]);
}
@@ -208,11 +201,13 @@ public class WiredEffectFurniNeighborhood extends InteractionWiredEffect {
message.appendInt(this.getId());
message.appendString("");
- int paramCount = 4 + tileOffsets.size() * 2;
+ int paramCount = 6 + tileOffsets.size() * 2;
message.appendInt(paramCount);
message.appendInt(sourceType);
message.appendInt(filterExisting ? 1 : 0);
message.appendInt(invert ? 1 : 0);
+ message.appendInt(targetOffsetX);
+ message.appendInt(targetOffsetY);
message.appendInt(tileOffsets.size());
for (int[] offset : tileOffsets) {
message.appendInt(offset[0]);
@@ -236,7 +231,7 @@ public class WiredEffectFurniNeighborhood extends InteractionWiredEffect {
@Override
public String getWiredData() {
return WiredManager.getGson().toJson(
- new JsonData(sourceType, filterExisting, invert, tileOffsets, pickedFurniIds, getDelay()));
+ new JsonData(sourceType, filterExisting, invert, targetOffsetX, targetOffsetY, tileOffsets, pickedFurniIds, getDelay()));
}
@Override
@@ -247,6 +242,8 @@ public class WiredEffectFurniNeighborhood extends InteractionWiredEffect {
this.sourceType = data.sourceType;
this.filterExisting = data.filterExisting;
this.invert = data.invert;
+ this.targetOffsetX = data.targetOffsetX;
+ this.targetOffsetY = data.targetOffsetY;
this.tileOffsets = data.tileOffsets != null ? data.tileOffsets : new ArrayList<>();
this.pickedFurniIds = data.pickedFurniIds != null ? data.pickedFurniIds : new ArrayList<>();
this.setDelay(data.delay);
@@ -258,6 +255,8 @@ public class WiredEffectFurniNeighborhood extends InteractionWiredEffect {
this.sourceType = SOURCE_USER_TRIGGER;
this.filterExisting = false;
this.invert = false;
+ this.targetOffsetX = 0;
+ this.targetOffsetY = 0;
this.tileOffsets = new ArrayList<>();
this.pickedFurniIds = new ArrayList<>();
this.setDelay(0);
@@ -270,15 +269,19 @@ public class WiredEffectFurniNeighborhood extends InteractionWiredEffect {
int sourceType;
boolean filterExisting;
boolean invert;
+ int targetOffsetX;
+ int targetOffsetY;
List tileOffsets;
List pickedFurniIds;
int delay;
- JsonData(int sourceType, boolean filterExisting, boolean invert,
+ JsonData(int sourceType, boolean filterExisting, boolean invert, int targetOffsetX, int targetOffsetY,
List tileOffsets, List pickedFurniIds, int delay) {
this.sourceType = sourceType;
this.filterExisting = filterExisting;
this.invert = invert;
+ this.targetOffsetX = targetOffsetX;
+ this.targetOffsetY = targetOffsetY;
this.tileOffsets = tileOffsets;
this.pickedFurniIds = pickedFurniIds;
this.delay = delay;
diff --git a/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/selector/WiredEffectFurniOnFurni.java b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/selector/WiredEffectFurniOnFurni.java
new file mode 100644
index 00000000..0ec8730c
--- /dev/null
+++ b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/selector/WiredEffectFurniOnFurni.java
@@ -0,0 +1,335 @@
+package com.eu.habbo.habbohotel.items.interactions.wired.selector;
+
+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.InteractionWired;
+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 java.math.BigDecimal;
+import java.math.RoundingMode;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.Collections;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+public class WiredEffectFurniOnFurni extends InteractionWiredEffect {
+ private static final double EPSILON = 0.0001D;
+
+ private static final int SELECT_FURNI_ABOVE = 0;
+ private static final int SELECT_FURNI_BELOW = 1;
+ private static final int SELECT_FURNI_SAME_HEIGHT = 2;
+ private static final int SELECT_ALL_FURNI_ON_TILE = 3;
+
+ public static final WiredEffectType type = WiredEffectType.FURNI_ON_FURNI_SELECTOR;
+
+ private final Set items = new LinkedHashSet<>();
+ private int selectionType = SELECT_FURNI_ABOVE;
+ private int furniSource = WiredSourceUtil.SOURCE_TRIGGER;
+ private boolean filterExisting = false;
+ private boolean invert = false;
+
+ public WiredEffectFurniOnFurni(ResultSet set, Item baseItem) throws SQLException {
+ super(set, baseItem);
+ }
+
+ public WiredEffectFurniOnFurni(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) {
+ ctx.targets().setItems(Collections.emptySet());
+ return;
+ }
+
+ this.refresh(room);
+
+ List sourceItems = WiredSourceUtil.resolveItems(ctx, this.furniSource, this.items);
+ if (sourceItems.isEmpty()) {
+ ctx.targets().setItems(Collections.emptySet());
+ return;
+ }
+
+ Set result = new LinkedHashSet<>();
+
+ for (HabboItem sourceItem : sourceItems) {
+ result.addAll(this.resolveRelatedItems(room, sourceItem));
+ }
+
+ result = this.applySelectorModifiers(result, this.getSelectableFloorItems(room), ctx.targets().items(), this.filterExisting, this.invert);
+
+ ctx.targets().setItems(result);
+ }
+
+ @Override
+ public boolean saveData(WiredSettings settings, GameClient gameClient) {
+ int[] params = settings.getIntParams();
+
+ this.selectionType = (params.length > 0) ? this.normalizeSelectionType(params[0]) : SELECT_FURNI_ABOVE;
+ this.furniSource = (params.length > 1) ? this.normalizeFurniSource(params[1]) : WiredSourceUtil.SOURCE_TRIGGER;
+ this.filterExisting = params.length > 2 && params[2] == 1;
+ this.invert = params.length > 3 && params[3] == 1;
+
+ 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);
+ }
+ }
+ }
+
+ this.setDelay(settings.getDelay());
+ return true;
+ }
+
+ @Override
+ public WiredEffectType getType() {
+ return type;
+ }
+
+ @Override
+ public boolean isSelector() {
+ return true;
+ }
+
+ @Override
+ public String getWiredData() {
+ this.refresh(Emulator.getGameEnvironment().getRoomManager().getRoom(this.getRoomId()));
+
+ return WiredManager.getGson().toJson(new JsonData(
+ this.selectionType,
+ this.furniSource,
+ this.filterExisting,
+ this.invert,
+ this.items.stream().map(HabboItem::getId).collect(Collectors.toList()),
+ this.getDelay()
+ ));
+ }
+
+ @Override
+ public void loadWiredData(ResultSet set, Room room) throws SQLException {
+ this.onPickUp();
+
+ 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.selectionType = this.normalizeSelectionType(data.selectionType);
+ this.furniSource = this.normalizeFurniSource(data.furniSource);
+ this.filterExisting = data.filterExisting;
+ this.invert = data.invert;
+ this.setDelay(data.delay);
+
+ if (room == null || 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.selectionType = SELECT_FURNI_ABOVE;
+ this.furniSource = WiredSourceUtil.SOURCE_TRIGGER;
+ this.filterExisting = false;
+ this.invert = false;
+ this.setDelay(0);
+ }
+
+ @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("");
+ message.appendInt(4);
+ message.appendInt(this.selectionType);
+ message.appendInt(this.furniSource);
+ message.appendInt(this.filterExisting ? 1 : 0);
+ message.appendInt(this.invert ? 1 : 0);
+ message.appendInt(0);
+ message.appendInt(this.getType().code);
+ message.appendInt(this.getDelay());
+ message.appendInt(0);
+ }
+
+ @Override
+ public boolean execute(RoomUnit roomUnit, Room room, Object[] stuff) {
+ return false;
+ }
+
+ private Set resolveRelatedItems(Room room, HabboItem sourceItem) {
+ Set result = new LinkedHashSet<>();
+
+ if (sourceItem == null) {
+ return result;
+ }
+
+ RoomTile baseTile = room.getLayout().getTile(sourceItem.getX(), sourceItem.getY());
+ if (baseTile == null) {
+ return result;
+ }
+
+ Set occupiedTiles = room.getLayout().getTilesAt(baseTile, sourceItem.getBaseItem().getWidth(), sourceItem.getBaseItem().getLength(), sourceItem.getRotation());
+ if (occupiedTiles == null) {
+ return result;
+ }
+
+ double sourceBase = this.normalizeAltitude(sourceItem.getZ());
+ double sourceTop = this.normalizeAltitude(sourceItem.getZ() + Item.getCurrentHeight(sourceItem));
+
+ for (RoomTile tile : occupiedTiles) {
+ if (tile == null) {
+ continue;
+ }
+
+ for (HabboItem matchedItem : room.getItemsAt(tile)) {
+ if (matchedItem == null || matchedItem instanceof InteractionWired) {
+ continue;
+ }
+
+ if (matchedItem == sourceItem) {
+ if (this.selectionType == SELECT_FURNI_SAME_HEIGHT || this.selectionType == SELECT_ALL_FURNI_ON_TILE) {
+ result.add(matchedItem);
+ }
+ continue;
+ }
+
+ if (this.matchesSelectionType(sourceBase, sourceTop, matchedItem)) {
+ result.add(matchedItem);
+ }
+ }
+ }
+
+ return result;
+ }
+
+ private boolean matchesSelectionType(double sourceBase, double sourceTop, HabboItem matchedItem) {
+ double matchedBase = this.normalizeAltitude(matchedItem.getZ());
+ double matchedTop = this.normalizeAltitude(matchedItem.getZ() + Item.getCurrentHeight(matchedItem));
+
+ switch (this.selectionType) {
+ case SELECT_FURNI_BELOW:
+ return matchedTop <= (sourceBase + EPSILON);
+ case SELECT_FURNI_SAME_HEIGHT:
+ return BigDecimal.valueOf(matchedBase).compareTo(BigDecimal.valueOf(sourceBase)) == 0;
+ case SELECT_ALL_FURNI_ON_TILE:
+ return true;
+ case SELECT_FURNI_ABOVE:
+ default:
+ return matchedBase >= (sourceTop - EPSILON);
+ }
+ }
+
+ private void refresh(Room room) {
+ Set invalidItems = new LinkedHashSet<>();
+
+ if (room == null) {
+ invalidItems.addAll(this.items);
+ } else {
+ for (HabboItem item : this.items) {
+ if (room.getHabboItem(item.getId()) == null) {
+ invalidItems.add(item);
+ }
+ }
+ }
+
+ this.items.removeAll(invalidItems);
+ }
+
+ private int normalizeSelectionType(int value) {
+ if (value < SELECT_FURNI_ABOVE || value > SELECT_ALL_FURNI_ON_TILE) {
+ return SELECT_FURNI_ABOVE;
+ }
+
+ return value;
+ }
+
+ 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();
+ }
+
+ static class JsonData {
+ int selectionType;
+ int furniSource;
+ boolean filterExisting;
+ boolean invert;
+ List itemIds;
+ int delay;
+
+ JsonData(int selectionType, int furniSource, boolean filterExisting, boolean invert, List itemIds, int delay) {
+ this.selectionType = selectionType;
+ this.furniSource = furniSource;
+ this.filterExisting = filterExisting;
+ this.invert = invert;
+ this.itemIds = itemIds;
+ this.delay = delay;
+ }
+ }
+}
diff --git a/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/selector/WiredEffectFurniPicks.java b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/selector/WiredEffectFurniPicks.java
new file mode 100644
index 00000000..53a3c92c
--- /dev/null
+++ b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/selector/WiredEffectFurniPicks.java
@@ -0,0 +1,167 @@
+package com.eu.habbo.habbohotel.items.interactions.wired.selector;
+
+import com.eu.habbo.habbohotel.gameclients.GameClient;
+import com.eu.habbo.habbohotel.items.Item;
+import com.eu.habbo.habbohotel.items.interactions.InteractionWired;
+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.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.messages.ServerMessage;
+
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+public class WiredEffectFurniPicks extends InteractionWiredEffect {
+ private static final int MAX_PICKED_FURNI = 20;
+
+ public static final WiredEffectType type = WiredEffectType.FURNI_PICKS_SELECTOR;
+
+ private boolean filterExisting = false;
+ private boolean invert = false;
+ private List pickedFurniIds = new ArrayList<>();
+
+ public WiredEffectFurniPicks(ResultSet set, Item baseItem) throws SQLException {
+ super(set, baseItem);
+ }
+
+ public WiredEffectFurniPicks(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;
+ }
+
+ Set result = this.pickedFurniIds.stream()
+ .map(room::getHabboItem)
+ .filter(item -> item != null && !(item instanceof InteractionWired))
+ .collect(Collectors.toCollection(LinkedHashSet::new));
+
+ result = this.applySelectorModifiers(result, this.getSelectableFloorItems(room), ctx.targets().items(), this.filterExisting, this.invert);
+
+ ctx.targets().setItems(result);
+ }
+
+ @Override
+ public boolean saveData(WiredSettings settings, GameClient gameClient) {
+ int[] params = settings.getIntParams();
+
+ this.filterExisting = params.length > 0 && params[0] == 1;
+ this.invert = params.length > 1 && params[1] == 1;
+
+ this.pickedFurniIds = new ArrayList<>();
+ if (settings.getFurniIds() != null) {
+ for (int id : settings.getFurniIds()) {
+ if (this.pickedFurniIds.size() >= MAX_PICKED_FURNI) break;
+ this.pickedFurniIds.add(id);
+ }
+ }
+
+ this.setDelay(settings.getDelay());
+ return true;
+ }
+
+ @Override
+ public WiredEffectType getType() {
+ return type;
+ }
+
+ @Override
+ public boolean isSelector() {
+ return true;
+ }
+
+ @Override
+ public String getWiredData() {
+ return WiredManager.getGson().toJson(new JsonData(
+ this.filterExisting,
+ this.invert,
+ this.pickedFurniIds,
+ this.getDelay()
+ ));
+ }
+
+ @Override
+ public void loadWiredData(ResultSet set, Room room) throws SQLException {
+ this.onPickUp();
+
+ 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.filterExisting = data.filterExisting;
+ this.invert = data.invert;
+ this.pickedFurniIds = (data.pickedFurniIds != null) ? data.pickedFurniIds : new ArrayList<>();
+ this.setDelay(data.delay);
+ }
+
+ @Override
+ public void onPickUp() {
+ this.filterExisting = false;
+ this.invert = false;
+ this.pickedFurniIds = new ArrayList<>();
+ this.setDelay(0);
+ }
+
+ @Override
+ public void serializeWiredData(ServerMessage message, Room room) {
+ message.appendBoolean(true);
+ message.appendInt(MAX_PICKED_FURNI);
+
+ if (!this.pickedFurniIds.isEmpty()) {
+ message.appendInt(this.pickedFurniIds.size());
+ this.pickedFurniIds.forEach(message::appendInt);
+ } else {
+ message.appendInt(0);
+ }
+
+ message.appendInt(this.getBaseItem().getSpriteId());
+ message.appendInt(this.getId());
+ message.appendString("");
+ message.appendInt(2);
+ message.appendInt(this.filterExisting ? 1 : 0);
+ message.appendInt(this.invert ? 1 : 0);
+ message.appendInt(0);
+ message.appendInt(this.getType().code);
+ message.appendInt(this.getDelay());
+ message.appendInt(0);
+ }
+
+ @Override
+ public boolean execute(RoomUnit roomUnit, Room room, Object[] stuff) {
+ return false;
+ }
+
+ static class JsonData {
+ boolean filterExisting;
+ boolean invert;
+ List pickedFurniIds;
+ int delay;
+
+ JsonData(boolean filterExisting, boolean invert, List pickedFurniIds, int delay) {
+ this.filterExisting = filterExisting;
+ this.invert = invert;
+ this.pickedFurniIds = pickedFurniIds;
+ this.delay = delay;
+ }
+ }
+}
diff --git a/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/selector/WiredEffectFurniSignal.java b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/selector/WiredEffectFurniSignal.java
new file mode 100644
index 00000000..2dc15691
--- /dev/null
+++ b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/selector/WiredEffectFurniSignal.java
@@ -0,0 +1,142 @@
+package com.eu.habbo.habbohotel.items.interactions.wired.selector;
+
+import com.eu.habbo.habbohotel.gameclients.GameClient;
+import com.eu.habbo.habbohotel.items.Item;
+import com.eu.habbo.habbohotel.items.interactions.InteractionWired;
+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.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.WiredEvent;
+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.LinkedHashSet;
+import java.util.List;
+import java.util.Set;
+
+public class WiredEffectFurniSignal extends InteractionWiredEffect {
+ public static final WiredEffectType type = WiredEffectType.FURNI_SIGNAL_SELECTOR;
+
+ private boolean filterExisting = false;
+ private boolean invert = false;
+
+ public WiredEffectFurniSignal(ResultSet set, Item baseItem) throws SQLException {
+ super(set, baseItem);
+ }
+
+ public WiredEffectFurniSignal(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;
+ }
+
+ Set result = new LinkedHashSet<>();
+
+ if (ctx.eventType() == WiredEvent.Type.SIGNAL_RECEIVED) {
+ List signalItems = WiredSourceUtil.resolveItems(ctx, WiredSourceUtil.SOURCE_SIGNAL, null);
+ Set matched = signalItems.stream()
+ .filter(item -> item != null && !(item instanceof InteractionWired))
+ .collect(java.util.stream.Collectors.toCollection(LinkedHashSet::new));
+
+ result = this.applySelectorModifiers(matched, this.getSelectableFloorItems(room), ctx.targets().items(), this.filterExisting, this.invert);
+ }
+
+ ctx.targets().setItems(result);
+ }
+
+ @Override
+ public boolean saveData(WiredSettings settings, GameClient gameClient) {
+ int[] params = settings.getIntParams();
+ this.filterExisting = params.length > 0 && params[0] == 1;
+ this.invert = params.length > 1 && params[1] == 1;
+ this.setDelay(settings.getDelay());
+ return true;
+ }
+
+ @Override
+ public WiredEffectType getType() {
+ return type;
+ }
+
+ @Override
+ public boolean isSelector() {
+ return true;
+ }
+
+ @Override
+ public String getWiredData() {
+ return WiredManager.getGson().toJson(new JsonData(this.filterExisting, this.invert, this.getDelay()));
+ }
+
+ @Override
+ public void loadWiredData(ResultSet set, Room room) throws SQLException {
+ this.onPickUp();
+
+ 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.filterExisting = data.filterExisting;
+ this.invert = data.invert;
+ this.setDelay(data.delay);
+ }
+
+ @Override
+ public void onPickUp() {
+ this.filterExisting = false;
+ this.invert = false;
+ this.setDelay(0);
+ }
+
+ @Override
+ public void serializeWiredData(ServerMessage message, Room room) {
+ message.appendBoolean(false);
+ message.appendInt(0);
+ message.appendInt(0);
+ message.appendInt(this.getBaseItem().getSpriteId());
+ message.appendInt(this.getId());
+ message.appendString("");
+ message.appendInt(2);
+ message.appendInt(this.filterExisting ? 1 : 0);
+ message.appendInt(this.invert ? 1 : 0);
+ message.appendInt(0);
+ message.appendInt(this.getType().code);
+ message.appendInt(this.getDelay());
+ message.appendInt(0);
+ }
+
+ @Override
+ public boolean execute(RoomUnit roomUnit, Room room, Object[] stuff) {
+ return false;
+ }
+
+ static class JsonData {
+ boolean filterExisting;
+ boolean invert;
+ int delay;
+
+ JsonData(boolean filterExisting, boolean invert, int delay) {
+ this.filterExisting = filterExisting;
+ this.invert = invert;
+ this.delay = delay;
+ }
+ }
+}
diff --git a/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/selector/WiredEffectUsersArea.java b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/selector/WiredEffectUsersArea.java
index 46984906..b03f4bb7 100644
--- a/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/selector/WiredEffectUsersArea.java
+++ b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/selector/WiredEffectUsersArea.java
@@ -6,7 +6,6 @@ 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.RoomUnit;
-import com.eu.habbo.habbohotel.rooms.RoomUnitType;
import com.eu.habbo.habbohotel.wired.WiredEffectType;
import com.eu.habbo.habbohotel.wired.core.WiredContext;
import com.eu.habbo.habbohotel.wired.core.WiredManager;
@@ -29,8 +28,6 @@ public class WiredEffectUsersArea extends InteractionWiredEffect {
private int areaHeight = 0;
private boolean filterExisting = false;
private boolean invert = false;
- private boolean excludeBots = false;
- private boolean excludePets = false;
public WiredEffectUsersArea(ResultSet set, Item baseItem) throws SQLException {
super(set, baseItem);
@@ -50,23 +47,15 @@ public class WiredEffectUsersArea extends InteractionWiredEffect {
List usersInArea = new ArrayList<>();
for (RoomUnit unit : room.getRoomUnits()) {
- if (excludeBots && unit.getRoomUnitType() == RoomUnitType.BOT) continue;
- if (excludePets && unit.getRoomUnitType() == RoomUnitType.PET) continue;
int x = unit.getX();
int y = unit.getY();
boolean inArea = x >= rootX && x <= maxX && y >= rootY && y <= maxY;
- if (invert ? !inArea : inArea) {
+ if (inArea) {
usersInArea.add(unit);
}
}
- if (filterExisting) {
- usersInArea.retainAll(ctx.targets().users());
- }
-
- if (!usersInArea.isEmpty()) {
- ctx.targets().setUsers(usersInArea);
- }
+ ctx.targets().setUsers(this.applySelectorModifiers(usersInArea, room.getRoomUnits(), ctx.targets().users(), filterExisting, invert));
}
@Override
@@ -82,8 +71,6 @@ public class WiredEffectUsersArea extends InteractionWiredEffect {
this.areaHeight = params[3];
this.filterExisting = params.length >= 5 && params[4] == 1;
this.invert = params.length >= 6 && params[5] == 1;
- this.excludeBots = params.length >= 7 && params[6] == 1;
- this.excludePets = params.length >= 8 && params[7] == 1;
this.setDelay(settings.getDelay());
return true;
@@ -101,7 +88,7 @@ public class WiredEffectUsersArea extends InteractionWiredEffect {
@Override
public String getWiredData() {
- return WiredManager.getGson().toJson(new JsonData(rootX, rootY, areaWidth, areaHeight, filterExisting, invert, excludeBots, excludePets, getDelay()));
+ return WiredManager.getGson().toJson(new JsonData(rootX, rootY, areaWidth, areaHeight, filterExisting, invert, getDelay()));
}
@Override
@@ -116,8 +103,6 @@ public class WiredEffectUsersArea extends InteractionWiredEffect {
this.areaHeight = data.height;
this.filterExisting = data.filterExisting;
this.invert = data.invert;
- this.excludeBots = data.excludeBots;
- this.excludePets = data.excludePets;
this.setDelay(data.delay);
}
}
@@ -130,8 +115,6 @@ public class WiredEffectUsersArea extends InteractionWiredEffect {
this.areaHeight = 0;
this.filterExisting = false;
this.invert = false;
- this.excludeBots = false;
- this.excludePets = false;
this.setDelay(0);
}
@@ -145,15 +128,13 @@ public class WiredEffectUsersArea extends InteractionWiredEffect {
message.appendInt(this.getId());
message.appendString("");
- message.appendInt(8);
+ message.appendInt(6);
message.appendInt(this.rootX);
message.appendInt(this.rootY);
message.appendInt(this.areaWidth);
message.appendInt(this.areaHeight);
message.appendInt(this.filterExisting ? 1 : 0);
message.appendInt(this.invert ? 1 : 0);
- message.appendInt(this.excludeBots ? 1 : 0);
- message.appendInt(this.excludePets ? 1 : 0);
message.appendInt(0);
message.appendInt(this.getType().code);
@@ -173,19 +154,15 @@ public class WiredEffectUsersArea extends InteractionWiredEffect {
int height;
boolean filterExisting;
boolean invert;
- boolean excludeBots;
- boolean excludePets;
int delay;
- JsonData(int rootX, int rootY, int width, int height, boolean filterExisting, boolean invert, boolean excludeBots, boolean excludePets, int delay) {
+ JsonData(int rootX, int rootY, int width, int height, boolean filterExisting, boolean invert, int delay) {
this.rootX = rootX;
this.rootY = rootY;
this.width = width;
this.height = height;
this.filterExisting = filterExisting;
this.invert = invert;
- this.excludeBots = excludeBots;
- this.excludePets = excludePets;
this.delay = delay;
}
}
diff --git a/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/selector/WiredEffectUsersByAction.java b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/selector/WiredEffectUsersByAction.java
new file mode 100644
index 00000000..3f88d99a
--- /dev/null
+++ b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/selector/WiredEffectUsersByAction.java
@@ -0,0 +1,333 @@
+package com.eu.habbo.habbohotel.items.interactions.wired.selector;
+
+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.RoomUnit;
+import com.eu.habbo.habbohotel.rooms.RoomUnitStatus;
+import com.eu.habbo.habbohotel.wired.WiredEffectType;
+import com.eu.habbo.habbohotel.wired.WiredUserActionType;
+import com.eu.habbo.habbohotel.wired.core.WiredContext;
+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;
+import java.util.LinkedHashSet;
+import java.util.Set;
+
+public class WiredEffectUsersByAction extends InteractionWiredEffect {
+ 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;
+ private static final int DEFAULT_ACTION = WiredUserActionType.WAVE;
+
+ public static final WiredEffectType type = WiredEffectType.USERS_BY_ACTION_SELECTOR;
+
+ private int selectedAction = DEFAULT_ACTION;
+ private boolean signFilterEnabled = false;
+ private int signId = 0;
+ private boolean danceFilterEnabled = false;
+ private int danceId = 1;
+ private boolean filterExisting = false;
+ private boolean invert = false;
+
+ public WiredEffectUsersByAction(ResultSet set, Item baseItem) throws SQLException {
+ super(set, baseItem);
+ }
+
+ public WiredEffectUsersByAction(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;
+ }
+
+ Set result = new LinkedHashSet<>();
+
+ for (RoomUnit roomUnit : room.getRoomUnits()) {
+ if (this.matchesAction(ctx, roomUnit)) {
+ result.add(roomUnit);
+ }
+ }
+
+ result = this.applySelectorModifiers(result, room.getRoomUnits(), ctx.targets().users(), this.filterExisting, this.invert);
+
+ ctx.targets().setUsers(result);
+ }
+
+ @Override
+ public boolean saveData(WiredSettings settings, GameClient gameClient) {
+ int[] params = settings.getIntParams();
+
+ this.onPickUp();
+
+ if (params.length > 0) this.selectedAction = this.normalizeAction(params[0]);
+ if (params.length > 1) this.signFilterEnabled = (params[1] == 1);
+ if (params.length > 2) this.signId = this.normalizeSignId(params[2]);
+ if (params.length > 3) this.danceFilterEnabled = (params[3] == 1);
+ if (params.length > 4) this.danceId = this.normalizeDanceId(params[4]);
+ if (params.length > 5) this.filterExisting = (params[5] == 1);
+ if (params.length > 6) this.invert = (params[6] == 1);
+
+ this.setDelay(settings.getDelay());
+ return true;
+ }
+
+ @Override
+ public WiredEffectType getType() {
+ return type;
+ }
+
+ @Override
+ public boolean isSelector() {
+ return true;
+ }
+
+ @Override
+ public String getWiredData() {
+ return WiredManager.getGson().toJson(new JsonData(
+ this.selectedAction,
+ this.signFilterEnabled,
+ this.signId,
+ this.danceFilterEnabled,
+ this.danceId,
+ this.filterExisting,
+ this.invert,
+ this.getDelay()
+ ));
+ }
+
+ @Override
+ public void loadWiredData(ResultSet set, Room room) throws SQLException {
+ this.onPickUp();
+
+ 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 = this.normalizeAction(data.selectedAction);
+ this.signFilterEnabled = data.signFilterEnabled;
+ this.signId = this.normalizeSignId(data.signId);
+ this.danceFilterEnabled = data.danceFilterEnabled;
+ this.danceId = this.normalizeDanceId(data.danceId);
+ this.filterExisting = data.filterExisting;
+ this.invert = data.invert;
+ this.setDelay(data.delay);
+ }
+
+ @Override
+ public void onPickUp() {
+ this.selectedAction = DEFAULT_ACTION;
+ this.signFilterEnabled = false;
+ this.signId = 0;
+ this.danceFilterEnabled = false;
+ this.danceId = 1;
+ this.filterExisting = false;
+ this.invert = false;
+ this.setDelay(0);
+ }
+
+ @Override
+ public void serializeWiredData(ServerMessage message, Room room) {
+ message.appendBoolean(false);
+ message.appendInt(0);
+ 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.filterExisting ? 1 : 0);
+ message.appendInt(this.invert ? 1 : 0);
+ message.appendInt(0);
+ message.appendInt(this.getType().code);
+ message.appendInt(this.getDelay());
+ message.appendInt(0);
+ }
+
+ @Override
+ public boolean execute(RoomUnit roomUnit, Room room, Object[] stuff) {
+ return false;
+ }
+
+ 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 value) {
+ return (value < 0 || value > 17) ? 0 : value;
+ }
+
+ private int normalizeDanceId(int value) {
+ return (value < 1 || value > 4) ? 1 : value;
+ }
+
+ private 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);
+ }
+
+ private boolean matchesEventAction(WiredContext ctx, RoomUnit roomUnit) {
+ RoomUnit actor = ctx.actor().orElse(null);
+
+ if (actor == null || actor.getId() != roomUnit.getId()) {
+ return false;
+ }
+
+ if (ctx.eventType() != WiredEvent.Type.USER_PERFORMS_ACTION) {
+ return false;
+ }
+
+ return this.matchesConfiguredAction(ctx.event().getActionId(), ctx.event().getActionParameter());
+ }
+
+ private 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;
+ }
+ }
+
+ private 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);
+ }
+
+ private 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;
+ }
+
+ private 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;
+ }
+ }
+
+ private boolean matchesDanceState(RoomUnit roomUnit) {
+ int currentDance = roomUnit.getDanceType().getType();
+ if (currentDance <= 0) {
+ return false;
+ }
+
+ if (!this.danceFilterEnabled) {
+ return true;
+ }
+
+ return currentDance == this.danceId;
+ }
+
+ static class JsonData {
+ int selectedAction;
+ boolean signFilterEnabled;
+ int signId;
+ boolean danceFilterEnabled;
+ int danceId;
+ boolean filterExisting;
+ boolean invert;
+ int delay;
+
+ JsonData(int selectedAction, boolean signFilterEnabled, int signId, boolean danceFilterEnabled, int danceId, boolean filterExisting, boolean invert, int delay) {
+ this.selectedAction = selectedAction;
+ this.signFilterEnabled = signFilterEnabled;
+ this.signId = signId;
+ this.danceFilterEnabled = danceFilterEnabled;
+ this.danceId = danceId;
+ this.filterExisting = filterExisting;
+ this.invert = invert;
+ this.delay = delay;
+ }
+ }
+}
diff --git a/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/selector/WiredEffectUsersByName.java b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/selector/WiredEffectUsersByName.java
new file mode 100644
index 00000000..a8dc2ef8
--- /dev/null
+++ b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/selector/WiredEffectUsersByName.java
@@ -0,0 +1,202 @@
+package com.eu.habbo.habbohotel.items.interactions.wired.selector;
+
+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.RoomUnit;
+import com.eu.habbo.habbohotel.users.Habbo;
+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.messages.ServerMessage;
+
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.LinkedHashSet;
+import java.util.Locale;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+public class WiredEffectUsersByName extends InteractionWiredEffect {
+ public static final WiredEffectType type = WiredEffectType.USERS_BY_NAME_SELECTOR;
+
+ private String namesText = "";
+ private Set usernames = new LinkedHashSet<>();
+ private boolean filterExisting = false;
+ private boolean invert = false;
+
+ public WiredEffectUsersByName(ResultSet set, Item baseItem) throws SQLException {
+ super(set, baseItem);
+ }
+
+ public WiredEffectUsersByName(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;
+ }
+
+ Set result = new LinkedHashSet<>();
+
+ for (Habbo habbo : room.getHabbos()) {
+ if (habbo == null || habbo.getHabboInfo() == null || habbo.getRoomUnit() == null) {
+ continue;
+ }
+
+ String username = habbo.getHabboInfo().getUsername();
+ if (username == null) {
+ continue;
+ }
+
+ if (this.usernames.contains(username.trim().toLowerCase(Locale.ROOT))) {
+ result.add(habbo.getRoomUnit());
+ }
+ }
+
+ Set availableUsers = room.getHabbos().stream()
+ .filter(habbo -> habbo != null && habbo.getRoomUnit() != null)
+ .map(Habbo::getRoomUnit)
+ .collect(Collectors.toCollection(LinkedHashSet::new));
+ result = this.applySelectorModifiers(result, availableUsers, ctx.targets().users(), this.filterExisting, this.invert);
+
+ ctx.targets().setUsers(result);
+ }
+
+ @Override
+ public boolean saveData(WiredSettings settings, GameClient gameClient) {
+ int[] params = settings.getIntParams();
+
+ this.namesText = this.normalizeNamesText(settings.getStringParam());
+ this.usernames = this.parseUsernames(this.namesText);
+ this.filterExisting = params.length > 0 && params[0] == 1;
+ this.invert = params.length > 1 && params[1] == 1;
+ this.setDelay(settings.getDelay());
+ return true;
+ }
+
+ @Override
+ public WiredEffectType getType() {
+ return type;
+ }
+
+ @Override
+ public boolean isSelector() {
+ return true;
+ }
+
+ @Override
+ public String getWiredData() {
+ return WiredManager.getGson().toJson(new JsonData(this.namesText, this.filterExisting, this.invert, this.getDelay()));
+ }
+
+ @Override
+ public void loadWiredData(ResultSet set, Room room) throws SQLException {
+ this.onPickUp();
+
+ 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.namesText = this.normalizeNamesText(data.namesText);
+ this.filterExisting = data.filterExisting;
+ this.invert = data.invert;
+ this.setDelay(data.delay);
+ } else {
+ this.namesText = this.normalizeNamesText(wiredData);
+ }
+
+ this.usernames = this.parseUsernames(this.namesText);
+ }
+
+ @Override
+ public void onPickUp() {
+ this.namesText = "";
+ this.usernames = new LinkedHashSet<>();
+ this.filterExisting = false;
+ this.invert = false;
+ this.setDelay(0);
+ }
+
+ @Override
+ public void serializeWiredData(ServerMessage message, Room room) {
+ message.appendBoolean(false);
+ message.appendInt(0);
+ message.appendInt(0);
+ message.appendInt(this.getBaseItem().getSpriteId());
+ message.appendInt(this.getId());
+ message.appendString(this.namesText);
+ message.appendInt(2);
+ message.appendInt(this.filterExisting ? 1 : 0);
+ message.appendInt(this.invert ? 1 : 0);
+ message.appendInt(0);
+ message.appendInt(this.getType().code);
+ message.appendInt(this.getDelay());
+ message.appendInt(0);
+ }
+
+ @Override
+ public boolean execute(RoomUnit roomUnit, Room room, Object[] stuff) {
+ return false;
+ }
+
+ private String normalizeNamesText(String value) {
+ if (value == null || value.trim().isEmpty()) {
+ return "";
+ }
+
+ Set normalizedLines = new LinkedHashSet<>();
+
+ for (String line : value.split("\\R")) {
+ String normalized = line.trim();
+ if (!normalized.isEmpty()) {
+ normalizedLines.add(normalized);
+ }
+ }
+
+ return normalizedLines.stream().collect(Collectors.joining("\n"));
+ }
+
+ private Set parseUsernames(String value) {
+ Set result = new LinkedHashSet<>();
+
+ if (value == null || value.trim().isEmpty()) {
+ return result;
+ }
+
+ for (String line : value.split("\\R")) {
+ String normalized = line.trim();
+ if (!normalized.isEmpty()) {
+ result.add(normalized.toLowerCase(Locale.ROOT));
+ }
+ }
+
+ return result;
+ }
+
+ static class JsonData {
+ String namesText;
+ boolean filterExisting;
+ boolean invert;
+ int delay;
+
+ JsonData(String namesText, boolean filterExisting, boolean invert, int delay) {
+ this.namesText = namesText;
+ this.filterExisting = filterExisting;
+ this.invert = invert;
+ this.delay = delay;
+ }
+ }
+}
diff --git a/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/selector/WiredEffectUsersByType.java b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/selector/WiredEffectUsersByType.java
new file mode 100644
index 00000000..b9280099
--- /dev/null
+++ b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/selector/WiredEffectUsersByType.java
@@ -0,0 +1,167 @@
+package com.eu.habbo.habbohotel.items.interactions.wired.selector;
+
+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.RoomUnit;
+import com.eu.habbo.habbohotel.rooms.RoomUnitType;
+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.messages.ServerMessage;
+
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.LinkedHashSet;
+import java.util.Set;
+
+public class WiredEffectUsersByType extends InteractionWiredEffect {
+ private static final int ENTITY_HABBO = 1;
+ private static final int ENTITY_PET = 2;
+ private static final int ENTITY_BOT = 4;
+
+ public static final WiredEffectType type = WiredEffectType.USERS_BY_TYPE_SELECTOR;
+
+ private int entityType = ENTITY_HABBO;
+ private boolean filterExisting = false;
+ private boolean invert = false;
+
+ public WiredEffectUsersByType(ResultSet set, Item baseItem) throws SQLException {
+ super(set, baseItem);
+ }
+
+ public WiredEffectUsersByType(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;
+ }
+
+ Set result = new LinkedHashSet<>();
+
+ for (RoomUnit roomUnit : room.getRoomUnits()) {
+ if (this.matchesType(roomUnit)) {
+ result.add(roomUnit);
+ }
+ }
+
+ result = this.applySelectorModifiers(result, room.getRoomUnits(), ctx.targets().users(), this.filterExisting, this.invert);
+
+ ctx.targets().setUsers(result);
+ }
+
+ @Override
+ public boolean saveData(WiredSettings settings, GameClient gameClient) {
+ int[] params = settings.getIntParams();
+ this.entityType = (params.length > 0) ? this.normalizeEntityType(params[0]) : ENTITY_HABBO;
+ this.filterExisting = params.length > 1 && params[1] == 1;
+ this.invert = params.length > 2 && params[2] == 1;
+ this.setDelay(settings.getDelay());
+ return true;
+ }
+
+ @Override
+ public WiredEffectType getType() {
+ return type;
+ }
+
+ @Override
+ public boolean isSelector() {
+ return true;
+ }
+
+ @Override
+ public String getWiredData() {
+ return WiredManager.getGson().toJson(new JsonData(this.entityType, this.filterExisting, this.invert, this.getDelay()));
+ }
+
+ @Override
+ public void loadWiredData(ResultSet set, Room room) throws SQLException {
+ this.onPickUp();
+
+ 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.filterExisting = data.filterExisting;
+ this.invert = data.invert;
+ this.setDelay(data.delay);
+ }
+
+ @Override
+ public void onPickUp() {
+ this.entityType = ENTITY_HABBO;
+ this.filterExisting = false;
+ this.invert = false;
+ this.setDelay(0);
+ }
+
+ @Override
+ public void serializeWiredData(ServerMessage message, Room room) {
+ message.appendBoolean(false);
+ message.appendInt(0);
+ message.appendInt(0);
+ message.appendInt(this.getBaseItem().getSpriteId());
+ message.appendInt(this.getId());
+ message.appendString("");
+ message.appendInt(3);
+ message.appendInt(this.entityType);
+ message.appendInt(this.filterExisting ? 1 : 0);
+ message.appendInt(this.invert ? 1 : 0);
+ message.appendInt(0);
+ message.appendInt(this.getType().code);
+ message.appendInt(this.getDelay());
+ message.appendInt(0);
+ }
+
+ @Override
+ public boolean execute(RoomUnit roomUnit, Room room, Object[] stuff) {
+ return false;
+ }
+
+ private int normalizeEntityType(int value) {
+ switch (value) {
+ case ENTITY_PET:
+ case ENTITY_BOT:
+ return value;
+ default:
+ return ENTITY_HABBO;
+ }
+ }
+
+ private boolean matchesType(RoomUnit roomUnit) {
+ if (roomUnit == null) {
+ return false;
+ }
+
+ RoomUnitType roomUnitType = roomUnit.getRoomUnitType();
+ return roomUnitType != null && roomUnitType.getTypeId() == this.entityType;
+ }
+
+ static class JsonData {
+ int entityType;
+ boolean filterExisting;
+ boolean invert;
+ int delay;
+
+ JsonData(int entityType, boolean filterExisting, boolean invert, int delay) {
+ this.entityType = entityType;
+ this.filterExisting = filterExisting;
+ this.invert = invert;
+ this.delay = delay;
+ }
+ }
+}
diff --git a/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/selector/WiredEffectUsersGroup.java b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/selector/WiredEffectUsersGroup.java
new file mode 100644
index 00000000..f74de64a
--- /dev/null
+++ b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/selector/WiredEffectUsersGroup.java
@@ -0,0 +1,179 @@
+package com.eu.habbo.habbohotel.items.interactions.wired.selector;
+
+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.RoomUnit;
+import com.eu.habbo.habbohotel.users.Habbo;
+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.messages.ServerMessage;
+
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.LinkedHashSet;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+public class WiredEffectUsersGroup extends InteractionWiredEffect {
+ private static final int GROUP_CURRENT_ROOM = 0;
+ private static final int GROUP_SELECTED = 1;
+
+ public static final WiredEffectType type = WiredEffectType.USERS_GROUP_SELECTOR;
+
+ private int groupType = GROUP_CURRENT_ROOM;
+ private int selectedGroupId = 0;
+ private boolean filterExisting = false;
+ private boolean invert = false;
+
+ public WiredEffectUsersGroup(ResultSet set, Item baseItem) throws SQLException {
+ super(set, baseItem);
+ }
+
+ public WiredEffectUsersGroup(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;
+ }
+
+ int targetGroupId = this.resolveTargetGroupId(room);
+ Set result = new LinkedHashSet<>();
+
+ if (targetGroupId > 0) {
+ for (Habbo habbo : room.getHabbos()) {
+ if (habbo == null || habbo.getRoomUnit() == null || habbo.getHabboStats() == null) {
+ continue;
+ }
+
+ if (habbo.getHabboStats().hasGuild(targetGroupId)) {
+ result.add(habbo.getRoomUnit());
+ }
+ }
+ }
+
+ Set availableUsers = room.getHabbos().stream()
+ .filter(habbo -> habbo != null && habbo.getRoomUnit() != null)
+ .map(Habbo::getRoomUnit)
+ .collect(Collectors.toCollection(LinkedHashSet::new));
+ result = this.applySelectorModifiers(result, availableUsers, ctx.targets().users(), this.filterExisting, this.invert);
+
+ ctx.targets().setUsers(result);
+ }
+
+ @Override
+ public boolean saveData(WiredSettings settings, GameClient gameClient) {
+ int[] params = settings.getIntParams();
+
+ this.groupType = (params.length > 0) ? this.normalizeGroupType(params[0]) : GROUP_CURRENT_ROOM;
+ this.selectedGroupId = (params.length > 1) ? Math.max(0, params[1]) : 0;
+ this.filterExisting = params.length > 2 && params[2] == 1;
+ this.invert = params.length > 3 && params[3] == 1;
+ this.setDelay(settings.getDelay());
+ return true;
+ }
+
+ @Override
+ public WiredEffectType getType() {
+ return type;
+ }
+
+ @Override
+ public boolean isSelector() {
+ return true;
+ }
+
+ @Override
+ public String getWiredData() {
+ return WiredManager.getGson().toJson(new JsonData(this.groupType, this.selectedGroupId, this.filterExisting, this.invert, this.getDelay()));
+ }
+
+ @Override
+ public void loadWiredData(ResultSet set, Room room) throws SQLException {
+ this.onPickUp();
+
+ 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.groupType = this.normalizeGroupType(data.groupType);
+ this.selectedGroupId = Math.max(0, data.selectedGroupId);
+ this.filterExisting = data.filterExisting;
+ this.invert = data.invert;
+ this.setDelay(data.delay);
+ }
+
+ @Override
+ public void onPickUp() {
+ this.groupType = GROUP_CURRENT_ROOM;
+ this.selectedGroupId = 0;
+ this.filterExisting = false;
+ this.invert = false;
+ this.setDelay(0);
+ }
+
+ @Override
+ public void serializeWiredData(ServerMessage message, Room room) {
+ message.appendBoolean(false);
+ message.appendInt(0);
+ message.appendInt(0);
+ message.appendInt(this.getBaseItem().getSpriteId());
+ message.appendInt(this.getId());
+ message.appendString("");
+ message.appendInt(4);
+ message.appendInt(this.groupType);
+ message.appendInt(this.selectedGroupId);
+ message.appendInt(this.filterExisting ? 1 : 0);
+ message.appendInt(this.invert ? 1 : 0);
+ message.appendInt(0);
+ message.appendInt(this.getType().code);
+ message.appendInt(this.getDelay());
+ message.appendInt(0);
+ }
+
+ @Override
+ public boolean execute(RoomUnit roomUnit, Room room, Object[] stuff) {
+ return false;
+ }
+
+ private int resolveTargetGroupId(Room room) {
+ if (this.groupType == GROUP_CURRENT_ROOM) {
+ return room.getGuildId();
+ }
+
+ return this.selectedGroupId;
+ }
+
+ private int normalizeGroupType(int value) {
+ return (value == GROUP_SELECTED) ? GROUP_SELECTED : GROUP_CURRENT_ROOM;
+ }
+
+ static class JsonData {
+ int groupType;
+ int selectedGroupId;
+ boolean filterExisting;
+ boolean invert;
+ int delay;
+
+ JsonData(int groupType, int selectedGroupId, boolean filterExisting, boolean invert, int delay) {
+ this.groupType = groupType;
+ this.selectedGroupId = selectedGroupId;
+ this.filterExisting = filterExisting;
+ this.invert = invert;
+ this.delay = delay;
+ }
+ }
+}
diff --git a/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/selector/WiredEffectUsersHandItem.java b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/selector/WiredEffectUsersHandItem.java
new file mode 100644
index 00000000..e34ef8e7
--- /dev/null
+++ b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/selector/WiredEffectUsersHandItem.java
@@ -0,0 +1,145 @@
+package com.eu.habbo.habbohotel.items.interactions.wired.selector;
+
+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.RoomUnit;
+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.messages.ServerMessage;
+
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.LinkedHashSet;
+import java.util.Set;
+
+public class WiredEffectUsersHandItem extends InteractionWiredEffect {
+ public static final WiredEffectType type = WiredEffectType.USERS_HANDITEM_SELECTOR;
+
+ private int handItemId = 0;
+ private boolean filterExisting = false;
+ private boolean invert = false;
+
+ public WiredEffectUsersHandItem(ResultSet set, Item baseItem) throws SQLException {
+ super(set, baseItem);
+ }
+
+ public WiredEffectUsersHandItem(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;
+ }
+
+ Set result = new LinkedHashSet<>();
+
+ for (RoomUnit roomUnit : room.getRoomUnits()) {
+ if (roomUnit != null && roomUnit.getHandItem() == this.handItemId) {
+ result.add(roomUnit);
+ }
+ }
+
+ result = this.applySelectorModifiers(result, room.getRoomUnits(), ctx.targets().users(), this.filterExisting, this.invert);
+
+ ctx.targets().setUsers(result);
+ }
+
+ @Override
+ public boolean saveData(WiredSettings settings, GameClient gameClient) {
+ int[] params = settings.getIntParams();
+
+ this.handItemId = (params.length > 0) ? Math.max(0, params[0]) : 0;
+ this.filterExisting = params.length > 1 && params[1] == 1;
+ this.invert = params.length > 2 && params[2] == 1;
+ this.setDelay(settings.getDelay());
+
+ return true;
+ }
+
+ @Override
+ public WiredEffectType getType() {
+ return type;
+ }
+
+ @Override
+ public boolean isSelector() {
+ return true;
+ }
+
+ @Override
+ public String getWiredData() {
+ return WiredManager.getGson().toJson(new JsonData(this.handItemId, this.filterExisting, this.invert, this.getDelay()));
+ }
+
+ @Override
+ public void loadWiredData(ResultSet set, Room room) throws SQLException {
+ this.onPickUp();
+
+ 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.handItemId = Math.max(0, data.handItemId);
+ this.filterExisting = data.filterExisting;
+ this.invert = data.invert;
+ this.setDelay(data.delay);
+ }
+
+ @Override
+ public void onPickUp() {
+ this.handItemId = 0;
+ this.filterExisting = false;
+ this.invert = false;
+ this.setDelay(0);
+ }
+
+ @Override
+ public void serializeWiredData(ServerMessage message, Room room) {
+ message.appendBoolean(false);
+ message.appendInt(0);
+ message.appendInt(0);
+ message.appendInt(this.getBaseItem().getSpriteId());
+ message.appendInt(this.getId());
+ message.appendString("");
+ message.appendInt(3);
+ message.appendInt(this.handItemId);
+ message.appendInt(this.filterExisting ? 1 : 0);
+ message.appendInt(this.invert ? 1 : 0);
+ message.appendInt(0);
+ message.appendInt(this.getType().code);
+ message.appendInt(this.getDelay());
+ message.appendInt(0);
+ }
+
+ @Override
+ public boolean execute(RoomUnit roomUnit, Room room, Object[] stuff) {
+ return false;
+ }
+
+ static class JsonData {
+ int handItemId;
+ boolean filterExisting;
+ boolean invert;
+ int delay;
+
+ JsonData(int handItemId, boolean filterExisting, boolean invert, int delay) {
+ this.handItemId = handItemId;
+ this.filterExisting = filterExisting;
+ this.invert = invert;
+ this.delay = delay;
+ }
+ }
+}
diff --git a/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/selector/WiredEffectUsersNeighborhood.java b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/selector/WiredEffectUsersNeighborhood.java
index 7c63b2fb..9c5dd91c 100644
--- a/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/selector/WiredEffectUsersNeighborhood.java
+++ b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/selector/WiredEffectUsersNeighborhood.java
@@ -6,7 +6,6 @@ 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.RoomUnit;
-import com.eu.habbo.habbohotel.rooms.RoomUnitType;
import com.eu.habbo.habbohotel.users.HabboItem;
import com.eu.habbo.habbohotel.wired.WiredEffectType;
import com.eu.habbo.habbohotel.wired.core.WiredContext;
@@ -43,8 +42,8 @@ public class WiredEffectUsersNeighborhood extends InteractionWiredEffect {
private int sourceType = SOURCE_USER_TRIGGER;
private boolean filterExisting = false;
private boolean invert = false;
- private boolean excludeBots = false;
- private boolean excludePets = false;
+ private int targetOffsetX = 0;
+ private int targetOffsetY = 0;
private List tileOffsets = new ArrayList<>();
private List pickedFurniIds = new ArrayList<>();
@@ -77,13 +76,11 @@ public class WiredEffectUsersNeighborhood extends InteractionWiredEffect {
tileOffsets.stream().map(o -> o[0] + "," + o[1]).collect(Collectors.joining(";")),
filterExisting, invert);
- // Apply tile offsets relative to each source position.
- // The offsets define a neighborhood pattern around the source furni/user.
Set targetTiles = new HashSet<>();
for (int[] src : sourcePositions) {
for (int[] offset : tileOffsets) {
- int tx = src[0] + offset[0];
- int ty = src[1] + offset[1];
+ int tx = src[0] + (offset[0] - this.targetOffsetX);
+ int ty = src[1] + (offset[1] - this.targetOffsetY);
targetTiles.add(tx + "," + ty);
}
}
@@ -92,22 +89,17 @@ public class WiredEffectUsersNeighborhood extends InteractionWiredEffect {
List result = new ArrayList<>();
for (RoomUnit unit : room.getRoomUnits()) {
- if (excludeBots && unit.getRoomUnitType() == RoomUnitType.BOT) continue;
- if (excludePets && unit.getRoomUnitType() == RoomUnitType.PET) continue;
-
String pos = unit.getX() + "," + unit.getY();
boolean onTile = targetTiles.contains(pos);
LOGGER.debug("[Neighborhood] Unit id={} type={} pos={} onTile={}", unit.getId(), unit.getRoomUnitType(), pos, onTile);
- if (invert ? !onTile : onTile) {
+ if (onTile) {
result.add(unit);
}
}
- if (filterExisting) {
- result.retainAll(ctx.targets().users());
- }
+ result = new ArrayList<>(this.applySelectorModifiers(result, room.getRoomUnits(), ctx.targets().users(), filterExisting, invert));
LOGGER.debug("[Neighborhood] Result: {} users selected", result.size());
@@ -169,8 +161,8 @@ public class WiredEffectUsersNeighborhood extends InteractionWiredEffect {
this.sourceType = params[0];
this.filterExisting = params.length > 1 && params[1] == 1;
this.invert = params.length > 2 && params[2] == 1;
- this.excludeBots = params.length > 3 && params[3] == 1;
- this.excludePets = params.length > 4 && params[4] == 1;
+ this.targetOffsetX = params.length > 3 ? params[3] : 0;
+ this.targetOffsetY = params.length > 4 ? params[4] : 0;
this.tileOffsets = new ArrayList<>();
if (params.length > 5) {
@@ -218,8 +210,8 @@ public class WiredEffectUsersNeighborhood extends InteractionWiredEffect {
message.appendInt(sourceType);
message.appendInt(filterExisting ? 1 : 0);
message.appendInt(invert ? 1 : 0);
- message.appendInt(excludeBots ? 1 : 0);
- message.appendInt(excludePets ? 1 : 0);
+ message.appendInt(targetOffsetX);
+ message.appendInt(targetOffsetY);
message.appendInt(tileOffsets.size());
for (int[] offset : tileOffsets) {
message.appendInt(offset[0]);
@@ -243,7 +235,7 @@ public class WiredEffectUsersNeighborhood extends InteractionWiredEffect {
@Override
public String getWiredData() {
return WiredManager.getGson().toJson(
- new JsonData(sourceType, filterExisting, invert, excludeBots, excludePets, tileOffsets, pickedFurniIds, getDelay()));
+ new JsonData(sourceType, filterExisting, invert, targetOffsetX, targetOffsetY, tileOffsets, pickedFurniIds, getDelay()));
}
@Override
@@ -254,8 +246,8 @@ public class WiredEffectUsersNeighborhood extends InteractionWiredEffect {
this.sourceType = data.sourceType;
this.filterExisting = data.filterExisting;
this.invert = data.invert;
- this.excludeBots = data.excludeBots;
- this.excludePets = data.excludePets;
+ this.targetOffsetX = data.targetOffsetX;
+ this.targetOffsetY = data.targetOffsetY;
this.tileOffsets = data.tileOffsets != null ? data.tileOffsets : new ArrayList<>();
this.pickedFurniIds = data.pickedFurniIds != null ? data.pickedFurniIds : new ArrayList<>();
this.setDelay(data.delay);
@@ -267,8 +259,8 @@ public class WiredEffectUsersNeighborhood extends InteractionWiredEffect {
this.sourceType = SOURCE_USER_TRIGGER;
this.filterExisting = false;
this.invert = false;
- this.excludeBots = false;
- this.excludePets = false;
+ this.targetOffsetX = 0;
+ this.targetOffsetY = 0;
this.tileOffsets = new ArrayList<>();
this.pickedFurniIds = new ArrayList<>();
this.setDelay(0);
@@ -281,20 +273,20 @@ public class WiredEffectUsersNeighborhood extends InteractionWiredEffect {
int sourceType;
boolean filterExisting;
boolean invert;
- boolean excludeBots;
- boolean excludePets;
+ int targetOffsetX;
+ int targetOffsetY;
List tileOffsets;
List pickedFurniIds;
int delay;
JsonData(int sourceType, boolean filterExisting, boolean invert,
- boolean excludeBots, boolean excludePets,
+ int targetOffsetX, int targetOffsetY,
List tileOffsets, List pickedFurniIds, int delay) {
this.sourceType = sourceType;
this.filterExisting = filterExisting;
this.invert = invert;
- this.excludeBots = excludeBots;
- this.excludePets = excludePets;
+ this.targetOffsetX = targetOffsetX;
+ this.targetOffsetY = targetOffsetY;
this.tileOffsets = tileOffsets;
this.pickedFurniIds = pickedFurniIds;
this.delay = delay;
diff --git a/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/selector/WiredEffectUsersOnFurni.java b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/selector/WiredEffectUsersOnFurni.java
new file mode 100644
index 00000000..833d10a4
--- /dev/null
+++ b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/selector/WiredEffectUsersOnFurni.java
@@ -0,0 +1,269 @@
+package com.eu.habbo.habbohotel.items.interactions.wired.selector;
+
+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 java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.Collections;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+public class WiredEffectUsersOnFurni extends InteractionWiredEffect {
+ public static final WiredEffectType type = WiredEffectType.USERS_ON_FURNI_SELECTOR;
+
+ private final Set items = new LinkedHashSet<>();
+ private int furniSource = WiredSourceUtil.SOURCE_TRIGGER;
+ private boolean filterExisting = false;
+ private boolean invert = false;
+
+ public WiredEffectUsersOnFurni(ResultSet set, Item baseItem) throws SQLException {
+ super(set, baseItem);
+ }
+
+ public WiredEffectUsersOnFurni(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) {
+ ctx.targets().setUsers(Collections.emptySet());
+ return;
+ }
+
+ this.refresh(room);
+
+ List sourceItems = WiredSourceUtil.resolveItems(ctx, this.furniSource, this.items);
+ if (sourceItems.isEmpty()) {
+ ctx.targets().setUsers(Collections.emptySet());
+ return;
+ }
+
+ Set result = new LinkedHashSet<>();
+
+ for (HabboItem sourceItem : sourceItems) {
+ result.addAll(this.resolveUnitsOnItem(room, sourceItem));
+ }
+
+ result = this.applySelectorModifiers(result, room.getRoomUnits(), ctx.targets().users(), this.filterExisting, this.invert);
+
+ ctx.targets().setUsers(result);
+ }
+
+ @Override
+ public boolean saveData(WiredSettings settings, GameClient gameClient) {
+ int[] params = settings.getIntParams();
+
+ this.furniSource = (params.length > 0) ? this.normalizeFurniSource(params[0]) : WiredSourceUtil.SOURCE_TRIGGER;
+ this.filterExisting = params.length > 1 && params[1] == 1;
+ this.invert = params.length > 2 && params[2] == 1;
+
+ 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);
+ }
+ }
+ }
+
+ this.setDelay(settings.getDelay());
+ return true;
+ }
+
+ @Override
+ public WiredEffectType getType() {
+ return type;
+ }
+
+ @Override
+ public boolean isSelector() {
+ return true;
+ }
+
+ @Override
+ public String getWiredData() {
+ this.refresh(Emulator.getGameEnvironment().getRoomManager().getRoom(this.getRoomId()));
+
+ return WiredManager.getGson().toJson(new JsonData(
+ this.furniSource,
+ this.filterExisting,
+ this.invert,
+ this.items.stream().map(HabboItem::getId).collect(Collectors.toList()),
+ this.getDelay()
+ ));
+ }
+
+ @Override
+ public void loadWiredData(ResultSet set, Room room) throws SQLException {
+ this.onPickUp();
+
+ 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.furniSource = this.normalizeFurniSource(data.furniSource);
+ this.filterExisting = data.filterExisting;
+ this.invert = data.invert;
+ this.setDelay(data.delay);
+
+ if (room == null || 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.furniSource = WiredSourceUtil.SOURCE_TRIGGER;
+ this.filterExisting = false;
+ this.invert = false;
+ this.setDelay(0);
+ }
+
+ @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("");
+ message.appendInt(3);
+ message.appendInt(this.furniSource);
+ message.appendInt(this.filterExisting ? 1 : 0);
+ message.appendInt(this.invert ? 1 : 0);
+ message.appendInt(0);
+ message.appendInt(this.getType().code);
+ message.appendInt(this.getDelay());
+ message.appendInt(0);
+ }
+
+ @Override
+ public boolean execute(RoomUnit roomUnit, Room room, Object[] stuff) {
+ return false;
+ }
+
+ private Set resolveUnitsOnItem(Room room, HabboItem sourceItem) {
+ Set result = new LinkedHashSet<>();
+
+ if (sourceItem == null) {
+ return result;
+ }
+
+ RoomTile baseTile = room.getLayout().getTile(sourceItem.getX(), sourceItem.getY());
+ if (baseTile == null) {
+ return result;
+ }
+
+ Set occupiedTiles = room.getLayout().getTilesAt(baseTile, sourceItem.getBaseItem().getWidth(), sourceItem.getBaseItem().getLength(), sourceItem.getRotation());
+ if (occupiedTiles == null) {
+ return result;
+ }
+
+ for (RoomTile tile : occupiedTiles) {
+ if (tile == null) {
+ continue;
+ }
+
+ result.addAll(room.getUnitManager().getRoomUnitsAt(tile));
+ }
+
+ return result;
+ }
+
+ private void refresh(Room room) {
+ Set invalidItems = new LinkedHashSet<>();
+
+ if (room == null) {
+ invalidItems.addAll(this.items);
+ } else {
+ for (HabboItem item : this.items) {
+ if (room.getHabboItem(item.getId()) == null) {
+ invalidItems.add(item);
+ }
+ }
+ }
+
+ this.items.removeAll(invalidItems);
+ }
+
+ 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;
+ }
+ }
+
+ static class JsonData {
+ int furniSource;
+ boolean filterExisting;
+ boolean invert;
+ List itemIds;
+ int delay;
+
+ JsonData(int furniSource, boolean filterExisting, boolean invert, List itemIds, int delay) {
+ this.furniSource = furniSource;
+ this.filterExisting = filterExisting;
+ this.invert = invert;
+ this.itemIds = itemIds;
+ this.delay = delay;
+ }
+ }
+}
diff --git a/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/selector/WiredEffectUsersSignal.java b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/selector/WiredEffectUsersSignal.java
new file mode 100644
index 00000000..1ce2eaba
--- /dev/null
+++ b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/selector/WiredEffectUsersSignal.java
@@ -0,0 +1,138 @@
+package com.eu.habbo.habbohotel.items.interactions.wired.selector;
+
+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.RoomUnit;
+import com.eu.habbo.habbohotel.wired.WiredEffectType;
+import com.eu.habbo.habbohotel.wired.core.WiredContext;
+import com.eu.habbo.habbohotel.wired.core.WiredEvent;
+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.LinkedHashSet;
+import java.util.List;
+import java.util.Set;
+
+public class WiredEffectUsersSignal extends InteractionWiredEffect {
+ public static final WiredEffectType type = WiredEffectType.USERS_SIGNAL_SELECTOR;
+
+ private boolean filterExisting = false;
+ private boolean invert = false;
+
+ public WiredEffectUsersSignal(ResultSet set, Item baseItem) throws SQLException {
+ super(set, baseItem);
+ }
+
+ public WiredEffectUsersSignal(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;
+ }
+
+ Set result = new LinkedHashSet<>();
+
+ if (ctx.eventType() == WiredEvent.Type.SIGNAL_RECEIVED) {
+ List