Merge branch 'redeemable-clothing-fixes' into 'dev'

Prevent unredeemed clothing to be used by user

See merge request morningstar/Arcturus-Community!34
This commit is contained in:
Beny 2019-05-17 09:24:26 -04:00
commit 43093feb2a
10 changed files with 107 additions and 100 deletions

View File

@ -17,4 +17,8 @@ INSERT INTO `emulator_texts`(`key`, `value`) VALUES ('invisible.prevent.chat.err
INSERT INTO `emulator_texts`(`key`, `value`) VALUES ('commands.succes.cmd_invisible.updated.back', 'You are now visible again.'); INSERT INTO `emulator_texts`(`key`, `value`) VALUES ('commands.succes.cmd_invisible.updated.back', 'You are now visible again.');
INSERT INTO `emulator_texts`(`key`, `value`) VALUES ('commands.error.cmd_mimic.forbidden_clothing', 'The other user has clothing that you do not own yet.');
ALTER TABLE `permissions`
ADD COLUMN `acc_mimic_unredeemed` enum('0','1') NOT NULL DEFAULT '0';
#END DATABASE UPDATE: 2.0.0 RC-2 -> 2.0.0 RC-3 #END DATABASE UPDATE: 2.0.0 RC-2 -> 2.0.0 RC-3

View File

@ -7,6 +7,7 @@ import com.eu.habbo.habbohotel.users.Habbo;
import com.eu.habbo.habbohotel.users.HabboGender; import com.eu.habbo.habbohotel.users.HabboGender;
import com.eu.habbo.messages.outgoing.rooms.users.RoomUserDataComposer; import com.eu.habbo.messages.outgoing.rooms.users.RoomUserDataComposer;
import com.eu.habbo.messages.outgoing.users.UserDataComposer; import com.eu.habbo.messages.outgoing.users.UserDataComposer;
import com.eu.habbo.util.figure.FigureUtil;
public class MimicCommand extends Command public class MimicCommand extends Command
{ {
@ -18,28 +19,24 @@ public class MimicCommand extends Command
@Override @Override
public boolean handle(GameClient gameClient, String[] params) throws Exception public boolean handle(GameClient gameClient, String[] params) throws Exception
{ {
if(params.length == 2) if (params.length == 2) {
{
Habbo habbo = gameClient.getHabbo().getHabboInfo().getCurrentRoom().getHabbo(params[1]); Habbo habbo = gameClient.getHabbo().getHabboInfo().getCurrentRoom().getHabbo(params[1]);
if (habbo == null) if (habbo == null) {
{
gameClient.getHabbo().whisper(Emulator.getTexts().getValue("commands.error.cmd_mimic.not_found").replace("%user%", ""), RoomChatMessageBubbles.ALERT); gameClient.getHabbo().whisper(Emulator.getTexts().getValue("commands.error.cmd_mimic.not_found").replace("%user%", ""), RoomChatMessageBubbles.ALERT);
return true; return true;
} }
if(habbo == gameClient.getHabbo()) if (habbo == gameClient.getHabbo()) {
{
gameClient.getHabbo().whisper(Emulator.getTexts().getValue("commands.error.cmd_mimic.not_self"), RoomChatMessageBubbles.ALERT); gameClient.getHabbo().whisper(Emulator.getTexts().getValue("commands.error.cmd_mimic.not_self"), RoomChatMessageBubbles.ALERT);
return true; return true;
} } else if (habbo.hasPermission("acc_not_mimiced") && !gameClient.getHabbo().hasPermission("acc_not_mimiced")) {
else if(habbo.hasPermission("acc_not_mimiced") && !gameClient.getHabbo().hasPermission("acc_not_mimiced"))
{
gameClient.getHabbo().whisper(Emulator.getTexts().getValue("commands.error.cmd_mimic.blocked").replace("%user%", params[1]).replace("%gender_name%", (habbo.getHabboInfo().getGender().equals(HabboGender.M) ? Emulator.getTexts().getValue("gender.him") : Emulator.getTexts().getValue("gender.her"))), RoomChatMessageBubbles.ALERT); gameClient.getHabbo().whisper(Emulator.getTexts().getValue("commands.error.cmd_mimic.blocked").replace("%user%", params[1]).replace("%gender_name%", (habbo.getHabboInfo().getGender().equals(HabboGender.M) ? Emulator.getTexts().getValue("gender.him") : Emulator.getTexts().getValue("gender.her"))), RoomChatMessageBubbles.ALERT);
return true; return true;
} } else if (!habbo.hasPermission("acc_mimic_unredeemed") && FigureUtil.hasBlacklistedClothing(habbo.getHabboInfo().getLook(), gameClient.getHabbo().getForbiddenClothing())) {
else gameClient.getHabbo().whisper(Emulator.getTexts().getValue("commands.error.cmd_mimic.forbidden_clothing"), RoomChatMessageBubbles.ALERT);
{ return true;
} else {
gameClient.getHabbo().getHabboInfo().setLook(habbo.getHabboInfo().getLook()); gameClient.getHabbo().getHabboInfo().setLook(habbo.getHabboInfo().getLook());
gameClient.getHabbo().getHabboInfo().setGender(habbo.getHabboInfo().getGender()); gameClient.getHabbo().getHabboInfo().setGender(habbo.getHabboInfo().getGender());
gameClient.sendResponse(new UserDataComposer(gameClient.getHabbo())); gameClient.sendResponse(new UserDataComposer(gameClient.getHabbo()));

View File

@ -9,6 +9,7 @@ import com.eu.habbo.habbohotel.users.HabboItem;
import com.eu.habbo.messages.ServerMessage; import com.eu.habbo.messages.ServerMessage;
import com.eu.habbo.messages.outgoing.rooms.users.RoomUserDataComposer; import com.eu.habbo.messages.outgoing.rooms.users.RoomUserDataComposer;
import com.eu.habbo.messages.outgoing.users.UserDataComposer; import com.eu.habbo.messages.outgoing.users.UserDataComposer;
import com.eu.habbo.util.figure.FigureUtil;
import java.sql.ResultSet; import java.sql.ResultSet;
import java.sql.SQLException; import java.sql.SQLException;
@ -93,7 +94,7 @@ public class InteractionMannequin extends HabboItem
} }
} }
client.getHabbo().getHabboInfo().setLook(look.substring(0, look.length() - 1)); client.getHabbo().getHabboInfo().setLook(look.substring(0, look.length() - 1), true);
room.sendComposer(new RoomUserDataComposer(client.getHabbo()).compose()); room.sendComposer(new RoomUserDataComposer(client.getHabbo()).compose());
client.sendResponse(new UserDataComposer(client.getHabbo())); client.sendResponse(new UserDataComposer(client.getHabbo()));
} }

View File

@ -14,7 +14,7 @@ import com.eu.habbo.plugin.EventHandler;
import com.eu.habbo.plugin.events.users.UserDisconnectEvent; import com.eu.habbo.plugin.events.users.UserDisconnectEvent;
import com.eu.habbo.plugin.events.users.UserExitRoomEvent; import com.eu.habbo.plugin.events.users.UserExitRoomEvent;
import com.eu.habbo.plugin.events.users.UserSavedLookEvent; import com.eu.habbo.plugin.events.users.UserSavedLookEvent;
import com.eu.habbo.util.FigureUtil; import com.eu.habbo.util.figure.FigureUtil;
import java.sql.ResultSet; import java.sql.ResultSet;
import java.sql.SQLException; import java.sql.SQLException;
@ -102,7 +102,7 @@ public class InteractionFootballGate extends HabboItem
Emulator.getPluginManager().fireEvent(lookEvent); Emulator.getPluginManager().fireEvent(lookEvent);
if(!lookEvent.isCancelled()) if(!lookEvent.isCancelled())
{ {
habbo.getHabboInfo().setLook(lookEvent.newLook); habbo.getHabboInfo().setLook(lookEvent.newLook, true);
Emulator.getThreading().run(habbo.getHabboInfo()); Emulator.getThreading().run(habbo.getHabboInfo());
habbo.getClient().sendResponse(new UpdateUserLookComposer(habbo)); habbo.getClient().sendResponse(new UpdateUserLookComposer(habbo));
room.sendComposer(new RoomUserDataComposer(habbo).compose()); room.sendComposer(new RoomUserDataComposer(habbo).compose());
@ -119,7 +119,7 @@ public class InteractionFootballGate extends HabboItem
if(!lookEvent.isCancelled()) if(!lookEvent.isCancelled())
{ {
habbo.getHabboStats().cache.put(CACHE_KEY, habbo.getHabboInfo().getLook()); habbo.getHabboStats().cache.put(CACHE_KEY, habbo.getHabboInfo().getLook());
habbo.getHabboInfo().setLook(lookEvent.newLook); habbo.getHabboInfo().setLook(lookEvent.newLook, true);
Emulator.getThreading().run(habbo.getHabboInfo()); Emulator.getThreading().run(habbo.getHabboInfo());
habbo.getClient().sendResponse(new UpdateUserLookComposer(habbo)); habbo.getClient().sendResponse(new UpdateUserLookComposer(habbo));
room.sendComposer(new RoomUserDataComposer(habbo).compose()); room.sendComposer(new RoomUserDataComposer(habbo).compose());

View File

@ -17,14 +17,15 @@ import com.eu.habbo.messages.outgoing.users.*;
import com.eu.habbo.plugin.events.users.UserCreditsEvent; import com.eu.habbo.plugin.events.users.UserCreditsEvent;
import com.eu.habbo.plugin.events.users.UserDisconnectEvent; import com.eu.habbo.plugin.events.users.UserDisconnectEvent;
import com.eu.habbo.plugin.events.users.UserPointsEvent; import com.eu.habbo.plugin.events.users.UserPointsEvent;
import gnu.trove.TIntCollection;
import gnu.trove.map.hash.THashMap; import gnu.trove.map.hash.THashMap;
import gnu.trove.set.hash.THashSet; import gnu.trove.set.hash.THashSet;
import java.net.InetSocketAddress; import java.net.InetSocketAddress;
import java.sql.ResultSet; import java.sql.ResultSet;
import java.util.ArrayList; import java.util.*;
import java.util.List; import java.util.stream.Collectors;
import java.util.Map; import java.util.stream.Stream;
public class Habbo implements Runnable public class Habbo implements Runnable
{ {
@ -512,4 +513,14 @@ public class Habbo implements Runnable
this.client.getHabbo().getHabboInfo().getCurrentRoom().unIdle(this.client.getHabbo()); this.client.getHabbo().getHabboInfo().getCurrentRoom().unIdle(this.client.getHabbo());
} }
} }
public Set<Integer> getForbiddenClothing() {
TIntCollection clothingIDs = this.getInventory().getWardrobeComponent().getClothing();
return Emulator.getGameEnvironment().getCatalogManager().clothing.values().stream()
.filter(c -> !clothingIDs.contains(c.id))
.map(c -> c.setId)
.flatMap(c -> Arrays.stream(c).boxed())
.collect(Collectors.toSet());
}
} }

View File

@ -13,6 +13,7 @@ import com.eu.habbo.habbohotel.rooms.RoomTile;
import com.eu.habbo.habbohotel.rooms.RoomUnit; import com.eu.habbo.habbohotel.rooms.RoomUnit;
import com.eu.habbo.messages.outgoing.rooms.users.RoomUserStatusComposer; import com.eu.habbo.messages.outgoing.rooms.users.RoomUserStatusComposer;
import com.eu.habbo.threading.runnables.RoomUnitRidePet; import com.eu.habbo.threading.runnables.RoomUnitRidePet;
import com.eu.habbo.util.figure.FigureUtil;
import gnu.trove.map.hash.TIntIntHashMap; import gnu.trove.map.hash.TIntIntHashMap;
import gnu.trove.procedure.TIntIntProcedure; import gnu.trove.procedure.TIntIntProcedure;
@ -215,7 +216,19 @@ public class HabboInfo implements Runnable
return this.look; return this.look;
} }
public void setLook(String look) { this.look = look; } public void setLook(String look) {
this.setLook(look, false);
}
public void setLook(String look, boolean stripForbidden) {
if (stripForbidden) {
Habbo habbo = Emulator.getGameEnvironment().getHabboManager().getHabbo(this.id);
if (habbo != null) look = FigureUtil.stripBlacklistedClothing(look, habbo.getForbiddenClothing());
}
this.look = look;
}
public HabboGender getGender() public HabboGender getGender()
{ {

View File

@ -8,6 +8,7 @@ import com.eu.habbo.messages.incoming.MessageHandler;
import com.eu.habbo.messages.outgoing.rooms.users.RoomUserDataComposer; import com.eu.habbo.messages.outgoing.rooms.users.RoomUserDataComposer;
import com.eu.habbo.messages.outgoing.users.UpdateUserLookComposer; import com.eu.habbo.messages.outgoing.users.UpdateUserLookComposer;
import com.eu.habbo.plugin.events.users.UserSavedLookEvent; import com.eu.habbo.plugin.events.users.UserSavedLookEvent;
import com.eu.habbo.util.figure.FigureUtil;
public class UserSaveLookEvent extends MessageHandler public class UserSaveLookEvent extends MessageHandler
{ {
@ -30,6 +31,12 @@ public class UserSaveLookEvent extends MessageHandler
} }
String look = this.packet.readString(); String look = this.packet.readString();
if (FigureUtil.hasBlacklistedClothing(look, this.client.getHabbo().getForbiddenClothing())) {
ScripterManager.scripterDetected(this.client, "The user tried to wear clothing that they have not bought yet.");
return;
}
UserSavedLookEvent lookEvent = new UserSavedLookEvent(this.client.getHabbo(), gender, look); UserSavedLookEvent lookEvent = new UserSavedLookEvent(this.client.getHabbo(), gender, look);
Emulator.getPluginManager().fireEvent(lookEvent); Emulator.getPluginManager().fireEvent(lookEvent);
if(lookEvent.isCancelled()) if(lookEvent.isCancelled())

View File

@ -5,6 +5,7 @@ import com.eu.habbo.habbohotel.users.Habbo;
import com.eu.habbo.messages.outgoing.rooms.users.RoomUserDataComposer; import com.eu.habbo.messages.outgoing.rooms.users.RoomUserDataComposer;
import com.eu.habbo.messages.outgoing.users.MeMenuSettingsComposer; import com.eu.habbo.messages.outgoing.users.MeMenuSettingsComposer;
import com.eu.habbo.messages.outgoing.users.UpdateUserLookComposer; import com.eu.habbo.messages.outgoing.users.UpdateUserLookComposer;
import com.eu.habbo.util.figure.FigureUtil;
import com.google.gson.Gson; import com.google.gson.Gson;
import java.sql.Connection; import java.sql.Connection;
@ -57,7 +58,7 @@ public class UpdateUser extends RCONMessage<UpdateUser.JSON>
if (!json.look.isEmpty()) if (!json.look.isEmpty())
{ {
habbo.getHabboInfo().setLook(json.look); habbo.getHabboInfo().setLook(json.look, json.strip_unredeemed_clothing);
if(habbo.getClient() != null) { if(habbo.getClient() != null) {
habbo.getClient().sendResponse(new UpdateUserLookComposer(habbo).compose()); habbo.getClient().sendResponse(new UpdateUserLookComposer(habbo).compose());
} }
@ -160,6 +161,8 @@ public class UpdateUser extends RCONMessage<UpdateUser.JSON>
public String look = ""; public String look = "";
public boolean strip_unredeemed_clothing = false;
//More could be added in the future. //More could be added in the future.
} }
} }

View File

@ -1,65 +0,0 @@
package com.eu.habbo.util;
import gnu.trove.map.hash.THashMap;
import org.apache.commons.lang3.ArrayUtils;
import java.util.Map;
public class FigureUtil
{
public static THashMap<String, String> getFigureBits(String looks)
{
THashMap<String, String> bits = new THashMap<>();
String[] sets = looks.split("\\.");
for(String set : sets)
{
String[] setBits = set.split("-", 2);
bits.put(setBits[0], setBits.length > 1 ? setBits[1] : "");
}
return bits;
}
public static String mergeFigures(String figure1, String figure2)
{
return mergeFigures(figure1, figure2, null, null);
}
public static String mergeFigures(String figure1, String figure2, String[] limitFigure1)
{
return mergeFigures(figure1, figure2, limitFigure1, null);
}
public static String mergeFigures(String figure1, String figure2, String[] limitFigure1, String[] limitFigure2)
{
THashMap<String, String> figureBits1 = getFigureBits(figure1);
THashMap<String, String> figureBits2 = getFigureBits(figure2);
StringBuilder finalLook = new StringBuilder();
for (Map.Entry<String, String> keys : figureBits1.entrySet())
{
if(limitFigure1 == null || ArrayUtils.contains(limitFigure1, keys.getKey()))
{
finalLook.append(keys.getKey()).append("-").append(keys.getValue()).append(".");
}
}
for (Map.Entry<String, String> keys : figureBits2.entrySet())
{
if(limitFigure2 == null || ArrayUtils.contains(limitFigure2, keys.getKey()))
{
finalLook.append(keys.getKey()).append("-").append(keys.getValue()).append(".");
}
}
if(finalLook.toString().endsWith("."))
{
finalLook = new StringBuilder(finalLook.substring(0, finalLook.length() - 1));
}
return finalLook.toString();
}
}

View File

@ -4,6 +4,8 @@ import gnu.trove.map.hash.THashMap;
import org.apache.commons.lang3.ArrayUtils; import org.apache.commons.lang3.ArrayUtils;
import java.util.Map; import java.util.Map;
import java.util.Set;
import java.util.StringJoiner;
public class FigureUtil public class FigureUtil
{ {
@ -32,6 +34,40 @@ public class FigureUtil
return mergeFigures(figure1, figure2, limitFigure1, null); return mergeFigures(figure1, figure2, limitFigure1, null);
} }
public static boolean hasBlacklistedClothing(String figure, Set<Integer> blacklist) {
for (String set : figure.split("\\.")) {
String[] pieces = set.split("-");
try {
if (pieces.length >= 2 && blacklist.contains(Integer.valueOf(pieces[1]))) {
return true;
}
} catch (NumberFormatException ignored) {
}
}
return false;
}
public static String stripBlacklistedClothing(String figure, Set<Integer> blacklist) {
StringJoiner joiner = new StringJoiner(".");
for (String set : figure.split("\\.")) {
String[] pieces = set.split("-");
try {
if (pieces.length < 2 || !blacklist.contains(Integer.valueOf(pieces[1]))) {
joiner.add(set);
}
} catch (NumberFormatException ignored) {
joiner.add(set);
}
}
return joiner.toString();
}
public static String mergeFigures(String figure1, String figure2, String[] limitFigure1, String[] limitFigure2) public static String mergeFigures(String figure1, String figure2, String[] limitFigure1, String[] limitFigure2)
{ {
THashMap<String, String> figureBits1 = getFigureBits(figure1); THashMap<String, String> figureBits1 = getFigureBits(figure1);