Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a34b07f2d1 | ||
|
|
1d90a59d5a | ||
|
|
2734836e58 | ||
|
|
768daf099f | ||
|
|
b6292667b8 | ||
|
|
8519535566 | ||
|
|
08e907678f | ||
|
|
27b93ac045 | ||
|
|
97f4c91c24 | ||
|
|
e919c845f7 | ||
|
|
1fb35276f7 | ||
|
|
f5f596f21c | ||
|
|
88523db213 | ||
|
|
3599b0fa1b | ||
|
|
950b543e98 | ||
|
|
e66927dd1a | ||
|
|
98d4f69ffb | ||
|
|
ad44c76309 | ||
|
|
58de66699e | ||
|
|
b81052327d | ||
|
|
59a3eff421 | ||
|
|
411a529e18 | ||
|
|
4d6946ab2c | ||
|
|
d5ae57b28e |
No files matched your search
@@ -0,0 +1,73 @@
|
||||
---
|
||||
name: Bug report
|
||||
about: Create a report to help us improve
|
||||
title: ''
|
||||
labels: bug
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
<!--
|
||||
Thank you for submitting an issue for NuVotifier. We appreciate
|
||||
any and all bug reports.
|
||||
|
||||
Before you continue, please ensure you are reporting
|
||||
a real bug and are not suffering from a configuration issue
|
||||
or a plugin problem. Once NuVotifier has received and
|
||||
called your vote listeners, it's not our issue any more.
|
||||
|
||||
If you are having difficulty setting up NuVotifier to receive
|
||||
votes, you are in the wrong place. Please view our wiki
|
||||
at https://github.com/NuVotifier/NuVotifier/wiki for a
|
||||
comprehensive set of instructions for configuring and
|
||||
diagnosing common problems with NuVotifier.
|
||||
|
||||
If you are certain that there is a problem with
|
||||
NuVotifier, please continue filling the form below.
|
||||
Make sure to follow these instructions:
|
||||
|
||||
1. Tell the exact NuVotifier version you're using.
|
||||
If you just say "latest" your issue will get closed.
|
||||
2. Please include all relevant logs and configuration
|
||||
files. Make sure to redact any tokens in the config
|
||||
file.
|
||||
3. Don't write anything between these arrows.
|
||||
We won't see it otherwise.
|
||||
4. Before you create your issue, delete this block of
|
||||
text and the code block at the very bottom. -->
|
||||
|
||||
### Information
|
||||
|
||||
**Platform on which you run NuVotifier**: <!-- Either Bukkit, Sponge, BungeeCord, or Velocity. -->
|
||||
|
||||
**Version of NuVotifier**:
|
||||
|
||||
```
|
||||
<!--
|
||||
Getting this depends on your platform:
|
||||
|
||||
Bukkit: Use /version Votifier
|
||||
|
||||
Sponge: Use /sponge plugins and find NuVotifier
|
||||
|
||||
BungeeCord: No such command exists.
|
||||
|
||||
Velocity: Use /velocity plugins from in-game and hover over "nuvotifier"
|
||||
-->
|
||||
```
|
||||
|
||||
**Relevant log**: <!-- Paste the log on https://gist.github.com/, replace this with link -->
|
||||
### Details
|
||||
|
||||
**Description**
|
||||
<!-- Replace this with a brief summary of the bug. -->
|
||||
|
||||
**Steps to reproduce**
|
||||
<!-- Replace this with exactly what you did to cause the bug. -->
|
||||
|
||||
**Expected behavior**
|
||||
<!-- Replace this with what you expected to happen. -->
|
||||
|
||||
```
|
||||
Please make sure to delete this line of text and the three ``` characters surrounding it, or your issue will be closed.
|
||||
```
|
||||
+1
-3
@@ -1,5 +1,3 @@
|
||||
dependencies {
|
||||
compile 'com.google.code.gson:gson:2.8.0'
|
||||
testCompile "junit:junit:4.11"
|
||||
testCompile "org.mockito:mockito-core:2.+"
|
||||
implementation 'com.google.code.gson:gson:2.8.0'
|
||||
}
|
||||
@@ -53,6 +53,10 @@ public class Vote {
|
||||
|
||||
private byte[] additionalData;
|
||||
|
||||
@Deprecated
|
||||
public Vote() {
|
||||
}
|
||||
|
||||
public Vote(String serviceName, String username, String address, String timeStamp) {
|
||||
this.serviceName = serviceName;
|
||||
this.username = username;
|
||||
@@ -66,7 +70,12 @@ public class Vote {
|
||||
this.username = username;
|
||||
this.address = address;
|
||||
this.timeStamp = timeStamp;
|
||||
this.additionalData = additionalData;
|
||||
this.additionalData = additionalData == null ? null : additionalData.clone();
|
||||
}
|
||||
|
||||
public Vote(Vote vote) {
|
||||
this(vote.getServiceName(), vote.getUsername(), vote.getAddress(), vote.getTimeStamp(),
|
||||
vote.getAdditionalData() == null ? null : vote.getAdditionalData().clone());
|
||||
}
|
||||
|
||||
private static String getTimestamp(JsonElement object) {
|
||||
@@ -181,7 +190,7 @@ public class Vote {
|
||||
* @return Additional data sent with the vote
|
||||
*/
|
||||
public byte[] getAdditionalData() {
|
||||
return additionalData;
|
||||
return additionalData == null ? null : additionalData.clone();
|
||||
}
|
||||
|
||||
public JsonObject serialize() {
|
||||
@@ -198,7 +207,7 @@ public class Vote {
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
if (!(o instanceof Vote)) return false;
|
||||
|
||||
Vote vote = (Vote) o;
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package com.vexsoftware.votifier.model;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
import org.junit.Test;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
|
||||
+19
-3
@@ -1,13 +1,18 @@
|
||||
|
||||
import org.apache.tools.ant.filters.ReplaceTokens
|
||||
|
||||
plugins {
|
||||
id "com.github.spotbugs" version "4.2.4" apply false
|
||||
}
|
||||
|
||||
allprojects {
|
||||
group 'com.vexsoftware'
|
||||
version '3.0.0-SNAPSHOT'
|
||||
version '2.7.0'
|
||||
}
|
||||
|
||||
subprojects {
|
||||
apply plugin: 'java'
|
||||
apply plugin: "com.github.spotbugs"
|
||||
|
||||
sourceCompatibility = 1.8
|
||||
|
||||
@@ -29,8 +34,9 @@ subprojects {
|
||||
|
||||
dependencies {
|
||||
testImplementation "org.junit.jupiter:junit-jupiter-api:5.4.2"
|
||||
testRuntime "org.junit.jupiter:junit-jupiter-engine:5.4.2"
|
||||
testCompile "org.mockito:mockito-core:2.+"
|
||||
testRuntimeOnly "org.junit.jupiter:junit-jupiter-engine:5.4.2"
|
||||
testImplementation "org.junit.jupiter:junit-jupiter-params:5.4.2"
|
||||
testImplementation "org.mockito:mockito-core:2.+"
|
||||
}
|
||||
|
||||
processResources {
|
||||
@@ -40,4 +46,14 @@ subprojects {
|
||||
test {
|
||||
useJUnitPlatform()
|
||||
}
|
||||
|
||||
tasks.withType(com.github.spotbugs.snom.SpotBugsTask) {
|
||||
reports {
|
||||
html {
|
||||
enabled = true
|
||||
destination = file("$buildDir/reports/spotbugs/main/spotbugs.html")
|
||||
stylesheet = 'fancy-hist.xsl'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+2
-1
@@ -1,5 +1,6 @@
|
||||
dependencies {
|
||||
compileOnly group: "org.spigotmc", name: "spigot-api", version: "1.8.8-R0.1-SNAPSHOT"
|
||||
compile project(":nuvotifier-common")
|
||||
implementation project(":nuvotifier-api")
|
||||
implementation project(":nuvotifier-common")
|
||||
}
|
||||
|
||||
@@ -18,8 +18,6 @@
|
||||
|
||||
package com.vexsoftware.votifier;
|
||||
|
||||
import com.google.common.io.ByteStreams;
|
||||
import com.google.common.io.Files;
|
||||
import com.vexsoftware.votifier.cmd.NVReloadCmd;
|
||||
import com.vexsoftware.votifier.cmd.TestVoteCmd;
|
||||
import com.vexsoftware.votifier.forwarding.BukkitPluginMessagingForwardingSink;
|
||||
@@ -35,25 +33,24 @@ import com.vexsoftware.votifier.platform.JavaUtilLogger;
|
||||
import com.vexsoftware.votifier.platform.LoggingAdapter;
|
||||
import com.vexsoftware.votifier.platform.VotifierPlugin;
|
||||
import com.vexsoftware.votifier.platform.scheduler.VotifierScheduler;
|
||||
import com.vexsoftware.votifier.util.IOUtil;
|
||||
import com.vexsoftware.votifier.util.KeyCreator;
|
||||
import com.vexsoftware.votifier.util.TokenUtil;
|
||||
import io.netty.channel.Channel;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.command.ConsoleCommandSender;
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.StandardCopyOption;
|
||||
import java.security.Key;
|
||||
import java.security.KeyPair;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.logging.Level;
|
||||
|
||||
/**
|
||||
@@ -64,16 +61,6 @@ import java.util.logging.Level;
|
||||
*/
|
||||
public class NuVotifierBukkit extends JavaPlugin implements VoteHandler, VotifierPlugin, ForwardedVoteListener {
|
||||
|
||||
/**
|
||||
* The Votifier instance.
|
||||
*/
|
||||
private static NuVotifierBukkit instance;
|
||||
|
||||
/**
|
||||
* The current Votifier version.
|
||||
*/
|
||||
private String version;
|
||||
|
||||
/**
|
||||
* The server bootstrap.
|
||||
*/
|
||||
@@ -102,7 +89,9 @@ public class NuVotifierBukkit extends JavaPlugin implements VoteHandler, Votifie
|
||||
scheduler = new BukkitScheduler(this);
|
||||
pluginLogger = new JavaUtilLogger(getLogger());
|
||||
if (!getDataFolder().exists()) {
|
||||
getDataFolder().mkdir();
|
||||
if (!getDataFolder().mkdir()) {
|
||||
throw new RuntimeException("Unable to create the plugin data folder " + getDataFolder());
|
||||
}
|
||||
}
|
||||
|
||||
// Handle configuration.
|
||||
@@ -127,13 +116,15 @@ public class NuVotifierBukkit extends JavaPlugin implements VoteHandler, Votifie
|
||||
getLogger().info("Configuring Votifier for the first time...");
|
||||
|
||||
// Initialize the configuration file.
|
||||
config.createNewFile();
|
||||
if (!config.createNewFile()) {
|
||||
throw new IOException("Unable to create the config file at " + config);
|
||||
}
|
||||
|
||||
// Load and manually replace variables in the configuration.
|
||||
String cfgStr = new String(ByteStreams.toByteArray(getResource("bukkitConfig.yml")), StandardCharsets.UTF_8);
|
||||
String cfgStr = new String(IOUtil.readAllBytes(getResource("bukkitConfig.yml")), StandardCharsets.UTF_8);
|
||||
String token = TokenUtil.newToken();
|
||||
cfgStr = cfgStr.replace("%default_token%", token).replace("%ip%", hostAddr);
|
||||
Files.asCharSink(config, StandardCharsets.UTF_8).write(cfgStr);
|
||||
Files.copy(new ByteArrayInputStream(cfgStr.getBytes(StandardCharsets.UTF_8)), config.toPath(), StandardCopyOption.REPLACE_EXISTING);
|
||||
|
||||
/*
|
||||
* Remind hosted server admins to be sure they have the right
|
||||
@@ -167,7 +158,9 @@ public class NuVotifierBukkit extends JavaPlugin implements VoteHandler, Votifie
|
||||
*/
|
||||
try {
|
||||
if (!rsaDirectory.exists()) {
|
||||
rsaDirectory.mkdir();
|
||||
if (!rsaDirectory.mkdir()) {
|
||||
throw new RuntimeException("Unable to create the RSA key folder " + rsaDirectory);
|
||||
}
|
||||
keyPair = RSAKeygen.generate(2048);
|
||||
RSAIO.save(rsaDirectory, keyPair);
|
||||
} else {
|
||||
@@ -276,11 +269,6 @@ public class NuVotifierBukkit extends JavaPlugin implements VoteHandler, Votifie
|
||||
|
||||
@Override
|
||||
public void onEnable() {
|
||||
NuVotifierBukkit.instance = this;
|
||||
|
||||
// Set the plugin version.
|
||||
version = getDescription().getVersion();
|
||||
|
||||
getCommand("nvreload").setExecutor(new NVReloadCmd(this));
|
||||
getCommand("testvote").setExecutor(new TestVoteCmd(this));
|
||||
|
||||
@@ -321,15 +309,6 @@ public class NuVotifierBukkit extends JavaPlugin implements VoteHandler, Votifie
|
||||
getLogger().log(Level.SEVERE, "Votifier did not initialize properly!");
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the instance.
|
||||
*
|
||||
* @return The instance
|
||||
*/
|
||||
public static NuVotifierBukkit getInstance() {
|
||||
return instance;
|
||||
}
|
||||
|
||||
@Override
|
||||
public LoggingAdapter getPluginLogger() {
|
||||
return pluginLogger;
|
||||
@@ -359,7 +338,7 @@ public class NuVotifierBukkit extends JavaPlugin implements VoteHandler, Votifie
|
||||
if (debug) {
|
||||
getLogger().info("Got a " + protocolVersion.humanReadable + " vote record from " + remoteAddress + " -> " + vote);
|
||||
}
|
||||
Bukkit.getScheduler().runTask(this, () -> Bukkit.getPluginManager().callEvent(new VotifierEvent(vote)));
|
||||
Bukkit.getScheduler().runTask(this, () -> fireVotifierEvent(vote));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -381,6 +360,15 @@ public class NuVotifierBukkit extends JavaPlugin implements VoteHandler, Votifie
|
||||
if (debug) {
|
||||
getLogger().info("Got a forwarded vote -> " + v);
|
||||
}
|
||||
Bukkit.getScheduler().runTask(this, () -> Bukkit.getPluginManager().callEvent(new VotifierEvent(v)));
|
||||
Bukkit.getScheduler().runTask(this, () -> fireVotifierEvent(v));
|
||||
}
|
||||
|
||||
private void fireVotifierEvent(Vote vote) {
|
||||
if (VotifierEvent.getHandlerList().getRegisteredListeners().length == 0) {
|
||||
getLogger().log(Level.SEVERE, "A vote was received, but you don't have any listeners available to listen for it.");
|
||||
getLogger().log(Level.SEVERE, "See https://github.com/NuVotifier/NuVotifier/wiki/Setup-Guide#vote-listeners for");
|
||||
getLogger().log(Level.SEVERE, "a list of listeners you can configure.");
|
||||
}
|
||||
Bukkit.getPluginManager().callEvent(new VotifierEvent(vote));
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
dependencies {
|
||||
compileOnly group: "net.md-5", name: "bungeecord-api", version: "1.8-SNAPSHOT"
|
||||
compile project(":nuvotifier-common")
|
||||
implementation project(":nuvotifier-api")
|
||||
implementation project(":nuvotifier-common")
|
||||
}
|
||||
@@ -1,14 +1,15 @@
|
||||
package com.vexsoftware.votifier.bungee;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.vexsoftware.votifier.platform.BackendServer;
|
||||
import net.md_5.bungee.api.config.ServerInfo;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
public class BungeeBackendServer implements BackendServer {
|
||||
private final ServerInfo info;
|
||||
|
||||
public BungeeBackendServer(ServerInfo info) {
|
||||
this.info = Preconditions.checkNotNull(info, "info");
|
||||
this.info = Objects.requireNonNull(info, "info");
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
package com.vexsoftware.votifier.bungee;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.io.ByteStreams;
|
||||
import com.google.common.io.Files;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.vexsoftware.votifier.VoteHandler;
|
||||
import com.vexsoftware.votifier.bungee.cmd.NVReloadCmd;
|
||||
import com.vexsoftware.votifier.bungee.cmd.TestVoteCmd;
|
||||
@@ -23,28 +21,26 @@ import com.vexsoftware.votifier.model.Vote;
|
||||
import com.vexsoftware.votifier.net.VotifierSession;
|
||||
import com.vexsoftware.votifier.net.protocol.v1crypto.RSAIO;
|
||||
import com.vexsoftware.votifier.net.protocol.v1crypto.RSAKeygen;
|
||||
import com.vexsoftware.votifier.util.IOUtil;
|
||||
import com.vexsoftware.votifier.util.KeyCreator;
|
||||
import com.vexsoftware.votifier.util.TokenUtil;
|
||||
import io.netty.channel.Channel;
|
||||
import net.md_5.bungee.api.ChatColor;
|
||||
import net.md_5.bungee.api.CommandSender;
|
||||
import net.md_5.bungee.api.ProxyServer;
|
||||
import net.md_5.bungee.api.config.ServerInfo;
|
||||
import net.md_5.bungee.api.connection.ProxiedPlayer;
|
||||
import net.md_5.bungee.api.plugin.Command;
|
||||
import net.md_5.bungee.api.plugin.Plugin;
|
||||
import net.md_5.bungee.api.plugin.PluginManager;
|
||||
import net.md_5.bungee.config.Configuration;
|
||||
import net.md_5.bungee.config.ConfigurationProvider;
|
||||
import net.md_5.bungee.config.YamlConfiguration;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.Proxy;
|
||||
import java.net.UnknownHostException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.StandardCopyOption;
|
||||
import java.security.Key;
|
||||
import java.security.KeyPair;
|
||||
import java.util.*;
|
||||
@@ -86,7 +82,9 @@ public class NuVotifier extends Plugin implements VoteHandler, ProxyVotifierPlug
|
||||
|
||||
private void loadAndBind() {
|
||||
if (!getDataFolder().exists()) {
|
||||
getDataFolder().mkdir();
|
||||
if (!getDataFolder().mkdir()) {
|
||||
throw new RuntimeException("Unable to create the plugin data folder " + getDataFolder());
|
||||
}
|
||||
}
|
||||
|
||||
// Handle configuration.
|
||||
@@ -100,12 +98,14 @@ public class NuVotifier extends Plugin implements VoteHandler, ProxyVotifierPlug
|
||||
getLogger().info("Configuring Votifier for the first time...");
|
||||
|
||||
// Initialize the configuration file.
|
||||
config.createNewFile();
|
||||
if (!config.createNewFile()) {
|
||||
throw new IOException("Unable to create the config file at " + config);
|
||||
}
|
||||
|
||||
String cfgStr = new String(ByteStreams.toByteArray(getResourceAsStream("bungeeConfig.yml")), StandardCharsets.UTF_8);
|
||||
String cfgStr = new String(IOUtil.readAllBytes(getResourceAsStream("bungeeConfig.yml")), StandardCharsets.UTF_8);
|
||||
String token = TokenUtil.newToken();
|
||||
cfgStr = cfgStr.replace("%default_token%", token);
|
||||
Files.asCharSink(config, StandardCharsets.UTF_8).write(cfgStr);
|
||||
Files.copy(new ByteArrayInputStream(cfgStr.getBytes(StandardCharsets.UTF_8)), config.toPath(), StandardCopyOption.REPLACE_EXISTING);
|
||||
|
||||
/*
|
||||
* Remind hosted server admins to be sure they have the right
|
||||
@@ -143,7 +143,9 @@ public class NuVotifier extends Plugin implements VoteHandler, ProxyVotifierPlug
|
||||
*/
|
||||
try {
|
||||
if (!rsaDirectory.exists()) {
|
||||
rsaDirectory.mkdir();
|
||||
if (!rsaDirectory.mkdir()) {
|
||||
throw new RuntimeException("Unable to create the RSA key folder " + rsaDirectory);
|
||||
}
|
||||
keyPair = RSAKeygen.generate(2048);
|
||||
RSAIO.save(rsaDirectory, keyPair);
|
||||
} else {
|
||||
@@ -163,7 +165,7 @@ public class NuVotifier extends Plugin implements VoteHandler, ProxyVotifierPlug
|
||||
}
|
||||
} else {
|
||||
String token = TokenUtil.newToken();
|
||||
configuration.set("tokens", ImmutableMap.of("default", token));
|
||||
configuration.set("tokens", Collections.singletonMap("default", token));
|
||||
tokens.put("default", KeyCreator.createKeyFrom(token));
|
||||
try {
|
||||
ConfigurationProvider.getProvider(YamlConfiguration.class).save(configuration, config);
|
||||
@@ -222,13 +224,13 @@ public class NuVotifier extends Plugin implements VoteHandler, ProxyVotifierPlug
|
||||
getLogger().info("Vote cache none selected for caching: votes that cannot be immediately delivered will be lost.");
|
||||
} else if ("memory".equals(cacheMethod)) {
|
||||
voteCache = new MemoryVoteCache(
|
||||
ProxyServer.getInstance().getServers().size(), this,
|
||||
this,
|
||||
fwdCfg.getInt("pluginMessaging.memory.cacheTime", -1));
|
||||
getLogger().info("Using in-memory cache for votes that are not able to be delivered.");
|
||||
} else if ("file".equals(cacheMethod)) {
|
||||
try {
|
||||
voteCache = new FileVoteCache(
|
||||
ProxyServer.getInstance().getServers().size(), this,
|
||||
this,
|
||||
new File(getDataFolder(), fwdCfg.getString("pluginMessaging.file.name")),
|
||||
fwdCfg.getInt("pluginMessaging.file.cacheTime", -1));
|
||||
} catch (IOException e) {
|
||||
@@ -289,7 +291,7 @@ public class NuVotifier extends Plugin implements VoteHandler, ProxyVotifierPlug
|
||||
}
|
||||
}
|
||||
|
||||
forwardingMethod = new ProxyForwardingVoteSource(this, bootstrap::client, serverList, null);
|
||||
forwardingMethod = bootstrap.createForwardingSource(serverList, null);
|
||||
getLogger().info("Forwarding votes from this NuVotifier instance to another NuVotifier server.");
|
||||
} else {
|
||||
getLogger().severe("No vote forwarding method '" + fwdMethod + "' known. Defaulting to noop implementation.");
|
||||
@@ -304,6 +306,7 @@ public class NuVotifier extends Plugin implements VoteHandler, ProxyVotifierPlug
|
||||
PluginManager pm = ProxyServer.getInstance().getPluginManager();
|
||||
pm.registerCommand(this, new NVReloadCmd(this));
|
||||
pm.registerCommand(this, new TestVoteCmd(this));
|
||||
pm.registerListener(this, new ReloadListener(this));
|
||||
|
||||
loadAndBind();
|
||||
}
|
||||
|
||||
+3
@@ -33,6 +33,9 @@ public final class OnlineForwardPluginMessagingForwardingSource extends Abstract
|
||||
if (p != null && p.getServer() != null &&
|
||||
serverFilter.isAllowed(p.getServer().getInfo().getName())) {
|
||||
if (forwardSpecific(new BungeeBackendServer(p.getServer().getInfo()), v)) {
|
||||
if (plugin.isDebug()) {
|
||||
plugin.getPluginLogger().info("Successfully forwarded vote " + v + " to server " + p.getServer().getInfo().getName());
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
package com.vexsoftware.votifier.bungee;
|
||||
|
||||
import net.md_5.bungee.api.event.ProxyReloadEvent;
|
||||
import net.md_5.bungee.api.plugin.Listener;
|
||||
import net.md_5.bungee.event.EventHandler;
|
||||
|
||||
public class ReloadListener implements Listener {
|
||||
private final NuVotifier nuVotifier;
|
||||
|
||||
public ReloadListener(NuVotifier nuVotifier) {
|
||||
this.nuVotifier = nuVotifier;
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onProxyReload(ProxyReloadEvent event) {
|
||||
this.nuVotifier.reload();
|
||||
}
|
||||
}
|
||||
+6
-5
@@ -1,7 +1,8 @@
|
||||
dependencies {
|
||||
compile project(":nuvotifier-api")
|
||||
compile group: "io.netty", name: "netty-handler", version: "4.1.32.Final"
|
||||
compile 'com.google.code.gson:gson:2.8.0'
|
||||
compile 'com.google.guava:guava:24.1-jre'
|
||||
testCompile group: "org.json", name: "json", version: "20180130" // retain this for testing reasons
|
||||
implementation project(":nuvotifier-api")
|
||||
implementation group: "io.netty", name: "netty-handler", version: "4.1.49.Final"
|
||||
implementation group: "io.netty", name: "netty-transport-native-epoll", version: "4.1.49.Final", classifier: "linux-x86_64"
|
||||
implementation 'com.google.code.gson:gson:2.8.0'
|
||||
testImplementation group: "org.json", name: "json", version: "20180130" // retain this for testing reasons
|
||||
testImplementation 'com.google.guava:guava:28.1-jre'
|
||||
}
|
||||
@@ -1,29 +1,41 @@
|
||||
package com.vexsoftware.votifier.net;
|
||||
|
||||
import com.google.common.util.concurrent.ThreadFactoryBuilder;
|
||||
import com.vexsoftware.votifier.net.protocol.VoteInboundHandler;
|
||||
import com.vexsoftware.votifier.net.protocol.VotifierGreetingHandler;
|
||||
import com.vexsoftware.votifier.net.protocol.VotifierProtocolDifferentiator;
|
||||
import com.vexsoftware.votifier.platform.VotifierPlugin;
|
||||
import com.vexsoftware.votifier.support.forwarding.cache.VoteCache;
|
||||
import com.vexsoftware.votifier.support.forwarding.proxy.ProxyForwardingVoteSource;
|
||||
import io.netty.bootstrap.Bootstrap;
|
||||
import io.netty.bootstrap.ServerBootstrap;
|
||||
import io.netty.channel.Channel;
|
||||
import io.netty.channel.ChannelFutureListener;
|
||||
import io.netty.channel.ChannelInitializer;
|
||||
import io.netty.channel.EventLoopGroup;
|
||||
import io.netty.channel.epoll.Epoll;
|
||||
import io.netty.channel.epoll.EpollEventLoopGroup;
|
||||
import io.netty.channel.epoll.EpollServerSocketChannel;
|
||||
import io.netty.channel.epoll.EpollSocketChannel;
|
||||
import io.netty.channel.nio.NioEventLoopGroup;
|
||||
import io.netty.channel.socket.SocketChannel;
|
||||
import io.netty.channel.socket.nio.NioServerSocketChannel;
|
||||
import io.netty.channel.socket.nio.NioSocketChannel;
|
||||
import io.netty.util.concurrent.FastThreadLocalThread;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.SocketAddress;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.ThreadFactory;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public class VotifierServerBootstrap {
|
||||
private static final boolean USE_EPOLL = Epoll.isAvailable();
|
||||
|
||||
private final String host;
|
||||
private final int port;
|
||||
private final NioEventLoopGroup bossLoopGroup;
|
||||
private final NioEventLoopGroup eventLoopGroup;
|
||||
private final EventLoopGroup bossLoopGroup;
|
||||
private final EventLoopGroup eventLoopGroup;
|
||||
private final VotifierPlugin plugin;
|
||||
private final boolean v1Disable;
|
||||
|
||||
@@ -34,23 +46,41 @@ public class VotifierServerBootstrap {
|
||||
this.port = port;
|
||||
this.plugin = plugin;
|
||||
this.v1Disable = v1Disable;
|
||||
this.bossLoopGroup = new NioEventLoopGroup(1, new ThreadFactoryBuilder().setDaemon(true).setNameFormat("Votifier NIO boss").build());
|
||||
this.eventLoopGroup = new NioEventLoopGroup(1, new ThreadFactoryBuilder().setDaemon(true).setNameFormat("Votifier NIO worker").build());
|
||||
if (USE_EPOLL) {
|
||||
this.bossLoopGroup = new EpollEventLoopGroup(1, createThreadFactory("Votifier epoll boss"));
|
||||
this.eventLoopGroup = new EpollEventLoopGroup(3, createThreadFactory("Votifier epoll worker"));
|
||||
plugin.getPluginLogger().info("Using epoll transport to accept votes.");
|
||||
} else {
|
||||
this.bossLoopGroup = new NioEventLoopGroup(1, createThreadFactory("Votifier NIO boss"));
|
||||
this.eventLoopGroup = new NioEventLoopGroup(3, createThreadFactory("Votifier NIO worker"));
|
||||
plugin.getPluginLogger().info("Using NIO transport to accept votes.");
|
||||
}
|
||||
}
|
||||
|
||||
private static ThreadFactory createThreadFactory(String name) {
|
||||
return runnable -> {
|
||||
FastThreadLocalThread thread = new FastThreadLocalThread(runnable, name);
|
||||
thread.setDaemon(true);
|
||||
return thread;
|
||||
};
|
||||
}
|
||||
|
||||
public void start(Consumer<Throwable> error) {
|
||||
Objects.requireNonNull(error, "error");
|
||||
|
||||
VoteInboundHandler voteInboundHandler = new VoteInboundHandler(plugin);
|
||||
|
||||
new ServerBootstrap()
|
||||
.channel(NioServerSocketChannel.class)
|
||||
.channel(USE_EPOLL ? EpollServerSocketChannel.class : NioServerSocketChannel.class)
|
||||
.group(bossLoopGroup, eventLoopGroup)
|
||||
.childHandler(new ChannelInitializer<NioSocketChannel>() {
|
||||
.childHandler(new ChannelInitializer<SocketChannel>() {
|
||||
@Override
|
||||
protected void initChannel(NioSocketChannel channel) {
|
||||
protected void initChannel(SocketChannel channel) {
|
||||
channel.attr(VotifierSession.KEY).set(new VotifierSession());
|
||||
channel.attr(VotifierPlugin.KEY).set(plugin);
|
||||
channel.pipeline().addLast("greetingHandler", new VotifierGreetingHandler());
|
||||
channel.pipeline().addLast("greetingHandler", VotifierGreetingHandler.INSTANCE);
|
||||
channel.pipeline().addLast("protocolDifferentiator", new VotifierProtocolDifferentiator(false, !v1Disable));
|
||||
channel.pipeline().addLast("voteHandler", new VoteInboundHandler(plugin));
|
||||
channel.pipeline().addLast("voteHandler", voteInboundHandler);
|
||||
}
|
||||
})
|
||||
.bind(host, port)
|
||||
@@ -70,12 +100,17 @@ public class VotifierServerBootstrap {
|
||||
});
|
||||
}
|
||||
|
||||
public Bootstrap client() {
|
||||
private Bootstrap client() {
|
||||
return new Bootstrap()
|
||||
.channel(NioSocketChannel.class)
|
||||
.channel(USE_EPOLL ? EpollSocketChannel.class : NioSocketChannel.class)
|
||||
.group(eventLoopGroup);
|
||||
}
|
||||
|
||||
public ProxyForwardingVoteSource createForwardingSource(List<ProxyForwardingVoteSource.BackendServer> backendServers,
|
||||
VoteCache voteCache) {
|
||||
return new ProxyForwardingVoteSource(plugin, this::client, backendServers, voteCache);
|
||||
}
|
||||
|
||||
public void shutdown() {
|
||||
if (serverChannel != null) {
|
||||
try {
|
||||
|
||||
@@ -6,14 +6,22 @@ import com.vexsoftware.votifier.model.Vote;
|
||||
import com.vexsoftware.votifier.net.VotifierSession;
|
||||
import com.vexsoftware.votifier.util.GsonInst;
|
||||
import io.netty.channel.ChannelFutureListener;
|
||||
import io.netty.channel.ChannelHandler;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.channel.SimpleChannelInboundHandler;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
|
||||
@ChannelHandler.Sharable
|
||||
public class VoteInboundHandler extends SimpleChannelInboundHandler<Vote> {
|
||||
private final VoteHandler handler;
|
||||
private final AtomicLong lastError;
|
||||
private final AtomicLong errorsSent;
|
||||
|
||||
public VoteInboundHandler(VoteHandler handler) {
|
||||
this.handler = handler;
|
||||
this.lastError = new AtomicLong();
|
||||
this.errorsSent = new AtomicLong();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -36,7 +44,8 @@ public class VoteInboundHandler extends SimpleChannelInboundHandler<Vote> {
|
||||
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
|
||||
VotifierSession session = ctx.channel().attr(VotifierSession.KEY).get();
|
||||
|
||||
handler.onError(cause, session.hasCompletedVote(), ctx.channel().remoteAddress().toString());
|
||||
String remoteAddr = ctx.channel().remoteAddress().toString();
|
||||
boolean hasCompletedVote = session.hasCompletedVote();
|
||||
|
||||
if (session.getVersion() == VotifierSession.ProtocolVersion.TWO) {
|
||||
JsonObject object = new JsonObject();
|
||||
@@ -47,5 +56,22 @@ public class VoteInboundHandler extends SimpleChannelInboundHandler<Vote> {
|
||||
} else {
|
||||
ctx.close();
|
||||
}
|
||||
|
||||
if (!willThrottleErrorLogging()) {
|
||||
handler.onError(cause, hasCompletedVote, remoteAddr);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean willThrottleErrorLogging() {
|
||||
long lastErrorAt = this.lastError.get();
|
||||
long now = System.currentTimeMillis();
|
||||
|
||||
if (lastErrorAt + 2000 >= now) {
|
||||
return this.errorsSent.incrementAndGet() >= 5;
|
||||
} else {
|
||||
this.lastError.set(now);
|
||||
this.errorsSent.set(0);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
+6
@@ -3,6 +3,7 @@ package com.vexsoftware.votifier.net.protocol;
|
||||
import com.vexsoftware.votifier.net.VotifierSession;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.Unpooled;
|
||||
import io.netty.channel.ChannelHandler;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.channel.ChannelInboundHandlerAdapter;
|
||||
|
||||
@@ -11,7 +12,12 @@ import java.nio.charset.StandardCharsets;
|
||||
/**
|
||||
* Handles the Votifier greeting.
|
||||
*/
|
||||
@ChannelHandler.Sharable
|
||||
public class VotifierGreetingHandler extends ChannelInboundHandlerAdapter {
|
||||
public static final VotifierGreetingHandler INSTANCE = new VotifierGreetingHandler();
|
||||
|
||||
private VotifierGreetingHandler() {}
|
||||
|
||||
@Override
|
||||
public void channelActive(ChannelHandlerContext ctx) {
|
||||
VotifierSession session = ctx.channel().attr(VotifierSession.KEY).get();
|
||||
|
||||
+24
-9
@@ -3,7 +3,9 @@ package com.vexsoftware.votifier.net.protocol;
|
||||
import com.vexsoftware.votifier.platform.VotifierPlugin;
|
||||
import com.vexsoftware.votifier.model.Vote;
|
||||
import com.vexsoftware.votifier.net.protocol.v1crypto.RSA;
|
||||
import com.vexsoftware.votifier.util.QuietException;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.ByteBufUtil;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.handler.codec.ByteToMessageDecoder;
|
||||
import io.netty.handler.codec.CorruptedFrameException;
|
||||
@@ -16,33 +18,46 @@ import java.util.List;
|
||||
*/
|
||||
public class VotifierProtocol1Decoder extends ByteToMessageDecoder {
|
||||
@Override
|
||||
protected void decode(ChannelHandlerContext ctx, ByteBuf buf, List<Object> list) {
|
||||
if (buf.readableBytes() < 256) {
|
||||
protected void decode(ChannelHandlerContext ctx, ByteBuf buf, List<Object> list) throws Exception {
|
||||
if (!ctx.channel().isActive()) {
|
||||
buf.skipBytes(buf.readableBytes());
|
||||
return;
|
||||
}
|
||||
|
||||
byte[] block = new byte[buf.readableBytes()];
|
||||
buf.getBytes(0, block);
|
||||
// "Drain" the whole buffer
|
||||
buf.readerIndex(buf.readableBytes());
|
||||
if (buf.readableBytes() < 256) {
|
||||
// The client might have not sent all the data yet, so don't eject the connection.
|
||||
return;
|
||||
}
|
||||
|
||||
if (buf.readableBytes() > 256) {
|
||||
// They sent too much data.
|
||||
throw new QuietException("Could not decrypt data from " + ctx.channel().remoteAddress() + " as it is too long. Attack?");
|
||||
}
|
||||
|
||||
byte[] block = ByteBufUtil.getBytes(buf);
|
||||
buf.skipBytes(buf.readableBytes());
|
||||
|
||||
VotifierPlugin plugin = ctx.channel().attr(VotifierPlugin.KEY).get();
|
||||
|
||||
try {
|
||||
block = RSA.decrypt(block, plugin.getProtocolV1Key().getPrivate());
|
||||
} catch (Exception e) {
|
||||
throw new CorruptedFrameException("Could not decrypt data (is your key correct?)", e);
|
||||
if (plugin.isDebug()) {
|
||||
throw new CorruptedFrameException("Could not decrypt data from " + ctx.channel().remoteAddress() + ". Make sure the public key on the list is correct.", e);
|
||||
} else {
|
||||
throw new QuietException("Could not decrypt data from " + ctx.channel().remoteAddress() + ". Make sure the public key on the list is correct.");
|
||||
}
|
||||
}
|
||||
|
||||
// Parse the string we received.
|
||||
String all = new String(block, StandardCharsets.US_ASCII);
|
||||
String[] split = all.split("\n");
|
||||
if (split.length < 5) {
|
||||
throw new CorruptedFrameException("Not enough fields specified in vote.");
|
||||
throw new QuietException("Not enough fields specified in vote. This is not a NuVotifier issue. Got " + split.length + " fields, but needed 5.");
|
||||
}
|
||||
|
||||
if (!split[0].equals("VOTE")) {
|
||||
throw new CorruptedFrameException("VOTE opcode not found");
|
||||
throw new QuietException("The VOTE opcode was not present. This is not a NuVotifier issue, but a bug with the server list.");
|
||||
}
|
||||
|
||||
// Create the vote.
|
||||
|
||||
+6
-8
@@ -1,10 +1,10 @@
|
||||
package com.vexsoftware.votifier.net.protocol;
|
||||
|
||||
import com.vexsoftware.votifier.net.VotifierSession;
|
||||
import com.vexsoftware.votifier.util.QuietException;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.handler.codec.ByteToMessageDecoder;
|
||||
import io.netty.handler.codec.CorruptedFrameException;
|
||||
import io.netty.handler.codec.LengthFieldBasedFrameDecoder;
|
||||
import io.netty.handler.codec.string.StringDecoder;
|
||||
import io.netty.handler.codec.string.StringEncoder;
|
||||
@@ -16,6 +16,8 @@ import java.util.List;
|
||||
* Attempts to determine if original protocol or protocol v2 is being used.
|
||||
*/
|
||||
public class VotifierProtocolDifferentiator extends ByteToMessageDecoder {
|
||||
private static final QuietException V2_ONLY = new QuietException("This server only accepts well-formed Votifier v2 packets.");
|
||||
|
||||
private static final short PROTOCOL_2_MAGIC = 0x733A;
|
||||
private final boolean testMode;
|
||||
private final boolean allowv1;
|
||||
@@ -26,7 +28,7 @@ public class VotifierProtocolDifferentiator extends ByteToMessageDecoder {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void decode(ChannelHandlerContext ctx, ByteBuf buf, List<Object> list) {
|
||||
protected void decode(ChannelHandlerContext ctx, ByteBuf buf, List<Object> list) throws Exception {
|
||||
// Determine the number of bytes that are available.
|
||||
int readable = buf.readableBytes();
|
||||
|
||||
@@ -35,11 +37,7 @@ public class VotifierProtocolDifferentiator extends ByteToMessageDecoder {
|
||||
return;
|
||||
}
|
||||
|
||||
short readMagic = buf.readShort();
|
||||
|
||||
// Reset reader index again
|
||||
buf.readerIndex(0);
|
||||
|
||||
short readMagic = buf.getShort(0);
|
||||
VotifierSession session = ctx.channel().attr(VotifierSession.KEY).get();
|
||||
|
||||
if (readMagic == PROTOCOL_2_MAGIC) {
|
||||
@@ -55,7 +53,7 @@ public class VotifierProtocolDifferentiator extends ByteToMessageDecoder {
|
||||
}
|
||||
} else {
|
||||
if (!allowv1) {
|
||||
throw new CorruptedFrameException("This server only accepts well-formed Votifier v2 packets.");
|
||||
throw V2_ONLY;
|
||||
}
|
||||
// Probably Protocol v1 Vote Message
|
||||
session.setVersion(VotifierSession.ProtocolVersion.ONE);
|
||||
|
||||
@@ -63,7 +63,7 @@ public class RSAIO {
|
||||
public static byte[] readB64File(File directory, String name) throws IOException {
|
||||
File f = new File(directory, name);
|
||||
byte[] contents = Files.readAllBytes(f.toPath());
|
||||
String strContents = new String(contents);
|
||||
String strContents = new String(contents, StandardCharsets.US_ASCII);
|
||||
strContents = strContents.trim();
|
||||
try {
|
||||
return Base64.getDecoder().decode(strContents);
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
package com.vexsoftware.votifier.platform;
|
||||
|
||||
import com.vexsoftware.votifier.platform.LoggingAdapter;
|
||||
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
|
||||
+2
-3
@@ -1,7 +1,6 @@
|
||||
package com.vexsoftware.votifier.platform.scheduler;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
@@ -10,7 +9,7 @@ public class ScheduledExecutorServiceVotifierScheduler implements VotifierSchedu
|
||||
private final ScheduledExecutorService service;
|
||||
|
||||
public ScheduledExecutorServiceVotifierScheduler(ScheduledExecutorService service) {
|
||||
this.service = Preconditions.checkNotNull(service, "service");
|
||||
this.service = Objects.requireNonNull(service, "service");
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+5
-1
@@ -39,7 +39,11 @@ public abstract class AbstractPluginMessagingForwardingSource implements Forward
|
||||
byte[] rawData = v.serialize().toString().getBytes(StandardCharsets.UTF_8);
|
||||
for (BackendServer server : plugin.getAllBackendServers()) {
|
||||
if (!serverFilter.isAllowed(server.getName())) continue;
|
||||
if (!forwardSpecific(server, rawData)) attemptToAddToCache(v, server.getName());
|
||||
if (!forwardSpecific(server, rawData)) {
|
||||
attemptToAddToCache(v, server.getName());
|
||||
} else if (plugin.isDebug()) {
|
||||
plugin.getPluginLogger().info("Successfully forwarded vote " + v + " to server " + server.getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ public class ServerFilter {
|
||||
}
|
||||
|
||||
public ServerFilter() {
|
||||
this(Collections.EMPTY_SET, true);
|
||||
this(Collections.emptySet(), true);
|
||||
}
|
||||
|
||||
private final Collection<String> names;
|
||||
|
||||
+24
-22
@@ -1,10 +1,8 @@
|
||||
package com.vexsoftware.votifier.support.forwarding.cache;
|
||||
|
||||
import com.google.common.io.Files;
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.vexsoftware.votifier.model.Vote;
|
||||
import com.vexsoftware.votifier.platform.LoggingAdapter;
|
||||
import com.vexsoftware.votifier.platform.VotifierPlugin;
|
||||
import com.vexsoftware.votifier.platform.scheduler.ScheduledVotifierTask;
|
||||
@@ -12,6 +10,8 @@ import com.vexsoftware.votifier.util.GsonInst;
|
||||
|
||||
import java.io.*;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.NoSuchFileException;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
@@ -21,8 +21,8 @@ public class FileVoteCache extends MemoryVoteCache {
|
||||
private final File cacheFile;
|
||||
private final ScheduledVotifierTask saveTask;
|
||||
|
||||
public FileVoteCache(int initialMemorySize, final VotifierPlugin plugin, File cacheFile, long voteTTL) throws IOException {
|
||||
super(initialMemorySize, plugin, voteTTL);
|
||||
public FileVoteCache(final VotifierPlugin plugin, File cacheFile, long voteTTL) throws IOException {
|
||||
super(plugin, voteTTL);
|
||||
this.cacheFile = cacheFile;
|
||||
this.l = plugin.getPluginLogger();
|
||||
|
||||
@@ -48,12 +48,13 @@ public class FileVoteCache extends MemoryVoteCache {
|
||||
private void load() throws IOException {
|
||||
// Load the cache from disk
|
||||
JsonObject object;
|
||||
try (BufferedReader reader = Files.newReader(cacheFile, StandardCharsets.UTF_8)) {
|
||||
try (BufferedReader reader = Files.newBufferedReader(cacheFile.toPath(), StandardCharsets.UTF_8)) {
|
||||
object = GsonInst.gson.fromJson(reader, JsonObject.class);
|
||||
if (object == null)
|
||||
if (object == null) {
|
||||
// When the input is not malformed but instead empty, this returns null. Simply assume it is empty.
|
||||
object = new JsonObject();
|
||||
} catch (FileNotFoundException e) {
|
||||
}
|
||||
} catch (NoSuchFileException e) {
|
||||
object = new JsonObject();
|
||||
}
|
||||
|
||||
@@ -76,11 +77,11 @@ public class FileVoteCache extends MemoryVoteCache {
|
||||
JsonObject servers = object.getAsJsonObject("servers");
|
||||
|
||||
for (String player : keySet(players)) {
|
||||
playerVoteCache.putAll(player, readVotes(players.getAsJsonArray(player)));
|
||||
playerVoteCache.put(player, readVotes(players.getAsJsonArray(player)));
|
||||
}
|
||||
|
||||
for (String server : keySet(servers)) {
|
||||
voteCache.putAll(server, readVotes(servers.getAsJsonArray(server)));
|
||||
voteCache.put(server, readVotes(servers.getAsJsonArray(server)));
|
||||
}
|
||||
|
||||
if (resave) {
|
||||
@@ -101,11 +102,11 @@ public class FileVoteCache extends MemoryVoteCache {
|
||||
}
|
||||
}
|
||||
|
||||
private Collection<Vote> readVotes(JsonArray voteArray) {
|
||||
List<Vote> votes = new ArrayList<>(voteArray.size());
|
||||
private Collection<VoteWithRecordedTimestamp> readVotes(JsonArray voteArray) {
|
||||
Collection<VoteWithRecordedTimestamp> votes = new HashSet<>(voteArray.size());
|
||||
for (int i = 0; i < voteArray.size(); i++) {
|
||||
JsonObject voteObject = voteArray.get(i).getAsJsonObject();
|
||||
Vote v = new Vote(voteObject);
|
||||
VoteWithRecordedTimestamp v = new VoteWithRecordedTimestamp(voteObject);
|
||||
if (hasTimedOut(v))
|
||||
l.warn("Purging out of date vote.", v);
|
||||
else
|
||||
@@ -115,31 +116,32 @@ public class FileVoteCache extends MemoryVoteCache {
|
||||
}
|
||||
|
||||
public void save() throws IOException {
|
||||
cacheLock.lock();
|
||||
JsonObject votesObject = new JsonObject();
|
||||
votesObject.addProperty("version", 2);
|
||||
|
||||
cacheLock.lock();
|
||||
try {
|
||||
votesObject.add("players", serializeMap(playerVoteCache.asMap()));
|
||||
votesObject.add("servers", serializeMap(voteCache.asMap()));
|
||||
votesObject.addProperty("version", 2);
|
||||
votesObject.add("players", serializeMap(playerVoteCache));
|
||||
votesObject.add("servers", serializeMap(voteCache));
|
||||
} finally {
|
||||
cacheLock.unlock();
|
||||
}
|
||||
|
||||
try (BufferedWriter writer = Files.newWriter(cacheFile, StandardCharsets.UTF_8)) {
|
||||
try (BufferedWriter writer = Files.newBufferedWriter(cacheFile.toPath(), StandardCharsets.UTF_8)) {
|
||||
GsonInst.gson.toJson(votesObject, writer);
|
||||
}
|
||||
}
|
||||
|
||||
public JsonObject serializeMap(Map<String, Collection<Vote>> map) {
|
||||
public JsonObject serializeMap(Map<String, Collection<VoteWithRecordedTimestamp>> map) {
|
||||
JsonObject o = new JsonObject();
|
||||
|
||||
Iterator<Map.Entry<String, Collection<Vote>>> entryItr = map.entrySet().iterator();
|
||||
Iterator<Map.Entry<String, Collection<VoteWithRecordedTimestamp>>> entryItr = map.entrySet().iterator();
|
||||
while (entryItr.hasNext()) {
|
||||
Map.Entry<String, Collection<Vote>> entry = entryItr.next();
|
||||
Map.Entry<String, Collection<VoteWithRecordedTimestamp>> entry = entryItr.next();
|
||||
JsonArray array = new JsonArray();
|
||||
Iterator<Vote> voteItr = entry.getValue().iterator();
|
||||
Iterator<VoteWithRecordedTimestamp> voteItr = entry.getValue().iterator();
|
||||
while (voteItr.hasNext()) {
|
||||
Vote vote = voteItr.next();
|
||||
VoteWithRecordedTimestamp vote = voteItr.next();
|
||||
|
||||
// if the vote is no longer valid, notify and remove
|
||||
if (hasTimedOut(vote)) {
|
||||
|
||||
Vendored
+78
-25
@@ -1,8 +1,6 @@
|
||||
package com.vexsoftware.votifier.support.forwarding.cache;
|
||||
|
||||
import com.google.common.collect.HashMultimap;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.Multimap;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.vexsoftware.votifier.model.Vote;
|
||||
import com.vexsoftware.votifier.platform.LoggingAdapter;
|
||||
import com.vexsoftware.votifier.platform.VotifierPlugin;
|
||||
@@ -20,16 +18,16 @@ public class MemoryVoteCache implements VoteCache {
|
||||
private final LoggingAdapter l;
|
||||
private final long voteTTL;
|
||||
|
||||
protected final Multimap<String, Vote> voteCache;
|
||||
protected final Multimap<String, Vote> playerVoteCache;
|
||||
protected final Map<String, Collection<VoteWithRecordedTimestamp>> voteCache;
|
||||
protected final Map<String, Collection<VoteWithRecordedTimestamp>> playerVoteCache;
|
||||
|
||||
protected final ReentrantLock cacheLock = new ReentrantLock();
|
||||
|
||||
private final ScheduledVotifierTask sweepTask;
|
||||
|
||||
public MemoryVoteCache(int initialSize, VotifierPlugin p, long voteTTL) {
|
||||
voteCache = HashMultimap.create(initialSize, 10); // 10 is a complete guess. I have no idea .-.
|
||||
playerVoteCache = HashMultimap.create();
|
||||
public MemoryVoteCache(VotifierPlugin p, long voteTTL) {
|
||||
voteCache = new HashMap<>();
|
||||
playerVoteCache = new HashMap<>();
|
||||
|
||||
this.voteTTL = voteTTL;
|
||||
|
||||
@@ -41,7 +39,7 @@ public class MemoryVoteCache implements VoteCache {
|
||||
public Collection<String> getCachedServers() {
|
||||
cacheLock.lock();
|
||||
try {
|
||||
return ImmutableList.copyOf(voteCache.keySet());
|
||||
return Collections.unmodifiableCollection(new ArrayList<>(voteCache.keySet()));
|
||||
} finally {
|
||||
cacheLock.unlock();
|
||||
}
|
||||
@@ -52,7 +50,7 @@ public class MemoryVoteCache implements VoteCache {
|
||||
if (server == null) throw new NullPointerException();
|
||||
cacheLock.lock();
|
||||
try {
|
||||
voteCache.put(server, v);
|
||||
voteCache.computeIfAbsent(server, k -> new HashSet<>()).add(new VoteWithRecordedTimestamp(v));
|
||||
} finally {
|
||||
cacheLock.unlock();
|
||||
}
|
||||
@@ -63,7 +61,7 @@ public class MemoryVoteCache implements VoteCache {
|
||||
if (player == null) throw new NullPointerException();
|
||||
cacheLock.lock();
|
||||
try {
|
||||
playerVoteCache.put(player, v);
|
||||
playerVoteCache.computeIfAbsent(player, k -> new HashSet<>()).add(new VoteWithRecordedTimestamp(v));
|
||||
} finally {
|
||||
cacheLock.unlock();
|
||||
}
|
||||
@@ -74,7 +72,12 @@ public class MemoryVoteCache implements VoteCache {
|
||||
if (player == null) throw new NullPointerException();
|
||||
cacheLock.lock();
|
||||
try {
|
||||
return new HashSet<>(playerVoteCache.removeAll(player));
|
||||
Collection<VoteWithRecordedTimestamp> playerVotes = playerVoteCache.remove(player);
|
||||
if (playerVotes != null) {
|
||||
return new HashSet<>(playerVotes);
|
||||
} else {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
} finally {
|
||||
cacheLock.unlock();
|
||||
}
|
||||
@@ -85,7 +88,12 @@ public class MemoryVoteCache implements VoteCache {
|
||||
if (server == null) throw new NullPointerException();
|
||||
cacheLock.lock();
|
||||
try {
|
||||
return new HashSet<>(voteCache.removeAll(server));
|
||||
Collection<VoteWithRecordedTimestamp> serverVotes = voteCache.remove(server);
|
||||
if (serverVotes != null) {
|
||||
return new HashSet<>(serverVotes);
|
||||
} else {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
} finally {
|
||||
cacheLock.unlock();
|
||||
}
|
||||
@@ -101,22 +109,67 @@ public class MemoryVoteCache implements VoteCache {
|
||||
}
|
||||
}
|
||||
|
||||
private void sweep(Multimap<?, Vote> m) {
|
||||
Iterator<Vote> vi = m.values().iterator();
|
||||
while (vi.hasNext()) {
|
||||
Vote v = vi.next();
|
||||
if (hasTimedOut(v)) {
|
||||
l.warn("Purging out of date vote.", v);
|
||||
vi.remove();
|
||||
private void sweep(Map<String, Collection<VoteWithRecordedTimestamp>> m) {
|
||||
for (Map.Entry<String, Collection<VoteWithRecordedTimestamp>> entry : m.entrySet()) {
|
||||
Iterator<VoteWithRecordedTimestamp> vi = entry.getValue().iterator();
|
||||
while (vi.hasNext()) {
|
||||
VoteWithRecordedTimestamp v = vi.next();
|
||||
if (hasTimedOut(v)) {
|
||||
l.warn("Purging out of date vote.", v);
|
||||
vi.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected boolean hasTimedOut(Vote v) {
|
||||
protected boolean hasTimedOut(VoteWithRecordedTimestamp v) {
|
||||
if (voteTTL == -1) return false;
|
||||
// TODO: FIX FOR 3.0 RELEASE
|
||||
// scale voteTTL to milliseconds
|
||||
return false;
|
||||
//return v.getLocalTimestamp() + voteTTL * 24 * 60 * 60 * 1000 < System.currentTimeMillis();
|
||||
|
||||
long daysAsMillis = TimeUnit.DAYS.toMillis(voteTTL);
|
||||
return v.recorded + daysAsMillis < System.currentTimeMillis();
|
||||
}
|
||||
|
||||
static class VoteWithRecordedTimestamp extends Vote {
|
||||
private final long recorded;
|
||||
|
||||
VoteWithRecordedTimestamp(Vote vote) {
|
||||
super(vote);
|
||||
this.recorded = System.currentTimeMillis();
|
||||
}
|
||||
|
||||
VoteWithRecordedTimestamp(JsonObject object) {
|
||||
super(object);
|
||||
if (object.has("recorded")) {
|
||||
this.recorded = object.get("recorded").getAsLong();
|
||||
} else {
|
||||
// Assign the current time, in the hope that the stale votes will eventually get purged.
|
||||
this.recorded = System.currentTimeMillis();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public JsonObject serialize() {
|
||||
JsonObject object = super.serialize();
|
||||
object.addProperty("recorded", this.recorded);
|
||||
return object;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
if (!super.equals(o)) return false;
|
||||
|
||||
VoteWithRecordedTimestamp that = (VoteWithRecordedTimestamp) o;
|
||||
|
||||
return recorded == that.recorded;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = super.hashCode();
|
||||
result = 31 * result + (int) (recorded ^ (recorded >>> 32));
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -26,19 +26,25 @@ public class ArgsToVote {
|
||||
if (m.matches()) {
|
||||
String key = m.group(1).toLowerCase();
|
||||
String v = m.group(2);
|
||||
if (key.equals("servicename")) {
|
||||
serviceName = v;
|
||||
} else if (key.equals("username")) {
|
||||
if (v.length() > 16)
|
||||
throw new IllegalArgumentException("Illegal username - must be less than 16 characters long.");
|
||||
username = v;
|
||||
} else if (key.equals("address")) {
|
||||
address = v;
|
||||
} else if (key.equals("timestamp")) {
|
||||
timestamp = v;
|
||||
} else {
|
||||
if (additionalArgs != null)
|
||||
additionalArgs.put(key, v);
|
||||
switch (key) {
|
||||
case "servicename":
|
||||
serviceName = v;
|
||||
break;
|
||||
case "username":
|
||||
if (v.length() > 16)
|
||||
throw new IllegalArgumentException("Illegal username - must be less than 16 characters long.");
|
||||
username = v;
|
||||
break;
|
||||
case "address":
|
||||
address = v;
|
||||
break;
|
||||
case "timestamp":
|
||||
timestamp = v;
|
||||
break;
|
||||
default:
|
||||
if (additionalArgs != null)
|
||||
additionalArgs.put(key, v);
|
||||
break;
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
package com.vexsoftware.votifier.util;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
public class IOUtil {
|
||||
public static byte[] readAllBytes(InputStream from) throws IOException {
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream(8192);
|
||||
byte[] buf = new byte[8192];
|
||||
int read;
|
||||
while ((read = from.read(buf)) != -1) {
|
||||
out.write(buf, 0, read);
|
||||
}
|
||||
return out.toByteArray();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package com.vexsoftware.votifier.util;
|
||||
|
||||
public class QuietException extends Exception {
|
||||
public QuietException() {
|
||||
}
|
||||
|
||||
public QuietException(String s) {
|
||||
super(s);
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized Throwable fillInStackTrace() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -85,6 +85,11 @@ public class TestVotifierPlugin implements VotifierPlugin {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDebug() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public void specificKeysOnly() {
|
||||
keyMap.clear();
|
||||
keyMap.put("Test", KeyCreator.createKeyFrom("test"));
|
||||
|
||||
@@ -26,6 +26,6 @@ public class VoteUtil {
|
||||
builder.append(s).append('\n'); // naive join needed!
|
||||
}
|
||||
|
||||
return RSA.encrypt(builder.toString().getBytes(StandardCharsets.UTF_8), key);
|
||||
return RSA.encrypt(builder.toString().getBytes(StandardCharsets.US_ASCII), key);
|
||||
}
|
||||
}
|
||||
+4
-2
@@ -4,10 +4,12 @@ import com.vexsoftware.votifier.platform.VotifierPlugin;
|
||||
import com.vexsoftware.votifier.model.Vote;
|
||||
import com.vexsoftware.votifier.net.VotifierSession;
|
||||
import com.vexsoftware.votifier.net.protocol.v1crypto.RSA;
|
||||
import com.vexsoftware.votifier.util.QuietException;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.Unpooled;
|
||||
import io.netty.channel.embedded.EmbeddedChannel;
|
||||
import io.netty.handler.codec.CorruptedFrameException;
|
||||
import io.netty.handler.codec.DecoderException;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
@@ -50,7 +52,7 @@ public class VotifierProtocol1DecoderTest {
|
||||
byte[] encrypted = RSA.encrypt(bad.getBytes(StandardCharsets.UTF_8), TestVotifierPlugin.getI().getProtocolV1Key().getPublic());
|
||||
ByteBuf encryptedByteBuf = Unpooled.wrappedBuffer(encrypted);
|
||||
|
||||
assertThrows(CorruptedFrameException.class, () -> channel.writeInbound(encryptedByteBuf));
|
||||
assertThrows(DecoderException.class, () -> channel.writeInbound(encryptedByteBuf));
|
||||
channel.close();
|
||||
}
|
||||
|
||||
@@ -77,7 +79,7 @@ public class VotifierProtocol1DecoderTest {
|
||||
byte[] encrypted = VoteUtil.encodePOJOv1(new Vote("Test", "test", "test", "test"), badPublicKey);
|
||||
ByteBuf encryptedByteBuf = Unpooled.wrappedBuffer(encrypted);
|
||||
|
||||
assertThrows(CorruptedFrameException.class, ()->channel.writeInbound(encryptedByteBuf));
|
||||
assertThrows(DecoderException.class, ()->channel.writeInbound(encryptedByteBuf));
|
||||
channel.close();
|
||||
}
|
||||
}
|
||||
-1
@@ -19,7 +19,6 @@ import java.util.Base64;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
|
||||
public class VotifierProtocol2DecoderTest {
|
||||
private static final VotifierSession SESSION = new VotifierSession();
|
||||
|
||||
|
||||
+2
-1
@@ -2,6 +2,7 @@ package com.vexsoftware.votifier.net.protocol;
|
||||
|
||||
import com.vexsoftware.votifier.model.Vote;
|
||||
import com.vexsoftware.votifier.net.VotifierSession;
|
||||
import com.vexsoftware.votifier.util.QuietException;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.Unpooled;
|
||||
import io.netty.channel.embedded.EmbeddedChannel;
|
||||
@@ -56,7 +57,7 @@ public class VotifierProtocolDifferentiatorTest {
|
||||
for (int i = 0; i < 256; i++) {
|
||||
test.writeByte(0);
|
||||
}
|
||||
assertThrows(CorruptedFrameException.class, () -> channel.writeInbound(test));
|
||||
assertThrows(DecoderException.class, () -> channel.writeInbound(test));
|
||||
channel.close();
|
||||
}
|
||||
|
||||
|
||||
+7
-5
@@ -1,9 +1,11 @@
|
||||
package com.vexsoftware.votifier.support.forwarding;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.vexsoftware.votifier.model.Vote;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
@@ -12,13 +14,13 @@ public class PMForwardingSinkTest {
|
||||
|
||||
@Test
|
||||
public void testSuccessfulMultiDecode() throws Exception {
|
||||
List<Vote> receivedVotes = Lists.newArrayList();
|
||||
List<Vote> receivedVotes = new ArrayList<>();
|
||||
ForwardedVoteListener vl = receivedVotes::add;
|
||||
|
||||
List<Vote> sentVotes = Lists.newArrayList(
|
||||
List<Vote> sentVotes = new ArrayList<>(Arrays.asList(
|
||||
new Vote("serviceA", "usernameA", "1.1.1.1", "1546300800"),
|
||||
new Vote("serviceB", "usernameBBBBBBB", "1.2.23.4", "1514764800")
|
||||
);
|
||||
));
|
||||
|
||||
StringBuilder message = new StringBuilder();
|
||||
|
||||
@@ -26,7 +28,7 @@ public class PMForwardingSinkTest {
|
||||
message.append(v.serialize());
|
||||
}
|
||||
|
||||
byte[] messageBytes = message.toString().getBytes();
|
||||
byte[] messageBytes = message.toString().getBytes(StandardCharsets.UTF_8);
|
||||
System.out.println(message.toString());
|
||||
|
||||
AbstractPluginMessagingForwardingSink sink = new AbstractPluginMessagingForwardingSink(vl) {
|
||||
|
||||
@@ -0,0 +1,108 @@
|
||||
package com.vexsoftware.votifier.util;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.Sets;
|
||||
import com.vexsoftware.votifier.model.Vote;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.MethodSource;
|
||||
import org.junit.jupiter.params.provider.ValueSource;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Locale;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
public class ArgsToVoteTest {
|
||||
@Test
|
||||
void handlesInvalidRequest() {
|
||||
assertThrows(IllegalArgumentException.class, () -> {
|
||||
ArgsToVote.parse(new String[0]);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void handlesSingleUsername() {
|
||||
Vote vote = ArgsToVote.parse(new String[] { "dummy_user" });
|
||||
assertEquals("dummy_user", vote.getUsername());
|
||||
}
|
||||
|
||||
@Test
|
||||
void handlesSingleUsernameTooLong() {
|
||||
assertThrows(IllegalArgumentException.class, () -> {
|
||||
ArgsToVote.parse(new String[] { "AVeryVeryVeryLongUsername" });
|
||||
});
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@ValueSource(strings = { "servicename", "address", "timestamp" })
|
||||
void handlesAdditionalKeywordArguments(String key) throws Exception {
|
||||
Vote vote = ArgsToVote.parse(new String[] { "username=abc123", key + "=dummy" });
|
||||
|
||||
// Find the getter on the Vote object
|
||||
for (Method method : Vote.class.getDeclaredMethods()) {
|
||||
if (method.getName().toLowerCase(Locale.ENGLISH).equals("get" + key)) {
|
||||
assertEquals("dummy", method.invoke(vote));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
fail("Unable to find appropriate getter - this is a bug");
|
||||
}
|
||||
|
||||
@Test
|
||||
void handlesUsernameKeywordArgument() {
|
||||
Vote vote = ArgsToVote.parse(new String[] { "username=dummy_user" });
|
||||
assertEquals("dummy_user", vote.getUsername());
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@ValueSource(strings = { "servicename", "address", "timestamp" })
|
||||
void handlesMixedUsernameAndKeywordArgument(String key) throws Exception {
|
||||
Vote vote = ArgsToVote.parse(new String[] { "abc123", key + "=dummy" });
|
||||
|
||||
assertEquals("abc123", vote.getUsername());
|
||||
|
||||
// Find the getter on the Vote object
|
||||
for (Method method : Vote.class.getDeclaredMethods()) {
|
||||
if (method.getName().toLowerCase(Locale.ENGLISH).equals("get" + key)) {
|
||||
assertEquals("dummy", method.invoke(vote));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
fail("Unable to find appropriate getter - this is a bug");
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("powerSetArgs")
|
||||
void handlesMixedKeywordArguments(Set<String> keys) throws Exception {
|
||||
String[] args = new String[keys.size() + 1];
|
||||
args[0] = "abc123";
|
||||
for (int i = 0; i < keys.size(); i++) {
|
||||
args[i + 1] = ImmutableList.copyOf(keys).get(i) + "=dummy";
|
||||
}
|
||||
Vote vote = ArgsToVote.parse(args);
|
||||
|
||||
assertEquals("abc123", vote.getUsername());
|
||||
|
||||
// Find the getters on the Vote object
|
||||
outer: for (String key : keys) {
|
||||
for (Method method : Vote.class.getDeclaredMethods()) {
|
||||
if (method.getName().toLowerCase(Locale.ENGLISH).equals("get" + key)) {
|
||||
assertEquals("dummy", method.invoke(vote));
|
||||
continue outer;
|
||||
}
|
||||
}
|
||||
|
||||
fail("Unable to find appropriate getter - this is a bug");
|
||||
}
|
||||
}
|
||||
|
||||
private static Stream<Set<String>> powerSetArgs() {
|
||||
return Sets.powerSet(ImmutableSet.of("servicename", "address", "timestamp")).stream();
|
||||
}
|
||||
}
|
||||
+13
-6
@@ -1,22 +1,29 @@
|
||||
|
||||
.PHONY: clean, all, run
|
||||
.PHONY: clean all run
|
||||
|
||||
all : resources/paper.jar resources/proxy.jar
|
||||
all : resources/paper.jar resources/waterfall.jar resources/velocity.jar resources/sponge.jar
|
||||
|
||||
resources :
|
||||
mkdir resources
|
||||
|
||||
resources/paper.jar : resources
|
||||
wget -O resources/paper.jar https://papermc.io/ci/job/Paper-1.13/lastSuccessfulBuild/artifact/paperclip.jar
|
||||
wget -O resources/paper.jar https://papermc.io/api/v1/paper/1.15.2/353/download
|
||||
|
||||
resources/proxy.jar : resources
|
||||
wget -O resources/proxy.jar https://papermc.io/ci/job/Waterfall/lastSuccessfulBuild/artifact/Waterfall-Proxy/bootstrap/target/Waterfall.jar
|
||||
resources/waterfall.jar : resources
|
||||
wget -O resources/waterfall.jar https://papermc.io/ci/job/Waterfall/lastSuccessfulBuild/artifact/Waterfall-Proxy/bootstrap/target/Waterfall.jar
|
||||
|
||||
resources/velocity.jar : resources
|
||||
wget -O resources/velocity.jar https://ci.velocitypowered.com/job/velocity-1.1.0/lastSuccessfulBuild/artifact/proxy/build/libs/velocity-proxy-1.1.0-SNAPSHOT-all.jar
|
||||
|
||||
resources/sponge.jar : resources
|
||||
wget -O resources/sponge.jar https://repo.spongepowered.org/maven/org/spongepowered/spongevanilla/1.12.2-7.2.2/spongevanilla-1.12.2-7.2.2.jar
|
||||
|
||||
clean :
|
||||
rm -r resources/
|
||||
|
||||
run :
|
||||
tmux new-session './proxy/run.sh' \; \
|
||||
tmux new-session './p1/run.sh' \; \
|
||||
split-window -h './p2/run.sh' \; \
|
||||
split-window -h './s1/run.sh' \; \
|
||||
split-window -h './s2/run.sh' \; \
|
||||
select-layout even-horizontal
|
||||
+10
-7
@@ -1,7 +1,7 @@
|
||||
## Using this testbed
|
||||
|
||||
This testbed runs one Bungeecord as well as two Paper servers behind it, labeled
|
||||
s1 and s2. Ports for where everything is bound is listed below.
|
||||
This testbed runs two proxies, labeled p1 and p2, as well as two servers behind it,
|
||||
labeled s1 and s2. Ports for where everything is bound is listed below.
|
||||
|
||||
First, download required sources using the following command:
|
||||
|
||||
@@ -19,8 +19,11 @@ FYI, this only works in Linux afaik because thats what I do my development on.
|
||||
|
||||
# Ports
|
||||
|
||||
| Server | MC Port | Votifier Port |
|
||||
| ------ | ------- | ------------- |
|
||||
| proxy | 25577 | 8192 |
|
||||
| s1 | 25565 | 8193 |
|
||||
| s2 | 25566 | 8194 |
|
||||
| Server | Server Software | MC Port | Votifier Port |
|
||||
| ------ | ---------------------- | ------- | ------------- |
|
||||
| p1 | Waterfall/BungeeCord | 25577 | 8192 |
|
||||
| p2 | Velocity | 25578 | 8193 |
|
||||
| s1 | Paper (1.15.2) | 25565 | 8194 |
|
||||
| s2 | SpongeVanilla (1.12.2) | 25566 | 8195 |
|
||||
|
||||
For compatibility with 1.15.2, s2 includes ViaVersion.
|
||||
File renamed without changes.
@@ -1,7 +1,4 @@
|
||||
forge_support: true
|
||||
timeout: 30000
|
||||
online_mode: true
|
||||
log_commands: false
|
||||
server_connect_timeout: 5000
|
||||
listeners:
|
||||
- query_port: 25577
|
||||
motd: '&4its a bungee cord surbur'
|
||||
@@ -17,16 +14,8 @@ listeners:
|
||||
max_players: 1
|
||||
tab_size: 60
|
||||
force_default_server: false
|
||||
connection_throttle: 1
|
||||
groups:
|
||||
md_5:
|
||||
- admin
|
||||
log_pings: true
|
||||
ip_forward: true
|
||||
prevent_proxy_connections: true
|
||||
remote_ping_cache: -1
|
||||
network_compression_threshold: 256
|
||||
disabled_commands: []
|
||||
stats: bf8a54ea-2917-4b9e-b463-2c05bd7f1ac6
|
||||
permissions:
|
||||
default:
|
||||
- bungeecord.command.server
|
||||
@@ -36,6 +25,22 @@ permissions:
|
||||
- bungeecord.command.end
|
||||
- bungeecord.command.ip
|
||||
- bungeecord.command.reload
|
||||
log_pings: true
|
||||
connection_throttle_limit: 3
|
||||
prevent_proxy_connections: true
|
||||
timeout: 30000
|
||||
player_limit: -1
|
||||
ip_forward: true
|
||||
groups:
|
||||
md_5:
|
||||
- admin
|
||||
remote_ping_timeout: 5000
|
||||
connection_throttle: 1
|
||||
log_commands: false
|
||||
stats: bf8a54ea-2917-4b9e-b463-2c05bd7f1ac6
|
||||
online_mode: true
|
||||
forge_support: true
|
||||
disabled_commands: []
|
||||
servers:
|
||||
s1:
|
||||
motd: SERVER 1
|
||||
@@ -45,4 +50,3 @@ servers:
|
||||
motd: SERVER 2
|
||||
address: localhost:25566
|
||||
restricted: false
|
||||
player_limit: -1
|
||||
File renamed without changes.
@@ -0,0 +1,2 @@
|
||||
rsa/
|
||||
cached-votes.json
|
||||
@@ -7,12 +7,12 @@ port: 8192
|
||||
|
||||
# Whether or not to print debug messages. In a production system, this should be set to false.
|
||||
# This is useful when initially setting up NuVotifier to ensure votes are being delivered.
|
||||
debug: false
|
||||
debug: true
|
||||
|
||||
# All tokens, labeled by the serviceName of each server list.
|
||||
tokens:
|
||||
# Default token for all server lists, if another isn't supplied.
|
||||
default: jqpli3gnd8l67qsg2d81vje09h
|
||||
default: proxy1token
|
||||
|
||||
# Setting this option to true will disable handling of Protocol v1 packets. While the old protocol is not secure, this
|
||||
# option is currently not recommended as most voting sites only support the old protocol at present.
|
||||
@@ -24,7 +24,7 @@ forwarding:
|
||||
# - none - Does not set up a forwarding method.
|
||||
# - pluginMessaging - Sets up plugin messaging.
|
||||
# - proxy - Proxies votes to other NuVotifier servers from this server.
|
||||
method: none
|
||||
method: pluginMessaging
|
||||
pluginMessaging:
|
||||
channel: nuvotifier:votes
|
||||
|
||||
@@ -46,11 +46,11 @@ forwarding:
|
||||
# most set ups.
|
||||
cache: file
|
||||
# Only sends the vote to the server in which the player is currently joined.
|
||||
onlySendToJoinedServer: false
|
||||
onlySendToJoinedServer: true
|
||||
#Sets which server to send the vote in the event the player is not online when the vote is cast
|
||||
#If you do not want the vote forwarded to a fallback, set this value to empty ('')
|
||||
#ONLY USED IF onlySendToJoinedServer is true!!
|
||||
joinedServerFallback: 'Hub'
|
||||
joinedServerFallback: 's1'
|
||||
# Defines how quickly to dump votes over a player's connection when offloading a cache in votes per second
|
||||
dumpRate: 5
|
||||
# Options for file caching.
|
||||
File renamed without changes.
Symlink
+1
@@ -0,0 +1 @@
|
||||
../resources/waterfall.jar
|
||||
File renamed without changes.
@@ -1,8 +1,9 @@
|
||||
use_netty_dns_resolver: true
|
||||
disable_modern_tab_limiter: true
|
||||
log_initial_handler_connections: true
|
||||
allow_empty_packets: false
|
||||
throttling:
|
||||
tab_complete: 1000
|
||||
game_version: ''
|
||||
disable_modern_tab_limiter: true
|
||||
use_netty_dns_resolver: true
|
||||
disable_entity_metadata_rewrite: false
|
||||
log_initial_handler_connections: true
|
||||
log_server_list_ping: false
|
||||
allow_empty_packets: false
|
||||
@@ -0,0 +1 @@
|
||||
logs/
|
||||
File renamed without changes.
@@ -0,0 +1,2 @@
|
||||
rsa/
|
||||
cached-votes.json
|
||||
@@ -0,0 +1,79 @@
|
||||
# The IP to listen to. Use 0.0.0.0 if you wish to listen to all interfaces on your server. (All IP addresses)
|
||||
# This defaults to the IP you have configured your server to listen on, or 0.0.0.0 if you have not configured this.
|
||||
host = "0.0.0.0"
|
||||
|
||||
# Port to listen for new votes on
|
||||
port = 8193
|
||||
|
||||
# Setting this option to true will disable handling of Protocol v1 packets. While the old protocol is not secure, this
|
||||
# option is currently not recommended as most voting sites only support the old protocol at present. However, if you are
|
||||
# using NuVotifier's proxy forwarding mechanism, enabling this option will increase your server's security.
|
||||
disable-v1-protocol = false
|
||||
|
||||
# All tokens, labeled by the serviceName of each server list.
|
||||
[tokens]
|
||||
# Default token for all server lists, if another isn't supplied.
|
||||
default = "proxy2token"
|
||||
|
||||
# Configuration section for all vote forwarding to NuVotifier
|
||||
[forwarding]
|
||||
# Sets whether to set up a remote method for fowarding. Supported methods:
|
||||
# - none - Does not set up a forwarding method.
|
||||
# - pluginMessaging - Sets up plugin messaging.
|
||||
# - proxy - Proxies votes to other NuVotifier servers from this server.
|
||||
method = "pluginMessaging"
|
||||
|
||||
[forwarding.pluginMessaging]
|
||||
channel = "nuvotifier:votes"
|
||||
|
||||
# Only send votes to certain servers. If a server is present on excludedServers, then votes will NOT be forwarded
|
||||
# to them. If excludedServers is not present, votes will be sent to all servers.
|
||||
# If onlySendToJoinedServer is true and a player is on one of these servers, NuVotifier will process the vote as if the
|
||||
# player was not on the network at all.
|
||||
# excludedServers = ["server1", "server2"]
|
||||
|
||||
# If uncommented, turns excludedServers into an includedServers, where only servers on the list will be used.
|
||||
# whitelist = true
|
||||
|
||||
# Sets which cache to use if there are no players on the server that the vote is being sent to. Supported caches:
|
||||
# - none - Votes will simply be lost when no players are present on the server.
|
||||
# - memory - Votes will be cached in memory when no players are present. When Bungee is restarted, the votes will be lost.
|
||||
# - file - Votes will be saved to a local file every 3 minutes and on shutdown and reloaded when Bungee is restarted. This is suitable for
|
||||
# most set ups.
|
||||
cache = "file"
|
||||
# Only sends the vote to the server in which the player is currently joined.
|
||||
onlySendToJoinedServer = true
|
||||
|
||||
# Sets which server to send the vote in the event the player is not online when the vote is cast
|
||||
# If you do not want the vote forwarded to a fallback, set this value to empty ('')
|
||||
# ONLY USED IF onlySendToJoinedServer is true!!
|
||||
joinedServerFallback = "s1"
|
||||
|
||||
# Defines how quickly to dump votes over a player's connection while offloading a cache in votes per second
|
||||
dumpRate = 5
|
||||
|
||||
[forwarding.file-cache]
|
||||
# Options for file caching.
|
||||
name = "cached-votes.json"
|
||||
# days before a vote is considered 'dead' - removed from cache with a console warning. -1 signifies no cache.
|
||||
cacheTime = 10
|
||||
|
||||
[forwarding.memory-cache]
|
||||
# Options for file caching.
|
||||
name = "cached-votes.json"
|
||||
# days before a vote is considered 'dead' - removed from cache with a console warning. -1 signifies no cache. Votes are
|
||||
# also removed on restart
|
||||
cacheTime = 10
|
||||
|
||||
[forwarding.proxy]
|
||||
# Specify servers to proxy votes for.
|
||||
|
||||
[forwarding.proxy.Hub]
|
||||
address = "127.0.0.1"
|
||||
port = 8193
|
||||
token = "MyKeyHere"
|
||||
|
||||
[forwarding.proxy.Hub2]
|
||||
address = "127.0.0.1"
|
||||
port = 8194
|
||||
token = "MyKeyHere"
|
||||
Symlink
+1
@@ -0,0 +1 @@
|
||||
../resources/velocity.jar
|
||||
Executable
+6
@@ -0,0 +1,6 @@
|
||||
#!/bin/sh
|
||||
|
||||
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null && pwd )"
|
||||
cd $DIR
|
||||
|
||||
java -jar proxy.jar
|
||||
@@ -0,0 +1,135 @@
|
||||
# Config version. Do not change this
|
||||
config-version = "1.0"
|
||||
|
||||
# What port should the proxy be bound to? By default, we'll bind to all addresses on port 25577.
|
||||
bind = "0.0.0.0:25578"
|
||||
|
||||
# What should be the MOTD? This gets displayed when the player adds your server to
|
||||
# their server list. Legacy color codes and JSON are accepted.
|
||||
motd = "&3doot doot imma velocity serbur"
|
||||
|
||||
# What should we display for the maximum number of players? (Velocity does not support a cap
|
||||
# on the number of players online.)
|
||||
show-max-players = 500
|
||||
|
||||
# Should we authenticate players with Mojang? By default, this is on.
|
||||
online-mode = true
|
||||
|
||||
# If client's ISP/AS sent from this proxy is different from the one from Mojang's
|
||||
# authentication server, the player is kicked. This disallows some VPN and proxy
|
||||
# connections but is a weak form of protection.
|
||||
prevent-client-proxy-connections = false
|
||||
|
||||
# Should we forward IP addresses and other data to backend servers?
|
||||
# Available options:
|
||||
# - "none": No forwarding will be done. All players will appear to be connecting
|
||||
# from the proxy and will have offline-mode UUIDs.
|
||||
# - "legacy": Forward player IPs and UUIDs in a BungeeCord-compatible format. Use this
|
||||
# if you run servers using Minecraft 1.12 or lower.
|
||||
# - "bungeeguard": Forward player IPs and UUIDs in a format supported by the BungeeGuard
|
||||
# plugin. Use this if you run servers using Minecraft 1.12 or lower, and are
|
||||
# unable to implement network level firewalling (on a shared host).
|
||||
# - "modern": Forward player IPs and UUIDs as part of the login process using
|
||||
# Velocity's native forwarding. Only applicable for Minecraft 1.13 or higher.
|
||||
player-info-forwarding-mode = "LEGACY"
|
||||
|
||||
# If you are using modern or BungeeGuard IP forwarding, configure an unique secret here.
|
||||
forwarding-secret = "not at all secret lolololol"
|
||||
|
||||
# Announce whether or not your server supports Forge. If you run a modded server, we
|
||||
# suggest turning this on.
|
||||
#
|
||||
# If your network runs one modpack consistently, consider using ping-passthrough = "mods"
|
||||
# instead for a nicer display in the server list.
|
||||
announce-forge = false
|
||||
|
||||
# If enabled (default is false) and the proxy is in online mode, Velocity will kick
|
||||
# any existing player who is online if a duplicate connection attempt is made.
|
||||
kick-existing-players = false
|
||||
|
||||
# Should Velocity pass server list ping requests to a backend server?
|
||||
# Available options:
|
||||
# - "disabled": No pass-through will be done. The velocity.toml and server-icon.png
|
||||
# will determine the initial server list ping response.
|
||||
# - "mods": Passes only the mod list from your backend server into the response.
|
||||
# The first server in your try list (or forced host) with a mod list will be
|
||||
# used. If no backend servers can be contacted, Velocity won't display any
|
||||
# mod information.
|
||||
# - "description": Uses the description and mod list from the backend server. The first
|
||||
# server in the try (or forced host) list that responds is used for the
|
||||
# description and mod list.
|
||||
# - "all": Uses the backend server's response as the proxy response. The Velocity
|
||||
# configuration is used if no servers could be contacted.
|
||||
ping-passthrough = "DISABLED"
|
||||
|
||||
[servers]
|
||||
# Configure your servers here. Each key represents the server's name, and the value
|
||||
# represents the IP address of the server to connect to.
|
||||
s1 = "127.0.0.1:25565"
|
||||
s2 = "127.0.0.1:25566"
|
||||
|
||||
# In what order we should try servers when a player logs in or is kicked from aserver.
|
||||
try = [
|
||||
"s1"
|
||||
]
|
||||
|
||||
[forced-hosts]
|
||||
# Configure your forced hosts here.
|
||||
|
||||
[advanced]
|
||||
# How large a Minecraft packet has to be before we compress it. Setting this to zero will
|
||||
# compress all packets, and setting it to -1 will disable compression entirely.
|
||||
compression-threshold = 256
|
||||
|
||||
# How much compression should be done (from 0-9). The default is -1, which uses the
|
||||
# default level of 6.
|
||||
compression-level = -1
|
||||
|
||||
# How fast (in milliseconds) are clients allowed to connect after the last connection? By
|
||||
# default, this is three seconds. Disable this by setting this to 0.
|
||||
login-ratelimit = 3000
|
||||
|
||||
# Specify a custom timeout for connection timeouts here. The default is five seconds.
|
||||
connection-timeout = 5000
|
||||
|
||||
# Specify a read timeout for connections here. The default is 30 seconds.
|
||||
read-timeout = 30000
|
||||
|
||||
# Enables compatibility with HAProxy.
|
||||
proxy-protocol = false
|
||||
|
||||
# Enables TCP fast open support on the proxy. Requires the proxy to run on Linux.
|
||||
tcp-fast-open = false
|
||||
|
||||
# Enables BungeeCord plugin messaging channel support on Velocity.
|
||||
bungee-plugin-message-channel = true
|
||||
|
||||
# Shows ping requests to the proxy from clients.
|
||||
show-ping-requests = false
|
||||
|
||||
[query]
|
||||
# Whether to enable responding to GameSpy 4 query responses or not.
|
||||
enabled = false
|
||||
|
||||
# If query is enabled, on what port should the query protocol listen on?
|
||||
port = 25577
|
||||
|
||||
# This is the map name that is reported to the query services.
|
||||
map = "Velocity"
|
||||
|
||||
# Whether plugins should be shown in query response by default or not
|
||||
show-plugins = false
|
||||
|
||||
[metrics]
|
||||
# Whether metrics will be reported to bStats (https://bstats.org).
|
||||
# bStats collects some basic information, like how many people use Velocity and their
|
||||
# player count. We recommend keeping bStats enabled, but if you're not comfortable with
|
||||
# this, you can turn this setting off. There is no performance penalty associated with
|
||||
# having metrics enabled, and data sent to bStats can't identify your server.
|
||||
enabled = true
|
||||
|
||||
# A unique, anonymous ID to identify this proxy with.
|
||||
id = "729fe923-b383-4e5b-b456-5adf554bfe69"
|
||||
|
||||
log-failure = false
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
rsa/
|
||||
@@ -1 +0,0 @@
|
||||
../resources/proxy.jar
|
||||
+1
-1
@@ -7,4 +7,4 @@ well as overriding the eula check. If you don't agree to the Mojang EULA
|
||||
thingie, then uh, smash your computer or something because you totally agreed
|
||||
to it so just fyi
|
||||
WARNING
|
||||
java -DIReallyKnowWhatIAmDoingISwear -Dcom.mojang.eula.agree=true -jar paper.jar
|
||||
java -DIReallyKnowWhatIAmDoingISwear -Dcom.mojang.eula.agree=true -jar paper.jar nogui
|
||||
@@ -13,6 +13,7 @@
|
||||
|
||||
|
||||
settings:
|
||||
minimum-api: none
|
||||
allow-end: true
|
||||
warn-on-overload: true
|
||||
permissions-file: permissions.yml
|
||||
@@ -31,6 +32,8 @@ chunk-gc:
|
||||
period-in-ticks: 600
|
||||
load-threshold: 0
|
||||
ticks-per:
|
||||
water-spawns: 1
|
||||
ambient-spawns: 1
|
||||
animal-spawns: 400
|
||||
monster-spawns: 1
|
||||
autosave: 6000
|
||||
|
||||
+41
-6
@@ -10,9 +10,12 @@
|
||||
# Website: https://papermc.io/
|
||||
# Docs: https://paper.readthedocs.org/
|
||||
|
||||
allow-perm-block-break-exploits: false
|
||||
verbose: false
|
||||
config-version: 16
|
||||
config-version: 20
|
||||
settings:
|
||||
console-has-all-permissions: false
|
||||
chunk-tasks-per-tick: 1000
|
||||
load-permissions-yml-before-plugins: true
|
||||
bungee-online-mode: true
|
||||
use-versioned-world: false
|
||||
@@ -41,10 +44,10 @@ settings:
|
||||
max-player-auto-save-per-tick: -1
|
||||
async-chunks:
|
||||
enable: true
|
||||
generation: true
|
||||
thread-per-world-generation: true
|
||||
load-threads: -1
|
||||
threads: -1
|
||||
use-alternative-luck-formula: false
|
||||
unsupported-settings:
|
||||
allow-tnt-duplication: false
|
||||
messages:
|
||||
no-permission: '&cI''m sorry, but you do not have permission to perform this command.
|
||||
Please contact the server administrators if you believe that this is in error.'
|
||||
@@ -54,6 +57,7 @@ messages:
|
||||
flying-vehicle: Flying is not enabled on this server
|
||||
connection-throttle: Connection throttled! Please wait before reconnecting.
|
||||
timings:
|
||||
server-name: Unknown Server
|
||||
enabled: true
|
||||
verbose: true
|
||||
server-name-privacy: false
|
||||
@@ -64,8 +68,23 @@ timings:
|
||||
history-length: 3600
|
||||
world-settings:
|
||||
default:
|
||||
per-player-mob-spawns: false
|
||||
phantoms-do-not-spawn-on-creative-players: true
|
||||
phantoms-only-attack-insomniacs: true
|
||||
light-queue-size: 20
|
||||
count-all-mobs-for-spawning: false
|
||||
seed-based-feature-search: true
|
||||
nether-ceiling-void-damage-height: 0
|
||||
fix-zero-tick-instant-grow-farms: true
|
||||
portal-create-radius: 16
|
||||
iron-golems-can-spawn-in-air: false
|
||||
entities-target-with-follow-range: false
|
||||
zombie-villager-infection-chance: -1.0
|
||||
portal-search-radius: 128
|
||||
game-mechanics:
|
||||
disable-pillager-patrols: false
|
||||
nerf-pigmen-from-nether-portals: false
|
||||
disable-relative-projectile-velocity: false
|
||||
villages-load-chunks: false
|
||||
scan-for-legacy-ender-dragon: true
|
||||
disable-chest-cat-detection: false
|
||||
@@ -74,6 +93,14 @@ world-settings:
|
||||
disable-sprint-interruption-on-attack: false
|
||||
shield-blocking-delay: 5
|
||||
disable-unloaded-chunk-enderpearl-exploit: true
|
||||
pillager-patrols:
|
||||
spawn-chance: 0.2
|
||||
spawn-delay:
|
||||
per-player: false
|
||||
ticks: 12000
|
||||
start:
|
||||
per-player: false
|
||||
day: 5
|
||||
queue-light-updates: false
|
||||
optimize-explosions: false
|
||||
disable-teleportation-suffocation-check: false
|
||||
@@ -141,13 +168,12 @@ world-settings:
|
||||
- chest
|
||||
- diamond_ore
|
||||
- redstone_ore
|
||||
- lit_redstone_ore
|
||||
- clay
|
||||
- emerald_ore
|
||||
- ender_chest
|
||||
replacement-blocks:
|
||||
- stone
|
||||
- planks
|
||||
- oak_planks
|
||||
skip-entity-ticking-in-chunks-scheduled-for-unload: true
|
||||
armor-stands-do-collision-entity-lookups: true
|
||||
keep-spawn-loaded-range: 8
|
||||
@@ -176,3 +202,12 @@ world-settings:
|
||||
mob-spawner-tick-rate: 1
|
||||
squid-spawn-height:
|
||||
maximum: 0.0
|
||||
alt-item-despawn-rate:
|
||||
enabled: false
|
||||
items:
|
||||
COBBLESTONE: 300
|
||||
viewdistances:
|
||||
no-tick-view-distance: -1
|
||||
generator-settings:
|
||||
flat-bedrock: false
|
||||
baby-zombie-movement-modifier: 0.5
|
||||
@@ -3,7 +3,7 @@
|
||||
host: 0.0.0.0
|
||||
|
||||
# Port to listen for new votes on
|
||||
port: 8193
|
||||
port: 8194
|
||||
|
||||
# Whether or not to print debug messages. In a production system, this should be set to false.
|
||||
# This is useful when initially setting up NuVotifier to ensure votes are being delivered.
|
||||
|
||||
Symlink
+1
@@ -0,0 +1 @@
|
||||
../../../universal/build/libs/nuvotifier.jar
|
||||
@@ -1,26 +1,33 @@
|
||||
#Minecraft server properties
|
||||
#Fri Dec 21 15:15:00 EST 2018
|
||||
#Tue Jun 23 23:02:31 EDT 2020
|
||||
spawn-protection=16
|
||||
max-tick-time=60000
|
||||
query.port=25565
|
||||
generator-settings=
|
||||
force-gamemode=false
|
||||
allow-nether=true
|
||||
enforce-whitelist=false
|
||||
gamemode=0
|
||||
gamemode=survival
|
||||
broadcast-console-to-ops=true
|
||||
enable-query=false
|
||||
player-idle-timeout=0
|
||||
difficulty=1
|
||||
difficulty=easy
|
||||
spawn-monsters=true
|
||||
broadcast-rcon-to-ops=true
|
||||
op-permission-level=4
|
||||
pvp=true
|
||||
snooper-enabled=true
|
||||
level-type=DEFAULT
|
||||
level-type=default
|
||||
hardcore=false
|
||||
enable-command-block=false
|
||||
max-players=20
|
||||
network-compression-threshold=256
|
||||
resource-pack-sha1=
|
||||
max-world-size=29999984
|
||||
function-permission-level=2
|
||||
rcon.port=25575
|
||||
server-port=25565
|
||||
debug=false
|
||||
server-ip=
|
||||
spawn-npcs=true
|
||||
allow-flight=false
|
||||
@@ -29,11 +36,12 @@ view-distance=10
|
||||
resource-pack=
|
||||
spawn-animals=true
|
||||
white-list=false
|
||||
rcon.password=
|
||||
generate-structures=true
|
||||
online-mode=false
|
||||
max-build-height=256
|
||||
level-seed=
|
||||
prevent-proxy-connections=false
|
||||
use-native-transport=true
|
||||
motd=A Minecraft Server
|
||||
enable-rcon=false
|
||||
motd=A Minecraft Server
|
||||
+32
-2
@@ -10,8 +10,9 @@
|
||||
# IRC: #spigot @ irc.spi.gt ( http://www.spigotmc.org/pages/irc/ )
|
||||
# Forums: http://www.spigotmc.org/
|
||||
|
||||
config-version: 11
|
||||
config-version: 12
|
||||
settings:
|
||||
log-villager-deaths: true
|
||||
debug: false
|
||||
save-user-cache-on-stop-only: false
|
||||
sample-count: 12
|
||||
@@ -60,6 +61,11 @@ advancements:
|
||||
- minecraft:story/disabled
|
||||
world-settings:
|
||||
default:
|
||||
seed-outpost: 165745296
|
||||
seed-endcity: 10387313
|
||||
view-distance: default
|
||||
trident-despawn-rate: 1200
|
||||
end-portal-sound-radius: 0
|
||||
verbose: true
|
||||
merge-radius:
|
||||
exp: 3.0
|
||||
@@ -91,6 +97,12 @@ world-settings:
|
||||
min: 45.0
|
||||
mob-spawn-range: 8
|
||||
growth:
|
||||
beetroot-modifier: 100
|
||||
carrot-modifier: 100
|
||||
potato-modifier: 100
|
||||
bamboo-modifier: 100
|
||||
sweetberry-modifier: 100
|
||||
kelp-modifier: 100
|
||||
cactus-modifier: 100
|
||||
cane-modifier: 100
|
||||
melon-modifier: 100
|
||||
@@ -102,11 +114,30 @@ world-settings:
|
||||
vine-modifier: 100
|
||||
cocoa-modifier: 100
|
||||
entity-activation-range:
|
||||
raiders: 48
|
||||
villagers: 32
|
||||
flying-monsters: 32
|
||||
villagers-work-immunity-after: 100
|
||||
villagers-work-immunity-for: 20
|
||||
villagers-active-for-panic: true
|
||||
animals: 32
|
||||
monsters: 32
|
||||
misc: 16
|
||||
water: 16
|
||||
tick-inactive-villagers: true
|
||||
wake-up-inactive:
|
||||
animals-max-per-tick: 4
|
||||
animals-every: 1200
|
||||
animals-for: 100
|
||||
monsters-max-per-tick: 8
|
||||
monsters-every: 400
|
||||
monsters-for: 100
|
||||
villagers-max-per-tick: 4
|
||||
villagers-every: 600
|
||||
villagers-for: 100
|
||||
flying-monsters-max-per-tick: 8
|
||||
flying-monsters-every: 200
|
||||
flying-monsters-for: 100
|
||||
entity-tracking-range:
|
||||
players: 48
|
||||
animals: 48
|
||||
@@ -120,7 +151,6 @@ world-settings:
|
||||
wither-spawn-sound-radius: 0
|
||||
enable-zombie-pigmen-portal-spawns: true
|
||||
item-despawn-rate: 6000
|
||||
view-distance: 10
|
||||
arrow-despawn-rate: 1200
|
||||
hanging-tick-frequency: 100
|
||||
zombie-aggressive-towards-villager: true
|
||||
|
||||
+2
-4
@@ -3,17 +3,15 @@ banned-players.json
|
||||
|
||||
cache/
|
||||
|
||||
eula.txt
|
||||
|
||||
logs/
|
||||
|
||||
permissions.yml
|
||||
|
||||
ops.json
|
||||
usercache.json
|
||||
usernamecache.json
|
||||
version_history.json
|
||||
whitelist.json
|
||||
|
||||
world/
|
||||
world_nether/
|
||||
world_the_end/
|
||||
.mixin.out
|
||||
@@ -1,37 +0,0 @@
|
||||
# This is the main configuration file for Bukkit.
|
||||
# As you can see, there's actually not that much to configure without any plugins.
|
||||
# For a reference for any variable inside this file, check out the Bukkit Wiki at
|
||||
# https://www.spigotmc.org/go/bukkit-yml
|
||||
#
|
||||
# If you need help on this file, feel free to join us on irc or leave a message
|
||||
# on the forums asking for advice.
|
||||
#
|
||||
# IRC: #spigot @ irc.spi.gt
|
||||
# (If this means nothing to you, just go to https://www.spigotmc.org/go/irc )
|
||||
# Forums: https://www.spigotmc.org/
|
||||
# Bug tracker: https://www.spigotmc.org/go/bugs
|
||||
|
||||
|
||||
settings:
|
||||
allow-end: true
|
||||
warn-on-overload: true
|
||||
permissions-file: permissions.yml
|
||||
update-folder: update
|
||||
plugin-profiling: false
|
||||
connection-throttle: 4000
|
||||
query-plugins: true
|
||||
deprecated-verbose: default
|
||||
shutdown-message: Server closed
|
||||
spawn-limits:
|
||||
monsters: 70
|
||||
animals: 10
|
||||
water-animals: 15
|
||||
ambient: 15
|
||||
chunk-gc:
|
||||
period-in-ticks: 600
|
||||
load-threshold: 0
|
||||
ticks-per:
|
||||
animal-spawns: 400
|
||||
monster-spawns: 1
|
||||
autosave: 6000
|
||||
aliases: now-in-commands.yml
|
||||
@@ -1,17 +0,0 @@
|
||||
# This is the commands configuration file for Bukkit.
|
||||
# For documentation on how to make use of this file, check out the Bukkit Wiki at
|
||||
# https://www.spigotmc.org/go/commands-yml
|
||||
#
|
||||
# If you need help on this file, feel free to join us on irc or leave a message
|
||||
# on the forums asking for advice.
|
||||
#
|
||||
# IRC: #spigot @ irc.spi.gt
|
||||
# (If this means nothing to you, just go to https://www.spigotmc.org/go/irc )
|
||||
# Forums: https://www.spigotmc.org/
|
||||
# Bug tracker: https://www.spigotmc.org/go/bugs
|
||||
|
||||
command-block-overrides: []
|
||||
ignore-vanilla-permissions: false
|
||||
aliases:
|
||||
icanhasbukkit:
|
||||
- version $1-
|
||||
@@ -0,0 +1 @@
|
||||
rsa/
|
||||
@@ -0,0 +1,8 @@
|
||||
host: 127.0.0.1
|
||||
port: 8195
|
||||
debug: true
|
||||
disable-v1-protocol: false
|
||||
tokens: {default: server2token}
|
||||
forwarding:
|
||||
method: pluginMessaging
|
||||
pluginMessaging: {channel: 'nuvotifier:votes'}
|
||||
@@ -0,0 +1,43 @@
|
||||
# 1.0
|
||||
#
|
||||
# # If you need help with the configuration or have any questions related to Sponge,
|
||||
# # join us at the IRC or drop by our forums and leave a post.
|
||||
#
|
||||
# # IRC: #sponge @ irc.esper.net ( https://webchat.esper.net/?channel=sponge )
|
||||
# # Forums: https://forums.spongepowered.org/
|
||||
#
|
||||
|
||||
sponge {
|
||||
data-registration {
|
||||
# A configurable list of registration ids that are to be removed
|
||||
# when discovered for deserialization. This can be controlled by
|
||||
# commands in sponge. It is adviseable to refer to the lists made
|
||||
# available through 'failed-data-list', as using any id's from
|
||||
# 'registered-data' will result in custom data being deleted at
|
||||
# every load.
|
||||
data-to-purge=[]
|
||||
# An auto generated list, by Sponge, to discover and list
|
||||
# all failed custom data deserializations at runtime due
|
||||
# to a lack of the registrations being made by a plugin.
|
||||
# Not to be confused by failed deserialization due to bad data.
|
||||
# Modifying the list will result in no effect as Sponge auto
|
||||
# generates this list. This is merely for user configuration.
|
||||
failed-data-list=[]
|
||||
# In the cases where there is already previously discovered data
|
||||
# we don't want to spam the log on each discovery in certain
|
||||
# contexts. If it is required, we still can emit the log warning
|
||||
# when necessary.
|
||||
print-on-discovery=false
|
||||
# An auto generated list, by Sponge, to provide a list of
|
||||
# registered custom data manipulators by plugins. Since
|
||||
# the list is generated AFTER the game starts, modifying
|
||||
# this list will not affect Sponge's system in any way.
|
||||
# However, it is advisable to view what registered datas
|
||||
# exist on a server instance, such that when Sponge completes
|
||||
# startup, it will be verified that all existing registrations
|
||||
# are accounted for. A warning will be emitted for any existing
|
||||
# registrations that were not registered, and moved to the
|
||||
# 'failed-data-list'.
|
||||
registered-data=[]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,641 @@
|
||||
# 1.0
|
||||
#
|
||||
# # If you need help with the configuration or have any questions related to Sponge,
|
||||
# # join us at the IRC or drop by our forums and leave a post.
|
||||
#
|
||||
# # IRC: #sponge @ irc.esper.net ( https://webchat.esper.net/?channel=sponge )
|
||||
# # Forums: https://forums.spongepowered.org/
|
||||
#
|
||||
|
||||
sponge {
|
||||
# Stopgap measures for dealing with broken mods
|
||||
broken-mods {
|
||||
# A list of mod ids that have broken network handlers (they interact with the game from a Netty handler thread).
|
||||
# All network handlers from a forcibly scheduled to run on the main thread.
|
||||
# Note that this setting should be considered a last resort, and should only be used as a stopgap measure while waiting for a mod to properly fix the issue.
|
||||
broken-network-handler-mods=[]
|
||||
}
|
||||
bungeecord {
|
||||
# If 'true', allows BungeeCord to forward IP address, UUID, and Game Profile to this server.
|
||||
ip-forwarding=true
|
||||
}
|
||||
cause-tracker {
|
||||
# A mapping that is semi-auto-populating for TileEntities whose types
|
||||
# are found to be providing "null" Block sources as neighbor notifications
|
||||
# that end up causing crashes or spam reports. If the value is set to
|
||||
# "true", then a "workaround" will be attempted. If not, the
|
||||
#
|
||||
# current BlockState at the target source will be queried from the world.
|
||||
# This map having a specific
|
||||
# entry of a TileEntity will prevent a log or warning come up to any logs
|
||||
# when that "null" arises, and Sponge will self-rectify the TileEntity
|
||||
# by calling the method "getBlockType()". It is advised that if the mod
|
||||
# id in question is coming up, that the mod author is notified about the
|
||||
# error-prone usage of the field "blockType". You can refer them to
|
||||
# the following links for the issue:
|
||||
# https://gist.github.com/gabizou/ad570dc09dfed259cac9d74284e78e8b
|
||||
# https://github.com/SpongePowered/SpongeForge/issues/2787
|
||||
# Also, please provide them with these links for the example PR to
|
||||
# fix the issue itself, as the fix is very simple:
|
||||
# https://github.com/TehNut/Soul-Shards-Respawn/pull/24
|
||||
# https://github.com/Epoxide-Software/Enchanting-Plus/pull/135
|
||||
#
|
||||
auto-fix-null-source-block-providing-tile-entities {}
|
||||
# If set to 'true', when a mod or plugin attempts to spawn an entity
|
||||
# off the main server thread, Sponge will automatically
|
||||
# capture said entity to spawn it properly on the main
|
||||
# server thread. The catch to this is that some mods are
|
||||
# not considering the consequences of spawning an entity
|
||||
# off the server thread, and are unaware of potential race
|
||||
# conditions they may cause. If this is set to false,
|
||||
# Sponge will politely ignore the entity being spawned,
|
||||
# and emit a warning about said spawn anyways.
|
||||
capture-async-spawning-entities=true
|
||||
# If 'true', more thorough debugging for PhaseStates
|
||||
# such that a StackTrace is created every time a PhaseState
|
||||
# switches, allowing for more fine grained troubleshooting
|
||||
# in the cases of runaway phase states. Note that this is
|
||||
# not extremely performant and may have some associated costs
|
||||
# with generating the stack traces constantly.
|
||||
generate-stacktrace-per-phase=false
|
||||
# The maximum number of times to recursively process transactions in a single phase.
|
||||
# Some mods may interact badly with Sponge's block capturing system, causing Sponge to
|
||||
# end up capturing block transactions every time it tries to process an existing batch.
|
||||
# Due to the recursive nature of the depth-first processing that Sponge uses to handle block transactions,
|
||||
# this can result in a stack overflow, which causes us to lose all infomration about the original cause of the issue.
|
||||
# To prevent a stack overflow, Sponge tracks the current processing depth, and aborts processing when it exceeds
|
||||
# this threshold.
|
||||
# The default value should almost always work properly - it's unlikely you'll ever have to change it.
|
||||
max-block-processing-depth=1000
|
||||
# If verbose is not enabled, this restricts the amount of
|
||||
# runaway phase state printouts, usually happens on a server
|
||||
# where a PhaseState is not completing. Although rare, it should
|
||||
# never happen, but when it does, sometimes it can continuously print
|
||||
# more and more. This attempts to placate that while a fix can be worked on
|
||||
# to resolve the runaway. If verbose is enabled, they will always print.
|
||||
maximum-printed-runaway-counts=3
|
||||
# If true, when a mod attempts to perform a neighbor notification
|
||||
# on a block, some mods do not know to perform a 'null' check
|
||||
# on the source block of their TileEntity. This usually goes by
|
||||
# unnoticed by other mods, because they may perform '==' instance
|
||||
# equality checks instead of calling methods on the potentially
|
||||
# null Block, but Sponge uses the block to build information to
|
||||
# help tracking. This has caused issues in the past. Generally,
|
||||
# this can be useful for leaving "true" so a proper report is
|
||||
# generated once for your server, and can be reported to the
|
||||
# offending mod author.
|
||||
# This is 'false' by default in SpongeVanilla.
|
||||
# Review the following links for more info:
|
||||
# https://gist.github.com/gabizou/ad570dc09dfed259cac9d74284e78e8b
|
||||
# https://github.com/SpongePowered/SpongeForge/issues/2787
|
||||
#
|
||||
report-null-source-blocks-on-neighbor-notifications=true
|
||||
# If set to 'true', when a mod or plugin attempts to submit a command
|
||||
# asynchronously, Sponge will automatically capture said command
|
||||
# and submit it for processing on the server thread. The catch to
|
||||
# this is that some mods are performing these commands in vanilla
|
||||
# without considering the possible consequences of such commands
|
||||
# affecting any thread-unsafe parts of Minecraft, such as worlds,
|
||||
# block edits, entity spawns, etc. If this is set to false, Sponge
|
||||
# will politely ignore the command being executed, and emit a warning
|
||||
# about said command anyways.
|
||||
resync-commands-from-async=true
|
||||
# If 'true', the phase tracker will print out when there are too many phases
|
||||
# being entered, usually considered as an issue of phase re-entrance and
|
||||
# indicates an unexpected issue of tracking phases not to complete.
|
||||
# If this is not reported yet, please report to Sponge. If it has been
|
||||
# reported, you may disable this.
|
||||
verbose=true
|
||||
# If 'true', the phase tracker will dump extra information about the current phases
|
||||
# when certain non-PhaseTracker related exceptions occur. This is usually not necessary, as the information
|
||||
# in the exception itself can normally be used to determine the cause of the issue
|
||||
verbose-errors=false
|
||||
}
|
||||
commands {
|
||||
# Command aliases will resolve conflicts when multiple plugins request a specific command,
|
||||
# Correct syntax is <unqualified command>=<plugin name> e.g. "sethome=homeplugin"
|
||||
aliases {}
|
||||
# Defines how Sponge should act when a user tries to access a command they do not have
|
||||
# permission for
|
||||
command-hiding {
|
||||
# If this is true, when a user tries to tab complete a command, or use "/sponge which" or
|
||||
# "/sponge:help" this prevents commands a user does not have permission for from being completed.
|
||||
#
|
||||
# Note that some commands may not show up during tab complete if a user does not have permission
|
||||
# regardless of this setting.
|
||||
hide-on-discovery-attempt=true
|
||||
# If this is true, when a user tries to use a command they don't have permission for, Sponge
|
||||
# will act as if the command doesn't exist, rather than showing a no permissions message.
|
||||
hide-on-execution-attempt=false
|
||||
}
|
||||
# Some mods may not trigger a permission check when running their command. Setting this to
|
||||
# true will enforce a check of the Sponge provided permission ("<modid>.command.<commandname>").
|
||||
# Note that setting this to true may cause some commands that are generally accessible to all to
|
||||
# require a permission to run.
|
||||
#
|
||||
# Setting this to true will enable greater control over whether a command will appear in
|
||||
# tab completion and Sponge's help command.
|
||||
#
|
||||
# If you are not using a permissions plugin, it is highly recommended that this is set to false
|
||||
# (as it is by default).
|
||||
enforce-permission-checks-on-non-sponge-commands=false
|
||||
# Patches the specified commands to respect the world of the sender instead of applying the
|
||||
# changes on the all worlds.
|
||||
multi-world-patches {
|
||||
defaultgamemode=true
|
||||
difficulty=true
|
||||
gamerule=true
|
||||
seed=true
|
||||
setdefaultspawnpoint=true
|
||||
time=true
|
||||
toggledownfall=true
|
||||
weather=true
|
||||
worldborder=true
|
||||
}
|
||||
}
|
||||
debug {
|
||||
# Detect and prevent parts of PlayerChunkMap being called off the main thread.
|
||||
# This may decrease sever preformance, so you should only enable it when debugging a specific issue.
|
||||
concurrent-chunk-map-checks=false
|
||||
# Detect and prevent certain attempts to use entities concurrently.
|
||||
# WARNING: May drastically decrease server performance. Only set this to 'true' to debug a pre-existing issue.
|
||||
concurrent-entity-checks=false
|
||||
# If 'true', Java's thread contention monitoring for thread dumps is enabled.
|
||||
thread-contention-monitoring=false
|
||||
}
|
||||
entity {
|
||||
# Number of colliding entities in one spot before logging a warning. Set to 0 to disable
|
||||
collision-warn-size=200
|
||||
# Number of ticks before a painting is respawned on clients when their art is changed
|
||||
entity-painting-respawn-delay=2
|
||||
# Number of ticks before the fake player entry of a human is removed from the tab list (range of 0 to 100 ticks).
|
||||
human-player-list-remove-delay=10
|
||||
# Controls the time in ticks for when an item despawns.
|
||||
item-despawn-rate=6000
|
||||
# The upper bounded range where living entities farther from a player will likely despawn
|
||||
living-hard-despawn-range=128
|
||||
# The amount of seconds before a living entity between the soft and hard despawn ranges from a player to be considered for despawning
|
||||
living-soft-despawn-minimum-life=30
|
||||
# The lower bounded range where living entities near a player may potentially despawn
|
||||
living-soft-despawn-range=32
|
||||
# Maximum size of an entity's bounding box before removing it. Set to 0 to disable
|
||||
max-bounding-box-size=1000
|
||||
# Square of the maximum speed of an entity before removing it. Set to 0 to disable
|
||||
max-speed=100
|
||||
}
|
||||
entity-activation-range {
|
||||
# If 'true', newly discovered entities will be added to this config with a default value.
|
||||
auto-populate=false
|
||||
# Default activation ranges used for all entities unless overridden.
|
||||
defaults {
|
||||
ambient=32
|
||||
aquatic=32
|
||||
creature=32
|
||||
misc=16
|
||||
monster=32
|
||||
}
|
||||
# Per-mod overrides. Refer to the minecraft default mod for example.
|
||||
mods {}
|
||||
}
|
||||
entity-collisions {
|
||||
# If 'true', newly discovered entities/blocks will be added to this config with a default value.
|
||||
auto-populate=false
|
||||
# Maximum amount of entities any given entity or block can collide with. This improves
|
||||
# performance when there are more than 8 entities on top of each other such as a 1x1
|
||||
# spawn pen. Set to 0 to disable.
|
||||
max-entities-within-aabb=8
|
||||
# Per-mod overrides. Refer to the minecraft default mod for example.
|
||||
mods {
|
||||
minecraft {
|
||||
# Default maximum collisions used for all entities unless overridden.
|
||||
defaults {}
|
||||
# If 'false', entity collision rules for this mod will be ignored.
|
||||
enabled=true
|
||||
entities {}
|
||||
}
|
||||
}
|
||||
}
|
||||
exploits {
|
||||
# If limit-book-size is enabled, controls the multiplier applied to each book page size
|
||||
book-size-total-multiplier=0.98
|
||||
# Enables filtering invalid entities when a chunk is being saved
|
||||
# such that the entity that does not "belong" in the saving
|
||||
# chunk will not be saved, and forced an update to the world's
|
||||
# tracked entity lists for chunks.
|
||||
# See https://github.com/PaperMC/Paper/blob/fd1bd5223a461b6d98280bb8f2d67280a30dd24a/Spigot-Server-Patches/0311-Prevent-Saving-Bad-entities-to-chunks.patch
|
||||
filter-invalid-entities-on-chunk-save=true
|
||||
# Limits the size of a book that can be sent by the client.
|
||||
# See https://github.com/PaperMC/Paper/blob/f8058a8187da9f6185d95bb786783e12c79c8b18/Spigot-Server-Patches/0403-Book-Size-Limits.patch
|
||||
# (Only affects SpongeVanilla)
|
||||
limit-book-size=true
|
||||
# Enables focing a chunk load when an entity position
|
||||
# is set. Usually due to teleportation, vehicle movement
|
||||
# etc. can a position lead an entity to no longer exist
|
||||
# within it's currently marked and tracked chunk. This will
|
||||
# enable that chunk for the position is loaded. Part of several
|
||||
# exploits.See https://github.com/PaperMC/Paper/blob/fd1bd5223a461b6d98280bb8f2d67280a30dd24a/Spigot-Server-Patches/0335-Ensure-chunks-are-always-loaded-on-hard-position-set.patch
|
||||
# (Only affects SpongeVanilla)
|
||||
load-chunk-on-position-set=true
|
||||
# Enables forcing chunks to save when an entity is added
|
||||
# or removed from said chunk. This is a partial fix for
|
||||
# some exploits using vehicles.See https://github.com/PaperMC/Paper/blob/fd1bd5223a461b6d98280bb8f2d67280a30dd24a/Spigot-Server-Patches/0306-Mark-chunk-dirty-anytime-entities-change-to-guarante.patch
|
||||
# (Only affects SpongeVanilla)
|
||||
mark-chunks-as-dirty-on-entity-list-modification=true
|
||||
# If limit-book-size is enabled, controls the maximum size of a book page
|
||||
max-book-page-size=2560
|
||||
# Prevents an exploit in which the client sends a packet with the
|
||||
# itemstack name exceeding the string limit.
|
||||
prevent-creative-itemstack-name-exploit=true
|
||||
# Enables forcing updates to the player's location on vehicle movement.
|
||||
# This is partially required to update the server's understanding of
|
||||
# where the player exists, and allows chunk loading issues to be avoided
|
||||
# with laggy connections and/or hack clients.See https://github.com/PaperMC/Paper/blob/fd1bd5223a461b6d98280bb8f2d67280a30dd24a/Spigot-Server-Patches/0378-Sync-Player-Position-to-Vehicles.patch
|
||||
# (Only affects SpongeVanilla)
|
||||
sync-player-positions-for-vehicle-movement=true
|
||||
# Enables forcing a chunk-tracking refresh on entity movement.
|
||||
# This enables a guarantee that the entity is tracked in the
|
||||
# proper chunk when moving.https://github.com/PaperMC/Paper/blob/fd1bd5223a461b6d98280bb8f2d67280a30dd24a/Spigot-Server-Patches/0315-Always-process-chunk-registration-after-moving.patch
|
||||
# (Only affects SpongeVanilla)
|
||||
update-tracked-chunk-on-entity-move=true
|
||||
}
|
||||
general {
|
||||
# If 'true', Sponge will try to ensure that its data is on
|
||||
# disk when saving the 'level_sponge.dat' file, but this
|
||||
# may cause a slight performance hit.
|
||||
#
|
||||
# Setting this to 'false' will mean Sponge does not
|
||||
# perform any consistency checks, but you may end up
|
||||
# with corrupt data if an unexpected failure occurs
|
||||
# on your server, requiring restoring this file from
|
||||
# backup.
|
||||
check-file-when-saving-sponge-data-file=true
|
||||
# The directory for Sponge plugin configurations, relative to the
|
||||
# execution root or specified as an absolute path.
|
||||
# Note that the default: "${CANONICAL_GAME_DIR}/config"
|
||||
# is going to use the "config" directory in the root game directory.
|
||||
# If you wish for plugin configs to reside within a child of the configuration
|
||||
# directory, change the value to, for example, "${CANONICAL_CONFIG_DIR}/sponge/plugins".
|
||||
# Note: It is not recommended to set this to "${CANONICAL_CONFIG_DIR}/sponge", as there is
|
||||
# a possibility that plugin configurations can conflict the Sponge core configurations.
|
||||
#
|
||||
config-dir="${CANONICAL_GAME_DIR}/config"
|
||||
# If 'true', sleeping between chunk saves will be enabled, beware of memory issues.
|
||||
file-io-thread-sleep=false
|
||||
# Additional directory to search for plugins, relative to the
|
||||
# execution root or specified as an absolute path.
|
||||
# Note that the default: "${CANONICAL_MODS_DIR}/plugins"
|
||||
# is going to search for a plugins folder in the mods directory.
|
||||
# If you wish for the plugins folder to reside in the root game
|
||||
# directory, change the value to "${CANONICAL_GAME_DIR}/plugins".
|
||||
plugins-dir="${CANONICAL_MODS_DIR}/plugins"
|
||||
}
|
||||
ip-sets {}
|
||||
logging {
|
||||
# Log when blocks are broken
|
||||
block-break=false
|
||||
# Log when blocks are modified
|
||||
block-modify=false
|
||||
# Log when blocks are placed
|
||||
block-place=false
|
||||
# Log when blocks are populated in a chunk
|
||||
block-populate=false
|
||||
# Log when blocks are placed by players and tracked
|
||||
block-tracking=false
|
||||
# Log when chunks are queued to be unloaded by the chunk garbage collector.
|
||||
chunk-gc-queue-unload=false
|
||||
# Log when chunks are loaded
|
||||
chunk-load=false
|
||||
# Log when chunks are unloaded
|
||||
chunk-unload=false
|
||||
# Whether to log entity collision/count checks
|
||||
entity-collision-checks=false
|
||||
# Log when living entities are destroyed
|
||||
entity-death=false
|
||||
# Log when living entities are despawned
|
||||
entity-despawn=false
|
||||
# Log when living entities are spawned
|
||||
entity-spawn=false
|
||||
# Whether to log entity removals due to speed
|
||||
entity-speed-removal=false
|
||||
# Log when server receives exploited packet with itemstack name exceeding string limit.
|
||||
exploit-itemstack-name-overflow=false
|
||||
# Log when player attempts to respawn invisible to surrounding players.
|
||||
exploit-respawn-invisibility=false
|
||||
# Log when server receives exploited packet to update a sign containing commands from player with no permission.
|
||||
exploit-sign-command-updates=false
|
||||
# Add stack traces to dev logging
|
||||
log-stacktraces=false
|
||||
# Log when a world auto-saves its chunk data. Note: This may be spammy depending on the auto-save-interval configured for world.
|
||||
world-auto-save=false
|
||||
}
|
||||
metrics {
|
||||
# The global collection state that should be respected by all plugins that have no specified collection state. If undefined then it is treated as disabled.
|
||||
global-state=UNDEFINED
|
||||
# Plugin-specific collection states that override the global collection state.
|
||||
plugin-states {}
|
||||
}
|
||||
modules {
|
||||
# Enables experimental fixes for broken mods
|
||||
broken-mod=false
|
||||
bungeecord=true
|
||||
entity-activation-range=true
|
||||
entity-collisions=true
|
||||
# Controls whether any exploit patches are applied.
|
||||
# If there are issues with any specific exploits, please
|
||||
# test in the exploit category first, before disabling all
|
||||
# exploits with this toggle.
|
||||
exploits=true
|
||||
# Allows configuring Vanilla movement and speed checks
|
||||
movement-checks=false
|
||||
optimizations=true
|
||||
# Use real (wall) time instead of ticks as much as possible
|
||||
realtime=false
|
||||
# Controls block range and tick rate of tileentities.
|
||||
# Use with caution as this can break intended functionality.
|
||||
tileentity-activation=false
|
||||
timings=true
|
||||
tracking=true
|
||||
}
|
||||
movement-checks {
|
||||
# Controls whether the 'player/entity moved wrongly!' check will be enforced
|
||||
moved-wrongly=true
|
||||
# Controls whether the 'player moved too quickly!' check will be enforced
|
||||
player-moved-too-quickly=true
|
||||
# Controls whether the 'vehicle of player moved too quickly!' check will be enforced
|
||||
player-vehicle-moved-too-quickly=true
|
||||
}
|
||||
optimizations {
|
||||
# Runs lighting updates asynchronously.
|
||||
async-lighting {
|
||||
# If 'true', lighting updates are run asynchronously.
|
||||
enabled=true
|
||||
# The amount of threads to dedicate for asynchronous lighting updates. (Default: 2)
|
||||
num-threads=2
|
||||
}
|
||||
# Caches tameable entities owners to avoid constant lookups against data watchers. If mods
|
||||
# cause issues, disable this.
|
||||
cache-tameable-owners=true
|
||||
# Occasionally, some built in advancements,
|
||||
# recipes, etc. can fail to deserialize properly
|
||||
# which ends up potentially spamming the server log
|
||||
# and the original provider of the failing content
|
||||
# is not able to fix. This provides an option to
|
||||
# suppress the exceptions printing out in the log.
|
||||
disable-failing-deserialization-log-spam=true
|
||||
# If 'true', block item drops are pre-processed to avoid
|
||||
# having to spawn extra entities that will be merged post spawning.
|
||||
# Usually, Sponge is smart enough to determine when to attempt an item pre-merge
|
||||
# and when not to, however, in certain cases, some mods rely on items not being
|
||||
# pre-merged and actually spawned, in which case, the items will flow right through
|
||||
# without being merged.
|
||||
drops-pre-merge=true
|
||||
# Uses theosib's redstone algorithms to completely overhaul the way redstone works.
|
||||
eigen-redstone {
|
||||
# If 'true', uses theosib's redstone implementation which improves performance.
|
||||
# See https://bugs.mojang.com/browse/MC-11193 and
|
||||
# https://bugs.mojang.com/browse/MC-81098 for more information.
|
||||
# Note: We cannot guarantee compatibility with mods. Use at your discretion.
|
||||
enabled=false
|
||||
# If 'true', restores the vanilla algorithm for computing wire power levels when powering off.
|
||||
vanilla-decrement=false
|
||||
# If 'true', restores the vanilla algorithm for propagating redstone wire changes.
|
||||
vanilla-search=false
|
||||
}
|
||||
# If 'true', provides a fix for possible leaks through
|
||||
# Minecraft's enchantment helper code that can leak
|
||||
# entity and world references without much interaction
|
||||
# Forge native (so when running SpongeForge implementation)
|
||||
# has a similar patch, but Sponge's patch works a little harder
|
||||
# at it, but Vanilla (SpongeVanilla implementation) does NOT
|
||||
# have any of the patch, leading to the recommendation that this
|
||||
# patch is enabled "for sure" when using SpongeVanilla implementation.
|
||||
# See https://bugs.mojang.com/browse/MC-128547 for more information.
|
||||
#
|
||||
enchantment-helper-leak-fix=true
|
||||
# If 'true', allows for Sponge to make better assumptinos on single threaded
|
||||
# operations with relation to various checks for server threaded operations.
|
||||
# This is default to true due to Sponge being able to precisely inject when
|
||||
# the server thread is available. This should make an already fast operation
|
||||
# much faster for better thread checks to ensure stability of sponge's systems.
|
||||
faster-thread-checks=true
|
||||
# If 'true', re-writes the incredibly inefficient Vanilla Map code.
|
||||
# This yields enormous performance enhancements when using many maps, but has a tiny chance of breaking mods that invasively modify Vanilla.It is strongly reccomended to keep this on, unless explicitly advised otherwise by a Sponge developer
|
||||
map-optimization=true
|
||||
# Based on Aikar's optimizationo of Hoppers, setting this to 'true'
|
||||
# will allow for hoppers to save performing server -> client updates
|
||||
# when transferring items. Because hoppers can transfer items multiple
|
||||
# times per tick, these updates can get costly on the server, with
|
||||
# little to no benefit to the client. Because of the nature of the
|
||||
# change, the default will be 'false' due to the inability to pre-emptively
|
||||
# foretell whether mod compatibility will fail with these changes or not.
|
||||
# Refer to: https://github.com/PaperMC/Paper/blob/8175ec916f31dcd130fe0884fe46bdc187d829aa/Spigot-Server-Patches/0269-Optimize-Hoppers.patch
|
||||
# for more details.
|
||||
optimize-hoppers=false
|
||||
# If 'true', uses Panda4494's redstone implementation which improves performance.
|
||||
# See https://bugs.mojang.com/browse/MC-11193 for more information.
|
||||
# Note: This optimization has a few issues which are explained in the bug report.
|
||||
# We strongly recommend using eigen redstone over this implementation as this will
|
||||
# be removed in a future release.
|
||||
panda-redstone=false
|
||||
# Handles structures that are saved to disk. Certain structures can take up large amounts
|
||||
# of disk space for very large maps and the data for these structures is only needed while the
|
||||
# world around them is generating. Disabling saving of these structures can save disk space and
|
||||
# time during saves if your world is already fully generated.
|
||||
# Warning: disabling structure saving will break the vanilla locate command.
|
||||
structure-saving {
|
||||
# If 'true', newly discovered structures will be added to this config
|
||||
# with a default value of 'true'. This is useful for finding out
|
||||
# potentially what structures are being saved from various mods, and
|
||||
# allowing those structures to be selectively disabled.
|
||||
auto-populate=false
|
||||
# If 'false', disables the modification to prevent certain structures
|
||||
# from saving to the world's data folder. If you wish to prevent certain
|
||||
# structures from saving, leave this "enabled=true". When 'true', the
|
||||
# modification allows for specific 'named' structures to NOT be saved to
|
||||
# disk. Examples of some structures that are costly and somewhat irrelivent
|
||||
# is 'mineshaft's, as they build several structures and save, even after
|
||||
# finished generating.
|
||||
enabled=false
|
||||
# Per-mod overrides. Refer to the minecraft default mod for example.
|
||||
mods {
|
||||
minecraft {
|
||||
# If 'false', this mod will never save its structures. This may
|
||||
# break some mod functionalities when requesting to locate their
|
||||
# structures in a World. If true, allows structures not overridden
|
||||
# in the section below to be saved by default. If you wish to find
|
||||
# a structure to prevent it being saved, enable 'auto-populate' and
|
||||
# restart the server/world instance.
|
||||
enabled=true
|
||||
# Per structure override. Having the value of 'false' will prevent
|
||||
# that specific named structure from saving.
|
||||
structures {
|
||||
mineshaft=false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
# Vanilla performs a lot of is area loaded checks during
|
||||
# entity collision calculations with blocks, and because
|
||||
# these calculations require fetching the chunks to see
|
||||
# if they are loaded, before getting the block states
|
||||
# from those chunks, there can be some small performance
|
||||
# increase by checking the entity's owned active chunk
|
||||
# it may currently reside in. Essentially, instead of
|
||||
# asking the world if those chunks are loaded, the entity
|
||||
# would know whether it's chunks are loaded and that neighbor's
|
||||
# chunks are loaded.
|
||||
use-active-chunks-for-collisions=false
|
||||
}
|
||||
permission {
|
||||
# If 'true', Sponge plugins will be used to handle permissions rather than any Forge mod
|
||||
forge-permissions-handler=false
|
||||
}
|
||||
player-block-tracker {
|
||||
# Block IDs that will be blacklisted for player block placement tracking.
|
||||
block-blacklist=[]
|
||||
# If 'true', adds player tracking support for block positions.
|
||||
# Note: This should only be disabled if you do not care who caused a block to change.
|
||||
enabled=true
|
||||
}
|
||||
# Used to control spawn limits around players.
|
||||
# Note: The radius uses the lower value of mob spawn range and server's view distance.
|
||||
spawner {
|
||||
# The number of ambients the spawner can potentially spawn around a player.
|
||||
spawn-limit-ambient=15
|
||||
# The number of animals the spawner can potentially spawn around a player.
|
||||
spawn-limit-animal=15
|
||||
# The number of aquatics the spawner can potentially spawn around a player.
|
||||
spawn-limit-aquatic=5
|
||||
# The number of monsters the spawner can potentially spawn around a player.
|
||||
spawn-limit-monster=70
|
||||
# The ambient spawning tick rate. Default: 400
|
||||
tick-rate-ambient=400
|
||||
# The animal spawning tick rate. Default: 400
|
||||
tick-rate-animal=400
|
||||
# The aquatic spawning tick rate. Default: 1
|
||||
tick-rate-aquatic=1
|
||||
# The monster spawning tick rate. Default: 1
|
||||
tick-rate-monster=1
|
||||
}
|
||||
# Configuration options related to the Sql service, including connection aliases etc
|
||||
sql {
|
||||
# Aliases for SQL connections, in the format jdbc:protocol://[username[:password]@]host/database
|
||||
aliases {}
|
||||
}
|
||||
# Blocks to blacklist for safe teleportation.
|
||||
teleport-helper {
|
||||
# If 'true', this blacklist will always be respected, otherwise, plugins can choose whether
|
||||
# or not to respect it.
|
||||
force-blacklist=false
|
||||
# Block IDs that are listed here will not be selected by Sponge's safe teleport routine as
|
||||
# a safe block for players to warp into.
|
||||
# You should only list blocks here that are incorrectly selected, solid blocks that prevent
|
||||
# movement are automatically excluded.
|
||||
unsafe-body-block-ids=[]
|
||||
# Block IDs that are listed here will not be selected by Sponge's safe
|
||||
# teleport routine as a safe floor block.
|
||||
unsafe-floor-block-ids=[]
|
||||
}
|
||||
tileentity-activation {
|
||||
# If 'true', newly discovered tileentities will be added to this config with default settings.
|
||||
auto-populate=false
|
||||
# Default activation block range used for all tileentities unless overridden.
|
||||
default-block-range=64
|
||||
# Default tick rate used for all tileentities unless overridden.
|
||||
default-tick-rate=1
|
||||
# Per-mod overrides. Refer to the minecraft default mod for example.
|
||||
mods {}
|
||||
}
|
||||
timings {
|
||||
enabled=true
|
||||
hidden-config-entries=[
|
||||
"sponge.sql"
|
||||
]
|
||||
history-interval=300
|
||||
history-length=3600
|
||||
server-name-privacy=false
|
||||
verbose=false
|
||||
}
|
||||
world {
|
||||
# The auto-save tick interval used when saving global player data. (Default: 900)
|
||||
# Note: 20 ticks is equivalent to 1 second. Set to 0 to disable.
|
||||
auto-player-save-interval=900
|
||||
# The auto-save tick interval used to save all loaded chunks in a world.
|
||||
# Set to 0 to disable. (Default: 900)
|
||||
# Note: 20 ticks is equivalent to 1 second.
|
||||
auto-save-interval=900
|
||||
# The number of newly loaded chunks before triggering a forced cleanup.
|
||||
# Note: When triggered, the loaded chunk threshold will reset and start incrementing.
|
||||
# Disabled by default.
|
||||
chunk-gc-load-threshold=0
|
||||
# The tick interval used to cleanup all inactive chunks that have leaked in a world.
|
||||
# Set to 0 to disable which restores vanilla handling. (Default: 600)
|
||||
chunk-gc-tick-interval=600
|
||||
# The number of seconds to delay a chunk unload once marked inactive. (Default: 15)
|
||||
# Note: This gets reset if the chunk becomes active again.
|
||||
chunk-unload-delay=15
|
||||
# If 'true', any request for a chunk not currently loaded will be denied (exceptions apply
|
||||
# for things like world gen and player movement).
|
||||
# Warning: As this is an experimental setting for performance gain, if you encounter any issues
|
||||
# then we recommend disabling it.
|
||||
deny-chunk-requests=true
|
||||
# The interval, in seconds, used by the GameProfileQueryTask to process queued GameProfile requests. (Default: 4)
|
||||
# Note: This setting should be raised if you experience the following error:
|
||||
# "The client has sent too many requests within a certain amount of time".
|
||||
# Finally, if set to 0 or less, the default interval will be used.
|
||||
gameprofile-lookup-task-interval=4
|
||||
# If 'true', this world will generate its spawn the moment its loaded.
|
||||
generate-spawn-on-load=false
|
||||
# The list of uuid's that should never perform a lookup against Mojang's session server.
|
||||
# Note: If you are using SpongeForge, make sure to enter any mod fake player's UUID to this list.
|
||||
invalid-lookup-uuids=[
|
||||
"00000000-0000-0000-0000-000000000000",
|
||||
"0d0c4ca0-4ff1-11e4-916c-0800200c9a66",
|
||||
"41c82c87-7afb-4024-ba57-13d2c99cae77"
|
||||
]
|
||||
# The defined merge radius for Item entities such that when two items are
|
||||
# within the defined radius of each other, they will attempt to merge. Usually,
|
||||
# the default radius is set to 0.5 in Vanilla, however, for performance reasons
|
||||
# 2.5 is generally acceptable.
|
||||
# Note: Increasing the radius higher will likely cause performance degradation
|
||||
# with larger amount of items as they attempt to merge and search nearby
|
||||
# areas for more items. Setting to a negative value is not supported!
|
||||
item-merge-radius=2.5
|
||||
# If 'true', this worlds spawn will remain loaded with no players.
|
||||
keep-spawn-loaded=true
|
||||
# If 'true', natural leaf decay is allowed.
|
||||
leaf-decay=true
|
||||
# If 'true', this world will load on startup.
|
||||
load-on-startup=false
|
||||
# The maximum number of queued unloaded chunks that will be unloaded in a single tick.
|
||||
# Note: With the chunk gc enabled, this setting only applies to the ticks
|
||||
# where the gc runs (controlled by 'chunk-gc-tick-interval')
|
||||
# Note: If the maximum unloads is too low, too many chunks may remain
|
||||
# loaded on the world and increases the chance for a drop in tps. (Default: 100)
|
||||
max-chunk-unloads-per-tick=100
|
||||
# Specifies the radius (in chunks) of where creatures will spawn.
|
||||
# This value is capped to the current view distance setting in server.properties
|
||||
mob-spawn-range=4
|
||||
# A list of all detected portal agents used in this world.
|
||||
# In order to override, change the target world name to any other valid world.
|
||||
# Note: If world is not found, it will fallback to default.
|
||||
portal-agents {
|
||||
"minecraft:default_the_end"=DIM1
|
||||
"minecraft:default_the_nether"=DIM-1
|
||||
}
|
||||
# If 'true', this world will allow PVP combat.
|
||||
pvp-enabled=true
|
||||
# Override world distance per world/dimension
|
||||
# The value must be greater than or equal to 3 and less than or equal to 32
|
||||
# The server-wide view distance will be used when the value is -1.
|
||||
view-distance=-1
|
||||
# If 'true', natural formation of ice and snow in supported biomes will be allowed.
|
||||
weather-ice-and-snow=true
|
||||
# If 'true', thunderstorms will be initiated in supported biomes.
|
||||
weather-thunder=true
|
||||
# If 'true', this world will be registered.
|
||||
world-enabled=true
|
||||
}
|
||||
# World Generation Modifiers to apply to the world
|
||||
world-generation-modifiers=[]
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
# 1.0
|
||||
#
|
||||
# # If you need help with the configuration or have any questions related to Sponge,
|
||||
# # join us at the IRC or drop by our forums and leave a post.
|
||||
#
|
||||
# # IRC: #sponge @ irc.esper.net ( https://webchat.esper.net/?channel=sponge )
|
||||
# # Forums: https://forums.spongepowered.org/
|
||||
#
|
||||
|
||||
sponge {
|
||||
block {
|
||||
# If 'true', newly discovered blocks will be added to this config with default settings.
|
||||
auto-populate=false
|
||||
# Per-mod block id mappings for controlling tracking behavior
|
||||
mods {
|
||||
extrautils2 {
|
||||
# Set to true to perform block bulk capturing during block ticks. (Default: true)
|
||||
block-bulk-capture {
|
||||
redstoneclock=false
|
||||
}
|
||||
# Set to true to create and fire block events during block ticks. (Default: true)
|
||||
block-event-creation {}
|
||||
# If 'false', all tracking for this mod will be ignored.
|
||||
enabled=true
|
||||
# Set to true to create and fire entity events during block ticks. (Default: true)
|
||||
entity-block-creation {}
|
||||
# Set to true to perform entity bulk capturing during block ticks. (Default: true)
|
||||
entity-bulk-capture {}
|
||||
}
|
||||
minecraft {
|
||||
# Set to true to perform block bulk capturing during block ticks. (Default: true)
|
||||
block-bulk-capture {}
|
||||
# Set to true to create and fire block events during block ticks. (Default: true)
|
||||
block-event-creation {}
|
||||
# If 'false', all tracking for this mod will be ignored.
|
||||
enabled=true
|
||||
# Set to true to create and fire entity events during block ticks. (Default: true)
|
||||
entity-block-creation {}
|
||||
# Set to true to perform entity bulk capturing during block ticks. (Default: true)
|
||||
entity-bulk-capture {}
|
||||
}
|
||||
}
|
||||
}
|
||||
entity {
|
||||
# If 'true', newly discovered entities will be added to this config with default settings.
|
||||
auto-populate=false
|
||||
# Per-mod entity id mappings for controlling tracking behavior
|
||||
mods {
|
||||
minecraft {
|
||||
# Set to true to perform block bulk capturing during entity ticks. (Default: true)
|
||||
block-bulk-capture {
|
||||
"armor_stand"=false
|
||||
"experience_orb"=false
|
||||
item=false
|
||||
"leash_hitch"=false
|
||||
"llama_spit"=false
|
||||
painting=false
|
||||
}
|
||||
# Set to true to create and fire block events during entity ticks. (Default: true)
|
||||
block-event-creation {}
|
||||
# If 'false', all tracking for this mod will be ignored.
|
||||
enabled=true
|
||||
# Set to true to create and fire entity events during entity ticks. (Default: true)
|
||||
entity-block-creation {}
|
||||
# Set to true to perform entity bulk capturing during entity ticks. (Default: true)
|
||||
entity-bulk-capture {}
|
||||
}
|
||||
}
|
||||
}
|
||||
tileentity {
|
||||
# If 'true', newly discovered tileentities will be added to this config with default settings.
|
||||
auto-populate=false
|
||||
# Per-mod tileentity id mappings for controlling tracking behavior
|
||||
mods {}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
# 1.0
|
||||
#
|
||||
# # If you need help with the configuration or have any questions related to Sponge,
|
||||
# # join us at the IRC or drop by our forums and leave a post.
|
||||
#
|
||||
# # IRC: #sponge @ irc.esper.net ( https://webchat.esper.net/?channel=sponge )
|
||||
# # Forums: https://forums.spongepowered.org/
|
||||
#
|
||||
|
||||
sponge {
|
||||
world {
|
||||
# If 'true', this world will load on startup.
|
||||
load-on-startup=true
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
# 1.0
|
||||
#
|
||||
# # If you need help with the configuration or have any questions related to Sponge,
|
||||
# # join us at the IRC or drop by our forums and leave a post.
|
||||
#
|
||||
# # IRC: #sponge @ irc.esper.net ( https://webchat.esper.net/?channel=sponge )
|
||||
# # Forums: https://forums.spongepowered.org/
|
||||
#
|
||||
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
# 1.0
|
||||
#
|
||||
# # If you need help with the configuration or have any questions related to Sponge,
|
||||
# # join us at the IRC or drop by our forums and leave a post.
|
||||
#
|
||||
# # IRC: #sponge @ irc.esper.net ( https://webchat.esper.net/?channel=sponge )
|
||||
# # Forums: https://forums.spongepowered.org/
|
||||
#
|
||||
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
# 1.0
|
||||
#
|
||||
# # If you need help with the configuration or have any questions related to Sponge,
|
||||
# # join us at the IRC or drop by our forums and leave a post.
|
||||
#
|
||||
# # IRC: #sponge @ irc.esper.net ( https://webchat.esper.net/?channel=sponge )
|
||||
# # Forums: https://forums.spongepowered.org/
|
||||
#
|
||||
|
||||
sponge {
|
||||
world {
|
||||
# If 'true', this world will load on startup.
|
||||
load-on-startup=true
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
# 1.0
|
||||
#
|
||||
# # If you need help with the configuration or have any questions related to Sponge,
|
||||
# # join us at the IRC or drop by our forums and leave a post.
|
||||
#
|
||||
# # IRC: #sponge @ irc.esper.net ( https://webchat.esper.net/?channel=sponge )
|
||||
# # Forums: https://forums.spongepowered.org/
|
||||
#
|
||||
|
||||
|
||||
@@ -0,0 +1,132 @@
|
||||
# Thanks for downloading ViaVersion
|
||||
# Ensure you look through all these options
|
||||
# If you need help:
|
||||
# Discord - https://viaversion.com/discord
|
||||
# viaversion.com - Discussion tab
|
||||
# Docs - https://docs.viaversion.com/display/VIAVERSION/Configuration
|
||||
#
|
||||
# ----------------------------------------------------------#
|
||||
# GLOBAL OPTIONS #
|
||||
# ----------------------------------------------------------#
|
||||
#
|
||||
# Should ViaVersion check for updates?
|
||||
checkforupdates: true
|
||||
# Send the supported versions with the Status (Ping) response packet
|
||||
send-supported-versions: false
|
||||
# Block specific Minecraft protocols that ViaVersion allows
|
||||
# List of all Minecraft protocol versions: http://wiki.vg/Protocol_version_numbers or use a generator: https://via.krusic22.com
|
||||
block-protocols: []
|
||||
# Change the blocked disconnect message
|
||||
block-disconnect-msg: You are using an unsupported Minecraft version!
|
||||
# If you use ProtocolLib, we can't reload without kicking the players.
|
||||
# (We don't suggest using reload either, use a plugin manager)
|
||||
# You can customise the message we kick people with if you use ProtocolLib here.
|
||||
reload-disconnect-msg: Server reload, please rejoin!
|
||||
# We warn when there's a error converting item and block data over versions, should we suppress these? (Only suggested if spamming)
|
||||
suppress-conversion-warnings: false
|
||||
#
|
||||
# ----------------------------------------------------------#
|
||||
# GLOBAL PACKET LIMITER #
|
||||
# ----------------------------------------------------------#
|
||||
#
|
||||
#
|
||||
# Packets Per Second (PPS) limiter (Use -1 on max-pps and tracking-period to disable)
|
||||
# Clients by default send around 20-90 packets per second.
|
||||
#
|
||||
# What is the maximum per second a client can send (Use %pps to display their pps)
|
||||
# Use -1 to disable.
|
||||
max-pps: 800
|
||||
max-pps-kick-msg: You are sending too many packets!
|
||||
#
|
||||
# We can also kick them if over a period they send over a threshold a certain amount of times.
|
||||
#
|
||||
# Period to track (in seconds)
|
||||
# Use -1 to disable.
|
||||
tracking-period: 6
|
||||
# How many packets per second counts as a warning
|
||||
tracking-warning-pps: 120
|
||||
# How many warnings over the interval can we have
|
||||
# This can never be higher than "tracking-period"
|
||||
tracking-max-warnings: 4
|
||||
tracking-max-kick-msg: You are sending too many packets, :(
|
||||
#
|
||||
# ----------------------------------------------------------#
|
||||
# MULTIPLE VERSIONS OPTIONS #
|
||||
# ----------------------------------------------------------#
|
||||
#
|
||||
# Should we enable our hologram patch?
|
||||
# If they're in the wrong place enable this
|
||||
hologram-patch: false
|
||||
# This is the offset, should work as default when enabled.
|
||||
hologram-y: -0.96
|
||||
# Should we disable piston animation for 1.11/1.11.1 clients?
|
||||
# In some cases when firing lots of pistons it crashes them.
|
||||
piston-animation-patch: false
|
||||
# Should we fix nbt for 1.12 and above clients in chat messages (causes invalid item)
|
||||
chat-nbt-fix: true
|
||||
# Should we use prefix for team colour on 1.13 and above clients
|
||||
team-colour-fix: true
|
||||
# 1.13 introduced new auto complete which can trigger "Kicked for spamming" for servers older than 1.13, the following option will disable it completely.
|
||||
disable-1_13-auto-complete: false
|
||||
# The following option will delay the tab complete request in x ticks if greater than 0, if other tab-complete is received, the previous is cancelled
|
||||
1_13-tab-complete-delay: 0
|
||||
# For 1.13 clients the smallest (1 layer) snow doesn't have collision, this will send these as 2 snowlayers for 1.13+ clients to prevent them bugging through them
|
||||
fix-low-snow-collision: false
|
||||
# Infested blocks are instantly breakable for 1.13+ clients, resulting in them being unable to break them on sub 1.13 servers. This remaps them to their normal stone variants
|
||||
fix-infested-block-breaking: true
|
||||
# In 1.14 the client page limit has been upped to 100 (from 50). Some anti-exploit plugins ban when clients go higher than 50. This option cuts edited books to 50 pages.
|
||||
truncate-1_14-books: false
|
||||
# Fixes 1.14+ clients on sub 1.14 servers having a light value of 0 for non full blocks.
|
||||
fix-non-full-blocklight: true
|
||||
# Fixes walk animation not shown when health is set to Float.NaN
|
||||
fix-1_14-health-nan: true
|
||||
# Should 1.15+ clients respawn instantly / without showing a death screen?
|
||||
use-1_15-instant-respawn: false
|
||||
#
|
||||
# Enable serverside block-connections for 1.13+ clients - all of the options in this section are built around this option
|
||||
serverside-blockconnections: true
|
||||
# When activated, only the most important blocks are stored in the blockstorage. (fences, glass panes etc. won't connect to solid blocks)
|
||||
reduce-blockstorage-memory: false
|
||||
# When activated with serverside-blockconnections, flower parts with blocks above will be sent as stems
|
||||
# Useful for lobbyservers where users can't build and those stems are used decoratively
|
||||
flowerstem-when-block-above: false
|
||||
# Vines that are not connected to blocks will be mapped to air, else 1.13+ would still be able to climb up on them.
|
||||
vine-climb-fix: false
|
||||
#
|
||||
# ----------------------------------------------------------#
|
||||
# 1.9+ CLIENTS ON 1.8 SERVERS OPTIONS #
|
||||
# ----------------------------------------------------------#
|
||||
#
|
||||
# No collide options, these allow you to configure how collision works.
|
||||
# Do you want us to prevent collision?
|
||||
prevent-collision: true
|
||||
# If the above is true, should we automatically team players until you do?
|
||||
auto-team: true
|
||||
# When enabled if certain metadata can't be read we won't tell you about it
|
||||
suppress-metadata-errors: false
|
||||
# When enabled 1.9+ will be able to block by using shields
|
||||
shield-blocking: true
|
||||
# Enable player tick simulation, this fixes eating, drinking, nether portals.
|
||||
simulate-pt: true
|
||||
# Should we use nms player to simulate packets, (may fix anti-cheat issues)
|
||||
nms-player-ticking: true
|
||||
# Should we patch boss bars so they work? (Default: true, disable if you're having issues)
|
||||
bossbar-patch: true
|
||||
# If your boss bar flickers on 1.9+, set this to 'true'. It will keep all boss bars on 100% (not recommended)
|
||||
bossbar-anti-flicker: false
|
||||
# This will show the new effect indicator in the top-right corner for 1.9+ players.
|
||||
use-new-effect-indicator: true
|
||||
# Show the new death messages for 1.9+ on the death screen
|
||||
use-new-deathmessages: true
|
||||
# Should we cache our items, this will prevent server from being lagged out, however the cost is a constant task caching items
|
||||
item-cache: true
|
||||
# Should we replace extended pistons to fix 1.10.1 (Only on chunk load)
|
||||
replace-pistons: false
|
||||
# What id should we replace with, default is air. (careful of players getting stuck standing on them)
|
||||
replacement-piston-id: 0
|
||||
# Force the string -> json transform
|
||||
force-json-transform: false
|
||||
# Minimize the cooldown animation in 1.8 servers
|
||||
minimize-cooldown: true
|
||||
# Left handed handling on 1.8 servers
|
||||
left-handed-handling: true
|
||||
@@ -0,0 +1,4 @@
|
||||
#By changing the setting below to TRUE you are indicating your agreement to our EULA (https://account.mojang.com/documents/minecraft_eula).
|
||||
#You also agree that tacos are tasty, and the best food in the world.
|
||||
#Tue Jun 16 08:43:06 EDT 2020
|
||||
eula=true
|
||||
@@ -1,56 +0,0 @@
|
||||
# This is the help configuration file for Bukkit.
|
||||
#
|
||||
# By default you do not need to modify this file. Help topics for all plugin commands are automatically provided by
|
||||
# or extracted from your installed plugins. You only need to modify this file if you wish to add new help pages to
|
||||
# your server or override the help pages of existing plugin commands.
|
||||
#
|
||||
# This file is divided up into the following parts:
|
||||
# -- general-topics: lists admin defined help topics
|
||||
# -- index-topics: lists admin defined index topics
|
||||
# -- amend-topics: lists topic amendments to apply to existing help topics
|
||||
# -- ignore-plugins: lists any plugins that should be excluded from help
|
||||
#
|
||||
# Examples are given below. When amending command topic, the string <text> will be replaced with the existing value
|
||||
# in the help topic. Color codes can be used in topic text. The color code character is & followed by 0-F.
|
||||
# ================================================================
|
||||
#
|
||||
# Set this to true to list the individual command help topics in the master help.
|
||||
# command-topics-in-master-index: true
|
||||
#
|
||||
# Each general topic will show up as a separate topic in the help index along with all the plugin command topics.
|
||||
# general-topics:
|
||||
# Rules:
|
||||
# shortText: Rules of the server
|
||||
# fullText: |
|
||||
# &61. Be kind to your fellow players.
|
||||
# &B2. No griefing.
|
||||
# &D3. No swearing.
|
||||
# permission: topics.rules
|
||||
#
|
||||
# Each index topic will show up as a separate sub-index in the help index along with all the plugin command topics.
|
||||
# To override the default help index (displayed when the user executes /help), name the index topic "Default".
|
||||
# index-topics:
|
||||
# Ban Commands:
|
||||
# shortText: Player banning commands
|
||||
# preamble: Moderator - do not abuse these commands
|
||||
# permission: op
|
||||
# commands:
|
||||
# - /ban
|
||||
# - /ban-ip
|
||||
# - /banlist
|
||||
#
|
||||
# Topic amendments are used to change the content of automatically generated plugin command topics.
|
||||
# amended-topics:
|
||||
# /stop:
|
||||
# shortText: Stops the server cold....in its tracks!
|
||||
# fullText: <text> - This kills the server.
|
||||
# permission: you.dont.have
|
||||
#
|
||||
# Any plugin in the ignored plugins list will be excluded from help. The name must match the name displayed by
|
||||
# the /plugins command. Ignore "Bukkit" to remove the standard bukkit commands from the index. Ignore "All"
|
||||
# to completely disable automatic help topic generation.
|
||||
# ignore-plugins:
|
||||
# - PluginNameOne
|
||||
# - PluginNameTwo
|
||||
# - PluginNameThree
|
||||
|
||||
Binary file not shown.
File renamed without changes.
Symlink
+1
@@ -0,0 +1 @@
|
||||
../../../universal/build/libs/nuvotifier.jar
|
||||
+1
-1
@@ -1 +1 @@
|
||||
../resources/paper.jar
|
||||
../resources/sponge.jar
|
||||
@@ -1,178 +0,0 @@
|
||||
# This is the main configuration file for Paper.
|
||||
# As you can see, there's tons to configure. Some options may impact gameplay, so use
|
||||
# with caution, and make sure you know what each option does before configuring.
|
||||
#
|
||||
# If you need help with the configuration or have any questions related to Paper,
|
||||
# join us in our Discord or IRC channel.
|
||||
#
|
||||
# Discord: https://paperdiscord.emc.gs
|
||||
# IRC: #paper @ irc.spi.gt ( http://irc.spi.gt/iris/?channels=paper )
|
||||
# Website: https://papermc.io/
|
||||
# Docs: https://paper.readthedocs.org/
|
||||
|
||||
verbose: false
|
||||
config-version: 16
|
||||
settings:
|
||||
load-permissions-yml-before-plugins: true
|
||||
bungee-online-mode: true
|
||||
incoming-packet-spam-threshold: 300
|
||||
use-versioned-world: false
|
||||
velocity-support:
|
||||
enabled: false
|
||||
online-mode: false
|
||||
secret: ''
|
||||
queue-light-updates-max-loss: 10
|
||||
suggest-player-names-when-null-tab-completions: true
|
||||
watchdog:
|
||||
early-warning-every: 5000
|
||||
early-warning-delay: 10000
|
||||
spam-limiter:
|
||||
tab-spam-increment: 1
|
||||
tab-spam-limit: 500
|
||||
save-player-data: true
|
||||
sleep-between-chunk-saves: false
|
||||
region-file-cache-size: 256
|
||||
save-empty-scoreboard-teams: false
|
||||
book-size:
|
||||
page-max: 2560
|
||||
total-multiplier: 0.98
|
||||
enable-player-collisions: true
|
||||
player-auto-save-rate: -1
|
||||
max-player-auto-save-per-tick: -1
|
||||
async-chunks:
|
||||
enable: true
|
||||
generation: true
|
||||
thread-per-world-generation: true
|
||||
load-threads: -1
|
||||
use-alternative-luck-formula: false
|
||||
messages:
|
||||
no-permission: '&cI''m sorry, but you do not have permission to perform this command.
|
||||
Please contact the server administrators if you believe that this is in error.'
|
||||
kick:
|
||||
authentication-servers-down: ''
|
||||
connection-throttle: Connection throttled! Please wait before reconnecting.
|
||||
flying-player: Flying is not enabled on this server
|
||||
flying-vehicle: Flying is not enabled on this server
|
||||
timings:
|
||||
enabled: true
|
||||
verbose: true
|
||||
server-name-privacy: false
|
||||
hidden-config-entries:
|
||||
- database
|
||||
- settings.bungeecord-addresses
|
||||
history-interval: 300
|
||||
history-length: 3600
|
||||
world-settings:
|
||||
default:
|
||||
portal-search-radius: 128
|
||||
game-mechanics:
|
||||
villages-load-chunks: false
|
||||
scan-for-legacy-ender-dragon: true
|
||||
disable-chest-cat-detection: false
|
||||
disable-end-credits: false
|
||||
disable-player-crits: false
|
||||
disable-sprint-interruption-on-attack: false
|
||||
shield-blocking-delay: 5
|
||||
disable-unloaded-chunk-enderpearl-exploit: true
|
||||
queue-light-updates: false
|
||||
optimize-explosions: false
|
||||
disable-teleportation-suffocation-check: false
|
||||
fixed-chunk-inhabited-time: -1
|
||||
use-vanilla-world-scoreboard-name-coloring: false
|
||||
delay-chunk-unloads-by: 10s
|
||||
max-auto-save-chunks-per-tick: 24
|
||||
save-queue-limit-for-auto-save: 50
|
||||
enable-treasure-maps: true
|
||||
treasure-maps-return-already-discovered: false
|
||||
experience-merge-max-value: -1
|
||||
max-chunk-sends-per-tick: 81
|
||||
max-chunk-gens-per-tick: 10
|
||||
prevent-moving-into-unloaded-chunks: false
|
||||
max-growth-height:
|
||||
cactus: 3
|
||||
reeds: 3
|
||||
fishing-time-range:
|
||||
MinimumTicks: 100
|
||||
MaximumTicks: 600
|
||||
despawn-ranges:
|
||||
soft: 32
|
||||
hard: 128
|
||||
falling-block-height-nerf: 0
|
||||
tnt-entity-height-nerf: 0
|
||||
remove-corrupt-tile-entities: false
|
||||
lightning-strike-distance-limit:
|
||||
sound: -1
|
||||
impact-sound: -1
|
||||
flash: -1
|
||||
frosted-ice:
|
||||
enabled: true
|
||||
delay:
|
||||
min: 20
|
||||
max: 40
|
||||
lootables:
|
||||
auto-replenish: false
|
||||
restrict-player-reloot: true
|
||||
reset-seed-on-fill: true
|
||||
max-refills: -1
|
||||
refresh-min: 12h
|
||||
refresh-max: 2d
|
||||
filter-nbt-data-from-spawn-eggs-and-related: true
|
||||
max-entity-collisions: 8
|
||||
disable-creeper-lingering-effect: false
|
||||
hopper:
|
||||
cooldown-when-full: true
|
||||
disable-move-event: false
|
||||
duplicate-uuid-resolver: saferegen
|
||||
duplicate-uuid-saferegen-delete-range: 32
|
||||
keep-spawn-loaded: true
|
||||
anti-xray:
|
||||
enabled: false
|
||||
engine-mode: 1
|
||||
chunk-edge-mode: 1
|
||||
max-chunk-section-index: 3
|
||||
update-radius: 2
|
||||
hidden-blocks:
|
||||
- gold_ore
|
||||
- iron_ore
|
||||
- coal_ore
|
||||
- lapis_ore
|
||||
- mossy_cobblestone
|
||||
- obsidian
|
||||
- chest
|
||||
- diamond_ore
|
||||
- redstone_ore
|
||||
- lit_redstone_ore
|
||||
- clay
|
||||
- emerald_ore
|
||||
- ender_chest
|
||||
replacement-blocks:
|
||||
- stone
|
||||
- planks
|
||||
skip-entity-ticking-in-chunks-scheduled-for-unload: true
|
||||
armor-stands-do-collision-entity-lookups: true
|
||||
keep-spawn-loaded-range: 8
|
||||
auto-save-interval: -1
|
||||
disable-thunder: false
|
||||
skeleton-horse-thunder-spawn-chance: 0.01
|
||||
disable-ice-and-snow: false
|
||||
fire-physics-event-for-redstone: false
|
||||
grass-spread-tick-rate: 1
|
||||
water-over-lava-flow-speed: 5
|
||||
bed-search-radius: 1
|
||||
use-faster-eigencraft-redstone: false
|
||||
nether-ceiling-void-damage: false
|
||||
allow-non-player-entities-on-scoreboards: false
|
||||
container-update-tick-rate: 1
|
||||
parrots-are-unaffected-by-player-movement: false
|
||||
prevent-tnt-from-moving-in-water: false
|
||||
non-player-arrow-despawn-rate: -1
|
||||
creative-arrow-despawn-rate: -1
|
||||
disable-explosion-knockback: false
|
||||
armor-stands-tick: true
|
||||
spawner-nerfed-mobs-should-jump: false
|
||||
allow-leashing-undead-horse: false
|
||||
baby-zombie-movement-speed: 0.5
|
||||
all-chunks-are-slime-chunks: false
|
||||
mob-spawner-tick-rate: 1
|
||||
squid-spawn-height:
|
||||
maximum: 0.0
|
||||
@@ -1 +0,0 @@
|
||||
rsa/
|
||||
@@ -1,29 +0,0 @@
|
||||
# The IP to listen to. Use 0.0.0.0 if you wish to listen to all interfaces on your server. (All IP addresses)
|
||||
# This defaults to the IP you have configured your server to listen on, or 0.0.0.0 if you have not configured this.
|
||||
host: 0.0.0.0
|
||||
|
||||
# Port to listen for new votes on
|
||||
port: 8194
|
||||
|
||||
# Whether or not to print debug messages. In a production system, this should be set to false.
|
||||
# This is useful when initially setting up NuVotifier to ensure votes are being delivered.
|
||||
debug: true
|
||||
|
||||
# Setting this option to true will disable handling of Protocol v1 packets. While the old protocol is not secure, this
|
||||
# option is currently not recommended as most voting sites only support the old protocol at present. However, if you are
|
||||
# using NuVotifier's proxy forwarding mechanism, enabling this option will increase your server's security.
|
||||
disable-v1-protocol: false
|
||||
|
||||
# All tokens, labeled by the serviceName of each server list.
|
||||
tokens:
|
||||
# Default token for all server lists, if another isn't supplied.
|
||||
default: server2token
|
||||
|
||||
# Configuration section for all vote forwarding to NuVotifier
|
||||
forwarding:
|
||||
# Sets whether to set up a remote method for fowarding. Supported methods:
|
||||
# - none - Does not set up a forwarding method.
|
||||
# - pluginMessaging - Sets up plugin messaging
|
||||
method: pluginMessaging
|
||||
pluginMessaging:
|
||||
channel: nuvotifier:votes
|
||||
@@ -1,5 +1,8 @@
|
||||
#Minecraft server properties
|
||||
#Fri Dec 21 15:15:00 EST 2018
|
||||
#Tue Jun 23 23:02:40 EDT 2020
|
||||
spawn-protection=16
|
||||
max-tick-time=60000
|
||||
query.port=25565
|
||||
generator-settings=
|
||||
force-gamemode=false
|
||||
allow-nether=true
|
||||
@@ -8,19 +11,23 @@ gamemode=0
|
||||
broadcast-console-to-ops=true
|
||||
enable-query=false
|
||||
player-idle-timeout=0
|
||||
difficulty=1
|
||||
difficulty=2
|
||||
spawn-monsters=true
|
||||
broadcast-rcon-to-ops=true
|
||||
op-permission-level=4
|
||||
pvp=true
|
||||
snooper-enabled=true
|
||||
level-type=DEFAULT
|
||||
level-type=default
|
||||
hardcore=false
|
||||
enable-command-block=false
|
||||
max-players=20
|
||||
network-compression-threshold=256
|
||||
resource-pack-sha1=
|
||||
max-world-size=29999984
|
||||
function-permission-level=2
|
||||
rcon.port=25575
|
||||
server-port=25566
|
||||
debug=false
|
||||
server-ip=
|
||||
spawn-npcs=true
|
||||
allow-flight=false
|
||||
@@ -29,11 +36,12 @@ view-distance=10
|
||||
resource-pack=
|
||||
spawn-animals=true
|
||||
white-list=false
|
||||
rcon.password=
|
||||
generate-structures=true
|
||||
online-mode=false
|
||||
max-build-height=256
|
||||
online-mode=false
|
||||
level-seed=
|
||||
prevent-proxy-connections=false
|
||||
use-native-transport=true
|
||||
prevent-proxy-connections=false
|
||||
motd=A Minecraft Server
|
||||
enable-rcon=false
|
||||
@@ -1,128 +0,0 @@
|
||||
# This is the main configuration file for Spigot.
|
||||
# As you can see, there's tons to configure. Some options may impact gameplay, so use
|
||||
# with caution, and make sure you know what each option does before configuring.
|
||||
# For a reference for any variable inside this file, check out the Spigot wiki at
|
||||
# http://www.spigotmc.org/wiki/spigot-configuration/
|
||||
#
|
||||
# If you need help with the configuration or have any questions related to Spigot,
|
||||
# join us at the IRC or drop by our forums and leave a post.
|
||||
#
|
||||
# IRC: #spigot @ irc.spi.gt ( http://www.spigotmc.org/pages/irc/ )
|
||||
# Forums: http://www.spigotmc.org/
|
||||
|
||||
config-version: 11
|
||||
settings:
|
||||
debug: false
|
||||
save-user-cache-on-stop-only: false
|
||||
sample-count: 12
|
||||
timeout-time: 60
|
||||
restart-on-crash: true
|
||||
restart-script: ./start.sh
|
||||
netty-threads: 4
|
||||
attribute:
|
||||
maxHealth:
|
||||
max: 2048.0
|
||||
movementSpeed:
|
||||
max: 2048.0
|
||||
attackDamage:
|
||||
max: 2048.0
|
||||
bungeecord: true
|
||||
late-bind: false
|
||||
player-shuffle: 0
|
||||
user-cache-size: 1000
|
||||
moved-wrongly-threshold: 0.0625
|
||||
moved-too-quickly-multiplier: 10.0
|
||||
messages:
|
||||
whitelist: You are not whitelisted on this server!
|
||||
unknown-command: Unknown command. Type "/help" for help.
|
||||
server-full: The server is full!
|
||||
outdated-client: Outdated client! Please use {0}
|
||||
outdated-server: Outdated server! I'm still on {0}
|
||||
restart: Server is restarting
|
||||
stats:
|
||||
disable-saving: false
|
||||
forced-stats: {}
|
||||
commands:
|
||||
tab-complete: 0
|
||||
send-namespaced: true
|
||||
log: true
|
||||
spam-exclusions:
|
||||
- /skill
|
||||
silent-commandblock-console: false
|
||||
replace-commands:
|
||||
- setblock
|
||||
- summon
|
||||
- testforblock
|
||||
- tellraw
|
||||
advancements:
|
||||
disable-saving: false
|
||||
disabled:
|
||||
- minecraft:story/disabled
|
||||
world-settings:
|
||||
default:
|
||||
verbose: true
|
||||
random-light-updates: false
|
||||
dragon-death-sound-radius: 0
|
||||
seed-village: 10387312
|
||||
seed-desert: 14357617
|
||||
seed-igloo: 14357618
|
||||
seed-jungle: 14357619
|
||||
seed-swamp: 14357620
|
||||
seed-monument: 10387313
|
||||
seed-shipwreck: 165745295
|
||||
seed-ocean: 14357621
|
||||
seed-slime: 987234911
|
||||
hunger:
|
||||
jump-walk-exhaustion: 0.05
|
||||
jump-sprint-exhaustion: 0.2
|
||||
combat-exhaustion: 0.1
|
||||
regen-exhaustion: 6.0
|
||||
swim-multiplier: 0.01
|
||||
sprint-multiplier: 0.1
|
||||
other-multiplier: 0.0
|
||||
max-tnt-per-tick: 100
|
||||
max-tick-time:
|
||||
tile: 50
|
||||
entity: 50
|
||||
squid-spawn-range:
|
||||
min: 45.0
|
||||
merge-radius:
|
||||
exp: 3.0
|
||||
item: 2.5
|
||||
mob-spawn-range: 8
|
||||
growth:
|
||||
cactus-modifier: 100
|
||||
cane-modifier: 100
|
||||
melon-modifier: 100
|
||||
mushroom-modifier: 100
|
||||
pumpkin-modifier: 100
|
||||
sapling-modifier: 100
|
||||
wheat-modifier: 100
|
||||
netherwart-modifier: 100
|
||||
vine-modifier: 100
|
||||
cocoa-modifier: 100
|
||||
entity-activation-range:
|
||||
animals: 32
|
||||
monsters: 32
|
||||
misc: 16
|
||||
water: 16
|
||||
tick-inactive-villagers: true
|
||||
entity-tracking-range:
|
||||
players: 48
|
||||
animals: 48
|
||||
monsters: 48
|
||||
misc: 32
|
||||
other: 64
|
||||
ticks-per:
|
||||
hopper-transfer: 8
|
||||
hopper-check: 1
|
||||
hopper-amount: 1
|
||||
wither-spawn-sound-radius: 0
|
||||
enable-zombie-pigmen-portal-spawns: true
|
||||
item-despawn-rate: 6000
|
||||
view-distance: 10
|
||||
arrow-despawn-rate: 1200
|
||||
zombie-aggressive-towards-villager: true
|
||||
hanging-tick-frequency: 100
|
||||
nerf-spawner-mobs: false
|
||||
max-entity-collisions: 8
|
||||
+1
-1
@@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-4.10-all.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-6.4-all.zip
|
||||
+2
-1
@@ -1,5 +1,6 @@
|
||||
dependencies {
|
||||
compileOnly group: "org.spongepowered", name: "spongeapi", version: "7.1.0"
|
||||
annotationProcessor group: "org.spongepowered", name: "spongeapi", version: "7.1.0"
|
||||
compile project(":nuvotifier-common")
|
||||
implementation project(":nuvotifier-api")
|
||||
implementation project(":nuvotifier-common")
|
||||
}
|
||||
+18
-15
@@ -8,6 +8,7 @@ import com.vexsoftware.votifier.net.VotifierSession;
|
||||
import com.vexsoftware.votifier.net.protocol.v1crypto.RSAIO;
|
||||
import com.vexsoftware.votifier.net.protocol.v1crypto.RSAKeygen;
|
||||
import com.vexsoftware.votifier.platform.LoggingAdapter;
|
||||
import com.vexsoftware.votifier.platform.VotifierPlugin;
|
||||
import com.vexsoftware.votifier.platform.scheduler.VotifierScheduler;
|
||||
import com.vexsoftware.votifier.sponge.cmd.NVReloadCmd;
|
||||
import com.vexsoftware.votifier.sponge.cmd.TestVoteCmd;
|
||||
@@ -23,6 +24,7 @@ import org.spongepowered.api.command.args.GenericArguments;
|
||||
import org.spongepowered.api.command.spec.CommandSpec;
|
||||
import org.spongepowered.api.config.ConfigDir;
|
||||
import org.spongepowered.api.event.Listener;
|
||||
import org.spongepowered.api.event.game.GameReloadEvent;
|
||||
import org.spongepowered.api.event.game.state.GameStartedServerEvent;
|
||||
import org.spongepowered.api.event.game.state.GameStoppingServerEvent;
|
||||
import org.spongepowered.api.plugin.Plugin;
|
||||
@@ -34,9 +36,9 @@ import java.security.KeyPair;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
@Plugin(id = "nuvotifier", name = "NuVotifier", version = "3.0.0-SNAPSHOT", authors = "Ichbinjoe",
|
||||
@Plugin(id = "nuvotifier", name = "NuVotifier", version = "2.7.0", authors = "Ichbinjoe",
|
||||
description = "Safe, smart, and secure Votifier server plugin")
|
||||
public class VotifierPlugin implements VoteHandler, com.vexsoftware.votifier.platform.VotifierPlugin, ForwardedVoteListener {
|
||||
public class NuVotifier implements VoteHandler, VotifierPlugin, ForwardedVoteListener {
|
||||
|
||||
@Inject
|
||||
public Logger logger;
|
||||
@@ -60,7 +62,9 @@ public class VotifierPlugin implements VoteHandler, com.vexsoftware.votifier.pla
|
||||
File rsaDirectory = new File(configDir, "rsa");
|
||||
try {
|
||||
if (!rsaDirectory.exists()) {
|
||||
rsaDirectory.mkdir();
|
||||
if (!rsaDirectory.mkdir()) {
|
||||
throw new RuntimeException("Unable to create the RSA key folder " + rsaDirectory);
|
||||
}
|
||||
keyPair = RSAKeygen.generate(2048);
|
||||
RSAIO.save(rsaDirectory, keyPair);
|
||||
} else {
|
||||
@@ -184,6 +188,11 @@ public class VotifierPlugin implements VoteHandler, com.vexsoftware.votifier.pla
|
||||
}
|
||||
}
|
||||
|
||||
@Listener
|
||||
public void onGameReload(GameReloadEvent event) {
|
||||
this.reload();
|
||||
}
|
||||
|
||||
@Listener
|
||||
public void onServerStop(GameStoppingServerEvent event) {
|
||||
halt();
|
||||
@@ -194,11 +203,6 @@ public class VotifierPlugin implements VoteHandler, com.vexsoftware.votifier.pla
|
||||
return logger;
|
||||
}
|
||||
|
||||
/**
|
||||
* The current Votifier version.
|
||||
*/
|
||||
private String version;
|
||||
|
||||
/**
|
||||
* The server bootstrap.
|
||||
*/
|
||||
@@ -262,12 +266,7 @@ public class VotifierPlugin implements VoteHandler, com.vexsoftware.votifier.pla
|
||||
logger.info("Got a protocol v2 vote record from " + remoteAddress + " -> " + vote);
|
||||
}
|
||||
}
|
||||
Sponge.getScheduler().createTaskBuilder()
|
||||
.execute(() -> {
|
||||
VotifierEvent event = new VotifierEvent(vote, Sponge.getCauseStackManager().getCurrentCause());
|
||||
Sponge.getEventManager().post(event);
|
||||
})
|
||||
.submit(this);
|
||||
this.fireVoteEvent(vote);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -289,9 +288,13 @@ public class VotifierPlugin implements VoteHandler, com.vexsoftware.votifier.pla
|
||||
if (debug) {
|
||||
logger.info("Got a forwarded vote -> " + v);
|
||||
}
|
||||
fireVoteEvent(v);
|
||||
}
|
||||
|
||||
private void fireVoteEvent(final Vote vote) {
|
||||
Sponge.getScheduler().createTaskBuilder()
|
||||
.execute(() -> {
|
||||
VotifierEvent event = new VotifierEvent(v, Sponge.getCauseStackManager().getCurrentCause());
|
||||
VotifierEvent event = new VotifierEvent(vote, Sponge.getCauseStackManager().getCurrentCause());
|
||||
Sponge.getEventManager().post(event);
|
||||
})
|
||||
.submit(this);
|
||||
@@ -8,9 +8,9 @@ import org.spongepowered.api.scheduler.Task;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
class SpongeScheduler implements VotifierScheduler {
|
||||
private final VotifierPlugin plugin;
|
||||
private final NuVotifier plugin;
|
||||
|
||||
SpongeScheduler(VotifierPlugin plugin) {
|
||||
SpongeScheduler(NuVotifier plugin) {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package com.vexsoftware.votifier.sponge.cmd;
|
||||
|
||||
import com.vexsoftware.votifier.sponge.VotifierPlugin;
|
||||
import com.vexsoftware.votifier.sponge.NuVotifier;
|
||||
import org.spongepowered.api.command.CommandException;
|
||||
import org.spongepowered.api.command.CommandResult;
|
||||
import org.spongepowered.api.command.CommandSource;
|
||||
@@ -11,9 +11,9 @@ import org.spongepowered.api.text.format.TextColors;
|
||||
|
||||
public class NVReloadCmd implements CommandExecutor {
|
||||
|
||||
private final VotifierPlugin plugin;
|
||||
private final NuVotifier plugin;
|
||||
|
||||
public NVReloadCmd(VotifierPlugin plugin) {
|
||||
public NVReloadCmd(NuVotifier plugin) {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@ package com.vexsoftware.votifier.sponge.cmd;
|
||||
|
||||
import com.vexsoftware.votifier.model.Vote;
|
||||
import com.vexsoftware.votifier.net.VotifierSession;
|
||||
import com.vexsoftware.votifier.sponge.VotifierPlugin;
|
||||
import com.vexsoftware.votifier.sponge.NuVotifier;
|
||||
import com.vexsoftware.votifier.util.ArgsToVote;
|
||||
import org.spongepowered.api.command.CommandException;
|
||||
import org.spongepowered.api.command.CommandResult;
|
||||
@@ -16,9 +16,9 @@ import java.util.Collection;
|
||||
|
||||
public class TestVoteCmd implements CommandExecutor {
|
||||
|
||||
private final VotifierPlugin plugin;
|
||||
private final NuVotifier plugin;
|
||||
|
||||
public TestVoteCmd(VotifierPlugin plugin) {
|
||||
public TestVoteCmd(NuVotifier plugin) {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
@@ -26,9 +26,8 @@ public class TestVoteCmd implements CommandExecutor {
|
||||
public CommandResult execute(CommandSource sender, CommandContext args) throws CommandException {
|
||||
Vote v;
|
||||
try {
|
||||
// well, this is a super nice feature of sponge. unfortunately, no one else has these features. Therefore, GET RID OF IT
|
||||
Collection<String> a = args.getAll("args");
|
||||
v = ArgsToVote.parse((String[]) a.toArray());
|
||||
v = ArgsToVote.parse(a.toArray(new String[0]));
|
||||
} catch (IllegalArgumentException e) {
|
||||
sender.sendMessage(Text.builder("Error while parsing arguments to create test vote: " + e.getMessage()).color(TextColors.DARK_RED).build());
|
||||
sender.sendMessage(Text.builder("Usage hint: /testvote [username] [serviceName=?] [username=?] [address=?] [localTimestamp=?] [timestamp=?]").color(TextColors.GRAY).build());
|
||||
|
||||
@@ -1,35 +1,36 @@
|
||||
package com.vexsoftware.votifier.sponge.config;
|
||||
|
||||
import com.google.common.reflect.TypeToken;
|
||||
import com.vexsoftware.votifier.sponge.VotifierPlugin;
|
||||
import com.vexsoftware.votifier.sponge.NuVotifier;
|
||||
import ninja.leaping.configurate.ConfigurationNode;
|
||||
import ninja.leaping.configurate.ConfigurationOptions;
|
||||
import ninja.leaping.configurate.loader.ConfigurationLoader;
|
||||
import ninja.leaping.configurate.yaml.YAMLConfigurationLoader;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
public class ConfigLoader {
|
||||
|
||||
private static VotifierPlugin plugin;
|
||||
private static SpongeConfig spongeConfig;
|
||||
|
||||
public static void loadConfig(VotifierPlugin pl) {
|
||||
plugin = pl;
|
||||
if (!plugin.getConfigDir().exists()) {
|
||||
plugin.getConfigDir().mkdirs();
|
||||
public static void loadConfig(NuVotifier pl) {
|
||||
if (!pl.getConfigDir().exists()) {
|
||||
if (!pl.getConfigDir().mkdirs()) {
|
||||
throw new RuntimeException("Unable to create the plugin data folder " + pl.getConfigDir());
|
||||
}
|
||||
}
|
||||
try {
|
||||
File file = new File(plugin.getConfigDir(), "config.yml");
|
||||
if (!file.exists()) {
|
||||
file.createNewFile();
|
||||
File config = new File(pl.getConfigDir(), "config.yml");
|
||||
if (!config.exists() && !config.createNewFile()) {
|
||||
throw new IOException("Unable to create the config file at " + config);
|
||||
}
|
||||
ConfigurationLoader loader = YAMLConfigurationLoader.builder().setFile(file).build();
|
||||
ConfigurationNode config = loader.load(ConfigurationOptions.defaults().setShouldCopyDefaults(true));
|
||||
spongeConfig = config.getValue(TypeToken.of(SpongeConfig.class), new SpongeConfig());
|
||||
loader.save(config);
|
||||
ConfigurationLoader loader = YAMLConfigurationLoader.builder().setFile(config).build();
|
||||
ConfigurationNode configNode = loader.load(ConfigurationOptions.defaults().setShouldCopyDefaults(true));
|
||||
spongeConfig = configNode.getValue(TypeToken.of(SpongeConfig.class), new SpongeConfig());
|
||||
loader.save(configNode);
|
||||
} catch (Exception e) {
|
||||
plugin.getLogger().error("Could not load config.", e);
|
||||
pl.getLogger().error("Could not load config.", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ import org.spongepowered.api.event.impl.AbstractEvent;
|
||||
|
||||
/**
|
||||
* This event is posted whenever a vote is received and processed by NuVotifier. Note that NuVotifier posts this event
|
||||
* asynchronously, so you can only use limited portions of the Sponge API.
|
||||
* synchronously.
|
||||
*/
|
||||
public class VotifierEvent extends AbstractEvent {
|
||||
private final Vote vote;
|
||||
|
||||
+3
-3
@@ -1,6 +1,6 @@
|
||||
package com.vexsoftware.votifier.sponge.forwarding;
|
||||
|
||||
import com.vexsoftware.votifier.sponge.VotifierPlugin;
|
||||
import com.vexsoftware.votifier.sponge.NuVotifier;
|
||||
import com.vexsoftware.votifier.support.forwarding.AbstractPluginMessagingForwardingSink;
|
||||
import com.vexsoftware.votifier.support.forwarding.ForwardedVoteListener;
|
||||
import org.spongepowered.api.Platform;
|
||||
@@ -12,14 +12,14 @@ import org.spongepowered.api.network.RemoteConnection;
|
||||
|
||||
public class SpongePluginMessagingForwardingSink extends AbstractPluginMessagingForwardingSink implements RawDataListener {
|
||||
|
||||
public SpongePluginMessagingForwardingSink(VotifierPlugin p, String channel, ForwardedVoteListener listener) {
|
||||
public SpongePluginMessagingForwardingSink(NuVotifier p, String channel, ForwardedVoteListener listener) {
|
||||
super(listener);
|
||||
this.channelBinding = Sponge.getChannelRegistrar().createRawChannel(p, channel);
|
||||
this.channelBinding.addListener(Platform.Type.SERVER, this);
|
||||
this.p = p;
|
||||
}
|
||||
|
||||
private final VotifierPlugin p;
|
||||
private final NuVotifier p;
|
||||
private final ChannelBinding.RawDataChannel channelBinding;
|
||||
|
||||
@Override
|
||||
|
||||
+41
-19
@@ -1,42 +1,66 @@
|
||||
import com.github.jengelman.gradle.plugins.shadow.relocation.SimpleRelocator
|
||||
|
||||
import java.nio.file.FileAlreadyExistsException
|
||||
import java.nio.file.Files
|
||||
import java.nio.file.Paths
|
||||
import java.nio.file.StandardCopyOption
|
||||
import java.util.regex.Pattern
|
||||
import com.github.jengelman.gradle.plugins.shadow.transformers.Transformer
|
||||
import com.github.jengelman.gradle.plugins.shadow.transformers.TransformerContext
|
||||
import shadow.org.apache.tools.zip.ZipEntry
|
||||
import shadow.org.apache.tools.zip.ZipOutputStream
|
||||
import org.gradle.api.file.FileTreeElement
|
||||
|
||||
buildscript {
|
||||
repositories {
|
||||
jcenter()
|
||||
}
|
||||
dependencies {
|
||||
classpath 'com.github.jengelman.gradle.plugins:shadow:2.0.4'
|
||||
classpath 'com.github.jengelman.gradle.plugins:shadow:4.0.4'
|
||||
}
|
||||
}
|
||||
|
||||
class NettyEpollTransformer implements Transformer {
|
||||
private java.nio.file.Path extractedNettyNative
|
||||
|
||||
boolean canTransformResource(FileTreeElement element) {
|
||||
return element.name.endsWith("libnetty_transport_native_epoll_x86_64.so")
|
||||
}
|
||||
|
||||
void transform(TransformerContext context) {
|
||||
this.extractedNettyNative = Files.createTempFile("nuvotifer_build", ".so")
|
||||
Files.copy(context.is, this.extractedNettyNative, StandardCopyOption.REPLACE_EXISTING)
|
||||
}
|
||||
|
||||
boolean hasTransformedResource() { this.extractedNettyNative != null }
|
||||
|
||||
void modifyOutputStream(ZipOutputStream jos, boolean preserveFileTimestamps) {
|
||||
ZipEntry entry = new ZipEntry("META-INF/native/libcom_vexsoftware_votifier_netty_transport_native_epoll_x86_64.so")
|
||||
entry.time = TransformerContext.getEntryTimestamp(preserveFileTimestamps, entry.time)
|
||||
jos.putNextEntry(entry)
|
||||
Files.copy(this.extractedNettyNative, jos)
|
||||
Files.delete(this.extractedNettyNative)
|
||||
}
|
||||
}
|
||||
|
||||
apply plugin: 'com.github.johnrengelman.shadow'
|
||||
|
||||
dependencies {
|
||||
compile project(":nuvotifier-bukkit")
|
||||
compile project(":nuvotifier-bungeecord")
|
||||
compile project(":nuvotifier-sponge")
|
||||
compile project(":nuvotifier-velocity")
|
||||
implementation project(":nuvotifier-api")
|
||||
implementation project(":nuvotifier-common")
|
||||
implementation project(":nuvotifier-bukkit")
|
||||
implementation project(":nuvotifier-bungeecord")
|
||||
implementation project(":nuvotifier-sponge")
|
||||
implementation project(":nuvotifier-velocity")
|
||||
}
|
||||
|
||||
shadowJar {
|
||||
dependencies {
|
||||
// All current implementations include Google Guava already, and explicitly shading in Guava causes the plugin
|
||||
// to fail to initialize on Sponge.
|
||||
exclude(dependency('com.google.guava:guava:24.1-jre'))
|
||||
}
|
||||
|
||||
baseName = 'nuvotifier'
|
||||
classifier = null
|
||||
relocate "io.netty", "com.vexsoftware.votifier.netty"
|
||||
archiveBaseName = 'nuvotifier'
|
||||
relocate "io.netty", "com.vexsoftware.votifier.io.netty"
|
||||
relocate "org.json", "com.vexsoftware.votifier.json"
|
||||
relocate new SimpleRelocator("com.google.code", "com.vexsoftware.votifier.google.code", new ArrayList<String>(), Collections.singletonList("com.vexsoftware.votifier.sponge"))
|
||||
relocate "com.google.guava", "com.vexsoftware.votifier.google.guava"
|
||||
relocate "org.apache.commons.io", "com.vexsoftware.votifier.commons.io"
|
||||
|
||||
transform(NettyEpollTransformer.class)
|
||||
}
|
||||
|
||||
artifacts {
|
||||
@@ -60,9 +84,7 @@ task('linkLatest') {
|
||||
|
||||
def noVer = Paths.get(noVerMatcher.group(1) + ".jar")
|
||||
def versnd = it.toPath()
|
||||
try {
|
||||
Files.createSymbolicLink(noVer, versnd)
|
||||
} catch (FileAlreadyExistsException ignored) {}
|
||||
Files.copy(versnd, noVer, StandardCopyOption.REPLACE_EXISTING)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
dependencies {
|
||||
compileOnly group: "com.velocitypowered", name: "velocity-api", version: "1.0-SNAPSHOT"
|
||||
annotationProcessor group: "com.velocitypowered", name: "velocity-api", version: "1.0-SNAPSHOT"
|
||||
compile project(":nuvotifier-common")
|
||||
compileOnly "com.velocitypowered:velocity-api:1.0.0-SNAPSHOT"
|
||||
annotationProcessor "com.velocitypowered:velocity-api:1.0.0-SNAPSHOT"
|
||||
implementation project(":nuvotifier-api")
|
||||
implementation project(":nuvotifier-common")
|
||||
}
|
||||
+3
@@ -38,6 +38,9 @@ public final class OnlineForwardPluginMessagingForwardingSource extends Abstract
|
||||
serverFilter.isAllowed(sc.get().getServerInfo().getName())
|
||||
) {
|
||||
if (forwardSpecific(new VelocityBackendServer(plugin.getServer(), sc.get().getServer()), v)) {
|
||||
if (plugin.isDebug()) {
|
||||
plugin.getPluginLogger().info("Successfully forwarded vote " + v + " to server " + sc.get().getServerInfo().getName());
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
package com.vexsoftware.votifier.velocity;
|
||||
|
||||
import com.google.common.io.ByteStreams;
|
||||
import com.google.inject.Inject;
|
||||
import com.moandjiezana.toml.Toml;
|
||||
import com.velocitypowered.api.event.Subscribe;
|
||||
import com.velocitypowered.api.event.proxy.ProxyInitializeEvent;
|
||||
import com.velocitypowered.api.event.proxy.ProxyReloadEvent;
|
||||
import com.velocitypowered.api.event.proxy.ProxyShutdownEvent;
|
||||
import com.velocitypowered.api.plugin.Plugin;
|
||||
import com.velocitypowered.api.plugin.annotation.DataDirectory;
|
||||
@@ -25,12 +25,12 @@ import com.vexsoftware.votifier.support.forwarding.cache.FileVoteCache;
|
||||
import com.vexsoftware.votifier.support.forwarding.cache.MemoryVoteCache;
|
||||
import com.vexsoftware.votifier.support.forwarding.cache.VoteCache;
|
||||
import com.vexsoftware.votifier.support.forwarding.proxy.ProxyForwardingVoteSource;
|
||||
import com.vexsoftware.votifier.util.IOUtil;
|
||||
import com.vexsoftware.votifier.util.KeyCreator;
|
||||
import com.vexsoftware.votifier.util.TokenUtil;
|
||||
import com.vexsoftware.votifier.velocity.cmd.NVReloadCmd;
|
||||
import com.vexsoftware.votifier.velocity.cmd.TestVoteCmd;
|
||||
import com.vexsoftware.votifier.velocity.event.VotifierEvent;
|
||||
import io.netty.channel.Channel;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
@@ -44,13 +44,13 @@ import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.NoSuchFileException;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.StandardCopyOption;
|
||||
import java.security.Key;
|
||||
import java.security.KeyPair;
|
||||
import java.util.*;
|
||||
import java.util.logging.Level;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Plugin(id = "nuvotifier", name = "NuVotifier", version = "3.0.0-SNAPSHOT", authors = "Ichbinjoe",
|
||||
@Plugin(id = "nuvotifier", name = "NuVotifier", version = "2.7.0", authors = "Ichbinjoe",
|
||||
description = "Safe, smart, and secure Votifier server plugin")
|
||||
public class VotifierPlugin implements VoteHandler, ProxyVotifierPlugin {
|
||||
|
||||
@@ -83,7 +83,9 @@ public class VotifierPlugin implements VoteHandler, ProxyVotifierPlugin {
|
||||
File rsaDirectory = new File(configDir.toFile(), "rsa");
|
||||
try {
|
||||
if (!rsaDirectory.exists()) {
|
||||
rsaDirectory.mkdir();
|
||||
if (!rsaDirectory.mkdir()) {
|
||||
throw new RuntimeException("Unable to create the RSA key folder " + rsaDirectory);
|
||||
}
|
||||
keyPair = RSAKeygen.generate(2048);
|
||||
RSAIO.save(rsaDirectory, keyPair);
|
||||
} else {
|
||||
@@ -138,13 +140,13 @@ public class VotifierPlugin implements VoteHandler, ProxyVotifierPlugin {
|
||||
getLogger().info("Vote cache none selected for caching: votes that cannot be immediately delivered will be lost.");
|
||||
} else if ("memory".equals(cacheMethod)) {
|
||||
voteCache = new MemoryVoteCache(
|
||||
server.getAllServers().size(), this,
|
||||
this,
|
||||
fwdCfg.getTable("memory-cache").getLong("cacheTime", -1L));
|
||||
getLogger().info("Using in-memory cache for votes that are not able to be delivered.");
|
||||
} else if ("file".equals(cacheMethod)) {
|
||||
try {
|
||||
voteCache = new FileVoteCache(
|
||||
server.getAllServers().size(), this,
|
||||
this,
|
||||
configDir.resolve(fwdCfg.getTable("file-cache").getString("name")).toFile(),
|
||||
fwdCfg.getTable("file-cache").getLong("cacheTime", -1L));
|
||||
} catch (IOException e) {
|
||||
@@ -154,7 +156,7 @@ public class VotifierPlugin implements VoteHandler, ProxyVotifierPlugin {
|
||||
int dumpRate = pmCfg.getLong("dumpRate", 5L).intValue();
|
||||
|
||||
ServerFilter filter = new ServerFilter(
|
||||
pmCfg.getList("excludedServers"),
|
||||
pmCfg.getList("excludedServers", Collections.emptyList()),
|
||||
pmCfg.getBoolean("whitelist", false)
|
||||
);
|
||||
|
||||
@@ -204,7 +206,7 @@ public class VotifierPlugin implements VoteHandler, ProxyVotifierPlugin {
|
||||
}
|
||||
}
|
||||
|
||||
forwardingMethod = new ProxyForwardingVoteSource(this, bootstrap::client, serverList, null);
|
||||
forwardingMethod = bootstrap.createForwardingSource(serverList, null);
|
||||
getLogger().info("Forwarding votes from this NuVotifier instance to another NuVotifier server.");
|
||||
} else {
|
||||
getLogger().error("No vote forwarding method '" + fwdMethod + "' known. Defaulting to noop implementation.");
|
||||
@@ -251,7 +253,7 @@ public class VotifierPlugin implements VoteHandler, ProxyVotifierPlugin {
|
||||
this.scheduler = new VelocityScheduler(server, this);
|
||||
this.loggingAdapter = new SLF4JLogger(logger);
|
||||
|
||||
this.getServer().getCommandManager().register(new NVReloadCmd(this), "nvpreload");
|
||||
this.getServer().getCommandManager().register(new NVReloadCmd(this), "pnvreload");
|
||||
this.getServer().getCommandManager().register(new TestVoteCmd(this), "ptestvote");
|
||||
|
||||
if (!loadAndBind())
|
||||
@@ -260,10 +262,15 @@ public class VotifierPlugin implements VoteHandler, ProxyVotifierPlugin {
|
||||
|
||||
@Subscribe
|
||||
public void onServerStop(ProxyShutdownEvent event) {
|
||||
|
||||
this.halt();
|
||||
logger.info("Votifier disabled.");
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onProxyReload(ProxyReloadEvent event) {
|
||||
this.reload();
|
||||
}
|
||||
|
||||
public ProxyServer getServer() {
|
||||
return server;
|
||||
}
|
||||
@@ -281,7 +288,8 @@ public class VotifierPlugin implements VoteHandler, ProxyVotifierPlugin {
|
||||
getLogger().info("Configuring Votifier for the first time...");
|
||||
|
||||
// Initialize the configuration file.
|
||||
String cfgStr = new String(ByteStreams.toByteArray(VotifierPlugin.class.getResourceAsStream("/config.toml")), StandardCharsets.UTF_8);
|
||||
|
||||
String cfgStr = new String(IOUtil.readAllBytes(VotifierPlugin.class.getResourceAsStream("/config.toml")), StandardCharsets.UTF_8);
|
||||
String token = TokenUtil.newToken();
|
||||
cfgStr = cfgStr.replace("%ip%", server.getBoundAddress().getAddress().getHostAddress());
|
||||
cfgStr = cfgStr.replace("%default_token%", token);
|
||||
@@ -294,18 +302,18 @@ public class VotifierPlugin implements VoteHandler, ProxyVotifierPlugin {
|
||||
getLogger().info("Assigning NuVotifier to listen on port 8192. If you are hosting BungeeCord on a");
|
||||
getLogger().info("shared server please check with your hosting provider to verify that this port");
|
||||
getLogger().info("is available for your use. Chances are that your hosting provider will assign");
|
||||
getLogger().info("a different port, which you need to specify in config.yml");
|
||||
getLogger().info("a different port, which you need to specify in config.toml.");
|
||||
getLogger().info("------------------------------------------------------------------------------");
|
||||
getLogger().info("Assigning NuVotifier to listen to interface 0.0.0.0. This is usually alright,");
|
||||
getLogger().info("however, if you want NuVotifier to only listen to one interface for security ");
|
||||
getLogger().info("reasons (or you use a shared host), you may change this in the config.yml.");
|
||||
getLogger().info("reasons (or you use a shared host), you may change this in the config.toml.");
|
||||
getLogger().info("------------------------------------------------------------------------------");
|
||||
getLogger().info("Your default Votifier token is " + token + ".");
|
||||
getLogger().info("You will need to provide this token when you submit your server to a voting");
|
||||
getLogger().info("list.");
|
||||
getLogger().info("------------------------------------------------------------------------------");
|
||||
|
||||
Files.copy(new ByteArrayInputStream(cfgStr.getBytes(StandardCharsets.UTF_8)), configPath);
|
||||
Files.copy(new ByteArrayInputStream(cfgStr.getBytes(StandardCharsets.UTF_8)), configPath, StandardCopyOption.REPLACE_EXISTING);
|
||||
return new Toml().read(cfgStr);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user