You've already forked Arcturus-Morningstar-Extended
mirror of
https://github.com/duckietm/Arcturus-Morningstar-Extended.git
synced 2026-06-19 15:06:19 +00:00
feat(wired): add advanced match conditions and hotel timezone
This commit is contained in:
@@ -0,0 +1,22 @@
|
||||
SET NAMES utf8mb4;
|
||||
|
||||
-- Create the hotel timezone setting if it does not exist yet.
|
||||
INSERT INTO `emulator_settings` (`key`, `value`)
|
||||
SELECT 'hotel.timezone', 'Europe/Rome'
|
||||
WHERE NOT EXISTS (
|
||||
SELECT 1
|
||||
FROM `emulator_settings`
|
||||
WHERE `key` = 'hotel.timezone'
|
||||
);
|
||||
|
||||
-- Keep the default/example value aligned for existing installs too.
|
||||
UPDATE `emulator_settings`
|
||||
SET `value` = 'Europe/Rome'
|
||||
WHERE `key` = 'hotel.timezone';
|
||||
|
||||
-- Helper query for a timezone selector.
|
||||
-- If MySQL/MariaDB timezone tables are populated, this returns the available timezone ids.
|
||||
SELECT `Name` AS `timezone_id`
|
||||
FROM `mysql`.`time_zone_name`
|
||||
WHERE `Name` IS NOT NULL
|
||||
ORDER BY `Name`;
|
||||
@@ -20,6 +20,8 @@ import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.*;
|
||||
import java.net.JarURLConnection;
|
||||
import java.net.URL;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.SecureRandom;
|
||||
import java.sql.Timestamp;
|
||||
@@ -52,6 +54,7 @@ public final class Emulator {
|
||||
"Still Rocking in 2026.\n";
|
||||
|
||||
public static String build = "";
|
||||
public static long buildTimestamp = -1L;
|
||||
public static boolean isReady = false;
|
||||
public static boolean isShuttingDown = false;
|
||||
public static boolean stopped = false;
|
||||
@@ -103,13 +106,6 @@ public final class Emulator {
|
||||
|
||||
System.out.println(logo);
|
||||
|
||||
System.out.println();
|
||||
LOGGER.info("https://github.com/duckietm/Arcturus-Morningstar-Extended, ");
|
||||
System.out.println();
|
||||
LOGGER.info("This project is for educational purposes only. This Emulator is an open-source fork of Arcturus created by TheGeneral.");
|
||||
LOGGER.info("Version: {}", version);
|
||||
LOGGER.info("Build: {}", build);
|
||||
|
||||
long startTime = System.nanoTime();
|
||||
|
||||
Emulator.runtime = Runtime.getRuntime();
|
||||
@@ -141,6 +137,15 @@ public final class Emulator {
|
||||
Emulator.config.register("camera.price.points", "0");
|
||||
Emulator.config.register("camera.price.points.type", "5");
|
||||
Emulator.config.register("camera.render.delay", "5");
|
||||
Emulator.config.register("hotel.timezone", java.time.ZoneId.systemDefault().getId());
|
||||
String hotelTimezoneId = Emulator.getConfig().getValue("hotel.timezone", java.time.ZoneId.systemDefault().getId());
|
||||
System.out.println();
|
||||
LOGGER.info("https://github.com/duckietm/Arcturus-Morningstar-Extended, ");
|
||||
System.out.println();
|
||||
LOGGER.info("This project is for educational purposes only. This Emulator is an open-source fork of Arcturus created by TheGeneral.");
|
||||
LOGGER.info("Version: {}", version);
|
||||
LOGGER.info("Build: {}", build);
|
||||
LOGGER.info("Build Timestamp: {} [{}]", formatBuildTimestamp(buildTimestamp, hotelTimezoneId), hotelTimezoneId);
|
||||
Emulator.texts.register("camera.permission", "You don't have permission to use the camera!");
|
||||
Emulator.texts.register("camera.wait", "Please wait %seconds% seconds before making another picture.");
|
||||
Emulator.texts.register("camera.error.creation", "Failed to create your picture. *sadpanda*");
|
||||
@@ -216,12 +221,21 @@ public final class Emulator {
|
||||
private static void setBuild() {
|
||||
if (Emulator.class.getProtectionDomain().getCodeSource() == null) {
|
||||
build = "UNKNOWN";
|
||||
buildTimestamp = -1L;
|
||||
return;
|
||||
}
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
try {
|
||||
String filepath = new File(Emulator.class.getProtectionDomain().getCodeSource().getLocation().getPath()).getAbsolutePath();
|
||||
File buildFile = new File(Emulator.class.getProtectionDomain().getCodeSource().getLocation().toURI());
|
||||
buildTimestamp = resolveBuildTimestamp(buildFile);
|
||||
|
||||
if (!buildFile.isFile()) {
|
||||
build = "DEV";
|
||||
return;
|
||||
}
|
||||
|
||||
String filepath = buildFile.getAbsolutePath();
|
||||
MessageDigest md = MessageDigest.getInstance("MD5");
|
||||
try (FileInputStream fis = new FileInputStream(filepath)) {
|
||||
byte[] dataBytes = new byte[1024];
|
||||
@@ -234,14 +248,69 @@ public final class Emulator {
|
||||
}
|
||||
} catch (Exception e) {
|
||||
build = "UNKNOWN";
|
||||
buildTimestamp = -1L;
|
||||
return;
|
||||
}
|
||||
|
||||
build = sb.toString();
|
||||
}
|
||||
|
||||
private static long resolveBuildTimestamp(File buildFile) {
|
||||
if (buildFile != null && buildFile.exists() && buildFile.isFile()) {
|
||||
return buildFile.lastModified();
|
||||
}
|
||||
|
||||
try {
|
||||
URL classUrl = Emulator.class.getResource("Emulator.class");
|
||||
|
||||
if (classUrl != null) {
|
||||
if ("file".equalsIgnoreCase(classUrl.getProtocol())) {
|
||||
File classFile = new File(classUrl.toURI());
|
||||
|
||||
if (classFile.exists()) {
|
||||
return classFile.lastModified();
|
||||
}
|
||||
}
|
||||
|
||||
if ("jar".equalsIgnoreCase(classUrl.getProtocol())) {
|
||||
JarURLConnection connection = (JarURLConnection) classUrl.openConnection();
|
||||
File jarFile = new File(connection.getJarFileURL().toURI());
|
||||
|
||||
if (jarFile.exists()) {
|
||||
return jarFile.lastModified();
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
|
||||
if (buildFile != null && buildFile.exists()) {
|
||||
return buildFile.lastModified();
|
||||
}
|
||||
|
||||
return -1L;
|
||||
}
|
||||
|
||||
private static String formatBuildTimestamp(long buildTimestamp, String timezoneId) {
|
||||
if (buildTimestamp <= 0) {
|
||||
return "UNKNOWN";
|
||||
}
|
||||
|
||||
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
||||
|
||||
try {
|
||||
format.setTimeZone(TimeZone.getTimeZone(java.time.ZoneId.of(timezoneId)));
|
||||
} catch (Exception ignored) {
|
||||
format.setTimeZone(TimeZone.getDefault());
|
||||
}
|
||||
|
||||
return format.format(new Timestamp(buildTimestamp));
|
||||
}
|
||||
|
||||
private static void dispose() {
|
||||
Emulator.getThreading().setCanAdd(false);
|
||||
if (Emulator.threading != null) {
|
||||
Emulator.threading.setCanAdd(false);
|
||||
}
|
||||
Emulator.isShuttingDown = true;
|
||||
Emulator.isReady = false;
|
||||
|
||||
|
||||
@@ -87,6 +87,7 @@ public class ConfigurationManager {
|
||||
// Runtime
|
||||
envMapping.put("runtime.threads", "RT_THREADS");
|
||||
envMapping.put("logging.errors.runtime", "RT_LOG_ERRORS");
|
||||
envMapping.put("hotel.timezone", "HOTEL_TIMEZONE");
|
||||
|
||||
for (Map.Entry<String, String> entry : envMapping.entrySet()) {
|
||||
String envValue = System.getenv(entry.getValue());
|
||||
|
||||
@@ -306,9 +306,19 @@ public class ItemManager {
|
||||
this.interactionsList.add(new ItemInteraction("wf_cnd_actor_in_team", WiredConditionTeamMember.class));
|
||||
this.interactionsList.add(new ItemInteraction("wf_cnd_trggrer_on_frn", WiredConditionTriggerOnFurni.class));
|
||||
this.interactionsList.add(new ItemInteraction("wf_cnd_has_handitem", WiredConditionHabboHasHandItem.class));
|
||||
this.interactionsList.add(new ItemInteraction("wf_cnd_not_has_handitem", WiredConditionNotHabboHasHandItem.class));
|
||||
this.interactionsList.add(new ItemInteraction("wf_cnd_date_rng_active", WiredConditionDateRangeActive.class));
|
||||
this.interactionsList.add(new ItemInteraction("wf_cnd_valid_moves", WiredConditionMovementValidation.class));
|
||||
this.interactionsList.add(new ItemInteraction("wf_cnd_counter_time_matches", WiredConditionCounterTimeMatches.class));
|
||||
this.interactionsList.add(new ItemInteraction("wf_cnd_match_time", WiredConditionMatchTime.class));
|
||||
this.interactionsList.add(new ItemInteraction("wf_cnd_match_date", WiredConditionMatchDate.class));
|
||||
this.interactionsList.add(new ItemInteraction("wf_cnd_user_performs_action", WiredConditionUserPerformsAction.class));
|
||||
this.interactionsList.add(new ItemInteraction("wf_cnd_not_user_performs_action", WiredConditionNotUserPerformsAction.class));
|
||||
this.interactionsList.add(new ItemInteraction("wf_cnd_has_altitude", WiredConditionHasAltitude.class));
|
||||
this.interactionsList.add(new ItemInteraction("wf_cnd_triggerer_match", WiredConditionTriggererMatch.class));
|
||||
this.interactionsList.add(new ItemInteraction("wf_cnd_not_triggerer_match", WiredConditionNotTriggererMatch.class));
|
||||
this.interactionsList.add(new ItemInteraction("wf_cnd_team_has_score", WiredConditionTeamHasScore.class));
|
||||
this.interactionsList.add(new ItemInteraction("wf_cnd_team_has_rank", WiredConditionTeamHasRank.class));
|
||||
|
||||
|
||||
this.interactionsList.add(new ItemInteraction("wf_xtra_random", WiredExtraRandom.class));
|
||||
|
||||
+8
@@ -115,6 +115,14 @@ public class WiredConditionHabboHasHandItem extends InteractionWiredCondition {
|
||||
this.userSource = WiredSourceUtil.SOURCE_TRIGGER;
|
||||
}
|
||||
|
||||
protected int getHandItem() {
|
||||
return this.handItem;
|
||||
}
|
||||
|
||||
protected int getUserSource() {
|
||||
return this.userSource;
|
||||
}
|
||||
|
||||
static class JsonData {
|
||||
int handItemId;
|
||||
int userSource;
|
||||
|
||||
+285
@@ -0,0 +1,285 @@
|
||||
package com.eu.habbo.habbohotel.items.interactions.wired.conditions;
|
||||
|
||||
import com.eu.habbo.Emulator;
|
||||
import com.eu.habbo.habbohotel.items.Item;
|
||||
import com.eu.habbo.habbohotel.items.interactions.InteractionWiredCondition;
|
||||
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.WiredConditionType;
|
||||
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.messages.ServerMessage;
|
||||
import gnu.trove.set.hash.THashSet;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.math.RoundingMode;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class WiredConditionHasAltitude extends InteractionWiredCondition {
|
||||
private static final int COMPARISON_LESS = 0;
|
||||
private static final int COMPARISON_EQUAL = 1;
|
||||
private static final int COMPARISON_GREATER = 2;
|
||||
private static final int QUANTIFIER_ALL = 0;
|
||||
private static final int QUANTIFIER_ANY = 1;
|
||||
|
||||
public static final WiredConditionType type = WiredConditionType.HAS_ALTITUDE;
|
||||
|
||||
private final THashSet<HabboItem> items;
|
||||
private int comparison = COMPARISON_EQUAL;
|
||||
private double altitude = 0.0D;
|
||||
private int furniSource = WiredSourceUtil.SOURCE_TRIGGER;
|
||||
private int quantifier = QUANTIFIER_ALL;
|
||||
|
||||
public WiredConditionHasAltitude(ResultSet set, Item baseItem) throws SQLException {
|
||||
super(set, baseItem);
|
||||
this.items = new THashSet<>();
|
||||
}
|
||||
|
||||
public WiredConditionHasAltitude(int id, int userId, Item item, String extradata, int limitedStack, int limitedSells) {
|
||||
super(id, userId, item, extradata, limitedStack, limitedSells);
|
||||
this.items = new THashSet<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean evaluate(WiredContext ctx) {
|
||||
Room room = ctx.room();
|
||||
if (room == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
this.refresh(room);
|
||||
|
||||
List<HabboItem> targets = WiredSourceUtil.resolveItems(ctx, this.furniSource, this.items);
|
||||
if (targets.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (this.quantifier == QUANTIFIER_ANY) {
|
||||
return targets.stream().anyMatch(this::matchesAltitude);
|
||||
}
|
||||
|
||||
return targets.stream().allMatch(this::matchesAltitude);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
@Override
|
||||
public boolean execute(RoomUnit roomUnit, Room room, Object[] stuff) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getWiredData() {
|
||||
return WiredManager.getGson().toJson(new JsonData(
|
||||
this.comparison,
|
||||
this.formatAltitude(this.altitude),
|
||||
this.furniSource,
|
||||
this.quantifier,
|
||||
this.items.stream().map(HabboItem::getId).collect(Collectors.toList())
|
||||
));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadWiredData(ResultSet set, Room room) throws SQLException {
|
||||
this.items.clear();
|
||||
this.comparison = COMPARISON_EQUAL;
|
||||
this.altitude = 0.0D;
|
||||
this.furniSource = WiredSourceUtil.SOURCE_TRIGGER;
|
||||
this.quantifier = QUANTIFIER_ALL;
|
||||
|
||||
String wiredData = set.getString("wired_data");
|
||||
if (wiredData == null || !wiredData.startsWith("{")) {
|
||||
return;
|
||||
}
|
||||
|
||||
JsonData data = WiredManager.getGson().fromJson(wiredData, JsonData.class);
|
||||
if (data == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.comparison = this.normalizeComparison(data.comparison);
|
||||
this.altitude = this.parseAltitudeOrDefault(data.altitude);
|
||||
this.furniSource = this.normalizeFurniSource(data.furniSource);
|
||||
this.quantifier = this.normalizeQuantifier(data.quantifier);
|
||||
|
||||
if (data.itemIds == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
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.comparison = COMPARISON_EQUAL;
|
||||
this.altitude = 0.0D;
|
||||
this.furniSource = WiredSourceUtil.SOURCE_TRIGGER;
|
||||
this.quantifier = QUANTIFIER_ALL;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WiredConditionType getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
@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(this.formatAltitude(this.altitude));
|
||||
message.appendInt(3);
|
||||
message.appendInt(this.comparison);
|
||||
message.appendInt(this.furniSource);
|
||||
message.appendInt(this.quantifier);
|
||||
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.comparison = (params.length > 0) ? this.normalizeComparison(params[0]) : COMPARISON_EQUAL;
|
||||
this.furniSource = (params.length > 1) ? this.normalizeFurniSource(params[1]) : WiredSourceUtil.SOURCE_TRIGGER;
|
||||
this.quantifier = (params.length > 2) ? this.normalizeQuantifier(params[2]) : QUANTIFIER_ALL;
|
||||
this.altitude = this.parseAltitudeOrDefault(settings.getStringParam());
|
||||
|
||||
int count = settings.getFurniIds().length;
|
||||
if (count > Emulator.getConfig().getInt("hotel.wired.furni.selection.count")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
this.items.clear();
|
||||
|
||||
if (this.furniSource == WiredSourceUtil.SOURCE_SELECTED) {
|
||||
Room room = Emulator.getGameEnvironment().getRoomManager().getRoom(this.getRoomId());
|
||||
if (room == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int itemId : settings.getFurniIds()) {
|
||||
HabboItem item = room.getHabboItem(itemId);
|
||||
if (item != null) {
|
||||
this.items.add(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean matchesAltitude(HabboItem item) {
|
||||
if (item == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
double normalizedAltitude = this.normalizeAltitude(item.getZ());
|
||||
|
||||
switch (this.comparison) {
|
||||
case COMPARISON_LESS:
|
||||
return normalizedAltitude < this.altitude;
|
||||
case COMPARISON_GREATER:
|
||||
return normalizedAltitude > this.altitude;
|
||||
default:
|
||||
return BigDecimal.valueOf(normalizedAltitude).compareTo(BigDecimal.valueOf(this.altitude)) == 0;
|
||||
}
|
||||
}
|
||||
|
||||
private void refresh(Room room) {
|
||||
THashSet<HabboItem> remove = new THashSet<>();
|
||||
|
||||
for (HabboItem item : this.items) {
|
||||
if (room.getHabboItem(item.getId()) == null) {
|
||||
remove.add(item);
|
||||
}
|
||||
}
|
||||
|
||||
for (HabboItem item : remove) {
|
||||
this.items.remove(item);
|
||||
}
|
||||
}
|
||||
|
||||
private int normalizeComparison(int value) {
|
||||
if (value < COMPARISON_LESS || value > COMPARISON_GREATER) {
|
||||
return COMPARISON_EQUAL;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
private int normalizeQuantifier(int value) {
|
||||
return (value == QUANTIFIER_ANY) ? QUANTIFIER_ANY : QUANTIFIER_ALL;
|
||||
}
|
||||
|
||||
private 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 double normalizeAltitude(double value) {
|
||||
double clampedValue = Math.max(0.0D, Math.min(Room.MAXIMUM_FURNI_HEIGHT, value));
|
||||
return BigDecimal.valueOf(clampedValue).setScale(2, RoundingMode.HALF_UP).doubleValue();
|
||||
}
|
||||
|
||||
private double parseAltitudeOrDefault(String value) {
|
||||
if (value == null || value.trim().isEmpty()) {
|
||||
return 0.0D;
|
||||
}
|
||||
|
||||
try {
|
||||
return this.normalizeAltitude(new BigDecimal(value.trim()).doubleValue());
|
||||
} catch (NumberFormatException exception) {
|
||||
return 0.0D;
|
||||
}
|
||||
}
|
||||
|
||||
private String formatAltitude(double value) {
|
||||
BigDecimal decimal = BigDecimal.valueOf(this.normalizeAltitude(value)).stripTrailingZeros();
|
||||
return (decimal.scale() < 0 ? decimal.setScale(0, RoundingMode.DOWN) : decimal).toPlainString();
|
||||
}
|
||||
|
||||
static class JsonData {
|
||||
int comparison;
|
||||
String altitude;
|
||||
int furniSource;
|
||||
int quantifier;
|
||||
List<Integer> itemIds;
|
||||
|
||||
public JsonData(int comparison, String altitude, int furniSource, int quantifier, List<Integer> itemIds) {
|
||||
this.comparison = comparison;
|
||||
this.altitude = altitude;
|
||||
this.furniSource = furniSource;
|
||||
this.quantifier = quantifier;
|
||||
this.itemIds = itemIds;
|
||||
}
|
||||
}
|
||||
}
|
||||
+253
@@ -0,0 +1,253 @@
|
||||
package com.eu.habbo.habbohotel.items.interactions.wired.conditions;
|
||||
|
||||
import com.eu.habbo.habbohotel.items.Item;
|
||||
import com.eu.habbo.habbohotel.items.interactions.InteractionWiredCondition;
|
||||
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.WiredConditionType;
|
||||
import com.eu.habbo.habbohotel.wired.core.WiredContext;
|
||||
import com.eu.habbo.habbohotel.wired.core.WiredManager;
|
||||
import com.eu.habbo.messages.ServerMessage;
|
||||
import com.eu.habbo.util.HotelDateTimeUtil;
|
||||
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.time.LocalDate;
|
||||
|
||||
public class WiredConditionMatchDate extends InteractionWiredCondition {
|
||||
private static final int MODE_SKIP = 0;
|
||||
private static final int MODE_EXACT = 1;
|
||||
private static final int MODE_RANGE = 2;
|
||||
private static final int ALL_WEEKDAYS_MASK = createMask(1, 7);
|
||||
private static final int ALL_MONTHS_MASK = createMask(1, 12);
|
||||
|
||||
public static final WiredConditionType type = WiredConditionType.MATCH_DATE;
|
||||
|
||||
private int weekdayMask = ALL_WEEKDAYS_MASK;
|
||||
private int dayMode = MODE_SKIP;
|
||||
private int dayFrom = 1;
|
||||
private int dayTo = 31;
|
||||
private int monthMask = ALL_MONTHS_MASK;
|
||||
private int yearMode = MODE_SKIP;
|
||||
private int yearFrom = HotelDateTimeUtil.localDateNow().getYear();
|
||||
private int yearTo = HotelDateTimeUtil.localDateNow().getYear();
|
||||
|
||||
public WiredConditionMatchDate(ResultSet set, Item baseItem) throws SQLException {
|
||||
super(set, baseItem);
|
||||
}
|
||||
|
||||
public WiredConditionMatchDate(int id, int userId, Item item, String extradata, int limitedStack, int limitedSells) {
|
||||
super(id, userId, item, extradata, limitedStack, limitedSells);
|
||||
}
|
||||
|
||||
@Override
|
||||
public WiredConditionType getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void serializeWiredData(ServerMessage message, Room room) {
|
||||
message.appendBoolean(false);
|
||||
message.appendInt(5);
|
||||
message.appendInt(0);
|
||||
message.appendInt(this.getBaseItem().getSpriteId());
|
||||
message.appendInt(this.getId());
|
||||
message.appendString("");
|
||||
message.appendInt(8);
|
||||
message.appendInt(this.weekdayMask);
|
||||
message.appendInt(this.dayMode);
|
||||
message.appendInt(this.dayFrom);
|
||||
message.appendInt(this.dayTo);
|
||||
message.appendInt(this.monthMask);
|
||||
message.appendInt(this.yearMode);
|
||||
message.appendInt(this.yearFrom);
|
||||
message.appendInt(this.yearTo);
|
||||
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.weekdayMask = (params.length > 0) ? this.normalizeWeekdayMask(params[0]) : ALL_WEEKDAYS_MASK;
|
||||
this.dayMode = (params.length > 1) ? this.normalizeMode(params[1]) : MODE_SKIP;
|
||||
this.dayFrom = (params.length > 2) ? this.normalizeDay(params[2]) : 1;
|
||||
this.dayTo = (params.length > 3) ? this.normalizeDay(params[3]) : this.dayFrom;
|
||||
this.monthMask = (params.length > 4) ? this.normalizeMonthMask(params[4]) : ALL_MONTHS_MASK;
|
||||
this.yearMode = (params.length > 5) ? this.normalizeMode(params[5]) : MODE_SKIP;
|
||||
this.yearFrom = (params.length > 6) ? this.normalizeYear(params[6]) : HotelDateTimeUtil.localDateNow().getYear();
|
||||
this.yearTo = (params.length > 7) ? this.normalizeYear(params[7]) : this.yearFrom;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean evaluate(WiredContext ctx) {
|
||||
LocalDate now = HotelDateTimeUtil.localDateNow();
|
||||
|
||||
return this.matchesMask(now.getDayOfWeek().getValue(), this.weekdayMask)
|
||||
&& this.matchesMask(now.getMonthValue(), this.monthMask)
|
||||
&& this.matchesDatePart(now.getDayOfMonth(), this.dayMode, this.dayFrom, this.dayTo)
|
||||
&& this.matchesDatePart(now.getYear(), this.yearMode, this.yearFrom, this.yearTo);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
@Override
|
||||
public boolean execute(RoomUnit roomUnit, Room room, Object[] stuff) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getWiredData() {
|
||||
return WiredManager.getGson().toJson(new JsonData(
|
||||
this.weekdayMask,
|
||||
this.dayMode,
|
||||
this.dayFrom,
|
||||
this.dayTo,
|
||||
this.monthMask,
|
||||
this.yearMode,
|
||||
this.yearFrom,
|
||||
this.yearTo
|
||||
));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadWiredData(ResultSet set, Room room) throws SQLException {
|
||||
this.reset();
|
||||
|
||||
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) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.weekdayMask = this.normalizeWeekdayMask(data.weekdayMask);
|
||||
this.dayMode = this.normalizeMode(data.dayMode);
|
||||
this.dayFrom = this.normalizeDay(data.dayFrom);
|
||||
this.dayTo = this.normalizeDay(data.dayTo);
|
||||
this.monthMask = this.normalizeMonthMask(data.monthMask);
|
||||
this.yearMode = this.normalizeMode(data.yearMode);
|
||||
this.yearFrom = this.normalizeYear(data.yearFrom);
|
||||
this.yearTo = this.normalizeYear(data.yearTo);
|
||||
return;
|
||||
}
|
||||
|
||||
String[] data = wiredData.split("\t");
|
||||
if (data.length != 8) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
this.weekdayMask = this.normalizeWeekdayMask(Integer.parseInt(data[0]));
|
||||
this.dayMode = this.normalizeMode(Integer.parseInt(data[1]));
|
||||
this.dayFrom = this.normalizeDay(Integer.parseInt(data[2]));
|
||||
this.dayTo = this.normalizeDay(Integer.parseInt(data[3]));
|
||||
this.monthMask = this.normalizeMonthMask(Integer.parseInt(data[4]));
|
||||
this.yearMode = this.normalizeMode(Integer.parseInt(data[5]));
|
||||
this.yearFrom = this.normalizeYear(Integer.parseInt(data[6]));
|
||||
this.yearTo = this.normalizeYear(Integer.parseInt(data[7]));
|
||||
} catch (NumberFormatException ignored) {
|
||||
this.reset();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPickUp() {
|
||||
this.reset();
|
||||
}
|
||||
|
||||
private void reset() {
|
||||
int currentYear = HotelDateTimeUtil.localDateNow().getYear();
|
||||
|
||||
this.weekdayMask = ALL_WEEKDAYS_MASK;
|
||||
this.dayMode = MODE_SKIP;
|
||||
this.dayFrom = 1;
|
||||
this.dayTo = 31;
|
||||
this.monthMask = ALL_MONTHS_MASK;
|
||||
this.yearMode = MODE_SKIP;
|
||||
this.yearFrom = currentYear;
|
||||
this.yearTo = currentYear;
|
||||
}
|
||||
|
||||
private boolean matchesMask(int value, int mask) {
|
||||
return (mask & (1 << value)) != 0;
|
||||
}
|
||||
|
||||
private boolean matchesDatePart(int currentValue, int mode, int fromValue, int toValue) {
|
||||
switch (mode) {
|
||||
case MODE_EXACT:
|
||||
return currentValue == fromValue;
|
||||
case MODE_RANGE:
|
||||
return currentValue >= Math.min(fromValue, toValue) && currentValue <= Math.max(fromValue, toValue);
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
private int normalizeMode(int value) {
|
||||
if (value < MODE_SKIP || value > MODE_RANGE) {
|
||||
return MODE_SKIP;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
private int normalizeDay(int value) {
|
||||
return Math.max(1, Math.min(31, value));
|
||||
}
|
||||
|
||||
private int normalizeYear(int value) {
|
||||
return Math.max(1, Math.min(9999, value));
|
||||
}
|
||||
|
||||
private int normalizeWeekdayMask(int value) {
|
||||
int normalized = value & ALL_WEEKDAYS_MASK;
|
||||
return (normalized == 0) ? ALL_WEEKDAYS_MASK : normalized;
|
||||
}
|
||||
|
||||
private int normalizeMonthMask(int value) {
|
||||
int normalized = value & ALL_MONTHS_MASK;
|
||||
return (normalized == 0) ? ALL_MONTHS_MASK : normalized;
|
||||
}
|
||||
|
||||
private static int createMask(int startValue, int endValue) {
|
||||
int mask = 0;
|
||||
|
||||
for (int value = startValue; value <= endValue; value++) {
|
||||
mask |= (1 << value);
|
||||
}
|
||||
|
||||
return mask;
|
||||
}
|
||||
|
||||
static class JsonData {
|
||||
int weekdayMask;
|
||||
int dayMode;
|
||||
int dayFrom;
|
||||
int dayTo;
|
||||
int monthMask;
|
||||
int yearMode;
|
||||
int yearFrom;
|
||||
int yearTo;
|
||||
|
||||
public JsonData(int weekdayMask, int dayMode, int dayFrom, int dayTo, int monthMask, int yearMode, int yearFrom, int yearTo) {
|
||||
this.weekdayMask = weekdayMask;
|
||||
this.dayMode = dayMode;
|
||||
this.dayFrom = dayFrom;
|
||||
this.dayTo = dayTo;
|
||||
this.monthMask = monthMask;
|
||||
this.yearMode = yearMode;
|
||||
this.yearFrom = yearFrom;
|
||||
this.yearTo = yearTo;
|
||||
}
|
||||
}
|
||||
}
|
||||
+237
@@ -0,0 +1,237 @@
|
||||
package com.eu.habbo.habbohotel.items.interactions.wired.conditions;
|
||||
|
||||
import com.eu.habbo.habbohotel.items.Item;
|
||||
import com.eu.habbo.habbohotel.items.interactions.InteractionWiredCondition;
|
||||
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.WiredConditionType;
|
||||
import com.eu.habbo.habbohotel.wired.core.WiredContext;
|
||||
import com.eu.habbo.habbohotel.wired.core.WiredManager;
|
||||
import com.eu.habbo.messages.ServerMessage;
|
||||
import com.eu.habbo.util.HotelDateTimeUtil;
|
||||
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.time.LocalTime;
|
||||
|
||||
public class WiredConditionMatchTime extends InteractionWiredCondition {
|
||||
private static final int MODE_SKIP = 0;
|
||||
private static final int MODE_EXACT = 1;
|
||||
private static final int MODE_RANGE = 2;
|
||||
|
||||
public static final WiredConditionType type = WiredConditionType.MATCH_TIME;
|
||||
|
||||
private int hourMode = MODE_SKIP;
|
||||
private int hourFrom = 0;
|
||||
private int hourTo = 0;
|
||||
private int minuteMode = MODE_SKIP;
|
||||
private int minuteFrom = 0;
|
||||
private int minuteTo = 0;
|
||||
private int secondMode = MODE_SKIP;
|
||||
private int secondFrom = 0;
|
||||
private int secondTo = 0;
|
||||
|
||||
public WiredConditionMatchTime(ResultSet set, Item baseItem) throws SQLException {
|
||||
super(set, baseItem);
|
||||
}
|
||||
|
||||
public WiredConditionMatchTime(int id, int userId, Item item, String extradata, int limitedStack, int limitedSells) {
|
||||
super(id, userId, item, extradata, limitedStack, limitedSells);
|
||||
}
|
||||
|
||||
@Override
|
||||
public WiredConditionType getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void serializeWiredData(ServerMessage message, Room room) {
|
||||
message.appendBoolean(false);
|
||||
message.appendInt(5);
|
||||
message.appendInt(0);
|
||||
message.appendInt(this.getBaseItem().getSpriteId());
|
||||
message.appendInt(this.getId());
|
||||
message.appendString("");
|
||||
message.appendInt(9);
|
||||
message.appendInt(this.hourMode);
|
||||
message.appendInt(this.hourFrom);
|
||||
message.appendInt(this.hourTo);
|
||||
message.appendInt(this.minuteMode);
|
||||
message.appendInt(this.minuteFrom);
|
||||
message.appendInt(this.minuteTo);
|
||||
message.appendInt(this.secondMode);
|
||||
message.appendInt(this.secondFrom);
|
||||
message.appendInt(this.secondTo);
|
||||
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.hourMode = (params.length > 0) ? this.normalizeMode(params[0]) : MODE_SKIP;
|
||||
this.hourFrom = (params.length > 1) ? this.normalizeHour(params[1]) : 0;
|
||||
this.hourTo = (params.length > 2) ? this.normalizeHour(params[2]) : this.hourFrom;
|
||||
this.minuteMode = (params.length > 3) ? this.normalizeMode(params[3]) : MODE_SKIP;
|
||||
this.minuteFrom = (params.length > 4) ? this.normalizeMinuteOrSecond(params[4]) : 0;
|
||||
this.minuteTo = (params.length > 5) ? this.normalizeMinuteOrSecond(params[5]) : this.minuteFrom;
|
||||
this.secondMode = (params.length > 6) ? this.normalizeMode(params[6]) : MODE_SKIP;
|
||||
this.secondFrom = (params.length > 7) ? this.normalizeMinuteOrSecond(params[7]) : 0;
|
||||
this.secondTo = (params.length > 8) ? this.normalizeMinuteOrSecond(params[8]) : this.secondFrom;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean evaluate(WiredContext ctx) {
|
||||
LocalTime now = HotelDateTimeUtil.localTimeNow();
|
||||
|
||||
return this.matchesTimePart(now.getHour(), this.hourMode, this.hourFrom, this.hourTo)
|
||||
&& this.matchesTimePart(now.getMinute(), this.minuteMode, this.minuteFrom, this.minuteTo)
|
||||
&& this.matchesTimePart(now.getSecond(), this.secondMode, this.secondFrom, this.secondTo);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
@Override
|
||||
public boolean execute(RoomUnit roomUnit, Room room, Object[] stuff) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getWiredData() {
|
||||
return WiredManager.getGson().toJson(new JsonData(
|
||||
this.hourMode,
|
||||
this.hourFrom,
|
||||
this.hourTo,
|
||||
this.minuteMode,
|
||||
this.minuteFrom,
|
||||
this.minuteTo,
|
||||
this.secondMode,
|
||||
this.secondFrom,
|
||||
this.secondTo
|
||||
));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadWiredData(ResultSet set, Room room) throws SQLException {
|
||||
this.reset();
|
||||
|
||||
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) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.hourMode = this.normalizeMode(data.hourMode);
|
||||
this.hourFrom = this.normalizeHour(data.hourFrom);
|
||||
this.hourTo = this.normalizeHour(data.hourTo);
|
||||
this.minuteMode = this.normalizeMode(data.minuteMode);
|
||||
this.minuteFrom = this.normalizeMinuteOrSecond(data.minuteFrom);
|
||||
this.minuteTo = this.normalizeMinuteOrSecond(data.minuteTo);
|
||||
this.secondMode = this.normalizeMode(data.secondMode);
|
||||
this.secondFrom = this.normalizeMinuteOrSecond(data.secondFrom);
|
||||
this.secondTo = this.normalizeMinuteOrSecond(data.secondTo);
|
||||
return;
|
||||
}
|
||||
|
||||
String[] data = wiredData.split("\t");
|
||||
if (data.length != 9) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
this.hourMode = this.normalizeMode(Integer.parseInt(data[0]));
|
||||
this.hourFrom = this.normalizeHour(Integer.parseInt(data[1]));
|
||||
this.hourTo = this.normalizeHour(Integer.parseInt(data[2]));
|
||||
this.minuteMode = this.normalizeMode(Integer.parseInt(data[3]));
|
||||
this.minuteFrom = this.normalizeMinuteOrSecond(Integer.parseInt(data[4]));
|
||||
this.minuteTo = this.normalizeMinuteOrSecond(Integer.parseInt(data[5]));
|
||||
this.secondMode = this.normalizeMode(Integer.parseInt(data[6]));
|
||||
this.secondFrom = this.normalizeMinuteOrSecond(Integer.parseInt(data[7]));
|
||||
this.secondTo = this.normalizeMinuteOrSecond(Integer.parseInt(data[8]));
|
||||
} catch (NumberFormatException ignored) {
|
||||
this.reset();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPickUp() {
|
||||
this.reset();
|
||||
}
|
||||
|
||||
private void reset() {
|
||||
this.hourMode = MODE_SKIP;
|
||||
this.hourFrom = 0;
|
||||
this.hourTo = 0;
|
||||
this.minuteMode = MODE_SKIP;
|
||||
this.minuteFrom = 0;
|
||||
this.minuteTo = 0;
|
||||
this.secondMode = MODE_SKIP;
|
||||
this.secondFrom = 0;
|
||||
this.secondTo = 0;
|
||||
}
|
||||
|
||||
private boolean matchesTimePart(int currentValue, int mode, int fromValue, int toValue) {
|
||||
switch (mode) {
|
||||
case MODE_EXACT:
|
||||
return currentValue == fromValue;
|
||||
case MODE_RANGE:
|
||||
if (fromValue <= toValue) {
|
||||
return currentValue >= fromValue && currentValue <= toValue;
|
||||
}
|
||||
|
||||
return currentValue >= fromValue || currentValue <= toValue;
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
private int normalizeMode(int value) {
|
||||
if (value < MODE_SKIP || value > MODE_RANGE) {
|
||||
return MODE_SKIP;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
private int normalizeHour(int value) {
|
||||
return Math.max(0, Math.min(23, value));
|
||||
}
|
||||
|
||||
private int normalizeMinuteOrSecond(int value) {
|
||||
return Math.max(0, Math.min(59, value));
|
||||
}
|
||||
|
||||
static class JsonData {
|
||||
int hourMode;
|
||||
int hourFrom;
|
||||
int hourTo;
|
||||
int minuteMode;
|
||||
int minuteFrom;
|
||||
int minuteTo;
|
||||
int secondMode;
|
||||
int secondFrom;
|
||||
int secondTo;
|
||||
|
||||
public JsonData(int hourMode, int hourFrom, int hourTo, int minuteMode, int minuteFrom, int minuteTo, int secondMode, int secondFrom, int secondTo) {
|
||||
this.hourMode = hourMode;
|
||||
this.hourFrom = hourFrom;
|
||||
this.hourTo = hourTo;
|
||||
this.minuteMode = minuteMode;
|
||||
this.minuteFrom = minuteFrom;
|
||||
this.minuteTo = minuteTo;
|
||||
this.secondMode = secondMode;
|
||||
this.secondFrom = secondFrom;
|
||||
this.secondTo = secondTo;
|
||||
}
|
||||
}
|
||||
}
|
||||
+42
@@ -0,0 +1,42 @@
|
||||
package com.eu.habbo.habbohotel.items.interactions.wired.conditions;
|
||||
|
||||
import com.eu.habbo.habbohotel.items.Item;
|
||||
import com.eu.habbo.habbohotel.rooms.RoomUnit;
|
||||
import com.eu.habbo.habbohotel.wired.WiredConditionType;
|
||||
import com.eu.habbo.habbohotel.wired.core.WiredContext;
|
||||
import com.eu.habbo.habbohotel.wired.core.WiredSourceUtil;
|
||||
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.List;
|
||||
|
||||
public class WiredConditionNotHabboHasHandItem extends WiredConditionHabboHasHandItem {
|
||||
public static final WiredConditionType type = WiredConditionType.NOT_ACTOR_HAS_HANDITEM;
|
||||
|
||||
public WiredConditionNotHabboHasHandItem(ResultSet set, Item baseItem) throws SQLException {
|
||||
super(set, baseItem);
|
||||
}
|
||||
|
||||
public WiredConditionNotHabboHasHandItem(int id, int userId, Item item, String extradata, int limitedStack, int limitedSells) {
|
||||
super(id, userId, item, extradata, limitedStack, limitedSells);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean evaluate(WiredContext ctx) {
|
||||
List<RoomUnit> targets = WiredSourceUtil.resolveUsers(ctx, this.getUserSource());
|
||||
if (targets.isEmpty()) return false;
|
||||
|
||||
for (RoomUnit roomUnit : targets) {
|
||||
if (roomUnit == null || roomUnit.getHandItem() == this.getHandItem()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WiredConditionType getType() {
|
||||
return type;
|
||||
}
|
||||
}
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
package com.eu.habbo.habbohotel.items.interactions.wired.conditions;
|
||||
|
||||
import com.eu.habbo.habbohotel.items.Item;
|
||||
import com.eu.habbo.habbohotel.wired.WiredConditionType;
|
||||
import com.eu.habbo.habbohotel.wired.core.WiredContext;
|
||||
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
|
||||
public class WiredConditionNotTriggererMatch extends WiredConditionTriggererMatch {
|
||||
public static final WiredConditionType type = WiredConditionType.NOT_TRIGGERER_MATCH;
|
||||
|
||||
public WiredConditionNotTriggererMatch(ResultSet set, Item baseItem) throws SQLException {
|
||||
super(set, baseItem);
|
||||
}
|
||||
|
||||
public WiredConditionNotTriggererMatch(int id, int userId, Item item, String extradata, int limitedStack, int limitedSells) {
|
||||
super(id, userId, item, extradata, limitedStack, limitedSells);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean evaluate(WiredContext ctx) {
|
||||
MatchResult result = this.evaluateMatch(ctx);
|
||||
return result.valid && !result.matched;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WiredConditionType getType() {
|
||||
return type;
|
||||
}
|
||||
}
|
||||
+46
@@ -0,0 +1,46 @@
|
||||
package com.eu.habbo.habbohotel.items.interactions.wired.conditions;
|
||||
|
||||
import com.eu.habbo.habbohotel.items.Item;
|
||||
import com.eu.habbo.habbohotel.rooms.Room;
|
||||
import com.eu.habbo.habbohotel.rooms.RoomUnit;
|
||||
import com.eu.habbo.habbohotel.wired.WiredConditionType;
|
||||
import com.eu.habbo.habbohotel.wired.core.WiredContext;
|
||||
import com.eu.habbo.habbohotel.wired.core.WiredSourceUtil;
|
||||
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.List;
|
||||
|
||||
public class WiredConditionNotUserPerformsAction extends WiredConditionUserPerformsAction {
|
||||
private static final int QUANTIFIER_ANY_NOT_MATCH = 0;
|
||||
private static final int QUANTIFIER_NONE_MATCH = 1;
|
||||
|
||||
public static final WiredConditionType type = WiredConditionType.NOT_USER_PERFORMS_ACTION;
|
||||
|
||||
public WiredConditionNotUserPerformsAction(ResultSet set, Item baseItem) throws SQLException {
|
||||
super(set, baseItem);
|
||||
}
|
||||
|
||||
public WiredConditionNotUserPerformsAction(int id, int userId, Item item, String extradata, int limitedStack, int limitedSells) {
|
||||
super(id, userId, item, extradata, limitedStack, limitedSells);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean evaluate(WiredContext ctx) {
|
||||
List<RoomUnit> targets = WiredSourceUtil.resolveUsers(ctx, this.getUserSource());
|
||||
if (targets.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (this.getQuantifier() == QUANTIFIER_NONE_MATCH) {
|
||||
return targets.stream().noneMatch(roomUnit -> this.matchesAction(ctx, roomUnit));
|
||||
}
|
||||
|
||||
return targets.stream().anyMatch(roomUnit -> !this.matchesAction(ctx, roomUnit));
|
||||
}
|
||||
|
||||
@Override
|
||||
public WiredConditionType getType() {
|
||||
return type;
|
||||
}
|
||||
}
|
||||
+197
@@ -0,0 +1,197 @@
|
||||
package com.eu.habbo.habbohotel.items.interactions.wired.conditions;
|
||||
|
||||
import com.eu.habbo.habbohotel.games.Game;
|
||||
import com.eu.habbo.habbohotel.games.GameState;
|
||||
import com.eu.habbo.habbohotel.games.GameTeam;
|
||||
import com.eu.habbo.habbohotel.games.GameTeamColors;
|
||||
import com.eu.habbo.habbohotel.games.battlebanzai.BattleBanzaiGame;
|
||||
import com.eu.habbo.habbohotel.games.freeze.FreezeGame;
|
||||
import com.eu.habbo.habbohotel.items.Item;
|
||||
import com.eu.habbo.habbohotel.items.interactions.InteractionWiredCondition;
|
||||
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.wired.core.WiredContext;
|
||||
import com.eu.habbo.habbohotel.wired.core.WiredSourceUtil;
|
||||
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
abstract class WiredConditionTeamGameBase extends InteractionWiredCondition {
|
||||
protected static final int QUANTIFIER_ALL = 0;
|
||||
protected static final int QUANTIFIER_ANY = 1;
|
||||
protected static final int COMPARISON_LOWER = 0;
|
||||
protected static final int COMPARISON_EQUAL = 1;
|
||||
protected static final int COMPARISON_HIGHER = 2;
|
||||
protected static final int TEAM_TRIGGERER = 0;
|
||||
|
||||
private static final GameTeamColors[] SUPPORTED_TEAM_COLORS = new GameTeamColors[] {
|
||||
GameTeamColors.RED,
|
||||
GameTeamColors.GREEN,
|
||||
GameTeamColors.BLUE,
|
||||
GameTeamColors.YELLOW
|
||||
};
|
||||
|
||||
protected WiredConditionTeamGameBase(ResultSet set, Item baseItem) throws SQLException {
|
||||
super(set, baseItem);
|
||||
}
|
||||
|
||||
protected WiredConditionTeamGameBase(int id, int userId, Item item, String extradata, int limitedStack, int limitedSells) {
|
||||
super(id, userId, item, extradata, limitedStack, limitedSells);
|
||||
}
|
||||
|
||||
protected List<RoomUnit> resolveUsers(WiredContext ctx, int userSource) {
|
||||
Map<Integer, RoomUnit> deduplicated = new LinkedHashMap<>();
|
||||
|
||||
for (RoomUnit roomUnit : WiredSourceUtil.resolveUsers(ctx, userSource)) {
|
||||
if (roomUnit != null) {
|
||||
deduplicated.putIfAbsent(roomUnit.getId(), roomUnit);
|
||||
}
|
||||
}
|
||||
|
||||
return new ArrayList<>(deduplicated.values());
|
||||
}
|
||||
|
||||
protected boolean matchesQuantifier(List<RoomUnit> users, int quantifier, Predicate<RoomUnit> predicate) {
|
||||
if (users.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (quantifier == QUANTIFIER_ANY) {
|
||||
return users.stream().anyMatch(predicate);
|
||||
}
|
||||
|
||||
return users.stream().allMatch(predicate);
|
||||
}
|
||||
|
||||
protected int normalizeQuantifier(int value) {
|
||||
return (value == QUANTIFIER_ANY) ? QUANTIFIER_ANY : QUANTIFIER_ALL;
|
||||
}
|
||||
|
||||
protected int normalizeComparison(int value) {
|
||||
switch (value) {
|
||||
case COMPARISON_LOWER:
|
||||
case COMPARISON_HIGHER:
|
||||
return value;
|
||||
default:
|
||||
return COMPARISON_EQUAL;
|
||||
}
|
||||
}
|
||||
|
||||
protected int normalizeUserSource(int value) {
|
||||
switch (value) {
|
||||
case WiredSourceUtil.SOURCE_SELECTOR:
|
||||
case WiredSourceUtil.SOURCE_SIGNAL:
|
||||
case WiredSourceUtil.SOURCE_TRIGGER:
|
||||
return value;
|
||||
default:
|
||||
return WiredSourceUtil.SOURCE_TRIGGER;
|
||||
}
|
||||
}
|
||||
|
||||
protected int normalizePlacement(int value) {
|
||||
if (value < 1 || value > 4) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
protected int normalizeScore(int value) {
|
||||
return Math.max(0, value);
|
||||
}
|
||||
|
||||
protected int normalizeExplicitTeamType(int value) {
|
||||
GameTeamColors color = GameTeamColors.fromType(value);
|
||||
return (color.type >= GameTeamColors.RED.type && color.type <= GameTeamColors.YELLOW.type)
|
||||
? color.type
|
||||
: GameTeamColors.RED.type;
|
||||
}
|
||||
|
||||
protected int normalizeRankTeamType(int value) {
|
||||
if (value == TEAM_TRIGGERER) {
|
||||
return TEAM_TRIGGERER;
|
||||
}
|
||||
|
||||
return this.normalizeExplicitTeamType(value);
|
||||
}
|
||||
|
||||
protected GameTeamColors resolveConfiguredTeamColor(int value) {
|
||||
return GameTeamColors.fromType(this.normalizeExplicitTeamType(value));
|
||||
}
|
||||
|
||||
protected boolean compareValue(int actual, int expected, int comparison) {
|
||||
switch (comparison) {
|
||||
case COMPARISON_LOWER:
|
||||
return actual < expected;
|
||||
case COMPARISON_HIGHER:
|
||||
return actual > expected;
|
||||
default:
|
||||
return actual == expected;
|
||||
}
|
||||
}
|
||||
|
||||
protected UserGameContext resolveUserGameContext(Room room, RoomUnit roomUnit) {
|
||||
if (room == null || roomUnit == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Habbo habbo = room.getHabbo(roomUnit);
|
||||
if (habbo == null || habbo.getHabboInfo() == null || habbo.getHabboInfo().getCurrentGame() == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Game game = room.getGame(habbo.getHabboInfo().getCurrentGame());
|
||||
if (!this.isSupportedGame(game)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
GameTeam team = game.getTeamForHabbo(habbo);
|
||||
if (team == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return new UserGameContext(habbo, game, team);
|
||||
}
|
||||
|
||||
protected int getTeamRank(Game game, GameTeam team) {
|
||||
if (game == null || team == null) {
|
||||
return Integer.MAX_VALUE;
|
||||
}
|
||||
|
||||
int rank = 1;
|
||||
int targetScore = team.getTotalScore();
|
||||
|
||||
for (GameTeamColors teamColor : SUPPORTED_TEAM_COLORS) {
|
||||
GameTeam otherTeam = game.getTeam(teamColor);
|
||||
if (otherTeam != null && otherTeam != team && otherTeam.getTotalScore() > targetScore) {
|
||||
rank++;
|
||||
}
|
||||
}
|
||||
|
||||
return rank;
|
||||
}
|
||||
|
||||
private boolean isSupportedGame(Game game) {
|
||||
return game != null
|
||||
&& game.getState() != GameState.IDLE
|
||||
&& (game instanceof FreezeGame || game instanceof BattleBanzaiGame);
|
||||
}
|
||||
|
||||
protected static class UserGameContext {
|
||||
protected final Habbo habbo;
|
||||
protected final Game game;
|
||||
protected final GameTeam team;
|
||||
|
||||
protected UserGameContext(Habbo habbo, Game game, GameTeam team) {
|
||||
this.habbo = habbo;
|
||||
this.game = game;
|
||||
this.team = team;
|
||||
}
|
||||
}
|
||||
}
|
||||
+175
@@ -0,0 +1,175 @@
|
||||
package com.eu.habbo.habbohotel.items.interactions.wired.conditions;
|
||||
|
||||
import com.eu.habbo.habbohotel.games.GameTeam;
|
||||
import com.eu.habbo.habbohotel.games.GameTeamColors;
|
||||
import com.eu.habbo.habbohotel.items.Item;
|
||||
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.WiredConditionType;
|
||||
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.messages.ServerMessage;
|
||||
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.List;
|
||||
|
||||
public class WiredConditionTeamHasRank extends WiredConditionTeamGameBase {
|
||||
public static final WiredConditionType type = WiredConditionType.TEAM_HAS_RANK;
|
||||
|
||||
private int teamType = GameTeamColors.RED.type;
|
||||
private int placement = 1;
|
||||
private int userSource = WiredSourceUtil.SOURCE_TRIGGER;
|
||||
private int quantifier = QUANTIFIER_ALL;
|
||||
|
||||
public WiredConditionTeamHasRank(ResultSet set, Item baseItem) throws SQLException {
|
||||
super(set, baseItem);
|
||||
}
|
||||
|
||||
public WiredConditionTeamHasRank(int id, int userId, Item item, String extradata, int limitedStack, int limitedSells) {
|
||||
super(id, userId, item, extradata, limitedStack, limitedSells);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean evaluate(WiredContext ctx) {
|
||||
Room room = ctx.room();
|
||||
List<RoomUnit> users = this.resolveUsers(ctx, this.userSource);
|
||||
|
||||
return this.matchesQuantifier(users, this.quantifier, roomUnit -> this.matchesUser(ctx, room, roomUnit));
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
@Override
|
||||
public boolean execute(RoomUnit roomUnit, Room room, Object[] stuff) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getWiredData() {
|
||||
return WiredManager.getGson().toJson(new JsonData(
|
||||
this.teamType,
|
||||
this.placement,
|
||||
this.userSource,
|
||||
this.quantifier
|
||||
));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadWiredData(ResultSet set, Room room) throws SQLException {
|
||||
this.resetSettings();
|
||||
|
||||
String wiredData = set.getString("wired_data");
|
||||
if (wiredData == null || !wiredData.startsWith("{")) {
|
||||
return;
|
||||
}
|
||||
|
||||
JsonData data = WiredManager.getGson().fromJson(wiredData, JsonData.class);
|
||||
if (data == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.teamType = this.normalizeRankTeamType(data.teamType);
|
||||
this.placement = this.normalizePlacement(data.placement);
|
||||
this.userSource = this.normalizeUserSource(data.userSource);
|
||||
this.quantifier = this.normalizeQuantifier(data.quantifier);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPickUp() {
|
||||
this.resetSettings();
|
||||
}
|
||||
|
||||
@Override
|
||||
public WiredConditionType getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void serializeWiredData(ServerMessage message, Room room) {
|
||||
message.appendBoolean(false);
|
||||
message.appendInt(5);
|
||||
message.appendInt(0);
|
||||
message.appendInt(this.getBaseItem().getSpriteId());
|
||||
message.appendInt(this.getId());
|
||||
message.appendString("");
|
||||
message.appendInt(4);
|
||||
message.appendInt(this.teamType);
|
||||
message.appendInt(this.placement);
|
||||
message.appendInt(this.userSource);
|
||||
message.appendInt(this.quantifier);
|
||||
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.resetSettings();
|
||||
|
||||
if (params.length > 0) this.teamType = this.normalizeRankTeamType(params[0]);
|
||||
if (params.length > 1) this.placement = this.normalizePlacement(params[1]);
|
||||
if (params.length > 2) this.userSource = this.normalizeUserSource(params[2]);
|
||||
if (params.length > 3) this.quantifier = this.normalizeQuantifier(params[3]);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean matchesUser(WiredContext ctx, Room room, RoomUnit roomUnit) {
|
||||
UserGameContext context = this.resolveUserGameContext(room, roomUnit);
|
||||
if (context == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
GameTeamColors requiredTeam = this.resolveRequiredTeamColor(ctx, room, context.game);
|
||||
if (requiredTeam == GameTeamColors.NONE || context.team.teamColor != requiredTeam) {
|
||||
return false;
|
||||
}
|
||||
|
||||
GameTeam team = context.game.getTeam(requiredTeam);
|
||||
if (team == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return this.getTeamRank(context.game, team) == this.placement;
|
||||
}
|
||||
|
||||
private GameTeamColors resolveRequiredTeamColor(WiredContext ctx, Room room, com.eu.habbo.habbohotel.games.Game game) {
|
||||
if (this.teamType == TEAM_TRIGGERER) {
|
||||
RoomUnit actor = ctx.actor().orElse(null);
|
||||
UserGameContext triggererContext = this.resolveUserGameContext(room, actor);
|
||||
|
||||
if (triggererContext == null || triggererContext.game != game) {
|
||||
return GameTeamColors.NONE;
|
||||
}
|
||||
|
||||
return triggererContext.team.teamColor;
|
||||
}
|
||||
|
||||
return this.resolveConfiguredTeamColor(this.teamType);
|
||||
}
|
||||
|
||||
private void resetSettings() {
|
||||
this.teamType = GameTeamColors.RED.type;
|
||||
this.placement = 1;
|
||||
this.userSource = WiredSourceUtil.SOURCE_TRIGGER;
|
||||
this.quantifier = QUANTIFIER_ALL;
|
||||
}
|
||||
|
||||
static class JsonData {
|
||||
int teamType;
|
||||
int placement;
|
||||
int userSource;
|
||||
int quantifier;
|
||||
|
||||
public JsonData(int teamType, int placement, int userSource, int quantifier) {
|
||||
this.teamType = teamType;
|
||||
this.placement = placement;
|
||||
this.userSource = userSource;
|
||||
this.quantifier = quantifier;
|
||||
}
|
||||
}
|
||||
}
|
||||
+162
@@ -0,0 +1,162 @@
|
||||
package com.eu.habbo.habbohotel.items.interactions.wired.conditions;
|
||||
|
||||
import com.eu.habbo.habbohotel.games.GameTeamColors;
|
||||
import com.eu.habbo.habbohotel.items.Item;
|
||||
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.WiredConditionType;
|
||||
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.messages.ServerMessage;
|
||||
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.List;
|
||||
|
||||
public class WiredConditionTeamHasScore extends WiredConditionTeamGameBase {
|
||||
public static final WiredConditionType type = WiredConditionType.TEAM_HAS_SCORE;
|
||||
|
||||
private int teamType = GameTeamColors.RED.type;
|
||||
private int comparison = COMPARISON_EQUAL;
|
||||
private int score = 0;
|
||||
private int userSource = WiredSourceUtil.SOURCE_TRIGGER;
|
||||
private int quantifier = QUANTIFIER_ALL;
|
||||
|
||||
public WiredConditionTeamHasScore(ResultSet set, Item baseItem) throws SQLException {
|
||||
super(set, baseItem);
|
||||
}
|
||||
|
||||
public WiredConditionTeamHasScore(int id, int userId, Item item, String extradata, int limitedStack, int limitedSells) {
|
||||
super(id, userId, item, extradata, limitedStack, limitedSells);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean evaluate(WiredContext ctx) {
|
||||
Room room = ctx.room();
|
||||
List<RoomUnit> users = this.resolveUsers(ctx, this.userSource);
|
||||
|
||||
return this.matchesQuantifier(users, this.quantifier, roomUnit -> this.matchesUser(room, roomUnit));
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
@Override
|
||||
public boolean execute(RoomUnit roomUnit, Room room, Object[] stuff) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getWiredData() {
|
||||
return WiredManager.getGson().toJson(new JsonData(
|
||||
this.teamType,
|
||||
this.comparison,
|
||||
this.score,
|
||||
this.userSource,
|
||||
this.quantifier
|
||||
));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadWiredData(ResultSet set, Room room) throws SQLException {
|
||||
this.resetSettings();
|
||||
|
||||
String wiredData = set.getString("wired_data");
|
||||
if (wiredData == null || !wiredData.startsWith("{")) {
|
||||
return;
|
||||
}
|
||||
|
||||
JsonData data = WiredManager.getGson().fromJson(wiredData, JsonData.class);
|
||||
if (data == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.teamType = this.normalizeExplicitTeamType(data.teamType);
|
||||
this.comparison = this.normalizeComparison(data.comparison);
|
||||
this.score = this.normalizeScore(data.score);
|
||||
this.userSource = this.normalizeUserSource(data.userSource);
|
||||
this.quantifier = this.normalizeQuantifier(data.quantifier);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPickUp() {
|
||||
this.resetSettings();
|
||||
}
|
||||
|
||||
@Override
|
||||
public WiredConditionType getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void serializeWiredData(ServerMessage message, Room room) {
|
||||
message.appendBoolean(false);
|
||||
message.appendInt(5);
|
||||
message.appendInt(0);
|
||||
message.appendInt(this.getBaseItem().getSpriteId());
|
||||
message.appendInt(this.getId());
|
||||
message.appendString("");
|
||||
message.appendInt(5);
|
||||
message.appendInt(this.teamType);
|
||||
message.appendInt(this.comparison);
|
||||
message.appendInt(this.score);
|
||||
message.appendInt(this.userSource);
|
||||
message.appendInt(this.quantifier);
|
||||
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.resetSettings();
|
||||
|
||||
if (params.length > 0) this.teamType = this.normalizeExplicitTeamType(params[0]);
|
||||
if (params.length > 1) this.comparison = this.normalizeComparison(params[1]);
|
||||
if (params.length > 2) this.score = this.normalizeScore(params[2]);
|
||||
if (params.length > 3) this.userSource = this.normalizeUserSource(params[3]);
|
||||
if (params.length > 4) this.quantifier = this.normalizeQuantifier(params[4]);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean matchesUser(Room room, RoomUnit roomUnit) {
|
||||
UserGameContext context = this.resolveUserGameContext(room, roomUnit);
|
||||
if (context == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
GameTeamColors requiredTeam = this.resolveConfiguredTeamColor(this.teamType);
|
||||
if (context.team.teamColor != requiredTeam) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return this.compareValue(context.team.getTotalScore(), this.score, this.comparison);
|
||||
}
|
||||
|
||||
private void resetSettings() {
|
||||
this.teamType = GameTeamColors.RED.type;
|
||||
this.comparison = COMPARISON_EQUAL;
|
||||
this.score = 0;
|
||||
this.userSource = WiredSourceUtil.SOURCE_TRIGGER;
|
||||
this.quantifier = QUANTIFIER_ALL;
|
||||
}
|
||||
|
||||
static class JsonData {
|
||||
int teamType;
|
||||
int comparison;
|
||||
int score;
|
||||
int userSource;
|
||||
int quantifier;
|
||||
|
||||
public JsonData(int teamType, int comparison, int score, int userSource, int quantifier) {
|
||||
this.teamType = teamType;
|
||||
this.comparison = comparison;
|
||||
this.score = score;
|
||||
this.userSource = userSource;
|
||||
this.quantifier = quantifier;
|
||||
}
|
||||
}
|
||||
}
|
||||
+368
@@ -0,0 +1,368 @@
|
||||
package com.eu.habbo.habbohotel.items.interactions.wired.conditions;
|
||||
|
||||
import com.eu.habbo.habbohotel.bots.Bot;
|
||||
import com.eu.habbo.habbohotel.items.Item;
|
||||
import com.eu.habbo.habbohotel.items.interactions.InteractionWiredCondition;
|
||||
import com.eu.habbo.habbohotel.items.interactions.wired.WiredSettings;
|
||||
import com.eu.habbo.habbohotel.pets.Pet;
|
||||
import com.eu.habbo.habbohotel.rooms.Room;
|
||||
import com.eu.habbo.habbohotel.rooms.RoomUnit;
|
||||
import com.eu.habbo.habbohotel.rooms.RoomUnitType;
|
||||
import com.eu.habbo.habbohotel.users.Habbo;
|
||||
import com.eu.habbo.habbohotel.wired.WiredConditionType;
|
||||
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.messages.ServerMessage;
|
||||
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class WiredConditionTriggererMatch extends InteractionWiredCondition {
|
||||
protected static final int ENTITY_HABBO = 1;
|
||||
protected static final int ENTITY_PET = 2;
|
||||
protected static final int ENTITY_BOT = 4;
|
||||
protected static final int AVATAR_MODE_ANY = 0;
|
||||
protected static final int AVATAR_MODE_CERTAIN = 1;
|
||||
protected static final int QUANTIFIER_ALL = 0;
|
||||
protected static final int QUANTIFIER_ANY = 1;
|
||||
protected static final int SOURCE_SPECIFIED_USERNAME = 101;
|
||||
|
||||
public static final WiredConditionType type = WiredConditionType.TRIGGERER_MATCH;
|
||||
|
||||
private int entityType = ENTITY_HABBO;
|
||||
private int avatarMode = AVATAR_MODE_ANY;
|
||||
private int matchUserSource = WiredSourceUtil.SOURCE_TRIGGER;
|
||||
private int compareUserSource = WiredSourceUtil.SOURCE_TRIGGER;
|
||||
private int quantifier = QUANTIFIER_ALL;
|
||||
private String username = "";
|
||||
|
||||
public WiredConditionTriggererMatch(ResultSet set, Item baseItem) throws SQLException {
|
||||
super(set, baseItem);
|
||||
}
|
||||
|
||||
public WiredConditionTriggererMatch(int id, int userId, Item item, String extradata, int limitedStack, int limitedSells) {
|
||||
super(id, userId, item, extradata, limitedStack, limitedSells);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean evaluate(WiredContext ctx) {
|
||||
MatchResult result = this.evaluateMatch(ctx);
|
||||
return result.valid && result.matched;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
@Override
|
||||
public boolean execute(RoomUnit roomUnit, Room room, Object[] stuff) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getWiredData() {
|
||||
return WiredManager.getGson().toJson(new JsonData(
|
||||
this.entityType,
|
||||
this.avatarMode,
|
||||
this.matchUserSource,
|
||||
this.compareUserSource,
|
||||
this.quantifier,
|
||||
this.username
|
||||
));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadWiredData(ResultSet set, Room room) throws SQLException {
|
||||
this.resetSettings();
|
||||
|
||||
String wiredData = set.getString("wired_data");
|
||||
if (wiredData == null || !wiredData.startsWith("{")) {
|
||||
return;
|
||||
}
|
||||
|
||||
JsonData data = WiredManager.getGson().fromJson(wiredData, JsonData.class);
|
||||
if (data == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.entityType = this.normalizeEntityType(data.entityType);
|
||||
this.avatarMode = this.normalizeAvatarMode(data.avatarMode);
|
||||
this.matchUserSource = this.normalizePrimaryUserSource(data.matchUserSource);
|
||||
this.compareUserSource = this.normalizeCompareUserSource(data.compareUserSource);
|
||||
this.quantifier = this.normalizeQuantifier(data.quantifier);
|
||||
this.username = this.normalizeUsername(data.username);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPickUp() {
|
||||
this.resetSettings();
|
||||
}
|
||||
|
||||
@Override
|
||||
public WiredConditionType getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void serializeWiredData(ServerMessage message, Room room) {
|
||||
message.appendBoolean(true);
|
||||
message.appendInt(5);
|
||||
message.appendInt(0);
|
||||
message.appendInt(this.getBaseItem().getSpriteId());
|
||||
message.appendInt(this.getId());
|
||||
message.appendString(this.username);
|
||||
message.appendInt(5);
|
||||
message.appendInt(this.entityType);
|
||||
message.appendInt(this.avatarMode);
|
||||
message.appendInt(this.matchUserSource);
|
||||
message.appendInt(this.compareUserSource);
|
||||
message.appendInt(this.quantifier);
|
||||
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.resetSettings();
|
||||
|
||||
if (params.length > 0) this.entityType = this.normalizeEntityType(params[0]);
|
||||
if (params.length > 1) this.avatarMode = this.normalizeAvatarMode(params[1]);
|
||||
if (params.length > 2) this.matchUserSource = this.normalizePrimaryUserSource(params[2]);
|
||||
if (params.length > 3) this.compareUserSource = this.normalizeCompareUserSource(params[3]);
|
||||
if (params.length > 4) this.quantifier = this.normalizeQuantifier(params[4]);
|
||||
|
||||
this.username = this.normalizeUsername(settings.getStringParam());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
protected MatchResult evaluateMatch(WiredContext ctx) {
|
||||
List<RoomUnit> matchUsers = this.resolvePrimaryUsers(ctx);
|
||||
if (matchUsers.isEmpty()) {
|
||||
return MatchResult.invalid();
|
||||
}
|
||||
|
||||
List<RoomUnit> compareUsers = this.resolveCompareUsers(ctx);
|
||||
if (compareUsers.isEmpty()) {
|
||||
return MatchResult.valid(false);
|
||||
}
|
||||
|
||||
Set<Integer> compareUserIds = compareUsers.stream()
|
||||
.filter(this::matchesEntityType)
|
||||
.map(RoomUnit::getId)
|
||||
.collect(Collectors.toSet());
|
||||
|
||||
if (compareUserIds.isEmpty()) {
|
||||
return MatchResult.valid(false);
|
||||
}
|
||||
|
||||
boolean matched;
|
||||
if (this.quantifier == QUANTIFIER_ANY) {
|
||||
matched = matchUsers.stream().anyMatch(roomUnit -> this.matchesCandidate(roomUnit, compareUserIds));
|
||||
} else {
|
||||
matched = matchUsers.stream().allMatch(roomUnit -> this.matchesCandidate(roomUnit, compareUserIds));
|
||||
}
|
||||
|
||||
return MatchResult.valid(matched);
|
||||
}
|
||||
|
||||
protected int getQuantifier() {
|
||||
return this.quantifier;
|
||||
}
|
||||
|
||||
private void resetSettings() {
|
||||
this.entityType = ENTITY_HABBO;
|
||||
this.avatarMode = AVATAR_MODE_ANY;
|
||||
this.matchUserSource = WiredSourceUtil.SOURCE_TRIGGER;
|
||||
this.compareUserSource = WiredSourceUtil.SOURCE_TRIGGER;
|
||||
this.quantifier = QUANTIFIER_ALL;
|
||||
this.username = "";
|
||||
}
|
||||
|
||||
private List<RoomUnit> resolvePrimaryUsers(WiredContext ctx) {
|
||||
return this.deduplicate(WiredSourceUtil.resolveUsers(ctx, this.matchUserSource));
|
||||
}
|
||||
|
||||
private List<RoomUnit> resolveCompareUsers(WiredContext ctx) {
|
||||
List<RoomUnit> resolved;
|
||||
|
||||
if (this.compareUserSource == SOURCE_SPECIFIED_USERNAME) {
|
||||
resolved = this.resolveUsersByName(ctx.room(), this.username);
|
||||
} else {
|
||||
resolved = WiredSourceUtil.resolveUsers(ctx, this.compareUserSource);
|
||||
}
|
||||
|
||||
if (this.avatarMode == AVATAR_MODE_CERTAIN) {
|
||||
String normalizedName = this.normalizeUsername(this.username);
|
||||
if (normalizedName.isEmpty()) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
resolved = resolved.stream()
|
||||
.filter(roomUnit -> normalizedName.equalsIgnoreCase(this.getRoomUnitName(ctx.room(), roomUnit)))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
return this.deduplicate(resolved);
|
||||
}
|
||||
|
||||
private List<RoomUnit> resolveUsersByName(Room room, String username) {
|
||||
List<RoomUnit> result = new ArrayList<>();
|
||||
String normalizedName = this.normalizeUsername(username);
|
||||
if (room == null || normalizedName.isEmpty()) {
|
||||
return result;
|
||||
}
|
||||
|
||||
Habbo habbo = room.getHabbo(normalizedName);
|
||||
if (habbo != null && habbo.getRoomUnit() != null) {
|
||||
result.add(habbo.getRoomUnit());
|
||||
}
|
||||
|
||||
for (Bot bot : room.getBots(normalizedName)) {
|
||||
if (bot != null && bot.getRoomUnit() != null) {
|
||||
result.add(bot.getRoomUnit());
|
||||
}
|
||||
}
|
||||
|
||||
for (Pet pet : room.getUnitManager().getPets()) {
|
||||
if (pet != null && pet.getRoomUnit() != null && normalizedName.equalsIgnoreCase(pet.getName())) {
|
||||
result.add(pet.getRoomUnit());
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private List<RoomUnit> deduplicate(List<RoomUnit> users) {
|
||||
Map<Integer, RoomUnit> deduplicated = new LinkedHashMap<>();
|
||||
|
||||
for (RoomUnit user : users) {
|
||||
if (user != null) {
|
||||
deduplicated.putIfAbsent(user.getId(), user);
|
||||
}
|
||||
}
|
||||
|
||||
return new ArrayList<>(deduplicated.values());
|
||||
}
|
||||
|
||||
private boolean matchesCandidate(RoomUnit roomUnit, Set<Integer> compareUserIds) {
|
||||
return roomUnit != null && this.matchesEntityType(roomUnit) && compareUserIds.contains(roomUnit.getId());
|
||||
}
|
||||
|
||||
private boolean matchesEntityType(RoomUnit roomUnit) {
|
||||
return roomUnit != null && roomUnit.getRoomUnitType().getTypeId() == this.entityType;
|
||||
}
|
||||
|
||||
private String getRoomUnitName(Room room, RoomUnit roomUnit) {
|
||||
if (room == null || roomUnit == null) {
|
||||
return "";
|
||||
}
|
||||
|
||||
if (roomUnit.getRoomUnitType() == RoomUnitType.USER) {
|
||||
Habbo habbo = room.getHabbo(roomUnit);
|
||||
return (habbo != null && habbo.getHabboInfo() != null) ? habbo.getHabboInfo().getUsername() : "";
|
||||
}
|
||||
|
||||
if (roomUnit.getRoomUnitType() == RoomUnitType.BOT) {
|
||||
Bot bot = room.getBot(roomUnit);
|
||||
return (bot != null) ? bot.getName() : "";
|
||||
}
|
||||
|
||||
if (roomUnit.getRoomUnitType() == RoomUnitType.PET) {
|
||||
Pet pet = room.getPet(roomUnit);
|
||||
return (pet != null) ? pet.getName() : "";
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
private int normalizeEntityType(int value) {
|
||||
switch (value) {
|
||||
case ENTITY_HABBO:
|
||||
case ENTITY_PET:
|
||||
case ENTITY_BOT:
|
||||
return value;
|
||||
default:
|
||||
return ENTITY_HABBO;
|
||||
}
|
||||
}
|
||||
|
||||
private int normalizeAvatarMode(int value) {
|
||||
return (value == AVATAR_MODE_CERTAIN) ? AVATAR_MODE_CERTAIN : AVATAR_MODE_ANY;
|
||||
}
|
||||
|
||||
private int normalizeQuantifier(int value) {
|
||||
return (value == QUANTIFIER_ANY) ? QUANTIFIER_ANY : QUANTIFIER_ALL;
|
||||
}
|
||||
|
||||
private int normalizePrimaryUserSource(int value) {
|
||||
switch (value) {
|
||||
case WiredSourceUtil.SOURCE_SELECTOR:
|
||||
case WiredSourceUtil.SOURCE_SIGNAL:
|
||||
case WiredSourceUtil.SOURCE_TRIGGER:
|
||||
return value;
|
||||
default:
|
||||
return WiredSourceUtil.SOURCE_TRIGGER;
|
||||
}
|
||||
}
|
||||
|
||||
private int normalizeCompareUserSource(int value) {
|
||||
switch (value) {
|
||||
case WiredSourceUtil.SOURCE_SELECTOR:
|
||||
case WiredSourceUtil.SOURCE_SIGNAL:
|
||||
case WiredSourceUtil.SOURCE_TRIGGER:
|
||||
case SOURCE_SPECIFIED_USERNAME:
|
||||
return value;
|
||||
default:
|
||||
return WiredSourceUtil.SOURCE_TRIGGER;
|
||||
}
|
||||
}
|
||||
|
||||
private String normalizeUsername(String value) {
|
||||
return (value == null) ? "" : value.trim();
|
||||
}
|
||||
|
||||
protected static class MatchResult {
|
||||
protected final boolean valid;
|
||||
protected final boolean matched;
|
||||
|
||||
private MatchResult(boolean valid, boolean matched) {
|
||||
this.valid = valid;
|
||||
this.matched = matched;
|
||||
}
|
||||
|
||||
private static MatchResult invalid() {
|
||||
return new MatchResult(false, false);
|
||||
}
|
||||
|
||||
private static MatchResult valid(boolean matched) {
|
||||
return new MatchResult(true, matched);
|
||||
}
|
||||
}
|
||||
|
||||
static class JsonData {
|
||||
int entityType;
|
||||
int avatarMode;
|
||||
int matchUserSource;
|
||||
int compareUserSource;
|
||||
int quantifier;
|
||||
String username;
|
||||
|
||||
public JsonData(int entityType, int avatarMode, int matchUserSource, int compareUserSource, int quantifier, String username) {
|
||||
this.entityType = entityType;
|
||||
this.avatarMode = avatarMode;
|
||||
this.matchUserSource = matchUserSource;
|
||||
this.compareUserSource = compareUserSource;
|
||||
this.quantifier = quantifier;
|
||||
this.username = username;
|
||||
}
|
||||
}
|
||||
}
|
||||
+346
@@ -0,0 +1,346 @@
|
||||
package com.eu.habbo.habbohotel.items.interactions.wired.conditions;
|
||||
|
||||
import com.eu.habbo.habbohotel.items.Item;
|
||||
import com.eu.habbo.habbohotel.items.interactions.InteractionWiredCondition;
|
||||
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.rooms.RoomUnitStatus;
|
||||
import com.eu.habbo.habbohotel.wired.WiredConditionType;
|
||||
import com.eu.habbo.habbohotel.wired.WiredUserActionType;
|
||||
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.messages.ServerMessage;
|
||||
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.List;
|
||||
|
||||
public class WiredConditionUserPerformsAction extends InteractionWiredCondition {
|
||||
private static final String CACHE_LAST_ACTION_ID = "wired.last_user_action.id";
|
||||
private static final String CACHE_LAST_ACTION_PARAMETER = "wired.last_user_action.parameter";
|
||||
private static final String CACHE_LAST_ACTION_TIMESTAMP = "wired.last_user_action.timestamp";
|
||||
private static final long TRANSIENT_ACTION_WINDOW_MS = 5_000L;
|
||||
protected static final int DEFAULT_ACTION = WiredUserActionType.WAVE;
|
||||
protected static final int QUANTIFIER_ALL = 0;
|
||||
protected static final int QUANTIFIER_ANY = 1;
|
||||
|
||||
public static final WiredConditionType type = WiredConditionType.USER_PERFORMS_ACTION;
|
||||
|
||||
private int selectedAction = DEFAULT_ACTION;
|
||||
private boolean signFilterEnabled = false;
|
||||
private int signId = 0;
|
||||
private boolean danceFilterEnabled = false;
|
||||
private int danceId = 1;
|
||||
private int userSource = WiredSourceUtil.SOURCE_TRIGGER;
|
||||
private int quantifier = QUANTIFIER_ALL;
|
||||
|
||||
public WiredConditionUserPerformsAction(ResultSet set, Item baseItem) throws SQLException {
|
||||
super(set, baseItem);
|
||||
}
|
||||
|
||||
public WiredConditionUserPerformsAction(int id, int userId, Item item, String extradata, int limitedStack, int limitedSells) {
|
||||
super(id, userId, item, extradata, limitedStack, limitedSells);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean evaluate(WiredContext ctx) {
|
||||
List<RoomUnit> targets = WiredSourceUtil.resolveUsers(ctx, this.userSource);
|
||||
if (targets.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (this.quantifier == QUANTIFIER_ANY) {
|
||||
return targets.stream().anyMatch(roomUnit -> this.matchesAction(ctx, roomUnit));
|
||||
}
|
||||
|
||||
return targets.stream().allMatch(roomUnit -> this.matchesAction(ctx, roomUnit));
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
@Override
|
||||
public boolean execute(RoomUnit roomUnit, Room room, Object[] stuff) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getWiredData() {
|
||||
return WiredManager.getGson().toJson(new JsonData(
|
||||
this.selectedAction,
|
||||
this.signFilterEnabled,
|
||||
this.signId,
|
||||
this.danceFilterEnabled,
|
||||
this.danceId,
|
||||
this.userSource,
|
||||
this.quantifier
|
||||
));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadWiredData(ResultSet set, Room room) throws SQLException {
|
||||
this.resetSettings();
|
||||
|
||||
String wiredData = set.getString("wired_data");
|
||||
|
||||
if (wiredData == null || !wiredData.startsWith("{")) {
|
||||
return;
|
||||
}
|
||||
|
||||
JsonData data = WiredManager.getGson().fromJson(wiredData, JsonData.class);
|
||||
|
||||
if (data == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.selectedAction = normalizeAction(data.selectedAction);
|
||||
this.signFilterEnabled = data.signFilterEnabled;
|
||||
this.signId = normalizeSignId(data.signId);
|
||||
this.danceFilterEnabled = data.danceFilterEnabled;
|
||||
this.danceId = normalizeDanceId(data.danceId);
|
||||
this.userSource = this.normalizeUserSource(data.userSource);
|
||||
this.quantifier = normalizeQuantifier(data.quantifier);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPickUp() {
|
||||
this.resetSettings();
|
||||
}
|
||||
|
||||
@Override
|
||||
public WiredConditionType getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void serializeWiredData(ServerMessage message, Room room) {
|
||||
message.appendBoolean(true);
|
||||
message.appendInt(5);
|
||||
message.appendInt(0);
|
||||
message.appendInt(this.getBaseItem().getSpriteId());
|
||||
message.appendInt(this.getId());
|
||||
message.appendString("");
|
||||
message.appendInt(7);
|
||||
message.appendInt(this.selectedAction);
|
||||
message.appendInt(this.signFilterEnabled ? 1 : 0);
|
||||
message.appendInt(this.signId);
|
||||
message.appendInt(this.danceFilterEnabled ? 1 : 0);
|
||||
message.appendInt(this.danceId);
|
||||
message.appendInt(this.userSource);
|
||||
message.appendInt(this.quantifier);
|
||||
message.appendInt(0);
|
||||
message.appendInt(this.getType().code);
|
||||
message.appendInt(0);
|
||||
message.appendInt(0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean saveData(WiredSettings settings) {
|
||||
int[] intParams = settings.getIntParams();
|
||||
|
||||
this.resetSettings();
|
||||
|
||||
if (intParams.length > 0) this.selectedAction = normalizeAction(intParams[0]);
|
||||
if (intParams.length > 1) this.signFilterEnabled = (intParams[1] == 1);
|
||||
if (intParams.length > 2) this.signId = normalizeSignId(intParams[2]);
|
||||
if (intParams.length > 3) this.danceFilterEnabled = (intParams[3] == 1);
|
||||
if (intParams.length > 4) this.danceId = normalizeDanceId(intParams[4]);
|
||||
if (intParams.length > 5) this.userSource = this.normalizeUserSource(intParams[5]);
|
||||
if (intParams.length > 6) this.quantifier = normalizeQuantifier(intParams[6]);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
protected void resetSettings() {
|
||||
this.selectedAction = DEFAULT_ACTION;
|
||||
this.signFilterEnabled = false;
|
||||
this.signId = 0;
|
||||
this.danceFilterEnabled = false;
|
||||
this.danceId = 1;
|
||||
this.userSource = WiredSourceUtil.SOURCE_TRIGGER;
|
||||
this.quantifier = QUANTIFIER_ALL;
|
||||
}
|
||||
|
||||
protected int normalizeAction(int action) {
|
||||
switch (action) {
|
||||
case WiredUserActionType.WAVE:
|
||||
case WiredUserActionType.BLOW_KISS:
|
||||
case WiredUserActionType.LAUGH:
|
||||
case WiredUserActionType.AWAKE:
|
||||
case WiredUserActionType.RELAX:
|
||||
case WiredUserActionType.SIT:
|
||||
case WiredUserActionType.STAND:
|
||||
case WiredUserActionType.LAY:
|
||||
case WiredUserActionType.SIGN:
|
||||
case WiredUserActionType.DANCE:
|
||||
case WiredUserActionType.THUMB_UP:
|
||||
return action;
|
||||
default:
|
||||
return DEFAULT_ACTION;
|
||||
}
|
||||
}
|
||||
|
||||
protected int normalizeQuantifier(int value) {
|
||||
return (value == QUANTIFIER_ANY) ? QUANTIFIER_ANY : QUANTIFIER_ALL;
|
||||
}
|
||||
|
||||
protected int normalizeUserSource(int value) {
|
||||
switch (value) {
|
||||
case WiredSourceUtil.SOURCE_SELECTOR:
|
||||
case WiredSourceUtil.SOURCE_SIGNAL:
|
||||
case WiredSourceUtil.SOURCE_TRIGGER:
|
||||
return value;
|
||||
default:
|
||||
return WiredSourceUtil.SOURCE_TRIGGER;
|
||||
}
|
||||
}
|
||||
|
||||
protected int normalizeSignId(int value) {
|
||||
return (value < 0 || value > 17) ? 0 : value;
|
||||
}
|
||||
|
||||
protected int normalizeDanceId(int value) {
|
||||
return (value < 1 || value > 4) ? 1 : value;
|
||||
}
|
||||
|
||||
protected boolean matchesAction(WiredContext ctx, RoomUnit roomUnit) {
|
||||
if (roomUnit == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (this.matchesEventAction(ctx, roomUnit)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (this.matchesCurrentState(roomUnit)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return this.matchesRecentAction(roomUnit);
|
||||
}
|
||||
|
||||
protected boolean matchesEventAction(WiredContext ctx, RoomUnit roomUnit) {
|
||||
RoomUnit actor = ctx.actor().orElse(null);
|
||||
|
||||
if (actor == null || actor.getId() != roomUnit.getId()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (ctx.eventType() != com.eu.habbo.habbohotel.wired.core.WiredEvent.Type.USER_PERFORMS_ACTION) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return this.matchesConfiguredAction(ctx.event().getActionId(), ctx.event().getActionParameter());
|
||||
}
|
||||
|
||||
protected boolean matchesCurrentState(RoomUnit roomUnit) {
|
||||
switch (this.selectedAction) {
|
||||
case WiredUserActionType.SIT:
|
||||
return roomUnit.hasStatus(RoomUnitStatus.SIT);
|
||||
case WiredUserActionType.LAY:
|
||||
return roomUnit.hasStatus(RoomUnitStatus.LAY);
|
||||
case WiredUserActionType.RELAX:
|
||||
return roomUnit.isIdle();
|
||||
case WiredUserActionType.SIGN:
|
||||
return this.matchesSignState(roomUnit);
|
||||
case WiredUserActionType.DANCE:
|
||||
return this.matchesDanceState(roomUnit);
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
protected boolean matchesRecentAction(RoomUnit roomUnit) {
|
||||
Object actionValue = roomUnit.getCacheable().get(CACHE_LAST_ACTION_ID);
|
||||
Object parameterValue = roomUnit.getCacheable().get(CACHE_LAST_ACTION_PARAMETER);
|
||||
Object timestampValue = roomUnit.getCacheable().get(CACHE_LAST_ACTION_TIMESTAMP);
|
||||
|
||||
if (!(actionValue instanceof Integer) || !(timestampValue instanceof Long)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
long timestamp = (Long) timestampValue;
|
||||
if ((System.currentTimeMillis() - timestamp) > TRANSIENT_ACTION_WINDOW_MS) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int actionId = (Integer) actionValue;
|
||||
int parameter = (parameterValue instanceof Integer) ? (Integer) parameterValue : -1;
|
||||
|
||||
return this.matchesConfiguredAction(actionId, parameter);
|
||||
}
|
||||
|
||||
protected boolean matchesConfiguredAction(int actionId, int actionParameter) {
|
||||
if (actionId != this.selectedAction) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (this.selectedAction == WiredUserActionType.SIGN && this.signFilterEnabled) {
|
||||
return actionParameter == this.signId;
|
||||
}
|
||||
|
||||
if (this.selectedAction == WiredUserActionType.DANCE && this.danceFilterEnabled) {
|
||||
return actionParameter == this.danceId;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
protected boolean matchesSignState(RoomUnit roomUnit) {
|
||||
String signStatus = roomUnit.getStatus(RoomUnitStatus.SIGN);
|
||||
if (signStatus == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!this.signFilterEnabled) {
|
||||
return true;
|
||||
}
|
||||
|
||||
try {
|
||||
return Integer.parseInt(signStatus) == this.signId;
|
||||
} catch (NumberFormatException ignored) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
protected boolean matchesDanceState(RoomUnit roomUnit) {
|
||||
int currentDance = roomUnit.getDanceType().getType();
|
||||
if (currentDance <= 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!this.danceFilterEnabled) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return currentDance == this.danceId;
|
||||
}
|
||||
|
||||
protected int getUserSource() {
|
||||
return this.userSource;
|
||||
}
|
||||
|
||||
protected int getQuantifier() {
|
||||
return this.quantifier;
|
||||
}
|
||||
|
||||
static class JsonData {
|
||||
int selectedAction;
|
||||
boolean signFilterEnabled;
|
||||
int signId;
|
||||
boolean danceFilterEnabled;
|
||||
int danceId;
|
||||
int userSource;
|
||||
int quantifier;
|
||||
|
||||
public JsonData(int selectedAction, boolean signFilterEnabled, int signId, boolean danceFilterEnabled, int danceId, int userSource, int quantifier) {
|
||||
this.selectedAction = selectedAction;
|
||||
this.signFilterEnabled = signFilterEnabled;
|
||||
this.signId = signId;
|
||||
this.danceFilterEnabled = danceFilterEnabled;
|
||||
this.danceId = danceId;
|
||||
this.userSource = userSource;
|
||||
this.quantifier = quantifier;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -26,7 +26,17 @@ public enum WiredConditionType {
|
||||
DATE_RANGE(24),
|
||||
ACTOR_HAS_HANDITEM(25),
|
||||
MOVEMENT_VALIDATION(26), // i dont know what type it is but its needed
|
||||
COUNTER_TIME_MATCHES(27);
|
||||
COUNTER_TIME_MATCHES(27),
|
||||
USER_PERFORMS_ACTION(28),
|
||||
HAS_ALTITUDE(29),
|
||||
NOT_USER_PERFORMS_ACTION(30),
|
||||
NOT_ACTOR_HAS_HANDITEM(31),
|
||||
TRIGGERER_MATCH(32),
|
||||
NOT_TRIGGERER_MATCH(33),
|
||||
TEAM_HAS_SCORE(34),
|
||||
TEAM_HAS_RANK(35),
|
||||
MATCH_TIME(36),
|
||||
MATCH_DATE(37);
|
||||
|
||||
public final int code;
|
||||
|
||||
|
||||
@@ -64,6 +64,9 @@ import java.sql.SQLException;
|
||||
* @see WiredEvents
|
||||
*/
|
||||
public final class WiredManager {
|
||||
private static final String CACHE_LAST_ACTION_ID = "wired.last_user_action.id";
|
||||
private static final String CACHE_LAST_ACTION_PARAMETER = "wired.last_user_action.parameter";
|
||||
private static final String CACHE_LAST_ACTION_TIMESTAMP = "wired.last_user_action.timestamp";
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(WiredManager.class);
|
||||
|
||||
@@ -279,6 +282,10 @@ public final class WiredManager {
|
||||
return false;
|
||||
}
|
||||
|
||||
user.getCacheable().put(CACHE_LAST_ACTION_ID, actionId);
|
||||
user.getCacheable().put(CACHE_LAST_ACTION_PARAMETER, actionParameter);
|
||||
user.getCacheable().put(CACHE_LAST_ACTION_TIMESTAMP, System.currentTimeMillis());
|
||||
|
||||
WiredEvent event = WiredEvents.userPerformsAction(room, user, actionId, actionParameter);
|
||||
return handleEvent(event);
|
||||
}
|
||||
|
||||
+7
-10
@@ -3,6 +3,7 @@ package com.eu.habbo.habbohotel.wired.highscores;
|
||||
import com.eu.habbo.Emulator;
|
||||
import com.eu.habbo.plugin.EventHandler;
|
||||
import com.eu.habbo.plugin.events.emulator.EmulatorLoadedEvent;
|
||||
import com.eu.habbo.util.HotelDateTimeUtil;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@@ -11,9 +12,7 @@ import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.time.DayOfWeek;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.LocalTime;
|
||||
import java.time.ZoneId;
|
||||
import java.time.temporal.TemporalAdjusters;
|
||||
import java.time.temporal.WeekFields;
|
||||
import java.util.*;
|
||||
@@ -31,8 +30,6 @@ public class WiredHighscoreManager {
|
||||
|
||||
private final static DayOfWeek firstDayOfWeek = WeekFields.of(Locale.of(locale, country)).getFirstDayOfWeek();
|
||||
private final static DayOfWeek lastDayOfWeek = DayOfWeek.of(((firstDayOfWeek.getValue() + 5) % DayOfWeek.values().length) + 1);
|
||||
private final static ZoneId zoneId = ZoneId.systemDefault();
|
||||
|
||||
public static ScheduledFuture<?> midnightUpdater = null;
|
||||
|
||||
public void load() {
|
||||
@@ -183,26 +180,26 @@ public class WiredHighscoreManager {
|
||||
}
|
||||
|
||||
private long getTodayStartTimestamp() {
|
||||
return LocalDateTime.now().with(LocalTime.MIDNIGHT).atZone(zoneId).toEpochSecond();
|
||||
return HotelDateTimeUtil.toEpochSecond(HotelDateTimeUtil.localDateTimeNow().with(LocalTime.MIDNIGHT));
|
||||
}
|
||||
|
||||
private long getTodayEndTimestamp() {
|
||||
return LocalDateTime.now().with(LocalTime.MIDNIGHT).plusDays(1).plusSeconds(-1).atZone(zoneId).toEpochSecond();
|
||||
return HotelDateTimeUtil.toEpochSecond(HotelDateTimeUtil.localDateTimeNow().with(LocalTime.MIDNIGHT).plusDays(1).plusSeconds(-1));
|
||||
}
|
||||
|
||||
private long getWeekStartTimestamp() {
|
||||
return LocalDateTime.now().with(LocalTime.MIDNIGHT).with(TemporalAdjusters.previousOrSame(firstDayOfWeek)).atZone(zoneId).toEpochSecond();
|
||||
return HotelDateTimeUtil.toEpochSecond(HotelDateTimeUtil.localDateTimeNow().with(LocalTime.MIDNIGHT).with(TemporalAdjusters.previousOrSame(firstDayOfWeek)));
|
||||
}
|
||||
|
||||
private long getWeekEndTimestamp() {
|
||||
return LocalDateTime.now().with(LocalTime.MIDNIGHT).plusDays(1).plusSeconds(-1).with(TemporalAdjusters.nextOrSame(lastDayOfWeek)).atZone(zoneId).toEpochSecond();
|
||||
return HotelDateTimeUtil.toEpochSecond(HotelDateTimeUtil.localDateTimeNow().with(LocalTime.MIDNIGHT).plusDays(1).plusSeconds(-1).with(TemporalAdjusters.nextOrSame(lastDayOfWeek)));
|
||||
}
|
||||
|
||||
private long getMonthStartTimestamp() {
|
||||
return LocalDateTime.now().with(LocalTime.MIDNIGHT).with(TemporalAdjusters.firstDayOfMonth()).atZone(zoneId).toEpochSecond();
|
||||
return HotelDateTimeUtil.toEpochSecond(HotelDateTimeUtil.localDateTimeNow().with(LocalTime.MIDNIGHT).with(TemporalAdjusters.firstDayOfMonth()));
|
||||
}
|
||||
|
||||
private long getMonthEndTimestamp() {
|
||||
return LocalDateTime.now().with(LocalTime.MIDNIGHT).plusDays(1).plusSeconds(-1).with(TemporalAdjusters.lastDayOfMonth()).atZone(zoneId).toEpochSecond();
|
||||
return HotelDateTimeUtil.toEpochSecond(HotelDateTimeUtil.localDateTimeNow().with(LocalTime.MIDNIGHT).plusDays(1).plusSeconds(-1).with(TemporalAdjusters.lastDayOfMonth()));
|
||||
}
|
||||
}
|
||||
|
||||
+3
-3
@@ -4,11 +4,10 @@ import com.eu.habbo.Emulator;
|
||||
import com.eu.habbo.habbohotel.items.interactions.InteractionWiredHighscore;
|
||||
import com.eu.habbo.habbohotel.rooms.Room;
|
||||
import com.eu.habbo.habbohotel.users.HabboItem;
|
||||
import com.eu.habbo.util.HotelDateTimeUtil;
|
||||
import gnu.trove.set.hash.THashSet;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.LocalTime;
|
||||
import java.time.ZoneId;
|
||||
import java.util.List;
|
||||
|
||||
public class WiredHighscoreMidnightUpdater implements Runnable {
|
||||
@@ -30,6 +29,7 @@ public class WiredHighscoreMidnightUpdater implements Runnable {
|
||||
}
|
||||
|
||||
public static int getNextUpdaterRun() {
|
||||
return Math.toIntExact(LocalDateTime.now().with(LocalTime.MIDNIGHT).plusDays(1).plusSeconds(-1).atZone(ZoneId.systemDefault()).toEpochSecond() - Emulator.getIntUnixTimestamp()) + 5;
|
||||
long nextRunTimestamp = HotelDateTimeUtil.toEpochSecond(HotelDateTimeUtil.localDateTimeNow().with(LocalTime.MIDNIGHT).plusDays(1).plusSeconds(-1));
|
||||
return Math.toIntExact(nextRunTimestamp - Emulator.getIntUnixTimestamp()) + 5;
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -3,9 +3,9 @@ package com.eu.habbo.messages.incoming.hotelview;
|
||||
import com.eu.habbo.Emulator;
|
||||
import com.eu.habbo.messages.incoming.MessageHandler;
|
||||
import com.eu.habbo.messages.outgoing.hotelview.HotelViewSecondsUntilComposer;
|
||||
import com.eu.habbo.util.HotelDateTimeUtil;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.ZoneId;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.time.format.DateTimeParseException;
|
||||
|
||||
@@ -18,7 +18,7 @@ public class HotelViewRequestSecondsUntilEvent extends MessageHandler {
|
||||
|
||||
try {
|
||||
LocalDateTime dt = LocalDateTime.parse(date, formatter);
|
||||
int secondsUntil = Math.max(0, (int) dt.atZone(ZoneId.systemDefault()).toEpochSecond() - Emulator.getIntUnixTimestamp());
|
||||
int secondsUntil = Math.max(0, (int) HotelDateTimeUtil.toEpochSecond(dt) - Emulator.getIntUnixTimestamp());
|
||||
this.client.sendResponse(new HotelViewSecondsUntilComposer(date, secondsUntil));
|
||||
} catch (DateTimeParseException ignored) {
|
||||
}
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
package com.eu.habbo.util;
|
||||
|
||||
import com.eu.habbo.Emulator;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.LocalTime;
|
||||
import java.time.ZoneId;
|
||||
import java.time.ZonedDateTime;
|
||||
|
||||
public final class HotelDateTimeUtil {
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(HotelDateTimeUtil.class);
|
||||
private static final String CONFIG_KEY = "hotel.timezone";
|
||||
private static volatile String lastInvalidTimezoneId = null;
|
||||
|
||||
private HotelDateTimeUtil() {
|
||||
}
|
||||
|
||||
public static String getTimezoneId() {
|
||||
return getZoneId().getId();
|
||||
}
|
||||
|
||||
public static ZoneId getZoneId() {
|
||||
String configuredZoneId = Emulator.getConfig().getValue(CONFIG_KEY, ZoneId.systemDefault().getId());
|
||||
|
||||
try {
|
||||
lastInvalidTimezoneId = null;
|
||||
return ZoneId.of(configuredZoneId.trim());
|
||||
} catch (Exception e) {
|
||||
if (!configuredZoneId.equals(lastInvalidTimezoneId)) {
|
||||
LOGGER.warn("Invalid {} '{}', falling back to system timezone '{}'.", CONFIG_KEY, configuredZoneId, ZoneId.systemDefault().getId());
|
||||
lastInvalidTimezoneId = configuredZoneId;
|
||||
}
|
||||
return ZoneId.systemDefault();
|
||||
}
|
||||
}
|
||||
|
||||
public static ZonedDateTime now() {
|
||||
return ZonedDateTime.now(getZoneId());
|
||||
}
|
||||
|
||||
public static LocalDateTime localDateTimeNow() {
|
||||
return LocalDateTime.now(getZoneId());
|
||||
}
|
||||
|
||||
public static LocalDate localDateNow() {
|
||||
return LocalDate.now(getZoneId());
|
||||
}
|
||||
|
||||
public static LocalTime localTimeNow() {
|
||||
return LocalTime.now(getZoneId());
|
||||
}
|
||||
|
||||
public static long toEpochSecond(LocalDateTime dateTime) {
|
||||
return dateTime.atZone(getZoneId()).toEpochSecond();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user