🆙 Wheel updates

This commit is contained in:
duckietm
2026-05-28 16:36:22 +02:00
parent 4f4f581371
commit 1ba2e43d4d
5 changed files with 138 additions and 92 deletions
@@ -1,3 +1,18 @@
-- Soundboard
-- The room flag column + sounds table are also created at boot by
ALTER TABLE `rooms` ADD COLUMN IF NOT EXISTS `soundboard_enabled` TINYINT(1) NOT NULL DEFAULT 0;
CREATE TABLE IF NOT EXISTS `soundboard_sounds` (
`id` INT(11) NOT NULL AUTO_INCREMENT,
`name` VARCHAR(64) NOT NULL DEFAULT '', -- pad label shown in the client
`url` VARCHAR(255) NOT NULL DEFAULT '', -- audio url (uploaded via CMS, like custom badges)
`enabled` TINYINT(1) NOT NULL DEFAULT 1,
`sort_order` INT(11) NOT NULL DEFAULT 0,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
-- Fortune Wheel -- Fortune Wheel
-- Tables are also created at boot by WheelManager (CREATE TABLE IF NOT EXISTS), -- Tables are also created at boot by WheelManager (CREATE TABLE IF NOT EXISTS),
-- so applying this file is only needed to seed prizes + settings. -- so applying this file is only needed to seed prizes + settings.
@@ -44,15 +59,20 @@ INSERT INTO `emulator_settings` (`key`, `value`, `comment`) VALUES
('wheel.spin_cost_type', '5', 'Fortune wheel: currency type for the spin cost (5 = diamonds; -1 = credits).') ('wheel.spin_cost_type', '5', 'Fortune wheel: currency type for the spin cost (5 = diamonds; -1 = credits).')
ON DUPLICATE KEY UPDATE `comment` = VALUES(`comment`); ON DUPLICATE KEY UPDATE `comment` = VALUES(`comment`);
-- Example prizes (currency / spin / nothing don't reference furniture ids).
-- Add `item`/`badge` rows with your own ids: e.g.
-- INSERT INTO wheel_prizes (type, value, amount, weight, label, sort_order) VALUES ('item','<base_item_id>',1,5,'Raro',1);
-- INSERT INTO wheel_prizes (type, value, amount, weight, label, sort_order) VALUES ('badge','<BADGE_CODE>',1,5,'Distintivo',2);
INSERT INTO `wheel_prizes` (`type`, `amount`, `points_type`, `weight`, `label`, `sort_order`) VALUES INSERT INTO `wheel_prizes` (`type`, `amount`, `points_type`, `weight`, `label`, `sort_order`) VALUES
('points', 25, 5, 20, '25 diamanti', 10), ('points',25, 5, 20, '25 diamonds',1),
('points', 50, 5, 12, '50 diamanti', 11), ('points',50, 5, 12, '50 diamonds',2),
('points', 200, 5, 3, '200 diamanti', 12), ('points',200, 5, 3, '200 diamonds',3),
('credits', 100, 0, 15, '100 crediti', 13), ('credits',100, 0, 15, '100 credits',4),
('spin', 1, 0, 15, '1 Giro Extra', 14), ('spin',1, 0, 15, '1 Extra spin', 5),
('spin', 2, 0, 6, '2 Giri Extra', 15), ('spin',2, 0, 6, '2 Extra spins',6),
('nothing', 0, 0, 29, 'Nulla', 16); ('nothing',0, 0, 29, 'Oh to bad!',7);
INSERT INTO `permission_definitions`
(`permission_key`, `max_value`, `comment`,
`rank_1`, `rank_2`, `rank_3`, `rank_4`, `rank_5`, `rank_6`, `rank_7`)
VALUES
('acc_wheeladmin', 1, 'Required to open the Fortune Wheel settings popup and edit prize rows.',
0, 0, 0, 0, 0, 0, 1)
ON DUPLICATE KEY UPDATE `comment` = VALUES(`comment`);
@@ -1,15 +0,0 @@
-- Soundboard
-- The room flag column + sounds table are also created at boot by
-- SoundboardManager (ALTER ... ADD COLUMN IF NOT EXISTS / CREATE TABLE IF NOT
-- EXISTS), so applying this file is only needed to seed sounds up-front.
ALTER TABLE `rooms` ADD COLUMN IF NOT EXISTS `soundboard_enabled` TINYINT(1) NOT NULL DEFAULT 0;
CREATE TABLE IF NOT EXISTS `soundboard_sounds` (
`id` INT(11) NOT NULL AUTO_INCREMENT,
`name` VARCHAR(64) NOT NULL DEFAULT '', -- pad label shown in the client
`url` VARCHAR(255) NOT NULL DEFAULT '', -- audio url (uploaded via CMS, like custom badges)
`enabled` TINYINT(1) NOT NULL DEFAULT 1,
`sort_order` INT(11) NOT NULL DEFAULT 0,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
@@ -12,9 +12,10 @@ import java.sql.Connection;
import java.sql.PreparedStatement; import java.sql.PreparedStatement;
import java.sql.ResultSet; import java.sql.ResultSet;
import java.sql.SQLException; import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ThreadLocalRandom; import java.util.concurrent.ThreadLocalRandom;
public class WheelManager { public class WheelManager {
@@ -22,15 +23,28 @@ public class WheelManager {
private static final int RECENT_KEEP = 50; private static final int RECENT_KEEP = 50;
private static final int SECONDS_PER_DAY = 86400; private static final int SECONDS_PER_DAY = 86400;
public static final Set<String> VALID_PRIZE_TYPES = Set.of(
"credits", "points", "spin", "item", "badge", "nothing");
public static final int MAX_PRIZES_PER_SAVE = 64;
public static final int MAX_STRING_LEN = 64;
public static final int MAX_PRIZE_AMOUNT = 1_000_000;
public static final int MAX_ITEM_QUANTITY = 100;
public static final int MAX_WEIGHT = 1_000_000;
public static final int MAX_EXTRA_SPINS = 10_000;
private static final long MIN_SPIN_INTERVAL_MS = 1500L;
private final List<WheelPrize> prizes = new ArrayList<>(); private final List<WheelPrize> prizes = new ArrayList<>();
private int totalWeight = 0; private int totalWeight = 0;
private int freeSpinsPerDay = 1; private int freeSpinsPerDay = 1;
private int spinCost = 50; private int spinCost = 50;
private int spinCostType = 5; private int spinCostType = 5;
private final ConcurrentHashMap<Integer, Long> lastSpinAt = new ConcurrentHashMap<>();
private final ConcurrentHashMap<Integer, WheelUserState> userStateCache = new ConcurrentHashMap<>();
private final java.util.concurrent.CopyOnWriteArrayList<WheelRecentWin> recentWinsCache = new java.util.concurrent.CopyOnWriteArrayList<>();
public WheelManager() { public WheelManager() {
long millis = System.currentTimeMillis(); long millis = System.currentTimeMillis();
this.createTables();
this.reload(); this.reload();
LOGGER.info("Wheel Manager -> Loaded! ({} MS)", System.currentTimeMillis() - millis); LOGGER.info("Wheel Manager -> Loaded! ({} MS)", System.currentTimeMillis() - millis);
} }
@@ -38,35 +52,7 @@ public class WheelManager {
public void reload() { public void reload() {
this.loadSettings(); this.loadSettings();
this.loadPrizes(); this.loadPrizes();
} this.loadRecentWins();
private void createTables() {
final String[] ddl = {
"CREATE TABLE IF NOT EXISTS `wheel_prizes` (" +
"`id` INT(11) NOT NULL AUTO_INCREMENT, `type` VARCHAR(16) NOT NULL DEFAULT 'nothing', " +
"`value` VARCHAR(64) NOT NULL DEFAULT '', `amount` INT(11) NOT NULL DEFAULT 1, " +
"`points_type` INT(11) NOT NULL DEFAULT 5, `weight` INT(11) NOT NULL DEFAULT 1, " +
"`label` VARCHAR(64) NOT NULL DEFAULT '', `enabled` TINYINT(1) NOT NULL DEFAULT 1, " +
"`sort_order` INT(11) NOT NULL DEFAULT 0, PRIMARY KEY (`id`)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4",
"CREATE TABLE IF NOT EXISTS `wheel_user_state` (" +
"`user_id` INT(11) NOT NULL, `free_spins` INT(11) NOT NULL DEFAULT 0, " +
"`extra_spins` INT(11) NOT NULL DEFAULT 0, `last_reset` INT(11) NOT NULL DEFAULT 0, " +
"PRIMARY KEY (`user_id`)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4",
"CREATE TABLE IF NOT EXISTS `wheel_recent_wins` (" +
"`id` INT(11) NOT NULL AUTO_INCREMENT, `user_id` INT(11) NOT NULL, " +
"`username` VARCHAR(64) NOT NULL DEFAULT '', `look` VARCHAR(255) NOT NULL DEFAULT '', " +
"`prize_label` VARCHAR(64) NOT NULL DEFAULT '', `won_at` INT(11) NOT NULL DEFAULT 0, " +
"PRIMARY KEY (`id`)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4"
};
try (Connection connection = Emulator.getDatabase().getDataSource().getConnection();
Statement statement = connection.createStatement()) {
for (String query : ddl) {
statement.execute(query);
}
} catch (SQLException e) {
LOGGER.error("Failed to create fortune wheel tables", e);
}
} }
private void loadSettings() { private void loadSettings() {
@@ -108,8 +94,19 @@ public class WheelManager {
return Emulator.getIntUnixTimestamp() / SECONDS_PER_DAY; return Emulator.getIntUnixTimestamp() / SECONDS_PER_DAY;
} }
// Reads the user's spin balance, applying the lazy daily reset and creating the row if missing. public synchronized WheelUserState getUserState(int userId) {
public WheelUserState getUserState(int userId) { int today = this.today();
WheelUserState cached = this.userStateCache.get(userId);
if (cached != null) {
if (cached.lastReset != today) {
cached.freeSpins = this.freeSpinsPerDay;
cached.lastReset = today;
this.persistUserState(userId, cached);
}
return cached;
}
WheelUserState state = new WheelUserState(); WheelUserState state = new WheelUserState();
boolean exists = false; boolean exists = false;
@@ -128,7 +125,6 @@ public class WheelManager {
LOGGER.error("Failed to read wheel state for user {}", userId, e); LOGGER.error("Failed to read wheel state for user {}", userId, e);
} }
int today = this.today();
if (!exists) { if (!exists) {
state.freeSpins = this.freeSpinsPerDay; state.freeSpins = this.freeSpinsPerDay;
state.extraSpins = 0; state.extraSpins = 0;
@@ -140,6 +136,7 @@ public class WheelManager {
this.persistUserState(userId, state); this.persistUserState(userId, state);
} }
this.userStateCache.put(userId, state);
return state; return state;
} }
@@ -158,10 +155,13 @@ public class WheelManager {
} }
} }
// Consumes a spin (free first, then extra), picks a weighted prize, grants it and records the win.
// Returns the prize, or null if the user has no spins or no prizes are configured.
public synchronized WheelPrize spin(Habbo habbo) { public synchronized WheelPrize spin(Habbo habbo) {
int userId = habbo.getHabboInfo().getId(); int userId = habbo.getHabboInfo().getId();
long now = System.currentTimeMillis();
Long last = this.lastSpinAt.get(userId);
if (last != null && (now - last) < MIN_SPIN_INTERVAL_MS) return null;
this.lastSpinAt.put(userId, now);
WheelUserState state = this.getUserState(userId); WheelUserState state = this.getUserState(userId);
boolean usedFree; boolean usedFree;
@@ -177,15 +177,12 @@ public class WheelManager {
WheelPrize prize = this.pickWeighted(); WheelPrize prize = this.pickWeighted();
if (prize == null) { if (prize == null) {
// No prizes configured — refund the spin we just consumed.
if (usedFree) state.freeSpins++; else state.extraSpins++; if (usedFree) state.freeSpins++; else state.extraSpins++;
return null; return null;
} }
this.giveReward(habbo, prize, state); this.giveReward(habbo, prize, state);
this.persistUserState(userId, state); this.persistUserState(userId, state);
// Record every spin (including "nothing") so the live feed shows all activity.
this.recordWin(habbo, prize); this.recordWin(habbo, prize);
return prize; return prize;
@@ -204,21 +201,26 @@ public class WheelManager {
} }
private void giveReward(Habbo habbo, WheelPrize prize, WheelUserState state) { private void giveReward(Habbo habbo, WheelPrize prize, WheelUserState state) {
int amount = Math.max(0, Math.min(prize.amount, MAX_PRIZE_AMOUNT));
switch (prize.type) { switch (prize.type) {
case "credits": case "credits":
habbo.giveCredits(prize.amount); if (amount > 0) habbo.giveCredits(amount);
break; break;
case "points": case "points":
habbo.givePoints(prize.pointsType, prize.amount); if (amount > 0) habbo.givePoints(prize.pointsType, amount);
break; break;
case "spin": case "spin":
state.extraSpins += Math.max(0, prize.amount); int room = Math.max(0, MAX_EXTRA_SPINS - state.extraSpins);
state.extraSpins += Math.min(amount, room);
break; break;
case "item": case "item":
this.giveItem(habbo, prize); this.giveItem(habbo, prize, Math.min(amount, MAX_ITEM_QUANTITY));
break; break;
case "badge": case "badge":
habbo.addBadge(prize.value, "Fortune Wheel"); if (prize.value != null && !prize.value.isEmpty()) {
habbo.addBadge(prize.value, "Fortune Wheel");
}
break; break;
case "nothing": case "nothing":
default: default:
@@ -226,7 +228,9 @@ public class WheelManager {
} }
} }
private void giveItem(Habbo habbo, WheelPrize prize) { private void giveItem(Habbo habbo, WheelPrize prize, int quantity) {
if (quantity <= 0 || prize.value == null) return;
int baseId; int baseId;
try { try {
baseId = Integer.parseInt(prize.value.trim()); baseId = Integer.parseInt(prize.value.trim());
@@ -237,7 +241,6 @@ public class WheelManager {
Item base = Emulator.getGameEnvironment().getItemManager().getItem(baseId); Item base = Emulator.getGameEnvironment().getItemManager().getItem(baseId);
if (base == null) return; if (base == null) return;
int quantity = Math.max(1, prize.amount);
THashSet<HabboItem> items = new THashSet<>(); THashSet<HabboItem> items = new THashSet<>();
for (int i = 0; i < quantity; i++) { for (int i = 0; i < quantity; i++) {
HabboItem item = Emulator.getGameEnvironment().getItemManager().createItem(habbo.getHabboInfo().getId(), base, 0, 0, ""); HabboItem item = Emulator.getGameEnvironment().getItemManager().createItem(habbo.getHabboInfo().getId(), base, 0, 0, "");
@@ -250,6 +253,16 @@ public class WheelManager {
} }
private void recordWin(Habbo habbo, WheelPrize prize) { private void recordWin(Habbo habbo, WheelPrize prize) {
WheelRecentWin win = new WheelRecentWin(
habbo.getHabboInfo().getUsername(),
habbo.getHabboInfo().getLook(),
prize.label);
this.recentWinsCache.add(0, win);
while (this.recentWinsCache.size() > RECENT_KEEP) {
this.recentWinsCache.remove(this.recentWinsCache.size() - 1);
}
try (Connection connection = Emulator.getDatabase().getDataSource().getConnection()) { try (Connection connection = Emulator.getDatabase().getDataSource().getConnection()) {
try (PreparedStatement statement = connection.prepareStatement( try (PreparedStatement statement = connection.prepareStatement(
"INSERT INTO wheel_recent_wins (user_id, username, look, prize_label, won_at) VALUES (?, ?, ?, ?, ?)")) { "INSERT INTO wheel_recent_wins (user_id, username, look, prize_label, won_at) VALUES (?, ?, ?, ?, ?)")) {
@@ -261,7 +274,6 @@ public class WheelManager {
statement.executeUpdate(); statement.executeUpdate();
} }
// Trim to the most recent RECENT_KEEP rows.
try (PreparedStatement trim = connection.prepareStatement( try (PreparedStatement trim = connection.prepareStatement(
"DELETE FROM wheel_recent_wins WHERE id < (SELECT id FROM (SELECT id FROM wheel_recent_wins ORDER BY id DESC LIMIT 1 OFFSET ?) t)")) { "DELETE FROM wheel_recent_wins WHERE id < (SELECT id FROM (SELECT id FROM wheel_recent_wins ORDER BY id DESC LIMIT 1 OFFSET ?) t)")) {
trim.setInt(1, RECENT_KEEP - 1); trim.setInt(1, RECENT_KEEP - 1);
@@ -273,25 +285,38 @@ public class WheelManager {
} }
public List<WheelRecentWin> getRecentWins(int limit) { public List<WheelRecentWin> getRecentWins(int limit) {
List<WheelRecentWin> wins = new ArrayList<>(); if (limit <= 0) return new ArrayList<>();
int size = this.recentWinsCache.size();
if (size == 0) return new ArrayList<>();
int take = Math.min(limit, size);
return new ArrayList<>(this.recentWinsCache.subList(0, take));
}
private void loadRecentWins() {
this.recentWinsCache.clear();
try (Connection connection = Emulator.getDatabase().getDataSource().getConnection(); try (Connection connection = Emulator.getDatabase().getDataSource().getConnection();
PreparedStatement statement = connection.prepareStatement("SELECT username, look, prize_label FROM wheel_recent_wins ORDER BY id DESC LIMIT ?")) { PreparedStatement statement = connection.prepareStatement("SELECT username, look, prize_label FROM wheel_recent_wins ORDER BY id DESC LIMIT ?")) {
statement.setInt(1, limit); statement.setInt(1, RECENT_KEEP);
try (ResultSet set = statement.executeQuery()) { try (ResultSet set = statement.executeQuery()) {
while (set.next()) { while (set.next()) {
wins.add(new WheelRecentWin(set.getString("username"), set.getString("look"), set.getString("prize_label"))); this.recentWinsCache.add(new WheelRecentWin(
set.getString("username"),
set.getString("look"),
set.getString("prize_label")));
} }
} }
} catch (SQLException e) { } catch (SQLException e) {
LOGGER.error("Failed to load wheel recent wins", e); LOGGER.error("Failed to load wheel recent wins", e);
} }
return wins;
} }
// Buys one extra spin with the configured currency. Returns false if the user can't afford it.
public synchronized boolean buySpin(Habbo habbo) { public synchronized boolean buySpin(Habbo habbo) {
if (this.spinCost <= 0) return false; if (this.spinCost <= 0) return false;
int userId = habbo.getHabboInfo().getId();
WheelUserState state = this.getUserState(userId);
if (state.extraSpins >= MAX_EXTRA_SPINS) return false;
if (this.spinCostType == -1) { if (this.spinCostType == -1) {
if (habbo.getHabboInfo().getCredits() < this.spinCost) return false; if (habbo.getHabboInfo().getCredits() < this.spinCost) return false;
habbo.giveCredits(-this.spinCost); habbo.giveCredits(-this.spinCost);
@@ -300,28 +325,42 @@ public class WheelManager {
habbo.givePoints(this.spinCostType, -this.spinCost); habbo.givePoints(this.spinCostType, -this.spinCost);
} }
int userId = habbo.getHabboInfo().getId();
WheelUserState state = this.getUserState(userId);
state.extraSpins++; state.extraSpins++;
this.persistUserState(userId, state); this.persistUserState(userId, state);
return true; return true;
} }
// Admin: update one prize row. Caller reloads once after a batch.
public void savePrize(int id, String type, String value, int amount, int pointsType, int weight, String label) { public void savePrize(int id, String type, String value, int amount, int pointsType, int weight, String label) {
String safeType = (type != null && VALID_PRIZE_TYPES.contains(type)) ? type : "nothing";
String safeValue = truncate(value, MAX_STRING_LEN);
String safeLabel = truncate(label, MAX_STRING_LEN);
int safeAmount = clamp(amount, 0, MAX_PRIZE_AMOUNT);
int safeWeight = clamp(weight, 0, MAX_WEIGHT);
try (Connection connection = Emulator.getDatabase().getDataSource().getConnection(); try (Connection connection = Emulator.getDatabase().getDataSource().getConnection();
PreparedStatement statement = connection.prepareStatement( PreparedStatement statement = connection.prepareStatement(
"UPDATE wheel_prizes SET type = ?, value = ?, amount = ?, points_type = ?, weight = ?, label = ? WHERE id = ?")) { "UPDATE wheel_prizes SET type = ?, value = ?, amount = ?, points_type = ?, weight = ?, label = ? WHERE id = ?")) {
statement.setString(1, type != null ? type : "nothing"); statement.setString(1, safeType);
statement.setString(2, value != null ? value : ""); statement.setString(2, safeValue);
statement.setInt(3, amount); statement.setInt(3, safeAmount);
statement.setInt(4, pointsType); statement.setInt(4, pointsType);
statement.setInt(5, Math.max(0, weight)); statement.setInt(5, safeWeight);
statement.setString(6, label != null ? label : ""); statement.setString(6, safeLabel);
statement.setInt(7, id); statement.setInt(7, id);
statement.executeUpdate(); statement.executeUpdate();
} catch (SQLException e) { } catch (SQLException e) {
LOGGER.error("Failed to save wheel prize {}", id, e); LOGGER.error("Failed to save wheel prize {}", id, e);
} }
} }
private static String truncate(String s, int max) {
if (s == null) return "";
return s.length() <= max ? s : s.substring(0, max);
}
private static int clamp(int value, int min, int max) {
if (value < min) return min;
if (value > max) return max;
return value;
}
} }
@@ -1,11 +1,12 @@
package com.eu.habbo.messages.incoming.wheel; package com.eu.habbo.messages.incoming.wheel;
import com.eu.habbo.Emulator; import com.eu.habbo.Emulator;
import com.eu.habbo.habbohotel.permissions.Permission;
import com.eu.habbo.messages.incoming.MessageHandler; import com.eu.habbo.messages.incoming.MessageHandler;
import com.eu.habbo.messages.outgoing.wheel.WheelAdminPrizesComposer; import com.eu.habbo.messages.outgoing.wheel.WheelAdminPrizesComposer;
public class WheelAdminGetPrizesEvent extends MessageHandler { public class WheelAdminGetPrizesEvent extends MessageHandler {
public static final String PERMISSION_KEY = "acc_wheeladmin";
@Override @Override
public int getRatelimit() { public int getRatelimit() {
return 500; return 500;
@@ -13,7 +14,7 @@ public class WheelAdminGetPrizesEvent extends MessageHandler {
@Override @Override
public void handle() throws Exception { public void handle() throws Exception {
if (this.client.getHabbo() == null || !this.client.getHabbo().hasPermission(Permission.ACC_SUPPORTTOOL)) { if (this.client.getHabbo() == null || !this.client.getHabbo().hasPermission(PERMISSION_KEY)) {
return; return;
} }
@@ -1,13 +1,14 @@
package com.eu.habbo.messages.incoming.wheel; package com.eu.habbo.messages.incoming.wheel;
import com.eu.habbo.Emulator; import com.eu.habbo.Emulator;
import com.eu.habbo.habbohotel.permissions.Permission;
import com.eu.habbo.habbohotel.wheel.WheelManager; import com.eu.habbo.habbohotel.wheel.WheelManager;
import com.eu.habbo.messages.incoming.MessageHandler; import com.eu.habbo.messages.incoming.MessageHandler;
import com.eu.habbo.messages.outgoing.wheel.WheelAdminPrizesComposer; import com.eu.habbo.messages.outgoing.wheel.WheelAdminPrizesComposer;
import com.eu.habbo.messages.outgoing.wheel.WheelDataComposer; import com.eu.habbo.messages.outgoing.wheel.WheelDataComposer;
public class WheelAdminSavePrizesEvent extends MessageHandler { public class WheelAdminSavePrizesEvent extends MessageHandler {
public static final String PERMISSION_KEY = "acc_wheeladmin";
@Override @Override
public int getRatelimit() { public int getRatelimit() {
return 1000; return 1000;
@@ -15,13 +16,15 @@ public class WheelAdminSavePrizesEvent extends MessageHandler {
@Override @Override
public void handle() throws Exception { public void handle() throws Exception {
if (this.client.getHabbo() == null || !this.client.getHabbo().hasPermission(Permission.ACC_SUPPORTTOOL)) { if (this.client.getHabbo() == null || !this.client.getHabbo().hasPermission(PERMISSION_KEY)) {
return; return;
} }
WheelManager wheel = Emulator.getGameEnvironment().getWheelManager(); WheelManager wheel = Emulator.getGameEnvironment().getWheelManager();
int count = this.packet.readInt(); int count = this.packet.readInt();
if (count <= 0 || count > WheelManager.MAX_PRIZES_PER_SAVE) return;
for (int i = 0; i < count; i++) { for (int i = 0; i < count; i++) {
int id = this.packet.readInt(); int id = this.packet.readInt();
String type = this.packet.readString(); String type = this.packet.readString();
@@ -30,13 +33,11 @@ public class WheelAdminSavePrizesEvent extends MessageHandler {
int pointsType = this.packet.readInt(); int pointsType = this.packet.readInt();
int weight = this.packet.readInt(); int weight = this.packet.readInt();
String label = this.packet.readString(); String label = this.packet.readString();
wheel.savePrize(id, type, value, amount, pointsType, weight, label); wheel.savePrize(id, type, value, amount, pointsType, weight, label);
} }
wheel.reload(); wheel.reload();
// Send the refreshed admin list + the player view so the editor updates live.
this.client.sendResponse(new WheelAdminPrizesComposer(wheel.getPrizes())); this.client.sendResponse(new WheelAdminPrizesComposer(wheel.getPrizes()));
this.client.sendResponse(new WheelDataComposer( this.client.sendResponse(new WheelDataComposer(
wheel.getUserState(this.client.getHabbo().getHabboInfo().getId()), wheel.getUserState(this.client.getHabbo().getHabboInfo().getId()),