diff --git a/README.md b/README.md
index f96ea1a0..fe6c2c88 100644
--- a/README.md
+++ b/README.md
@@ -16,7 +16,7 @@ Arcturus Morningstar is as a fork of Arcturus Emulator by TheGeneral. Arcturus M
[![image](https://img.shields.io/discord/557240155040251905?style=for-the-badge&logo=discord&color=7289DA&label=KREWS&logoColor=fff)](https://discord.gg/BzfFsTp)
## Download ##
-[![image](https://img.shields.io/badge/STABLE%20RELEASES-3.5.3-success.svg?style=for-the-badge&logo=appveyor)](https://git.krews.org/morningstar/Arcturus-Community/-/releases)
+[![image](https://img.shields.io/badge/STABLE%20RELEASES-3.5.4-success.svg?style=for-the-badge&logo=appveyor)](https://git.krews.org/morningstar/Arcturus-Community/-/releases)
[![image](https://img.shields.io/badge/DEVELOPER%20BUILDS-4.0-red.svg?style=for-the-badge&logo=appveyor)](https://git.krews.org/morningstar/Arcturus-Community/-/jobs) *
diff --git a/pom.xml b/pom.xml
index b8b6b996..4a2fec2e 100644
--- a/pom.xml
+++ b/pom.xml
@@ -6,7 +6,7 @@
com.eu.habbo
Habbo
- 3.5.3
+ 3.5.4
UTF-8
diff --git a/src/main/java/com/eu/habbo/Emulator.java b/src/main/java/com/eu/habbo/Emulator.java
index f83cbc6f..d532cc1d 100644
--- a/src/main/java/com/eu/habbo/Emulator.java
+++ b/src/main/java/com/eu/habbo/Emulator.java
@@ -37,7 +37,7 @@ public final class Emulator {
public final static int MAJOR = 3;
public final static int MINOR = 5;
- public final static int BUILD = 3;
+ public final static int BUILD = 4;
public final static String PREVIEW = "";
public static final String version = "Arcturus Morningstar" + " " + MAJOR + "." + MINOR + "." + BUILD + " " + PREVIEW;
@@ -49,7 +49,7 @@ public final class Emulator {
"██║╚██╔╝██║██║ ██║██╔══██╗██║╚██╗██║██║██║╚██╗██║██║ ██║╚════██║ ██║ ██╔══██║██╔══██╗\n" +
"██║ ╚═╝ ██║╚██████╔╝██║ ██║██║ ╚████║██║██║ ╚████║╚██████╔╝███████║ ██║ ██║ ██║██║ ██║\n" +
"╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝╚═╝ ╚═══╝╚═╝╚═╝ ╚═══╝ ╚═════╝ ╚══════╝ ╚═╝ ╚═╝ ╚═╝╚═╝ ╚═╝\n" +
- "Still Rocking in 2023.\n";
+ "Still Rocking in 2024.\n";
public static String build = "";
public static boolean isReady = false;
diff --git a/src/main/java/com/eu/habbo/habbohotel/catalog/CatalogManager.java b/src/main/java/com/eu/habbo/habbohotel/catalog/CatalogManager.java
index b274b1be..886e4928 100644
--- a/src/main/java/com/eu/habbo/habbohotel/catalog/CatalogManager.java
+++ b/src/main/java/com/eu/habbo/habbohotel/catalog/CatalogManager.java
@@ -902,7 +902,9 @@ public class CatalogManager {
boolean badgeFound = false;
for (int i = 0; i < amount; i++) {
- habbo.getHabboStats().addLtdLog(item.getId(), Emulator.getIntUnixTimestamp());
+ if(item.isLimited()) {
+ habbo.getHabboStats().addLtdLog(item.getId(), Emulator.getIntUnixTimestamp());
+ }
for (Item baseItem : item.getBaseItems()) {
for (int k = 0; k < item.getItemAmount(baseItem.getId()); k++) {
diff --git a/src/main/java/com/eu/habbo/habbohotel/commands/CommandHandler.java b/src/main/java/com/eu/habbo/habbohotel/commands/CommandHandler.java
index 64dd09d8..b2f98f3a 100644
--- a/src/main/java/com/eu/habbo/habbohotel/commands/CommandHandler.java
+++ b/src/main/java/com/eu/habbo/habbohotel/commands/CommandHandler.java
@@ -62,7 +62,7 @@ public class CommandHandler {
public static boolean handleCommand(GameClient gameClient, String commandLine) {
- if (gameClient != null) {
+ if (gameClient != null && commandLine != null) {
if (commandLine.startsWith(":")) {
commandLine = commandLine.replaceFirst(":", "");
diff --git a/src/main/java/com/eu/habbo/habbohotel/items/interactions/InteractionWired.java b/src/main/java/com/eu/habbo/habbohotel/items/interactions/InteractionWired.java
index 166768cb..f2541e11 100644
--- a/src/main/java/com/eu/habbo/habbohotel/items/interactions/InteractionWired.java
+++ b/src/main/java/com/eu/habbo/habbohotel/items/interactions/InteractionWired.java
@@ -16,11 +16,12 @@ import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
+import java.util.HashMap;
public abstract class InteractionWired extends InteractionDefault {
private static final Logger LOGGER = LoggerFactory.getLogger(InteractionWired.class);
private long cooldown;
- private TLongLongHashMap userExecutionCache = new TLongLongHashMap(3);
+ private final HashMap userExecutionCache = new HashMap<>();
InteractionWired(ResultSet set, Item baseItem) throws SQLException {
super(set, baseItem);
@@ -76,8 +77,10 @@ public abstract class InteractionWired extends InteractionDefault {
}
public void activateBox(Room room, RoomUnit roomUnit, long millis) {
- this.setExtradata(this.getExtradata().equals("1") ? "0" : "1");
- room.sendComposer(new ItemStateComposer(this).compose());
+ if(!room.isHideWired()) {
+ this.setExtradata(this.getExtradata().equals("1") ? "0" : "1");
+ room.sendComposer(new ItemStateComposer(this).compose());
+ }
if (roomUnit != null) {
this.addUserExecutionCache(roomUnit.getId(), millis);
}
@@ -112,7 +115,7 @@ public abstract class InteractionWired extends InteractionDefault {
} else {
if (this.userExecutionCache.containsKey((long)roomUnitId)) {
long lastTimestamp = this.userExecutionCache.get((long)roomUnitId);
- if (timestamp - lastTimestamp < 100L) {
+ if (timestamp - lastTimestamp < Math.max(100L, this.requiredCooldown())) {
return false;
}
}
diff --git a/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/triggers/WiredTriggerRepeater.java b/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/triggers/WiredTriggerRepeater.java
index f43ffac0..d7e6af03 100644
--- a/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/triggers/WiredTriggerRepeater.java
+++ b/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/triggers/WiredTriggerRepeater.java
@@ -125,10 +125,16 @@ public class WiredTriggerRepeater extends InteractionWiredTrigger implements ICy
@Override
public void cycle(Room room) {
this.counter += 500;
- if (this.counter >= this.repeatTime) {
+ long currentMillis = System.currentTimeMillis();
+ String Key = Double.toString(this.getX()) + Double.toString(this.getY());
+
+ room.repeatersLastTick.putIfAbsent(Key, currentMillis);
+
+ if (this.counter >= this.repeatTime && room.repeatersLastTick.get(Key) < currentMillis - 450) {
this.counter = 0;
if (this.getRoomId() != 0) {
if (room.isLoaded()) {
+ room.repeatersLastTick.put(Key, currentMillis);
WiredHandler.handle(this, null, room, new Object[]{this});
}
}
diff --git a/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/triggers/WiredTriggerRepeaterLong.java b/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/triggers/WiredTriggerRepeaterLong.java
index 536aca86..0723ba1f 100644
--- a/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/triggers/WiredTriggerRepeaterLong.java
+++ b/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/triggers/WiredTriggerRepeaterLong.java
@@ -119,10 +119,16 @@ public class WiredTriggerRepeaterLong extends InteractionWiredTrigger implements
@Override
public void cycle(Room room) {
this.counter += 500;
- if (this.counter >= this.repeatTime) {
+ long currentMillis = System.currentTimeMillis();
+ String Key = Double.toString(this.getX()) + Double.toString(this.getY());
+
+ room.repeatersLastTick.putIfAbsent(Key, currentMillis);
+
+ if (this.counter >= this.repeatTime && room.repeatersLastTick.get(Key) < currentMillis - 4950) {
this.counter = 0;
if (this.getRoomId() != 0) {
if (room.isLoaded()) {
+ room.repeatersLastTick.put(Key, currentMillis);
WiredHandler.handle(this, null, room, new Object[]{this});
}
}
diff --git a/src/main/java/com/eu/habbo/habbohotel/modtool/WordFilter.java b/src/main/java/com/eu/habbo/habbohotel/modtool/WordFilter.java
index 791d12d5..68168d61 100644
--- a/src/main/java/com/eu/habbo/habbohotel/modtool/WordFilter.java
+++ b/src/main/java/com/eu/habbo/habbohotel/modtool/WordFilter.java
@@ -194,6 +194,10 @@ public class WordFilter {
}
}
+ public THashSet getWords() {
+ return new THashSet<>(this.words);
+ }
+
public void addWord(WordFilterWord word) {
this.words.add(word);
}
diff --git a/src/main/java/com/eu/habbo/habbohotel/rooms/Room.java b/src/main/java/com/eu/habbo/habbohotel/rooms/Room.java
index 119df291..e98dd691 100644
--- a/src/main/java/com/eu/habbo/habbohotel/rooms/Room.java
+++ b/src/main/java/com/eu/habbo/habbohotel/rooms/Room.java
@@ -213,6 +213,7 @@ public class Room implements Comparable, ISerialize, Runnable {
private TraxManager traxManager;
private boolean cycleOdd;
private long cycleTimestamp;
+ public Map repeatersLastTick = new HashMap<>();
public Room(ResultSet set) throws SQLException {
this.id = set.getInt("id");
diff --git a/src/main/java/com/eu/habbo/habbohotel/rooms/RoomManager.java b/src/main/java/com/eu/habbo/habbohotel/rooms/RoomManager.java
index ab507719..3bf26bcc 100644
--- a/src/main/java/com/eu/habbo/habbohotel/rooms/RoomManager.java
+++ b/src/main/java/com/eu/habbo/habbohotel/rooms/RoomManager.java
@@ -294,6 +294,10 @@ public class RoomManager {
public Room loadRoom(int id, boolean loadData) {
Room room = null;
+ if(id == 0) {
+ return null;
+ }
+
if (this.activeRooms.containsKey(id)) {
room = this.activeRooms.get(id);
@@ -414,7 +418,7 @@ public class RoomManager {
public RoomLayout loadLayout(String name, Room room) {
RoomLayout layout = null;
- try (Connection connection = Emulator.getDatabase().getDataSource().getConnection(); PreparedStatement statement = connection.prepareStatement("SELECT * FROM room_models WHERE name LIKE ? LIMIT 1")) {
+ try (Connection connection = Emulator.getDatabase().getDataSource().getConnection(); PreparedStatement statement = connection.prepareStatement("SELECT * FROM room_models WHERE name = ? LIMIT 1")) {
statement.setString(1, name);
try (ResultSet set = statement.executeQuery()) {
if (set.next()) {
diff --git a/src/main/java/com/eu/habbo/habbohotel/users/Habbo.java b/src/main/java/com/eu/habbo/habbohotel/users/Habbo.java
index 6e6029f2..4dd34962 100644
--- a/src/main/java/com/eu/habbo/habbohotel/users/Habbo.java
+++ b/src/main/java/com/eu/habbo/habbohotel/users/Habbo.java
@@ -448,18 +448,23 @@ public class Habbo implements Runnable {
}
public void clearCaches() {
- int timestamp = Emulator.getIntUnixTimestamp();
- THashMap> newLog = new THashMap<>();
- for (Map.Entry> ltdLog : this.habboStats.ltdPurchaseLog.entrySet()) {
- for (Integer time : ltdLog.getValue()) {
- if (time > timestamp) {
- if (!newLog.containsKey(ltdLog.getKey())) {
- newLog.put(ltdLog.getKey(), new ArrayList<>());
- }
+ int currentTimestamp = Emulator.getIntUnixTimestamp();
+ int twentyFourHoursInSeconds = 24 * 60 * 60; // 24 hours in seconds
- newLog.get(ltdLog.getKey()).add(time);
+ THashMap> newLog = new THashMap<>();
+
+ for (Map.Entry> ltdLog : this.habboStats.ltdPurchaseLog.entrySet()) {
+ List filteredTimestamps = new ArrayList<>();
+
+ for (Integer time : ltdLog.getValue()) {
+ if (currentTimestamp - time <= twentyFourHoursInSeconds) {
+ filteredTimestamps.add(time);
}
}
+
+ if (!filteredTimestamps.isEmpty()) {
+ newLog.put(ltdLog.getKey(), filteredTimestamps);
+ }
}
this.habboStats.ltdPurchaseLog = newLog;
diff --git a/src/main/java/com/eu/habbo/habbohotel/users/HabboStats.java b/src/main/java/com/eu/habbo/habbohotel/users/HabboStats.java
index 462af849..29ef2a2f 100644
--- a/src/main/java/com/eu/habbo/habbohotel/users/HabboStats.java
+++ b/src/main/java/com/eu/habbo/habbohotel/users/HabboStats.java
@@ -102,7 +102,7 @@ public class HabboStats implements Runnable {
public THashSet subscriptions;
private HabboStats(ResultSet set, HabboInfo habboInfo) throws SQLException {
- this.cache = new THashMap<>(0);
+ this.cache = new THashMap<>(1000);
this.achievementProgress = new THashMap<>(0);
this.achievementCache = new THashMap<>(0);
this.recentPurchases = new THashMap<>(0);
diff --git a/src/main/java/com/eu/habbo/habbohotel/wired/WiredHandler.java b/src/main/java/com/eu/habbo/habbohotel/wired/WiredHandler.java
index 1d2b20fc..955cf264 100644
--- a/src/main/java/com/eu/habbo/habbohotel/wired/WiredHandler.java
+++ b/src/main/java/com/eu/habbo/habbohotel/wired/WiredHandler.java
@@ -234,7 +234,7 @@ public class WiredHandler {
executed = true;
if (!effect.requiresTriggeringUser() || (roomUnit != null && effect.requiresTriggeringUser())) {
Emulator.getThreading().run(() -> {
- if (room.isLoaded()) {
+ if (room.isLoaded() && room.getHabbos().size() > 0) {
try {
if (!effect.execute(roomUnit, room, stuff)) return;
effect.setCooldown(millis);
diff --git a/src/main/java/com/eu/habbo/habbohotel/wired/highscores/WiredHighscoreManager.java b/src/main/java/com/eu/habbo/habbohotel/wired/highscores/WiredHighscoreManager.java
index e7cf9cef..d1769ac0 100644
--- a/src/main/java/com/eu/habbo/habbohotel/wired/highscores/WiredHighscoreManager.java
+++ b/src/main/java/com/eu/habbo/habbohotel/wired/highscores/WiredHighscoreManager.java
@@ -154,6 +154,18 @@ public class WiredHighscoreManager {
return false;
}
+ public HashMap> getData() {
+ return this.data;
+ }
+
+ public List getEntriesForItemId(int itemId) {
+ return this.data.get(itemId);
+ }
+
+ public void setEntriesForItemId(int itemId, List entries) {
+ this.data.put(itemId, entries);
+ }
+
private long getTodayStartTimestamp() {
return LocalDateTime.now().with(LocalTime.MIDNIGHT).atZone(zoneId).toEpochSecond();
}
diff --git a/src/main/java/com/eu/habbo/messages/outgoing/rooms/UpdateStackHeightComposer.java b/src/main/java/com/eu/habbo/messages/outgoing/rooms/UpdateStackHeightComposer.java
index a6d5d643..9da42a67 100644
--- a/src/main/java/com/eu/habbo/messages/outgoing/rooms/UpdateStackHeightComposer.java
+++ b/src/main/java/com/eu/habbo/messages/outgoing/rooms/UpdateStackHeightComposer.java
@@ -8,6 +8,8 @@ import com.eu.habbo.messages.outgoing.MessageComposer;
import com.eu.habbo.messages.outgoing.Outgoing;
import gnu.trove.set.hash.THashSet;
+import java.util.Objects;
+
public class UpdateStackHeightComposer extends MessageComposer {
private int x;
private int y;
@@ -34,6 +36,7 @@ public class UpdateStackHeightComposer extends MessageComposer {
//TODO: maybe do this another way? doesn't seem to be very clean but gets the job done
this.response.init(Outgoing.UpdateStackHeightComposer);
if (this.updateTiles != null) {
+ this.updateTiles.removeIf(Objects::isNull);
// prevent overflow. Byte max value is 127
if(this.updateTiles.size() > 127) {
RoomTile[] tiles = this.updateTiles.toArray(new RoomTile[updateTiles.size()]);