🆕 wf_act_send_signal & wf_trg_recv_signal

the signal sender can only be a max of 25 in a room
the signal receiver can only be a max of 5 in a room
one signal receiver can only accept a max of 5 senders (you can select the receivers with the senders)
Why : otherwise you can flood the rooms and let you CPU go 🍌
This commit is contained in:
duckietm
2026-03-11 12:37:05 +01:00
parent 1f35e6ab55
commit 8463a9cea0
9 changed files with 542 additions and 5 deletions
@@ -221,6 +221,7 @@ public class ItemManager {
this.interactionsList.add(new ItemInteraction("wf_trg_score_achieved", WiredTriggerScoreAchieved.class));
this.interactionsList.add(new ItemInteraction("wf_trg_game_team_win", WiredTriggerTeamWins.class));
this.interactionsList.add(new ItemInteraction("wf_trg_game_team_lose", WiredTriggerTeamLoses.class));
this.interactionsList.add(new ItemInteraction("wf_trg_recv_signal", WiredTriggerReceiveSignal.class));
this.interactionsList.add(new ItemInteraction("wf_act_toggle_state", WiredEffectToggleFurni.class));
@@ -258,6 +259,7 @@ public class ItemManager {
this.interactionsList.add(new ItemInteraction("wf_slc_furni_bytype", WiredEffectFurniByType.class));
this.interactionsList.add(new ItemInteraction("wf_slc_users_area", WiredEffectUsersArea.class));
this.interactionsList.add(new ItemInteraction("wf_slc_users_neighborhood", WiredEffectUsersNeighborhood.class));
this.interactionsList.add(new ItemInteraction("wf_act_send_signal", WiredEffectSendSignal.class));
this.interactionsList.add(new ItemInteraction("wf_cnd_has_furni_on", WiredConditionFurniHaveFurni.class));
this.interactionsList.add(new ItemInteraction("wf_cnd_furnis_hv_avtrs", WiredConditionFurniHaveHabbo.class));
@@ -0,0 +1,350 @@
package com.eu.habbo.habbohotel.items.interactions.wired.effects;
import com.eu.habbo.Emulator;
import com.eu.habbo.habbohotel.gameclients.GameClient;
import com.eu.habbo.habbohotel.items.Item;
import com.eu.habbo.habbohotel.items.interactions.InteractionWiredEffect;
import com.eu.habbo.habbohotel.items.interactions.InteractionWiredTrigger;
import com.eu.habbo.habbohotel.items.interactions.wired.WiredSettings;
import com.eu.habbo.habbohotel.rooms.Room;
import com.eu.habbo.habbohotel.rooms.RoomSpecialTypes;
import com.eu.habbo.habbohotel.rooms.RoomTile;
import com.eu.habbo.habbohotel.rooms.RoomUnit;
import com.eu.habbo.habbohotel.users.HabboItem;
import com.eu.habbo.habbohotel.wired.WiredEffectType;
import com.eu.habbo.habbohotel.wired.core.*;
import com.eu.habbo.habbohotel.wired.core.WiredEvent;
import com.eu.habbo.messages.ServerMessage;
import com.eu.habbo.messages.incoming.wired.WiredSaveException;
import gnu.trove.procedure.TObjectProcedure;
import gnu.trove.set.hash.THashSet;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.*;
import java.util.stream.Collectors;
public class WiredEffectSendSignal extends InteractionWiredEffect {
private static final Logger LOGGER = LoggerFactory.getLogger(WiredEffectSendSignal.class);
public static final WiredEffectType type = WiredEffectType.SEND_SIGNAL;
private static final int MAX_SIGNAL_DEPTH = 10;
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 THashSet<HabboItem> items;
private int antennaSource = ANTENNA_PICKED;
private int furniForward = FORWARD_NONE;
private int userForward = FORWARD_NONE;
private boolean signalPerFurni = false;
private boolean signalPerUser = false;
private int channel = 0;
public WiredEffectSendSignal(ResultSet set, Item baseItem) throws SQLException {
super(set, baseItem);
this.items = 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<>();
}
@Override
public void execute(WiredContext ctx) {
Room room = ctx.room();
if (room == null) return;
LOGGER.debug("[SendSignal] execute() called, itemId={}, antennaSource={}, pickedItems={}", this.getId(), antennaSource, this.items.size());
int currentDepth = ctx.event().getCallStackDepth();
if (currentDepth >= MAX_SIGNAL_DEPTH) {
LOGGER.debug("[SendSignal] Max signal depth reached ({}), aborting", currentDepth);
return;
}
Collection<HabboItem> antennas;
if (antennaSource == ANTENNA_TRIGGER) {
antennas = ctx.sourceItem()
.map(Collections::<HabboItem>singleton)
.orElse(Collections.emptySet());
} else {
antennas = ctx.targets().isItemsModifiedBySelector()
? new ArrayList<>(ctx.targets().items())
: new ArrayList<>(this.items);
}
if (antennas.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());
RoomUnit forwardedUser = null;
if (userForward == FORWARD_TRIGGER) {
forwardedUser = ctx.actor().orElse(null);
}
HabboItem forwardedFurni = null;
if (furniForward == FORWARD_TRIGGER) {
forwardedFurni = ctx.sourceItem().orElse(null);
}
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);
}
}
}
int nextDepth = currentDepth + 1;
if (signalPerFurni || signalPerUser) {
if (signalPerFurni) {
for (RoomTile tile : antennaTiles) {
fireSignalAtTile(room, tile, forwardedUser, forwardedFurni, 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");
WiredEvent.Builder builder = WiredEvent.builder(WiredEvent.Type.SIGNAL_RECEIVED, room)
.tile(tile)
.callStackDepth(depth)
.signalChannel(this.channel)
.triggeredByEffect(true);
if (actor != null) builder.actor(actor);
if (sourceItem != null) builder.sourceItem(sourceItem);
boolean result = WiredManager.handleEvent(builder.build());
LOGGER.debug("[SendSignal] handleEvent returned: {}", result);
}
@Override
public void serializeWiredData(ServerMessage message, Room room) {
List<HabboItem> itemsSnapshot = new ArrayList<>(this.items);
itemsSnapshot.removeIf(item ->
item.getRoomId() != this.getRoomId() || room.getHabboItem(item.getId()) == null);
this.items.retainAll(itemsSnapshot);
message.appendBoolean(false);
message.appendInt(WiredManager.MAXIMUM_FURNI_SELECTION);
message.appendInt(itemsSnapshot.size());
for (HabboItem item : itemsSnapshot) {
message.appendInt(item.getId());
}
message.appendInt(this.getBaseItem().getSpriteId());
message.appendInt(this.getId());
message.appendString("");
message.appendInt(6);
message.appendInt(antennaSource);
message.appendInt(furniForward);
message.appendInt(userForward);
message.appendInt(signalPerFurni ? 1 : 0);
message.appendInt(signalPerUser ? 1 : 0);
message.appendInt(channel);
message.appendInt(0);
message.appendInt(this.getType().code);
message.appendInt(this.getDelay());
if (this.requiresTriggeringUser()) {
List<Integer> invalidTriggers = new ArrayList<>();
room.getRoomSpecialTypes().getTriggers(this.getX(), this.getY()).forEach(new TObjectProcedure<InteractionWiredTrigger>() {
@Override
public boolean execute(InteractionWiredTrigger object) {
if (!object.isTriggeredByRoomUnit()) {
invalidTriggers.add(object.getBaseItem().getSpriteId());
}
return true;
}
});
message.appendInt(invalidTriggers.size());
for (Integer i : invalidTriggers) {
message.appendInt(i);
}
} else {
message.appendInt(0);
}
}
@Override
public boolean saveData(WiredSettings settings, GameClient gameClient) throws WiredSaveException {
int itemsCount = settings.getFurniIds().length;
if (itemsCount > Emulator.getConfig().getInt("hotel.wired.furni.selection.count")) {
throw new WiredSaveException("Too many furni selected");
}
List<HabboItem> newItems = new ArrayList<>();
Room room = Emulator.getGameEnvironment().getRoomManager().getRoom(this.getRoomId());
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));
newItems.add(it);
}
if (room != null && room.getRoomSpecialTypes() != null) {
for (HabboItem receiver : newItems) {
int count = room.getRoomSpecialTypes().countSendersTargetingReceiver(receiver.getId(), this);
if (count >= RoomSpecialTypes.MAX_SENDERS_PER_RECEIVER) {
throw new WiredSaveException("Maximum of " + RoomSpecialTypes.MAX_SENDERS_PER_RECEIVER + " senders per receiver reached");
}
}
}
int delay = settings.getDelay();
if (delay > Emulator.getConfig().getInt("hotel.wired.max_delay", 20)) {
throw new WiredSaveException("Delay too long");
}
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;
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.items.clear();
this.items.addAll(newItems);
this.setDelay(delay);
LOGGER.debug("[SendSignal] saveData: antennaSource={}, furniForward={}, userForward={}, signalPerFurni={}, signalPerUser={}, channel={}, items={}",
antennaSource, furniForward, userForward, signalPerFurni, signalPerUser, channel, items.size());
return true;
}
@Deprecated
@Override
public boolean execute(RoomUnit roomUnit, Room room, Object[] stuff) {
return false;
}
@Override
public String getWiredData() {
List<HabboItem> itemsSnapshot = new ArrayList<>(this.items);
return WiredManager.getGson().toJson(new JsonData(
this.getDelay(),
itemsSnapshot.stream().map(HabboItem::getId).collect(Collectors.toList()),
antennaSource, furniForward, userForward, signalPerFurni, signalPerUser, channel
));
}
@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.setDelay(data.delay);
this.antennaSource = data.antennaSource;
this.furniForward = data.furniForward;
this.userForward = data.userForward;
this.signalPerFurni = data.signalPerFurni;
this.signalPerUser = data.signalPerUser;
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.items.clear();
this.antennaSource = ANTENNA_PICKED;
this.furniForward = FORWARD_NONE;
this.userForward = FORWARD_NONE;
this.signalPerFurni = false;
this.signalPerUser = false;
this.channel = 0;
this.setDelay(0);
}
@Override
public WiredEffectType getType() {
return type;
}
public int getChannel() {
return channel;
}
public boolean hasPickedItem(int itemId) {
try {
for (HabboItem item : new ArrayList<>(this.items)) {
if (item != null && item.getId() == itemId) return true;
}
} catch (Exception e) {
}
return false;
}
@Override
protected long requiredCooldown() {
return COOLDOWN_TRIGGER_STACKS;
}
static class JsonData {
int delay;
List<Integer> itemIds;
int antennaSource;
int furniForward;
int userForward;
boolean signalPerFurni;
boolean signalPerUser;
int channel;
public JsonData(int delay, List<Integer> itemIds, int antennaSource, int furniForward,
int userForward, boolean signalPerFurni, boolean signalPerUser, int channel) {
this.delay = delay;
this.itemIds = itemIds;
this.antennaSource = antennaSource;
this.furniForward = furniForward;
this.userForward = userForward;
this.signalPerFurni = signalPerFurni;
this.signalPerUser = signalPerUser;
this.channel = channel;
}
}
}
@@ -0,0 +1,118 @@
package com.eu.habbo.habbohotel.items.interactions.wired.triggers;
import com.eu.habbo.habbohotel.items.Item;
import com.eu.habbo.habbohotel.items.interactions.InteractionWiredTrigger;
import com.eu.habbo.habbohotel.items.interactions.wired.WiredSettings;
import com.eu.habbo.habbohotel.rooms.Room;
import com.eu.habbo.habbohotel.rooms.RoomSpecialTypes;
import com.eu.habbo.habbohotel.rooms.RoomUnit;
import com.eu.habbo.habbohotel.users.HabboItem;
import com.eu.habbo.habbohotel.wired.WiredTriggerType;
import com.eu.habbo.habbohotel.wired.core.WiredEvent;
import com.eu.habbo.habbohotel.wired.core.WiredManager;
import com.eu.habbo.messages.ServerMessage;
import java.sql.ResultSet;
import java.sql.SQLException;
public class WiredTriggerReceiveSignal extends InteractionWiredTrigger {
public static final WiredTriggerType type = WiredTriggerType.RECEIVE_SIGNAL;
private int channel = 0; // signal channel (0-based)
public WiredTriggerReceiveSignal(ResultSet set, Item baseItem) throws SQLException {
super(set, baseItem);
}
public WiredTriggerReceiveSignal(int id, int userId, Item item, String extradata, int limitedStack, int limitedSells) {
super(id, userId, item, extradata, limitedStack, limitedSells);
}
@Override
public boolean matches(HabboItem triggerItem, WiredEvent event) {
return event.getType() == WiredEvent.Type.SIGNAL_RECEIVED
&& event.getSignalChannel() == this.channel;
}
public int getChannel() {
return channel;
}
@Override
public boolean isTriggeredByRoomUnit() {
return false;
}
@Deprecated
@Override
public boolean execute(RoomUnit roomUnit, Room room, Object[] stuff) {
return false;
}
@Override
public WiredTriggerType getType() {
return type;
}
@Override
public void serializeWiredData(ServerMessage message, Room room) {
int senderCount = 0;
try {
if (room != null && room.getRoomSpecialTypes() != null) {
senderCount = room.getRoomSpecialTypes().countSendersTargetingReceiver(this.getId());
}
} catch (Exception e) {
}
message.appendBoolean(false);
message.appendInt(0);
message.appendInt(0);
message.appendInt(this.getBaseItem().getSpriteId());
message.appendInt(this.getId());
message.appendString("");
message.appendInt(3);
message.appendInt(channel);
message.appendInt(senderCount);
message.appendInt(RoomSpecialTypes.MAX_SENDERS_PER_RECEIVER);
message.appendInt(0);
message.appendInt(this.getType().code);
message.appendInt(0);
message.appendInt(0);
}
@Override
public boolean saveData(WiredSettings settings) {
int[] params = settings.getIntParams();
this.channel = params.length > 0 ? params[0] : 0;
return true;
}
@Override
public String getWiredData() {
return WiredManager.getGson().toJson(new JsonData(channel));
}
@Override
public void loadWiredData(ResultSet set, Room room) throws SQLException {
String wiredData = set.getString("wired_data");
if (wiredData != null && wiredData.startsWith("{")) {
JsonData data = WiredManager.getGson().fromJson(wiredData, JsonData.class);
this.channel = data.channel;
}
}
@Override
public void onPickUp() {
this.channel = 0;
}
static class JsonData {
int channel;
public JsonData() {}
public JsonData(int channel) {
this.channel = channel;
}
}
}
@@ -14,7 +14,9 @@ public enum FurnitureMovementError {
MAX_DIMMERS("${room.error.max_dimmers}"),
MAX_SOUNDFURNI("${room.errors.max_soundfurni}"),
MAX_ITEMS("${room.error.max_furniture}"),
MAX_STICKIES("${room.error.max_stickies}");
MAX_STICKIES("${room.error.max_stickies}"),
MAX_SIGNAL_SENDERS("${room.error.max_signal_senders}"),
MAX_SIGNAL_RECEIVERS("${room.error.max_signal_receivers}");
public final String errorCode;
@@ -14,7 +14,9 @@ import com.eu.habbo.habbohotel.items.interactions.games.freeze.InteractionFreeze
import com.eu.habbo.habbohotel.items.interactions.games.tag.InteractionTagField;
import com.eu.habbo.habbohotel.items.interactions.games.tag.InteractionTagPole;
import com.eu.habbo.habbohotel.items.interactions.pets.*;
import com.eu.habbo.habbohotel.items.interactions.wired.effects.WiredEffectSendSignal;
import com.eu.habbo.habbohotel.items.interactions.wired.extra.WiredBlob;
import com.eu.habbo.habbohotel.items.interactions.wired.triggers.WiredTriggerReceiveSignal;
import com.eu.habbo.habbohotel.permissions.Permission;
import com.eu.habbo.habbohotel.users.Habbo;
import com.eu.habbo.habbohotel.users.HabboInfo;
@@ -1261,6 +1263,16 @@ public class RoomItemManager {
* Places a floor furniture item at a position.
*/
public FurnitureMovementError placeFloorFurniAt(HabboItem item, RoomTile tile, int rotation, Habbo owner) {
RoomSpecialTypes specialTypes = this.room.getRoomSpecialTypes();
if (specialTypes != null) {
if (item instanceof WiredEffectSendSignal && specialTypes.isSignalSenderLimitReached()) {
return FurnitureMovementError.MAX_SIGNAL_SENDERS;
}
if (item instanceof WiredTriggerReceiveSignal && specialTypes.isSignalReceiverLimitReached()) {
return FurnitureMovementError.MAX_SIGNAL_RECEIVERS;
}
}
boolean pluginHelper = false;
if (Emulator.getPluginManager().isRegistered(FurniturePlacedEvent.class, true)) {
FurniturePlacedEvent event = Emulator.getPluginManager()
@@ -21,6 +21,7 @@ import com.eu.habbo.habbohotel.items.interactions.pets.InteractionPetFood;
import com.eu.habbo.habbohotel.items.interactions.pets.InteractionPetToy;
import com.eu.habbo.habbohotel.items.interactions.pets.InteractionPetTree;
import com.eu.habbo.habbohotel.users.HabboItem;
import com.eu.habbo.habbohotel.items.interactions.wired.effects.WiredEffectSendSignal;
import com.eu.habbo.habbohotel.wired.WiredConditionType;
import com.eu.habbo.habbohotel.wired.WiredEffectType;
import com.eu.habbo.habbohotel.wired.WiredTriggerType;
@@ -340,11 +341,46 @@ public class RoomSpecialTypes {
* Adds a wired trigger to the room.
* @param trigger The trigger to add
*/
public static final int MAX_SIGNAL_SENDERS_PER_ROOM = 25;
public static final int MAX_SIGNAL_RECEIVERS_PER_ROOM = 5;
public static final int MAX_SENDERS_PER_RECEIVER = 5;
public boolean isSignalSenderLimitReached() {
Set<InteractionWiredEffect> existing = this.wiredEffects.get(WiredEffectType.SEND_SIGNAL);
return existing != null && existing.size() >= MAX_SIGNAL_SENDERS_PER_ROOM;
}
public boolean isSignalReceiverLimitReached() {
Set<InteractionWiredTrigger> existing = this.wiredTriggers.get(WiredTriggerType.RECEIVE_SIGNAL);
return existing != null && existing.size() >= MAX_SIGNAL_RECEIVERS_PER_ROOM;
}
public int countSendersTargetingReceiver(int receiverItemId, InteractionWiredEffect excludeSender) {
Set<InteractionWiredEffect> senders = this.wiredEffects.get(WiredEffectType.SEND_SIGNAL);
if (senders == null) return 0;
int count = 0;
for (InteractionWiredEffect effect : senders) {
if (excludeSender != null && effect.getId() == excludeSender.getId()) continue;
if (effect instanceof WiredEffectSendSignal) {
WiredEffectSendSignal sender = (WiredEffectSendSignal) effect;
if (sender.hasPickedItem(receiverItemId)) {
count++;
}
}
}
return count;
}
public int countSendersTargetingReceiver(int receiverItemId) {
return countSendersTargetingReceiver(receiverItemId, null);
}
public void addTrigger(InteractionWiredTrigger trigger) {
// Add to type-based index
this.wiredTriggers.computeIfAbsent(trigger.getType(), k -> ConcurrentHashMap.newKeySet())
.add(trigger);
// Add to spatial index
long key = coordinateKey(trigger.getX(), trigger.getY());
this.wiredTriggersByLocation.computeIfAbsent(key, k -> ConcurrentHashMap.newKeySet())
@@ -464,7 +500,7 @@ public class RoomSpecialTypes {
// Add to type-based index
this.wiredEffects.computeIfAbsent(effect.getType(), k -> ConcurrentHashMap.newKeySet())
.add(effect);
// Add to spatial index
long key = coordinateKey(effect.getX(), effect.getY());
this.wiredEffectsByLocation.computeIfAbsent(key, k -> ConcurrentHashMap.newKeySet())
@@ -31,7 +31,8 @@ public enum WiredEffectType {
FURNI_NEIGHBORHOOD_SELECTOR(29),
FURNI_BYTYPE_SELECTOR(30),
USERS_AREA_SELECTOR(31),
USERS_NEIGHBORHOOD_SELECTOR(32);
USERS_NEIGHBORHOOD_SELECTOR(32),
SEND_SIGNAL(33);
public final int code;
@@ -20,7 +20,8 @@ public enum WiredTriggerType {
UNIDLES(11),
CUSTOM(13),
STARTS_DANCING(11),
STOPS_DANCING(11);
STOPS_DANCING(11),
RECEIVE_SIGNAL(15);
public final int code;
@@ -94,6 +94,9 @@ public final class WiredEvent {
/** Team loses a game */
TEAM_LOSES(WiredTriggerType.CUSTOM),
/** Signal received from a Send Signal effect */
SIGNAL_RECEIVED(WiredTriggerType.RECEIVE_SIGNAL),
/** Custom trigger type for plugins */
CUSTOM(WiredTriggerType.CUSTOM);
@@ -137,6 +140,7 @@ public final class WiredEvent {
private final int scoreAdded; // amount added for score achieved events
private final boolean triggeredByEffect; // true if triggered by a wired effect (to prevent loops)
private final int callStackDepth; // recursion depth for trigger stacks effect
private final int signalChannel; // channel for signal routing (0-based)
private final long createdAtMs;
private WiredEvent(Builder builder) {
@@ -151,6 +155,7 @@ public final class WiredEvent {
this.scoreAdded = builder.scoreAdded;
this.triggeredByEffect = builder.triggeredByEffect;
this.callStackDepth = builder.callStackDepth;
this.signalChannel = builder.signalChannel;
this.createdAtMs = builder.createdAtMs;
}
@@ -249,6 +254,10 @@ public final class WiredEvent {
return callStackDepth;
}
public int getSignalChannel() {
return signalChannel;
}
/**
* Get the timestamp when this event was created.
* @return milliseconds since epoch
@@ -303,6 +312,7 @@ public final class WiredEvent {
private int scoreAdded;
private boolean triggeredByEffect;
private int callStackDepth;
private int signalChannel;
private long createdAtMs = System.currentTimeMillis();
private Builder(Type type, Room room) {
@@ -402,6 +412,11 @@ public final class WiredEvent {
return this;
}
public Builder signalChannel(int signalChannel) {
this.signalChannel = signalChannel;
return this;
}
/**
* Set a custom creation timestamp.
* @param createdAtMs milliseconds since epoch