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
🆕 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_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));
|
||||
|
||||
+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_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
|
||||
|
||||
Reference in New Issue
Block a user