You've already forked Arcturus-Morningstar-Extended
mirror of
https://github.com/duckietm/Arcturus-Morningstar-Extended.git
synced 2026-06-19 15:06:19 +00:00
Add wired signal and variable fixes
This commit is contained in:
@@ -2,6 +2,8 @@ UPDATE `items_base` SET `interaction_type` = 'wf_cnd_time_more_than' WHERE `publ
|
|||||||
UPDATE `items_base` SET `interaction_type` = 'wf_cnd_time_less_than' WHERE `public_name` = 'wf_cnd_time_less_than';
|
UPDATE `items_base` SET `interaction_type` = 'wf_cnd_time_less_than' WHERE `public_name` = 'wf_cnd_time_less_than';
|
||||||
UPDATE `items_base` SET `interaction_type` = 'wf_act_give_reward' WHERE `public_name` = 'wf_act_give_reward';
|
UPDATE `items_base` SET `interaction_type` = 'wf_act_give_reward' WHERE `public_name` = 'wf_act_give_reward';
|
||||||
UPDATE `items_base` SET `interaction_type` = 'wf_act_call_stacks' WHERE `public_name` = 'wf_act_call_stacks';
|
UPDATE `items_base` SET `interaction_type` = 'wf_act_call_stacks' WHERE `public_name` = 'wf_act_call_stacks';
|
||||||
|
UPDATE `items_base` SET `interaction_type` = 'wf_act_neg_call_stack' WHERE `public_name` = 'wf_act_neg_call_stack';
|
||||||
|
UPDATE `items_base` SET `interaction_type` = 'wf_act_neg_call_stacks' WHERE `public_name` = 'wf_act_neg_call_stacks';
|
||||||
UPDATE `items_base` SET `interaction_type` = 'default' WHERE `public_name` = 'wf_maze';
|
UPDATE `items_base` SET `interaction_type` = 'default' WHERE `public_name` = 'wf_maze';
|
||||||
UPDATE `items_base` SET `interaction_type` = 'wf_act_give_score_tm' WHERE `public_name` = 'wf_act_give_score_tm';
|
UPDATE `items_base` SET `interaction_type` = 'wf_act_give_score_tm' WHERE `public_name` = 'wf_act_give_score_tm';
|
||||||
UPDATE `items_base` SET `interaction_type` = 'wf_act_move_to_dir' WHERE `public_name` = 'wf_act_move_to_dir';
|
UPDATE `items_base` SET `interaction_type` = 'wf_act_move_to_dir' WHERE `public_name` = 'wf_act_move_to_dir';
|
||||||
@@ -111,6 +113,7 @@ UPDATE `items_base` SET `interaction_type` = 'wf_act_furni_to_furni' WHERE `publ
|
|||||||
UPDATE `items_base` SET `interaction_type` = 'wf_act_furni_to_user' WHERE `public_name` = 'wf_act_furni_to_user';
|
UPDATE `items_base` SET `interaction_type` = 'wf_act_furni_to_user' WHERE `public_name` = 'wf_act_furni_to_user';
|
||||||
UPDATE `items_base` SET `interaction_type` = 'wf_act_rel_mov' WHERE `public_name` = 'wf_act_rel_mov';
|
UPDATE `items_base` SET `interaction_type` = 'wf_act_rel_mov' WHERE `public_name` = 'wf_act_rel_mov';
|
||||||
UPDATE `items_base` SET `interaction_type` = 'wf_act_send_signal' WHERE `public_name` = 'wf_act_send_signal';
|
UPDATE `items_base` SET `interaction_type` = 'wf_act_send_signal' WHERE `public_name` = 'wf_act_send_signal';
|
||||||
|
UPDATE `items_base` SET `interaction_type` = 'wf_act_neg_send_signal' WHERE `public_name` = 'wf_act_neg_send_signal';
|
||||||
UPDATE `items_base` SET `interaction_type` = 'wf_act_set_altitude' WHERE `public_name` = 'wf_act_set_altitude';
|
UPDATE `items_base` SET `interaction_type` = 'wf_act_set_altitude' WHERE `public_name` = 'wf_act_set_altitude';
|
||||||
UPDATE `items_base` SET `interaction_type` = 'wf_act_unfreeze' WHERE `public_name` = 'wf_act_unfreeze';
|
UPDATE `items_base` SET `interaction_type` = 'wf_act_unfreeze' WHERE `public_name` = 'wf_act_unfreeze';
|
||||||
UPDATE `items_base` SET `interaction_type` = 'antenna' WHERE `public_name` = 'wf_antenna1';
|
UPDATE `items_base` SET `interaction_type` = 'antenna' WHERE `public_name` = 'wf_antenna1';
|
||||||
|
|||||||
@@ -91,7 +91,23 @@ public class Item implements ISerialize {
|
|||||||
this.allowGift = set.getBoolean("allow_gift");
|
this.allowGift = set.getBoolean("allow_gift");
|
||||||
this.allowInventoryStack = set.getBoolean("allow_inventory_stack");
|
this.allowInventoryStack = set.getBoolean("allow_inventory_stack");
|
||||||
|
|
||||||
this.interactionType = Emulator.getGameEnvironment().getItemManager().getItemInteraction(set.getString("interaction_type").toLowerCase());
|
String interactionTypeName = set.getString("interaction_type");
|
||||||
|
if (interactionTypeName == null) {
|
||||||
|
interactionTypeName = "default";
|
||||||
|
}
|
||||||
|
|
||||||
|
this.interactionType = Emulator.getGameEnvironment().getItemManager().getItemInteraction(interactionTypeName.toLowerCase());
|
||||||
|
|
||||||
|
if ((this.interactionType != null)
|
||||||
|
&& "default".equalsIgnoreCase(this.interactionType.getName())
|
||||||
|
&& (this.fullName != null)
|
||||||
|
&& this.fullName.toLowerCase().startsWith("wf_")) {
|
||||||
|
ItemInteraction fallbackInteraction = Emulator.getGameEnvironment().getItemManager().getItemInteraction(this.fullName.toLowerCase());
|
||||||
|
|
||||||
|
if ((fallbackInteraction != null) && !"default".equalsIgnoreCase(fallbackInteraction.getName())) {
|
||||||
|
this.interactionType = fallbackInteraction;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
this.stateCount = set.getShort("interaction_modes_count");
|
this.stateCount = set.getShort("interaction_modes_count");
|
||||||
this.effectM = set.getShort("effect_id_male");
|
this.effectM = set.getShort("effect_id_male");
|
||||||
|
|||||||
@@ -281,6 +281,8 @@ public class ItemManager {
|
|||||||
this.interactionsList.add(new ItemInteraction("wf_act_move_furni_to", WiredEffectMoveFurniTo.class));
|
this.interactionsList.add(new ItemInteraction("wf_act_move_furni_to", WiredEffectMoveFurniTo.class));
|
||||||
this.interactionsList.add(new ItemInteraction("wf_act_give_reward", WiredEffectGiveReward.class));
|
this.interactionsList.add(new ItemInteraction("wf_act_give_reward", WiredEffectGiveReward.class));
|
||||||
this.interactionsList.add(new ItemInteraction("wf_act_call_stacks", WiredEffectTriggerStacks.class));
|
this.interactionsList.add(new ItemInteraction("wf_act_call_stacks", WiredEffectTriggerStacks.class));
|
||||||
|
this.interactionsList.add(new ItemInteraction("wf_act_neg_call_stack", WiredEffectNegativeTriggerStacks.class));
|
||||||
|
this.interactionsList.add(new ItemInteraction("wf_act_neg_call_stacks", WiredEffectNegativeTriggerStacks.class));
|
||||||
this.interactionsList.add(new ItemInteraction("wf_act_kick_user", WiredEffectKickHabbo.class));
|
this.interactionsList.add(new ItemInteraction("wf_act_kick_user", WiredEffectKickHabbo.class));
|
||||||
this.interactionsList.add(new ItemInteraction("wf_act_mute_triggerer", WiredEffectMuteHabbo.class));
|
this.interactionsList.add(new ItemInteraction("wf_act_mute_triggerer", WiredEffectMuteHabbo.class));
|
||||||
this.interactionsList.add(new ItemInteraction("wf_act_bot_teleport", WiredEffectBotTeleport.class));
|
this.interactionsList.add(new ItemInteraction("wf_act_bot_teleport", WiredEffectBotTeleport.class));
|
||||||
@@ -324,6 +326,7 @@ public class ItemManager {
|
|||||||
this.interactionsList.add(new ItemInteraction("wf_slc_furni_with_var", WiredEffectFurniWithVariable.class));
|
this.interactionsList.add(new ItemInteraction("wf_slc_furni_with_var", WiredEffectFurniWithVariable.class));
|
||||||
this.interactionsList.add(new ItemInteraction("wf_slc_users_with_var", WiredEffectUsersWithVariable.class));
|
this.interactionsList.add(new ItemInteraction("wf_slc_users_with_var", WiredEffectUsersWithVariable.class));
|
||||||
this.interactionsList.add(new ItemInteraction("wf_act_send_signal", WiredEffectSendSignal.class));
|
this.interactionsList.add(new ItemInteraction("wf_act_send_signal", WiredEffectSendSignal.class));
|
||||||
|
this.interactionsList.add(new ItemInteraction("wf_act_neg_send_signal", WiredEffectNegativeSendSignal.class));
|
||||||
this.interactionsList.add(new ItemInteraction("wf_act_give_var", WiredEffectGiveVariable.class));
|
this.interactionsList.add(new ItemInteraction("wf_act_give_var", WiredEffectGiveVariable.class));
|
||||||
this.interactionsList.add(new ItemInteraction("wf_act_remove_var", WiredEffectRemoveVariable.class));
|
this.interactionsList.add(new ItemInteraction("wf_act_remove_var", WiredEffectRemoveVariable.class));
|
||||||
this.interactionsList.add(new ItemInteraction("wf_act_change_var_val", WiredEffectChangeVariableValue.class));
|
this.interactionsList.add(new ItemInteraction("wf_act_change_var_val", WiredEffectChangeVariableValue.class));
|
||||||
|
|||||||
+31
@@ -0,0 +1,31 @@
|
|||||||
|
package com.eu.habbo.habbohotel.items.interactions.wired.effects;
|
||||||
|
|
||||||
|
import com.eu.habbo.habbohotel.items.Item;
|
||||||
|
import com.eu.habbo.habbohotel.wired.WiredEffectType;
|
||||||
|
import com.eu.habbo.habbohotel.wired.core.WiredEvent;
|
||||||
|
import com.eu.habbo.habbohotel.wired.core.WiredManager;
|
||||||
|
|
||||||
|
import java.sql.ResultSet;
|
||||||
|
import java.sql.SQLException;
|
||||||
|
|
||||||
|
public class WiredEffectNegativeSendSignal extends WiredEffectSendSignal {
|
||||||
|
public static final WiredEffectType type = WiredEffectType.NEG_SEND_SIGNAL;
|
||||||
|
|
||||||
|
public WiredEffectNegativeSendSignal(ResultSet set, Item baseItem) throws SQLException {
|
||||||
|
super(set, baseItem);
|
||||||
|
}
|
||||||
|
|
||||||
|
public WiredEffectNegativeSendSignal(int id, int userId, Item item, String extradata, int limitedStack, int limitedSells) {
|
||||||
|
super(id, userId, item, extradata, limitedStack, limitedSells);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean dispatchSignalEvent(WiredEvent event) {
|
||||||
|
return WiredManager.dispatchEffectTriggeredEvent(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public WiredEffectType getType() {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
}
|
||||||
+30
@@ -0,0 +1,30 @@
|
|||||||
|
package com.eu.habbo.habbohotel.items.interactions.wired.effects;
|
||||||
|
|
||||||
|
import com.eu.habbo.habbohotel.items.Item;
|
||||||
|
import com.eu.habbo.habbohotel.wired.WiredEffectType;
|
||||||
|
import com.eu.habbo.habbohotel.wired.core.WiredContext;
|
||||||
|
|
||||||
|
import java.sql.ResultSet;
|
||||||
|
import java.sql.SQLException;
|
||||||
|
|
||||||
|
public class WiredEffectNegativeTriggerStacks extends WiredEffectTriggerStacks {
|
||||||
|
public static final WiredEffectType type = WiredEffectType.NEG_CALL_STACKS;
|
||||||
|
|
||||||
|
public WiredEffectNegativeTriggerStacks(ResultSet set, Item baseItem) throws SQLException {
|
||||||
|
super(set, baseItem);
|
||||||
|
}
|
||||||
|
|
||||||
|
public WiredEffectNegativeTriggerStacks(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) {
|
||||||
|
super.execute(ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public WiredEffectType getType() {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
}
|
||||||
+49
-12
@@ -103,34 +103,30 @@ public class WiredEffectSendSignal extends InteractionWiredEffect {
|
|||||||
}
|
}
|
||||||
LOGGER.debug("[SendSignal] Resolved {} antenna(s), firing signals", resolvedAntennas.size());
|
LOGGER.debug("[SendSignal] Resolved {} antenna(s), firing signals", resolvedAntennas.size());
|
||||||
|
|
||||||
List<RoomUnit> forwardedUsers = WiredSourceUtil.resolveUsers(ctx, this.userForward);
|
List<RoomUnit> forwardedUsers = WiredSourceUtil.resolveUsersRaw(ctx, this.userForward);
|
||||||
List<HabboItem> forwardedFurni = WiredSourceUtil.resolveItems(ctx, this.furniForward, this.forwardItems);
|
List<HabboItem> forwardedFurni = WiredSourceUtil.resolveItemsRaw(ctx, this.furniForward, this.forwardItems);
|
||||||
|
|
||||||
RoomUnit defaultUser = forwardedUsers.isEmpty() ? null : forwardedUsers.get(0);
|
RoomUnit defaultUser = forwardedUsers.isEmpty() ? null : forwardedUsers.get(0);
|
||||||
HabboItem defaultFurni = forwardedFurni.isEmpty() ? null : forwardedFurni.get(0);
|
|
||||||
|
|
||||||
Collection<RoomUnit> usersToSend = (signalPerUser && !forwardedUsers.isEmpty())
|
Collection<RoomUnit> usersToSend = (signalPerUser && !forwardedUsers.isEmpty())
|
||||||
? forwardedUsers
|
? forwardedUsers
|
||||||
: Collections.singletonList(defaultUser);
|
: Collections.singletonList(defaultUser);
|
||||||
|
|
||||||
Collection<HabboItem> furniToSend = (signalPerFurni && !forwardedFurni.isEmpty())
|
Collection<HabboItem> furniToSend = !forwardedFurni.isEmpty()
|
||||||
? forwardedFurni
|
? forwardedFurni
|
||||||
: Collections.singletonList(defaultFurni);
|
: Collections.singletonList(null);
|
||||||
|
|
||||||
int nextDepth = currentDepth + 1;
|
int nextDepth = currentDepth + 1;
|
||||||
boolean isolateBranchContext = (signalPerUser && forwardedUsers.size() > 1)
|
|
||||||
|| (signalPerFurni && forwardedFurni.size() > 1);
|
|
||||||
|
|
||||||
for (RoomUnit user : usersToSend) {
|
for (RoomUnit user : usersToSend) {
|
||||||
for (HabboItem sourceItem : furniToSend) {
|
for (HabboItem sourceItem : furniToSend) {
|
||||||
for (HabboItem antenna : resolvedAntennas) {
|
for (HabboItem antenna : resolvedAntennas) {
|
||||||
fireSignalAtAntenna(ctx, room, antenna, user, sourceItem, nextDepth, isolateBranchContext);
|
fireSignalAtAntenna(ctx, room, antenna, user, sourceItem, nextDepth);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void fireSignalAtAntenna(WiredContext ctx, Room room, HabboItem antenna, RoomUnit actor, HabboItem sourceItem, int depth, boolean isolateBranchContext) {
|
private void fireSignalAtAntenna(WiredContext ctx, Room room, HabboItem antenna, RoomUnit actor, HabboItem sourceItem, int depth) {
|
||||||
if (antenna == null) return;
|
if (antenna == null) return;
|
||||||
RoomTile tile = room.getLayout().getTile(antenna.getX(), antenna.getY());
|
RoomTile tile = room.getLayout().getTile(antenna.getX(), antenna.getY());
|
||||||
if (tile == null) return;
|
if (tile == null) return;
|
||||||
@@ -148,13 +144,13 @@ public class WiredEffectSendSignal extends InteractionWiredEffect {
|
|||||||
.signalChannel(signalChannel)
|
.signalChannel(signalChannel)
|
||||||
.signalUserCount(actor != null ? 1 : 0)
|
.signalUserCount(actor != null ? 1 : 0)
|
||||||
.signalFurniCount(sourceItem != null ? 1 : 0)
|
.signalFurniCount(sourceItem != null ? 1 : 0)
|
||||||
.contextVariableScope(isolateBranchContext ? ctx.contextVariables().copy() : ctx.contextVariables())
|
.contextVariableScope(ctx.contextVariables())
|
||||||
.triggeredByEffect(true);
|
.triggeredByEffect(true);
|
||||||
|
|
||||||
if (actor != null) builder.actor(actor);
|
if (actor != null) builder.actor(actor);
|
||||||
if (sourceItem != null) builder.sourceItem(sourceItem);
|
if (sourceItem != null) builder.sourceItem(sourceItem);
|
||||||
|
|
||||||
boolean result = WiredManager.dispatchEffectTriggeredEvent(builder.build());
|
boolean result = dispatchSignalEvent(builder.build());
|
||||||
LOGGER.debug("[SendSignal] handleEvent returned: {}", result);
|
LOGGER.debug("[SendSignal] handleEvent returned: {}", result);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -452,11 +448,52 @@ public class WiredEffectSendSignal extends InteractionWiredEffect {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean unlinkAntenna(int antennaItemId) {
|
||||||
|
if (antennaItemId <= 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean changed = false;
|
||||||
|
|
||||||
|
Iterator<HabboItem> iterator = this.items.iterator();
|
||||||
|
while (iterator.hasNext()) {
|
||||||
|
HabboItem item = iterator.next();
|
||||||
|
|
||||||
|
if (item == null || item.getId() != antennaItemId) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
iterator.remove();
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.antennaSource == antennaItemId) {
|
||||||
|
if (!this.items.isEmpty()) {
|
||||||
|
HabboItem firstItem = this.items.iterator().next();
|
||||||
|
this.antennaSource = (firstItem != null) ? firstItem.getId() : ANTENNA_PICKED;
|
||||||
|
} else {
|
||||||
|
this.antennaSource = ANTENNA_PICKED;
|
||||||
|
}
|
||||||
|
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (changed) {
|
||||||
|
this.needsUpdate(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
return changed;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected long requiredCooldown() {
|
protected long requiredCooldown() {
|
||||||
return COOLDOWN_TRIGGER_STACKS;
|
return COOLDOWN_TRIGGER_STACKS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected boolean dispatchSignalEvent(WiredEvent event) {
|
||||||
|
return WiredManager.dispatchEffectTriggeredEvent(event);
|
||||||
|
}
|
||||||
|
|
||||||
static class JsonData {
|
static class JsonData {
|
||||||
int delay;
|
int delay;
|
||||||
List<Integer> itemIds;
|
List<Integer> itemIds;
|
||||||
|
|||||||
+29
-26
@@ -28,8 +28,8 @@ import java.util.stream.Collectors;
|
|||||||
public class WiredEffectTriggerStacks extends InteractionWiredEffect {
|
public class WiredEffectTriggerStacks extends InteractionWiredEffect {
|
||||||
public static final WiredEffectType type = WiredEffectType.CALL_STACKS;
|
public static final WiredEffectType type = WiredEffectType.CALL_STACKS;
|
||||||
|
|
||||||
private THashSet<HabboItem> items;
|
protected THashSet<HabboItem> items;
|
||||||
private int furniSource = WiredSourceUtil.SOURCE_TRIGGER;
|
protected int furniSource = WiredSourceUtil.SOURCE_TRIGGER;
|
||||||
|
|
||||||
public WiredEffectTriggerStacks(ResultSet set, Item baseItem) throws SQLException {
|
public WiredEffectTriggerStacks(ResultSet set, Item baseItem) throws SQLException {
|
||||||
super(set, baseItem);
|
super(set, baseItem);
|
||||||
@@ -132,7 +132,7 @@ public class WiredEffectTriggerStacks extends InteractionWiredEffect {
|
|||||||
/**
|
/**
|
||||||
* Maximum recursion depth to prevent infinite loops when trigger stacks call each other.
|
* Maximum recursion depth to prevent infinite loops when trigger stacks call each other.
|
||||||
*/
|
*/
|
||||||
private static final int MAX_STACK_DEPTH = 10;
|
protected static final int MAX_STACK_DEPTH = 10;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void execute(WiredContext ctx) {
|
public void execute(WiredContext ctx) {
|
||||||
@@ -147,30 +147,8 @@ public class WiredEffectTriggerStacks extends InteractionWiredEffect {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
List<HabboItem> effectiveItems = WiredSourceUtil.resolveItems(ctx, this.furniSource, this.items);
|
THashSet<RoomTile> usedTiles = collectTargetTiles(room, ctx);
|
||||||
|
|
||||||
THashSet<RoomTile> usedTiles = new THashSet<>();
|
|
||||||
|
|
||||||
for (HabboItem item : effectiveItems) {
|
|
||||||
if (item == null) continue;
|
|
||||||
|
|
||||||
boolean found = false;
|
|
||||||
for (RoomTile tile : usedTiles) {
|
|
||||||
if (tile.x == item.getX() && tile.y == item.getY()) {
|
|
||||||
found = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!found) {
|
|
||||||
RoomTile tile = room.getLayout().getTile(item.getX(), item.getY());
|
|
||||||
if (tile != null) {
|
|
||||||
usedTiles.add(tile);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Execute effects at tiles with incremented call stack depth
|
|
||||||
WiredManager.executeEffectsAtTiles(usedTiles, roomUnit, room, currentDepth + 1);
|
WiredManager.executeEffectsAtTiles(usedTiles, roomUnit, room, currentDepth + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -246,6 +224,31 @@ public class WiredEffectTriggerStacks extends InteractionWiredEffect {
|
|||||||
return COOLDOWN_TRIGGER_STACKS;
|
return COOLDOWN_TRIGGER_STACKS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected List<HabboItem> resolveEffectiveItems(WiredContext ctx) {
|
||||||
|
return WiredSourceUtil.resolveItems(ctx, this.furniSource, this.items);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected THashSet<RoomTile> collectTargetTiles(Room room, WiredContext ctx) {
|
||||||
|
THashSet<RoomTile> usedTiles = new THashSet<>();
|
||||||
|
|
||||||
|
if (room == null || room.getLayout() == null) {
|
||||||
|
return usedTiles;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (HabboItem item : resolveEffectiveItems(ctx)) {
|
||||||
|
if (item == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
RoomTile tile = room.getLayout().getTile(item.getX(), item.getY());
|
||||||
|
if (tile != null) {
|
||||||
|
usedTiles.add(tile);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return usedTiles;
|
||||||
|
}
|
||||||
|
|
||||||
static class JsonData {
|
static class JsonData {
|
||||||
int delay;
|
int delay;
|
||||||
List<Integer> itemIds;
|
List<Integer> itemIds;
|
||||||
|
|||||||
+26
-7
@@ -10,6 +10,7 @@ import com.eu.habbo.habbohotel.rooms.RoomUnit;
|
|||||||
import com.eu.habbo.habbohotel.wired.core.WiredContextVariableSupport;
|
import com.eu.habbo.habbohotel.wired.core.WiredContextVariableSupport;
|
||||||
import com.eu.habbo.habbohotel.wired.core.WiredManager;
|
import com.eu.habbo.habbohotel.wired.core.WiredManager;
|
||||||
import com.eu.habbo.messages.ServerMessage;
|
import com.eu.habbo.messages.ServerMessage;
|
||||||
|
import com.eu.habbo.messages.incoming.wired.WiredSaveException;
|
||||||
|
|
||||||
import java.sql.ResultSet;
|
import java.sql.ResultSet;
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
@@ -19,7 +20,8 @@ import java.util.Map;
|
|||||||
|
|
||||||
public class WiredExtraVariableTextConnector extends InteractionWiredExtra {
|
public class WiredExtraVariableTextConnector extends InteractionWiredExtra {
|
||||||
public static final int CODE = 79;
|
public static final int CODE = 79;
|
||||||
private static final int MAX_MAPPING_LENGTH = 4096;
|
public static final int MAX_MAPPING_LENGTH = 1000;
|
||||||
|
public static final int MAX_MAPPING_LINES = 30;
|
||||||
|
|
||||||
private String mappingsText = "";
|
private String mappingsText = "";
|
||||||
private LinkedHashMap<Integer, String> mappings = new LinkedHashMap<>();
|
private LinkedHashMap<Integer, String> mappings = new LinkedHashMap<>();
|
||||||
@@ -38,8 +40,10 @@ public class WiredExtraVariableTextConnector extends InteractionWiredExtra {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean saveData(WiredSettings settings, GameClient gameClient) {
|
public boolean saveData(WiredSettings settings, GameClient gameClient) throws WiredSaveException {
|
||||||
this.setMappingsText(settings.getStringParam());
|
String mappingsText = normalizeMappingsText(settings.getStringParam());
|
||||||
|
validateMappingsText(mappingsText);
|
||||||
|
this.setMappingsText(mappingsText);
|
||||||
|
|
||||||
Room room = Emulator.getGameEnvironment().getRoomManager().getRoom(this.getRoomId());
|
Room room = Emulator.getGameEnvironment().getRoomManager().getRoom(this.getRoomId());
|
||||||
if (room != null) {
|
if (room != null) {
|
||||||
@@ -156,13 +160,28 @@ public class WiredExtraVariableTextConnector extends InteractionWiredExtra {
|
|||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
String normalized = value.replace("\r", "");
|
return value.replace("\r", "");
|
||||||
|
}
|
||||||
|
|
||||||
if (normalized.length() > MAX_MAPPING_LENGTH) {
|
private static void validateMappingsText(String value) throws WiredSaveException {
|
||||||
normalized = normalized.substring(0, MAX_MAPPING_LENGTH);
|
if (value == null || value.isEmpty()) {
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
return normalized;
|
if (value.length() > MAX_MAPPING_LENGTH) {
|
||||||
|
throw new WiredSaveException("Variable text connector can contain at most 1000 characters.");
|
||||||
|
}
|
||||||
|
|
||||||
|
int lineCount = 1;
|
||||||
|
for (int i = 0; i < value.length(); i++) {
|
||||||
|
if (value.charAt(i) == '\n') {
|
||||||
|
lineCount++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lineCount > MAX_MAPPING_LINES) {
|
||||||
|
throw new WiredSaveException("Variable text connector can contain at most 30 lines.");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static LinkedHashMap<Integer, String> parseMappings(String value) {
|
private static LinkedHashMap<Integer, String> parseMappings(String value) {
|
||||||
|
|||||||
+5
-4
@@ -20,21 +20,22 @@ final class WiredVariableNameValidator {
|
|||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
return value.trim()
|
return value
|
||||||
.replace("\t", "")
|
.replace("\t", "")
|
||||||
.replace("\r", "")
|
.replace("\r", "")
|
||||||
.replace("\n", "");
|
.replace("\n", "")
|
||||||
|
.replaceAll("\\s+", "_");
|
||||||
}
|
}
|
||||||
|
|
||||||
static String normalizeLegacy(String value) {
|
static String normalizeLegacy(String value) {
|
||||||
String normalized = normalizeForSave(value);
|
String normalized = normalizeForSave(value);
|
||||||
|
|
||||||
if (normalized.contains("=")) {
|
if (normalized.contains("=")) {
|
||||||
normalized = normalized.substring(0, normalized.indexOf('=')).trim();
|
normalized = normalized.substring(0, normalized.indexOf('='));
|
||||||
}
|
}
|
||||||
|
|
||||||
while (normalized.startsWith("@") || normalized.startsWith("~")) {
|
while (normalized.startsWith("@") || normalized.startsWith("~")) {
|
||||||
normalized = normalized.substring(1).trim();
|
normalized = normalized.substring(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (normalized.length() > MAX_NAME_LENGTH) {
|
if (normalized.length() > MAX_NAME_LENGTH) {
|
||||||
|
|||||||
+3
-2
@@ -169,11 +169,12 @@ public final class WiredVariableReferenceSupport {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int now = Emulator.getIntUnixTimestamp();
|
int now = Emulator.getIntUnixTimestamp();
|
||||||
SharedUserAssignment nextAssignment = (existingAssignment == null)
|
boolean overwritten = existingAssignment != null && overrideExisting;
|
||||||
|
SharedUserAssignment nextAssignment = (existingAssignment == null || overwritten)
|
||||||
? new SharedUserAssignment(normalizedValue, now, now)
|
? new SharedUserAssignment(normalizedValue, now, now)
|
||||||
: new SharedUserAssignment(normalizedValue, existingAssignment.getCreatedAt(), Objects.equals(existingAssignment.getValue(), normalizedValue) ? existingAssignment.getUpdatedAt() : now);
|
: new SharedUserAssignment(normalizedValue, existingAssignment.getCreatedAt(), Objects.equals(existingAssignment.getValue(), normalizedValue) ? existingAssignment.getUpdatedAt() : now);
|
||||||
|
|
||||||
if (existingAssignment != null && Objects.equals(existingAssignment.getValue(), normalizedValue)) {
|
if (!overwritten && existingAssignment != null && Objects.equals(existingAssignment.getValue(), normalizedValue)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+17
-8
@@ -11,6 +11,7 @@ import com.eu.habbo.habbohotel.users.HabboItem;
|
|||||||
import com.eu.habbo.habbohotel.wired.WiredEffectType;
|
import com.eu.habbo.habbohotel.wired.WiredEffectType;
|
||||||
import com.eu.habbo.habbohotel.wired.core.WiredContext;
|
import com.eu.habbo.habbohotel.wired.core.WiredContext;
|
||||||
import com.eu.habbo.habbohotel.wired.core.WiredManager;
|
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.ServerMessage;
|
||||||
import com.eu.habbo.messages.incoming.wired.WiredSaveException;
|
import com.eu.habbo.messages.incoming.wired.WiredSaveException;
|
||||||
|
|
||||||
@@ -51,7 +52,6 @@ public class WiredEffectFurniByType extends InteractionWiredEffect {
|
|||||||
boolean includeWiredItems = this.includeWiredTargets(ctx);
|
boolean includeWiredItems = this.includeWiredTargets(ctx);
|
||||||
|
|
||||||
List<HabboItem> sourceFurni = resolveSourceFurni(ctx, room);
|
List<HabboItem> sourceFurni = resolveSourceFurni(ctx, room);
|
||||||
if (sourceFurni.isEmpty()) return;
|
|
||||||
|
|
||||||
Set<String> matchKeys = new LinkedHashSet<>();
|
Set<String> matchKeys = new LinkedHashSet<>();
|
||||||
for (HabboItem src : sourceFurni) {
|
for (HabboItem src : sourceFurni) {
|
||||||
@@ -85,12 +85,10 @@ public class WiredEffectFurniByType extends InteractionWiredEffect {
|
|||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
}
|
}
|
||||||
case SOURCE_FURNI_SIGNAL: {
|
case SOURCE_FURNI_SIGNAL: {
|
||||||
return new ArrayList<>(ctx.targets().items());
|
return WiredSourceUtil.resolveItemsRaw(ctx, WiredSourceUtil.SOURCE_SIGNAL, null);
|
||||||
}
|
}
|
||||||
case SOURCE_FURNI_TRIGGER: {
|
case SOURCE_FURNI_TRIGGER: {
|
||||||
return ctx.sourceItem()
|
return WiredSourceUtil.resolveItemsRaw(ctx, WiredSourceUtil.SOURCE_TRIGGER, null);
|
||||||
.map(Collections::singletonList)
|
|
||||||
.orElse(Collections.emptyList());
|
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
return Collections.emptyList();
|
return Collections.emptyList();
|
||||||
@@ -104,7 +102,7 @@ public class WiredEffectFurniByType extends InteractionWiredEffect {
|
|||||||
throw new WiredSaveException("wf_slc_furni_bytype: intParams must have at least 4 elements");
|
throw new WiredSaveException("wf_slc_furni_bytype: intParams must have at least 4 elements");
|
||||||
}
|
}
|
||||||
|
|
||||||
this.sourceType = SOURCE_FURNI_PICKED;
|
this.sourceType = normalizeSourceType(params[0]);
|
||||||
this.matchState = params.length > 1 && params[1] == 1;
|
this.matchState = params.length > 1 && params[1] == 1;
|
||||||
this.filterExisting = params.length > 2 && params[2] == 1;
|
this.filterExisting = params.length > 2 && params[2] == 1;
|
||||||
this.invert = params.length > 3 && params[3] == 1;
|
this.invert = params.length > 3 && params[3] == 1;
|
||||||
@@ -138,7 +136,7 @@ public class WiredEffectFurniByType extends InteractionWiredEffect {
|
|||||||
message.appendString("");
|
message.appendString("");
|
||||||
|
|
||||||
message.appendInt(4);
|
message.appendInt(4);
|
||||||
message.appendInt(SOURCE_FURNI_PICKED);
|
message.appendInt(this.sourceType);
|
||||||
message.appendInt(matchState ? 1 : 0);
|
message.appendInt(matchState ? 1 : 0);
|
||||||
message.appendInt(filterExisting ? 1 : 0);
|
message.appendInt(filterExisting ? 1 : 0);
|
||||||
message.appendInt(invert ? 1 : 0);
|
message.appendInt(invert ? 1 : 0);
|
||||||
@@ -168,7 +166,7 @@ public class WiredEffectFurniByType extends InteractionWiredEffect {
|
|||||||
String wiredData = set.getString("wired_data");
|
String wiredData = set.getString("wired_data");
|
||||||
if (wiredData != null && wiredData.startsWith("{")) {
|
if (wiredData != null && wiredData.startsWith("{")) {
|
||||||
JsonData data = WiredManager.getGson().fromJson(wiredData, JsonData.class);
|
JsonData data = WiredManager.getGson().fromJson(wiredData, JsonData.class);
|
||||||
this.sourceType = data.sourceType;
|
this.sourceType = normalizeSourceType(data.sourceType);
|
||||||
this.matchState = data.matchState;
|
this.matchState = data.matchState;
|
||||||
this.filterExisting = data.filterExisting;
|
this.filterExisting = data.filterExisting;
|
||||||
this.invert = data.invert;
|
this.invert = data.invert;
|
||||||
@@ -190,6 +188,17 @@ public class WiredEffectFurniByType extends InteractionWiredEffect {
|
|||||||
@Override
|
@Override
|
||||||
public boolean execute(RoomUnit roomUnit, Room room, Object[] stuff) { return false; }
|
public boolean execute(RoomUnit roomUnit, Room room, Object[] stuff) { return false; }
|
||||||
|
|
||||||
|
private int normalizeSourceType(int value) {
|
||||||
|
switch (value) {
|
||||||
|
case SOURCE_FURNI_SIGNAL:
|
||||||
|
case SOURCE_FURNI_TRIGGER:
|
||||||
|
case SOURCE_FURNI_PICKED:
|
||||||
|
return value;
|
||||||
|
default:
|
||||||
|
return SOURCE_FURNI_PICKED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static class JsonData {
|
static class JsonData {
|
||||||
int sourceType;
|
int sourceType;
|
||||||
boolean matchState;
|
boolean matchState;
|
||||||
|
|||||||
+48
-18
@@ -101,24 +101,46 @@ public class WiredEffectFurniNeighborhood extends InteractionWiredEffect {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private List<int[]> resolveSourcePositions(WiredContext ctx, Room room) {
|
private List<int[]> resolveSourcePositions(WiredContext ctx, Room room) {
|
||||||
|
|
||||||
if (isUserGroup(sourceType)) {
|
|
||||||
// Prefer the event tile for user-based sources because during walk-on/walk-off
|
|
||||||
// events the user's position (getX/getY) hasn't been updated yet (stale position).
|
|
||||||
// The event tile correctly represents where the triggering action occurred.
|
|
||||||
if (ctx.tile().isPresent()) {
|
|
||||||
return Collections.singletonList(new int[]{ ctx.tile().get().x, ctx.tile().get().y });
|
|
||||||
}
|
|
||||||
List<int[]> positions = ctx.targets().users().stream()
|
|
||||||
.map(u -> new int[]{ u.getX(), u.getY() })
|
|
||||||
.collect(Collectors.toList());
|
|
||||||
if (positions.isEmpty()) {
|
|
||||||
ctx.actor().ifPresent(a -> positions.add(new int[]{ a.getX(), a.getY() }));
|
|
||||||
}
|
|
||||||
return positions;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (sourceType) {
|
switch (sourceType) {
|
||||||
|
case SOURCE_USER_TRIGGER: {
|
||||||
|
if (ctx.tile().isPresent()) {
|
||||||
|
return Collections.singletonList(new int[]{ ctx.tile().get().x, ctx.tile().get().y });
|
||||||
|
}
|
||||||
|
|
||||||
|
return ctx.actor()
|
||||||
|
.map(actor -> Collections.singletonList(new int[]{ actor.getX(), actor.getY() }))
|
||||||
|
.orElse(Collections.emptyList());
|
||||||
|
}
|
||||||
|
case SOURCE_USER_SIGNAL: {
|
||||||
|
List<int[]> positions = ctx.targets().users().stream()
|
||||||
|
.map(user -> new int[]{ user.getX(), user.getY() })
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
|
if (!positions.isEmpty()) {
|
||||||
|
return positions;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ctx.actor()
|
||||||
|
.map(actor -> Collections.singletonList(new int[]{ actor.getX(), actor.getY() }))
|
||||||
|
.orElse(Collections.emptyList());
|
||||||
|
}
|
||||||
|
case SOURCE_USER_CLICKED: {
|
||||||
|
if (ctx.event().getTargetUnit().isPresent()) {
|
||||||
|
RoomUnit targetUnit = ctx.event().getTargetUnit().get();
|
||||||
|
|
||||||
|
return Collections.singletonList(new int[]{ targetUnit.getX(), targetUnit.getY() });
|
||||||
|
}
|
||||||
|
|
||||||
|
List<int[]> positions = ctx.targets().users().stream()
|
||||||
|
.map(user -> new int[]{ user.getX(), user.getY() })
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
|
if (!positions.isEmpty()) {
|
||||||
|
return positions;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
case SOURCE_FURNI_TRIGGER: {
|
case SOURCE_FURNI_TRIGGER: {
|
||||||
return ctx.sourceItem()
|
return ctx.sourceItem()
|
||||||
.map(i -> Collections.singletonList(new int[]{ i.getX(), i.getY() }))
|
.map(i -> Collections.singletonList(new int[]{ i.getX(), i.getY() }))
|
||||||
@@ -132,9 +154,17 @@ public class WiredEffectFurniNeighborhood extends InteractionWiredEffect {
|
|||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
}
|
}
|
||||||
case SOURCE_FURNI_SIGNAL: {
|
case SOURCE_FURNI_SIGNAL: {
|
||||||
return ctx.targets().items().stream()
|
List<int[]> positions = ctx.targets().items().stream()
|
||||||
.map(i -> new int[]{ i.getX(), i.getY() })
|
.map(i -> new int[]{ i.getX(), i.getY() })
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
|
if (!positions.isEmpty()) {
|
||||||
|
return positions;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ctx.sourceItem()
|
||||||
|
.map(item -> Collections.singletonList(new int[]{ item.getX(), item.getY() }))
|
||||||
|
.orElse(Collections.emptyList());
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
return Collections.emptyList();
|
return Collections.emptyList();
|
||||||
|
|||||||
+48
-18
@@ -111,24 +111,46 @@ public class WiredEffectUsersNeighborhood extends InteractionWiredEffect {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private List<int[]> resolveSourcePositions(WiredContext ctx, Room room) {
|
private List<int[]> resolveSourcePositions(WiredContext ctx, Room room) {
|
||||||
|
|
||||||
if (isUserGroup(sourceType)) {
|
|
||||||
// Prefer the event tile for user-based sources because during walk-on/walk-off
|
|
||||||
// events the user's position (getX/getY) hasn't been updated yet (stale position).
|
|
||||||
// The event tile correctly represents where the triggering action occurred.
|
|
||||||
if (ctx.tile().isPresent()) {
|
|
||||||
return Collections.singletonList(new int[]{ ctx.tile().get().x, ctx.tile().get().y });
|
|
||||||
}
|
|
||||||
List<int[]> positions = ctx.targets().users().stream()
|
|
||||||
.map(u -> new int[]{ u.getX(), u.getY() })
|
|
||||||
.collect(Collectors.toList());
|
|
||||||
if (positions.isEmpty()) {
|
|
||||||
ctx.actor().ifPresent(a -> positions.add(new int[]{ a.getX(), a.getY() }));
|
|
||||||
}
|
|
||||||
return positions;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (sourceType) {
|
switch (sourceType) {
|
||||||
|
case SOURCE_USER_TRIGGER: {
|
||||||
|
if (ctx.tile().isPresent()) {
|
||||||
|
return Collections.singletonList(new int[]{ ctx.tile().get().x, ctx.tile().get().y });
|
||||||
|
}
|
||||||
|
|
||||||
|
return ctx.actor()
|
||||||
|
.map(actor -> Collections.singletonList(new int[]{ actor.getX(), actor.getY() }))
|
||||||
|
.orElse(Collections.emptyList());
|
||||||
|
}
|
||||||
|
case SOURCE_USER_SIGNAL: {
|
||||||
|
List<int[]> positions = ctx.targets().users().stream()
|
||||||
|
.map(user -> new int[]{ user.getX(), user.getY() })
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
|
if (!positions.isEmpty()) {
|
||||||
|
return positions;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ctx.actor()
|
||||||
|
.map(actor -> Collections.singletonList(new int[]{ actor.getX(), actor.getY() }))
|
||||||
|
.orElse(Collections.emptyList());
|
||||||
|
}
|
||||||
|
case SOURCE_USER_CLICKED: {
|
||||||
|
if (ctx.event().getTargetUnit().isPresent()) {
|
||||||
|
RoomUnit targetUnit = ctx.event().getTargetUnit().get();
|
||||||
|
|
||||||
|
return Collections.singletonList(new int[]{ targetUnit.getX(), targetUnit.getY() });
|
||||||
|
}
|
||||||
|
|
||||||
|
List<int[]> positions = ctx.targets().users().stream()
|
||||||
|
.map(user -> new int[]{ user.getX(), user.getY() })
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
|
if (!positions.isEmpty()) {
|
||||||
|
return positions;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
case SOURCE_FURNI_TRIGGER: {
|
case SOURCE_FURNI_TRIGGER: {
|
||||||
return ctx.sourceItem()
|
return ctx.sourceItem()
|
||||||
.map(i -> Collections.singletonList(new int[]{ i.getX(), i.getY() }))
|
.map(i -> Collections.singletonList(new int[]{ i.getX(), i.getY() }))
|
||||||
@@ -142,9 +164,17 @@ public class WiredEffectUsersNeighborhood extends InteractionWiredEffect {
|
|||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
}
|
}
|
||||||
case SOURCE_FURNI_SIGNAL: {
|
case SOURCE_FURNI_SIGNAL: {
|
||||||
return ctx.targets().items().stream()
|
List<int[]> positions = ctx.targets().items().stream()
|
||||||
.map(i -> new int[]{ i.getX(), i.getY() })
|
.map(i -> new int[]{ i.getX(), i.getY() })
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
|
if (!positions.isEmpty()) {
|
||||||
|
return positions;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ctx.sourceItem()
|
||||||
|
.map(item -> Collections.singletonList(new int[]{ item.getX(), item.getY() }))
|
||||||
|
.orElse(Collections.emptyList());
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
return Collections.emptyList();
|
return Collections.emptyList();
|
||||||
|
|||||||
+46
@@ -68,6 +68,52 @@ public class WiredTriggerReceiveSignal extends InteractionWiredTrigger {
|
|||||||
return channel;
|
return channel;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean unlinkAntenna(int antennaItemId) {
|
||||||
|
if (antennaItemId <= 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean changed = false;
|
||||||
|
|
||||||
|
if (!this.items.isEmpty()) {
|
||||||
|
THashSet<HabboItem> itemsToRemove = new THashSet<>();
|
||||||
|
|
||||||
|
for (HabboItem item : this.items) {
|
||||||
|
if (item == null || item.getId() == antennaItemId) {
|
||||||
|
itemsToRemove.add(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!itemsToRemove.isEmpty()) {
|
||||||
|
this.items.removeAll(itemsToRemove);
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.furniSource == WiredSourceUtil.SOURCE_SELECTED) {
|
||||||
|
int nextChannel = 0;
|
||||||
|
|
||||||
|
if (!this.items.isEmpty()) {
|
||||||
|
HabboItem firstItem = this.items.iterator().next();
|
||||||
|
nextChannel = (firstItem != null) ? firstItem.getId() : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.channel != nextChannel) {
|
||||||
|
this.channel = nextChannel;
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
} else if (this.channel == antennaItemId) {
|
||||||
|
this.channel = 0;
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (changed) {
|
||||||
|
this.needsUpdate(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
return changed;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isTriggeredByRoomUnit() {
|
public boolean isTriggeredByRoomUnit() {
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -147,12 +147,14 @@ public class RoomFurniVariableManager {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean changed = existingAssignment == null || !Objects.equals(existingAssignment.getValue(), normalizedValue);
|
boolean overwritten = existingAssignment != null && overrideExisting;
|
||||||
|
boolean valueChanged = existingAssignment == null || !Objects.equals(existingAssignment.getValue(), normalizedValue);
|
||||||
|
boolean changed = overwritten || valueChanged;
|
||||||
|
|
||||||
if (existingAssignment == null) {
|
if (existingAssignment == null || overwritten) {
|
||||||
int now = Emulator.getIntUnixTimestamp();
|
int now = Emulator.getIntUnixTimestamp();
|
||||||
assignments.put(definitionItemId, new VariableAssignment(normalizedValue, now, now));
|
assignments.put(definitionItemId, new VariableAssignment(normalizedValue, now, now));
|
||||||
} else if (changed) {
|
} else if (valueChanged) {
|
||||||
existingAssignment.setValue(normalizedValue, Emulator.getIntUnixTimestamp());
|
existingAssignment.setValue(normalizedValue, Emulator.getIntUnixTimestamp());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -613,7 +615,13 @@ public class RoomFurniVariableManager {
|
|||||||
|
|
||||||
for (InteractionWiredExtra extra : extras) {
|
for (InteractionWiredExtra extra : extras) {
|
||||||
if (extra instanceof WiredExtraFurniVariable) {
|
if (extra instanceof WiredExtraFurniVariable) {
|
||||||
result.add((WiredExtraFurniVariable) extra);
|
WiredExtraFurniVariable definition = (WiredExtraFurniVariable) extra;
|
||||||
|
|
||||||
|
if (!hasVisibleDefinitionName(definition.getVariableName())) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
result.add(definition);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -659,6 +667,11 @@ public class RoomFurniVariableManager {
|
|||||||
|
|
||||||
if (extra instanceof WiredExtraFurniVariable) {
|
if (extra instanceof WiredExtraFurniVariable) {
|
||||||
WiredExtraFurniVariable definition = (WiredExtraFurniVariable) extra;
|
WiredExtraFurniVariable definition = (WiredExtraFurniVariable) extra;
|
||||||
|
|
||||||
|
if (!hasVisibleDefinitionName(definition.getVariableName())) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
return new WiredVariableDefinitionInfo(
|
return new WiredVariableDefinitionInfo(
|
||||||
definition.getId(),
|
definition.getId(),
|
||||||
definition.getVariableName(),
|
definition.getVariableName(),
|
||||||
@@ -670,7 +683,8 @@ public class RoomFurniVariableManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (extra instanceof WiredExtraVariableEcho && ((WiredExtraVariableEcho) extra).isFurniEcho()) {
|
if (extra instanceof WiredExtraVariableEcho && ((WiredExtraVariableEcho) extra).isFurniEcho()) {
|
||||||
return ((WiredExtraVariableEcho) extra).createDefinitionInfo(this.room);
|
WiredVariableDefinitionInfo info = ((WiredExtraVariableEcho) extra).createDefinitionInfo(this.room);
|
||||||
|
return (info != null && hasVisibleDefinitionName(info.getName())) ? info : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return WiredVariableLevelSystemSupport.getDerivedDefinitionInfo(this.room, WiredVariableLevelSystemSupport.TARGET_FURNI, definitionItemId);
|
return WiredVariableLevelSystemSupport.getDerivedDefinitionInfo(this.room, WiredVariableLevelSystemSupport.TARGET_FURNI, definitionItemId);
|
||||||
@@ -703,7 +717,13 @@ public class RoomFurniVariableManager {
|
|||||||
|
|
||||||
for (InteractionWiredExtra extra : this.room.getRoomSpecialTypes().getExtras()) {
|
for (InteractionWiredExtra extra : this.room.getRoomSpecialTypes().getExtras()) {
|
||||||
if (extra instanceof WiredExtraVariableEcho && ((WiredExtraVariableEcho) extra).isFurniEcho()) {
|
if (extra instanceof WiredExtraVariableEcho && ((WiredExtraVariableEcho) extra).isFurniEcho()) {
|
||||||
result.add((WiredExtraVariableEcho) extra);
|
WiredExtraVariableEcho echo = (WiredExtraVariableEcho) extra;
|
||||||
|
|
||||||
|
if (!hasVisibleDefinitionName(echo.getVariableName())) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
result.add(echo);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -711,6 +731,10 @@ public class RoomFurniVariableManager {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static boolean hasVisibleDefinitionName(String name) {
|
||||||
|
return name != null && !name.trim().isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
private VariableAssignment getRawAssignment(int furniId, int definitionItemId) {
|
private VariableAssignment getRawAssignment(int furniId, int definitionItemId) {
|
||||||
if (furniId <= 0 || definitionItemId <= 0) {
|
if (furniId <= 0 || definitionItemId <= 0) {
|
||||||
return null;
|
return null;
|
||||||
|
|||||||
@@ -804,6 +804,11 @@ public class RoomItemManager {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
boolean cleanedSignalAntennaReferences = false;
|
||||||
|
if (this.isAntennaItem(item)) {
|
||||||
|
cleanedSignalAntennaReferences = specialTypes.unlinkSignalAntennaReferences(item.getId());
|
||||||
|
}
|
||||||
|
|
||||||
this.room.getFurniVariableManager().removeAssignmentsForFurni(item.getId());
|
this.room.getFurniVariableManager().removeAssignmentsForFurni(item.getId());
|
||||||
|
|
||||||
boolean isWiredItem = false;
|
boolean isWiredItem = false;
|
||||||
@@ -905,11 +910,20 @@ public class RoomItemManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Invalidate wired cache when wired items are removed
|
// Invalidate wired cache when wired items are removed
|
||||||
if (isWiredItem) {
|
if (isWiredItem || cleanedSignalAntennaReferences) {
|
||||||
WiredManager.invalidateRoom(this.room);
|
WiredManager.invalidateRoom(this.room);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean isAntennaItem(HabboItem item) {
|
||||||
|
if (item == null || item.getBaseItem() == null || item.getBaseItem().getInteractionType() == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
String interactionType = item.getBaseItem().getInteractionType().getName();
|
||||||
|
return interactionType != null && interactionType.equalsIgnoreCase("antenna");
|
||||||
|
}
|
||||||
|
|
||||||
// ==================== ITEM UPDATES ====================
|
// ==================== ITEM UPDATES ====================
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -348,7 +348,7 @@ public class RoomSpecialTypes {
|
|||||||
public static final int MAX_SENDERS_PER_RECEIVER = 5;
|
public static final int MAX_SENDERS_PER_RECEIVER = 5;
|
||||||
|
|
||||||
public boolean isSignalSenderLimitReached() {
|
public boolean isSignalSenderLimitReached() {
|
||||||
Set<InteractionWiredEffect> existing = this.wiredEffects.get(WiredEffectType.SEND_SIGNAL);
|
Set<InteractionWiredEffect> existing = this.getSignalSenders();
|
||||||
return existing != null && existing.size() >= MAX_SIGNAL_SENDERS_PER_ROOM;
|
return existing != null && existing.size() >= MAX_SIGNAL_SENDERS_PER_ROOM;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -358,7 +358,7 @@ public class RoomSpecialTypes {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public int countSendersTargetingReceiver(int receiverItemId, InteractionWiredEffect excludeSender) {
|
public int countSendersTargetingReceiver(int receiverItemId, InteractionWiredEffect excludeSender) {
|
||||||
Set<InteractionWiredEffect> senders = this.wiredEffects.get(WiredEffectType.SEND_SIGNAL);
|
Set<InteractionWiredEffect> senders = this.getSignalSenders();
|
||||||
if (senders == null) return 0;
|
if (senders == null) return 0;
|
||||||
|
|
||||||
int count = 0;
|
int count = 0;
|
||||||
@@ -383,7 +383,7 @@ public class RoomSpecialTypes {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
Set<InteractionWiredEffect> senders = this.wiredEffects.get(WiredEffectType.SEND_SIGNAL);
|
Set<InteractionWiredEffect> senders = this.getSignalSenders();
|
||||||
if (senders == null) {
|
if (senders == null) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -411,6 +411,62 @@ public class RoomSpecialTypes {
|
|||||||
return countSendersTargetingAnyReceiver(receiverItemIds, null);
|
return countSendersTargetingAnyReceiver(receiverItemIds, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean unlinkSignalAntennaReferences(int antennaItemId) {
|
||||||
|
if (antennaItemId <= 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean changed = false;
|
||||||
|
|
||||||
|
THashSet<InteractionWiredTrigger> receivers = this.getTriggers(WiredTriggerType.RECEIVE_SIGNAL);
|
||||||
|
for (InteractionWiredTrigger trigger : receivers) {
|
||||||
|
if (!(trigger instanceof com.eu.habbo.habbohotel.items.interactions.wired.triggers.WiredTriggerReceiveSignal receiver)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!receiver.unlinkAntenna(antennaItemId)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
changed = true;
|
||||||
|
Emulator.getThreading().run(receiver);
|
||||||
|
}
|
||||||
|
|
||||||
|
Set<InteractionWiredEffect> senders = this.getSignalSenders();
|
||||||
|
if (senders != null) {
|
||||||
|
for (InteractionWiredEffect effect : senders) {
|
||||||
|
if (!(effect instanceof WiredEffectSendSignal sender)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!sender.unlinkAntenna(antennaItemId)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
changed = true;
|
||||||
|
Emulator.getThreading().run(sender);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return changed;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Set<InteractionWiredEffect> getSignalSenders() {
|
||||||
|
Set<InteractionWiredEffect> senders = new HashSet<>();
|
||||||
|
|
||||||
|
Set<InteractionWiredEffect> standardSenders = this.wiredEffects.get(WiredEffectType.SEND_SIGNAL);
|
||||||
|
if (standardSenders != null) {
|
||||||
|
senders.addAll(standardSenders);
|
||||||
|
}
|
||||||
|
|
||||||
|
Set<InteractionWiredEffect> negativeSenders = this.wiredEffects.get(WiredEffectType.NEG_SEND_SIGNAL);
|
||||||
|
if (negativeSenders != null) {
|
||||||
|
senders.addAll(negativeSenders);
|
||||||
|
}
|
||||||
|
|
||||||
|
return senders.isEmpty() ? null : senders;
|
||||||
|
}
|
||||||
|
|
||||||
public void addTrigger(InteractionWiredTrigger trigger) {
|
public void addTrigger(InteractionWiredTrigger trigger) {
|
||||||
// Add to type-based index
|
// Add to type-based index
|
||||||
this.wiredTriggers.computeIfAbsent(trigger.getType(), k -> ConcurrentHashMap.newKeySet())
|
this.wiredTriggers.computeIfAbsent(trigger.getType(), k -> ConcurrentHashMap.newKeySet())
|
||||||
|
|||||||
@@ -158,12 +158,14 @@ public class RoomUserVariableManager {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean changed = existingAssignment == null || !Objects.equals(existingAssignment.getValue(), normalizedValue);
|
boolean overwritten = existingAssignment != null && overrideExisting;
|
||||||
|
boolean valueChanged = existingAssignment == null || !Objects.equals(existingAssignment.getValue(), normalizedValue);
|
||||||
|
boolean changed = overwritten || valueChanged;
|
||||||
|
|
||||||
if (existingAssignment == null) {
|
if (existingAssignment == null || overwritten) {
|
||||||
int now = Emulator.getIntUnixTimestamp();
|
int now = Emulator.getIntUnixTimestamp();
|
||||||
assignments.put(definitionItemId, new VariableAssignment(normalizedValue, now, now));
|
assignments.put(definitionItemId, new VariableAssignment(normalizedValue, now, now));
|
||||||
} else if (changed) {
|
} else if (valueChanged) {
|
||||||
existingAssignment.setValue(normalizedValue, Emulator.getIntUnixTimestamp());
|
existingAssignment.setValue(normalizedValue, Emulator.getIntUnixTimestamp());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -686,7 +688,13 @@ public class RoomUserVariableManager {
|
|||||||
|
|
||||||
for (InteractionWiredExtra extra : extras) {
|
for (InteractionWiredExtra extra : extras) {
|
||||||
if (extra instanceof WiredExtraUserVariable) {
|
if (extra instanceof WiredExtraUserVariable) {
|
||||||
result.add((WiredExtraUserVariable) extra);
|
WiredExtraUserVariable definition = (WiredExtraUserVariable) extra;
|
||||||
|
|
||||||
|
if (!hasVisibleDefinitionName(definition.getVariableName())) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
result.add(definition);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -743,6 +751,11 @@ public class RoomUserVariableManager {
|
|||||||
|
|
||||||
if (extra instanceof WiredExtraUserVariable) {
|
if (extra instanceof WiredExtraUserVariable) {
|
||||||
WiredExtraUserVariable definition = (WiredExtraUserVariable) extra;
|
WiredExtraUserVariable definition = (WiredExtraUserVariable) extra;
|
||||||
|
|
||||||
|
if (!hasVisibleDefinitionName(definition.getVariableName())) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
return new WiredVariableDefinitionInfo(
|
return new WiredVariableDefinitionInfo(
|
||||||
definition.getId(),
|
definition.getId(),
|
||||||
definition.getVariableName(),
|
definition.getVariableName(),
|
||||||
@@ -755,11 +768,17 @@ public class RoomUserVariableManager {
|
|||||||
|
|
||||||
if (extra instanceof WiredExtraVariableReference && ((WiredExtraVariableReference) extra).isUserReference()) {
|
if (extra instanceof WiredExtraVariableReference && ((WiredExtraVariableReference) extra).isUserReference()) {
|
||||||
WiredExtraVariableReference reference = (WiredExtraVariableReference) extra;
|
WiredExtraVariableReference reference = (WiredExtraVariableReference) extra;
|
||||||
|
|
||||||
|
if (!hasVisibleDefinitionName(reference.getVariableName())) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
return new WiredVariableDefinitionInfo(reference.getId(), reference.getVariableName(), reference.hasValue(), reference.getAvailability(), false, reference.isReadOnly());
|
return new WiredVariableDefinitionInfo(reference.getId(), reference.getVariableName(), reference.hasValue(), reference.getAvailability(), false, reference.isReadOnly());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (extra instanceof WiredExtraVariableEcho && ((WiredExtraVariableEcho) extra).isUserEcho()) {
|
if (extra instanceof WiredExtraVariableEcho && ((WiredExtraVariableEcho) extra).isUserEcho()) {
|
||||||
return ((WiredExtraVariableEcho) extra).createDefinitionInfo(this.room);
|
WiredVariableDefinitionInfo info = ((WiredExtraVariableEcho) extra).createDefinitionInfo(this.room);
|
||||||
|
return (info != null && hasVisibleDefinitionName(info.getName())) ? info : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return WiredVariableLevelSystemSupport.getDerivedDefinitionInfo(this.room, WiredVariableLevelSystemSupport.TARGET_USER, definitionItemId);
|
return WiredVariableLevelSystemSupport.getDerivedDefinitionInfo(this.room, WiredVariableLevelSystemSupport.TARGET_USER, definitionItemId);
|
||||||
@@ -792,7 +811,13 @@ public class RoomUserVariableManager {
|
|||||||
|
|
||||||
for (InteractionWiredExtra extra : this.room.getRoomSpecialTypes().getExtras()) {
|
for (InteractionWiredExtra extra : this.room.getRoomSpecialTypes().getExtras()) {
|
||||||
if (extra instanceof WiredExtraVariableReference && ((WiredExtraVariableReference) extra).isUserReference()) {
|
if (extra instanceof WiredExtraVariableReference && ((WiredExtraVariableReference) extra).isUserReference()) {
|
||||||
result.add((WiredExtraVariableReference) extra);
|
WiredExtraVariableReference reference = (WiredExtraVariableReference) extra;
|
||||||
|
|
||||||
|
if (!hasVisibleDefinitionName(reference.getVariableName())) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
result.add(reference);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -809,7 +834,13 @@ public class RoomUserVariableManager {
|
|||||||
|
|
||||||
for (InteractionWiredExtra extra : this.room.getRoomSpecialTypes().getExtras()) {
|
for (InteractionWiredExtra extra : this.room.getRoomSpecialTypes().getExtras()) {
|
||||||
if (extra instanceof WiredExtraVariableEcho && ((WiredExtraVariableEcho) extra).isUserEcho()) {
|
if (extra instanceof WiredExtraVariableEcho && ((WiredExtraVariableEcho) extra).isUserEcho()) {
|
||||||
result.add((WiredExtraVariableEcho) extra);
|
WiredExtraVariableEcho echo = (WiredExtraVariableEcho) extra;
|
||||||
|
|
||||||
|
if (!hasVisibleDefinitionName(echo.getVariableName())) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
result.add(echo);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -817,6 +848,10 @@ public class RoomUserVariableManager {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static boolean hasVisibleDefinitionName(String name) {
|
||||||
|
return name != null && !name.trim().isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
private VariableAssignment getRawAssignment(int userId, int definitionItemId) {
|
private VariableAssignment getRawAssignment(int userId, int definitionItemId) {
|
||||||
if (userId <= 0 || definitionItemId <= 0) {
|
if (userId <= 0 || definitionItemId <= 0) {
|
||||||
return null;
|
return null;
|
||||||
|
|||||||
@@ -457,7 +457,13 @@ public class RoomVariableManager {
|
|||||||
|
|
||||||
for (InteractionWiredExtra extra : extras) {
|
for (InteractionWiredExtra extra : extras) {
|
||||||
if (extra instanceof WiredExtraRoomVariable) {
|
if (extra instanceof WiredExtraRoomVariable) {
|
||||||
result.add((WiredExtraRoomVariable) extra);
|
WiredExtraRoomVariable definition = (WiredExtraRoomVariable) extra;
|
||||||
|
|
||||||
|
if (!hasVisibleDefinitionName(definition.getVariableName())) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
result.add(definition);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -503,6 +509,11 @@ public class RoomVariableManager {
|
|||||||
|
|
||||||
if (extra instanceof WiredExtraRoomVariable) {
|
if (extra instanceof WiredExtraRoomVariable) {
|
||||||
WiredExtraRoomVariable definition = (WiredExtraRoomVariable) extra;
|
WiredExtraRoomVariable definition = (WiredExtraRoomVariable) extra;
|
||||||
|
|
||||||
|
if (!hasVisibleDefinitionName(definition.getVariableName())) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
return new WiredVariableDefinitionInfo(
|
return new WiredVariableDefinitionInfo(
|
||||||
definition.getId(),
|
definition.getId(),
|
||||||
definition.getVariableName(),
|
definition.getVariableName(),
|
||||||
@@ -515,11 +526,17 @@ public class RoomVariableManager {
|
|||||||
|
|
||||||
if (extra instanceof WiredExtraVariableReference && ((WiredExtraVariableReference) extra).isRoomReference()) {
|
if (extra instanceof WiredExtraVariableReference && ((WiredExtraVariableReference) extra).isRoomReference()) {
|
||||||
WiredExtraVariableReference reference = (WiredExtraVariableReference) extra;
|
WiredExtraVariableReference reference = (WiredExtraVariableReference) extra;
|
||||||
|
|
||||||
|
if (!hasVisibleDefinitionName(reference.getVariableName())) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
return new WiredVariableDefinitionInfo(reference.getId(), reference.getVariableName(), reference.hasValue(), reference.getAvailability(), false, reference.isReadOnly());
|
return new WiredVariableDefinitionInfo(reference.getId(), reference.getVariableName(), reference.hasValue(), reference.getAvailability(), false, reference.isReadOnly());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (extra instanceof WiredExtraVariableEcho && ((WiredExtraVariableEcho) extra).isRoomEcho()) {
|
if (extra instanceof WiredExtraVariableEcho && ((WiredExtraVariableEcho) extra).isRoomEcho()) {
|
||||||
return ((WiredExtraVariableEcho) extra).createDefinitionInfo(this.room);
|
WiredVariableDefinitionInfo info = ((WiredExtraVariableEcho) extra).createDefinitionInfo(this.room);
|
||||||
|
return (info != null && hasVisibleDefinitionName(info.getName())) ? info : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return WiredVariableLevelSystemSupport.getDerivedDefinitionInfo(this.room, WiredVariableLevelSystemSupport.TARGET_ROOM, definitionItemId);
|
return WiredVariableLevelSystemSupport.getDerivedDefinitionInfo(this.room, WiredVariableLevelSystemSupport.TARGET_ROOM, definitionItemId);
|
||||||
@@ -557,7 +574,13 @@ public class RoomVariableManager {
|
|||||||
|
|
||||||
for (InteractionWiredExtra extra : this.room.getRoomSpecialTypes().getExtras()) {
|
for (InteractionWiredExtra extra : this.room.getRoomSpecialTypes().getExtras()) {
|
||||||
if (extra instanceof WiredExtraVariableReference && ((WiredExtraVariableReference) extra).isRoomReference()) {
|
if (extra instanceof WiredExtraVariableReference && ((WiredExtraVariableReference) extra).isRoomReference()) {
|
||||||
result.add((WiredExtraVariableReference) extra);
|
WiredExtraVariableReference reference = (WiredExtraVariableReference) extra;
|
||||||
|
|
||||||
|
if (!hasVisibleDefinitionName(reference.getVariableName())) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
result.add(reference);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -574,7 +597,13 @@ public class RoomVariableManager {
|
|||||||
|
|
||||||
for (InteractionWiredExtra extra : this.room.getRoomSpecialTypes().getExtras()) {
|
for (InteractionWiredExtra extra : this.room.getRoomSpecialTypes().getExtras()) {
|
||||||
if (extra instanceof WiredExtraVariableEcho && ((WiredExtraVariableEcho) extra).isRoomEcho()) {
|
if (extra instanceof WiredExtraVariableEcho && ((WiredExtraVariableEcho) extra).isRoomEcho()) {
|
||||||
result.add((WiredExtraVariableEcho) extra);
|
WiredExtraVariableEcho echo = (WiredExtraVariableEcho) extra;
|
||||||
|
|
||||||
|
if (!hasVisibleDefinitionName(echo.getVariableName())) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
result.add(echo);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -696,6 +725,10 @@ public class RoomVariableManager {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static boolean hasVisibleDefinitionName(String name) {
|
||||||
|
return name != null && !name.trim().isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
public static class Snapshot {
|
public static class Snapshot {
|
||||||
private final int roomId;
|
private final int roomId;
|
||||||
private final List<DefinitionEntry> definitions;
|
private final List<DefinitionEntry> definitions;
|
||||||
|
|||||||
@@ -59,7 +59,9 @@ public enum WiredEffectType {
|
|||||||
REMOVE_VAR(73),
|
REMOVE_VAR(73),
|
||||||
CHANGE_VAR_VAL(74),
|
CHANGE_VAR_VAL(74),
|
||||||
FURNI_WITH_VAR_SELECTOR(75),
|
FURNI_WITH_VAR_SELECTOR(75),
|
||||||
USERS_WITH_VAR_SELECTOR(76);
|
USERS_WITH_VAR_SELECTOR(76),
|
||||||
|
NEG_CALL_STACKS(86),
|
||||||
|
NEG_SEND_SIGNAL(87);
|
||||||
|
|
||||||
public final int code;
|
public final int code;
|
||||||
|
|
||||||
|
|||||||
@@ -158,6 +158,34 @@ public final class RoomWiredStackIndex implements WiredStackIndex {
|
|||||||
return stacks.isEmpty() ? Collections.emptyList() : Collections.unmodifiableList(stacks);
|
return stacks.isEmpty() ? Collections.emptyList() : Collections.unmodifiableList(stacks);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<WiredStack> getStacksAtTile(Room room, RoomTile tile) {
|
||||||
|
if (room == null || tile == null || room.getRoomSpecialTypes() == null) {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
|
RoomSpecialTypes specialTypes = room.getRoomSpecialTypes();
|
||||||
|
THashSet<InteractionWiredTrigger> triggers = specialTypes.getTriggers(tile.x, tile.y);
|
||||||
|
|
||||||
|
if (triggers == null || triggers.isEmpty()) {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
|
List<WiredStack> stacks = new ArrayList<>();
|
||||||
|
|
||||||
|
for (InteractionWiredTrigger trigger : WiredExecutionOrderUtil.sort(triggers)) {
|
||||||
|
if (trigger == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
WiredStack stack = buildStack(room, specialTypes, trigger, tile.x, tile.y);
|
||||||
|
if (stack != null) {
|
||||||
|
stacks.add(stack);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return stacks.isEmpty() ? Collections.emptyList() : Collections.unmodifiableList(stacks);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Build a single wired stack for a trigger at a specific location.
|
* Build a single wired stack for a trigger at a specific location.
|
||||||
*/
|
*/
|
||||||
|
|||||||
+2
-2
@@ -71,7 +71,7 @@ public final class WiredContextVariableSupport {
|
|||||||
|
|
||||||
public static WiredVariableDefinitionInfo getDefinitionInfo(Room room, int definitionItemId) {
|
public static WiredVariableDefinitionInfo getDefinitionInfo(Room room, int definitionItemId) {
|
||||||
WiredExtraContextVariable definition = getDefinition(room, definitionItemId);
|
WiredExtraContextVariable definition = getDefinition(room, definitionItemId);
|
||||||
if (definition == null) {
|
if (definition == null || definition.getVariableName() == null || definition.getVariableName().trim().isEmpty()) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -85,7 +85,7 @@ public final class WiredContextVariableSupport {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static boolean hasDefinition(Room room, int definitionItemId) {
|
public static boolean hasDefinition(Room room, int definitionItemId) {
|
||||||
return getDefinition(room, definitionItemId) != null;
|
return getDefinitionInfo(room, definitionItemId) != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean assignVariable(WiredContext ctx, Room room, int definitionItemId, Integer value, boolean overrideExisting) {
|
public static boolean assignVariable(WiredContext ctx, Room room, int definitionItemId, Integer value, boolean overrideExisting) {
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ import com.eu.habbo.habbohotel.rooms.Room;
|
|||||||
import com.eu.habbo.habbohotel.rooms.RoomUnit;
|
import com.eu.habbo.habbohotel.rooms.RoomUnit;
|
||||||
import com.eu.habbo.habbohotel.users.HabboItem;
|
import com.eu.habbo.habbohotel.users.HabboItem;
|
||||||
import com.eu.habbo.habbohotel.wired.WiredConditionOperator;
|
import com.eu.habbo.habbohotel.wired.WiredConditionOperator;
|
||||||
|
import com.eu.habbo.habbohotel.wired.WiredEffectType;
|
||||||
import com.eu.habbo.habbohotel.wired.api.IWiredCondition;
|
import com.eu.habbo.habbohotel.wired.api.IWiredCondition;
|
||||||
import com.eu.habbo.habbohotel.wired.api.IWiredEffect;
|
import com.eu.habbo.habbohotel.wired.api.IWiredEffect;
|
||||||
import com.eu.habbo.habbohotel.wired.api.WiredStack;
|
import com.eu.habbo.habbohotel.wired.api.WiredStack;
|
||||||
@@ -159,6 +160,10 @@ public final class WiredEngine {
|
|||||||
* @return true if any stack was triggered (useful for SAY_SOMETHING to suppress message)
|
* @return true if any stack was triggered (useful for SAY_SOMETHING to suppress message)
|
||||||
*/
|
*/
|
||||||
public boolean handleEvent(WiredEvent event) {
|
public boolean handleEvent(WiredEvent event) {
|
||||||
|
return handleEvent(event, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean handleEvent(WiredEvent event, boolean negateConditions) {
|
||||||
if (event == null) {
|
if (event == null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -192,7 +197,7 @@ public final class WiredEngine {
|
|||||||
roomRecursionDepth.put(roomId, currentDepth + 1);
|
roomRecursionDepth.put(roomId, currentDepth + 1);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
return handleEventInternal(event, room);
|
return handleEventInternal(event, room, negateConditions);
|
||||||
} finally {
|
} finally {
|
||||||
// Decrement recursion depth
|
// Decrement recursion depth
|
||||||
int newDepth = roomRecursionDepth.getOrDefault(roomId, 1) - 1;
|
int newDepth = roomRecursionDepth.getOrDefault(roomId, 1) - 1;
|
||||||
@@ -329,7 +334,7 @@ public final class WiredEngine {
|
|||||||
/**
|
/**
|
||||||
* Internal event handling after recursion check.
|
* Internal event handling after recursion check.
|
||||||
*/
|
*/
|
||||||
private boolean handleEventInternal(WiredEvent event, Room room) {
|
private boolean handleEventInternal(WiredEvent event, Room room, boolean negateConditions) {
|
||||||
|
|
||||||
// Find candidate stacks for this event type
|
// Find candidate stacks for this event type
|
||||||
List<WiredStack> stacks = index.getStacks(room, event.getType());
|
List<WiredStack> stacks = index.getStacks(room, event.getType());
|
||||||
@@ -345,7 +350,7 @@ public final class WiredEngine {
|
|||||||
|
|
||||||
for (WiredStack stack : stacks) {
|
for (WiredStack stack : stacks) {
|
||||||
try {
|
try {
|
||||||
boolean triggered = processStack(stack, event, triggerTime);
|
boolean triggered = processStack(stack, event, triggerTime, negateConditions);
|
||||||
if (triggered) {
|
if (triggered) {
|
||||||
anyTriggered = true;
|
anyTriggered = true;
|
||||||
|
|
||||||
@@ -374,6 +379,10 @@ public final class WiredEngine {
|
|||||||
* Process a single wired stack.
|
* Process a single wired stack.
|
||||||
*/
|
*/
|
||||||
private boolean processStack(WiredStack stack, WiredEvent event, long currentTime) {
|
private boolean processStack(WiredStack stack, WiredEvent event, long currentTime) {
|
||||||
|
return processStack(stack, event, currentTime, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean processStack(WiredStack stack, WiredEvent event, long currentTime, boolean negateConditions) {
|
||||||
Room room = event.getRoom();
|
Room room = event.getRoom();
|
||||||
WiredTextInputCaptureSupport.CaptureResult captureResult = resolveTextInputCapture(stack, event);
|
WiredTextInputCaptureSupport.CaptureResult captureResult = resolveTextInputCapture(stack, event);
|
||||||
|
|
||||||
@@ -417,17 +426,12 @@ public final class WiredEngine {
|
|||||||
applySelectionFilterExtras(stack, ctx, executedSelectors);
|
applySelectionFilterExtras(stack, ctx, executedSelectors);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Evaluate conditions
|
boolean conditionsPassedForExecution = getConditionOutcomeForExecution(stack, ctx, negateConditions);
|
||||||
if (stack.hasConditions()) {
|
List<IWiredEffect> executableEffects = getExecutableEffectsForCurrentExecution(stack, conditionsPassedForExecution);
|
||||||
debug(room, "Evaluating {} conditions...", stack.conditions().size());
|
boolean hasSpecialOutcome = conditionsPassedForExecution && hasSpecialTriggerOutcome(stack, event);
|
||||||
boolean conditionsPassed = evaluateConditions(stack, ctx);
|
|
||||||
debug(room, "Conditions result: {}", conditionsPassed ? "PASSED" : "FAILED");
|
if (!shouldContinueAfterConditionCheck(stack, room, conditionsPassedForExecution, executableEffects, hasSpecialOutcome)) {
|
||||||
if (!conditionsPassed) {
|
return false;
|
||||||
debug(room, "Conditions failed, aborting stack");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
debug(room, "No conditions in stack, proceeding to effects");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
WiredExtraExecutionLimit executionLimitExtra = getExecutionLimitExtra(room, stack);
|
WiredExtraExecutionLimit executionLimitExtra = getExecutionLimitExtra(room, stack);
|
||||||
@@ -455,7 +459,8 @@ public final class WiredEngine {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((event.getType() == WiredEvent.Type.USER_CLICKS_USER)
|
if (conditionsPassedForExecution
|
||||||
|
&& (event.getType() == WiredEvent.Type.USER_CLICKS_USER)
|
||||||
&& (stack.triggerItem() instanceof WiredTriggerHabboClicksUser)
|
&& (stack.triggerItem() instanceof WiredTriggerHabboClicksUser)
|
||||||
&& event.getActor().isPresent()) {
|
&& event.getActor().isPresent()) {
|
||||||
WiredTriggerHabboClicksUser clickUserTrigger = (WiredTriggerHabboClicksUser) stack.triggerItem();
|
WiredTriggerHabboClicksUser clickUserTrigger = (WiredTriggerHabboClicksUser) stack.triggerItem();
|
||||||
@@ -477,8 +482,8 @@ public final class WiredEngine {
|
|||||||
finalizeSelectors(executedSelectors, ctx, currentTime);
|
finalizeSelectors(executedSelectors, ctx, currentTime);
|
||||||
|
|
||||||
// Execute effects
|
// Execute effects
|
||||||
if (stack.hasEffects()) {
|
if (!executableEffects.isEmpty()) {
|
||||||
executeEffects(stack, ctx, currentTime);
|
executeEffects(stack, executableEffects, ctx, currentTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fire executed event
|
// Fire executed event
|
||||||
@@ -494,6 +499,139 @@ public final class WiredEngine {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean executeDirectStack(WiredStack stack, WiredEvent event, boolean negateConditions) {
|
||||||
|
if (stack == null || event == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Room room = event.getRoom();
|
||||||
|
if (room == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stack.trigger().requiresActor() && !event.getActor().isPresent()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!stackHasExecutableOutcome(stack, event)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
long currentTime = System.currentTimeMillis();
|
||||||
|
|
||||||
|
WiredState state = new WiredState(maxStepsPerStack);
|
||||||
|
WiredContext ctx = new WiredContext(event, stack.triggerItem(), stack, services, state, null);
|
||||||
|
WiredRoomDiagnostics diagnostics = getDiagnostics(room.getId());
|
||||||
|
|
||||||
|
state.step();
|
||||||
|
|
||||||
|
int stackCost = estimateStackCost(stack, roomRecursionDepth.getOrDefault(room.getId(), 0));
|
||||||
|
String monitorSourceLabel = getMonitorSourceLabel(stack.triggerItem(), event);
|
||||||
|
int monitorSourceId = getMonitorSourceId(stack.triggerItem());
|
||||||
|
|
||||||
|
debug(room, "Direct stack execution for item {} (conditions: {}, effects: {}, negated: {})",
|
||||||
|
stack.triggerItem() != null ? stack.triggerItem().getId() : "null",
|
||||||
|
stack.conditions().size(),
|
||||||
|
stack.effects().size(),
|
||||||
|
negateConditions);
|
||||||
|
|
||||||
|
List<InteractionWiredEffect> executedSelectors = Collections.emptyList();
|
||||||
|
if (stack.hasEffects()) {
|
||||||
|
executedSelectors = executeSelectors(stack, ctx);
|
||||||
|
applySelectionFilterExtras(stack, ctx, executedSelectors);
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean conditionsPassedForExecution = getConditionOutcomeForExecution(stack, ctx, negateConditions);
|
||||||
|
List<IWiredEffect> executableEffects = getExecutableEffectsForCurrentExecution(stack, conditionsPassedForExecution);
|
||||||
|
boolean hasSpecialOutcome = conditionsPassedForExecution && hasSpecialTriggerOutcome(stack, event);
|
||||||
|
|
||||||
|
if (!shouldContinueAfterConditionCheck(stack, room, conditionsPassedForExecution, executableEffects, hasSpecialOutcome)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
WiredExtraExecutionLimit executionLimitExtra = getExecutionLimitExtra(room, stack);
|
||||||
|
if (executionLimitExtra != null && !executionLimitExtra.tryAcquireExecutionSlot(currentTime)) {
|
||||||
|
debug(room, "Execution limit blocked direct stack {} (max {} in {} ms)",
|
||||||
|
stack.triggerItem() != null ? stack.triggerItem().getId() : "null",
|
||||||
|
executionLimitExtra.getMaxExecutions(),
|
||||||
|
executionLimitExtra.getTimeWindowMs());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!fireTriggeredEvent(stack, event)) {
|
||||||
|
debug(room, "Direct stack cancelled by plugin");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!diagnostics.tryConsumeExecutionBudget(
|
||||||
|
stackCost,
|
||||||
|
currentTime,
|
||||||
|
monitorSourceLabel,
|
||||||
|
monitorSourceId,
|
||||||
|
buildStackMonitorReason(stack, event, stackCost))) {
|
||||||
|
debug(room, "Execution cap blocked direct stack {}", stack.triggerItem() != null ? stack.triggerItem().getId() : "null");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
RoomUnit actor = event.getActor().orElse(null);
|
||||||
|
|
||||||
|
if (stack.triggerItem() instanceof InteractionWiredTrigger) {
|
||||||
|
InteractionWiredTrigger trigger = (InteractionWiredTrigger) stack.triggerItem();
|
||||||
|
trigger.activateBox(room, actor, currentTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
activateExtras(room, stack.triggerItem(), actor, currentTime);
|
||||||
|
finalizeSelectors(executedSelectors, ctx, currentTime);
|
||||||
|
|
||||||
|
if (!executableEffects.isEmpty()) {
|
||||||
|
executeEffects(stack, executableEffects, ctx, currentTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
fireExecutedEvent(stack, event);
|
||||||
|
diagnostics.recordExecution(
|
||||||
|
state.elapsedMs(),
|
||||||
|
System.currentTimeMillis(),
|
||||||
|
monitorSourceLabel,
|
||||||
|
monitorSourceId,
|
||||||
|
buildExecutionMonitorReason(stack, state.elapsedMs())
|
||||||
|
);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean shouldExecuteDirectStack(WiredStack stack, WiredEvent event, boolean negateConditions) {
|
||||||
|
if (stack == null || event == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Room room = event.getRoom();
|
||||||
|
if (room == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stack.trigger().requiresActor() && !event.getActor().isPresent()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!stack.hasEffects()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
WiredState state = new WiredState(maxStepsPerStack);
|
||||||
|
WiredContext ctx = new WiredContext(event, stack.triggerItem(), stack, services, state, null);
|
||||||
|
state.step();
|
||||||
|
|
||||||
|
List<InteractionWiredEffect> executedSelectors = Collections.emptyList();
|
||||||
|
if (stack.hasEffects()) {
|
||||||
|
executedSelectors = executeSelectors(stack, ctx);
|
||||||
|
applySelectionFilterExtras(stack, ctx, executedSelectors);
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean conditionsPassedForExecution = getConditionOutcomeForExecution(stack, ctx, negateConditions);
|
||||||
|
List<IWiredEffect> executableEffects = getExecutableEffectsForCurrentExecution(stack, conditionsPassedForExecution);
|
||||||
|
return !executableEffects.isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
private boolean wouldTriggerStack(WiredStack stack, WiredEvent event, long currentTime) {
|
private boolean wouldTriggerStack(WiredStack stack, WiredEvent event, long currentTime) {
|
||||||
Room room = event.getRoom();
|
Room room = event.getRoom();
|
||||||
WiredTextInputCaptureSupport.CaptureResult captureResult = resolveTextInputCapture(stack, event);
|
WiredTextInputCaptureSupport.CaptureResult captureResult = resolveTextInputCapture(stack, event);
|
||||||
@@ -522,7 +660,14 @@ public final class WiredEngine {
|
|||||||
applySelectionFilterExtras(stack, ctx, executedSelectors);
|
applySelectionFilterExtras(stack, ctx, executedSelectors);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (stack.hasConditions() && !evaluateConditions(stack, ctx)) {
|
boolean conditionsPassedForExecution = getConditionOutcomeForExecution(stack, ctx, false);
|
||||||
|
if (!conditionsPassedForExecution) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
List<IWiredEffect> executableEffects = getExecutableEffectsForCurrentExecution(stack, true);
|
||||||
|
boolean hasSpecialOutcome = hasSpecialTriggerOutcome(stack, event);
|
||||||
|
if (executableEffects.isEmpty() && !hasSpecialOutcome) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -553,6 +698,67 @@ public final class WiredEngine {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean hasSpecialTriggerOutcome(WiredStack stack, WiredEvent event) {
|
||||||
|
if (stack == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stack.triggerItem() instanceof WiredTriggerHabboSaysKeyword) {
|
||||||
|
return ((WiredTriggerHabboSaysKeyword) stack.triggerItem()).isHideMessage();
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((event != null)
|
||||||
|
&& (event.getType() == WiredEvent.Type.USER_CLICKS_USER)
|
||||||
|
&& (stack.triggerItem() instanceof WiredTriggerHabboClicksUser)) {
|
||||||
|
WiredTriggerHabboClicksUser trigger = (WiredTriggerHabboClicksUser) stack.triggerItem();
|
||||||
|
return trigger.isBlockMenuOpen() || trigger.isDoNotRotate();
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean getConditionOutcomeForExecution(WiredStack stack, WiredContext ctx, boolean negateConditions) {
|
||||||
|
if (!stack.hasConditions()) {
|
||||||
|
return !negateConditions;
|
||||||
|
}
|
||||||
|
|
||||||
|
return shouldConditionsPass(stack, ctx, negateConditions);
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<IWiredEffect> getExecutableEffectsForCurrentExecution(WiredStack stack, boolean conditionsPassed) {
|
||||||
|
List<IWiredEffect> executableEffects = new ArrayList<>();
|
||||||
|
|
||||||
|
for (IWiredEffect effect : stack.effects()) {
|
||||||
|
if (effect == null || effect.isSelector()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean negativeEffect = isNegativeConditionEffect(effect);
|
||||||
|
|
||||||
|
if (conditionsPassed) {
|
||||||
|
if (!negativeEffect) {
|
||||||
|
executableEffects.add(effect);
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stack.hasConditions() && negativeEffect) {
|
||||||
|
executableEffects.add(effect);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return executableEffects;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isNegativeConditionEffect(IWiredEffect effect) {
|
||||||
|
if (!(effect instanceof InteractionWiredEffect)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
WiredEffectType effectType = ((InteractionWiredEffect) effect).getType();
|
||||||
|
return effectType == WiredEffectType.NEG_CALL_STACKS || effectType == WiredEffectType.NEG_SEND_SIGNAL;
|
||||||
|
}
|
||||||
|
|
||||||
private WiredTextInputCaptureSupport.CaptureResult resolveTextInputCapture(WiredStack stack, WiredEvent event) {
|
private WiredTextInputCaptureSupport.CaptureResult resolveTextInputCapture(WiredStack stack, WiredEvent event) {
|
||||||
if (stack == null || event == null) {
|
if (stack == null || event == null) {
|
||||||
return WiredTextInputCaptureSupport.CaptureResult.noMatch();
|
return WiredTextInputCaptureSupport.CaptureResult.noMatch();
|
||||||
@@ -576,6 +782,48 @@ public final class WiredEngine {
|
|||||||
return evaluateConditionsByMode(conditions, ctx, stack.conditionEvaluationMode(), stack.conditionEvaluationValue());
|
return evaluateConditionsByMode(conditions, ctx, stack.conditionEvaluationMode(), stack.conditionEvaluationValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean shouldContinueAfterConditionCheck(WiredStack stack, Room room, boolean conditionsPassedForExecution, List<IWiredEffect> executableEffects, boolean hasSpecialOutcome) {
|
||||||
|
if (stack.hasConditions()) {
|
||||||
|
debug(room, "Evaluating {} conditions...", stack.conditions().size());
|
||||||
|
|
||||||
|
if (!conditionsPassedForExecution && !executableEffects.isEmpty()) {
|
||||||
|
debug(room, "Conditions failed, executing negative effects");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!conditionsPassedForExecution) {
|
||||||
|
debug(room, "Conditions failed, aborting stack");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hasSpecialOutcome || !executableEffects.isEmpty()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
debug(room, "Conditions passed, but no executable effects remain");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!conditionsPassedForExecution) {
|
||||||
|
debug(room, "No conditions in stack, negated execution aborted");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hasSpecialOutcome || !executableEffects.isEmpty()) {
|
||||||
|
debug(room, "No conditions in stack, proceeding to effects");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
debug(room, "No conditions in stack, but no executable effects remain");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean shouldConditionsPass(WiredStack stack, WiredContext ctx, boolean negateConditions) {
|
||||||
|
boolean conditionsPassed = evaluateConditions(stack, ctx);
|
||||||
|
debug(ctx.room(), "Conditions result: {}", conditionsPassed ? "PASSED" : "FAILED");
|
||||||
|
return negateConditions ? !conditionsPassed : conditionsPassed;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Evaluate conditions according to the configured stack mode.
|
* Evaluate conditions according to the configured stack mode.
|
||||||
*/
|
*/
|
||||||
@@ -638,65 +886,57 @@ public final class WiredEngine {
|
|||||||
/**
|
/**
|
||||||
* Execute effects in a stack.
|
* Execute effects in a stack.
|
||||||
*/
|
*/
|
||||||
private void executeEffects(WiredStack stack, WiredContext ctx, long currentTime) {
|
private void executeEffects(WiredStack stack, List<IWiredEffect> effects, WiredContext ctx, long currentTime) {
|
||||||
List<IWiredEffect> effects = stack.effects();
|
|
||||||
|
|
||||||
if (effects.isEmpty()) {
|
if (effects.isEmpty()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Selectors already executed before conditions; only run regular effects here
|
|
||||||
List<IWiredEffect> regulars = new ArrayList<>();
|
|
||||||
for (IWiredEffect e : effects) {
|
|
||||||
if (!e.isSelector()) regulars.add(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Determine which (regular) effects to execute
|
// Determine which (regular) effects to execute
|
||||||
List<IWiredEffect> toExecute;
|
List<IWiredEffect> toExecute;
|
||||||
|
|
||||||
if (stack.useRandom()) {
|
if (stack.useRandom()) {
|
||||||
WiredExtraRandom randomExtra = getRandomExtra(ctx.room(), stack);
|
WiredExtraRandom randomExtra = getRandomExtra(ctx.room(), stack);
|
||||||
if (regulars.isEmpty()) {
|
if (effects.isEmpty()) {
|
||||||
toExecute = new ArrayList<>();
|
toExecute = new ArrayList<>();
|
||||||
} else if (randomExtra != null) {
|
} else if (randomExtra != null) {
|
||||||
toExecute = randomExtra.selectWiredEffects(regulars);
|
toExecute = randomExtra.selectWiredEffects(effects);
|
||||||
debug(ctx.room(), "Random mode: selected {} effect(s), skip window {}", toExecute.size(), randomExtra.getSkipExecutions());
|
debug(ctx.room(), "Random mode: selected {} effect(s), skip window {}", toExecute.size(), randomExtra.getSkipExecutions());
|
||||||
} else {
|
} else {
|
||||||
int randomIndex = new Random().nextInt(regulars.size());
|
int randomIndex = new Random().nextInt(effects.size());
|
||||||
toExecute = Collections.singletonList(regulars.get(randomIndex));
|
toExecute = Collections.singletonList(effects.get(randomIndex));
|
||||||
debug(ctx.room(), "Random mode: selected effect {}/{}", randomIndex + 1, regulars.size());
|
debug(ctx.room(), "Random mode: selected effect {}/{}", randomIndex + 1, effects.size());
|
||||||
}
|
}
|
||||||
} else if (stack.useUnseen()) {
|
} else if (stack.useUnseen()) {
|
||||||
// Unseen mode: execute in stable order with memory
|
// Unseen mode: execute in stable order with memory
|
||||||
if (regulars.isEmpty()) {
|
if (effects.isEmpty()) {
|
||||||
toExecute = new ArrayList<>();
|
toExecute = new ArrayList<>();
|
||||||
} else {
|
} else {
|
||||||
WiredExtraUnseen unseenExtra = getUnseenExtra(ctx.room(), stack);
|
WiredExtraUnseen unseenExtra = getUnseenExtra(ctx.room(), stack);
|
||||||
|
|
||||||
if (unseenExtra != null) {
|
if (unseenExtra != null) {
|
||||||
toExecute = unseenExtra.selectWiredEffects(regulars);
|
toExecute = unseenExtra.selectWiredEffects(effects);
|
||||||
|
|
||||||
if (!toExecute.isEmpty()) {
|
if (!toExecute.isEmpty()) {
|
||||||
int selectedIndex = regulars.indexOf(toExecute.get(0));
|
int selectedIndex = effects.indexOf(toExecute.get(0));
|
||||||
debug(ctx.room(), "Unseen mode: selected effect {}/{}", selectedIndex + 1, regulars.size());
|
debug(ctx.room(), "Unseen mode: selected effect {}/{}", selectedIndex + 1, effects.size());
|
||||||
} else {
|
} else {
|
||||||
debug(ctx.room(), "Unseen mode: no eligible effect found");
|
debug(ctx.room(), "Unseen mode: no eligible effect found");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
int index = getNextUnseenIndex(stack, regulars.size());
|
int index = getNextUnseenIndex(stack, effects.size());
|
||||||
toExecute = Collections.singletonList(regulars.get(index));
|
toExecute = Collections.singletonList(effects.get(index));
|
||||||
debug(ctx.room(), "Unseen mode fallback: selected effect {}/{}", index + 1, regulars.size());
|
debug(ctx.room(), "Unseen mode fallback: selected effect {}/{}", index + 1, effects.size());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (stack.executeInOrder()) {
|
} else if (stack.executeInOrder()) {
|
||||||
debug(ctx.room(), "Ordered mode: executing effect batches in stack order by delay");
|
debug(ctx.room(), "Ordered mode: executing effect batches in stack order by delay");
|
||||||
executeOrderedEffects(regulars, ctx, currentTime);
|
executeOrderedEffects(effects, ctx, currentTime);
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
// Normal mode: preserve the physical stack order.
|
// Normal mode: preserve the physical stack order.
|
||||||
// This matches the legacy handler behavior and avoids visual/state races
|
// This matches the legacy handler behavior and avoids visual/state races
|
||||||
// for combinations such as Move/Rotate + Match To Snapshot in the same stack.
|
// for combinations such as Move/Rotate + Match To Snapshot in the same stack.
|
||||||
toExecute = new ArrayList<>(regulars);
|
toExecute = new ArrayList<>(effects);
|
||||||
}
|
}
|
||||||
|
|
||||||
WiredMoveCarryHelper.beginMovementCollection();
|
WiredMoveCarryHelper.beginMovementCollection();
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ import com.eu.habbo.habbohotel.users.HabboBadge;
|
|||||||
import com.eu.habbo.habbohotel.users.HabboItem;
|
import com.eu.habbo.habbohotel.users.HabboItem;
|
||||||
import com.eu.habbo.habbohotel.wired.WiredGiveRewardItem;
|
import com.eu.habbo.habbohotel.wired.WiredGiveRewardItem;
|
||||||
import com.eu.habbo.habbohotel.wired.WiredTriggerType;
|
import com.eu.habbo.habbohotel.wired.WiredTriggerType;
|
||||||
|
import com.eu.habbo.habbohotel.wired.api.WiredStack;
|
||||||
import com.eu.habbo.habbohotel.wired.migrate.WiredEvents;
|
import com.eu.habbo.habbohotel.wired.migrate.WiredEvents;
|
||||||
import com.eu.habbo.habbohotel.wired.tick.WiredTickService;
|
import com.eu.habbo.habbohotel.wired.tick.WiredTickService;
|
||||||
import com.eu.habbo.habbohotel.wired.tick.WiredTickable;
|
import com.eu.habbo.habbohotel.wired.tick.WiredTickable;
|
||||||
@@ -40,6 +41,10 @@ import java.sql.PreparedStatement;
|
|||||||
import java.sql.ResultSet;
|
import java.sql.ResultSet;
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
import java.util.ArrayDeque;
|
import java.util.ArrayDeque;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Manager class for the wired runtime.
|
* Manager class for the wired runtime.
|
||||||
@@ -95,7 +100,7 @@ public final class WiredManager {
|
|||||||
/** Whether the engine is initialized */
|
/** Whether the engine is initialized */
|
||||||
private static volatile boolean initialized = false;
|
private static volatile boolean initialized = false;
|
||||||
private static final ThreadLocal<Integer> EVENT_HANDLING_DEPTH = new ThreadLocal<>();
|
private static final ThreadLocal<Integer> EVENT_HANDLING_DEPTH = new ThreadLocal<>();
|
||||||
private static final ThreadLocal<ArrayDeque<WiredEvent>> DEFERRED_EFFECT_EVENTS = new ThreadLocal<>();
|
private static final ThreadLocal<ArrayDeque<DeferredEffectEvent>> DEFERRED_EFFECT_EVENTS = new ThreadLocal<>();
|
||||||
private WiredManager() {
|
private WiredManager() {
|
||||||
// Static utility class
|
// Static utility class
|
||||||
}
|
}
|
||||||
@@ -241,6 +246,10 @@ public final class WiredManager {
|
|||||||
* @return true if any stack was triggered
|
* @return true if any stack was triggered
|
||||||
*/
|
*/
|
||||||
public static boolean handleEvent(WiredEvent event) {
|
public static boolean handleEvent(WiredEvent event) {
|
||||||
|
return handleEvent(event, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean handleEvent(WiredEvent event, boolean negateConditions) {
|
||||||
if (!isEnabled() || engine == null) {
|
if (!isEnabled() || engine == null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -260,19 +269,19 @@ public final class WiredManager {
|
|||||||
boolean handled = false;
|
boolean handled = false;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
handled = engine.handleEvent(event);
|
handled = engine.handleEvent(event, negateConditions);
|
||||||
|
|
||||||
if (nextDepth == 1) {
|
if (nextDepth == 1) {
|
||||||
ArrayDeque<WiredEvent> deferredEvents = DEFERRED_EFFECT_EVENTS.get();
|
ArrayDeque<DeferredEffectEvent> deferredEvents = DEFERRED_EFFECT_EVENTS.get();
|
||||||
|
|
||||||
while (deferredEvents != null && !deferredEvents.isEmpty()) {
|
while (deferredEvents != null && !deferredEvents.isEmpty()) {
|
||||||
WiredEvent deferredEvent = deferredEvents.pollFirst();
|
DeferredEffectEvent deferredEvent = deferredEvents.pollFirst();
|
||||||
|
|
||||||
if (deferredEvent == null || RoomWiredDisableSupport.isWiredDisabled(deferredEvent.getRoom())) {
|
if (deferredEvent == null || deferredEvent.event == null || RoomWiredDisableSupport.isWiredDisabled(deferredEvent.event.getRoom())) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
handled = engine.handleEvent(deferredEvent) || handled;
|
handled = engine.handleEvent(deferredEvent.event, deferredEvent.negateConditions) || handled;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -288,6 +297,14 @@ public final class WiredManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static boolean dispatchEffectTriggeredEvent(WiredEvent event) {
|
public static boolean dispatchEffectTriggeredEvent(WiredEvent event) {
|
||||||
|
return dispatchEffectTriggeredEvent(event, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean dispatchNegatedEffectTriggeredEvent(WiredEvent event) {
|
||||||
|
return dispatchEffectTriggeredEvent(event, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean dispatchEffectTriggeredEvent(WiredEvent event, boolean negateConditions) {
|
||||||
if (!isEnabled() || engine == null || event == null || RoomWiredDisableSupport.isWiredDisabled(event.getRoom())) {
|
if (!isEnabled() || engine == null || event == null || RoomWiredDisableSupport.isWiredDisabled(event.getRoom())) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -295,17 +312,17 @@ public final class WiredManager {
|
|||||||
Integer currentDepth = EVENT_HANDLING_DEPTH.get();
|
Integer currentDepth = EVENT_HANDLING_DEPTH.get();
|
||||||
|
|
||||||
if (currentDepth == null || currentDepth <= 0) {
|
if (currentDepth == null || currentDepth <= 0) {
|
||||||
return handleEvent(event);
|
return handleEvent(event, negateConditions);
|
||||||
}
|
}
|
||||||
|
|
||||||
ArrayDeque<WiredEvent> deferredEvents = DEFERRED_EFFECT_EVENTS.get();
|
ArrayDeque<DeferredEffectEvent> deferredEvents = DEFERRED_EFFECT_EVENTS.get();
|
||||||
|
|
||||||
if (deferredEvents == null) {
|
if (deferredEvents == null) {
|
||||||
deferredEvents = new ArrayDeque<>();
|
deferredEvents = new ArrayDeque<>();
|
||||||
DEFERRED_EFFECT_EVENTS.set(deferredEvents);
|
DEFERRED_EFFECT_EVENTS.set(deferredEvents);
|
||||||
}
|
}
|
||||||
|
|
||||||
deferredEvents.addLast(event);
|
deferredEvents.addLast(new DeferredEffectEvent(event, negateConditions));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -971,6 +988,10 @@ public final class WiredManager {
|
|||||||
* @return true if any effects were executed
|
* @return true if any effects were executed
|
||||||
*/
|
*/
|
||||||
public static boolean executeEffectsAtTiles(THashSet<RoomTile> tiles, final RoomUnit roomUnit, final Room room, final int callStackDepth) {
|
public static boolean executeEffectsAtTiles(THashSet<RoomTile> tiles, final RoomUnit roomUnit, final Room room, final int callStackDepth) {
|
||||||
|
if (tiles == null || tiles.isEmpty() || room == null || engine == null || stackIndex == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
for (RoomTile tile : tiles) {
|
for (RoomTile tile : tiles) {
|
||||||
if (room != null) {
|
if (room != null) {
|
||||||
THashSet<HabboItem> items = room.getItemsAt(tile);
|
THashSet<HabboItem> items = room.getItemsAt(tile);
|
||||||
@@ -994,6 +1015,82 @@ public final class WiredManager {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static boolean executeNegatedStacksAtTiles(THashSet<RoomTile> tiles, final RoomUnit roomUnit, final Room room, final int callStackDepth) {
|
||||||
|
if (tiles == null || tiles.isEmpty() || room == null || engine == null || stackIndex == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean handled = false;
|
||||||
|
WiredEvent event = WiredEvent.builder(WiredEvent.Type.CUSTOM, room)
|
||||||
|
.actor(roomUnit)
|
||||||
|
.callStackDepth(callStackDepth)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
for (RoomTile tile : tiles) {
|
||||||
|
List<WiredStack> stacks = stackIndex.getStacksAtTile(room, tile);
|
||||||
|
if (stacks.isEmpty()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (WiredStack stack : stacks) {
|
||||||
|
handled = engine.executeDirectStack(stack, event, true) || handled;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return handled;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean executeNegatedTargetStacks(Iterable<HabboItem> triggerItems, final RoomUnit roomUnit, final Room room, final int callStackDepth) {
|
||||||
|
if (triggerItems == null || room == null || engine == null || stackIndex == null || room.getLayout() == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean handled = false;
|
||||||
|
Set<Integer> seenTriggerIds = new HashSet<>();
|
||||||
|
WiredEvent event = WiredEvent.builder(WiredEvent.Type.CUSTOM, room)
|
||||||
|
.actor(roomUnit)
|
||||||
|
.callStackDepth(callStackDepth)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
for (HabboItem triggerItem : triggerItems) {
|
||||||
|
if (triggerItem == null || !seenTriggerIds.add(triggerItem.getId())) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
RoomTile tile = room.getLayout().getTile(triggerItem.getX(), triggerItem.getY());
|
||||||
|
if (tile == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
List<WiredStack> stacks = stackIndex.getStacksAtTile(room, tile);
|
||||||
|
if (stacks.isEmpty()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (WiredStack stack : stacks) {
|
||||||
|
HabboItem stackTriggerItem = stack.triggerItem();
|
||||||
|
if (stackTriggerItem == null || stackTriggerItem.getId() != triggerItem.getId()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
handled = engine.executeDirectStack(stack, event, true) || handled;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return handled;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final class DeferredEffectEvent {
|
||||||
|
private final WiredEvent event;
|
||||||
|
private final boolean negateConditions;
|
||||||
|
|
||||||
|
private DeferredEffectEvent(WiredEvent event, boolean negateConditions) {
|
||||||
|
this.event = event;
|
||||||
|
this.negateConditions = negateConditions;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// ========== Reward System ==========
|
// ========== Reward System ==========
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -981,7 +981,7 @@ public final class WiredMoveCarryHelper {
|
|||||||
return new ArrayList<>();
|
return new ArrayList<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
return WiredSourceUtil.resolveItems(ctx, sourceType, null);
|
return WiredSourceUtil.resolveItemsRaw(ctx, sourceType, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Collection<RoomUnit> resolvePhysicsUsers(Room room, WiredContext ctx, int userSource) {
|
private static Collection<RoomUnit> resolvePhysicsUsers(Room room, WiredContext ctx, int userSource) {
|
||||||
@@ -997,7 +997,7 @@ public final class WiredMoveCarryHelper {
|
|||||||
return new ArrayList<>();
|
return new ArrayList<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
return WiredSourceUtil.resolveUsers(ctx, userSource);
|
return WiredSourceUtil.resolveUsersRaw(ctx, userSource);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static WiredExtraMovePhysics getMovementPhysicsExtra(Room room, HabboItem stackItem) {
|
private static WiredExtraMovePhysics getMovementPhysicsExtra(Room room, HabboItem stackItem) {
|
||||||
|
|||||||
@@ -29,31 +29,10 @@ public final class WiredSourceUtil {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static List<HabboItem> resolveItems(WiredContext ctx, int sourceType, Collection<HabboItem> selectedItems) {
|
public static List<HabboItem> resolveItems(WiredContext ctx, int sourceType, Collection<HabboItem> selectedItems) {
|
||||||
List<HabboItem> resolvedItems;
|
List<HabboItem> resolvedItems = resolveItemsInternal(ctx, sourceType, selectedItems, false);
|
||||||
|
|
||||||
switch (sourceType) {
|
if (ctx == null) {
|
||||||
case SOURCE_TRIGGER:
|
return resolvedItems;
|
||||||
resolvedItems = ctx.sourceItem().map(Collections::singletonList).orElse(Collections.emptyList());
|
|
||||||
break;
|
|
||||||
case SOURCE_SELECTED:
|
|
||||||
resolvedItems = (selectedItems != null) ? new ArrayList<>(selectedItems) : Collections.emptyList();
|
|
||||||
break;
|
|
||||||
case SOURCE_SELECTOR:
|
|
||||||
WiredTargets itemTargets = getSelectorTargets(ctx);
|
|
||||||
resolvedItems = itemTargets.isItemsModifiedBySelector()
|
|
||||||
? new ArrayList<>(itemTargets.items())
|
|
||||||
: Collections.emptyList();
|
|
||||||
break;
|
|
||||||
case SOURCE_SIGNAL:
|
|
||||||
if (ctx.eventType() == WiredEvent.Type.SIGNAL_RECEIVED) {
|
|
||||||
resolvedItems = ctx.sourceItem().map(Collections::singletonList).orElse(Collections.emptyList());
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
resolvedItems = Collections.emptyList();
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
resolvedItems = ctx.sourceItem().map(Collections::singletonList).orElse(Collections.emptyList());
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return (sourceType == SOURCE_SELECTOR)
|
return (sourceType == SOURCE_SELECTOR)
|
||||||
@@ -61,43 +40,19 @@ public final class WiredSourceUtil {
|
|||||||
: WiredSelectionFilterSupport.filterItems(ctx.room(), ctx.triggerItem(), ctx, resolvedItems);
|
: WiredSelectionFilterSupport.filterItems(ctx.room(), ctx.triggerItem(), ctx, resolvedItems);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static List<HabboItem> resolveItemsRaw(WiredContext ctx, int sourceType, Collection<HabboItem> selectedItems) {
|
||||||
|
return resolveItemsInternal(ctx, sourceType, selectedItems, true);
|
||||||
|
}
|
||||||
|
|
||||||
public static List<RoomUnit> resolveUsers(WiredContext ctx, int sourceType) {
|
public static List<RoomUnit> resolveUsers(WiredContext ctx, int sourceType) {
|
||||||
return resolveUsers(ctx, sourceType, null);
|
return resolveUsers(ctx, sourceType, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static List<RoomUnit> resolveUsers(WiredContext ctx, int sourceType, Collection<RoomUnit> selectedUsers) {
|
public static List<RoomUnit> resolveUsers(WiredContext ctx, int sourceType, Collection<RoomUnit> selectedUsers) {
|
||||||
List<RoomUnit> resolvedUsers;
|
List<RoomUnit> resolvedUsers = resolveUsersInternal(ctx, sourceType, selectedUsers);
|
||||||
|
|
||||||
switch (sourceType) {
|
if (ctx == null) {
|
||||||
case SOURCE_TRIGGER:
|
return resolvedUsers;
|
||||||
resolvedUsers = ctx.actor().map(Collections::singletonList).orElse(Collections.emptyList());
|
|
||||||
break;
|
|
||||||
case SOURCE_CLICKED_USER:
|
|
||||||
if (ctx.eventType() == WiredEvent.Type.USER_CLICKS_USER) {
|
|
||||||
resolvedUsers = ctx.event().getTargetUnit().map(Collections::singletonList).orElse(Collections.emptyList());
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
resolvedUsers = Collections.emptyList();
|
|
||||||
break;
|
|
||||||
case SOURCE_SELECTED:
|
|
||||||
resolvedUsers = (selectedUsers != null) ? new ArrayList<>(selectedUsers) : Collections.emptyList();
|
|
||||||
break;
|
|
||||||
case SOURCE_SELECTOR:
|
|
||||||
WiredTargets userTargets = getSelectorTargets(ctx);
|
|
||||||
resolvedUsers = userTargets.isUsersModifiedBySelector()
|
|
||||||
? new ArrayList<>(userTargets.users())
|
|
||||||
: Collections.emptyList();
|
|
||||||
break;
|
|
||||||
case SOURCE_SIGNAL:
|
|
||||||
if (ctx.eventType() == WiredEvent.Type.SIGNAL_RECEIVED) {
|
|
||||||
resolvedUsers = ctx.actor().map(Collections::singletonList).orElse(Collections.emptyList());
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
resolvedUsers = Collections.emptyList();
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
resolvedUsers = ctx.actor().map(Collections::singletonList).orElse(Collections.emptyList());
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return (sourceType == SOURCE_SELECTOR)
|
return (sourceType == SOURCE_SELECTOR)
|
||||||
@@ -105,6 +60,14 @@ public final class WiredSourceUtil {
|
|||||||
: WiredSelectionFilterSupport.filterUsers(ctx.room(), ctx.triggerItem(), ctx, resolvedUsers);
|
: WiredSelectionFilterSupport.filterUsers(ctx.room(), ctx.triggerItem(), ctx, resolvedUsers);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static List<RoomUnit> resolveUsersRaw(WiredContext ctx, int sourceType) {
|
||||||
|
return resolveUsersRaw(ctx, sourceType, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<RoomUnit> resolveUsersRaw(WiredContext ctx, int sourceType, Collection<RoomUnit> selectedUsers) {
|
||||||
|
return resolveUsersInternal(ctx, sourceType, selectedUsers);
|
||||||
|
}
|
||||||
|
|
||||||
public static boolean isDefaultUserSource(int value) {
|
public static boolean isDefaultUserSource(int value) {
|
||||||
switch (value) {
|
switch (value) {
|
||||||
case SOURCE_TRIGGER:
|
case SOURCE_TRIGGER:
|
||||||
@@ -251,4 +214,75 @@ public final class WiredSourceUtil {
|
|||||||
private static void applySelectionFilterExtras(Room room, HabboItem triggerItem, WiredContext selectorCtx) {
|
private static void applySelectionFilterExtras(Room room, HabboItem triggerItem, WiredContext selectorCtx) {
|
||||||
WiredSelectionFilterSupport.applySelectorFilters(room, triggerItem, selectorCtx);
|
WiredSelectionFilterSupport.applySelectorFilters(room, triggerItem, selectorCtx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static List<HabboItem> resolveItemsInternal(WiredContext ctx, int sourceType, Collection<HabboItem> selectedItems, boolean allowTriggerItemFallback) {
|
||||||
|
if (ctx == null) {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (sourceType) {
|
||||||
|
case SOURCE_TRIGGER:
|
||||||
|
return resolveTriggerItems(ctx, allowTriggerItemFallback);
|
||||||
|
case SOURCE_SELECTED:
|
||||||
|
return (selectedItems != null) ? new ArrayList<>(selectedItems) : Collections.emptyList();
|
||||||
|
case SOURCE_SELECTOR:
|
||||||
|
WiredTargets itemTargets = getSelectorTargets(ctx);
|
||||||
|
return itemTargets.isItemsModifiedBySelector()
|
||||||
|
? new ArrayList<>(itemTargets.items())
|
||||||
|
: Collections.emptyList();
|
||||||
|
case SOURCE_SIGNAL:
|
||||||
|
if (ctx.eventType() == WiredEvent.Type.SIGNAL_RECEIVED) {
|
||||||
|
return ctx.sourceItem().map(Collections::singletonList).orElse(Collections.emptyList());
|
||||||
|
}
|
||||||
|
return Collections.emptyList();
|
||||||
|
default:
|
||||||
|
return resolveTriggerItems(ctx, allowTriggerItemFallback);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static List<RoomUnit> resolveUsersInternal(WiredContext ctx, int sourceType, Collection<RoomUnit> selectedUsers) {
|
||||||
|
if (ctx == null) {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (sourceType) {
|
||||||
|
case SOURCE_TRIGGER:
|
||||||
|
return ctx.actor().map(Collections::singletonList).orElse(Collections.emptyList());
|
||||||
|
case SOURCE_CLICKED_USER:
|
||||||
|
if (ctx.eventType() == WiredEvent.Type.USER_CLICKS_USER) {
|
||||||
|
return ctx.event().getTargetUnit().map(Collections::singletonList).orElse(Collections.emptyList());
|
||||||
|
}
|
||||||
|
return Collections.emptyList();
|
||||||
|
case SOURCE_SELECTED:
|
||||||
|
return (selectedUsers != null) ? new ArrayList<>(selectedUsers) : Collections.emptyList();
|
||||||
|
case SOURCE_SELECTOR:
|
||||||
|
WiredTargets userTargets = getSelectorTargets(ctx);
|
||||||
|
return userTargets.isUsersModifiedBySelector()
|
||||||
|
? new ArrayList<>(userTargets.users())
|
||||||
|
: Collections.emptyList();
|
||||||
|
case SOURCE_SIGNAL:
|
||||||
|
if (ctx.eventType() == WiredEvent.Type.SIGNAL_RECEIVED) {
|
||||||
|
return ctx.actor().map(Collections::singletonList).orElse(Collections.emptyList());
|
||||||
|
}
|
||||||
|
return Collections.emptyList();
|
||||||
|
default:
|
||||||
|
return ctx.actor().map(Collections::singletonList).orElse(Collections.emptyList());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static List<HabboItem> resolveTriggerItems(WiredContext ctx, boolean allowTriggerItemFallback) {
|
||||||
|
if (ctx == null) {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ctx.sourceItem().isPresent()) {
|
||||||
|
return Collections.singletonList(ctx.sourceItem().get());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (allowTriggerItemFallback && ctx.triggerItem() != null) {
|
||||||
|
return Collections.singletonList(ctx.triggerItem());
|
||||||
|
}
|
||||||
|
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+49
-10
@@ -5,6 +5,11 @@ import com.eu.habbo.habbohotel.items.interactions.wired.extra.WiredExtraVariable
|
|||||||
import com.eu.habbo.habbohotel.rooms.Room;
|
import com.eu.habbo.habbohotel.rooms.Room;
|
||||||
import gnu.trove.set.hash.THashSet;
|
import gnu.trove.set.hash.THashSet;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
public final class WiredVariableTextConnectorSupport {
|
public final class WiredVariableTextConnectorSupport {
|
||||||
private WiredVariableTextConnectorSupport() {
|
private WiredVariableTextConnectorSupport() {
|
||||||
}
|
}
|
||||||
@@ -18,31 +23,43 @@ public final class WiredVariableTextConnectorSupport {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static WiredExtraVariableTextConnector getConnector(Room room, int definitionItemId) {
|
public static WiredExtraVariableTextConnector getConnector(Room room, int definitionItemId) {
|
||||||
|
List<WiredExtraVariableTextConnector> connectors = getConnectors(room, definitionItemId);
|
||||||
|
return connectors.isEmpty() ? null : connectors.get(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<WiredExtraVariableTextConnector> getConnectors(Room room, int definitionItemId) {
|
||||||
if (room == null || room.getRoomSpecialTypes() == null || definitionItemId <= 0) {
|
if (room == null || room.getRoomSpecialTypes() == null || definitionItemId <= 0) {
|
||||||
return null;
|
return Collections.emptyList();
|
||||||
}
|
}
|
||||||
|
|
||||||
InteractionWiredExtra extra = room.getRoomSpecialTypes().getExtra(definitionItemId);
|
InteractionWiredExtra extra = room.getRoomSpecialTypes().getExtra(definitionItemId);
|
||||||
return getConnector(room, extra);
|
return getConnectors(room, extra);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static WiredExtraVariableTextConnector getConnector(Room room, InteractionWiredExtra definition) {
|
public static WiredExtraVariableTextConnector getConnector(Room room, InteractionWiredExtra definition) {
|
||||||
|
List<WiredExtraVariableTextConnector> connectors = getConnectors(room, definition);
|
||||||
|
return connectors.isEmpty() ? null : connectors.get(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<WiredExtraVariableTextConnector> getConnectors(Room room, InteractionWiredExtra definition) {
|
||||||
if (room == null || definition == null || room.getRoomSpecialTypes() == null) {
|
if (room == null || definition == null || room.getRoomSpecialTypes() == null) {
|
||||||
return null;
|
return Collections.emptyList();
|
||||||
}
|
}
|
||||||
|
|
||||||
THashSet<InteractionWiredExtra> extras = room.getRoomSpecialTypes().getExtras(definition.getX(), definition.getY());
|
THashSet<InteractionWiredExtra> extras = room.getRoomSpecialTypes().getExtras(definition.getX(), definition.getY());
|
||||||
if (extras == null || extras.isEmpty()) {
|
if (extras == null || extras.isEmpty()) {
|
||||||
return null;
|
return Collections.emptyList();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
List<WiredExtraVariableTextConnector> connectors = new ArrayList<>();
|
||||||
|
|
||||||
for (InteractionWiredExtra extra : WiredExecutionOrderUtil.sort(extras)) {
|
for (InteractionWiredExtra extra : WiredExecutionOrderUtil.sort(extras)) {
|
||||||
if (extra instanceof WiredExtraVariableTextConnector) {
|
if (extra instanceof WiredExtraVariableTextConnector) {
|
||||||
return (WiredExtraVariableTextConnector) extra;
|
connectors.add((WiredExtraVariableTextConnector) extra);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return connectors;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String toText(Room room, int definitionItemId, Integer value) {
|
public static String toText(Room room, int definitionItemId, Integer value) {
|
||||||
@@ -50,12 +67,34 @@ public final class WiredVariableTextConnectorSupport {
|
|||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
WiredExtraVariableTextConnector connector = getConnector(room, definitionItemId);
|
for (WiredExtraVariableTextConnector connector : getConnectors(room, definitionItemId)) {
|
||||||
return connector != null ? connector.resolveText(value) : String.valueOf(value);
|
Map<Integer, String> mappings = connector.getMappings();
|
||||||
|
if (mappings.containsKey(value)) {
|
||||||
|
String mappedValue = mappings.get(value);
|
||||||
|
return mappedValue != null ? mappedValue : String.valueOf(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return String.valueOf(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Integer toValue(Room room, int definitionItemId, String text) {
|
public static Integer toValue(Room room, int definitionItemId, String text) {
|
||||||
WiredExtraVariableTextConnector connector = getConnector(room, definitionItemId);
|
if (text == null) {
|
||||||
return connector != null ? connector.resolveValue(text) : null;
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
String normalizedText = text.trim();
|
||||||
|
if (normalizedText.isEmpty()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (WiredExtraVariableTextConnector connector : getConnectors(room, definitionItemId)) {
|
||||||
|
Integer mappedValue = connector.resolveValue(normalizedText);
|
||||||
|
if (mappedValue != null) {
|
||||||
|
return mappedValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user