Skip to content

Commit a825cff

Browse files
committed
add common template to handle player-number leaderboards
1 parent 9459d33 commit a825cff

File tree

10 files changed

+626
-0
lines changed

10 files changed

+626
-0
lines changed

pom.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
<module>agent</module>
1515
<module>query</module>
1616
<module>value</module>
17+
<module>template</module>
1718
</modules>
1819

1920
<name>Topper</name>

template/pom.xml

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
3+
xmlns="http://maven.apache.org/POM/4.0.0"
4+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
5+
<modelVersion>4.0.0</modelVersion>
6+
<parent>
7+
<groupId>me.hsgamer</groupId>
8+
<artifactId>topper</artifactId>
9+
<version>4.5.0-SNAPSHOT</version>
10+
</parent>
11+
12+
<artifactId>topper-template</artifactId>
13+
<packaging>pom</packaging>
14+
<name>Topper Template</name>
15+
<modules>
16+
<module>top-player-number</module>
17+
</modules>
18+
</project>

template/top-player-number/pom.xml

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
3+
xmlns="http://maven.apache.org/POM/4.0.0"
4+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
5+
<modelVersion>4.0.0</modelVersion>
6+
<parent>
7+
<groupId>me.hsgamer</groupId>
8+
<artifactId>topper-template</artifactId>
9+
<version>4.5.0-SNAPSHOT</version>
10+
</parent>
11+
12+
<artifactId>topper-template-top-player-number</artifactId>
13+
<name>Topper Template - Top Player Number</name>
14+
<description>A Topper template to handle player-number leaderboards</description>
15+
16+
<dependencies>
17+
<dependency>
18+
<groupId>me.hsgamer</groupId>
19+
<artifactId>topper-data-simple</artifactId>
20+
<version>${project.version}</version>
21+
</dependency>
22+
<dependency>
23+
<groupId>me.hsgamer</groupId>
24+
<artifactId>topper-agent-core</artifactId>
25+
<version>${project.version}</version>
26+
</dependency>
27+
<dependency>
28+
<groupId>me.hsgamer</groupId>
29+
<artifactId>topper-agent-update</artifactId>
30+
<version>${project.version}</version>
31+
</dependency>
32+
<dependency>
33+
<groupId>me.hsgamer</groupId>
34+
<artifactId>topper-agent-snapshot</artifactId>
35+
<version>${project.version}</version>
36+
</dependency>
37+
<dependency>
38+
<groupId>me.hsgamer</groupId>
39+
<artifactId>topper-agent-storage</artifactId>
40+
<version>${project.version}</version>
41+
</dependency>
42+
<dependency>
43+
<groupId>me.hsgamer</groupId>
44+
<artifactId>topper-query-display-number</artifactId>
45+
<version>${project.version}</version>
46+
</dependency>
47+
<dependency>
48+
<groupId>me.hsgamer</groupId>
49+
<artifactId>topper-query-holder</artifactId>
50+
<version>${project.version}</version>
51+
</dependency>
52+
<dependency>
53+
<groupId>me.hsgamer</groupId>
54+
<artifactId>topper-query-snapshot</artifactId>
55+
<version>${project.version}</version>
56+
</dependency>
57+
<dependency>
58+
<groupId>me.hsgamer</groupId>
59+
<artifactId>topper-query-forward</artifactId>
60+
<version>${project.version}</version>
61+
</dependency>
62+
<dependency>
63+
<groupId>me.hsgamer</groupId>
64+
<artifactId>topper-storage-flat-core</artifactId>
65+
<version>${project.version}</version>
66+
</dependency>
67+
<dependency>
68+
<groupId>me.hsgamer</groupId>
69+
<artifactId>topper-storage-flat-converter</artifactId>
70+
<version>${project.version}</version>
71+
</dependency>
72+
<dependency>
73+
<groupId>me.hsgamer</groupId>
74+
<artifactId>topper-storage-sql-core</artifactId>
75+
<version>${project.version}</version>
76+
</dependency>
77+
<dependency>
78+
<groupId>me.hsgamer</groupId>
79+
<artifactId>topper-storage-sql-converter</artifactId>
80+
<version>${project.version}</version>
81+
</dependency>
82+
<dependency>
83+
<groupId>me.hsgamer</groupId>
84+
<artifactId>topper-value-string</artifactId>
85+
<version>${project.version}</version>
86+
</dependency>
87+
</dependencies>
88+
</project>
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
package me.hsgamer.topper.template.topplayernumber;
2+
3+
import me.hsgamer.topper.agent.core.Agent;
4+
import me.hsgamer.topper.agent.core.DataEntryAgent;
5+
import me.hsgamer.topper.template.topplayernumber.holder.NumberTopHolder;
6+
import me.hsgamer.topper.template.topplayernumber.manager.EntryConsumeManager;
7+
import me.hsgamer.topper.template.topplayernumber.manager.TopManager;
8+
import me.hsgamer.topper.template.topplayernumber.manager.TopQueryManager;
9+
import me.hsgamer.topper.template.topplayernumber.storage.DataStorageSupplier;
10+
import me.hsgamer.topper.value.core.ValueProvider;
11+
import org.jetbrains.annotations.Nullable;
12+
13+
import java.util.List;
14+
import java.util.Map;
15+
import java.util.Optional;
16+
import java.util.UUID;
17+
18+
public abstract class TopPlayerNumberTemplate {
19+
private final Settings settings;
20+
private final TopManager topManager;
21+
private final TopQueryManager topQueryManager;
22+
private final EntryConsumeManager entryConsumeManager;
23+
24+
protected TopPlayerNumberTemplate(Settings settings) {
25+
this.settings = settings;
26+
this.topManager = new TopManager(this);
27+
this.topQueryManager = new TopQueryManager(this);
28+
this.entryConsumeManager = new EntryConsumeManager(this);
29+
}
30+
31+
public abstract DataStorageSupplier getDataStorageSupplier(String type, DataStorageSupplier.Settings setting);
32+
33+
public abstract Optional<ValueProvider<UUID, Double>> createValueProvider(Map<String, Object> settings);
34+
35+
public abstract boolean isOnline(UUID uuid);
36+
37+
public abstract String getName(UUID uuid);
38+
39+
public abstract boolean hasPermission(UUID uuid, String permission);
40+
41+
public abstract Agent createTaskAgent(Runnable runnable, boolean async, long delay);
42+
43+
public abstract void logWarning(String message, @Nullable Throwable throwable);
44+
45+
public void logWarning(String message) {
46+
logWarning(message, null);
47+
}
48+
49+
public void modifyAgents(NumberTopHolder holder, List<Agent> agents, List<DataEntryAgent<UUID, Double>> entryAgents) {
50+
51+
}
52+
53+
public void enable() {
54+
topManager.enable();
55+
entryConsumeManager.enable();
56+
}
57+
58+
public void disable() {
59+
entryConsumeManager.disable();
60+
topManager.disable();
61+
}
62+
63+
public Settings getSettings() {
64+
return settings;
65+
}
66+
67+
public TopManager getTopManager() {
68+
return topManager;
69+
}
70+
71+
public TopQueryManager getTopQueryManager() {
72+
return topQueryManager;
73+
}
74+
75+
public EntryConsumeManager getEntryConsumeManager() {
76+
return entryConsumeManager;
77+
}
78+
79+
public interface Settings extends DataStorageSupplier.Settings {
80+
String storageType();
81+
82+
Map<String, NumberTopHolder.Settings> holders();
83+
84+
int taskSaveDelay();
85+
86+
int taskSaveEntryPerTick();
87+
88+
int taskUpdateEntryPerTick();
89+
90+
int taskUpdateDelay();
91+
92+
int taskUpdateSetDelay();
93+
94+
int taskUpdateMaxSkips();
95+
}
96+
}
Lines changed: 169 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,169 @@
1+
package me.hsgamer.topper.template.topplayernumber.holder;
2+
3+
import me.hsgamer.topper.agent.core.Agent;
4+
import me.hsgamer.topper.agent.core.AgentHolder;
5+
import me.hsgamer.topper.agent.core.DataEntryAgent;
6+
import me.hsgamer.topper.agent.snapshot.SnapshotAgent;
7+
import me.hsgamer.topper.agent.storage.StorageAgent;
8+
import me.hsgamer.topper.agent.update.UpdateAgent;
9+
import me.hsgamer.topper.data.core.DataEntry;
10+
import me.hsgamer.topper.data.simple.SimpleDataHolder;
11+
import me.hsgamer.topper.template.topplayernumber.TopPlayerNumberTemplate;
12+
import me.hsgamer.topper.template.topplayernumber.holder.display.ValueDisplay;
13+
import me.hsgamer.topper.template.topplayernumber.manager.EntryConsumeManager;
14+
import me.hsgamer.topper.value.core.ValueProvider;
15+
import me.hsgamer.topper.value.core.ValueWrapper;
16+
import org.jetbrains.annotations.Nullable;
17+
18+
import java.util.*;
19+
20+
public class NumberTopHolder extends SimpleDataHolder<UUID, Double> implements AgentHolder<UUID, Double> {
21+
public static final String GROUP = "topper";
22+
23+
private final ValueDisplay valueDisplay;
24+
private final List<Agent> agents;
25+
private final List<DataEntryAgent<UUID, Double>> entryAgents;
26+
private final StorageAgent<UUID, Double> storageAgent;
27+
private final UpdateAgent<UUID, Double> updateAgent;
28+
private final SnapshotAgent<UUID, Double> snapshotAgent;
29+
private final Double defaultValue;
30+
31+
public NumberTopHolder(TopPlayerNumberTemplate template, String name, Settings settings) {
32+
this.defaultValue = settings.defaultValue();
33+
34+
List<Agent> agents = new ArrayList<>();
35+
List<DataEntryAgent<UUID, Double>> entryAgents = new ArrayList<>();
36+
this.valueDisplay = new ValueDisplay(template, settings);
37+
38+
this.storageAgent = new StorageAgent<>(template.getTopManager().buildStorage(name));
39+
storageAgent.setMaxEntryPerCall(template.getSettings().taskSaveEntryPerTick());
40+
agents.add(storageAgent);
41+
agents.add(storageAgent.getLoadAgent(this));
42+
agents.add(template.createTaskAgent(storageAgent, true, template.getSettings().taskSaveDelay()));
43+
entryAgents.add(storageAgent);
44+
45+
ValueProvider<UUID, Double> valueProvider = template.createValueProvider(settings.valueProvider()).orElseGet(() -> {
46+
template.logWarning("No value provider found for " + name);
47+
return ValueProvider.empty();
48+
});
49+
boolean isAsync = settings.async();
50+
boolean showErrors = settings.showErrors();
51+
boolean resetOnError = settings.resetOnError();
52+
List<String> ignorePermissions = settings.ignorePermissions();
53+
List<String> resetPermissions = settings.resetPermissions();
54+
this.updateAgent = new UpdateAgent<>(this, valueProvider);
55+
if (!ignorePermissions.isEmpty() || !resetPermissions.isEmpty()) {
56+
updateAgent.setFilter(uuid -> {
57+
if (!template.isOnline(uuid)) {
58+
return UpdateAgent.FilterResult.SKIP;
59+
}
60+
if (!resetPermissions.isEmpty() && resetPermissions.stream().anyMatch(s -> template.hasPermission(uuid, s))) {
61+
return UpdateAgent.FilterResult.RESET;
62+
}
63+
if (!ignorePermissions.isEmpty() && ignorePermissions.stream().anyMatch(s -> template.hasPermission(uuid, s))) {
64+
return UpdateAgent.FilterResult.SKIP;
65+
}
66+
return UpdateAgent.FilterResult.CONTINUE;
67+
});
68+
}
69+
if (resetOnError) {
70+
updateAgent.setErrorHandler((uuid, valueWrapper) -> {
71+
if (showErrors && valueWrapper.state == ValueWrapper.State.ERROR) {
72+
template.logWarning("Error on getting value for " + name + " from " + uuid + " - " + valueWrapper.errorMessage, valueWrapper.throwable);
73+
}
74+
return ValueWrapper.handled(defaultValue);
75+
});
76+
} else if (showErrors) {
77+
updateAgent.setErrorHandler((uuid, valueWrapper) -> {
78+
if (valueWrapper.state == ValueWrapper.State.ERROR) {
79+
template.logWarning("Error on getting value for " + name + " from " + uuid + " - " + valueWrapper.errorMessage, valueWrapper.throwable);
80+
}
81+
});
82+
}
83+
updateAgent.setMaxSkips(template.getSettings().taskUpdateMaxSkips());
84+
entryAgents.add(updateAgent);
85+
agents.add(template.createTaskAgent(updateAgent.getUpdateRunnable(template.getSettings().taskUpdateEntryPerTick()), isAsync, template.getSettings().taskUpdateDelay()));
86+
agents.add(template.createTaskAgent(updateAgent.getSetRunnable(), true, template.getSettings().taskUpdateSetDelay()));
87+
88+
this.snapshotAgent = SnapshotAgent.create(this);
89+
boolean reverseOrder = settings.reverse();
90+
snapshotAgent.setComparator(reverseOrder ? Comparator.naturalOrder() : Comparator.reverseOrder());
91+
snapshotAgent.setFilter(entry -> entry.getValue() != null);
92+
agents.add(snapshotAgent);
93+
agents.add(template.createTaskAgent(snapshotAgent, true, 20L));
94+
95+
entryAgents.add(new DataEntryAgent<UUID, Double>() {
96+
@Override
97+
public void onUpdate(DataEntry<UUID, Double> entry, Double oldValue, Double newValue) {
98+
template.getEntryConsumeManager().consume(new EntryConsumeManager.Context(
99+
GROUP,
100+
name,
101+
entry.getKey(),
102+
oldValue,
103+
newValue
104+
));
105+
}
106+
});
107+
108+
template.modifyAgents(this, agents, entryAgents);
109+
this.agents = Collections.unmodifiableList(agents);
110+
this.entryAgents = Collections.unmodifiableList(entryAgents);
111+
}
112+
113+
@Override
114+
public @Nullable Double getDefaultValue() {
115+
return defaultValue;
116+
}
117+
118+
@Override
119+
public List<Agent> getAgents() {
120+
return agents;
121+
}
122+
123+
@Override
124+
public List<DataEntryAgent<UUID, Double>> getEntryAgents() {
125+
return entryAgents;
126+
}
127+
128+
public StorageAgent<UUID, Double> getStorageAgent() {
129+
return storageAgent;
130+
}
131+
132+
public UpdateAgent<UUID, Double> getUpdateAgent() {
133+
return updateAgent;
134+
}
135+
136+
public SnapshotAgent<UUID, Double> getSnapshotAgent() {
137+
return snapshotAgent;
138+
}
139+
140+
public ValueDisplay getValueDisplay() {
141+
return valueDisplay;
142+
}
143+
144+
public interface Settings {
145+
Double defaultValue();
146+
147+
String defaultLine();
148+
149+
String displayNullName();
150+
151+
String displayNullUuid();
152+
153+
String displayNullValue();
154+
155+
boolean async();
156+
157+
boolean showErrors();
158+
159+
boolean resetOnError();
160+
161+
boolean reverse();
162+
163+
List<String> ignorePermissions();
164+
165+
List<String> resetPermissions();
166+
167+
Map<String, Object> valueProvider();
168+
}
169+
}

0 commit comments

Comments
 (0)