You've already forked Arcturus-Morningstar-Extended
mirror of
https://github.com/duckietm/Arcturus-Morningstar-Extended.git
synced 2026-06-19 23:16:19 +00:00
@@ -60,6 +60,7 @@ import com.eu.habbo.habbohotel.items.interactions.wired.extra.WiredExtraMovePhys
|
||||
import com.eu.habbo.habbohotel.items.interactions.wired.extra.WiredExtraMoveNoAnimation;
|
||||
import com.eu.habbo.habbohotel.items.interactions.wired.extra.WiredExtraOrEval;
|
||||
import com.eu.habbo.habbohotel.items.interactions.wired.extra.WiredExtraRandom;
|
||||
import com.eu.habbo.habbohotel.items.interactions.wired.extra.WiredExtraTextOutputUsername;
|
||||
import com.eu.habbo.habbohotel.items.interactions.wired.extra.WiredExtraUnseen;
|
||||
import com.eu.habbo.habbohotel.items.interactions.wired.selector.*;
|
||||
import com.eu.habbo.habbohotel.items.interactions.wired.triggers.*;
|
||||
@@ -353,6 +354,7 @@ public class ItemManager {
|
||||
this.interactionsList.add(new ItemInteraction("wf_xtra_mov_physics", WiredExtraMovePhysics.class));
|
||||
this.interactionsList.add(new ItemInteraction("wf_xtra_exec_in_order", WiredExtraExecuteInOrder.class));
|
||||
this.interactionsList.add(new ItemInteraction("wf_xtra_execution_limit", WiredExtraExecutionLimit.class));
|
||||
this.interactionsList.add(new ItemInteraction("wf_xtra_text_output_username", WiredExtraTextOutputUsername.class));
|
||||
|
||||
|
||||
this.interactionsList.add(new ItemInteraction("wf_highscore", InteractionWiredHighscore.class));
|
||||
|
||||
+4
-2
@@ -5,6 +5,7 @@ import com.eu.habbo.habbohotel.items.Item;
|
||||
import com.eu.habbo.habbohotel.rooms.Room;
|
||||
import com.eu.habbo.habbohotel.users.Habbo;
|
||||
import com.eu.habbo.habbohotel.wired.core.WiredContext;
|
||||
import com.eu.habbo.habbohotel.wired.core.WiredTextPlaceholderUtil;
|
||||
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
@@ -26,10 +27,11 @@ public class WiredEffectAlert extends WiredEffectWhisper {
|
||||
Habbo habbo = room.getHabbo(unit);
|
||||
if (habbo == null) continue;
|
||||
|
||||
habbo.alert(this.message
|
||||
String message = this.message
|
||||
.replace("%online%", Emulator.getGameEnvironment().getHabboManager().getOnlineCount() + "")
|
||||
.replace("%username%", habbo.getHabboInfo().getUsername())
|
||||
.replace("%roomsloaded%", Emulator.getGameEnvironment().getRoomManager().loadedRoomsCount() + ""));
|
||||
.replace("%roomsloaded%", Emulator.getGameEnvironment().getRoomManager().loadedRoomsCount() + "");
|
||||
habbo.alert(WiredTextPlaceholderUtil.applyUsernamePlaceholders(ctx, message));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+4
-1
@@ -13,6 +13,7 @@ import com.eu.habbo.habbohotel.wired.WiredEffectType;
|
||||
import com.eu.habbo.habbohotel.wired.core.WiredBotSourceUtil;
|
||||
import com.eu.habbo.habbohotel.wired.core.WiredManager;
|
||||
import com.eu.habbo.habbohotel.wired.core.WiredContext;
|
||||
import com.eu.habbo.habbohotel.wired.core.WiredTextPlaceholderUtil;
|
||||
import com.eu.habbo.messages.ServerMessage;
|
||||
import com.eu.habbo.messages.incoming.wired.WiredSaveException;
|
||||
|
||||
@@ -111,6 +112,8 @@ public class WiredEffectBotTalk extends InteractionWiredEffect {
|
||||
.replace(Emulator.getTexts().getValue("wired.variable.user_count", "%user_count%"), room.getUserCount() + "");
|
||||
}
|
||||
|
||||
message = WiredTextPlaceholderUtil.applyUsernamePlaceholders(ctx, message);
|
||||
|
||||
List<Bot> bots = WiredBotSourceUtil.resolveBots(ctx, room, this.botSource, this.botName);
|
||||
|
||||
for (Bot bot : bots) {
|
||||
@@ -177,7 +180,7 @@ public class WiredEffectBotTalk extends InteractionWiredEffect {
|
||||
|
||||
@Override
|
||||
public boolean requiresTriggeringUser() {
|
||||
return WiredBotSourceUtil.requiresTriggeringUser(this.botSource);
|
||||
return WiredBotSourceUtil.requiresTriggeringUser(this.botSource) || WiredTextPlaceholderUtil.requiresActor(this.getRoom(), this);
|
||||
}
|
||||
|
||||
public int getMode() {
|
||||
|
||||
+3
-1
@@ -15,6 +15,7 @@ import com.eu.habbo.habbohotel.wired.core.WiredBotSourceUtil;
|
||||
import com.eu.habbo.habbohotel.wired.core.WiredManager;
|
||||
import com.eu.habbo.habbohotel.wired.core.WiredContext;
|
||||
import com.eu.habbo.habbohotel.wired.core.WiredSourceUtil;
|
||||
import com.eu.habbo.habbohotel.wired.core.WiredTextPlaceholderUtil;
|
||||
import com.eu.habbo.messages.ServerMessage;
|
||||
import com.eu.habbo.messages.incoming.wired.WiredSaveException;
|
||||
import gnu.trove.procedure.TObjectProcedure;
|
||||
@@ -136,6 +137,7 @@ public class WiredEffectBotTalkToHabbo extends InteractionWiredEffect {
|
||||
.replace(Emulator.getTexts().getValue("wired.variable.item_count", "%item_count%"), room.itemCount() + "")
|
||||
.replace(Emulator.getTexts().getValue("wired.variable.roomname", "%roomname%"), room.getName())
|
||||
.replace(Emulator.getTexts().getValue("wired.variable.user_count", "%user_count%"), room.getUserCount() + "");
|
||||
m = WiredTextPlaceholderUtil.applyUsernamePlaceholders(ctx, m);
|
||||
|
||||
for (Bot bot : bots) {
|
||||
String botMessage = m.replace(Emulator.getTexts().getValue("wired.variable.name", "%name%"), bot.getName());
|
||||
@@ -203,7 +205,7 @@ public class WiredEffectBotTalkToHabbo extends InteractionWiredEffect {
|
||||
|
||||
@Override
|
||||
public boolean requiresTriggeringUser() {
|
||||
return this.userSource == WiredSourceUtil.SOURCE_TRIGGER || WiredBotSourceUtil.requiresTriggeringUser(this.botSource);
|
||||
return this.userSource == WiredSourceUtil.SOURCE_TRIGGER || WiredBotSourceUtil.requiresTriggeringUser(this.botSource) || WiredTextPlaceholderUtil.requiresActor(this.getRoom(), this);
|
||||
}
|
||||
|
||||
static class JsonData {
|
||||
|
||||
+6
-3
@@ -16,6 +16,7 @@ import com.eu.habbo.habbohotel.wired.WiredEffectType;
|
||||
import com.eu.habbo.habbohotel.wired.core.WiredManager;
|
||||
import com.eu.habbo.habbohotel.wired.core.WiredContext;
|
||||
import com.eu.habbo.habbohotel.wired.core.WiredSourceUtil;
|
||||
import com.eu.habbo.habbohotel.wired.core.WiredTextPlaceholderUtil;
|
||||
import com.eu.habbo.messages.ServerMessage;
|
||||
import com.eu.habbo.messages.incoming.wired.WiredSaveException;
|
||||
import com.eu.habbo.messages.outgoing.rooms.users.RoomUserWhisperComposer;
|
||||
@@ -70,8 +71,10 @@ public class WiredEffectKickHabbo extends InteractionWiredEffect {
|
||||
|
||||
room.giveEffect(habbo, 4, 2);
|
||||
|
||||
if (!this.message.isEmpty())
|
||||
habbo.getClient().sendResponse(new RoomUserWhisperComposer(new RoomChatMessage(this.message, habbo, habbo, RoomChatMessageBubbles.ALERT)));
|
||||
if (!this.message.isEmpty()) {
|
||||
String message = WiredTextPlaceholderUtil.applyUsernamePlaceholders(ctx, this.message);
|
||||
habbo.getClient().sendResponse(new RoomUserWhisperComposer(new RoomChatMessage(message, habbo, habbo, RoomChatMessageBubbles.ALERT)));
|
||||
}
|
||||
|
||||
Emulator.getThreading().run(new RoomUnitKick(habbo, room, true), 2000);
|
||||
}
|
||||
@@ -183,7 +186,7 @@ public class WiredEffectKickHabbo extends InteractionWiredEffect {
|
||||
|
||||
@Override
|
||||
public boolean requiresTriggeringUser() {
|
||||
return this.userSource == WiredSourceUtil.SOURCE_TRIGGER;
|
||||
return this.userSource == WiredSourceUtil.SOURCE_TRIGGER || WiredTextPlaceholderUtil.requiresActor(this.getRoom(), this);
|
||||
}
|
||||
|
||||
static class JsonData {
|
||||
|
||||
+5
-2
@@ -14,6 +14,7 @@ import com.eu.habbo.habbohotel.wired.WiredEffectType;
|
||||
import com.eu.habbo.habbohotel.wired.core.WiredContext;
|
||||
import com.eu.habbo.habbohotel.wired.core.WiredManager;
|
||||
import com.eu.habbo.habbohotel.wired.core.WiredSourceUtil;
|
||||
import com.eu.habbo.habbohotel.wired.core.WiredTextPlaceholderUtil;
|
||||
import com.eu.habbo.messages.ServerMessage;
|
||||
import com.eu.habbo.messages.incoming.wired.WiredSaveException;
|
||||
import com.eu.habbo.messages.outgoing.rooms.users.RoomUserWhisperComposer;
|
||||
@@ -78,7 +79,9 @@ public class WiredEffectMuteHabbo extends InteractionWiredEffect {
|
||||
|
||||
room.muteHabbo(habbo, Math.max(1, this.length));
|
||||
|
||||
habbo.getClient().sendResponse(new RoomUserWhisperComposer(new RoomChatMessage(this.message.replace("%user%", habbo.getHabboInfo().getUsername()).replace("%online_count%", Emulator.getGameEnvironment().getHabboManager().getOnlineCount() + "").replace("%room_count%", Emulator.getGameEnvironment().getRoomManager().getActiveRooms().size() + ""), habbo, habbo, RoomChatMessageBubbles.WIRED)));
|
||||
String message = this.message.replace("%user%", habbo.getHabboInfo().getUsername()).replace("%online_count%", Emulator.getGameEnvironment().getHabboManager().getOnlineCount() + "").replace("%room_count%", Emulator.getGameEnvironment().getRoomManager().getActiveRooms().size() + "");
|
||||
message = WiredTextPlaceholderUtil.applyUsernamePlaceholders(ctx, message);
|
||||
habbo.getClient().sendResponse(new RoomUserWhisperComposer(new RoomChatMessage(message, habbo, habbo, RoomChatMessageBubbles.WIRED)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -137,7 +140,7 @@ public class WiredEffectMuteHabbo extends InteractionWiredEffect {
|
||||
|
||||
@Override
|
||||
public boolean requiresTriggeringUser() {
|
||||
return this.userSource == WiredSourceUtil.SOURCE_TRIGGER;
|
||||
return this.userSource == WiredSourceUtil.SOURCE_TRIGGER || WiredTextPlaceholderUtil.requiresActor(this.getRoom(), this);
|
||||
}
|
||||
|
||||
static class JsonData {
|
||||
|
||||
+3
-1
@@ -13,6 +13,7 @@ import com.eu.habbo.habbohotel.wired.WiredEffectType;
|
||||
import com.eu.habbo.habbohotel.wired.core.WiredManager;
|
||||
import com.eu.habbo.habbohotel.wired.core.WiredContext;
|
||||
import com.eu.habbo.habbohotel.wired.core.WiredSourceUtil;
|
||||
import com.eu.habbo.habbohotel.wired.core.WiredTextPlaceholderUtil;
|
||||
import com.eu.habbo.messages.ServerMessage;
|
||||
import com.eu.habbo.messages.incoming.wired.WiredSaveException;
|
||||
import com.eu.habbo.messages.outgoing.rooms.users.RoomUserWhisperComposer;
|
||||
@@ -105,6 +106,7 @@ public class WiredEffectWhisper extends InteractionWiredEffect {
|
||||
if (habbo == null) continue;
|
||||
|
||||
String msg = this.message.replace("%user%", habbo.getHabboInfo().getUsername()).replace("%online_count%", Emulator.getGameEnvironment().getHabboManager().getOnlineCount() + "").replace("%room_count%", Emulator.getGameEnvironment().getRoomManager().getActiveRooms().size() + "");
|
||||
msg = WiredTextPlaceholderUtil.applyUsernamePlaceholders(ctx, msg);
|
||||
habbo.getClient().sendResponse(new RoomUserWhisperComposer(new RoomChatMessage(msg, habbo, habbo, RoomChatMessageBubbles.WIRED)));
|
||||
|
||||
if (habbo.getRoomUnit().isIdle()) {
|
||||
@@ -162,7 +164,7 @@ public class WiredEffectWhisper extends InteractionWiredEffect {
|
||||
|
||||
@Override
|
||||
public boolean requiresTriggeringUser() {
|
||||
return this.userSource == WiredSourceUtil.SOURCE_TRIGGER;
|
||||
return (this.userSource == WiredSourceUtil.SOURCE_TRIGGER) || WiredTextPlaceholderUtil.requiresActor(this.getRoom(), this);
|
||||
}
|
||||
|
||||
static class JsonData {
|
||||
|
||||
+253
-2
@@ -1,21 +1,48 @@
|
||||
package com.eu.habbo.habbohotel.items.interactions.wired.extra;
|
||||
|
||||
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.InteractionWiredExtra;
|
||||
import com.eu.habbo.habbohotel.items.interactions.wired.WiredSettings;
|
||||
import com.eu.habbo.habbohotel.rooms.Room;
|
||||
import com.eu.habbo.habbohotel.rooms.RoomUnit;
|
||||
import com.eu.habbo.habbohotel.users.HabboItem;
|
||||
import com.eu.habbo.habbohotel.wired.core.WiredManager;
|
||||
import com.eu.habbo.habbohotel.wired.core.WiredSourceUtil;
|
||||
import com.eu.habbo.messages.ServerMessage;
|
||||
import gnu.trove.set.hash.THashSet;
|
||||
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class WiredExtraOrEval extends InteractionWiredExtra {
|
||||
public static final int CODE = 66;
|
||||
public static final int MODE_ALL = 0;
|
||||
public static final int MODE_AT_LEAST_ONE = 1;
|
||||
public static final int MODE_NOT_ALL = 2;
|
||||
public static final int MODE_NONE = 3;
|
||||
public static final int MODE_LESS_THAN = 4;
|
||||
public static final int MODE_EXACTLY = 5;
|
||||
public static final int MODE_MORE_THAN = 6;
|
||||
public static final int MIN_COMPARE_VALUE = 0;
|
||||
public static final int MAX_COMPARE_VALUE = 100;
|
||||
|
||||
private final THashSet<HabboItem> items;
|
||||
private int evaluationMode = MODE_ALL;
|
||||
private int furniSource = WiredSourceUtil.SOURCE_TRIGGER;
|
||||
private int compareValue = 1;
|
||||
|
||||
public WiredExtraOrEval(ResultSet set, Item baseItem) throws SQLException {
|
||||
super(set, baseItem);
|
||||
this.items = new THashSet<>();
|
||||
}
|
||||
|
||||
public WiredExtraOrEval(int id, int userId, Item item, String extradata, int limitedStack, int limitedSells) {
|
||||
super(id, userId, item, extradata, limitedStack, limitedSells);
|
||||
this.items = new THashSet<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -23,28 +50,252 @@ public class WiredExtraOrEval extends InteractionWiredExtra {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean saveData(WiredSettings settings, GameClient gameClient) {
|
||||
int[] params = settings.getIntParams();
|
||||
|
||||
this.evaluationMode = normalizeEvaluationMode((params.length > 0) ? params[0] : MODE_ALL);
|
||||
this.furniSource = normalizeFurniSource((params.length > 1) ? params[1] : WiredSourceUtil.SOURCE_TRIGGER);
|
||||
this.compareValue = normalizeCompareValue((params.length > 2) ? params[2] : this.compareValue);
|
||||
this.items.clear();
|
||||
|
||||
if (this.furniSource != WiredSourceUtil.SOURCE_SELECTED) {
|
||||
return true;
|
||||
}
|
||||
|
||||
Room room = Emulator.getGameEnvironment().getRoomManager().getRoom(this.getRoomId());
|
||||
if (room == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (settings.getFurniIds().length > Emulator.getConfig().getInt("hotel.wired.furni.selection.count")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int itemId : settings.getFurniIds()) {
|
||||
HabboItem item = room.getHabboItem(itemId);
|
||||
|
||||
if (isSelectableConditionOrExtra(item)) {
|
||||
this.items.add(item);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getWiredData() {
|
||||
return null;
|
||||
return WiredManager.getGson().toJson(new JsonData(
|
||||
this.evaluationMode,
|
||||
this.furniSource,
|
||||
this.compareValue,
|
||||
this.items.stream().map(HabboItem::getId).collect(Collectors.toList())
|
||||
));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void serializeWiredData(ServerMessage message, Room room) {
|
||||
this.refresh(room);
|
||||
|
||||
message.appendBoolean(false);
|
||||
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("");
|
||||
message.appendInt(3);
|
||||
message.appendInt(this.evaluationMode);
|
||||
message.appendInt(this.furniSource);
|
||||
message.appendInt(this.compareValue);
|
||||
message.appendInt(0);
|
||||
message.appendInt(CODE);
|
||||
message.appendInt(0);
|
||||
message.appendInt(0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadWiredData(ResultSet set, Room room) throws SQLException {
|
||||
this.onPickUp();
|
||||
|
||||
String wiredData = set.getString("wired_data");
|
||||
if (wiredData == null || wiredData.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (wiredData.startsWith("{")) {
|
||||
JsonData data = WiredManager.getGson().fromJson(wiredData, JsonData.class);
|
||||
|
||||
if (data != null) {
|
||||
this.evaluationMode = normalizeEvaluationMode(data.evaluationMode);
|
||||
this.furniSource = normalizeFurniSource(data.furniSource);
|
||||
this.compareValue = normalizeCompareValue(data.compareValue);
|
||||
|
||||
if (data.itemIds != null) {
|
||||
for (Integer itemId : data.itemIds) {
|
||||
HabboItem item = room.getHabboItem(itemId);
|
||||
|
||||
if (isSelectableConditionOrExtra(item)) {
|
||||
this.items.add(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
String[] legacyData = wiredData.split("[;\t]");
|
||||
|
||||
try {
|
||||
if (legacyData.length > 0) {
|
||||
this.evaluationMode = normalizeEvaluationMode(Integer.parseInt(legacyData[0]));
|
||||
}
|
||||
|
||||
if (legacyData.length > 1) {
|
||||
this.furniSource = normalizeFurniSource(Integer.parseInt(legacyData[1]));
|
||||
}
|
||||
|
||||
if (legacyData.length > 2) {
|
||||
this.compareValue = normalizeCompareValue(Integer.parseInt(legacyData[2]));
|
||||
}
|
||||
} catch (NumberFormatException ignored) {
|
||||
this.evaluationMode = MODE_ALL;
|
||||
this.furniSource = WiredSourceUtil.SOURCE_TRIGGER;
|
||||
this.compareValue = 1;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPickUp() {
|
||||
|
||||
this.items.clear();
|
||||
this.evaluationMode = MODE_ALL;
|
||||
this.furniSource = WiredSourceUtil.SOURCE_TRIGGER;
|
||||
this.compareValue = 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onWalk(RoomUnit roomUnit, Room room, Object[] objects) throws Exception {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasConfiguration() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public int getEvaluationMode() {
|
||||
return this.evaluationMode;
|
||||
}
|
||||
|
||||
public int getFurniSource() {
|
||||
return this.furniSource;
|
||||
}
|
||||
|
||||
public int getCompareValue() {
|
||||
return this.compareValue;
|
||||
}
|
||||
|
||||
private void refresh(Room room) {
|
||||
THashSet<HabboItem> remove = new THashSet<>();
|
||||
|
||||
for (HabboItem item : this.items) {
|
||||
HabboItem roomItem = room.getHabboItem(item.getId());
|
||||
|
||||
if (!isSelectableConditionOrExtra(roomItem)) {
|
||||
remove.add(item);
|
||||
}
|
||||
}
|
||||
|
||||
for (HabboItem item : remove) {
|
||||
this.items.remove(item);
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean matchesMode(int evaluationMode, int matchedRequirements, int totalRequirements, int compareValue) {
|
||||
if (totalRequirements <= 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
switch (normalizeEvaluationMode(evaluationMode)) {
|
||||
case MODE_AT_LEAST_ONE:
|
||||
return matchedRequirements > 0;
|
||||
case MODE_NOT_ALL:
|
||||
return matchedRequirements > 0 && matchedRequirements < totalRequirements;
|
||||
case MODE_NONE:
|
||||
return matchedRequirements == 0;
|
||||
case MODE_LESS_THAN:
|
||||
return matchedRequirements < normalizeCompareValue(compareValue);
|
||||
case MODE_EXACTLY:
|
||||
return matchedRequirements == normalizeCompareValue(compareValue);
|
||||
case MODE_MORE_THAN:
|
||||
return matchedRequirements > normalizeCompareValue(compareValue);
|
||||
case MODE_ALL:
|
||||
default:
|
||||
return matchedRequirements >= totalRequirements;
|
||||
}
|
||||
}
|
||||
|
||||
private static int normalizeEvaluationMode(int value) {
|
||||
switch (value) {
|
||||
case MODE_ALL:
|
||||
case MODE_AT_LEAST_ONE:
|
||||
case MODE_NOT_ALL:
|
||||
case MODE_NONE:
|
||||
case MODE_LESS_THAN:
|
||||
case MODE_EXACTLY:
|
||||
case MODE_MORE_THAN:
|
||||
return value;
|
||||
default:
|
||||
return MODE_ALL;
|
||||
}
|
||||
}
|
||||
|
||||
private static int normalizeCompareValue(int value) {
|
||||
return Math.max(MIN_COMPARE_VALUE, Math.min(MAX_COMPARE_VALUE, value));
|
||||
}
|
||||
|
||||
private static int normalizeFurniSource(int value) {
|
||||
switch (value) {
|
||||
case WiredSourceUtil.SOURCE_SELECTED:
|
||||
case WiredSourceUtil.SOURCE_SELECTOR:
|
||||
case WiredSourceUtil.SOURCE_SIGNAL:
|
||||
case WiredSourceUtil.SOURCE_TRIGGER:
|
||||
return value;
|
||||
default:
|
||||
return WiredSourceUtil.SOURCE_TRIGGER;
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean isSelectableConditionOrExtra(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 normalizedInteraction = interaction.toLowerCase();
|
||||
return normalizedInteraction.startsWith("wf_cnd_") || normalizedInteraction.startsWith("wf_xtra_");
|
||||
}
|
||||
|
||||
static class JsonData {
|
||||
int evaluationMode;
|
||||
int furniSource;
|
||||
int compareValue;
|
||||
List<Integer> itemIds;
|
||||
|
||||
JsonData(int evaluationMode, int furniSource, int compareValue, List<Integer> itemIds) {
|
||||
this.evaluationMode = evaluationMode;
|
||||
this.furniSource = furniSource;
|
||||
this.compareValue = compareValue;
|
||||
this.itemIds = itemIds;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+212
@@ -0,0 +1,212 @@
|
||||
package com.eu.habbo.habbohotel.items.interactions.wired.extra;
|
||||
|
||||
import com.eu.habbo.habbohotel.gameclients.GameClient;
|
||||
import com.eu.habbo.habbohotel.items.Item;
|
||||
import com.eu.habbo.habbohotel.items.interactions.InteractionWiredExtra;
|
||||
import com.eu.habbo.habbohotel.items.interactions.wired.WiredSettings;
|
||||
import com.eu.habbo.habbohotel.rooms.Room;
|
||||
import com.eu.habbo.habbohotel.rooms.RoomUnit;
|
||||
import com.eu.habbo.habbohotel.wired.core.WiredManager;
|
||||
import com.eu.habbo.habbohotel.wired.core.WiredSourceUtil;
|
||||
import com.eu.habbo.messages.ServerMessage;
|
||||
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public class WiredExtraTextOutputUsername extends InteractionWiredExtra {
|
||||
public static final int CODE = 67;
|
||||
public static final int TYPE_SINGLE = 1;
|
||||
public static final int TYPE_MULTIPLE = 2;
|
||||
public static final String DEFAULT_PLACEHOLDER_NAME = "";
|
||||
public static final String DEFAULT_DELIMITER = ", ";
|
||||
public static final int MAX_PLACEHOLDER_NAME_LENGTH = 32;
|
||||
public static final int MAX_DELIMITER_LENGTH = 16;
|
||||
|
||||
private static final Pattern WRAPPED_PLACEHOLDER_PATTERN = Pattern.compile("^\\$\\((.*)\\)$");
|
||||
|
||||
private String placeholderName = DEFAULT_PLACEHOLDER_NAME;
|
||||
private int placeholderType = TYPE_SINGLE;
|
||||
private String delimiter = DEFAULT_DELIMITER;
|
||||
private int userSource = WiredSourceUtil.SOURCE_TRIGGER;
|
||||
|
||||
public WiredExtraTextOutputUsername(ResultSet set, Item baseItem) throws SQLException {
|
||||
super(set, baseItem);
|
||||
}
|
||||
|
||||
public WiredExtraTextOutputUsername(int id, int userId, Item item, String extradata, int limitedStack, int limitedSells) {
|
||||
super(id, userId, item, extradata, limitedStack, limitedSells);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean execute(RoomUnit roomUnit, Room room, Object[] stuff) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean saveData(WiredSettings settings, GameClient gameClient) {
|
||||
int[] intParams = settings.getIntParams();
|
||||
String[] stringData = splitStringData(settings.getStringParam());
|
||||
|
||||
this.placeholderType = normalizePlaceholderType((intParams.length > 0) ? intParams[0] : TYPE_SINGLE);
|
||||
this.userSource = normalizeUserSource((intParams.length > 1) ? intParams[1] : WiredSourceUtil.SOURCE_TRIGGER);
|
||||
this.placeholderName = normalizePlaceholderName(stringData[0]);
|
||||
this.delimiter = normalizeDelimiter(stringData[1]);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getWiredData() {
|
||||
return WiredManager.getGson().toJson(new JsonData(this.placeholderName, this.placeholderType, this.delimiter, this.userSource));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void serializeWiredData(ServerMessage message, Room room) {
|
||||
message.appendBoolean(false);
|
||||
message.appendInt(0);
|
||||
message.appendInt(0);
|
||||
message.appendInt(this.getBaseItem().getSpriteId());
|
||||
message.appendInt(this.getId());
|
||||
message.appendString(this.placeholderName + "\t" + this.delimiter);
|
||||
message.appendInt(2);
|
||||
message.appendInt(this.placeholderType);
|
||||
message.appendInt(this.userSource);
|
||||
message.appendInt(0);
|
||||
message.appendInt(CODE);
|
||||
message.appendInt(0);
|
||||
message.appendInt(0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadWiredData(ResultSet set, Room room) throws SQLException {
|
||||
this.onPickUp();
|
||||
|
||||
String wiredData = set.getString("wired_data");
|
||||
if (wiredData == null || wiredData.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (wiredData.startsWith("{")) {
|
||||
JsonData data = WiredManager.getGson().fromJson(wiredData, JsonData.class);
|
||||
|
||||
if (data != null) {
|
||||
this.placeholderName = normalizePlaceholderName(data.placeholderName);
|
||||
this.placeholderType = normalizePlaceholderType(data.placeholderType);
|
||||
this.delimiter = normalizeDelimiter(data.delimiter);
|
||||
this.userSource = normalizeUserSource(data.userSource);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
String[] legacyData = splitStringData(wiredData);
|
||||
this.placeholderName = normalizePlaceholderName(legacyData[0]);
|
||||
this.delimiter = normalizeDelimiter(legacyData[1]);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPickUp() {
|
||||
this.placeholderName = DEFAULT_PLACEHOLDER_NAME;
|
||||
this.placeholderType = TYPE_SINGLE;
|
||||
this.delimiter = DEFAULT_DELIMITER;
|
||||
this.userSource = WiredSourceUtil.SOURCE_TRIGGER;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onWalk(RoomUnit roomUnit, Room room, Object[] objects) throws Exception {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasConfiguration() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public String getPlaceholderName() {
|
||||
return this.placeholderName;
|
||||
}
|
||||
|
||||
public String getPlaceholderToken() {
|
||||
return this.placeholderName.isEmpty() ? "" : "$(" + this.placeholderName + ")";
|
||||
}
|
||||
|
||||
public int getPlaceholderType() {
|
||||
return this.placeholderType;
|
||||
}
|
||||
|
||||
public String getDelimiter() {
|
||||
return this.delimiter;
|
||||
}
|
||||
|
||||
public int getUserSource() {
|
||||
return this.userSource;
|
||||
}
|
||||
|
||||
private static String[] splitStringData(String value) {
|
||||
if (value == null) {
|
||||
return new String[] { DEFAULT_PLACEHOLDER_NAME, DEFAULT_DELIMITER };
|
||||
}
|
||||
|
||||
String[] parts = value.split("\t", -1);
|
||||
|
||||
if (parts.length <= 1) {
|
||||
return new String[] { value, DEFAULT_DELIMITER };
|
||||
}
|
||||
|
||||
return new String[] { parts[0], parts[1] };
|
||||
}
|
||||
|
||||
private static int normalizePlaceholderType(int value) {
|
||||
return (value == TYPE_MULTIPLE) ? TYPE_MULTIPLE : TYPE_SINGLE;
|
||||
}
|
||||
|
||||
private static String normalizePlaceholderName(String value) {
|
||||
if (value == null) {
|
||||
return DEFAULT_PLACEHOLDER_NAME;
|
||||
}
|
||||
|
||||
String normalized = value.trim().replace("\t", "").replace("\r", "").replace("\n", "");
|
||||
if (WRAPPED_PLACEHOLDER_PATTERN.matcher(normalized).matches()) {
|
||||
normalized = normalized.substring(2, normalized.length() - 1).trim();
|
||||
}
|
||||
|
||||
if (normalized.length() > MAX_PLACEHOLDER_NAME_LENGTH) {
|
||||
normalized = normalized.substring(0, MAX_PLACEHOLDER_NAME_LENGTH);
|
||||
}
|
||||
|
||||
return normalized;
|
||||
}
|
||||
|
||||
private static String normalizeDelimiter(String value) {
|
||||
if (value == null) {
|
||||
return DEFAULT_DELIMITER;
|
||||
}
|
||||
|
||||
String normalized = value.replace("\t", "").replace("\r", "").replace("\n", "");
|
||||
|
||||
if (normalized.length() > MAX_DELIMITER_LENGTH) {
|
||||
normalized = normalized.substring(0, MAX_DELIMITER_LENGTH);
|
||||
}
|
||||
|
||||
return normalized;
|
||||
}
|
||||
|
||||
private static int normalizeUserSource(int value) {
|
||||
return WiredSourceUtil.isDefaultUserSource(value) ? value : WiredSourceUtil.SOURCE_TRIGGER;
|
||||
}
|
||||
|
||||
static class JsonData {
|
||||
String placeholderName;
|
||||
int placeholderType;
|
||||
String delimiter;
|
||||
int userSource;
|
||||
|
||||
JsonData(String placeholderName, int placeholderType, String delimiter, int userSource) {
|
||||
this.placeholderName = placeholderName;
|
||||
this.placeholderType = placeholderType;
|
||||
this.delimiter = delimiter;
|
||||
this.userSource = userSource;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -313,21 +313,22 @@ public class RoomChatManager {
|
||||
}
|
||||
}
|
||||
|
||||
String wiredSayMessage = roomChatMessage.getMessage();
|
||||
|
||||
// Handle commands and wired
|
||||
boolean suppressSaysOutput = false;
|
||||
if (chatType != RoomChatType.WHISPER) {
|
||||
if (CommandHandler.handleCommand(habbo.getClient(), roomChatMessage.getUnfilteredMessage())) {
|
||||
WiredManager.triggerUserSays(habbo.getHabboInfo().getCurrentRoom(), habbo.getRoomUnit(), roomChatMessage.getMessage());
|
||||
WiredManager.triggerUserSays(habbo.getHabboInfo().getCurrentRoom(), habbo.getRoomUnit(), wiredSayMessage);
|
||||
roomChatMessage.isCommand = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!ignoreWired) {
|
||||
if (WiredManager.triggerUserSays(habbo.getHabboInfo().getCurrentRoom(), habbo.getRoomUnit(), roomChatMessage.getMessage())) {
|
||||
habbo.getClient().sendResponse(new RoomUserWhisperComposer(
|
||||
new RoomChatMessage(roomChatMessage.getMessage(), habbo, habbo,
|
||||
roomChatMessage.getBubble())));
|
||||
return;
|
||||
}
|
||||
suppressSaysOutput = WiredManager.shouldSuppressUserSaysOutput(
|
||||
habbo.getHabboInfo().getCurrentRoom(),
|
||||
habbo.getRoomUnit(),
|
||||
wiredSayMessage);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -388,9 +389,25 @@ public class RoomChatManager {
|
||||
if (chatType == RoomChatType.WHISPER) {
|
||||
this.handleWhisper(habbo, roomChatMessage, prefixMessage, clearPrefixMessage);
|
||||
} else if (chatType == RoomChatType.TALK) {
|
||||
this.handleTalk(habbo, roomChatMessage, prefixMessage, clearPrefixMessage, tentRectangle);
|
||||
if (suppressSaysOutput) {
|
||||
habbo.getClient().sendResponse(new RoomUserWhisperComposer(
|
||||
new RoomChatMessage(roomChatMessage.getMessage(), habbo, habbo,
|
||||
roomChatMessage.getBubble())));
|
||||
} else {
|
||||
this.handleTalk(habbo, roomChatMessage, prefixMessage, clearPrefixMessage, tentRectangle);
|
||||
}
|
||||
} else if (chatType == RoomChatType.SHOUT) {
|
||||
this.handleShout(habbo, roomChatMessage, prefixMessage, clearPrefixMessage, tentRectangle);
|
||||
if (suppressSaysOutput) {
|
||||
habbo.getClient().sendResponse(new RoomUserWhisperComposer(
|
||||
new RoomChatMessage(roomChatMessage.getMessage(), habbo, habbo,
|
||||
roomChatMessage.getBubble())));
|
||||
} else {
|
||||
this.handleShout(habbo, roomChatMessage, prefixMessage, clearPrefixMessage, tentRectangle);
|
||||
}
|
||||
}
|
||||
|
||||
if (chatType != RoomChatType.WHISPER && !ignoreWired && !roomChatMessage.isCommand) {
|
||||
WiredManager.triggerUserSays(habbo.getHabboInfo().getCurrentRoom(), habbo.getRoomUnit(), wiredSayMessage);
|
||||
}
|
||||
|
||||
// Notify bots and talking furniture
|
||||
|
||||
@@ -12,6 +12,7 @@ import com.eu.habbo.habbohotel.items.interactions.wired.effects.WiredEffectGiveR
|
||||
import com.eu.habbo.habbohotel.items.interactions.wired.effects.WiredEffectTriggerStacks;
|
||||
import com.eu.habbo.habbohotel.items.interactions.wired.extra.WiredExtraExecuteInOrder;
|
||||
import com.eu.habbo.habbohotel.items.interactions.wired.extra.WiredExtraExecutionLimit;
|
||||
import com.eu.habbo.habbohotel.items.interactions.wired.extra.WiredExtraOrEval;
|
||||
import com.eu.habbo.habbohotel.items.interactions.wired.extra.WiredExtraRandom;
|
||||
import com.eu.habbo.habbohotel.items.interactions.wired.extra.WiredExtraUnseen;
|
||||
import com.eu.habbo.habbohotel.rooms.Room;
|
||||
@@ -40,8 +41,10 @@ import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class WiredHandler {
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(WiredHandler.class);
|
||||
@@ -185,20 +188,24 @@ public class WiredHandler {
|
||||
}
|
||||
|
||||
if (!conditions.isEmpty()) {
|
||||
ArrayList<WiredConditionType> matchedConditions = new ArrayList<>(conditions.size());
|
||||
for (InteractionWiredCondition searchMatched : conditions) {
|
||||
if (!matchedConditions.contains(searchMatched.getType()) && searchMatched.operator() == WiredConditionOperator.OR && searchMatched.execute(roomUnit, room, stuff)) {
|
||||
matchedConditions.add(searchMatched.getType());
|
||||
int conditionEvaluationMode = WiredExtraOrEval.MODE_ALL;
|
||||
int conditionEvaluationValue = 1;
|
||||
for (InteractionWiredExtra extra : extras) {
|
||||
if (extra instanceof WiredExtraOrEval) {
|
||||
conditionEvaluationMode = ((WiredExtraOrEval) extra).getEvaluationMode();
|
||||
conditionEvaluationValue = ((WiredExtraOrEval) extra).getCompareValue();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (InteractionWiredCondition condition : conditions) {
|
||||
if (!((condition.operator() == WiredConditionOperator.OR && matchedConditions.contains(condition.getType())) ||
|
||||
(condition.operator() == WiredConditionOperator.AND && condition.execute(roomUnit, room, stuff))) &&
|
||||
!Emulator.getPluginManager().fireEvent(new WiredConditionFailedEvent(room, roomUnit, trigger, condition)).isCancelled()) {
|
||||
|
||||
return false;
|
||||
if (!evaluateConditions(conditions, roomUnit, room, stuff, conditionEvaluationMode, conditionEvaluationValue)) {
|
||||
for (InteractionWiredCondition condition : conditions) {
|
||||
if (!Emulator.getPluginManager().fireEvent(new WiredConditionFailedEvent(room, roomUnit, trigger, condition)).isCancelled()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -253,6 +260,40 @@ public class WiredHandler {
|
||||
return false;
|
||||
}
|
||||
|
||||
private static boolean evaluateConditions(THashSet<InteractionWiredCondition> conditions, RoomUnit roomUnit, Room room, Object[] stuff, int evaluationMode, int evaluationValue) {
|
||||
if (conditions == null || conditions.isEmpty()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
Map<WiredConditionType, Boolean> orGroupResults = new HashMap<>();
|
||||
int matchedRequirements = 0;
|
||||
int totalRequirements = 0;
|
||||
|
||||
for (InteractionWiredCondition condition : conditions) {
|
||||
boolean result = condition.execute(roomUnit, room, stuff);
|
||||
|
||||
if (condition.operator() == WiredConditionOperator.OR) {
|
||||
orGroupResults.merge(condition.getType(), result, (left, right) -> left || right);
|
||||
continue;
|
||||
}
|
||||
|
||||
totalRequirements++;
|
||||
if (result) {
|
||||
matchedRequirements++;
|
||||
}
|
||||
}
|
||||
|
||||
totalRequirements += orGroupResults.size();
|
||||
|
||||
for (Boolean groupResult : orGroupResults.values()) {
|
||||
if (Boolean.TRUE.equals(groupResult)) {
|
||||
matchedRequirements++;
|
||||
}
|
||||
}
|
||||
|
||||
return WiredExtraOrEval.matchesMode(evaluationMode, matchedRequirements, totalRequirements, evaluationValue);
|
||||
}
|
||||
|
||||
private static boolean triggerEffect(InteractionWiredEffect effect, RoomUnit roomUnit, Room room, Object[] stuff, long millis) {
|
||||
boolean executed = false;
|
||||
if (effect != null && (effect.canExecute(millis) || (roomUnit != null && effect.requiresTriggeringUser() && Emulator.getConfig().getBoolean("wired.custom.enabled", false) && effect.userCanExecute(roomUnit.getId(), millis)))) {
|
||||
|
||||
@@ -36,7 +36,8 @@ public final class WiredStack {
|
||||
private final List<IWiredEffect> effects;
|
||||
|
||||
// Extra modifiers
|
||||
private final boolean useOrMode; // WiredExtraOrEval present
|
||||
private final int conditionEvaluationMode; // WiredExtraOrEval mode
|
||||
private final int conditionEvaluationValue; // WiredExtraOrEval numeric threshold
|
||||
private final boolean useRandom; // WiredExtraRandom present
|
||||
private final boolean useUnseen; // WiredExtraUnseen present
|
||||
private final boolean executeInOrder; // WiredExtraExecuteInOrder present
|
||||
@@ -53,7 +54,7 @@ public final class WiredStack {
|
||||
IWiredTrigger trigger,
|
||||
List<IWiredCondition> conditions,
|
||||
List<IWiredEffect> effects) {
|
||||
this(triggerItem, trigger, conditions, effects, false, false, false, false);
|
||||
this(triggerItem, trigger, conditions, effects, 0, 1, false, false, false);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -63,7 +64,8 @@ public final class WiredStack {
|
||||
* @param trigger the trigger implementation
|
||||
* @param conditions list of conditions
|
||||
* @param effects list of effects
|
||||
* @param useOrMode if true, conditions use OR logic (any pass = success)
|
||||
* @param conditionEvaluationMode condition evaluation mode from WiredExtraOrEval
|
||||
* @param conditionEvaluationValue numeric comparison value from WiredExtraOrEval
|
||||
* @param useRandom if true, select one random effect instead of all
|
||||
* @param useUnseen if true, execute effects in "unseen" order (round-robin)
|
||||
* @param executeInOrder if true, execute all regular effects in stable stack order
|
||||
@@ -72,7 +74,8 @@ public final class WiredStack {
|
||||
IWiredTrigger trigger,
|
||||
List<IWiredCondition> conditions,
|
||||
List<IWiredEffect> effects,
|
||||
boolean useOrMode,
|
||||
int conditionEvaluationMode,
|
||||
int conditionEvaluationValue,
|
||||
boolean useRandom,
|
||||
boolean useUnseen,
|
||||
boolean executeInOrder) {
|
||||
@@ -80,7 +83,8 @@ public final class WiredStack {
|
||||
this.trigger = trigger;
|
||||
this.conditions = conditions != null ? Collections.unmodifiableList(conditions) : Collections.emptyList();
|
||||
this.effects = effects != null ? Collections.unmodifiableList(effects) : Collections.emptyList();
|
||||
this.useOrMode = useOrMode;
|
||||
this.conditionEvaluationMode = conditionEvaluationMode;
|
||||
this.conditionEvaluationValue = conditionEvaluationValue;
|
||||
this.useRandom = useRandom;
|
||||
this.useUnseen = useUnseen;
|
||||
this.executeInOrder = executeInOrder;
|
||||
@@ -135,12 +139,19 @@ public final class WiredStack {
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if OR mode is enabled (WiredExtraOrEval).
|
||||
* When true, any condition passing means all pass.
|
||||
* @return true if OR mode is enabled
|
||||
* Get the condition evaluation mode from WiredExtraOrEval.
|
||||
* @return evaluation mode code
|
||||
*/
|
||||
public boolean useOrMode() {
|
||||
return useOrMode;
|
||||
public int conditionEvaluationMode() {
|
||||
return conditionEvaluationMode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the condition evaluation numeric value from WiredExtraOrEval.
|
||||
* @return comparison value
|
||||
*/
|
||||
public int conditionEvaluationValue() {
|
||||
return conditionEvaluationValue;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -193,7 +204,8 @@ public final class WiredStack {
|
||||
", trigger=" + (trigger != null ? trigger.listensTo() : "null") +
|
||||
", conditions=" + conditions.size() +
|
||||
", effects=" + effects.size() +
|
||||
", orMode=" + useOrMode +
|
||||
", conditionEvaluationMode=" + conditionEvaluationMode +
|
||||
", conditionEvaluationValue=" + conditionEvaluationValue +
|
||||
", random=" + useRandom +
|
||||
", unseen=" + useUnseen +
|
||||
", executeInOrder=" + executeInOrder +
|
||||
|
||||
@@ -2,6 +2,7 @@ package com.eu.habbo.habbohotel.wired.core;
|
||||
|
||||
import com.eu.habbo.habbohotel.items.interactions.InteractionWiredCondition;
|
||||
import com.eu.habbo.habbohotel.items.interactions.InteractionWiredEffect;
|
||||
import com.eu.habbo.habbohotel.items.interactions.InteractionWiredExtra;
|
||||
import com.eu.habbo.habbohotel.items.interactions.InteractionWiredTrigger;
|
||||
import com.eu.habbo.habbohotel.items.interactions.wired.extra.WiredExtraExecuteInOrder;
|
||||
import com.eu.habbo.habbohotel.items.interactions.wired.extra.WiredExtraOrEval;
|
||||
@@ -174,17 +175,30 @@ public final class RoomWiredStackIndex implements WiredStackIndex {
|
||||
List<IWiredEffect> effects = collectEffects(rawEffects);
|
||||
|
||||
// Check for extras
|
||||
boolean useOrMode = specialTypes.hasExtraType(x, y, WiredExtraOrEval.class);
|
||||
THashSet<InteractionWiredExtra> extras = specialTypes.getExtras(x, y);
|
||||
int conditionEvaluationMode = WiredExtraOrEval.MODE_ALL;
|
||||
int conditionEvaluationValue = 1;
|
||||
boolean useRandom = specialTypes.hasExtraType(x, y, WiredExtraRandom.class);
|
||||
boolean useUnseen = specialTypes.hasExtraType(x, y, WiredExtraUnseen.class);
|
||||
boolean executeInOrder = specialTypes.hasExtraType(x, y, WiredExtraExecuteInOrder.class);
|
||||
|
||||
if (extras != null) {
|
||||
for (InteractionWiredExtra extra : extras) {
|
||||
if (extra instanceof WiredExtraOrEval) {
|
||||
conditionEvaluationMode = ((WiredExtraOrEval) extra).getEvaluationMode();
|
||||
conditionEvaluationValue = ((WiredExtraOrEval) extra).getCompareValue();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return new WiredStack(
|
||||
trigger,
|
||||
wrappedTrigger,
|
||||
conditions,
|
||||
effects,
|
||||
useOrMode,
|
||||
conditionEvaluationMode,
|
||||
conditionEvaluationValue,
|
||||
useRandom,
|
||||
useUnseen,
|
||||
executeInOrder
|
||||
|
||||
@@ -7,6 +7,7 @@ import com.eu.habbo.habbohotel.items.interactions.InteractionWiredExtra;
|
||||
import com.eu.habbo.habbohotel.items.interactions.wired.extra.WiredExtraFilterFurni;
|
||||
import com.eu.habbo.habbohotel.items.interactions.wired.extra.WiredExtraFilterUser;
|
||||
import com.eu.habbo.habbohotel.items.interactions.wired.extra.WiredExtraExecutionLimit;
|
||||
import com.eu.habbo.habbohotel.items.interactions.wired.extra.WiredExtraOrEval;
|
||||
import com.eu.habbo.habbohotel.items.interactions.wired.extra.WiredExtraRandom;
|
||||
import com.eu.habbo.habbohotel.items.interactions.wired.extra.WiredExtraUnseen;
|
||||
import com.eu.habbo.habbohotel.items.interactions.InteractionWiredTrigger;
|
||||
@@ -305,83 +306,102 @@ public final class WiredEngine {
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean wouldTriggerStack(WiredStack stack, WiredEvent event, long currentTime) {
|
||||
Room room = event.getRoom();
|
||||
|
||||
if (!stack.trigger().matches(stack.triggerItem(), event)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (stack.trigger().requiresActor() && !event.getActor().isPresent()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
WiredState state = new WiredState(maxStepsPerStack);
|
||||
WiredContext ctx = new WiredContext(event, stack.triggerItem(), stack, services, state, null);
|
||||
|
||||
state.step();
|
||||
|
||||
List<InteractionWiredEffect> executedSelectors = Collections.emptyList();
|
||||
if (stack.hasEffects()) {
|
||||
executedSelectors = executeSelectors(stack, ctx);
|
||||
applySelectionFilterExtras(stack, ctx, executedSelectors);
|
||||
}
|
||||
|
||||
if (stack.hasConditions() && !evaluateConditions(stack, ctx)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
WiredExtraExecutionLimit executionLimitExtra = getExecutionLimitExtra(room, stack);
|
||||
return executionLimitExtra == null || executionLimitExtra.canExecuteAt(currentTime);
|
||||
}
|
||||
|
||||
/**
|
||||
* Evaluate all conditions in a stack.
|
||||
*/
|
||||
private boolean evaluateConditions(WiredStack stack, WiredContext ctx) {
|
||||
List<IWiredCondition> conditions = stack.conditions();
|
||||
|
||||
if (stack.useOrMode()) {
|
||||
// OR mode: at least one condition must pass
|
||||
return evaluateOrMode(conditions, ctx);
|
||||
} else {
|
||||
// Standard mode: use individual operators
|
||||
return evaluateStandardMode(conditions, ctx);
|
||||
}
|
||||
|
||||
return evaluateConditionsByMode(conditions, ctx, stack.conditionEvaluationMode(), stack.conditionEvaluationValue());
|
||||
}
|
||||
|
||||
/**
|
||||
* Evaluate conditions in OR mode (any pass = success).
|
||||
* Evaluate conditions according to the configured stack mode.
|
||||
*/
|
||||
private boolean evaluateOrMode(List<IWiredCondition> conditions, WiredContext ctx) {
|
||||
// Group by condition type (for legacy compatibility)
|
||||
Map<String, Boolean> typeResults = new HashMap<>();
|
||||
|
||||
private boolean evaluateConditionsByMode(List<IWiredCondition> conditions, WiredContext ctx, int evaluationMode, int evaluationValue) {
|
||||
if (conditions == null || conditions.isEmpty()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
Room room = ctx.room();
|
||||
Map<String, List<Boolean>> groupedOrResults = new LinkedHashMap<>();
|
||||
int matchedRequirements = 0;
|
||||
int totalRequirements = 0;
|
||||
|
||||
for (IWiredCondition condition : conditions) {
|
||||
ctx.state().step();
|
||||
|
||||
String typeName = condition.getClass().getSimpleName();
|
||||
if (!typeResults.containsKey(typeName) && condition.evaluate(ctx)) {
|
||||
typeResults.put(typeName, true);
|
||||
|
||||
boolean result = condition.evaluate(ctx);
|
||||
String conditionKey = getConditionGroupKey(condition);
|
||||
|
||||
if (condition.operator() == WiredConditionOperator.OR) {
|
||||
groupedOrResults.computeIfAbsent(conditionKey, ignored -> new ArrayList<>()).add(result);
|
||||
debug(room, " Condition (OR group {}) {}: {}", conditionKey, condition.getClass().getSimpleName(), result ? "PASS" : "FAIL");
|
||||
continue;
|
||||
}
|
||||
|
||||
totalRequirements++;
|
||||
|
||||
if (result) {
|
||||
matchedRequirements++;
|
||||
}
|
||||
|
||||
debug(room, " Condition {}: {}", condition.getClass().getSimpleName(), result ? "PASS" : "FAIL");
|
||||
}
|
||||
|
||||
// At least one condition type must have passed
|
||||
return !typeResults.isEmpty();
|
||||
|
||||
for (Map.Entry<String, List<Boolean>> entry : groupedOrResults.entrySet()) {
|
||||
totalRequirements++;
|
||||
|
||||
boolean groupPassed = entry.getValue().stream().anyMatch(Boolean::booleanValue);
|
||||
if (groupPassed) {
|
||||
matchedRequirements++;
|
||||
}
|
||||
|
||||
debug(room, " Condition (OR result {}) : {}", entry.getKey(), groupPassed ? "PASS" : "FAIL");
|
||||
}
|
||||
|
||||
boolean matches = WiredExtraOrEval.matchesMode(evaluationMode, matchedRequirements, totalRequirements, evaluationValue);
|
||||
|
||||
debug(room, "Condition eval mode {} value {} matched {}/{} logical requirements => {}", evaluationMode, evaluationValue, matchedRequirements, totalRequirements, matches ? "PASS" : "FAIL");
|
||||
return matches;
|
||||
}
|
||||
|
||||
/**
|
||||
* Evaluate conditions in standard mode using operators.
|
||||
*/
|
||||
private boolean evaluateStandardMode(List<IWiredCondition> conditions, WiredContext ctx) {
|
||||
Room room = ctx.room();
|
||||
|
||||
// First pass: collect all OR conditions that passed
|
||||
Map<String, Boolean> orResults = new HashMap<>();
|
||||
for (IWiredCondition condition : conditions) {
|
||||
if (condition.operator() == WiredConditionOperator.OR) {
|
||||
ctx.state().step();
|
||||
String typeName = condition.getClass().getSimpleName();
|
||||
boolean result = condition.evaluate(ctx);
|
||||
debug(room, " Condition (OR) {}: {}", typeName, result ? "PASS" : "FAIL");
|
||||
if (!orResults.containsKey(typeName) && result) {
|
||||
orResults.put(typeName, true);
|
||||
}
|
||||
}
|
||||
private String getConditionGroupKey(IWiredCondition condition) {
|
||||
if (condition instanceof InteractionWiredCondition) {
|
||||
return String.valueOf(((InteractionWiredCondition) condition).getType());
|
||||
}
|
||||
|
||||
// Second pass: verify all conditions
|
||||
for (IWiredCondition condition : conditions) {
|
||||
boolean passes;
|
||||
String typeName = condition.getClass().getSimpleName();
|
||||
|
||||
if (condition.operator() == WiredConditionOperator.OR) {
|
||||
// OR: passes if any of same type passed
|
||||
passes = orResults.containsKey(typeName);
|
||||
debug(room, " Condition (OR check) {}: {}", typeName, passes ? "PASS" : "FAIL");
|
||||
} else {
|
||||
// AND: must evaluate and pass
|
||||
ctx.state().step();
|
||||
passes = condition.evaluate(ctx);
|
||||
debug(room, " Condition (AND) {}: {}", typeName, passes ? "PASS" : "FAIL");
|
||||
}
|
||||
|
||||
if (!passes) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
return condition.getClass().getName();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -646,6 +666,51 @@ public final class WiredEngine {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Preview whether a USER_SAYS event should suppress the public room chat output.
|
||||
* This mirrors trigger and condition eligibility without executing regular effects.
|
||||
*/
|
||||
public boolean shouldSuppressUserSaysOutput(WiredEvent event) {
|
||||
if (event == null || event.getType() != WiredEvent.Type.USER_SAYS) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Room room = event.getRoom();
|
||||
if (room == null || !room.isLoaded()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
List<WiredStack> stacks = index.getStacks(room, event.getType());
|
||||
if (stacks.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
long triggerTime = event.getCreatedAtMs();
|
||||
|
||||
for (WiredStack stack : stacks) {
|
||||
if (!(stack.triggerItem() instanceof WiredTriggerHabboSaysKeyword)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
WiredTriggerHabboSaysKeyword trigger = (WiredTriggerHabboSaysKeyword) stack.triggerItem();
|
||||
if (!trigger.isHideMessage()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
if (wouldTriggerStack(stack, event, triggerTime)) {
|
||||
return true;
|
||||
}
|
||||
} catch (WiredLimitException limitEx) {
|
||||
debug(room, "Suppression preview stopped (limit): {}", limitEx.getMessage());
|
||||
} catch (Exception ex) {
|
||||
LOGGER.warn("Error previewing USER_SAYS suppression in room {}: {}", room.getId(), ex.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private void scheduleOrderedEffectBatch(List<IWiredEffect> batch, WiredContext ctx, int delay, long triggerTime) {
|
||||
long delayMs = delay * 500L;
|
||||
long elapsedSinceTrigger = Math.max(0L, System.currentTimeMillis() - triggerTime);
|
||||
|
||||
@@ -316,6 +316,15 @@ public final class WiredManager {
|
||||
return handleEvent(event);
|
||||
}
|
||||
|
||||
public static boolean shouldSuppressUserSaysOutput(Room room, RoomUnit user, String message) {
|
||||
if (!isEnabled() || engine == null || room == null || user == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
WiredEvent event = WiredEvents.userSays(room, user, message);
|
||||
return engine.shouldSuppressUserSaysOutput(event);
|
||||
}
|
||||
|
||||
/**
|
||||
* Trigger when a user enters the room.
|
||||
*/
|
||||
|
||||
+113
@@ -0,0 +1,113 @@
|
||||
package com.eu.habbo.habbohotel.wired.core;
|
||||
|
||||
import com.eu.habbo.habbohotel.items.interactions.InteractionWiredExtra;
|
||||
import com.eu.habbo.habbohotel.items.interactions.wired.extra.WiredExtraTextOutputUsername;
|
||||
import com.eu.habbo.habbohotel.rooms.Room;
|
||||
import com.eu.habbo.habbohotel.rooms.RoomUnit;
|
||||
import com.eu.habbo.habbohotel.users.Habbo;
|
||||
import com.eu.habbo.habbohotel.users.HabboItem;
|
||||
import gnu.trove.set.hash.THashSet;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
|
||||
public final class WiredTextPlaceholderUtil {
|
||||
private WiredTextPlaceholderUtil() {
|
||||
}
|
||||
|
||||
public static String applyUsernamePlaceholders(WiredContext ctx, String text) {
|
||||
if (ctx == null || text == null || text.isEmpty()) {
|
||||
return text;
|
||||
}
|
||||
|
||||
Room room = ctx.room();
|
||||
HabboItem triggerItem = ctx.triggerItem();
|
||||
|
||||
if (room == null || triggerItem == null || room.getRoomSpecialTypes() == null) {
|
||||
return text;
|
||||
}
|
||||
|
||||
THashSet<InteractionWiredExtra> extras = room.getRoomSpecialTypes().getExtras(triggerItem.getX(), triggerItem.getY());
|
||||
if (extras == null || extras.isEmpty()) {
|
||||
return text;
|
||||
}
|
||||
|
||||
String resolvedText = text;
|
||||
|
||||
for (InteractionWiredExtra extra : WiredExecutionOrderUtil.sort(extras)) {
|
||||
if (!(extra instanceof WiredExtraTextOutputUsername)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
WiredExtraTextOutputUsername usernameExtra = (WiredExtraTextOutputUsername) extra;
|
||||
String placeholderToken = usernameExtra.getPlaceholderToken();
|
||||
|
||||
if (placeholderToken.isEmpty() || !resolvedText.contains(placeholderToken)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
resolvedText = resolvedText.replace(placeholderToken, buildUsernameReplacement(ctx, usernameExtra));
|
||||
}
|
||||
|
||||
return resolvedText;
|
||||
}
|
||||
|
||||
public static boolean requiresActor(Room room, HabboItem stackItem) {
|
||||
if (room == null || stackItem == null || room.getRoomSpecialTypes() == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
THashSet<InteractionWiredExtra> extras = room.getRoomSpecialTypes().getExtras(stackItem.getX(), stackItem.getY());
|
||||
if (extras == null || extras.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (InteractionWiredExtra extra : extras) {
|
||||
if (!(extra instanceof WiredExtraTextOutputUsername)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
int userSource = ((WiredExtraTextOutputUsername) extra).getUserSource();
|
||||
if ((userSource == WiredSourceUtil.SOURCE_TRIGGER) || (userSource == WiredSourceUtil.SOURCE_CLICKED_USER)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private static String buildUsernameReplacement(WiredContext ctx, WiredExtraTextOutputUsername extra) {
|
||||
List<RoomUnit> users = WiredSourceUtil.resolveUsers(ctx, extra.getUserSource());
|
||||
if (users.isEmpty()) {
|
||||
return "";
|
||||
}
|
||||
|
||||
Room room = ctx.room();
|
||||
LinkedHashSet<Integer> seenUserIds = new LinkedHashSet<>();
|
||||
List<String> usernames = new ArrayList<>();
|
||||
|
||||
for (RoomUnit unit : users) {
|
||||
if ((unit == null) || !seenUserIds.add(unit.getId())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Habbo habbo = room.getHabbo(unit);
|
||||
if ((habbo == null) || (habbo.getHabboInfo() == null)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
usernames.add(habbo.getHabboInfo().getUsername());
|
||||
}
|
||||
|
||||
if (usernames.isEmpty()) {
|
||||
return "";
|
||||
}
|
||||
|
||||
if (extra.getPlaceholderType() == WiredExtraTextOutputUsername.TYPE_MULTIPLE) {
|
||||
return String.join(extra.getDelimiter(), usernames);
|
||||
}
|
||||
|
||||
return usernames.get(0);
|
||||
}
|
||||
}
|
||||
@@ -11,8 +11,19 @@ import gnu.trove.procedure.TIntProcedure;
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class UserClothesComposer extends MessageComposer {
|
||||
private static class ClothEntry {
|
||||
private final String name;
|
||||
private final int[] setIds;
|
||||
|
||||
private ClothEntry(String name, int[] setIds) {
|
||||
this.name = name;
|
||||
this.setIds = setIds;
|
||||
}
|
||||
}
|
||||
|
||||
private final ArrayList<Integer> idList = new ArrayList<>();
|
||||
private final ArrayList<String> nameList = new ArrayList<>();
|
||||
private final ArrayList<ClothEntry> clothEntries = new ArrayList<>();
|
||||
|
||||
public UserClothesComposer(Habbo habbo) {
|
||||
habbo.getInventory().getWardrobeComponent().getClothing().forEach(new TIntProcedure() {
|
||||
@@ -31,6 +42,12 @@ public class UserClothesComposer extends MessageComposer {
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
for (ClothItem item : Emulator.getGameEnvironment().getCatalogManager().clothing.values()) {
|
||||
if (item != null) {
|
||||
this.clothEntries.add(new ClothEntry(item.name, item.setId));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -40,6 +57,17 @@ public class UserClothesComposer extends MessageComposer {
|
||||
this.idList.forEach(this.response::appendInt);
|
||||
this.response.appendInt(this.nameList.size());
|
||||
this.nameList.forEach(this.response::appendString);
|
||||
this.response.appendInt(this.clothEntries.size());
|
||||
|
||||
for (ClothEntry entry : this.clothEntries) {
|
||||
this.response.appendString(entry.name);
|
||||
this.response.appendInt(entry.setIds.length);
|
||||
|
||||
for (int setId : entry.setIds) {
|
||||
this.response.appendInt(setId);
|
||||
}
|
||||
}
|
||||
|
||||
return this.response;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user