You've already forked Arcturus-Morningstar-Extended
mirror of
https://github.com/duckietm/Arcturus-Morningstar-Extended.git
synced 2026-06-20 15:36:17 +00:00
🆕 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:
@@ -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_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_win", WiredTriggerTeamWins.class));
|
||||||
this.interactionsList.add(new ItemInteraction("wf_trg_game_team_lose", WiredTriggerTeamLoses.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));
|
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_furni_bytype", WiredEffectFurniByType.class));
|
||||||
this.interactionsList.add(new ItemInteraction("wf_slc_users_area", WiredEffectUsersArea.class));
|
this.interactionsList.add(new ItemInteraction("wf_slc_users_area", WiredEffectUsersArea.class));
|
||||||
this.interactionsList.add(new ItemInteraction("wf_slc_users_neighborhood", WiredEffectUsersNeighborhood.class));
|
this.interactionsList.add(new ItemInteraction("wf_slc_users_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_has_furni_on", WiredConditionFurniHaveFurni.class));
|
||||||
this.interactionsList.add(new ItemInteraction("wf_cnd_furnis_hv_avtrs", WiredConditionFurniHaveHabbo.class));
|
this.interactionsList.add(new ItemInteraction("wf_cnd_furnis_hv_avtrs", WiredConditionFurniHaveHabbo.class));
|
||||||
|
|||||||
+350
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+118
@@ -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_DIMMERS("${room.error.max_dimmers}"),
|
||||||
MAX_SOUNDFURNI("${room.errors.max_soundfurni}"),
|
MAX_SOUNDFURNI("${room.errors.max_soundfurni}"),
|
||||||
MAX_ITEMS("${room.error.max_furniture}"),
|
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;
|
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.InteractionTagField;
|
||||||
import com.eu.habbo.habbohotel.items.interactions.games.tag.InteractionTagPole;
|
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.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.extra.WiredBlob;
|
||||||
|
import com.eu.habbo.habbohotel.items.interactions.wired.triggers.WiredTriggerReceiveSignal;
|
||||||
import com.eu.habbo.habbohotel.permissions.Permission;
|
import com.eu.habbo.habbohotel.permissions.Permission;
|
||||||
import com.eu.habbo.habbohotel.users.Habbo;
|
import com.eu.habbo.habbohotel.users.Habbo;
|
||||||
import com.eu.habbo.habbohotel.users.HabboInfo;
|
import com.eu.habbo.habbohotel.users.HabboInfo;
|
||||||
@@ -1261,6 +1263,16 @@ public class RoomItemManager {
|
|||||||
* Places a floor furniture item at a position.
|
* Places a floor furniture item at a position.
|
||||||
*/
|
*/
|
||||||
public FurnitureMovementError placeFloorFurniAt(HabboItem item, RoomTile tile, int rotation, Habbo owner) {
|
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;
|
boolean pluginHelper = false;
|
||||||
if (Emulator.getPluginManager().isRegistered(FurniturePlacedEvent.class, true)) {
|
if (Emulator.getPluginManager().isRegistered(FurniturePlacedEvent.class, true)) {
|
||||||
FurniturePlacedEvent event = Emulator.getPluginManager()
|
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.InteractionPetToy;
|
||||||
import com.eu.habbo.habbohotel.items.interactions.pets.InteractionPetTree;
|
import com.eu.habbo.habbohotel.items.interactions.pets.InteractionPetTree;
|
||||||
import com.eu.habbo.habbohotel.users.HabboItem;
|
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.WiredConditionType;
|
||||||
import com.eu.habbo.habbohotel.wired.WiredEffectType;
|
import com.eu.habbo.habbohotel.wired.WiredEffectType;
|
||||||
import com.eu.habbo.habbohotel.wired.WiredTriggerType;
|
import com.eu.habbo.habbohotel.wired.WiredTriggerType;
|
||||||
@@ -340,6 +341,41 @@ public class RoomSpecialTypes {
|
|||||||
* Adds a wired trigger to the room.
|
* Adds a wired trigger to the room.
|
||||||
* @param trigger The trigger to add
|
* @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) {
|
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())
|
||||||
|
|||||||
@@ -31,7 +31,8 @@ public enum WiredEffectType {
|
|||||||
FURNI_NEIGHBORHOOD_SELECTOR(29),
|
FURNI_NEIGHBORHOOD_SELECTOR(29),
|
||||||
FURNI_BYTYPE_SELECTOR(30),
|
FURNI_BYTYPE_SELECTOR(30),
|
||||||
USERS_AREA_SELECTOR(31),
|
USERS_AREA_SELECTOR(31),
|
||||||
USERS_NEIGHBORHOOD_SELECTOR(32);
|
USERS_NEIGHBORHOOD_SELECTOR(32),
|
||||||
|
SEND_SIGNAL(33);
|
||||||
|
|
||||||
public final int code;
|
public final int code;
|
||||||
|
|
||||||
|
|||||||
@@ -20,7 +20,8 @@ public enum WiredTriggerType {
|
|||||||
UNIDLES(11),
|
UNIDLES(11),
|
||||||
CUSTOM(13),
|
CUSTOM(13),
|
||||||
STARTS_DANCING(11),
|
STARTS_DANCING(11),
|
||||||
STOPS_DANCING(11);
|
STOPS_DANCING(11),
|
||||||
|
RECEIVE_SIGNAL(15);
|
||||||
|
|
||||||
public final int code;
|
public final int code;
|
||||||
|
|
||||||
|
|||||||
@@ -94,6 +94,9 @@ public final class WiredEvent {
|
|||||||
/** Team loses a game */
|
/** Team loses a game */
|
||||||
TEAM_LOSES(WiredTriggerType.CUSTOM),
|
TEAM_LOSES(WiredTriggerType.CUSTOM),
|
||||||
|
|
||||||
|
/** Signal received from a Send Signal effect */
|
||||||
|
SIGNAL_RECEIVED(WiredTriggerType.RECEIVE_SIGNAL),
|
||||||
|
|
||||||
/** Custom trigger type for plugins */
|
/** Custom trigger type for plugins */
|
||||||
CUSTOM(WiredTriggerType.CUSTOM);
|
CUSTOM(WiredTriggerType.CUSTOM);
|
||||||
|
|
||||||
@@ -137,6 +140,7 @@ public final class WiredEvent {
|
|||||||
private final int scoreAdded; // amount added for score achieved events
|
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 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 callStackDepth; // recursion depth for trigger stacks effect
|
||||||
|
private final int signalChannel; // channel for signal routing (0-based)
|
||||||
private final long createdAtMs;
|
private final long createdAtMs;
|
||||||
|
|
||||||
private WiredEvent(Builder builder) {
|
private WiredEvent(Builder builder) {
|
||||||
@@ -151,6 +155,7 @@ public final class WiredEvent {
|
|||||||
this.scoreAdded = builder.scoreAdded;
|
this.scoreAdded = builder.scoreAdded;
|
||||||
this.triggeredByEffect = builder.triggeredByEffect;
|
this.triggeredByEffect = builder.triggeredByEffect;
|
||||||
this.callStackDepth = builder.callStackDepth;
|
this.callStackDepth = builder.callStackDepth;
|
||||||
|
this.signalChannel = builder.signalChannel;
|
||||||
this.createdAtMs = builder.createdAtMs;
|
this.createdAtMs = builder.createdAtMs;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -249,6 +254,10 @@ public final class WiredEvent {
|
|||||||
return callStackDepth;
|
return callStackDepth;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int getSignalChannel() {
|
||||||
|
return signalChannel;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the timestamp when this event was created.
|
* Get the timestamp when this event was created.
|
||||||
* @return milliseconds since epoch
|
* @return milliseconds since epoch
|
||||||
@@ -303,6 +312,7 @@ public final class WiredEvent {
|
|||||||
private int scoreAdded;
|
private int scoreAdded;
|
||||||
private boolean triggeredByEffect;
|
private boolean triggeredByEffect;
|
||||||
private int callStackDepth;
|
private int callStackDepth;
|
||||||
|
private int signalChannel;
|
||||||
private long createdAtMs = System.currentTimeMillis();
|
private long createdAtMs = System.currentTimeMillis();
|
||||||
|
|
||||||
private Builder(Type type, Room room) {
|
private Builder(Type type, Room room) {
|
||||||
@@ -402,6 +412,11 @@ public final class WiredEvent {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Builder signalChannel(int signalChannel) {
|
||||||
|
this.signalChannel = signalChannel;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set a custom creation timestamp.
|
* Set a custom creation timestamp.
|
||||||
* @param createdAtMs milliseconds since epoch
|
* @param createdAtMs milliseconds since epoch
|
||||||
|
|||||||
Reference in New Issue
Block a user