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
feat(wired): add antenna signals and selector-aware snapshots
This commit is contained in:
@@ -201,6 +201,7 @@ public class ItemManager {
|
||||
this.interactionsList.add(new ItemInteraction("random_state", InteractionRandomState.class));
|
||||
this.interactionsList.add(new ItemInteraction("vendingmachine_no_sides", InteractionNoSidesVendingMachine.class));
|
||||
this.interactionsList.add(new ItemInteraction("tile_walkmagic", InteractionTileWalkMagic.class));
|
||||
this.interactionsList.add(new ItemInteraction("antenna", InteractionDefault.class));
|
||||
|
||||
this.interactionsList.add(new ItemInteraction("game_timer", InteractionGameTimer.class));
|
||||
|
||||
|
||||
+56
-57
@@ -19,9 +19,7 @@ import gnu.trove.set.hash.THashSet;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
public class WiredConditionMatchStatePosition extends InteractionWiredCondition implements InteractionWiredMatchFurniSettings {
|
||||
public static final WiredConditionType type = WiredConditionType.MATCH_SSHOT;
|
||||
@@ -92,14 +90,12 @@ public class WiredConditionMatchStatePosition extends InteractionWiredCondition
|
||||
|
||||
this.settings.clear();
|
||||
|
||||
if (this.furniSource == WiredSourceUtil.SOURCE_SELECTED) {
|
||||
for (int i = 0; i < count; i++) {
|
||||
int itemId = settings.getFurniIds()[i];
|
||||
HabboItem item = room.getHabboItem(itemId);
|
||||
for (int i = 0; i < count; i++) {
|
||||
int itemId = settings.getFurniIds()[i];
|
||||
HabboItem item = room.getHabboItem(itemId);
|
||||
|
||||
if (item != null)
|
||||
this.settings.add(new WiredMatchFurniSetting(item.getId(), item.getExtradata(), item.getRotation(), item.getX(), item.getY()));
|
||||
}
|
||||
if (item != null)
|
||||
this.settings.add(new WiredMatchFurniSetting(item.getId(), item.getExtradata(), item.getRotation(), item.getX(), item.getY()));
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -108,65 +104,71 @@ public class WiredConditionMatchStatePosition extends InteractionWiredCondition
|
||||
@Override
|
||||
public boolean evaluate(WiredContext ctx) {
|
||||
Room room = ctx.room();
|
||||
this.refresh();
|
||||
|
||||
if (this.settings.isEmpty())
|
||||
return true;
|
||||
|
||||
List<HabboItem> targets = null;
|
||||
Set<Integer> targetIds = null;
|
||||
|
||||
if (this.furniSource != WiredSourceUtil.SOURCE_SELECTED) {
|
||||
targets = WiredSourceUtil.resolveItems(ctx, this.furniSource, null);
|
||||
List<HabboItem> targets = WiredSourceUtil.resolveItems(ctx, this.furniSource, null);
|
||||
if (targets.isEmpty()) return false;
|
||||
targetIds = new HashSet<>();
|
||||
for (HabboItem item : targets) {
|
||||
if (item != null) targetIds.add(item.getId());
|
||||
}
|
||||
if (targetIds.isEmpty()) return false;
|
||||
}
|
||||
|
||||
THashSet<WiredMatchFurniSetting> toRemove = new THashSet<>();
|
||||
Set<Integer> settingsIds = new HashSet<>();
|
||||
for (HabboItem item : targets) {
|
||||
if (item == null) return false;
|
||||
|
||||
WiredMatchFurniSetting setting = this.resolveSettingForTarget(room, item);
|
||||
if (setting == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!this.matchesSetting(item, setting)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
for (WiredMatchFurniSetting setting : this.settings) {
|
||||
if (targetIds != null && !targetIds.contains(setting.item_id)) {
|
||||
continue;
|
||||
}
|
||||
HabboItem item = room.getHabboItem(setting.item_id);
|
||||
|
||||
if (item != null) {
|
||||
settingsIds.add(setting.item_id);
|
||||
if (this.state) {
|
||||
if (!item.getExtradata().equals(setting.state))
|
||||
return false;
|
||||
}
|
||||
|
||||
if (this.position) {
|
||||
if (!(setting.x == item.getX() && setting.y == item.getY()))
|
||||
return false;
|
||||
}
|
||||
|
||||
if (this.direction) {
|
||||
if (setting.rotation != item.getRotation())
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
toRemove.add(setting);
|
||||
}
|
||||
}
|
||||
|
||||
if (targetIds != null && !settingsIds.containsAll(targetIds)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!toRemove.isEmpty()) {
|
||||
for (WiredMatchFurniSetting setting : toRemove) {
|
||||
this.settings.remove(setting);
|
||||
}
|
||||
if (item == null) continue;
|
||||
if (!this.matchesSetting(item, setting))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private WiredMatchFurniSetting resolveSettingForTarget(Room room, HabboItem target) {
|
||||
WiredMatchFurniSetting fallback = null;
|
||||
|
||||
for (WiredMatchFurniSetting setting : this.settings) {
|
||||
HabboItem sourceItem = room.getHabboItem(setting.item_id);
|
||||
if (sourceItem == null) continue;
|
||||
if (sourceItem.getBaseItem().getId() != target.getBaseItem().getId()) continue;
|
||||
|
||||
if (setting.state.equals(target.getExtradata())) {
|
||||
return setting;
|
||||
}
|
||||
|
||||
if (fallback == null) {
|
||||
fallback = setting;
|
||||
}
|
||||
}
|
||||
|
||||
return fallback;
|
||||
}
|
||||
|
||||
private boolean matchesSetting(HabboItem item, WiredMatchFurniSetting setting) {
|
||||
if (this.state && !item.getExtradata().equals(setting.state))
|
||||
return false;
|
||||
|
||||
if (this.position && !(setting.x == item.getX() && setting.y == item.getY()))
|
||||
return false;
|
||||
|
||||
return !this.direction || setting.rotation == item.getRotation();
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
@Override
|
||||
public boolean execute(RoomUnit roomUnit, Room room, Object[] stuff) {
|
||||
@@ -214,9 +216,6 @@ public class WiredConditionMatchStatePosition extends InteractionWiredCondition
|
||||
this.position = data[4].equals("1");
|
||||
this.furniSource = this.settings.isEmpty() ? WiredSourceUtil.SOURCE_TRIGGER : WiredSourceUtil.SOURCE_SELECTED;
|
||||
}
|
||||
if (this.furniSource == WiredSourceUtil.SOURCE_TRIGGER && !this.settings.isEmpty()) {
|
||||
this.furniSource = WiredSourceUtil.SOURCE_SELECTED;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+80
-59
@@ -50,6 +50,7 @@ public class WiredEffectMatchFurni extends InteractionWiredEffect implements Int
|
||||
@Override
|
||||
public void execute(WiredContext ctx) {
|
||||
Room room = ctx.room();
|
||||
this.refresh();
|
||||
|
||||
if(this.settings.isEmpty())
|
||||
return;
|
||||
@@ -57,54 +58,80 @@ public class WiredEffectMatchFurni extends InteractionWiredEffect implements Int
|
||||
if (room.getLayout() == null)
|
||||
return;
|
||||
|
||||
java.util.Set<Integer> allowedItemIds = null;
|
||||
if (this.furniSource != WiredSourceUtil.SOURCE_SELECTED) {
|
||||
allowedItemIds = new java.util.HashSet<>();
|
||||
for (HabboItem si : WiredSourceUtil.resolveItems(ctx, this.furniSource, null)) {
|
||||
if (si != null) {
|
||||
allowedItemIds.add(si.getId());
|
||||
if (this.furniSource == WiredSourceUtil.SOURCE_SELECTED) {
|
||||
for (WiredMatchFurniSetting setting : this.settings) {
|
||||
HabboItem item = room.getHabboItem(setting.item_id);
|
||||
if (item != null) {
|
||||
this.applySetting(room, item, setting);
|
||||
}
|
||||
}
|
||||
if (allowedItemIds.isEmpty()) {
|
||||
return;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
List<HabboItem> targets = WiredSourceUtil.resolveItems(ctx, this.furniSource, null);
|
||||
if (targets.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (HabboItem item : targets) {
|
||||
if (item == null) continue;
|
||||
|
||||
WiredMatchFurniSetting setting = this.resolveSettingForTarget(room, item);
|
||||
if (setting == null) continue;
|
||||
|
||||
this.applySetting(room, item, setting);
|
||||
}
|
||||
}
|
||||
|
||||
private WiredMatchFurniSetting resolveSettingForTarget(Room room, HabboItem target) {
|
||||
WiredMatchFurniSetting fallback = null;
|
||||
|
||||
for (WiredMatchFurniSetting setting : this.settings) {
|
||||
HabboItem sourceItem = room.getHabboItem(setting.item_id);
|
||||
if (sourceItem == null) continue;
|
||||
if (sourceItem.getBaseItem().getId() != target.getBaseItem().getId()) continue;
|
||||
|
||||
if (setting.state.equals(target.getExtradata())) {
|
||||
return setting;
|
||||
}
|
||||
|
||||
if (fallback == null) {
|
||||
fallback = setting;
|
||||
}
|
||||
}
|
||||
|
||||
for (WiredMatchFurniSetting setting : this.settings) {
|
||||
if (allowedItemIds != null && !allowedItemIds.contains(setting.item_id)) continue;
|
||||
return fallback;
|
||||
}
|
||||
|
||||
HabboItem item = room.getHabboItem(setting.item_id);
|
||||
if (item != null) {
|
||||
if (this.state && (this.checkForWiredResetPermission && item.allowWiredResetState())) {
|
||||
if (!setting.state.equals(" ") && !item.getExtradata().equals(setting.state)) {
|
||||
item.setExtradata(setting.state);
|
||||
room.updateItemState(item);
|
||||
private void applySetting(Room room, HabboItem item, WiredMatchFurniSetting setting) {
|
||||
if (this.state && (this.checkForWiredResetPermission && item.allowWiredResetState())) {
|
||||
if (!setting.state.equals(" ") && !item.getExtradata().equals(setting.state)) {
|
||||
item.setExtradata(setting.state);
|
||||
room.updateItemState(item);
|
||||
}
|
||||
}
|
||||
|
||||
RoomTile oldLocation = room.getLayout().getTile(item.getX(), item.getY());
|
||||
if (oldLocation == null) return;
|
||||
double oldZ = item.getZ();
|
||||
|
||||
if(this.direction && !this.position) {
|
||||
if(item.getRotation() != setting.rotation && room.furnitureFitsAt(oldLocation, item, setting.rotation, false) == FurnitureMovementError.NONE) {
|
||||
room.moveFurniTo(item, oldLocation, setting.rotation, null, true);
|
||||
}
|
||||
}
|
||||
else if(this.position) {
|
||||
boolean slideAnimation = !this.direction || item.getRotation() == setting.rotation;
|
||||
RoomTile newLocation = room.getLayout().getTile((short) setting.x, (short) setting.y);
|
||||
int newRotation = this.direction ? setting.rotation : item.getRotation();
|
||||
|
||||
if(newLocation != null && newLocation.state != RoomTileState.INVALID && (newLocation != oldLocation || newRotation != item.getRotation()) && room.furnitureFitsAt(newLocation, item, newRotation, true) == FurnitureMovementError.NONE) {
|
||||
if(room.moveFurniTo(item, newLocation, newRotation, null, !slideAnimation) == FurnitureMovementError.NONE) {
|
||||
if(slideAnimation) {
|
||||
room.sendComposer(new FloorItemOnRollerComposer(item, null, oldLocation, oldZ, newLocation, item.getZ(), 0, room).compose());
|
||||
}
|
||||
}
|
||||
|
||||
RoomTile oldLocation = room.getLayout().getTile(item.getX(), item.getY());
|
||||
if (oldLocation == null) continue;
|
||||
double oldZ = item.getZ();
|
||||
|
||||
if(this.direction && !this.position) {
|
||||
if(item.getRotation() != setting.rotation && room.furnitureFitsAt(oldLocation, item, setting.rotation, false) == FurnitureMovementError.NONE) {
|
||||
room.moveFurniTo(item, oldLocation, setting.rotation, null, true);
|
||||
}
|
||||
}
|
||||
else if(this.position) {
|
||||
boolean slideAnimation = !this.direction || item.getRotation() == setting.rotation;
|
||||
RoomTile newLocation = room.getLayout().getTile((short) setting.x, (short) setting.y);
|
||||
int newRotation = this.direction ? setting.rotation : item.getRotation();
|
||||
|
||||
if(newLocation != null && newLocation.state != RoomTileState.INVALID && (newLocation != oldLocation || newRotation != item.getRotation()) && room.furnitureFitsAt(newLocation, item, newRotation, true) == FurnitureMovementError.NONE) {
|
||||
if(room.moveFurniTo(item, newLocation, newRotation, null, !slideAnimation) == FurnitureMovementError.NONE) {
|
||||
if(slideAnimation) {
|
||||
room.sendComposer(new FloorItemOnRollerComposer(item, null, oldLocation, oldZ, newLocation, item.getZ(), 0, room).compose());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -134,9 +161,6 @@ public class WiredEffectMatchFurni extends InteractionWiredEffect implements Int
|
||||
this.settings.clear();
|
||||
this.settings.addAll(data.items);
|
||||
this.furniSource = data.furniSource;
|
||||
if (this.furniSource == WiredSourceUtil.SOURCE_TRIGGER && !this.settings.isEmpty()) {
|
||||
this.furniSource = WiredSourceUtil.SOURCE_SELECTED;
|
||||
}
|
||||
}
|
||||
else {
|
||||
String[] data = set.getString("wired_data").split(":");
|
||||
@@ -221,23 +245,22 @@ public class WiredEffectMatchFurni extends InteractionWiredEffect implements Int
|
||||
if (room == null)
|
||||
throw new WiredSaveException("Trying to save wired in unloaded room");
|
||||
|
||||
int itemsCount = settings.getFurniIds().length;
|
||||
|
||||
if(itemsCount > Emulator.getConfig().getInt("hotel.wired.furni.selection.count")) {
|
||||
throw new WiredSaveException("Too many furni selected");
|
||||
}
|
||||
|
||||
List<WiredMatchFurniSetting> newSettings = new ArrayList<>();
|
||||
if (this.furniSource == WiredSourceUtil.SOURCE_SELECTED) {
|
||||
int itemsCount = settings.getFurniIds().length;
|
||||
|
||||
if(itemsCount > Emulator.getConfig().getInt("hotel.wired.furni.selection.count")) {
|
||||
throw new WiredSaveException("Too many furni selected");
|
||||
}
|
||||
for (int i = 0; i < itemsCount; i++) {
|
||||
int itemId = settings.getFurniIds()[i];
|
||||
HabboItem it = room.getHabboItem(itemId);
|
||||
|
||||
for (int i = 0; i < itemsCount; i++) {
|
||||
int itemId = settings.getFurniIds()[i];
|
||||
HabboItem it = room.getHabboItem(itemId);
|
||||
if(it == null)
|
||||
throw new WiredSaveException(String.format("Item %s not found", itemId));
|
||||
|
||||
if(it == null)
|
||||
throw new WiredSaveException(String.format("Item %s not found", itemId));
|
||||
|
||||
newSettings.add(new WiredMatchFurniSetting(it.getId(), this.checkForWiredResetPermission && it.allowWiredResetState() ? it.getExtradata() : " ", it.getRotation(), it.getX(), it.getY()));
|
||||
}
|
||||
newSettings.add(new WiredMatchFurniSetting(it.getId(), this.checkForWiredResetPermission && it.allowWiredResetState() ? it.getExtradata() : " ", it.getRotation(), it.getX(), it.getY()));
|
||||
}
|
||||
|
||||
int delay = settings.getDelay();
|
||||
@@ -249,9 +272,7 @@ public class WiredEffectMatchFurni extends InteractionWiredEffect implements Int
|
||||
this.direction = setDirection;
|
||||
this.position = setPosition;
|
||||
this.settings.clear();
|
||||
if (this.furniSource == WiredSourceUtil.SOURCE_SELECTED) {
|
||||
this.settings.addAll(newSettings);
|
||||
}
|
||||
this.settings.addAll(newSettings);
|
||||
this.setDelay(delay);
|
||||
|
||||
return true;
|
||||
|
||||
+192
-63
@@ -24,6 +24,7 @@ import org.slf4j.LoggerFactory;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
|
||||
@@ -36,14 +37,16 @@ public class WiredEffectSendSignal extends InteractionWiredEffect {
|
||||
|
||||
private static final int ANTENNA_PICKED = 0;
|
||||
private static final int ANTENNA_TRIGGER = 1;
|
||||
|
||||
private static final int FORWARD_NONE = 0;
|
||||
private static final int FORWARD_TRIGGER = 1;
|
||||
private static final String ANTENNA_INTERACTION = "antenna";
|
||||
private static final String FORWARD_ITEM_SPLIT_REGEX = "[;,\\t]";
|
||||
private static final long ANTENNA_PULSE_MS = 300L;
|
||||
private static final ConcurrentHashMap<Integer, Long> ANTENNA_PULSE_TOKENS = new ConcurrentHashMap<>();
|
||||
|
||||
private THashSet<HabboItem> items;
|
||||
private THashSet<HabboItem> forwardItems;
|
||||
private int antennaSource = ANTENNA_PICKED;
|
||||
private int furniForward = FORWARD_NONE;
|
||||
private int userForward = FORWARD_NONE;
|
||||
private int furniForward = WiredSourceUtil.SOURCE_TRIGGER;
|
||||
private int userForward = WiredSourceUtil.SOURCE_TRIGGER;
|
||||
private boolean signalPerFurni = false;
|
||||
private boolean signalPerUser = false;
|
||||
private int channel = 0;
|
||||
@@ -51,11 +54,13 @@ public class WiredEffectSendSignal extends InteractionWiredEffect {
|
||||
public WiredEffectSendSignal(ResultSet set, Item baseItem) throws SQLException {
|
||||
super(set, baseItem);
|
||||
this.items = new THashSet<>();
|
||||
this.forwardItems = new THashSet<>();
|
||||
}
|
||||
|
||||
public WiredEffectSendSignal(int id, int userId, Item item, String extradata, int limitedStack, int limitedSells) {
|
||||
super(id, userId, item, extradata, limitedStack, limitedSells);
|
||||
this.items = new THashSet<>();
|
||||
this.forwardItems = new THashSet<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -77,73 +82,68 @@ public class WiredEffectSendSignal extends InteractionWiredEffect {
|
||||
.map(Collections::<HabboItem>singleton)
|
||||
.orElse(Collections.emptySet());
|
||||
} else {
|
||||
antennas = ctx.targets().isItemsModifiedBySelector()
|
||||
? new ArrayList<>(ctx.targets().items())
|
||||
: new ArrayList<>(this.items);
|
||||
Collection<HabboItem> baseAntennas = new ArrayList<>(this.items);
|
||||
|
||||
if (baseAntennas.isEmpty() && antennaSource > ANTENNA_TRIGGER) {
|
||||
HabboItem antenna = room.getHabboItem(antennaSource);
|
||||
antennas = (antenna != null) ? Collections.singleton(antenna) : Collections.emptySet();
|
||||
} else {
|
||||
antennas = baseAntennas;
|
||||
}
|
||||
}
|
||||
|
||||
if (antennas.isEmpty()) {
|
||||
List<HabboItem> resolvedAntennas = antennas.stream()
|
||||
.filter(Objects::nonNull)
|
||||
.filter(this::isAntennaItem)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
if (resolvedAntennas.isEmpty()) {
|
||||
LOGGER.debug("[SendSignal] No antennas resolved, aborting. antennaSource={}, selectorModified={}", antennaSource, ctx.targets().isItemsModifiedBySelector());
|
||||
return;
|
||||
}
|
||||
LOGGER.debug("[SendSignal] Resolved {} antenna(s), firing signals", antennas.size());
|
||||
LOGGER.debug("[SendSignal] Resolved {} antenna(s), firing signals", resolvedAntennas.size());
|
||||
|
||||
RoomUnit forwardedUser = null;
|
||||
if (userForward == FORWARD_TRIGGER) {
|
||||
forwardedUser = ctx.actor().orElse(null);
|
||||
}
|
||||
List<RoomUnit> forwardedUsers = WiredSourceUtil.resolveUsers(ctx, this.userForward);
|
||||
List<HabboItem> forwardedFurni = WiredSourceUtil.resolveItems(ctx, this.furniForward, this.forwardItems);
|
||||
|
||||
HabboItem forwardedFurni = null;
|
||||
if (furniForward == FORWARD_TRIGGER) {
|
||||
forwardedFurni = ctx.sourceItem().orElse(null);
|
||||
}
|
||||
RoomUnit defaultUser = forwardedUsers.isEmpty() ? null : forwardedUsers.get(0);
|
||||
HabboItem defaultFurni = forwardedFurni.isEmpty() ? null : forwardedFurni.get(0);
|
||||
|
||||
Set<String> visitedTiles = new HashSet<>();
|
||||
List<RoomTile> antennaTiles = new ArrayList<>();
|
||||
for (HabboItem antenna : antennas) {
|
||||
if (antenna == null) continue;
|
||||
String key = antenna.getX() + "," + antenna.getY();
|
||||
if (visitedTiles.add(key)) {
|
||||
RoomTile tile = room.getLayout().getTile(antenna.getX(), antenna.getY());
|
||||
if (tile != null) {
|
||||
antennaTiles.add(tile);
|
||||
}
|
||||
}
|
||||
}
|
||||
Collection<RoomUnit> usersToSend = (signalPerUser && !forwardedUsers.isEmpty())
|
||||
? forwardedUsers
|
||||
: Collections.singletonList(defaultUser);
|
||||
|
||||
Collection<HabboItem> furniToSend = (signalPerFurni && !forwardedFurni.isEmpty())
|
||||
? forwardedFurni
|
||||
: Collections.singletonList(defaultFurni);
|
||||
|
||||
int nextDepth = currentDepth + 1;
|
||||
|
||||
if (signalPerFurni || signalPerUser) {
|
||||
if (signalPerFurni) {
|
||||
for (RoomTile tile : antennaTiles) {
|
||||
fireSignalAtTile(room, tile, forwardedUser, forwardedFurni, nextDepth);
|
||||
for (RoomUnit user : usersToSend) {
|
||||
for (HabboItem sourceItem : furniToSend) {
|
||||
for (HabboItem antenna : resolvedAntennas) {
|
||||
fireSignalAtAntenna(room, antenna, user, sourceItem, nextDepth);
|
||||
}
|
||||
}
|
||||
if (signalPerUser && ctx.targets().hasUsers()) {
|
||||
for (RoomUnit user : ctx.targets().users()) {
|
||||
for (RoomTile tile : antennaTiles) {
|
||||
fireSignalAtTile(room, tile, user, forwardedFurni, nextDepth);
|
||||
}
|
||||
}
|
||||
} else if (!signalPerFurni) {
|
||||
for (RoomTile tile : antennaTiles) {
|
||||
fireSignalAtTile(room, tile, forwardedUser, forwardedFurni, nextDepth);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (RoomTile tile : antennaTiles) {
|
||||
fireSignalAtTile(room, tile, forwardedUser, forwardedFurni, nextDepth);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void fireSignalAtTile(Room room, RoomTile tile, RoomUnit actor, HabboItem sourceItem, int depth) {
|
||||
LOGGER.debug("[SendSignal] fireSignalAtTile: tile={},{} depth={} channel={} actor={} sourceItem={}", tile.x, tile.y, depth, channel, actor != null ? actor.getId() : "null", sourceItem != null ? sourceItem.getId() : "null");
|
||||
private void fireSignalAtAntenna(Room room, HabboItem antenna, RoomUnit actor, HabboItem sourceItem, int depth) {
|
||||
if (antenna == null) return;
|
||||
RoomTile tile = room.getLayout().getTile(antenna.getX(), antenna.getY());
|
||||
if (tile == null) return;
|
||||
|
||||
pulseAntenna(room, antenna);
|
||||
|
||||
int signalChannel = antenna.getId();
|
||||
|
||||
LOGGER.debug("[SendSignal] fireSignalAtAntenna: antennaId={} tile={},{} depth={} channel={} actor={} sourceItem={}",
|
||||
signalChannel, tile.x, tile.y, depth, signalChannel, actor != null ? actor.getId() : "null", sourceItem != null ? sourceItem.getId() : "null");
|
||||
|
||||
WiredEvent.Builder builder = WiredEvent.builder(WiredEvent.Type.SIGNAL_RECEIVED, room)
|
||||
.tile(tile)
|
||||
.callStackDepth(depth)
|
||||
.signalChannel(this.channel)
|
||||
.signalChannel(signalChannel)
|
||||
.triggeredByEffect(true);
|
||||
|
||||
if (actor != null) builder.actor(actor);
|
||||
@@ -153,6 +153,33 @@ public class WiredEffectSendSignal extends InteractionWiredEffect {
|
||||
LOGGER.debug("[SendSignal] handleEvent returned: {}", result);
|
||||
}
|
||||
|
||||
private void pulseAntenna(Room room, HabboItem antenna) {
|
||||
if (room == null || antenna == null || antenna.getBaseItem() == null) return;
|
||||
if (antenna.getBaseItem().getStateCount() <= 1) return;
|
||||
|
||||
final long token = System.currentTimeMillis();
|
||||
ANTENNA_PULSE_TOKENS.put(antenna.getId(), token);
|
||||
|
||||
if ("1".equals(antenna.getExtradata())) {
|
||||
antenna.setExtradata("0");
|
||||
room.updateItemState(antenna);
|
||||
}
|
||||
|
||||
antenna.setExtradata("1");
|
||||
room.updateItemState(antenna);
|
||||
|
||||
Emulator.getThreading().run(() -> {
|
||||
if (!room.isLoaded()) return;
|
||||
|
||||
Long currentToken = ANTENNA_PULSE_TOKENS.get(antenna.getId());
|
||||
if (currentToken == null || currentToken.longValue() != token) return;
|
||||
|
||||
antenna.setExtradata("0");
|
||||
room.updateItemState(antenna);
|
||||
ANTENNA_PULSE_TOKENS.remove(antenna.getId(), token);
|
||||
}, ANTENNA_PULSE_MS);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void serializeWiredData(ServerMessage message, Room room) {
|
||||
List<HabboItem> itemsSnapshot = new ArrayList<>(this.items);
|
||||
@@ -161,6 +188,16 @@ public class WiredEffectSendSignal extends InteractionWiredEffect {
|
||||
item.getRoomId() != this.getRoomId() || room.getHabboItem(item.getId()) == null);
|
||||
this.items.retainAll(itemsSnapshot);
|
||||
|
||||
List<HabboItem> forwardSnapshot = new ArrayList<>(this.forwardItems);
|
||||
forwardSnapshot.removeIf(item ->
|
||||
item.getRoomId() != this.getRoomId() || room.getHabboItem(item.getId()) == null);
|
||||
this.forwardItems.retainAll(forwardSnapshot);
|
||||
|
||||
String forwardString = forwardSnapshot.stream()
|
||||
.filter(Objects::nonNull)
|
||||
.map(item -> Integer.toString(item.getId()))
|
||||
.collect(Collectors.joining(";"));
|
||||
|
||||
message.appendBoolean(false);
|
||||
message.appendInt(WiredManager.MAXIMUM_FURNI_SELECTION);
|
||||
message.appendInt(itemsSnapshot.size());
|
||||
@@ -169,7 +206,7 @@ public class WiredEffectSendSignal extends InteractionWiredEffect {
|
||||
}
|
||||
message.appendInt(this.getBaseItem().getSpriteId());
|
||||
message.appendInt(this.getId());
|
||||
message.appendString("");
|
||||
message.appendString(forwardString);
|
||||
|
||||
message.appendInt(6);
|
||||
message.appendInt(antennaSource);
|
||||
@@ -219,6 +256,12 @@ public class WiredEffectSendSignal extends InteractionWiredEffect {
|
||||
newItems.add(it);
|
||||
}
|
||||
|
||||
for (HabboItem receiver : newItems) {
|
||||
if (!isAntennaItem(receiver)) {
|
||||
throw new WiredSaveException("Only antenna furni can be selected");
|
||||
}
|
||||
}
|
||||
|
||||
if (room != null && room.getRoomSpecialTypes() != null) {
|
||||
for (HabboItem receiver : newItems) {
|
||||
int count = room.getRoomSpecialTypes().countSendersTargetingReceiver(receiver.getId(), this);
|
||||
@@ -234,18 +277,36 @@ public class WiredEffectSendSignal extends InteractionWiredEffect {
|
||||
}
|
||||
|
||||
int[] params = settings.getIntParams();
|
||||
this.antennaSource = params.length > 0 ? params[0] : ANTENNA_PICKED;
|
||||
this.furniForward = params.length > 1 ? params[1] : FORWARD_NONE;
|
||||
this.userForward = params.length > 2 ? params[2] : FORWARD_NONE;
|
||||
int requestedAntennaSource = params.length > 0 ? params[0] : ANTENNA_PICKED;
|
||||
this.furniForward = normalizeSource(params.length > 1 ? params[1] : WiredSourceUtil.SOURCE_TRIGGER);
|
||||
this.userForward = normalizeSource(params.length > 2 ? params[2] : WiredSourceUtil.SOURCE_TRIGGER);
|
||||
this.signalPerFurni = params.length > 3 && params[3] == 1;
|
||||
this.signalPerUser = params.length > 4 && params[4] == 1;
|
||||
this.channel = params.length > 5 ? params[5] : 0;
|
||||
this.antennaSource = requestedAntennaSource;
|
||||
if (!newItems.isEmpty()) {
|
||||
this.antennaSource = newItems.get(0).getId();
|
||||
}
|
||||
|
||||
List<HabboItem> newForwardItems = new ArrayList<>();
|
||||
if (this.furniForward == WiredSourceUtil.SOURCE_SELECTED && room != null) {
|
||||
newForwardItems = parseForwardItems(settings.getStringParam(), room);
|
||||
}
|
||||
if (newForwardItems.size() > Emulator.getConfig().getInt("hotel.wired.furni.selection.count")) {
|
||||
throw new WiredSaveException("Too many furni selected");
|
||||
}
|
||||
|
||||
this.items.clear();
|
||||
this.items.addAll(newItems);
|
||||
|
||||
this.forwardItems.clear();
|
||||
if (this.furniForward == WiredSourceUtil.SOURCE_SELECTED) {
|
||||
this.forwardItems.addAll(newForwardItems);
|
||||
}
|
||||
this.setDelay(delay);
|
||||
|
||||
LOGGER.debug("[SendSignal] saveData: antennaSource={}, furniForward={}, userForward={}, signalPerFurni={}, signalPerUser={}, channel={}, items={}",
|
||||
antennaSource, furniForward, userForward, signalPerFurni, signalPerUser, channel, items.size());
|
||||
LOGGER.debug("[SendSignal] saveData: antennaSource={}, furniForward={}, userForward={}, signalPerFurni={}, signalPerUser={}, channel={}, items={}, forwardItems={}",
|
||||
antennaSource, furniForward, userForward, signalPerFurni, signalPerUser, channel, items.size(), forwardItems.size());
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -259,9 +320,11 @@ public class WiredEffectSendSignal extends InteractionWiredEffect {
|
||||
@Override
|
||||
public String getWiredData() {
|
||||
List<HabboItem> itemsSnapshot = new ArrayList<>(this.items);
|
||||
List<HabboItem> forwardSnapshot = new ArrayList<>(this.forwardItems);
|
||||
return WiredManager.getGson().toJson(new JsonData(
|
||||
this.getDelay(),
|
||||
itemsSnapshot.stream().map(HabboItem::getId).collect(Collectors.toList()),
|
||||
forwardSnapshot.stream().map(HabboItem::getId).collect(Collectors.toList()),
|
||||
antennaSource, furniForward, userForward, signalPerFurni, signalPerUser, channel
|
||||
));
|
||||
}
|
||||
@@ -269,14 +332,15 @@ public class WiredEffectSendSignal extends InteractionWiredEffect {
|
||||
@Override
|
||||
public void loadWiredData(ResultSet set, Room room) throws SQLException {
|
||||
this.items = new THashSet<>();
|
||||
this.forwardItems = new THashSet<>();
|
||||
String wiredData = set.getString("wired_data");
|
||||
|
||||
if (wiredData != null && wiredData.startsWith("{")) {
|
||||
JsonData data = WiredManager.getGson().fromJson(wiredData, JsonData.class);
|
||||
this.setDelay(data.delay);
|
||||
this.antennaSource = data.antennaSource;
|
||||
this.furniForward = data.furniForward;
|
||||
this.userForward = data.userForward;
|
||||
this.furniForward = normalizeSource(data.furniForward);
|
||||
this.userForward = normalizeSource(data.userForward);
|
||||
this.signalPerFurni = data.signalPerFurni;
|
||||
this.signalPerUser = data.signalPerUser;
|
||||
this.channel = data.channel;
|
||||
@@ -286,21 +350,84 @@ public class WiredEffectSendSignal extends InteractionWiredEffect {
|
||||
if (item != null) this.items.add(item);
|
||||
}
|
||||
}
|
||||
if (data.forwardItemIds != null) {
|
||||
for (Integer id : data.forwardItemIds) {
|
||||
HabboItem item = room.getHabboItem(id);
|
||||
if (item != null) this.forwardItems.add(item);
|
||||
}
|
||||
}
|
||||
|
||||
if (this.antennaSource <= ANTENNA_TRIGGER && !this.items.isEmpty()) {
|
||||
HabboItem first = this.items.iterator().next();
|
||||
if (first != null) this.antennaSource = first.getId();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPickUp() {
|
||||
this.items.clear();
|
||||
this.forwardItems.clear();
|
||||
this.antennaSource = ANTENNA_PICKED;
|
||||
this.furniForward = FORWARD_NONE;
|
||||
this.userForward = FORWARD_NONE;
|
||||
this.furniForward = WiredSourceUtil.SOURCE_TRIGGER;
|
||||
this.userForward = WiredSourceUtil.SOURCE_TRIGGER;
|
||||
this.signalPerFurni = false;
|
||||
this.signalPerUser = false;
|
||||
this.channel = 0;
|
||||
this.setDelay(0);
|
||||
}
|
||||
|
||||
private int normalizeSource(int source) {
|
||||
if (source == 1) return WiredSourceUtil.SOURCE_TRIGGER;
|
||||
if (source == WiredSourceUtil.SOURCE_TRIGGER
|
||||
|| source == WiredSourceUtil.SOURCE_SELECTED
|
||||
|| source == WiredSourceUtil.SOURCE_SELECTOR
|
||||
|| source == WiredSourceUtil.SOURCE_SIGNAL) {
|
||||
return source;
|
||||
}
|
||||
return WiredSourceUtil.SOURCE_TRIGGER;
|
||||
}
|
||||
|
||||
private List<HabboItem> parseForwardItems(String data, Room room) throws WiredSaveException {
|
||||
List<HabboItem> results = new ArrayList<>();
|
||||
if (data == null || data.trim().isEmpty() || room == null) return results;
|
||||
|
||||
Set<Integer> seen = new HashSet<>();
|
||||
String[] parts = data.split(FORWARD_ITEM_SPLIT_REGEX);
|
||||
|
||||
for (String part : parts) {
|
||||
if (part == null) continue;
|
||||
|
||||
String trimmed = part.trim();
|
||||
if (trimmed.isEmpty()) continue;
|
||||
|
||||
int itemId;
|
||||
try {
|
||||
itemId = Integer.parseInt(trimmed);
|
||||
} catch (NumberFormatException e) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (itemId <= 0 || !seen.add(itemId)) continue;
|
||||
|
||||
HabboItem item = room.getHabboItem(itemId);
|
||||
if (item == null) throw new WiredSaveException(String.format("Item %s not found", itemId));
|
||||
|
||||
results.add(item);
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
private boolean isAntennaItem(HabboItem item) {
|
||||
if (item == null || item.getBaseItem() == null || item.getBaseItem().getInteractionType() == null) return false;
|
||||
String interaction = item.getBaseItem().getInteractionType().getName();
|
||||
if (interaction == null) return false;
|
||||
|
||||
String normalized = interaction.toLowerCase();
|
||||
return normalized.equals(ANTENNA_INTERACTION);
|
||||
}
|
||||
|
||||
@Override
|
||||
public WiredEffectType getType() {
|
||||
return type;
|
||||
@@ -328,6 +455,7 @@ public class WiredEffectSendSignal extends InteractionWiredEffect {
|
||||
static class JsonData {
|
||||
int delay;
|
||||
List<Integer> itemIds;
|
||||
List<Integer> forwardItemIds;
|
||||
int antennaSource;
|
||||
int furniForward;
|
||||
int userForward;
|
||||
@@ -335,10 +463,11 @@ public class WiredEffectSendSignal extends InteractionWiredEffect {
|
||||
boolean signalPerUser;
|
||||
int channel;
|
||||
|
||||
public JsonData(int delay, List<Integer> itemIds, int antennaSource, int furniForward,
|
||||
public JsonData(int delay, List<Integer> itemIds, List<Integer> forwardItemIds, int antennaSource, int furniForward,
|
||||
int userForward, boolean signalPerFurni, boolean signalPerUser, int channel) {
|
||||
this.delay = delay;
|
||||
this.itemIds = itemIds;
|
||||
this.forwardItemIds = forwardItemIds;
|
||||
this.antennaSource = antennaSource;
|
||||
this.furniForward = furniForward;
|
||||
this.userForward = userForward;
|
||||
|
||||
+8
-10
@@ -112,17 +112,17 @@ public class WiredEffectFurniByType extends InteractionWiredEffect {
|
||||
@Override
|
||||
public boolean saveData(WiredSettings settings, GameClient gameClient) throws WiredSaveException {
|
||||
int[] params = settings.getIntParams();
|
||||
if (params == null || params.length < 1) {
|
||||
throw new WiredSaveException("wf_slc_furni_bytype: intParams must have at least 1 element");
|
||||
if (params == null || params.length < 4) {
|
||||
throw new WiredSaveException("wf_slc_furni_bytype: intParams must have at least 4 elements");
|
||||
}
|
||||
|
||||
this.sourceType = params[0];
|
||||
this.sourceType = SOURCE_FURNI_PICKED;
|
||||
this.matchState = params.length > 1 && params[1] == 1;
|
||||
this.filterExisting = params.length > 2 && params[2] == 1;
|
||||
this.invert = params.length > 3 && params[3] == 1;
|
||||
|
||||
this.pickedFurniIds = new ArrayList<>();
|
||||
if (this.sourceType == SOURCE_FURNI_PICKED && settings.getFurniIds() != null) {
|
||||
if (settings.getFurniIds() != null) {
|
||||
for (int id : settings.getFurniIds()) {
|
||||
if (pickedFurniIds.size() >= MAX_PICKED_FURNI) break;
|
||||
pickedFurniIds.add(id);
|
||||
@@ -135,12 +135,10 @@ public class WiredEffectFurniByType extends InteractionWiredEffect {
|
||||
|
||||
@Override
|
||||
public void serializeWiredData(ServerMessage message, Room room) {
|
||||
boolean pickMode = (sourceType == SOURCE_FURNI_PICKED);
|
||||
message.appendBoolean(true);
|
||||
message.appendInt(MAX_PICKED_FURNI);
|
||||
|
||||
message.appendBoolean(pickMode);
|
||||
message.appendInt(pickMode ? MAX_PICKED_FURNI : 0);
|
||||
|
||||
if (pickMode && !pickedFurniIds.isEmpty()) {
|
||||
if (!pickedFurniIds.isEmpty()) {
|
||||
message.appendInt(pickedFurniIds.size());
|
||||
pickedFurniIds.forEach(message::appendInt);
|
||||
} else {
|
||||
@@ -152,7 +150,7 @@ public class WiredEffectFurniByType extends InteractionWiredEffect {
|
||||
message.appendString("");
|
||||
|
||||
message.appendInt(4);
|
||||
message.appendInt(sourceType);
|
||||
message.appendInt(SOURCE_FURNI_PICKED);
|
||||
message.appendInt(matchState ? 1 : 0);
|
||||
message.appendInt(filterExisting ? 1 : 0);
|
||||
message.appendInt(invert ? 1 : 0);
|
||||
|
||||
+112
-7
@@ -1,5 +1,6 @@
|
||||
package com.eu.habbo.habbohotel.items.interactions.wired.triggers;
|
||||
|
||||
import com.eu.habbo.Emulator;
|
||||
import com.eu.habbo.habbohotel.items.Item;
|
||||
import com.eu.habbo.habbohotel.items.interactions.InteractionWiredTrigger;
|
||||
import com.eu.habbo.habbohotel.items.interactions.wired.WiredSettings;
|
||||
@@ -11,27 +12,49 @@ import com.eu.habbo.habbohotel.wired.WiredTriggerType;
|
||||
import com.eu.habbo.habbohotel.wired.core.WiredEvent;
|
||||
import com.eu.habbo.habbohotel.wired.core.WiredManager;
|
||||
import com.eu.habbo.messages.ServerMessage;
|
||||
import com.eu.habbo.messages.incoming.wired.WiredTriggerSaveException;
|
||||
import com.eu.habbo.messages.outgoing.rooms.items.ItemStateComposer;
|
||||
import gnu.trove.set.hash.THashSet;
|
||||
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class WiredTriggerReceiveSignal extends InteractionWiredTrigger {
|
||||
public static final WiredTriggerType type = WiredTriggerType.RECEIVE_SIGNAL;
|
||||
|
||||
private static final String ANTENNA_INTERACTION = "antenna";
|
||||
private static final long ACTIVATION_PULSE_MS = 300L;
|
||||
|
||||
private int channel = 0; // signal channel (0-based)
|
||||
private THashSet<HabboItem> items;
|
||||
private final AtomicLong activationToken = new AtomicLong();
|
||||
|
||||
public WiredTriggerReceiveSignal(ResultSet set, Item baseItem) throws SQLException {
|
||||
super(set, baseItem);
|
||||
this.items = new THashSet<>();
|
||||
}
|
||||
|
||||
public WiredTriggerReceiveSignal(int id, int userId, Item item, String extradata, int limitedStack, int limitedSells) {
|
||||
super(id, userId, item, extradata, limitedStack, limitedSells);
|
||||
this.items = new THashSet<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matches(HabboItem triggerItem, WiredEvent event) {
|
||||
return event.getType() == WiredEvent.Type.SIGNAL_RECEIVED
|
||||
&& event.getSignalChannel() == this.channel;
|
||||
if (event.getType() != WiredEvent.Type.SIGNAL_RECEIVED) return false;
|
||||
|
||||
if (!this.items.isEmpty()) {
|
||||
int signalChannel = event.getSignalChannel();
|
||||
for (HabboItem antenna : this.items) {
|
||||
if (antenna != null && antenna.getId() == signalChannel) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
return event.getSignalChannel() == this.channel;
|
||||
}
|
||||
|
||||
public int getChannel() {
|
||||
@@ -59,14 +82,33 @@ public class WiredTriggerReceiveSignal extends InteractionWiredTrigger {
|
||||
int senderCount = 0;
|
||||
try {
|
||||
if (room != null && room.getRoomSpecialTypes() != null) {
|
||||
senderCount = room.getRoomSpecialTypes().countSendersTargetingReceiver(this.getId());
|
||||
if (!this.items.isEmpty()) {
|
||||
for (HabboItem item : this.items) {
|
||||
senderCount += room.getRoomSpecialTypes().countSendersTargetingReceiver(item.getId());
|
||||
}
|
||||
} else {
|
||||
senderCount = room.getRoomSpecialTypes().countSendersTargetingReceiver(this.getId());
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
}
|
||||
|
||||
THashSet<HabboItem> itemsToRemove = new THashSet<>();
|
||||
for (HabboItem item : this.items) {
|
||||
if (item.getRoomId() != this.getRoomId() || room.getHabboItem(item.getId()) == null) {
|
||||
itemsToRemove.add(item);
|
||||
}
|
||||
}
|
||||
for (HabboItem item : itemsToRemove) {
|
||||
this.items.remove(item);
|
||||
}
|
||||
|
||||
message.appendBoolean(false);
|
||||
message.appendInt(0);
|
||||
message.appendInt(0);
|
||||
message.appendInt(WiredManager.MAXIMUM_FURNI_SELECTION);
|
||||
message.appendInt(this.items.size());
|
||||
for (HabboItem item : this.items) {
|
||||
message.appendInt(item.getId());
|
||||
}
|
||||
message.appendInt(this.getBaseItem().getSpriteId());
|
||||
message.appendInt(this.getId());
|
||||
message.appendString("");
|
||||
@@ -82,37 +124,100 @@ public class WiredTriggerReceiveSignal extends InteractionWiredTrigger {
|
||||
|
||||
@Override
|
||||
public boolean saveData(WiredSettings settings) {
|
||||
this.items.clear();
|
||||
|
||||
Room room = Emulator.getGameEnvironment().getRoomManager().getRoom(this.getRoomId());
|
||||
int count = settings.getFurniIds().length;
|
||||
|
||||
for (int i = 0; i < count; i++) {
|
||||
HabboItem item = room.getHabboItem(settings.getFurniIds()[i]);
|
||||
if (item == null) continue;
|
||||
if (!isAntennaItem(item)) throw new WiredTriggerSaveException("wiredfurni.error.require_antenna_furni");
|
||||
this.items.add(item);
|
||||
}
|
||||
|
||||
int[] params = settings.getIntParams();
|
||||
this.channel = params.length > 0 ? params[0] : 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void activateBox(Room room, RoomUnit roomUnit, long millis) {
|
||||
if (roomUnit != null) {
|
||||
this.addUserExecutionCache(roomUnit.getId(), millis);
|
||||
}
|
||||
|
||||
if (room == null || room.isHideWired() || this.getBaseItem().getStateCount() <= 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
final long token = this.activationToken.incrementAndGet();
|
||||
|
||||
if ("1".equals(this.getExtradata())) {
|
||||
this.setExtradata("0");
|
||||
room.sendComposer(new ItemStateComposer(this).compose());
|
||||
}
|
||||
|
||||
this.setExtradata("1");
|
||||
room.sendComposer(new ItemStateComposer(this).compose());
|
||||
|
||||
Emulator.getThreading().run(() -> {
|
||||
if (!room.isLoaded()) return;
|
||||
if (this.activationToken.get() != token) return;
|
||||
|
||||
this.setExtradata("0");
|
||||
room.sendComposer(new ItemStateComposer(this).compose());
|
||||
}, ACTIVATION_PULSE_MS);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getWiredData() {
|
||||
return WiredManager.getGson().toJson(new JsonData(channel));
|
||||
return WiredManager.getGson().toJson(new JsonData(
|
||||
channel,
|
||||
this.items.stream().map(HabboItem::getId).collect(Collectors.toList())
|
||||
));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadWiredData(ResultSet set, Room room) throws SQLException {
|
||||
this.items = new THashSet<>();
|
||||
String wiredData = set.getString("wired_data");
|
||||
if (wiredData != null && wiredData.startsWith("{")) {
|
||||
JsonData data = WiredManager.getGson().fromJson(wiredData, JsonData.class);
|
||||
this.channel = data.channel;
|
||||
if (data.itemIds != null) {
|
||||
for (Integer id : data.itemIds) {
|
||||
HabboItem item = room.getHabboItem(id);
|
||||
if (item != null) this.items.add(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPickUp() {
|
||||
this.channel = 0;
|
||||
this.items.clear();
|
||||
}
|
||||
|
||||
private boolean isAntennaItem(HabboItem item) {
|
||||
if (item == null || item.getBaseItem() == null || item.getBaseItem().getInteractionType() == null) return false;
|
||||
String interaction = item.getBaseItem().getInteractionType().getName();
|
||||
if (interaction == null) return false;
|
||||
|
||||
String normalized = interaction.toLowerCase();
|
||||
return normalized.equals(ANTENNA_INTERACTION);
|
||||
}
|
||||
|
||||
static class JsonData {
|
||||
int channel;
|
||||
List<Integer> itemIds;
|
||||
|
||||
public JsonData() {}
|
||||
|
||||
public JsonData(int channel) {
|
||||
public JsonData(int channel, List<Integer> itemIds) {
|
||||
this.channel = channel;
|
||||
this.itemIds = itemIds;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -214,24 +214,16 @@ public final class WiredEngine {
|
||||
// Initial step for trigger
|
||||
state.step();
|
||||
|
||||
// Activate the trigger box animation
|
||||
if (stack.triggerItem() instanceof InteractionWiredTrigger) {
|
||||
InteractionWiredTrigger trigger = (InteractionWiredTrigger) stack.triggerItem();
|
||||
trigger.activateBox(room, event.getActor().orElse(null), currentTime);
|
||||
}
|
||||
|
||||
debug(room, "Trigger matched: {} at item {} (conditions: {}, effects: {})",
|
||||
event.getType(),
|
||||
stack.triggerItem() != null ? stack.triggerItem().getId() : "null",
|
||||
stack.conditions().size(),
|
||||
stack.effects().size());
|
||||
|
||||
// Activate extras (for their animation)
|
||||
activateExtras(room, stack.triggerItem(), event.getActor().orElse(null), currentTime);
|
||||
|
||||
// Run selectors before conditions so targets are available
|
||||
List<InteractionWiredEffect> executedSelectors = Collections.emptyList();
|
||||
if (stack.hasEffects()) {
|
||||
executeSelectors(stack, ctx, currentTime);
|
||||
executedSelectors = executeSelectors(stack, ctx);
|
||||
}
|
||||
|
||||
// Evaluate conditions
|
||||
@@ -253,6 +245,17 @@ public final class WiredEngine {
|
||||
return false;
|
||||
}
|
||||
|
||||
RoomUnit actor = event.getActor().orElse(null);
|
||||
|
||||
// Only show the trigger/selector activation when the stack is actually allowed to continue.
|
||||
if (stack.triggerItem() instanceof InteractionWiredTrigger) {
|
||||
InteractionWiredTrigger trigger = (InteractionWiredTrigger) stack.triggerItem();
|
||||
trigger.activateBox(room, actor, currentTime);
|
||||
}
|
||||
|
||||
activateExtras(room, stack.triggerItem(), actor, currentTime);
|
||||
finalizeSelectors(executedSelectors, ctx, currentTime);
|
||||
|
||||
// Execute effects
|
||||
if (stack.hasEffects()) {
|
||||
executeEffects(stack, ctx, currentTime);
|
||||
@@ -420,9 +423,11 @@ public final class WiredEngine {
|
||||
/**
|
||||
* Execute selector effects before conditions so ctx.targets() is populated.
|
||||
*/
|
||||
private void executeSelectors(WiredStack stack, WiredContext ctx, long currentTime) {
|
||||
private List<InteractionWiredEffect> executeSelectors(WiredStack stack, WiredContext ctx) {
|
||||
List<IWiredEffect> effects = stack.effects();
|
||||
if (effects.isEmpty()) return;
|
||||
if (effects.isEmpty()) return Collections.emptyList();
|
||||
|
||||
List<InteractionWiredEffect> executedSelectors = new ArrayList<>();
|
||||
|
||||
for (IWiredEffect effect : effects) {
|
||||
if (!effect.isSelector()) continue;
|
||||
@@ -433,16 +438,29 @@ public final class WiredEngine {
|
||||
ctx.state().step();
|
||||
try {
|
||||
effect.execute(ctx);
|
||||
|
||||
if (effect instanceof InteractionWiredEffect) {
|
||||
InteractionWiredEffect wiredEffect = (InteractionWiredEffect) effect;
|
||||
wiredEffect.setCooldown(currentTime);
|
||||
wiredEffect.activateBox(ctx.room(), ctx.actor().orElse(null), currentTime);
|
||||
executedSelectors.add((InteractionWiredEffect) effect);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
LOGGER.warn("Error executing selector: {}", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
return executedSelectors;
|
||||
}
|
||||
|
||||
private void finalizeSelectors(List<InteractionWiredEffect> executedSelectors, WiredContext ctx, long currentTime) {
|
||||
if (executedSelectors == null || executedSelectors.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
Room room = ctx.room();
|
||||
RoomUnit actor = ctx.actor().orElse(null);
|
||||
|
||||
for (InteractionWiredEffect wiredEffect : executedSelectors) {
|
||||
wiredEffect.setCooldown(currentTime);
|
||||
wiredEffect.activateBox(room, actor, currentTime);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+13
-9
@@ -34,17 +34,21 @@ public class WiredTriggerSaveDataEvent extends MessageHandler {
|
||||
if (saveMethod.get().getParameterTypes()[0] == WiredSettings.class) {
|
||||
WiredSettings settings = InteractionWired.readSettings(this.packet, false);
|
||||
|
||||
if (trigger.saveData(settings)) {
|
||||
this.client.sendResponse(new WiredSavedComposer());
|
||||
try {
|
||||
if (trigger.saveData(settings)) {
|
||||
this.client.sendResponse(new WiredSavedComposer());
|
||||
|
||||
trigger.needsUpdate(true);
|
||||
trigger.needsUpdate(true);
|
||||
|
||||
Emulator.getThreading().run(trigger);
|
||||
|
||||
// Invalidate wired cache when trigger is saved
|
||||
WiredManager.invalidateRoom(room);
|
||||
} else {
|
||||
this.client.sendResponse(new UpdateFailedComposer("There was an error while saving that trigger"));
|
||||
Emulator.getThreading().run(trigger);
|
||||
|
||||
// Invalidate wired cache when trigger is saved
|
||||
WiredManager.invalidateRoom(room);
|
||||
} else {
|
||||
this.client.sendResponse(new UpdateFailedComposer("There was an error while saving that trigger"));
|
||||
}
|
||||
} catch (WiredTriggerSaveException e) {
|
||||
this.client.sendResponse(new UpdateFailedComposer(e.getMessage()));
|
||||
}
|
||||
} else {
|
||||
if ((boolean) saveMethod.get().invoke(trigger, this.packet)) {
|
||||
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
package com.eu.habbo.messages.incoming.wired;
|
||||
|
||||
public class WiredTriggerSaveException extends RuntimeException {
|
||||
public WiredTriggerSaveException(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user