Rename and clean up MaplePartySearchCoordinator

This commit is contained in:
P0nk committed 2021-09-09 21:30:38 +02:00
1 parent c02efc5ca1
commit fbb0a08663
3 files changed
+93 -86

No files matched your search

@@ -47,7 +47,7 @@ public class PartySearchCharacter {
public Character callPlayer(int leaderid, int callerMapid) { public Character callPlayer(int leaderid, int callerMapid) {
Character chr = player.get(); Character chr = player.get();
if (chr == null || !MaplePartySearchCoordinator.isInVicinity(callerMapid, chr.getMapId())) { if (chr == null || !PartySearchCoordinator.isInVicinity(callerMapid, chr.getMapId())) {
return null; return null;
} }
@@ -42,32 +42,31 @@ import java.util.*;
import java.util.Map.Entry; import java.util.Map.Entry;
/** /**
*
* @author Ronan * @author Ronan
*/ */
public class MaplePartySearchCoordinator { public class PartySearchCoordinator {
private Map<Job, PartySearchStorage> storage = new HashMap<>(); private final Map<Job, PartySearchStorage> storage = new HashMap<>();
private Map<Job, PartySearchEchelon> upcomers = new HashMap<>(); private final Map<Job, PartySearchEchelon> upcomers = new HashMap<>();
private List<Character> leaderQueue = new LinkedList<>(); private final List<Character> leaderQueue = new LinkedList<>();
private final MonitoredReentrantReadWriteLock leaderQueueLock = new MonitoredReentrantReadWriteLock(MonitoredLockType.WORLD_PARTY_SEARCH_QUEUE, true); private final MonitoredReentrantReadWriteLock leaderQueueLock = new MonitoredReentrantReadWriteLock(MonitoredLockType.WORLD_PARTY_SEARCH_QUEUE, true);
private final MonitoredReadLock leaderQueueRLock = MonitoredReadLockFactory.createLock(leaderQueueLock); private final MonitoredReadLock leaderQueueRLock = MonitoredReadLockFactory.createLock(leaderQueueLock);
private final MonitoredWriteLock leaderQueueWLock = MonitoredWriteLockFactory.createLock(leaderQueueLock); private final MonitoredWriteLock leaderQueueWLock = MonitoredWriteLockFactory.createLock(leaderQueueLock);
private Map<Integer, Character> searchLeaders = new HashMap<>(); private final Map<Integer, Character> searchLeaders = new HashMap<>();
private Map<Integer, LeaderSearchMetadata> searchSettings = new HashMap<>(); private final Map<Integer, LeaderSearchMetadata> searchSettings = new HashMap<>();
private Map<Character, LeaderSearchMetadata> timeoutLeaders = new HashMap<>(); private final Map<Character, LeaderSearchMetadata> timeoutLeaders = new HashMap<>();
private int updateCount = 0; private int updateCount = 0;
private static Map<Integer, Set<Integer>> mapNeighbors = fetchNeighbouringMaps(); private static final Map<Integer, Set<Integer>> mapNeighbors = fetchNeighbouringMaps();
private static Map<Integer, Job> jobTable = instantiateJobTable(); private static final Map<Integer, Job> jobTable = instantiateJobTable();
private static Map<Integer, Set<Integer>> fetchNeighbouringMaps() { private static Map<Integer, Set<Integer>> fetchNeighbouringMaps() {
Map<Integer, Set<Integer>> mapLinks = new HashMap<>(); Map<Integer, Set<Integer>> mapLinks = new HashMap<>();
MapleData data = MapleDataProviderFactory.getDataProvider(WZFiles.ETC).getData("MapNeighbors.img"); MapleData data = MapleDataProviderFactory.getDataProvider(WZFiles.ETC).getData("MapNeighbors.img");
if (data != null) { if (data != null) {
for (MapleData mapdata : data.getChildren()) { for (MapleData mapdata : data.getChildren()) {
@@ -85,13 +84,13 @@ public class MaplePartySearchCoordinator {
} }
} }
} }
return mapLinks; return mapLinks;
} }
public static boolean isInVicinity(int callerMapid, int calleeMapid) { public static boolean isInVicinity(int callerMapid, int calleeMapid) {
Set<Integer> vicinityMapids = mapNeighbors.get(calleeMapid); Set<Integer> vicinityMapids = mapNeighbors.get(calleeMapid);
if (vicinityMapids != null) { if (vicinityMapids != null) {
return vicinityMapids.contains(calleeMapid); return vicinityMapids.contains(calleeMapid);
} else { } else {
@@ -103,10 +102,10 @@ public class MaplePartySearchCoordinator {
} }
} }
} }
private static Map<Integer, Job> instantiateJobTable() { private static Map<Integer, Job> instantiateJobTable() {
Map<Integer, Job> table = new HashMap<>(); Map<Integer, Job> table = new HashMap<>();
List<Pair<Integer, Integer>> jobSearchTypes = new LinkedList<Pair<Integer, Integer>>() {{ List<Pair<Integer, Integer>> jobSearchTypes = new LinkedList<Pair<Integer, Integer>>() {{
add(new Pair<>(Job.MAPLELEAF_BRIGADIER.getId(), 0)); add(new Pair<>(Job.MAPLELEAF_BRIGADIER.getId(), 0));
add(new Pair<>(0, 0)); add(new Pair<>(0, 0));
@@ -123,33 +122,33 @@ public class MaplePartySearchCoordinator {
add(new Pair<>(Job.WINDARCHER1.getId(), 0)); add(new Pair<>(Job.WINDARCHER1.getId(), 0));
add(new Pair<>(Job.EVAN1.getId(), 0)); add(new Pair<>(Job.EVAN1.getId(), 0));
}}; }};
int i = 0; int i = 0;
for (Pair<Integer, Integer> p : jobSearchTypes) { for (Pair<Integer, Integer> p : jobSearchTypes) {
table.put(i, Job.getById(p.getLeft())); table.put(i, Job.getById(p.getLeft()));
i++; i++;
for (int j = 1; j <= p.getRight(); j++) { for (int j = 1; j <= p.getRight(); j++) {
table.put(i, Job.getById(p.getLeft() + 10 * j)); table.put(i, Job.getById(p.getLeft() + 10 * j));
i++; i++;
} }
} }
return table; return table;
} }
private class LeaderSearchMetadata { private class LeaderSearchMetadata {
private int minLevel; private final int minLevel;
private int maxLevel; private final int maxLevel;
private List<Job> searchedJobs; private final List<Job> searchedJobs;
private int reentryCount; private int reentryCount;
private List<Job> decodeSearchedJobs(int jobsSelected) { private List<Job> decodeSearchedJobs(int jobsSelected) {
List<Job> searchedJobs = new LinkedList<>(); List<Job> searchedJobs = new LinkedList<>();
int topByte = (int)((Math.log(jobsSelected) / Math.log(2)) + 1e-5); int topByte = (int) ((Math.log(jobsSelected) / Math.log(2)) + 1e-5);
for (int i = 0; i <= topByte; i++) { for (int i = 0; i <= topByte; i++) {
if (jobsSelected % 2 == 1) { if (jobsSelected % 2 == 1) {
Job job = jobTable.get(i); Job job = jobTable.get(i);
@@ -157,50 +156,50 @@ public class MaplePartySearchCoordinator {
searchedJobs.add(job); searchedJobs.add(job);
} }
} }
jobsSelected = jobsSelected >> 1; jobsSelected = jobsSelected >> 1;
if (jobsSelected == 0) { if (jobsSelected == 0) {
break; break;
} }
} }
return searchedJobs; return searchedJobs;
} }
private LeaderSearchMetadata(int minLevel, int maxLevel, int jobs) { private LeaderSearchMetadata(int minLevel, int maxLevel, int jobs) {
this.minLevel = minLevel; this.minLevel = minLevel;
this.maxLevel = maxLevel; this.maxLevel = maxLevel;
this.searchedJobs = decodeSearchedJobs(jobs); this.searchedJobs = decodeSearchedJobs(jobs);
this.reentryCount = 0; this.reentryCount = 0;
} }
} }
public MaplePartySearchCoordinator() { public PartySearchCoordinator() {
for (Job job : jobTable.values()) { for (Job job : jobTable.values()) {
storage.put(job, new PartySearchStorage()); storage.put(job, new PartySearchStorage());
upcomers.put(job, new PartySearchEchelon()); upcomers.put(job, new PartySearchEchelon());
} }
} }
public void attachPlayer(Character chr) { public void attachPlayer(Character chr) {
upcomers.get(getPartySearchJob(chr.getJob())).attachPlayer(chr); upcomers.get(getPartySearchJob(chr.getJob())).attachPlayer(chr);
} }
public void detachPlayer(Character chr) { public void detachPlayer(Character chr) {
Job psJob = getPartySearchJob(chr.getJob()); Job psJob = getPartySearchJob(chr.getJob());
if (!upcomers.get(psJob).detachPlayer(chr)) { if (!upcomers.get(psJob).detachPlayer(chr)) {
storage.get(psJob).detachPlayer(chr); storage.get(psJob).detachPlayer(chr);
} }
} }
public void updatePartySearchStorage() { public void updatePartySearchStorage() {
for (Entry<Job, PartySearchEchelon> psUpdate : upcomers.entrySet()) { for (Entry<Job, PartySearchEchelon> psUpdate : upcomers.entrySet()) {
storage.get(psUpdate.getKey()).updateStorage(psUpdate.getValue().exportEchelon()); storage.get(psUpdate.getKey()).updateStorage(psUpdate.getValue().exportEchelon());
} }
} }
private static Job getPartySearchJob(Job job) { private static Job getPartySearchJob(Job job) {
if (job.getJobNiche() == 0) { if (job.getJobNiche() == 0) {
return Job.BEGINNER; return Job.BEGINNER;
@@ -212,11 +211,11 @@ public class MaplePartySearchCoordinator {
return Job.MAPLELEAF_BRIGADIER; return Job.MAPLELEAF_BRIGADIER;
} }
} }
private Character fetchPlayer(int callerCid, int callerMapid, Job job, int minLevel, int maxLevel) { private Character fetchPlayer(int callerCid, int callerMapid, Job job, int minLevel, int maxLevel) {
return storage.get(getPartySearchJob(job)).callPlayer(callerCid, callerMapid, minLevel, maxLevel); return storage.get(getPartySearchJob(job)).callPlayer(callerCid, callerMapid, minLevel, maxLevel);
} }
private void addQueueLeader(Character leader) { private void addQueueLeader(Character leader) {
leaderQueueRLock.lock(); leaderQueueRLock.lock();
try { try {
@@ -225,7 +224,7 @@ public class MaplePartySearchCoordinator {
leaderQueueRLock.unlock(); leaderQueueRLock.unlock();
} }
} }
private void removeQueueLeader(Character leader) { private void removeQueueLeader(Character leader) {
leaderQueueRLock.lock(); leaderQueueRLock.lock();
try { try {
@@ -234,23 +233,27 @@ public class MaplePartySearchCoordinator {
leaderQueueRLock.unlock(); leaderQueueRLock.unlock();
} }
} }
public void registerPartyLeader(Character leader, int minLevel, int maxLevel, int jobs) { public void registerPartyLeader(Character leader, int minLevel, int maxLevel, int jobs) {
if (searchLeaders.containsKey(leader.getId())) return; if (searchLeaders.containsKey(leader.getId())) {
return;
}
searchSettings.put(leader.getId(), new LeaderSearchMetadata(minLevel, maxLevel, jobs)); searchSettings.put(leader.getId(), new LeaderSearchMetadata(minLevel, maxLevel, jobs));
searchLeaders.put(leader.getId(), leader); searchLeaders.put(leader.getId(), leader);
addQueueLeader(leader); addQueueLeader(leader);
} }
private void registerPartyLeader(Character leader, LeaderSearchMetadata settings) { private void registerPartyLeader(Character leader, LeaderSearchMetadata settings) {
if (searchLeaders.containsKey(leader.getId())) return; if (searchLeaders.containsKey(leader.getId())) {
return;
}
searchSettings.put(leader.getId(), settings); searchSettings.put(leader.getId(), settings);
searchLeaders.put(leader.getId(), leader); searchLeaders.put(leader.getId(), leader);
addQueueLeader(leader); addQueueLeader(leader);
} }
public void unregisterPartyLeader(Character leader) { public void unregisterPartyLeader(Character leader) {
Character toRemove = searchLeaders.remove(leader.getId()); Character toRemove = searchLeaders.remove(leader.getId());
if (toRemove != null) { if (toRemove != null) {
@@ -260,13 +263,13 @@ public class MaplePartySearchCoordinator {
unregisterLongTermPartyLeader(leader); unregisterLongTermPartyLeader(leader);
} }
} }
private Character searchPlayer(Character leader) { private Character searchPlayer(Character leader) {
LeaderSearchMetadata settings = searchSettings.get(leader.getId()); LeaderSearchMetadata settings = searchSettings.get(leader.getId());
if (settings != null) { if (settings != null) {
int minLevel = settings.minLevel, maxLevel = settings.maxLevel; int minLevel = settings.minLevel, maxLevel = settings.maxLevel;
Collections.shuffle(settings.searchedJobs); Collections.shuffle(settings.searchedJobs);
int leaderCid = leader.getId(); int leaderCid = leader.getId();
int leaderMapid = leader.getMapId(); int leaderMapid = leader.getMapId();
for (Job searchJob : settings.searchedJobs) { for (Job searchJob : settings.searchedJobs) {
@@ -276,20 +279,20 @@ public class MaplePartySearchCoordinator {
} }
} }
} }
return null; return null;
} }
private boolean sendPartyInviteFromSearch(Character chr, Character leader) { private boolean sendPartyInviteFromSearch(Character chr, Character leader) {
if (chr == null) { if (chr == null) {
return false; return false;
} }
int partyid = leader.getPartyId(); int partyid = leader.getPartyId();
if (partyid < 0) { if (partyid < 0) {
return false; return false;
} }
if (MapleInviteCoordinator.createInvite(InviteType.PARTY, leader, partyid, chr.getId())) { if (MapleInviteCoordinator.createInvite(InviteType.PARTY, leader, partyid, chr.getId())) {
chr.disablePartySearchInvite(leader.getId()); chr.disablePartySearchInvite(leader.getId());
chr.sendPacket(PacketCreator.partySearchInvite(leader)); chr.sendPacket(PacketCreator.partySearchInvite(leader));
@@ -298,23 +301,23 @@ public class MaplePartySearchCoordinator {
return false; return false;
} }
} }
private Pair<List<Character>, List<Character>> fetchQueuedLeaders() { private Pair<List<Character>, List<Character>> fetchQueuedLeaders() {
List<Character> queuedLeaders, nextLeaders; List<Character> queuedLeaders, nextLeaders;
leaderQueueWLock.lock(); leaderQueueWLock.lock();
try { try {
int splitIdx = Math.min(leaderQueue.size(), 100); int splitIdx = Math.min(leaderQueue.size(), 100);
queuedLeaders = new LinkedList<>(leaderQueue.subList(0, splitIdx)); queuedLeaders = new LinkedList<>(leaderQueue.subList(0, splitIdx));
nextLeaders = new LinkedList<>(leaderQueue.subList(splitIdx, leaderQueue.size())); nextLeaders = new LinkedList<>(leaderQueue.subList(splitIdx, leaderQueue.size()));
} finally { } finally {
leaderQueueWLock.unlock(); leaderQueueWLock.unlock();
} }
return new Pair<>(queuedLeaders, nextLeaders); return new Pair<>(queuedLeaders, nextLeaders);
} }
private void registerLongTermPartyLeaders(List<Pair<Character, LeaderSearchMetadata>> recycledLeaders) { private void registerLongTermPartyLeaders(List<Pair<Character, LeaderSearchMetadata>> recycledLeaders) {
leaderQueueRLock.lock(); leaderQueueRLock.lock();
try { try {
@@ -325,7 +328,7 @@ public class MaplePartySearchCoordinator {
leaderQueueRLock.unlock(); leaderQueueRLock.unlock();
} }
} }
private void unregisterLongTermPartyLeader(Character leader) { private void unregisterLongTermPartyLeader(Character leader) {
leaderQueueRLock.lock(); leaderQueueRLock.lock();
try { try {
@@ -334,7 +337,7 @@ public class MaplePartySearchCoordinator {
leaderQueueRLock.unlock(); leaderQueueRLock.unlock();
} }
} }
private void reinstateLongTermPartyLeaders() { private void reinstateLongTermPartyLeaders() {
Map<Character, LeaderSearchMetadata> timeoutLeadersCopy; Map<Character, LeaderSearchMetadata> timeoutLeadersCopy;
leaderQueueWLock.lock(); leaderQueueWLock.lock();
@@ -344,19 +347,19 @@ public class MaplePartySearchCoordinator {
} finally { } finally {
leaderQueueWLock.unlock(); leaderQueueWLock.unlock();
} }
for (Entry<Character, LeaderSearchMetadata> e : timeoutLeadersCopy.entrySet()) { for (Entry<Character, LeaderSearchMetadata> e : timeoutLeadersCopy.entrySet()) {
registerPartyLeader(e.getKey(), e.getValue()); registerPartyLeader(e.getKey(), e.getValue());
} }
} }
public void runPartySearch() { public void runPartySearch() {
Pair<List<Character>, List<Character>> queuedLeaders = fetchQueuedLeaders(); Pair<List<Character>, List<Character>> queuedLeaders = fetchQueuedLeaders();
List<Character> searchedLeaders = new LinkedList<>(); List<Character> searchedLeaders = new LinkedList<>();
List<Character> recalledLeaders = new LinkedList<>(); List<Character> recalledLeaders = new LinkedList<>();
List<Character> expiredLeaders = new LinkedList<>(); List<Character> expiredLeaders = new LinkedList<>();
for (Character leader : queuedLeaders.getLeft()) { for (Character leader : queuedLeaders.getLeft()) {
Character chr = searchPlayer(leader); Character chr = searchPlayer(leader);
if (sendPartyInviteFromSearch(chr, leader)) { if (sendPartyInviteFromSearch(chr, leader)) {
@@ -373,7 +376,7 @@ public class MaplePartySearchCoordinator {
} }
} }
} }
leaderQueueRLock.lock(); leaderQueueRLock.lock();
try { try {
leaderQueue.clear(); leaderQueue.clear();
@@ -387,41 +390,45 @@ public class MaplePartySearchCoordinator {
} finally { } finally {
leaderQueueRLock.unlock(); leaderQueueRLock.unlock();
} }
for (Character leader : searchedLeaders) { for (Character leader : searchedLeaders) {
MapleParty party = leader.getParty(); MapleParty party = leader.getParty();
if (party != null && party.getMembers().size() < 6) { if (party != null && party.getMembers().size() < 6) {
addQueueLeader(leader); addQueueLeader(leader);
} else { } else {
if (leader.isLoggedinWorld()) leader.dropMessage(5, "Your Party Search token session has finished as your party reached full capacity."); if (leader.isLoggedinWorld()) {
leader.dropMessage(5, "Your Party Search token session has finished as your party reached full capacity.");
}
searchLeaders.remove(leader.getId()); searchLeaders.remove(leader.getId());
searchSettings.remove(leader.getId()); searchSettings.remove(leader.getId());
} }
} }
List<Pair<Character, LeaderSearchMetadata>> recycledLeaders = new LinkedList<>(); List<Pair<Character, LeaderSearchMetadata>> recycledLeaders = new LinkedList<>();
for (Character leader : expiredLeaders) { for (Character leader : expiredLeaders) {
searchLeaders.remove(leader.getId()); searchLeaders.remove(leader.getId());
LeaderSearchMetadata settings = searchSettings.remove(leader.getId()); LeaderSearchMetadata settings = searchSettings.remove(leader.getId());
if (leader.isLoggedinWorld()) { if (leader.isLoggedinWorld()) {
if (settings != null) { if (settings != null) {
recycledLeaders.add(new Pair<>(leader, settings)); recycledLeaders.add(new Pair<>(leader, settings));
if (YamlConfig.config.server.USE_DEBUG && leader.isGM()) leader.dropMessage(5, "Your Party Search token session is now on waiting queue for up to 7 minutes, to get it working right away please stop your Party Search and retry again later."); if (YamlConfig.config.server.USE_DEBUG && leader.isGM()) {
leader.dropMessage(5, "Your Party Search token session is now on waiting queue for up to 7 minutes, to get it working right away please stop your Party Search and retry again later.");
}
} else { } else {
leader.dropMessage(5, "Your Party Search token session expired, please stop your Party Search and retry again later."); leader.dropMessage(5, "Your Party Search token session expired, please stop your Party Search and retry again later.");
} }
} }
} }
if (!recycledLeaders.isEmpty()) { if (!recycledLeaders.isEmpty()) {
registerLongTermPartyLeaders(recycledLeaders); registerLongTermPartyLeaders(recycledLeaders);
} }
updateCount++; updateCount++;
if (updateCount % 77 == 0) { if (updateCount % 77 == 0) {
reinstateLongTermPartyLeaders(); reinstateLongTermPartyLeaders();
} }
} }
} }
+3 -3
View File
@@ -40,7 +40,7 @@ import net.server.audit.locks.factory.MonitoredWriteLockFactory;
import net.server.channel.Channel; import net.server.channel.Channel;
import net.server.channel.CharacterIdChannelPair; import net.server.channel.CharacterIdChannelPair;
import net.server.coordinator.matchchecker.MatchCheckerCoordinator; import net.server.coordinator.matchchecker.MatchCheckerCoordinator;
import net.server.coordinator.partysearch.MaplePartySearchCoordinator; import net.server.coordinator.partysearch.PartySearchCoordinator;
import net.server.coordinator.world.MapleInviteCoordinator; import net.server.coordinator.world.MapleInviteCoordinator;
import net.server.coordinator.world.MapleInviteCoordinator.InviteResult; import net.server.coordinator.world.MapleInviteCoordinator.InviteResult;
import net.server.coordinator.world.MapleInviteCoordinator.InviteType; import net.server.coordinator.world.MapleInviteCoordinator.InviteType;
@@ -89,7 +89,7 @@ public class World {
private PlayerStorage players = new PlayerStorage(); private PlayerStorage players = new PlayerStorage();
private ServicesManager services = new ServicesManager(WorldServices.SAVE_CHARACTER); private ServicesManager services = new ServicesManager(WorldServices.SAVE_CHARACTER);
private MatchCheckerCoordinator matchChecker = new MatchCheckerCoordinator(); private MatchCheckerCoordinator matchChecker = new MatchCheckerCoordinator();
private MaplePartySearchCoordinator partySearch = new MaplePartySearchCoordinator(); private PartySearchCoordinator partySearch = new PartySearchCoordinator();
private final MonitoredReentrantReadWriteLock chnLock = new MonitoredReentrantReadWriteLock(MonitoredLockType.WORLD_CHANNELS, true); private final MonitoredReentrantReadWriteLock chnLock = new MonitoredReentrantReadWriteLock(MonitoredLockType.WORLD_CHANNELS, true);
private MonitoredReadLock chnRLock = MonitoredReadLockFactory.createLock(chnLock); private MonitoredReadLock chnRLock = MonitoredReadLockFactory.createLock(chnLock);
@@ -517,7 +517,7 @@ public class World {
return matchChecker; return matchChecker;
} }
public MaplePartySearchCoordinator getPartySearchCoordinator() { public PartySearchCoordinator getPartySearchCoordinator() {
return partySearch; return partySearch;
} }