Fix community servers and the browser

This commit is contained in:
Dan Mulloy 2018-01-14 10:22:34 -05:00 committed by Alexander Meech
parent c5f29533b7
commit 0234cf0f74
6 changed files with 161 additions and 36 deletions

View File

@ -1,5 +1,7 @@
package mineplex.core.communities;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
@ -21,9 +23,9 @@ public class Community
private long _chatDelay;
private GameDisplay _favoriteGame;
private PrivacySetting _privacy;
private boolean _showInBrowser;
private transient boolean unloaded = false;
private transient boolean persist = false;
private transient List<String> flags = new ArrayList<>();
public Community(int id, String name)
{
@ -110,7 +112,20 @@ public class Community
{
_privacy = privacy;
}
public boolean isBrowserFlagSet()
{
return _showInBrowser;
}
/**
* We don't actually care if they should be shown in the browser, just that the flag has been set
*/
public void setBrowserFlag()
{
_showInBrowser = true;
}
public void sendChat(String chat)
{
getMembers().values().stream().filter(info -> info.ReadingChat).forEach(member -> UtilPlayer.message(Bukkit.getPlayer(member.UUID), chat));
@ -126,26 +141,17 @@ public class Community
getMembers().values().stream().filter(member -> member.Role.ordinal() <= minimumRole.ordinal()).forEach(member -> UtilPlayer.message(Bukkit.getPlayer(member.UUID), message));
}
public void markUnloaded()
public void setFlag(String flag, boolean value)
{
this.unloaded = true;
if (value) flags.add(flag.toLowerCase());
else flags.remove(flag.toLowerCase());
}
public boolean isUnloaded()
public boolean getFlag(String flag)
{
return unloaded;
return flags.contains(flag.toLowerCase());
}
public void persist()
{
this.persist = persist;
}
public boolean isPersistent()
{
return persist;
}
public static enum PrivacySetting
{
OPEN("Open to Join"),

View File

@ -9,12 +9,15 @@ import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Objects;
import java.util.Random;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import com.google.common.collect.Sets;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
@ -103,10 +106,13 @@ public class CommunityManager extends MiniDbClientPlugin<CommunityMemberData>
private final int CACHE_INVALIDATION_SECONDS = 300; // The number of seconds between full communities refreshes
public final Pattern ALPHA_NUMERIC_PATTERN = Pattern.compile("[^A-Za-z0-9]");
public final String[] BLOCKED_NAMES = new String[] {"help", "chat", "create", "description", "disband", "invite", "join", "mcs", "rename", "uninvite", "trainee", "mod", "moderator", "srmod", "seniormod", "seniormoderator", "builder", "maplead", "twitch", "youtube", "support", "admin", "administrator", "leader", "dev", "developer", "owner", "party", "mineplex", "mineplexOfficial", "staff", "mineplexstaff", "qualityassurance", "traineemanagement", "modcoordination", "forumninja", "communitymanagement", "event", "socialmedia"};
private final CommunityRepository _repo;
private final Map<Integer, Community> _loadedCommunities;
public final List<Integer> BrowserIds = new LinkedList<>();
private final Random rand = new Random();
private final List<Integer> _browserIds = new LinkedList<>();
private final List<UUID> _creating = new ArrayList<>();
// private final DataRepository<PlayerStatus> StatusRepository;
@ -135,6 +141,8 @@ public class CommunityManager extends MiniDbClientPlugin<CommunityMemberData>
_loadedCommunities = new ConcurrentHashMap<>();
runAsync(() -> _repo.loadBrowserCommunities(_browserIds));
_clientManager = require(CoreClientManager.class);
_clientManager.addStoredProcedureLoginProcessor(new ILoginProcessor()
{
@ -180,7 +188,7 @@ public class CommunityManager extends MiniDbClientPlugin<CommunityMemberData>
_updateCycleCount = 0;
// Make sure to include communities that should be unloaded after their update
dirty.stream().filter(Community::isUnloaded).forEach(communities::add);
dirty.stream().filter(com -> com.getFlag("unloaded")).forEach(communities::add);
dirty.clear();
communities.addAll(_loadedCommunities.values());
@ -222,7 +230,7 @@ public class CommunityManager extends MiniDbClientPlugin<CommunityMemberData>
if (community == null)
community = _repo.loadCommunity(_loadedCommunities, comId);
community.persist();
community.setFlag("persist", true);
}
generatePermissions();
@ -265,21 +273,49 @@ public class CommunityManager extends MiniDbClientPlugin<CommunityMemberData>
_cycling = true;
runAsync(() ->
{
final List<Integer> ids = new LinkedList<>();
_loadedCommunities.values().stream().filter(c -> c.getMembers().size() >= 5 && c.getPrivacySetting() != PrivacySetting.PRIVATE).forEach(c -> ids.add(c.getId()));
Collections.shuffle(ids);
Collections.shuffle(_browserIds, rand);
runSync(() ->
{
BrowserIds.clear();
BrowserIds.addAll(ids);
_cycling = false;
UtilServer.CallEvent(new CommunityBrowserUpdateEvent());
});
});
}
public List<Integer> getBrowserIds()
{
return _browserIds;
}
public void loadCommunitiesForDisplay(List<Integer> communities)
{
List<Integer> load = communities.stream().filter(com -> getLoadedCommunity(com) == null).collect(Collectors.toList());
_repo.loadCommunities(_loadedCommunities, load);
for (int id : load)
{
Community com = _loadedCommunities.get(id);
if (com != null)
com.setFlag("display", true);
}
}
public void unloadDisplayCommunities(List<Integer> unload)
{
unload.stream().filter(com ->
{
Community community = getLoadedCommunity(com);
return community == null || (community.getFlag("display") && !community.getFlag("persist"));
}).forEach(_loadedCommunities::remove);
}
public void updateBrowserStatus(Community community)
{
_repo.updateBrowserStatus(community, community.getPrivacySetting() != PrivacySetting.PRIVATE
&& community.getMembers().size() >= 5);
}
public int getCount()
{
return _loadedCommunities.size();
@ -531,7 +567,7 @@ public class CommunityManager extends MiniDbClientPlugin<CommunityMemberData>
_loadedCommunities.remove(community.getId());
runSync(() ->
{
if (BrowserIds.remove(community.getId()))
if (_browserIds.remove(community.getId()))
{
UtilServer.CallEvent(new CommunityBrowserUpdateEvent());
}
@ -675,6 +711,7 @@ public class CommunityManager extends MiniDbClientPlugin<CommunityMemberData>
{
_repo.deleteInviteToCommunity(community.getId(), playerName);
}
updateBrowserStatus(community);
});
new CommunityUpdateMembership(community.getId(), sender.getName(), sender.getName(), sender.getUniqueId().toString(), accountId, false, false).publish();
if (fromInvite)
@ -697,6 +734,7 @@ public class CommunityManager extends MiniDbClientPlugin<CommunityMemberData>
runAsync(() ->
{
_repo.removeFromCommunity(info.AccountId, community.getId());
updateBrowserStatus(community);
});
new CommunityUpdateMembership(community.getId(), sender.getName(), info.Name, info.UUID.toString(), info.AccountId, false, true).publish();
}
@ -706,6 +744,8 @@ public class CommunityManager extends MiniDbClientPlugin<CommunityMemberData>
runAsync(() ->
{
_repo.updateCommunitySetting(setting, community.getId(), newValue);
if (setting == CommunitySetting.PRIVACY)
updateBrowserStatus(community);
});
new CommunityUpdateSetting(community.getId(), sender.getName(), setting.toString(), newValue).publish();
}
@ -876,14 +916,14 @@ public class CommunityManager extends MiniDbClientPlugin<CommunityMemberData>
List<Community> communities = Get(player).getCommunities();
for (Community community : communities)
{
if (community.isPersistent()
if (community.getFlag("persist")
|| community.getMembers().keySet().stream().anyMatch(uuid -> !player.getUniqueId().equals(uuid) && Bukkit.getPlayer(uuid) != null))
continue;
System.out.println("Unloading community: " + community.getId());
// Unload this community from memory
community.markUnloaded();
community.setFlag("unloaded", true);
_loadedCommunities.remove(community.getId());
}
}

View File

@ -88,7 +88,12 @@ public enum CommunitySetting
Community community = pair.getRight();
community.setDescription(value);
});
}),
SHOW_IN_BROWSER(8, pair ->
{
pair.getRight().setBrowserFlag();
}),
;
private int _id;
private Callback<Pair<String, Community>> _parser;

View File

@ -23,6 +23,8 @@ public abstract class CommunitiesGUIPage implements Listener
protected Player Viewer;
protected Inventory Inv;
protected Map<Integer, CommunitiesGUIButton> Buttons = new HashMap<>();
protected static CommunityManager _manager;
public CommunitiesGUIPage(String name, int rows, Player viewer)
{
@ -37,7 +39,9 @@ public abstract class CommunitiesGUIPage implements Listener
public static CommunityManager getCommunityManager()
{
return Managers.get(CommunityManager.class);
if (_manager == null)
_manager = Managers.require(CommunityManager.class);
return _manager;
}
public void open()

View File

@ -10,6 +10,7 @@ import org.bukkit.event.EventHandler;
import mineplex.core.common.util.C;
import mineplex.core.communities.CommunityBrowserUpdateEvent;
import mineplex.core.communities.CommunityDisbandEvent;
import mineplex.core.communities.CommunityManager;
import mineplex.core.communities.gui.ActionButton;
import mineplex.core.communities.gui.CommunitiesGUIPage;
import mineplex.core.communities.gui.overview.CommunityInvitesPage;
@ -80,11 +81,26 @@ public class CommunityBrowserPage extends CommunitiesGUIPage
Buttons.put(53, next);
Inv.setItem(53, next.Button);
}
CommunityManager manager = getCommunityManager();
int slot = 18;
boolean cleared = false;
// Unload the old communities
manager.unloadDisplayCommunities(_displaying);
// Generate the list of ids we're going to display
_displaying.clear();
for (int i = (page - 1) * COMMUNITIES_PER_PAGE; i < (page - 1) * COMMUNITIES_PER_PAGE + COMMUNITIES_PER_PAGE && i < getCommunityManager().BrowserIds.size(); i++)
for (int i = (page - 1) * COMMUNITIES_PER_PAGE; i < (page - 1) * COMMUNITIES_PER_PAGE + COMMUNITIES_PER_PAGE && i < manager.getBrowserIds().size(); i++)
{
_displaying.add(manager.getBrowserIds().get(i));
}
// Temporarily load the new ones
manager.loadCommunitiesForDisplay(_displaying);
for (int i = (page - 1) * COMMUNITIES_PER_PAGE; i < (page - 1) * COMMUNITIES_PER_PAGE + COMMUNITIES_PER_PAGE && i < manager.getBrowserIds().size(); i++)
{
if (!cleared && !initial)
{
@ -96,8 +112,8 @@ public class CommunityBrowserPage extends CommunitiesGUIPage
Inv.setItem(clear, null);
}
}
CommunityBrowserButton button = new CommunityBrowserButton(Viewer, getCommunityManager().getLoadedCommunity(getCommunityManager().BrowserIds.get(i)));
_displaying.add(getCommunityManager().BrowserIds.get(i));
CommunityBrowserButton button = new CommunityBrowserButton(Viewer, getCommunityManager().getLoadedCommunity(manager.getBrowserIds().get(i)));
// _displaying.add(manager.getBrowserIds().get(i));
Buttons.put(slot, button);
Inv.setItem(slot, button.Button);

View File

@ -2,10 +2,14 @@ package mineplex.core.communities.storage;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.stream.Collectors;
import java.util.stream.Stream;
@ -33,6 +37,7 @@ public class CommunityRepository extends RepositoryBase
private static final String GET_COMMUNITY_MEMBERS = "SELECT cm.communityId, cm.accountId, cm.communityRole, ac.name, ac.uuid, ac.lastLogin, cm.readingChat FROM communityMembers cm INNER JOIN accounts ac ON ac.id=cm.accountId";
private static final String GET_COMMUNITY_JOIN_REQUESTS = "SELECT cjr.communityId, cjr.accountId, ac.name, ac.uuid FROM communityJoinRequests cjr INNER JOIN accounts ac ON ac.id=cjr.accountId WHERE cjr.accountId=?;";
private static final String GET_COMMUNITY_SETTINGS = "SELECT communityId, settingId, settingValue FROM communitySettings";
private static final String GET_PUBLIC_COMMUNITIES = "SELECT communityId FROM communities WHERE settingId=8 AND settingValue='true';";
// Old queries
private static final String GET_ALL_COMMUNITIES = "SELECT * FROM communities WHERE region=?;";
@ -64,20 +69,69 @@ public class CommunityRepository extends RepositoryBase
_us = us;
}
private ColumnInt[] genIdColumns(String colName, List<Integer> nums)
/**
* Loads all communities that are eligible to be shown in the browser.
* That is, they have 5 or more members and aren't private.
*/
public void loadBrowserCommunities(final Collection<Integer> store)
{
return nums.stream().map(i -> new ColumnInt(colName, i)).toArray(ColumnInt[]::new);
try (Connection connection = getConnection())
{
executeQuery(connection, GET_PUBLIC_COMMUNITIES, resultSet ->
{
int id = resultSet.getInt("communityId");
store.add(id);
});
} catch (SQLException ex)
{
System.err.println("Failed to load public community IDs");
ex.printStackTrace();
}
}
/**
* Loads and stores a single community.
*/
public Community loadCommunity(final Map<Integer, Community> store, final int id)
{
loadInternal(store, Collections.singletonList(id), -1);
return store.get(id);
}
/**
* Loads all of the provided communities
*/
public void loadCommunities(final Map<Integer, Community> store, final List<Integer> load)
{
loadInternal(store, load, -1);
}
/**
* Loads all of the provided communities and the player's join requests.
*/
public void handlePlayerJoin(final Map<Integer, Community> store, final List<Integer> load, final int accountId)
{
loadInternal(store, load, accountId);
for (int id : load)
{
Community com = store.get(id);
if (com != null && !com.isBrowserFlagSet())
{
updateBrowserStatus(com, com.getPrivacySetting() != Community.PrivacySetting.PRIVATE
&& com.getMembers().size() >= 5);
}
}
}
public void updateBrowserStatus(Community community, boolean flag)
{
updateCommunitySetting(CommunitySetting.SHOW_IN_BROWSER, community.getId(), String.valueOf(flag));
}
private ColumnInt[] genIdColumns(String colName, List<Integer> nums)
{
return nums.stream().map(i -> new ColumnInt(colName, i)).toArray(ColumnInt[]::new);
}
private void loadInternal(final Map<Integer, Community> store, final List<Integer> load, final int accountId)