Implement merchant blacklist, blocking any listed characters from entering

This commit is contained in:
P0nk
2021-09-28 18:26:27 +02:00
parent 3a9305d0d9
commit 5cae3fc336
3 changed files with 61 additions and 12 deletions

View File

@@ -44,7 +44,6 @@ import tools.PacketCreator;
import java.awt.*; import java.awt.*;
import java.sql.SQLException; import java.sql.SQLException;
import java.util.Arrays; import java.util.Arrays;
import java.util.List;
/** /**
* @author Matze * @author Matze
@@ -286,8 +285,7 @@ public final class PlayerInteractionHandler extends AbstractPacketHandler {
int oid = p.readInt(); int oid = p.readInt();
MapObject ob = chr.getMap().getMapObject(oid); MapObject ob = chr.getMap().getMapObject(oid);
if (ob instanceof PlayerShop) { if (ob instanceof PlayerShop shop) {
PlayerShop shop = (PlayerShop) ob;
shop.visitShop(chr); shop.visitShop(chr);
} else if (ob instanceof MiniGame) { } else if (ob instanceof MiniGame) {
p.skip(1); p.skip(1);
@@ -691,10 +689,26 @@ public final class PlayerInteractionHandler extends AbstractPacketHandler {
} }
c.sendPacket(PacketCreator.viewMerchantVisitorHistory(merchant.getVisitorHistory())); c.sendPacket(PacketCreator.viewMerchantVisitorHistory(merchant.getVisitorHistory()));
} else if (mode == Action.VIEW_BLACKLIST.getCode()) { } else if (mode == Action.VIEW_BLACKLIST.getCode()) {
List<String> blacklistedNames = List.of("Blanca", "Betsy", "Kevin", "Rosa", "Evan", "Terence", HiredMerchant merchant = chr.getHiredMerchant();
"Cecilia", "Gayle", "Erma", "Dorothy", "Willis", "Alberta", "Marilyn", "Myron", "Sheryl", if (merchant == null || !merchant.isOwner(chr)) {
"Marco", "Jose", "Kendra", "Laurence", "Victoria", "NonListed"); return;
c.sendPacket(PacketCreator.viewMerchantBlacklist(blacklistedNames)); }
c.sendPacket(PacketCreator.viewMerchantBlacklist(merchant.getBlacklist()));
} else if (mode == Action.ADD_TO_BLACKLIST.getCode()) {
HiredMerchant merchant = chr.getHiredMerchant();
if (merchant == null || !merchant.isOwner(chr)) {
return;
}
String chrName = p.readString();
merchant.addToBlacklist(chrName);
} else if (mode == Action.REMOVE_FROM_BLACKLIST.getCode()) {
HiredMerchant merchant = chr.getHiredMerchant();
if (merchant == null || !merchant.isOwner(chr)) {
return;
}
String chrName = p.readString();
merchant.removeFromBlacklist(chrName);
} else if (mode == Action.MERCHANT_ORGANIZE.getCode()) { } else if (mode == Action.MERCHANT_ORGANIZE.getCode()) {
HiredMerchant merchant = chr.getHiredMerchant(); HiredMerchant merchant = chr.getHiredMerchant();
if (merchant == null || !merchant.isOwner(chr)) { if (merchant == null || !merchant.isOwner(chr)) {

View File

@@ -47,10 +47,7 @@ import java.sql.ResultSet;
import java.sql.SQLException; import java.sql.SQLException;
import java.time.Duration; import java.time.Duration;
import java.time.Instant; import java.time.Instant;
import java.util.ArrayList; import java.util.*;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.Lock;
@@ -78,6 +75,7 @@ public class HiredMerchant extends AbstractMapObject {
private MapleMap map; private MapleMap map;
private final Visitor[] visitors = new Visitor[3]; private final Visitor[] visitors = new Visitor[3];
private final LinkedList<PastVisitor> visitorHistory = new LinkedList<>(); private final LinkedList<PastVisitor> visitorHistory = new LinkedList<>();
private final LinkedHashSet<String> blacklist = new LinkedHashSet<>(); // case-sensitive character names
private final Lock visitorLock = MonitoredReentrantLockFactory.createLock(MonitoredLockType.VISITOR_MERCH, true); private final Lock visitorLock = MonitoredReentrantLockFactory.createLock(MonitoredLockType.VISITOR_MERCH, true);
private record Visitor(Character chr, Instant enteredAt) {} private record Visitor(Character chr, Instant enteredAt) {}
@@ -489,6 +487,9 @@ public class HiredMerchant extends AbstractMapObject {
} else if (!this.isOpen()) { } else if (!this.isOpen()) {
chr.sendPacket(PacketCreator.getMiniRoomError(18)); chr.sendPacket(PacketCreator.getMiniRoomError(18));
return; return;
} else if (isBlacklisted(chr.getName())) {
chr.sendPacket(PacketCreator.getMiniRoomError(17));
return;
} else if (!this.addVisitor(chr)) { } else if (!this.addVisitor(chr)) {
chr.sendPacket(PacketCreator.getMiniRoomError(2)); chr.sendPacket(PacketCreator.getMiniRoomError(2));
return; return;
@@ -722,6 +723,40 @@ public class HiredMerchant extends AbstractMapObject {
return Collections.unmodifiableList(visitorHistory); return Collections.unmodifiableList(visitorHistory);
} }
public void addToBlacklist(String chrName) {
visitorLock.lock();
try {
if (blacklist.size() >= BLACKLIST_LIMIT) {
return;
}
blacklist.add(chrName);
} finally {
visitorLock.unlock();
}
}
public void removeFromBlacklist(String chrName) {
visitorLock.lock();
try {
blacklist.remove(chrName);
} finally {
visitorLock.unlock();
}
}
public Set<String> getBlacklist() {
return Collections.unmodifiableSet(blacklist);
}
private boolean isBlacklisted(String chrName) {
visitorLock.lock();
try {
return blacklist.contains(chrName);
} finally {
visitorLock.unlock();
}
}
public int getMapId() { public int getMapId() {
return map.getId(); return map.getId();
} }

View File

@@ -5221,7 +5221,7 @@ public class PacketCreator {
/** /**
* @param chrNames Blacklisted names. The first 20 names will be displayed, anything beyond does no difference. * @param chrNames Blacklisted names. The first 20 names will be displayed, anything beyond does no difference.
*/ */
public static Packet viewMerchantBlacklist(List<String> chrNames) { public static Packet viewMerchantBlacklist(Set<String> chrNames) {
final OutPacket p = OutPacket.create(SendOpcode.PLAYER_INTERACTION); final OutPacket p = OutPacket.create(SendOpcode.PLAYER_INTERACTION);
p.writeByte(PlayerInteractionHandler.Action.VIEW_BLACKLIST.getCode()); p.writeByte(PlayerInteractionHandler.Action.VIEW_BLACKLIST.getCode());
p.writeShort(chrNames.size()); p.writeShort(chrNames.size());