Initial commit

This commit is contained in:
Kristian Knarvik 2023-08-26 16:59:45 +02:00
commit b5338806e3
511 changed files with 55833 additions and 0 deletions

247
.gitignore vendored Normal file
View File

@ -0,0 +1,247 @@
#################### Misc ####################
# Home made stuff not present in the gitignore project.
# Manually forged MassiveCraft stuff.
# Eclipse jar description files
*.jardesc
# IntelliJ missing files
*.iml
*.ipr
# Just because we had it in our old gitignore.
manifest.mf
#################### Language ####################
# Language general ignores.
### Maven
# https://github.com/github/gitignore/blob/master/Maven.gitignore
target/
pom.xml.tag
pom.xml.releaseBackup
pom.xml.versionsBackup
pom.xml.next
release.properties
dependency-reduced-pom.xml
buildNumber.properties
.mvn/timing.properties
#################### IDE ####################
# IDE general ignores.
### Eclipse
# https://github.com/github/gitignore/blob/master/Global/Eclipse.gitignore
.metadata
bin/
tmp/
*.tmp
*.bak
*.swp
*~.nib
local.properties
.settings/
.loadpath
.recommenders
# Eclipse Core
.project
# External tool builders
.externalToolBuilders/
# Locally stored "Eclipse launch configurations"
*.launch
# PyDev specific (Python IDE for Eclipse)
*.pydevproject
# CDT-specific (C/C++ Development Tooling)
.cproject
# JDT-specific (Eclipse Java Development Tools)
.classpath
# Java annotation processor (APT)
.factorypath
# PDT-specific (PHP Development Tools)
.buildpath
# sbteclipse plugin
.target
# Tern plugin
.tern-project
# TeXlipse plugin
.texlipse
# STS (Spring Tool Suite)
.springBeans
# Code Recommenders
.recommenders/
### JetBrains
# https://github.com/github/gitignore/blob/master/Global/JetBrains.gitignore
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and Webstorm
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
# User-specific stuff:
.idea/*
# Gradle:
.idea/gradle.xml
.idea/libraries
# Mongo Explorer plugin:
.idea/mongoSettings.xml
## File-based project format:
*.iws
## Plugin-specific files:
# IntelliJ
/out/
# mpeltonen/sbt-idea plugin
.idea_modules/
# JIRA plugin
atlassian-ide-plugin.xml
# Crashlytics plugin (for Android Studio and IntelliJ)
com_crashlytics_export_strings.xml
crashlytics.properties
crashlytics-build.properties
fabric.properties
### NetBeans
# https://github.com/github/gitignore/blob/master/Global/NetBeans.gitignore
nbproject/private/
build/
nbbuild/
dist/
nbdist/
.nb-gradle/
### SublimeText
# https://github.com/github/gitignore/blob/master/Global/SublimeText.gitignore
# cache files for sublime text
*.tmlanguage.cache
*.tmPreferences.cache
*.stTheme.cache
# workspace files are user-specific
*.sublime-workspace
# project files should be checked into the repository, unless a significant
# proportion of contributors will probably not be using SublimeText
# *.sublime-project
# sftp configuration file
sftp-config.json
# Package control specific files
Package Control.last-run
Package Control.ca-list
Package Control.ca-bundle
Package Control.system-ca-bundle
Package Control.cache/
Package Control.ca-certs/
bh_unicode_properties.cache
# Sublime-github package stores a github token in this file
# https://packagecontrol.io/packages/sublime-github
GitHub.sublime-settings
### Vim
# https://github.com/github/gitignore/blob/master/Global/Vim.gitignore
# swap
[._]*.s[a-w][a-z]
[._]s[a-w][a-z]
# session
Session.vim
# temporary
.netrwhist
# auto-generated tag files
tags
#################### OS ####################
# Operating system general ignores.
### https://github.com/github/gitignore/blob/master/Global/macOS.gitignore
*.DS_Store
.AppleDouble
.LSOverride
# Icon must end with two \r
Icon
# Thumbnails
._*
# Files that might appear in the root of a volume
.DocumentRevisions-V100
.fseventsd
.Spotlight-V100
.TemporaryItems
.Trashes
.VolumeIcon.icns
.com.apple.timemachine.donotpresent
# Directories potentially created on remote AFP share
.AppleDB
.AppleDesktop
Network Trash Folder
Temporary Items
.apdisk
### https://github.com/github/gitignore/blob/master/Global/Linux.gitignore
*~
# temporary files which can be created if a process still has a handle open of a deleted file
.fuse_hidden*
# KDE directory preferences
.directory
# Linux trash folder which might appear on any partition or disk
.Trash-*
### https://github.com/github/gitignore/blob/master/Global/Windows.gitignore
# Windows image file caches
Thumbs.db
ehthumbs.db
# Folder config file
Desktop.ini
# Recycle Bin used on file shares
$RECYCLE.BIN/
# Windows Installer files
*.cab
*.msi
*.msm
*.msp
# Windows shortcuts
*.lnk
#################### OTHER ####################
# Other general ignores.
### Dropbox
# https://github.com/github/gitignore/blob/master/Global/Dropbox.gitignore
# Dropbox settings and caches
.dropbox
.dropbox.attr
.dropbox.cache

View File

@ -0,0 +1,4 @@
#Created by Apache Maven 3.8.1
groupId=com.massivecraft.massivecore
artifactId=MassiveCore
version=3.3.3

View File

@ -0,0 +1,101 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<!-- Parent -->
<parent>
<groupId>com.massivecraft.massivesuper</groupId>
<artifactId>MassiveSuper</artifactId>
<version>3.3.3</version>
<relativePath>../MassiveSuper</relativePath>
</parent>
<!-- Basics -->
<groupId>com.massivecraft.massivecore</groupId>
<artifactId>MassiveCore</artifactId>
<packaging>jar</packaging>
<!-- Info -->
<name>${project.artifactId}</name>
<description>${massiveColorInfo}${project.name} is a plugin that contains libraries and features that other plugins
make use of. ${massiveDescriptionSuffix}
</description>
<url>${massiveBaseUrl}/massivecore</url>
<!-- Dependencies -->
<dependencies>
<!-- Spigot -->
<dependency>
<groupId>org.spigotmc</groupId>
<artifactId>spigot-api</artifactId>
</dependency>
<!-- Vault -->
<dependency>
<groupId>net.milkbowl.vault</groupId>
<artifactId>Vault</artifactId>
</dependency>
<!-- MongoDB -->
<dependency>
<groupId>org.mongodb</groupId>
<artifactId>mongo-java-driver</artifactId>
<version>2.14.0</version>
</dependency>
</dependencies>
<!-- Build -->
<build>
<!-- Plugins-->
<plugins>
<!-- Enforcer -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-enforcer-plugin</artifactId>
</plugin>
<!-- Shade -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<artifactSet>
<includes>
<include>com.massivecraft.massivecore:MassiveCoreXlib</include>
</includes>
</artifactSet>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
<!-- Resources -->
<resources>
<!-- Standard -->
<resource>
<directory>${project.basedir}</directory>
<filtering>true</filtering>
<includes>
<include>*.yml</include>
</includes>
</resource>
<!-- OpenSource -->
<resource>
<directory>${project.build.sourceDirectory}</directory>
<filtering>false</filtering>
</resource>
<!-- Sponsor Disable Code -->
<resource>
<directory>${project.basedir}</directory>
<filtering>true</filtering>
<includes>
<include>sponsor-disable-code</include>
</includes>
</resource>
</resources>
</build>
</project>

111
pom.xml Normal file
View File

@ -0,0 +1,111 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<!-- Basics -->
<groupId>com.massivecraft.massivecore</groupId>
<artifactId>MassiveCore</artifactId>
<packaging>jar</packaging>
<!-- Info -->
<name>${project.artifactId}</name>
<description>${project.name} is a plugin that contains libraries and features that other plugins make use of.
</description>
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
</properties>
<!--<url>${massiveBaseUrl}/massivecore</url>-->
<version>3.3.3</version>
<repositories>
<repository>
<id>spigotmc-repo</id>
<url>https://hub.spigotmc.org/nexus/content/repositories/snapshots/</url>
</repository>
<repository>
<id>jitpack.io</id>
<url>https://jitpack.io</url>
</repository>
</repositories>
<!-- Dependencies -->
<dependencies>
<!-- Spigot -->
<dependency>
<groupId>org.spigotmc</groupId>
<artifactId>spigot-api</artifactId>
<version>1.20.1-R0.1-SNAPSHOT</version>
</dependency>
<!-- Vault -->
<dependency>
<groupId>com.github.MilkBowl</groupId>
<artifactId>VaultAPI</artifactId>
<version>1.7</version>
<scope>provided</scope>
</dependency>
<!-- MongoDB -->
<dependency>
<groupId>org.mongodb</groupId>
<artifactId>mongo-java-driver</artifactId>
<version>3.12.12</version>
</dependency>
</dependencies>
<!-- Build -->
<build>
<!-- Plugins-->
<plugins>
<!-- Enforcer -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-enforcer-plugin</artifactId>
</plugin>
<!-- Shade -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<artifactSet>
<includes>
<include>com.massivecraft.massivecore:MassiveCoreXlib</include>
</includes>
</artifactSet>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
<!-- Resources -->
<resources>
<!-- Standard -->
<resource>
<directory>${project.basedir}</directory>
<filtering>true</filtering>
<includes>
<include>*.yml</include>
</includes>
</resource>
<!-- OpenSource -->
<resource>
<directory>${project.build.sourceDirectory}</directory>
<filtering>false</filtering>
</resource>
<!-- Sponsor Disable Code -->
<resource>
<directory>${project.basedir}</directory>
<filtering>true</filtering>
<includes>
<include>sponsor-disable-code</include>
</includes>
</resource>
</resources>
</build>
</project>

1
sponsor-disable-code Normal file
View File

@ -0,0 +1 @@
${yvqdqhdszvhutafh}

View File

@ -0,0 +1,19 @@
package com.massivecraft.massivecore;
public interface Active {
// Boolean
boolean isActive();
void setActive(boolean active);
// Plugin
MassivePlugin setActivePlugin(MassivePlugin plugin);
MassivePlugin getActivePlugin();
// Combined Setter
// Plugin is set first.
// Boolean by null state.
void setActive(MassivePlugin plugin);
}

View File

@ -0,0 +1,261 @@
package com.massivecraft.massivecore;
import com.massivecraft.massivecore.cmd.CmdMassiveCore;
import com.massivecraft.massivecore.collections.MassiveList;
import com.massivecraft.massivecore.command.MassiveCommand;
import com.massivecraft.massivecore.command.requirement.Requirement;
import com.massivecraft.massivecore.command.requirement.RequirementAbstract;
import com.massivecraft.massivecore.command.requirement.RequirementIsPlayer;
import com.massivecraft.massivecore.mson.Mson;
import com.massivecraft.massivecore.mson.MsonEvent;
import org.bukkit.ChatColor;
import org.bukkit.command.CommandSender;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import static com.massivecraft.massivecore.mson.Mson.mson;
public class Button {
// -------------------------------------------- //
// INSTANCE
// -------------------------------------------- //
public static Button get() {
return new Button();
}
// -------------------------------------------- //
// CONSTRUCT
// -------------------------------------------- //
public Button() {
}
// -------------------------------------------- //
// CONSTANTS
// -------------------------------------------- //
// A button is either enabled or disabled. These are the two corresponding colors.
public static final ChatColor COLOR_ENABLED = ChatColor.AQUA;
public static final ChatColor COLOR_DISABLED = ChatColor.GRAY;
// -------------------------------------------- //
// FIELDS > COMMON
// -------------------------------------------- //
// This is the text inside the button.
private String name = null;
public String getName() {
return this.name;
}
public Button setName(String name) {
this.name = name;
return this;
}
// Padding right, left or none.
public Boolean paddingRight = null;
public Boolean isPaddingRight() {
return this.paddingRight;
}
public Button setPaddingRight(Boolean paddingRight) {
this.paddingRight = paddingRight;
return this;
}
// Verbose visible as grey. Otherwise hidden.
public boolean verbose = true;
public boolean isVerbose() {
return this.verbose;
}
public Button setVerbose(boolean verbose) {
this.verbose = verbose;
return this;
}
// When you just want to error really hard!
private String error = null;
public String getError() {
return this.error;
}
public Button setError(String error) {
this.error = error;
return this;
}
// Requirements to always be validated.
private List<Requirement> requirements = new MassiveList<>();
public List<Requirement> getRequirements() {
return this.requirements;
}
public Button addRequirements(Collection<Requirement> requirements) {
this.requirements.addAll(requirements);
return this;
}
public Button addRequirements(Requirement... requirements) {
this.addRequirements(Arrays.asList(requirements));
return this;
}
// -------------------------------------------- //
// FIELDS > COMMAND
// -------------------------------------------- //
private CommandSender sender = null;
public CommandSender getSender() {
return this.sender;
}
public Button setSender(CommandSender sender) {
this.sender = sender;
return this;
}
private MassiveCommand command = null;
public MassiveCommand getCommand() {
return this.command;
}
public Button setCommand(MassiveCommand command) {
this.command = command;
return this;
}
private List<String> args = new MassiveList<>();
public List<String> getArgs() {
return this.args;
}
public Button setArgs(Collection<String> args) {
this.args = new MassiveList<>(args);
return this;
}
public Button setArgs(String... args) {
this.setArgs(Arrays.asList(args));
return this;
}
public boolean clicking = true;
public boolean isClicking() {
return this.clicking;
}
public Button setClicking(boolean clicking) {
this.clicking = clicking;
return this;
}
// -------------------------------------------- //
// FIELDS > LINK
// -------------------------------------------- //
private String link = null;
public String getLink() {
return this.link;
}
public Button setLink(String link) {
this.link = link;
return this;
}
// -------------------------------------------- //
// RENDER
// -------------------------------------------- //
public Mson render() {
// Create
Mson ret = mson(
"[",
Mson.parse(this.getName()),
"]"
);
// Error and Enabled
String error = this.getError();
if (error == null) {
// Get Requirements
List<Requirement> requirements = new MassiveList<>();
requirements.add(RequirementIsPlayer.get());
requirements.addAll(this.getRequirements());
if (this.getCommand() != null) {
requirements.addAll(this.getCommand().getRequirements());
}
// Check Requirements
error = RequirementAbstract.getRequirementsError(requirements, this.getSender(), this.getCommand(), true);
}
boolean enabled = (error == null);
// Check Verbose
if (!enabled && !this.isVerbose()) {
return null;
}
// Colorize
ChatColor color = (enabled ? COLOR_ENABLED : COLOR_DISABLED);
ret = ret.color(color);
// Empower
if (enabled) {
if (this.getCommand() != null) {
// Create the command line
String commandLine = this.getCommand().getCommandLine(this.getArgs());
// Render the corresponding tooltip
String tooltip = MsonEvent.command(commandLine).createTooltip();
// Possibly make command line clicking
if (this.isClicking()) {
commandLine = CmdMassiveCore.get().cmdMassiveCoreClick.getCommandLine(commandLine);
}
// Apply command
ret = ret.command(commandLine);
// Possibly set tooltip to hide the clicking clutter
if (this.isClicking()) {
ret = ret.tooltip(tooltip);
}
} else if (this.getLink() != null) {
ret = ret.link(this.getLink());
} else {
throw new RuntimeException();
}
} else {
ret = ret.tooltip(error);
}
// Pad
if (Boolean.TRUE.equals(this.isPaddingRight())) {
return mson(ret, " ");
}
if (Boolean.FALSE.equals(this.isPaddingRight())) {
return mson(" ", ret);
}
// Return
return ret;
}
}

View File

@ -0,0 +1,7 @@
package com.massivecraft.massivecore;
import org.bukkit.ChatColor;
public interface Colorized {
ChatColor getColor();
}

View File

@ -0,0 +1,39 @@
package com.massivecraft.massivecore;
import com.massivecraft.massivecore.util.MUtil;
import java.util.Map;
import java.util.UUID;
public class ConfServer extends SimpleConfig {
// -------------------------------------------- //
// INSTANCE & CONSTRUCT
// -------------------------------------------- //
private static transient ConfServer i = new ConfServer();
public static ConfServer get() {
return i;
}
public ConfServer() {
super(MassiveCore.get());
}
// -------------------------------------------- //
// FIELDS
// -------------------------------------------- //
public static boolean localPollingEnabled = true;
public static String serverid = UUID.randomUUID().toString();
public static String dburi = "default";
public static Map<String, String> alias2uri = MUtil.map(
"default", "flatfile",
"flatfile", "flatfile://mstore",
"mongodb", "mongodb://localhost:27017/mstore"
);
}

View File

@ -0,0 +1,108 @@
package com.massivecraft.massivecore;
import com.massivecraft.massivecore.util.MUtil;
import java.io.Serializable;
import java.util.Map.Entry;
public class Couple<A, B> implements Entry<A, B>, Cloneable, Serializable {
// -------------------------------------------- //
// CONSTANTS
// -------------------------------------------- //
private static final transient long serialVersionUID = 1L;
// -------------------------------------------- //
// FIELDS: RAW
// -------------------------------------------- //
private final A first;
public A getFirst() {
return this.first;
}
private final B second;
public B getSecond() {
return this.second;
}
// -------------------------------------------- //
// FIELDS: WITH
// -------------------------------------------- //
public Couple<A, B> withFirst(A first) {
return valueOf(first, second);
}
public Couple<A, B> withSecond(B second) {
return valueOf(first, second);
}
// -------------------------------------------- //
// CONSTRUCT
// -------------------------------------------- //
public Couple() {
this(null, null);
}
public Couple(A first, B second) {
this.first = first;
this.second = second;
}
// -------------------------------------------- //
// OVERRIDE: ENTRY
// -------------------------------------------- //
@Override
public A getKey() {
return this.first;
}
@Override
public B getValue() {
return this.second;
}
@Override
public B setValue(B value) {
throw new IllegalStateException("This entry is a couple which is immutable.");
}
// -------------------------------------------- //
// FACTORY: VALUE OF
// -------------------------------------------- //
public static <A, B> Couple<A, B> valueOf(A first, B second) {
return new Couple<>(first, second);
}
// -------------------------------------------- //
// EQUALS
// -------------------------------------------- //
@Override
public boolean equals(Object object) {
if (!(object instanceof Couple<?, ?>)) {
return false;
}
Couple<?, ?> that = (Couple<?, ?>) object;
return MUtil.equals(
this.getFirst(), that.getFirst(),
this.getSecond(), that.getSecond()
);
}
// -------------------------------------------- //
// CLONE
// -------------------------------------------- //
@Override
public Couple<A, B> clone() {
return this;
}
}

View File

@ -0,0 +1,215 @@
package com.massivecraft.massivecore;
import com.massivecraft.massivecore.collections.MassiveSet;
import com.massivecraft.massivecore.predicate.PredicateStartsWithIgnoreCase;
import org.bukkit.Bukkit;
import org.bukkit.event.Event;
import org.bukkit.event.HandlerList;
import org.bukkit.event.Listener;
import org.bukkit.event.block.BlockMultiPlaceEvent;
import org.bukkit.event.block.BlockPlaceEvent;
import org.bukkit.event.player.PlayerInteractEntityEvent;
import org.bukkit.scheduler.BukkitTask;
import java.util.Set;
public abstract class Engine implements Active, Listener, Runnable {
// -------------------------------------------- //
// REGISTRY
// -------------------------------------------- //
private static final transient Set<Engine> allInstances = new MassiveSet<>();
public static Set<Engine> getAllInstances() {
return allInstances;
}
// -------------------------------------------- //
// PLUGIN
// -------------------------------------------- //
private MassivePlugin plugin = null;
public MassivePlugin getPlugin() {
return this.plugin;
}
public boolean hasPlugin() {
return this.getPlugin() != null;
}
public void setPlugin(MassivePlugin plugin) {
this.plugin = plugin;
}
public void setPluginSoft(MassivePlugin plugin) {
if (this.hasPlugin()) {
return;
}
this.plugin = plugin;
}
// -------------------------------------------- //
// TASK
// -------------------------------------------- //
private Long delay = 0L;
public Long getDelay() {
return this.delay;
}
public void setDelay(Long delay) {
this.delay = delay;
}
private Long period = null;
public Long getPeriod() {
return this.period;
}
public void setPeriod(Long period) {
this.period = period;
}
private boolean sync = true;
public boolean isSync() {
return this.sync;
}
public void setSync(boolean sync) {
this.sync = sync;
}
private BukkitTask task = null;
public BukkitTask getTask() {
return this.task;
}
public Integer getTaskId() {
return this.task == null ? null : this.task.getTaskId();
}
@Override
public void run() {
}
// -------------------------------------------- //
// ACTIVE
// -------------------------------------------- //
@Override
public boolean isActive() {
return getAllInstances().contains(this);
}
@Override
public void setActive(boolean active) {
this.setActiveListener(active);
this.setActiveTask(active);
this.setActiveInner(active);
if (active) {
getAllInstances().add(this);
} else {
getAllInstances().remove(this);
}
}
@Override
public MassivePlugin setActivePlugin(MassivePlugin plugin) {
this.setPluginSoft(plugin);
return null;
}
@Override
public MassivePlugin getActivePlugin() {
return this.getPlugin();
}
@Override
public void setActive(MassivePlugin plugin) {
this.setActivePlugin(plugin);
this.setActive(plugin != null);
}
// -------------------------------------------- //
// ACTIVE > EVENTS
// -------------------------------------------- //
public void setActiveListener(boolean active) {
if (active) {
// Support without at load
MassivePlugin plugin = this.getPlugin();
if (plugin.isEnabled()) {
Bukkit.getPluginManager().registerEvents(this, this.getPlugin());
}
} else {
HandlerList.unregisterAll(this);
}
}
// -------------------------------------------- //
// ACTIVE > TASK
// -------------------------------------------- //
public void setActiveTask(boolean active) {
if (active) {
if (this.getPeriod() != null) {
// Support without at load
MassivePlugin plugin = this.getPlugin();
if (plugin.isEnabled()) {
if (this.isSync()) {
this.task = Bukkit.getScheduler().runTaskTimer(this.getPlugin(), this, this.getDelay(), this.getPeriod());
} else {
this.task = Bukkit.getScheduler().runTaskTimerAsynchronously(this.getPlugin(), this, this.getDelay(), this.getPeriod());
}
}
}
} else {
if (this.task != null) {
this.task.cancel();
this.task = null;
}
}
}
// -------------------------------------------- //
// ACTIVE > INNER
// -------------------------------------------- //
public void setActiveInner(boolean active) {
// NOTE: Here you can add some extra custom logic.
}
// -------------------------------------------- //
// IS FAKE
// -------------------------------------------- //
public static final PredicateStartsWithIgnoreCase STARTING_WITH_FAKE = PredicateStartsWithIgnoreCase.get("fake");
public static boolean isFake(Event event) {
final Class<?> clazz = event.getClass();
if (event instanceof BlockPlaceEvent) {
return !BlockPlaceEvent.class.equals(clazz) && !BlockMultiPlaceEvent.class.equals(clazz);
} else {
return STARTING_WITH_FAKE.apply(clazz.getSimpleName());
}
}
// -------------------------------------------- //
// IS OFF HAND
// -------------------------------------------- //
public static boolean isOffHand(PlayerInteractEntityEvent event) {
try {
return event.getHand() == org.bukkit.inventory.EquipmentSlot.OFF_HAND;
} catch (Throwable t) {
return false;
}
}
}

View File

@ -0,0 +1,91 @@
package com.massivecraft.massivecore;
public final class HeatData {
// -------------------------------------------- //
// CONSTANTS
// -------------------------------------------- //
public static final transient double HEAT_MIN = 0D;
public static final transient double HEAT_HIGH = 1D;
public static final transient long MILLIS_CALC_EPSILON = 50;
// -------------------------------------------- //
// FIELDS: RAW
// -------------------------------------------- //
private final double heat;
public double getHeat() {
return this.heat;
}
private final long lastCalcMillis;
public long getLastCalcMillis() {
return this.lastCalcMillis;
}
// -------------------------------------------- //
// FIELDS: INSPECT
// -------------------------------------------- //
public double getOverheat() {
return this.getHeat() - HEAT_HIGH;
}
public boolean isOverheated() {
return this.getOverheat() > 0;
}
// -------------------------------------------- //
// FIELDS: WITH
// -------------------------------------------- //
public HeatData withHeat(double heat) {
return new HeatData(heat, lastCalcMillis);
}
public HeatData withLastCalcMillis(long lastCalcMillis) {
return new HeatData(heat, lastCalcMillis);
}
// -------------------------------------------- //
// CONSTRUCT
// -------------------------------------------- //
private HeatData(double heat, long lastCalcMillis) {
this.heat = Math.max(0, heat);
this.lastCalcMillis = lastCalcMillis;
}
private HeatData() {
this.heat = 0;
this.lastCalcMillis = 0;
}
// -------------------------------------------- //
// FACTORY: VALUE OF
// -------------------------------------------- //
public static HeatData valueOf(double heat, long lastCalcMillis) {
return new HeatData(heat, lastCalcMillis);
}
// -------------------------------------------- //
// FACTORY: RECALCULATED
// -------------------------------------------- //
public HeatData recalculated(long now, double heatPerMilli) {
if (this.lastCalcMillis + MILLIS_CALC_EPSILON >= now) {
return this;
}
long deltaMillis = now - this.lastCalcMillis;
double heatDelta = heatPerMilli * deltaMillis;
double heatTarget = this.heat + heatDelta;
heatTarget = Math.max(0, heatTarget);
return valueOf(heatTarget, now);
}
}

View File

@ -0,0 +1,94 @@
package com.massivecraft.massivecore;
public abstract class Heatable {
// -------------------------------------------- //
// ABSTRACT
// -------------------------------------------- //
public abstract HeatData getData();
public abstract void setData(HeatData data);
public abstract double getHeatPerMilli();
public abstract double getHeatPerExecution();
// -------------------------------------------- //
// CUSTOM
// -------------------------------------------- //
private HeatData getRecalculatedData(double heatPerMilli) {
long now = System.currentTimeMillis();
HeatData data = this.getData().recalculated(now, heatPerMilli);
this.setData(data);
return data;
}
public void addHeat(double heatPerMilli, double heat) {
long now = System.currentTimeMillis();
HeatData data = this.getData().recalculated(now, heatPerMilli);
data = data.withHeat(data.getHeat() + heat);
this.setData(data);
}
public double getHeat(double heatPerMilli) {
HeatData data = getRecalculatedData(heatPerMilli);
return data.getHeat();
}
public boolean isOverheated(double heatPerMilli) {
HeatData data = getRecalculatedData(heatPerMilli);
return data.isOverheated();
}
public double getOverheat(double heatPerMilli) {
HeatData data = getRecalculatedData(heatPerMilli);
return data.getOverheat();
}
public long getCooldownMillisLeft(double heatPerMilli) {
double overheat = this.getOverheat(heatPerMilli);
return (long) (-overheat / heatPerMilli);
}
// -------------------------------------------- //
// DEFAULT
// -------------------------------------------- //
public void addHeat(double heat) {
this.addHeat(this.getHeatPerMilli(), heat);
}
public void addHeat() {
this.addHeat(this.getHeatPerExecution());
}
public double getHeat() {
return this.getHeat(this.getHeatPerMilli());
}
public boolean isOverheated() {
return this.isOverheated(this.getHeatPerMilli());
}
public double getOverheat() {
return this.getOverheat(this.getHeatPerMilli());
}
public long getCooldownMillisLeft() {
return this.getCooldownMillisLeft(this.getHeatPerMilli());
}
// -------------------------------------------- //
// UTIL
// -------------------------------------------- //
public static double calcHeatPerExecution(long executionCount, long periodMillis) {
return 1D / (double) executionCount;
}
public static double calcHeatPerMilli(long executionCount, long periodMillis) {
return -1D / (double) periodMillis;
}
}

View File

@ -0,0 +1,5 @@
package com.massivecraft.massivecore;
public interface Identified {
String getId();
}

View File

@ -0,0 +1,210 @@
package com.massivecraft.massivecore;
import com.massivecraft.massivecore.collections.MassiveList;
import com.massivecraft.massivecore.predicate.PredicateIntegration;
import com.massivecraft.massivecore.util.Txt;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.server.PluginDisableEvent;
import org.bukkit.event.server.PluginEnableEvent;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.function.Predicate;
public class Integration extends Engine {
// -------------------------------------------- //
// NAME
// -------------------------------------------- //
private String name = null;
public String getName() {
return this.name;
}
public Integration setName(String name) {
this.name = name;
return this;
}
// -------------------------------------------- //
// PREDICATE
// -------------------------------------------- //
private Predicate<Integration> predicate = PredicateIntegration.get();
public Predicate<Integration> getPredicate() {
return this.predicate;
}
public Integration setPredicate(Predicate<Integration> predicate) {
this.predicate = predicate;
return this;
}
private List<String> pluginNames = Collections.emptyList();
public List<String> getPluginNames() {
return this.pluginNames;
}
public Integration setPluginNames(Collection<String> pluginNames) {
this.pluginNames = new MassiveList<>(pluginNames);
return this;
}
public Integration setPluginNames(String... pluginNames) {
return this.setPluginNames(Arrays.asList(pluginNames));
}
public Integration setPluginName(String pluginName) {
return this.setPluginNames(pluginName);
}
private List<String> classNames = Collections.emptyList();
public List<String> getClassNames() {
return this.classNames;
}
public Integration setClassNames(Collection<String> classNames) {
this.classNames = new MassiveList<>(classNames);
return this;
}
public Integration setClassNames(String... classNames) {
return this.setClassNames(Arrays.asList(classNames));
}
public Integration setClassName(String className) {
return this.setClassNames(className);
}
// -------------------------------------------- //
// INTEGRATION ACTIVE
// -------------------------------------------- //
// NOTE: We must make use of duplicate information to avoid triggering class loads.
private boolean integrationActive = false;
public boolean isIntegrationActive() {
return this.integrationActive;
}
public void setIntegrationActive(Boolean integrationActive) {
// Calc
if (integrationActive == null) {
integrationActive = this.getPredicate().test(this);
}
// NoChange
if (this.isIntegrationActive() == integrationActive) {
return;
}
try {
this.setIntegrationActiveEngines(integrationActive);
this.setIntegrationActiveInner(integrationActive);
this.integrationActive = integrationActive;
String message = Txt.parse(integrationActive ? "<g>Integration Activated <h>%s" : "<b>Integration Deactivated <h>%s", this.getName());
this.getPlugin().log(message);
} catch (Throwable t) {
String message = Txt.parse(integrationActive ? "<b>Integration Activation <h>%s<b> FAILED:" : "<b>Integration Deactivation <h>%s<b> FAILED:", this.getName());
this.getPlugin().log(message);
t.printStackTrace();
}
}
public void setIntegrationActive() {
this.setIntegrationActive(null);
}
// -------------------------------------------- //
// INTEGRATION ACTIVE > ENGINES
// -------------------------------------------- //
public void setIntegrationActiveEngines(boolean active) {
for (Engine engine : this.getEngines()) {
engine.setPluginSoft(this.getPlugin());
engine.setActive(active);
}
}
public List<Engine> getEngines() {
Engine engine = this.getEngine();
if (engine == null) {
return Collections.emptyList();
}
return Collections.singletonList(engine);
}
public Engine getEngine() {
return null;
}
// -------------------------------------------- //
// INTEGRATION ACTIVE > INNER
// -------------------------------------------- //
public void setIntegrationActiveInner(boolean active) {
}
// -------------------------------------------- //
// CONSTRUCT
// -------------------------------------------- //
public Integration() {
// TODO: Improve upon this one
this.setName(this.getClass().getSimpleName());
// TODO: Is this period fine?
this.setPeriod(10L);
}
// -------------------------------------------- //
// TICK > ACTIVE
// -------------------------------------------- //
@Override
public void setActiveInner(boolean active) {
if (active) {
this.setIntegrationActive();
} else {
this.setIntegrationActive(false);
}
}
// -------------------------------------------- //
// TICK > RUN
// -------------------------------------------- //
@Override
public void run() {
this.setIntegrationActive();
}
// -------------------------------------------- //
// TICK > EVENT LISTENERS
// -------------------------------------------- //
@EventHandler(priority = EventPriority.MONITOR)
public void onPluginDisable(PluginDisableEvent event) {
if (this.getPlugin().equals(event.getPlugin())) {
this.setIntegrationActive(false);
} else {
this.setIntegrationActive();
}
}
@EventHandler(priority = EventPriority.MONITOR)
public void onPluginEnable(PluginEnableEvent event) {
this.setIntegrationActive();
}
}

View File

@ -0,0 +1,26 @@
package com.massivecraft.massivecore;
import com.massivecraft.massivecore.mson.Mson;
import org.bukkit.ChatColor;
import static com.massivecraft.massivecore.mson.Mson.mson;
public class Lang {
public static final String PERM_DEFAULT_DENIED_FORMAT = "<b>You don't have permission to <h>%s<b>.";
public static final String PERM_DEFAULT_DESCRIPTION = "do that";
public static final String COMMAND_SENDER_MUST_BE_PLAYER = "<b>This command can only be used by ingame players.";
public static final String COMMAND_SENDER_MUSNT_BE_PLAYER = "<b>This command can not be used by ingame players.";
public static final String COMMAND_TITLES_MUST_BE_AVAILABLE = "<b>This command requires the Minecraft 1.8 titles.";
public static final String COMMAND_TOO_FEW_ARGUMENTS = "<b>Not enough command input. <i>You should use it like this:";
public static final String COMMAND_TOO_MANY_ARGUMENTS = "<b>Too much command input %s<b>.";
public static final String COMMAND_TOO_MANY_ARGUMENTS2 = "<i>You should use the command like this:";
public static final Mson COMMAND_REPLACEMENT = mson("REPLACEMENT");
public static final Mson COMMAND_CHILD_AMBIGUOUS = mson("The sub command ", COMMAND_REPLACEMENT, " is ambiguous.").color(ChatColor.YELLOW);
public static final Mson COMMAND_CHILD_NONE = mson("The sub command ", COMMAND_REPLACEMENT, " couldn't be found.").color(ChatColor.YELLOW);
public static final Mson COMMAND_CHILD_HELP = mson("Use ", COMMAND_REPLACEMENT, " to see all commands.").color(ChatColor.YELLOW);
public static final String COMMAND_TOO_MANY_TAB_SUGGESTIONS = "<h>%d <b>tab completions available. Be more specific and try again.";
}

View File

@ -0,0 +1,129 @@
package com.massivecraft.massivecore;
import com.massivecraft.massivecore.collections.MassiveMap;
import com.massivecraft.massivecore.event.EventMassiveCoreLog;
import com.massivecraft.massivecore.mixin.MixinLog;
import org.bukkit.plugin.Plugin;
import java.util.Map;
import java.util.logging.Level;
public class Log {
// -------------------------------------------- //
// CONSTANTS
// -------------------------------------------- //
public static final String FIELD_TIMESTAMP = "timestamp";
public static final String FIELD_PLUGIN = "plugin";
public static final String FIELD_PLAYER_OBJECT = "player_object";
public static final String FIELD_LEVEL = "level";
public static final String FIELD_TYPE = "type";
public static final String FIELD_MESSAGE = "message";
// -------------------------------------------- //
// FIELDS
// -------------------------------------------- //
private Map<String, Object> fields = new MassiveMap<>();
public Map<String, Object> getFields() {
return this.fields;
}
// -------------------------------------------- //
// CONSTRUCT
// -------------------------------------------- //
public Log() {
this
.timestamp(System.currentTimeMillis())
;
}
// -------------------------------------------- //
// ACCESS > RAW
// -------------------------------------------- //
public Log set(String key, Object value) {
if (value != null) {
this.getFields().put(key, value);
} else {
this.getFields().remove(key);
}
return this;
}
public <T> T get(String key) {
return (T) this.getFields().get(key);
}
// -------------------------------------------- //
// ACCESS > SUGAR
// -------------------------------------------- //
public Log timestamp(Long timestamp) {
return this.set(FIELD_TIMESTAMP, timestamp);
}
public Long timestamp() {
return this.get(FIELD_TIMESTAMP);
}
public Log plugin(Plugin plugin) {
return this.set(FIELD_PLUGIN, plugin);
}
public Plugin plugin() {
return this.get(FIELD_PLUGIN);
}
public Log playerObject(Object playerObject) {
return this.set(FIELD_PLAYER_OBJECT, playerObject);
}
public Object playerObject() {
return this.get(FIELD_PLAYER_OBJECT);
}
public Log level(Level level) {
return this.set(FIELD_LEVEL, level);
}
public Level level() {
return this.get(FIELD_LEVEL);
}
public Log type(String category) {
return this.set(FIELD_TYPE, category);
}
public String type() {
return this.get(FIELD_TYPE);
}
public Log message(String message) {
return this.set(FIELD_MESSAGE, message);
}
public String message() {
return this.get(FIELD_MESSAGE);
}
// -------------------------------------------- //
// SEND
// -------------------------------------------- //
public void send() {
// Run Event
EventMassiveCoreLog event = new EventMassiveCoreLog(this);
event.run();
if (event.isCancelled()) {
return;
}
// Send Through Mixin
MixinLog.get().send(this);
}
}

View File

@ -0,0 +1,407 @@
package com.massivecraft.massivecore;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonArray;
import com.google.gson.JsonNull;
import com.google.gson.JsonObject;
import com.google.gson.JsonPrimitive;
import com.massivecraft.massivecore.adapter.AdapterBackstringSet;
import com.massivecraft.massivecore.adapter.AdapterEntityInternalMap;
import com.massivecraft.massivecore.adapter.AdapterEntry;
import com.massivecraft.massivecore.adapter.AdapterJsonElement;
import com.massivecraft.massivecore.adapter.AdapterMassiveList;
import com.massivecraft.massivecore.adapter.AdapterMassiveMap;
import com.massivecraft.massivecore.adapter.AdapterMassiveSet;
import com.massivecraft.massivecore.adapter.AdapterMassiveTreeMap;
import com.massivecraft.massivecore.adapter.AdapterMassiveTreeSet;
import com.massivecraft.massivecore.adapter.AdapterModdedEnumType;
import com.massivecraft.massivecore.adapter.AdapterMson;
import com.massivecraft.massivecore.adapter.AdapterMsonEvent;
import com.massivecraft.massivecore.adapter.AdapterSound;
import com.massivecraft.massivecore.adapter.AdapterUUID;
import com.massivecraft.massivecore.cmd.CmdMassiveCore;
import com.massivecraft.massivecore.cmd.CmdMassiveCoreBuffer;
import com.massivecraft.massivecore.cmd.CmdMassiveCoreClick;
import com.massivecraft.massivecore.cmd.CmdMassiveCoreCmdurl;
import com.massivecraft.massivecore.cmd.CmdMassiveCoreStore;
import com.massivecraft.massivecore.cmd.CmdMassiveCoreUsys;
import com.massivecraft.massivecore.collections.BackstringSet;
import com.massivecraft.massivecore.collections.MassiveList;
import com.massivecraft.massivecore.collections.MassiveListDef;
import com.massivecraft.massivecore.collections.MassiveMap;
import com.massivecraft.massivecore.collections.MassiveMapDef;
import com.massivecraft.massivecore.collections.MassiveSet;
import com.massivecraft.massivecore.collections.MassiveSetDef;
import com.massivecraft.massivecore.collections.MassiveTreeMap;
import com.massivecraft.massivecore.collections.MassiveTreeMapDef;
import com.massivecraft.massivecore.collections.MassiveTreeSet;
import com.massivecraft.massivecore.collections.MassiveTreeSetDef;
import com.massivecraft.massivecore.command.type.RegistryType;
import com.massivecraft.massivecore.engine.EngineMassiveCoreChestGui;
import com.massivecraft.massivecore.engine.EngineMassiveCoreClean;
import com.massivecraft.massivecore.engine.EngineMassiveCoreCollTick;
import com.massivecraft.massivecore.engine.EngineMassiveCoreCommandRegistration;
import com.massivecraft.massivecore.engine.EngineMassiveCoreCommandSet;
import com.massivecraft.massivecore.engine.EngineMassiveCoreDatabase;
import com.massivecraft.massivecore.engine.EngineMassiveCoreDestination;
import com.massivecraft.massivecore.engine.EngineMassiveCoreGank;
import com.massivecraft.massivecore.engine.EngineMassiveCoreLorePriority;
import com.massivecraft.massivecore.engine.EngineMassiveCoreMain;
import com.massivecraft.massivecore.engine.EngineMassiveCorePlayerLeave;
import com.massivecraft.massivecore.engine.EngineMassiveCorePlayerState;
import com.massivecraft.massivecore.engine.EngineMassiveCorePlayerUpdate;
import com.massivecraft.massivecore.engine.EngineMassiveCoreScheduledTeleport;
import com.massivecraft.massivecore.engine.EngineMassiveCoreTeleportMixinCause;
import com.massivecraft.massivecore.engine.EngineMassiveCoreVariable;
import com.massivecraft.massivecore.engine.EngineMassiveCoreWorldNameSet;
import com.massivecraft.massivecore.entity.MassiveCoreMConf;
import com.massivecraft.massivecore.entity.MassiveCoreMConfColl;
import com.massivecraft.massivecore.entity.MultiverseColl;
import com.massivecraft.massivecore.entity.migrator.MigratorMassiveCoreMConf001CleanInactivity;
import com.massivecraft.massivecore.integration.vault.IntegrationVault;
import com.massivecraft.massivecore.mixin.MixinActionbar;
import com.massivecraft.massivecore.mixin.MixinActual;
import com.massivecraft.massivecore.mixin.MixinCommand;
import com.massivecraft.massivecore.mixin.MixinDisplayName;
import com.massivecraft.massivecore.mixin.MixinEvent;
import com.massivecraft.massivecore.mixin.MixinGamemode;
import com.massivecraft.massivecore.mixin.MixinKick;
import com.massivecraft.massivecore.mixin.MixinLog;
import com.massivecraft.massivecore.mixin.MixinMessage;
import com.massivecraft.massivecore.mixin.MixinModification;
import com.massivecraft.massivecore.mixin.MixinPlayed;
import com.massivecraft.massivecore.mixin.MixinRecipe;
import com.massivecraft.massivecore.mixin.MixinSenderPs;
import com.massivecraft.massivecore.mixin.MixinTeleport;
import com.massivecraft.massivecore.mixin.MixinTitle;
import com.massivecraft.massivecore.mixin.MixinVisibility;
import com.massivecraft.massivecore.mixin.MixinWorld;
import com.massivecraft.massivecore.mson.Mson;
import com.massivecraft.massivecore.mson.MsonEvent;
import com.massivecraft.massivecore.nms.NmsBasics;
import com.massivecraft.massivecore.nms.NmsBoard;
import com.massivecraft.massivecore.nms.NmsChat;
import com.massivecraft.massivecore.nms.NmsEntityDamageEvent;
import com.massivecraft.massivecore.nms.NmsEntityGet;
import com.massivecraft.massivecore.nms.NmsItemStackTooltip;
import com.massivecraft.massivecore.nms.NmsPermissions;
import com.massivecraft.massivecore.nms.NmsRecipe;
import com.massivecraft.massivecore.nms.NmsSkullMeta;
import com.massivecraft.massivecore.ps.PS;
import com.massivecraft.massivecore.ps.PSAdapter;
import com.massivecraft.massivecore.store.EntityInternalMap;
import com.massivecraft.massivecore.store.ModificationPollerLocal;
import com.massivecraft.massivecore.store.ModificationPollerRemote;
import com.massivecraft.massivecore.util.BoardUtil;
import com.massivecraft.massivecore.util.ContainerUtil;
import com.massivecraft.massivecore.util.EventUtil;
import com.massivecraft.massivecore.util.IdUtil;
import com.massivecraft.massivecore.util.IntervalUtil;
import com.massivecraft.massivecore.util.InventoryUtil;
import com.massivecraft.massivecore.util.MUtil;
import com.massivecraft.massivecore.util.PeriodUtil;
import com.massivecraft.massivecore.util.PlayerUtil;
import com.massivecraft.massivecore.util.RecipeUtil;
import com.massivecraft.massivecore.util.ReflectionUtil;
import com.massivecraft.massivecore.util.SignUtil;
import com.massivecraft.massivecore.util.SmokeUtil;
import com.massivecraft.massivecore.util.TimeDiffUtil;
import com.massivecraft.massivecore.util.TimeUnit;
import com.massivecraft.massivecore.util.Txt;
import org.bukkit.Bukkit;
import org.bukkit.Sound;
import java.lang.reflect.Modifier;
import java.util.List;
import java.util.Map.Entry;
import java.util.Random;
import java.util.Set;
import java.util.UUID;
public class MassiveCore extends MassivePlugin {
// -------------------------------------------- //
// COMMON CONSTANTS
// -------------------------------------------- //
public final static String INSTANCE = "instance";
public final static String DEFAULT = "default";
public static final String NONE = Txt.parse("<silver>none");
public final static Set<String> NOTHING = MUtil.treeset("", "none", "null", "nothing");
public final static Set<String> REMOVE = MUtil.treeset("clear", "c", "delete", "del", "d", "erase", "e", "remove", "rem", "r", "reset", "res");
public final static Set<String> NOTHING_REMOVE = MUtil.treeset("", "none", "null", "nothing", "clear", "c", "delete", "del", "d", "erase", "e", "remove", "rem", "r", "reset", "res");
// -------------------------------------------- //
// INSTANCE & CONSTRUCT
// -------------------------------------------- //
private static MassiveCore i;
public static MassiveCore get() {
return i;
}
public MassiveCore() {
i = this;
}
// -------------------------------------------- //
// STATIC
// -------------------------------------------- //
public static Random random = new Random();
public static Gson gson = getMassiveCoreGsonBuilder().create();
public static GsonBuilder getMassiveCoreGsonBuilder() {
// Create
GsonBuilder ret = new GsonBuilder();
// Basic Behavior
ret.setPrettyPrinting();
ret.disableHtmlEscaping();
ret.excludeFieldsWithModifiers(Modifier.TRANSIENT);
// Raw Adapters
ret.registerTypeAdapter(JsonNull.class, AdapterJsonElement.get());
ret.registerTypeAdapter(JsonPrimitive.class, AdapterJsonElement.get());
ret.registerTypeAdapter(JsonArray.class, AdapterJsonElement.get());
ret.registerTypeAdapter(JsonObject.class, AdapterJsonElement.get());
// Enumeration Annotation Dodge
ret.registerTypeAdapterFactory(AdapterModdedEnumType.ENUM_FACTORY);
// Massive Containers
ret.registerTypeAdapter(MassiveList.class, AdapterMassiveList.get());
ret.registerTypeAdapter(MassiveListDef.class, AdapterMassiveList.get());
ret.registerTypeAdapter(MassiveMap.class, AdapterMassiveMap.get());
ret.registerTypeAdapter(MassiveMapDef.class, AdapterMassiveMap.get());
ret.registerTypeAdapter(MassiveSet.class, AdapterMassiveSet.get());
ret.registerTypeAdapter(MassiveSetDef.class, AdapterMassiveSet.get());
ret.registerTypeAdapter(MassiveTreeMap.class, AdapterMassiveTreeMap.get());
ret.registerTypeAdapter(MassiveTreeMapDef.class, AdapterMassiveTreeMap.get());
ret.registerTypeAdapter(MassiveTreeSet.class, AdapterMassiveTreeSet.get());
ret.registerTypeAdapter(MassiveTreeSetDef.class, AdapterMassiveTreeSet.get());
// Entries (Is this still needed?)
ret.registerTypeAdapter(Entry.class, AdapterEntry.get());
// Assorted Custom
ret.registerTypeAdapter(BackstringSet.class, AdapterBackstringSet.get());
ret.registerTypeAdapter(PS.class, PSAdapter.get());
ret.registerTypeAdapter(Sound.class, AdapterSound.get());
ret.registerTypeAdapter(UUID.class, AdapterUUID.get());
// Mson
ret.registerTypeAdapter(Mson.class, AdapterMson.get());
ret.registerTypeAdapter(MsonEvent.class, AdapterMsonEvent.get());
// Storage
ret.registerTypeAdapter(EntityInternalMap.class, AdapterEntityInternalMap.get());
// Return
return ret;
}
public static String getServerId() {
return ConfServer.serverid;
}
public static String getTaskServerId() {
return MassiveCoreMConf.get().taskServerId;
}
public static boolean isTaskServer() {
String taskServerId = getTaskServerId();
if (taskServerId == null) {
return true;
}
if (getServerId().equals(taskServerId)) {
return true;
}
return false;
}
// -------------------------------------------- //
// LOAD
// -------------------------------------------- //
@Override
public void onLoadInner() {
// These util classes are not automatically loaded/resolved when MassiveCore is being loaded.
// However they need to be loaded to ensure async safety.
// This fixes a race condition within the asynchronous class loader (LinkageError).
ReflectionUtil.forceLoadClasses(
ContainerUtil.class,
EventUtil.class,
IntervalUtil.class,
InventoryUtil.class,
PeriodUtil.class,
RecipeUtil.class,
SignUtil.class,
SmokeUtil.class,
TimeUnit.class,
TimeDiffUtil.class
);
}
// -------------------------------------------- //
// ENABLE
// -------------------------------------------- //
@Override
public void onEnableInner() {
// This is safe since all plugins using Persist should bukkit-depend this plugin.
// Note this one must be before preEnable. dooh.
// TODO: Create something like "deinit all" (perhaps a forloop) to readd this.
// TODO: Test and ensure reload compat.
// Coll.instances.clear();
// Load Server Config
ConfServer.get().load();
// Setup IdUtil
IdUtil.setup();
// Setup RegistryType
RegistryType.registerAll();
// Activate
this.activateAuto();
// These must be activated after nms
this.activate(
// Util
PlayerUtil.class,
BoardUtil.class
);
// Start the examine threads
// Start AFTER initializing the MConf, because they rely on the MConf.
if (ConfServer.localPollingEnabled) {
ModificationPollerLocal.get().start();
}
ModificationPollerRemote.get().start();
// Delete Files (at once and additionally after all plugins loaded)
MassiveCoreTaskDeleteFiles.get().run();
Bukkit.getScheduler().scheduleSyncDelayedTask(this, MassiveCoreTaskDeleteFiles.get());
}
// These are overriden because the reflection trick was buggy and didn't work on all systems
@Override
public List<Class<?>> getClassesActiveMigrators() {
return MUtil.list(
MigratorMassiveCoreMConf001CleanInactivity.class
);
}
@Override
public List<Class<?>> getClassesActiveColls() {
return MUtil.list(
MassiveCoreMConfColl.class,
MultiverseColl.class
);
}
@Override
public List<Class<?>> getClassesActiveNms() {
return MUtil.list(
NmsBasics.class,
NmsBoard.class,
NmsChat.class,
NmsEntityDamageEvent.class,
NmsEntityGet.class,
NmsItemStackTooltip.class,
NmsPermissions.class,
NmsSkullMeta.class,
NmsRecipe.class
);
}
@Override
public List<Class<?>> getClassesActiveCommands() {
return MUtil.list(
CmdMassiveCore.class,
CmdMassiveCoreBuffer.class,
CmdMassiveCoreClick.class,
CmdMassiveCoreCmdurl.class,
CmdMassiveCoreStore.class,
CmdMassiveCoreUsys.class
);
}
@Override
public List<Class<?>> getClassesActiveEngines() {
return MUtil.list(
EngineMassiveCoreChestGui.class,
EngineMassiveCoreClean.class,
EngineMassiveCoreCollTick.class,
EngineMassiveCoreCommandRegistration.class,
EngineMassiveCoreCommandSet.class,
EngineMassiveCoreDatabase.class,
EngineMassiveCoreDestination.class,
EngineMassiveCoreGank.class,
EngineMassiveCoreLorePriority.class,
EngineMassiveCoreMain.class,
EngineMassiveCorePlayerLeave.class,
EngineMassiveCorePlayerState.class,
EngineMassiveCorePlayerUpdate.class,
EngineMassiveCoreScheduledTeleport.class,
EngineMassiveCoreTeleportMixinCause.class,
EngineMassiveCoreVariable.class,
EngineMassiveCoreWorldNameSet.class
);
}
@Override
public List<Class<?>> getClassesActiveIntegrations() {
return MUtil.list(
IntegrationVault.class
);
}
@Override
public List<Class<?>> getClassesActiveMixins() {
return MUtil.list(
MixinEvent.class,
MixinActionbar.class,
MixinActual.class,
MixinCommand.class,
MixinDisplayName.class,
MixinGamemode.class,
MixinKick.class,
MixinLog.class,
MixinMessage.class,
MixinModification.class,
MixinPlayed.class,
MixinRecipe.class,
MixinSenderPs.class,
MixinTeleport.class,
MixinTitle.class,
MixinVisibility.class,
MixinWorld.class
);
}
@Override
public List<Class<?>> getClassesActiveTests() {
return MUtil.list();
}
// -------------------------------------------- //
// DISABLE
// -------------------------------------------- //
@Override
public void onDisable() {
super.onDisable();
ModificationPollerLocal.get().interrupt();
ModificationPollerRemote.get().interrupt();
MassiveCoreTaskDeleteFiles.get().run();
IdUtil.saveCachefileDatas();
}
}

View File

@ -0,0 +1,93 @@
package com.massivecraft.massivecore;
import com.massivecraft.massivecore.util.PermissionUtil;
import org.bukkit.permissions.Permissible;
public enum MassiveCorePerm implements Identified {
// -------------------------------------------- //
// ENUM
// -------------------------------------------- //
/*BASECOMMAND,
TEST,
ID,
HEARSOUND,
STORE,
STORE_STATS,
STORE_LISTCOLLS,
STORE_COPYDB,
STORE_CLEAN,
USYS,
USYS_MULTIVERSE,
USYS_MULTIVERSE_SHOW,
USYS_MULTIVERSE_NEW,
USYS_MULTIVERSE_DEL,
USYS_UNIVERSE,
USYS_UNIVERSE_NEW,
USYS_UNIVERSE_DEL,
USYS_UNIVERSE_CLEAR,
USYS_WORLD,
USYS_ASPECT,
USYS_ASPECT_SHOW,
USYS_ASPECT_USE,
BUFFER,
BUFFER_PRINT,
BUFFER_CLEAR,
BUFFER_SET,
BUFFER_ADD,
BUFFER_WHITESPACE,
CMDURL,
SPONSOR,
CLICK,
NOTPDELAY,*/
CONFIG,
VERSION,
USYS_MULTIVERSE_LIST,
USYS_ASPECT_LIST,
VARIABLE_BOOK,
VARIABLE_BUFFER,
// END OF LIST
;
// -------------------------------------------- //
// FIELDS
// -------------------------------------------- //
private final String id;
@Override
public String getId() {
return this.id;
}
// -------------------------------------------- //
// CONSTRUCT
// -------------------------------------------- //
MassiveCorePerm() {
this.id = PermissionUtil.createPermissionId(MassiveCore.get(), this);
}
// -------------------------------------------- //
// HAS
// -------------------------------------------- //
public boolean has(Permissible permissible, boolean verboose) {
return PermissionUtil.hasPermission(permissible, this, verboose);
}
public boolean has(Permissible permissible) {
return PermissionUtil.hasPermission(permissible, this);
}
public void hasOrThrow(Permissible permissible) throws MassiveException {
PermissionUtil.hasPermissionOrThrow(permissible, this);
}
}

View File

@ -0,0 +1,38 @@
package com.massivecraft.massivecore;
import com.massivecraft.massivecore.entity.MassiveCoreMConf;
import java.io.File;
public class MassiveCoreTaskDeleteFiles implements Runnable {
// -------------------------------------------- //
// INSTANCE & CONSTRUCT
// -------------------------------------------- //
private static MassiveCoreTaskDeleteFiles i = new MassiveCoreTaskDeleteFiles();
public static MassiveCoreTaskDeleteFiles get() {
return i;
}
// -------------------------------------------- //
// OVERRIDE
// -------------------------------------------- //
@Override
public void run() {
// Some people got null pointers
if (MassiveCoreMConf.get() == null) {
throw new NullPointerException("mconf");
}
if (MassiveCoreMConf.get().deleteFiles == null) {
throw new NullPointerException("deleteFiles");
}
for (String deleteFile : MassiveCoreMConf.get().deleteFiles) {
File file = new File(deleteFile);
file.delete();
}
}
}

View File

@ -0,0 +1,85 @@
package com.massivecraft.massivecore;
import com.massivecraft.massivecore.mson.Mson;
import java.util.Arrays;
import java.util.Collection;
public class MassiveException extends Exception {
// -------------------------------------------- //
// CONSTANTS
// -------------------------------------------- //
private static final long serialVersionUID = 1L;
// -------------------------------------------- //
// MESSAGES
// -------------------------------------------- //
protected Mson messages = Mson.mson();
public boolean hasMessages() {
return !this.messages.isEmpty();
}
public Mson getMessages() {
return this.messages;
}
@Override
public String getMessage() {
return this.messages.toPlain(true);
}
// Set single
public MassiveException setMessage(Object part) {
this.messages = Mson.mson(part);
return this;
}
public MassiveException setMsg(String msg) {
this.messages = Mson.parse(msg);
return this;
}
public MassiveException setMsg(String msg, Object... objects) {
this.messages = Mson.parse(msg, objects);
return this;
}
// Add single
public MassiveException addMessage(Object part) {
// Only add a newline if not empty.
Mson mson = this.messages.isEmpty() ? Mson.mson(part) : Mson.mson("\n", part);
this.messages = this.messages.add(mson);
return this;
}
public MassiveException addMsg(String msg) {
return this.addMessage(Mson.parse(msg));
}
public MassiveException addMsg(String msg, Object... args) {
return this.addMessage(Mson.parse(msg, args));
}
// Set several
public MassiveException setMsgs(Collection<String> msgs) {
this.messages = Mson.parse(msgs);
return this;
}
public MassiveException setMsgs(String... msgs) {
return this.setMsgs(Arrays.asList(msgs));
}
public MassiveException addMsgs(Collection<String> msgs) {
return this.addMessage(Mson.parse(msgs));
}
public MassiveException addMsgs(String... msgs) {
return this.addMsgs(Arrays.asList(msgs));
}
}

View File

@ -0,0 +1,439 @@
package com.massivecraft.massivecore;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.massivecraft.massivecore.collections.MassiveList;
import com.massivecraft.massivecore.command.MassiveCommand;
import com.massivecraft.massivecore.engine.EngineMassiveCoreCommandRegistration;
import com.massivecraft.massivecore.entity.MassiveCoreMConf;
import com.massivecraft.massivecore.mixin.Mixin;
import com.massivecraft.massivecore.mixin.MixinMessage;
import com.massivecraft.massivecore.predicate.PredicateIsClassSingleton;
import com.massivecraft.massivecore.store.Coll;
import com.massivecraft.massivecore.store.migrator.MigratorRoot;
import com.massivecraft.massivecore.test.Test;
import com.massivecraft.massivecore.util.MUtil;
import com.massivecraft.massivecore.util.ReflectionUtil;
import com.massivecraft.massivecore.util.Txt;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.command.ConsoleCommandSender;
import org.bukkit.event.Listener;
import org.bukkit.plugin.java.JavaPlugin;
import java.lang.reflect.Modifier;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.function.Predicate;
import java.util.logging.Level;
import java.util.logging.Logger;
public abstract class MassivePlugin extends JavaPlugin implements Listener, Named {
// -------------------------------------------- //
// FIELDS
// -------------------------------------------- //
// Gson
protected Gson gson = null;
public Gson getGson() {
return this.gson;
}
public void setGson(Gson gson) {
this.gson = gson;
}
protected boolean versionSynchronized = true;
public boolean isVersionSynchronized() {
return this.versionSynchronized;
}
public void setVersionSynchronized(boolean versionSynchronized) {
this.versionSynchronized = versionSynchronized;
}
// -------------------------------------------- //
// LOAD
// -------------------------------------------- //
@Override
public void onLoad() {
this.onLoadPre();
this.onLoadInner();
this.onLoadPost();
}
public void onLoadPre() {
this.logPrefixColored = Txt.parse("<teal>[<aqua>%s %s<teal>] <i>", this.getDescription().getName(), this.getDescription().getVersion());
this.logPrefixPlain = ChatColor.stripColor(this.logPrefixColored);
}
public void onLoadInner() {
}
public void onLoadPost() {
}
// -------------------------------------------- //
// ENABLE
// -------------------------------------------- //
@Override
public void onEnable() {
if (!this.onEnablePre()) {
return;
}
this.onEnableInner();
this.onEnablePost();
}
private long enableTime;
public long getEnableTime() {
return this.enableTime;
}
public boolean onEnablePre() {
this.enableTime = System.currentTimeMillis();
log("=== ENABLE START ===");
// Version Synchronization
this.checkVersionSynchronization();
// Create Gson
Gson gson = this.getGsonBuilder().create();
this.setGson(gson);
// Listener
Bukkit.getPluginManager().registerEvents(this, this);
return true;
}
public void checkVersionSynchronization() {
// If this plugin is version synchronized ...
if (!this.isVersionSynchronized()) {
return;
}
// ... and it's not MassiveCore itself ...
if (this.getClass().equals(MassiveCore.class)) {
return;
}
// ... and checking is enabled ...
if (!MassiveCoreMConf.get().versionSynchronizationEnabled) {
return;
}
// ... get the version numbers ...
String thisVersion = this.getDescription().getVersion();
String massiveVersion = MassiveCore.get().getDescription().getVersion();
// ... and if the version numbers are different ...
if (thisVersion.equals(massiveVersion)) {
return;
}
// ... log a warning message ...
String thisName = this.getDescription().getName();
String massiveName = MassiveCore.get().getDescription().getName();
log(Txt.parse("<b>WARNING: You are using <pink>" + thisName + " <aqua>" + thisVersion + " <b>and <pink>" + massiveName + " <aqua>" + massiveVersion + "<b>!"));
log(Txt.parse("<b>WARNING: They must be the exact same version to work properly!"));
log(Txt.parse("<b>WARNING: Remember to always update all plugins at the same time!"));
log(Txt.parse("<b>WARNING: You should stop your server and properly update."));
// ... and pause for 10 seconds.
try {
Thread.sleep(10000L);
} catch (InterruptedException ignored) {
}
}
public void onEnableInner() {
}
public void onEnablePost() {
// Metrics
if (MassiveCoreMConf.get().metricsEnabled) {
try {
new Metrics(this);
} catch (RuntimeException e) {
String message = Txt.parse("<b>Metrics Initialization Failed :'(");
log(message);
}
}
long ms = System.currentTimeMillis() - this.enableTime;
EngineMassiveCoreCommandRegistration.get().run();
log(Txt.parse("=== ENABLE <g>COMPLETE <i>(Took <h>" + ms + "ms<i>) ==="));
}
// -------------------------------------------- //
// DISABLE
// -------------------------------------------- //
@Override
public void onDisable() {
// Commands
this.deactivate(MassiveCommand.getAllInstances());
// Engines
this.deactivate(Engine.getAllInstances());
// Collections
this.deactivate(Coll.getInstances());
log("Disabled");
}
// -------------------------------------------- //
// GSON
// -------------------------------------------- //
public GsonBuilder getGsonBuilder() {
return MassiveCore.getMassiveCoreGsonBuilder();
}
// -------------------------------------------- //
// CONVENIENCE
// -------------------------------------------- //
public void suicide() {
this.log(Txt.parse("<b>Now I suicide!"));
Bukkit.getPluginManager().disablePlugin(this);
}
public void activate(Object... objects) {
this.activateOne(objects);
}
// We must get one active at a time because initialisation of some
// can only happen after others have been initialised.
public void activateOne(Object object) {
boolean debug = MassiveCoreMConf.get() != null && MassiveCoreMConf.get().debugEnabled;
// Try collection
if (object instanceof Iterable) {
Iterable<?> elements = (Iterable) object;
for (Object element : elements) {
this.activateOne(element);
}
return;
}
// Try array
if (object instanceof Object[]) {
Object[] array = (Object[]) object;
activateOne(Arrays.asList(array));
return;
}
Active active = asActive(object);
if (active == null) {
return;
}
if (active.isActive() && debug) {
log(Txt.parse("<h>%s<b> is already active.", active.getClass().getName()));
}
active.setActive(this);
if (debug) {
log(Txt.parse("<i>Activating <h>%s<i>.", active.getClass().getName()));
}
}
private static Active asActive(Object object) {
// Active already
if (object instanceof Active) {
return (Active) object;
}
// Try string as class name
if (object instanceof String) {
String string = (String) object;
try {
object = Class.forName(string);
} catch (NoClassDefFoundError | ClassNotFoundException e) {
// Silently skip and move on
return null;
}
}
// Try class
if (object instanceof Class<?>) {
Class<?> clazz = (Class<?>) object;
if (!Active.class.isAssignableFrom(clazz)) {
throw new IllegalArgumentException("Not Active Class: " + (clazz == null ? "NULL" : clazz));
}
Object instance = ReflectionUtil.getSingletonInstance(clazz);
if (!(instance instanceof Active)) {
throw new IllegalArgumentException("Not Active Instance: " + (instance == null ? "NULL" : instance) + " for object: " + (object == null ? "NULL" : object));
}
Active active = (Active) instance;
return active;
}
// No success
throw new IllegalArgumentException("Neither Active nor Class: " + object);
}
private void deactivate(Collection<? extends Active> actives) {
// Fail Fast
if (actives == null) {
throw new NullPointerException("actives");
}
// Clone to Avoid CME
List<Active> all = new MassiveList<>(actives);
// Reverse to Disable Reversely
Collections.reverse(all);
// Loop
for (Active active : all) {
// Check
if (!this.equals(active.getActivePlugin())) {
continue;
}
// Deactivate
active.setActive(false);
}
}
// -------------------------------------------- //
// ACTIVATE AUTO
// -------------------------------------------- //
public void activateAuto() {
// And activate them
this.activate(getClassesActive());
}
public List<Class<?>> getClassesActive() {
List<Class<?>> ret = new MassiveList<>();
// Fill with all kinds of Actives
ret.addAll(this.getClassesActiveMigrators());
ret.addAll(this.getClassesActiveColls());
ret.addAll(this.getClassesActiveNms());
ret.addAll(this.getClassesActiveCommands());
ret.addAll(this.getClassesActiveEngines());
ret.addAll(this.getClassesActiveIntegrations());
ret.addAll(this.getClassesActiveTasks());
ret.addAll(this.getClassesActiveMixins());
ret.addAll(this.getClassesActiveTests());
return ret;
}
public List<Class<?>> getClassesActiveColls() {
return getClassesActive("entity", Coll.class);
}
public List<Class<?>> getClassesActiveNms() {
return getClassesActive("nms", Mixin.class, (Predicate<Class<?>>) clazz -> {
try {
ReflectionUtil.getField(clazz, "d");
return true;
} catch (Throwable throwable) {
// We need to catch throwable here.
// NoClassDefFoundError will happen for NmsMixins targeting incompatible versions.
// On Minecraft 1.8 we did for example get this error:
// > java.lang.NoClassDefFoundError: org/bukkit/scoreboard/Team$Option
// > at java.lang.Class.getDeclaredFields0(Native Method) ~[?:1.8.0_111]
// > at java.lang.Class.privateGetDeclaredFields(Class.java:2583) ~[?:1.8.0_111]
// > at java.lang.Class.getDeclaredField(Class.java:2068) ~[?:1.8.0_111]
// The Java reflection itself is simply not careful enough.
return false;
}
}
);
}
public List<Class<?>> getClassesActiveCommands() {
return getClassesActive("cmd", MassiveCommand.class);
}
public List<Class<?>> getClassesActiveEngines() {
return getClassesActive(Engine.class);
}
public List<Class<?>> getClassesActiveIntegrations() {
return getClassesActive(Integration.class);
}
public List<Class<?>> getClassesActiveTasks() {
return getClassesActive("task", ModuloRepeatTask.class);
}
public List<Class<?>> getClassesActiveMixins() {
return getClassesActive(Mixin.class);
}
public List<Class<?>> getClassesActiveTests() {
return getClassesActive(Test.class);
}
public List<Class<?>> getClassesActiveMigrators() {
return getClassesActive("entity.migrator", MigratorRoot.class);
}
public List<Class<?>> getClassesActive(Class<? extends Active> superClass, Predicate<Class<?>>... predicates) {
return getClassesActive(superClass.getSimpleName().toLowerCase(), superClass);
}
@SuppressWarnings("unchecked")
public List<Class<?>> getClassesActive(String packageName, final Class<?> superClass, Predicate<Class<?>>... predicates) {
if (!Active.class.isAssignableFrom(superClass)) {
throw new IllegalArgumentException(superClass.getName() + " is not instance of Active.");
}
packageName = packageName == null ? "" : "." + packageName;
packageName = this.getClass().getPackage().getName() + packageName;
Predicate predicateCombined = predicates.length > 0 ? MUtil.predicatesAnd(predicates) : x -> true;
Predicate<Class<?>> predicateNotAbstract = type -> !Modifier.isAbstract(type.getModifiers());
Predicate<Class<?>> predicateSubclass = type -> !Modifier.isAbstract(type.getModifiers());
Predicate<Class<?>> predicateSingleton = PredicateIsClassSingleton.get();
return ReflectionUtil.getPackageClasses(packageName, this.getClassLoader(), true, predicateCombined, predicateNotAbstract, predicateSubclass, predicateSingleton);
}
// -------------------------------------------- //
// LOGGING
// -------------------------------------------- //
private String logPrefixColored = null;
private String logPrefixPlain = null;
public void log(Object... msg) {
log(Level.INFO, msg);
}
public void log(Level level, Object... msg) {
String imploded = Txt.implode(msg, " ");
ConsoleCommandSender console = Bukkit.getConsoleSender();
if (level == Level.INFO && console != null) {
MixinMessage.get().messageOne(console, this.logPrefixColored + imploded);
} else {
Logger.getLogger("Minecraft").log(level, this.logPrefixPlain + imploded);
}
}
}

View File

@ -0,0 +1,709 @@
package com.massivecraft.massivecore;
import org.bukkit.Bukkit;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.entity.Player;
import org.bukkit.plugin.Plugin;
import org.bukkit.plugin.RegisteredServiceProvider;
import org.bukkit.plugin.ServicePriority;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import javax.net.ssl.HttpsURLConnection;
import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Timer;
import java.util.TimerTask;
import java.util.UUID;
import java.util.concurrent.Callable;
import java.util.logging.Level;
import java.util.zip.GZIPOutputStream;
/**
* bStats collects some data for plugin authors.
* <p>
* Check out https://bStats.org/ to learn more about bStats!
*/
@SuppressWarnings({"WeakerAccess", "unused"})
public class Metrics {
static {
// You can use the property to disable the check in your test environment
if (System.getProperty("bstats.relocatecheck") == null || !System.getProperty("bstats.relocatecheck").equals("false")) {
// Maven's Relocate is clever and changes strings, too. So we have to use this little "trick" ... :D
final String defaultPackage = new String(
new byte[]{'o', 'r', 'g', '.', 'b', 's', 't', 'a', 't', 's', '.', 'b', 'u', 'k', 'k', 'i', 't'});
final String examplePackage = new String(new byte[]{'y', 'o', 'u', 'r', '.', 'p', 'a', 'c', 'k', 'a', 'g', 'e'});
// We want to make sure nobody just copy & pastes the example and use the wrong package names
if (Metrics.class.getPackage().getName().equals(defaultPackage) || Metrics.class.getPackage().getName().equals(examplePackage)) {
throw new IllegalStateException("bStats Metrics class has not been relocated correctly!");
}
}
}
// The version of this bStats class
public static final int B_STATS_VERSION = 1;
// The url to which the data is sent
private static final String URL = "https://bStats.org/submitData/bukkit";
// Is bStats enabled on this server?
private boolean enabled;
// Should failed requests be logged?
private static boolean logFailedRequests;
// Should the sent data be logged?
private static boolean logSentData;
// Should the response text be logged?
private static boolean logResponseStatusText;
// The uuid of the server
private static String serverUUID;
// The plugin
private final Plugin plugin;
// A list with all custom charts
private final List<CustomChart> charts = new ArrayList<>();
/**
* Class constructor.
*
* @param plugin The plugin which stats should be submitted.
*/
public Metrics(Plugin plugin) {
if (plugin == null) {
throw new IllegalArgumentException("Plugin cannot be null!");
}
this.plugin = plugin;
// Get the config file
File bStatsFolder = new File(plugin.getDataFolder().getParentFile(), "bStats");
File configFile = new File(bStatsFolder, "config.yml");
YamlConfiguration config = YamlConfiguration.loadConfiguration(configFile);
// Check if the config file exists
if (!config.isSet("serverUuid")) {
// Add default values
config.addDefault("enabled", true);
// Every server gets it's unique random id.
config.addDefault("serverUuid", UUID.randomUUID().toString());
// Should failed request be logged?
config.addDefault("logFailedRequests", false);
// Should the sent data be logged?
config.addDefault("logSentData", false);
// Should the response text be logged?
config.addDefault("logResponseStatusText", false);
// Inform the server owners about bStats
config.options().header(
"bStats collects some data for plugin authors like how many servers are using their plugins.\n" +
"To honor their work, you should not disable it.\n" +
"This has nearly no effect on the server performance!\n" +
"Check out https://bStats.org/ to learn more :)"
).copyDefaults(true);
try {
config.save(configFile);
} catch (IOException ignored) {
}
}
// Load the data
enabled = config.getBoolean("enabled", true);
serverUUID = config.getString("serverUuid");
logFailedRequests = config.getBoolean("logFailedRequests", false);
logSentData = config.getBoolean("logSentData", false);
logResponseStatusText = config.getBoolean("logResponseStatusText", false);
if (enabled) {
boolean found = false;
// Search for all other bStats Metrics classes to see if we are the first one
for (Class<?> service : Bukkit.getServicesManager().getKnownServices()) {
try {
service.getField("B_STATS_VERSION"); // Our identifier :)
found = true; // We aren't the first
break;
} catch (NoSuchFieldException ignored) {
}
}
// Register our service
Bukkit.getServicesManager().register(Metrics.class, this, plugin, ServicePriority.Normal);
if (!found) {
// We are the first!
startSubmitting();
}
}
}
/**
* Checks if bStats is enabled.
*
* @return Whether bStats is enabled or not.
*/
public boolean isEnabled() {
return enabled;
}
/**
* Adds a custom chart.
*
* @param chart The chart to add.
*/
public void addCustomChart(CustomChart chart) {
if (chart == null) {
throw new IllegalArgumentException("Chart cannot be null!");
}
charts.add(chart);
}
/**
* Starts the Scheduler which submits our data every 30 minutes.
*/
private void startSubmitting() {
final Timer timer = new Timer(true); // We use a timer cause the Bukkit scheduler is affected by server lags
timer.scheduleAtFixedRate(new TimerTask() {
@Override
public void run() {
if (!plugin.isEnabled()) { // Plugin was disabled
timer.cancel();
return;
}
// Nevertheless we want our code to run in the Bukkit main thread, so we have to use the Bukkit scheduler
// Don't be afraid! The connection to the bStats server is still async, only the stats collection is sync ;)
Bukkit.getScheduler().runTask(plugin, () -> submitData());
}
}, 1000 * 60 * 5, 1000 * 60 * 30);
// Submit the data every 30 minutes, first time after 5 minutes to give other plugins enough time to start
// WARNING: Changing the frequency has no effect but your plugin WILL be blocked/deleted!
// WARNING: Just don't do it!
}
/**
* Gets the plugin specific data.
* This method is called using Reflection.
*
* @return The plugin specific data.
*/
public JSONObject getPluginData() {
JSONObject data = new JSONObject();
String pluginName = plugin.getDescription().getName();
String pluginVersion = plugin.getDescription().getVersion();
data.put("pluginName", pluginName); // Append the name of the plugin
data.put("pluginVersion", pluginVersion); // Append the version of the plugin
JSONArray customCharts = new JSONArray();
for (CustomChart customChart : charts) {
// Add the data of the custom charts
JSONObject chart = customChart.getRequestJsonObject();
if (chart == null) { // If the chart is null, we skip it
continue;
}
customCharts.add(chart);
}
data.put("customCharts", customCharts);
return data;
}
/**
* Gets the server specific data.
*
* @return The server specific data.
*/
private JSONObject getServerData() {
// Minecraft specific data
int playerAmount;
try {
// Around MC 1.8 the return type was changed to a collection from an array,
// This fixes java.lang.NoSuchMethodError: org.bukkit.Bukkit.getOnlinePlayers()Ljava/util/Collection;
Method onlinePlayersMethod = Class.forName("org.bukkit.Server").getMethod("getOnlinePlayers");
playerAmount = onlinePlayersMethod.getReturnType().equals(Collection.class)
? ((Collection<?>) onlinePlayersMethod.invoke(Bukkit.getServer())).size()
: ((Player[]) onlinePlayersMethod.invoke(Bukkit.getServer())).length;
} catch (Exception e) {
playerAmount = Bukkit.getOnlinePlayers().size(); // Just use the new method if the Reflection failed
}
int onlineMode = Bukkit.getOnlineMode() ? 1 : 0;
String bukkitVersion = Bukkit.getVersion();
// OS/Java specific data
String javaVersion = System.getProperty("java.version");
String osName = System.getProperty("os.name");
String osArch = System.getProperty("os.arch");
String osVersion = System.getProperty("os.version");
int coreCount = Runtime.getRuntime().availableProcessors();
JSONObject data = new JSONObject();
data.put("serverUUID", serverUUID);
data.put("playerAmount", playerAmount);
data.put("onlineMode", onlineMode);
data.put("bukkitVersion", bukkitVersion);
data.put("javaVersion", javaVersion);
data.put("osName", osName);
data.put("osArch", osArch);
data.put("osVersion", osVersion);
data.put("coreCount", coreCount);
return data;
}
/**
* Collects the data and sends it afterwards.
*/
private void submitData() {
final JSONObject data = getServerData();
JSONArray pluginData = new JSONArray();
// Search for all other bStats Metrics classes to get their plugin data
for (Class<?> service : Bukkit.getServicesManager().getKnownServices()) {
try {
service.getField("B_STATS_VERSION"); // Our identifier :)
for (RegisteredServiceProvider<?> provider : Bukkit.getServicesManager().getRegistrations(service)) {
try {
pluginData.add(provider.getService().getMethod("getPluginData").invoke(provider.getProvider()));
} catch (NullPointerException | NoSuchMethodException | IllegalAccessException |
InvocationTargetException ignored) {
}
}
} catch (NoSuchFieldException ignored) {
}
}
data.put("plugins", pluginData);
// Create a new thread for the connection to the bStats server
new Thread(() -> {
try {
// Send the data
sendData(plugin, data);
} catch (Exception e) {
// Something went wrong! :(
if (logFailedRequests) {
plugin.getLogger().log(Level.WARNING, "Could not submit plugin stats of " + plugin.getName(), e);
}
}
}).start();
}
/**
* Sends the data to the bStats server.
*
* @param plugin Any plugin. It's just used to get a logger instance.
* @param data The data to send.
* @throws Exception If the request failed.
*/
private static void sendData(Plugin plugin, JSONObject data) throws Exception {
if (data == null) {
throw new IllegalArgumentException("Data cannot be null!");
}
if (Bukkit.isPrimaryThread()) {
throw new IllegalAccessException("This method must not be called from the main thread!");
}
if (logSentData) {
plugin.getLogger().info("Sending data to bStats: " + data.toString());
}
HttpsURLConnection connection = (HttpsURLConnection) new URL(URL).openConnection();
// Compress the data to save bandwidth
byte[] compressedData = compress(data.toString());
// Add headers
connection.setRequestMethod("POST");
connection.addRequestProperty("Accept", "application/json");
connection.addRequestProperty("Connection", "close");
connection.addRequestProperty("Content-Encoding", "gzip"); // We gzip our request
connection.addRequestProperty("Content-Length", String.valueOf(compressedData.length));
connection.setRequestProperty("Content-Type", "application/json"); // We send our data in JSON format
connection.setRequestProperty("User-Agent", "MC-Server/" + B_STATS_VERSION);
// Send data
connection.setDoOutput(true);
DataOutputStream outputStream = new DataOutputStream(connection.getOutputStream());
outputStream.write(compressedData);
outputStream.flush();
outputStream.close();
InputStream inputStream = connection.getInputStream();
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
StringBuilder builder = new StringBuilder();
String line;
while ((line = bufferedReader.readLine()) != null) {
builder.append(line);
}
bufferedReader.close();
if (logResponseStatusText) {
plugin.getLogger().info("Sent data to bStats and received response: " + builder.toString());
}
}
/**
* Gzips the given String.
*
* @param str The string to gzip.
* @return The gzipped String.
* @throws IOException If the compression failed.
*/
private static byte[] compress(final String str) throws IOException {
if (str == null) {
return null;
}
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
GZIPOutputStream gzip = new GZIPOutputStream(outputStream);
gzip.write(str.getBytes(StandardCharsets.UTF_8));
gzip.close();
return outputStream.toByteArray();
}
/**
* Represents a custom chart.
*/
public static abstract class CustomChart {
// The id of the chart
final String chartId;
/**
* Class constructor.
*
* @param chartId The id of the chart.
*/
CustomChart(String chartId) {
if (chartId == null || chartId.isEmpty()) {
throw new IllegalArgumentException("ChartId cannot be null or empty!");
}
this.chartId = chartId;
}
private JSONObject getRequestJsonObject() {
JSONObject chart = new JSONObject();
chart.put("chartId", chartId);
try {
JSONObject data = getChartData();
if (data == null) {
// If the data is null we don't send the chart.
return null;
}
chart.put("data", data);
} catch (Throwable t) {
if (logFailedRequests) {
Bukkit.getLogger().log(Level.WARNING, "Failed to get data for custom chart with id " + chartId, t);
}
return null;
}
return chart;
}
protected abstract JSONObject getChartData() throws Exception;
}
/**
* Represents a custom simple pie.
*/
public static class SimplePie extends CustomChart {
private final Callable<String> callable;
/**
* Class constructor.
*
* @param chartId The id of the chart.
* @param callable The callable which is used to request the chart data.
*/
public SimplePie(String chartId, Callable<String> callable) {
super(chartId);
this.callable = callable;
}
@Override
protected JSONObject getChartData() throws Exception {
JSONObject data = new JSONObject();
String value = callable.call();
if (value == null || value.isEmpty()) {
// Null = skip the chart
return null;
}
data.put("value", value);
return data;
}
}
/**
* Represents a custom advanced pie.
*/
public static class AdvancedPie extends CustomChart {
private final Callable<Map<String, Integer>> callable;
/**
* Class constructor.
*
* @param chartId The id of the chart.
* @param callable The callable which is used to request the chart data.
*/
public AdvancedPie(String chartId, Callable<Map<String, Integer>> callable) {
super(chartId);
this.callable = callable;
}
@Override
protected JSONObject getChartData() throws Exception {
JSONObject data = new JSONObject();
JSONObject values = new JSONObject();
Map<String, Integer> map = callable.call();
if (map == null || map.isEmpty()) {
// Null = skip the chart
return null;
}
boolean allSkipped = true;
for (Map.Entry<String, Integer> entry : map.entrySet()) {
if (entry.getValue() == 0) {
continue; // Skip this invalid
}
allSkipped = false;
values.put(entry.getKey(), entry.getValue());
}
if (allSkipped) {
// Null = skip the chart
return null;
}
data.put("values", values);
return data;
}
}
/**
* Represents a custom drilldown pie.
*/
public static class DrilldownPie extends CustomChart {
private final Callable<Map<String, Map<String, Integer>>> callable;
/**
* Class constructor.
*
* @param chartId The id of the chart.
* @param callable The callable which is used to request the chart data.
*/
public DrilldownPie(String chartId, Callable<Map<String, Map<String, Integer>>> callable) {
super(chartId);
this.callable = callable;
}
@Override
public JSONObject getChartData() throws Exception {
JSONObject data = new JSONObject();
JSONObject values = new JSONObject();
Map<String, Map<String, Integer>> map = callable.call();
if (map == null || map.isEmpty()) {
// Null = skip the chart
return null;
}
boolean reallyAllSkipped = true;
for (Map.Entry<String, Map<String, Integer>> entryValues : map.entrySet()) {
JSONObject value = new JSONObject();
boolean allSkipped = true;
for (Map.Entry<String, Integer> valueEntry : map.get(entryValues.getKey()).entrySet()) {
value.put(valueEntry.getKey(), valueEntry.getValue());
allSkipped = false;
}
if (!allSkipped) {
reallyAllSkipped = false;
values.put(entryValues.getKey(), value);
}
}
if (reallyAllSkipped) {
// Null = skip the chart
return null;
}
data.put("values", values);
return data;
}
}
/**
* Represents a custom single line chart.
*/
public static class SingleLineChart extends CustomChart {
private final Callable<Integer> callable;
/**
* Class constructor.
*
* @param chartId The id of the chart.
* @param callable The callable which is used to request the chart data.
*/
public SingleLineChart(String chartId, Callable<Integer> callable) {
super(chartId);
this.callable = callable;
}
@Override
protected JSONObject getChartData() throws Exception {
JSONObject data = new JSONObject();
int value = callable.call();
if (value == 0) {
// Null = skip the chart
return null;
}
data.put("value", value);
return data;
}
}
/**
* Represents a custom multi line chart.
*/
public static class MultiLineChart extends CustomChart {
private final Callable<Map<String, Integer>> callable;
/**
* Class constructor.
*
* @param chartId The id of the chart.
* @param callable The callable which is used to request the chart data.
*/
public MultiLineChart(String chartId, Callable<Map<String, Integer>> callable) {
super(chartId);
this.callable = callable;
}
@Override
protected JSONObject getChartData() throws Exception {
JSONObject data = new JSONObject();
JSONObject values = new JSONObject();
Map<String, Integer> map = callable.call();
if (map == null || map.isEmpty()) {
// Null = skip the chart
return null;
}
boolean allSkipped = true;
for (Map.Entry<String, Integer> entry : map.entrySet()) {
if (entry.getValue() == 0) {
continue; // Skip this invalid
}
allSkipped = false;
values.put(entry.getKey(), entry.getValue());
}
if (allSkipped) {
// Null = skip the chart
return null;
}
data.put("values", values);
return data;
}
}
/**
* Represents a custom simple bar chart.
*/
public static class SimpleBarChart extends CustomChart {
private final Callable<Map<String, Integer>> callable;
/**
* Class constructor.
*
* @param chartId The id of the chart.
* @param callable The callable which is used to request the chart data.
*/
public SimpleBarChart(String chartId, Callable<Map<String, Integer>> callable) {
super(chartId);
this.callable = callable;
}
@Override
protected JSONObject getChartData() throws Exception {
JSONObject data = new JSONObject();
JSONObject values = new JSONObject();
Map<String, Integer> map = callable.call();
if (map == null || map.isEmpty()) {
// Null = skip the chart
return null;
}
for (Map.Entry<String, Integer> entry : map.entrySet()) {
JSONArray categoryValues = new JSONArray();
categoryValues.add(entry.getValue());
values.put(entry.getKey(), categoryValues);
}
data.put("values", values);
return data;
}
}
/**
* Represents a custom advanced bar chart.
*/
public static class AdvancedBarChart extends CustomChart {
private final Callable<Map<String, int[]>> callable;
/**
* Class constructor.
*
* @param chartId The id of the chart.
* @param callable The callable which is used to request the chart data.
*/
public AdvancedBarChart(String chartId, Callable<Map<String, int[]>> callable) {
super(chartId);
this.callable = callable;
}
@Override
protected JSONObject getChartData() throws Exception {
JSONObject data = new JSONObject();
JSONObject values = new JSONObject();
Map<String, int[]> map = callable.call();
if (map == null || map.isEmpty()) {
// Null = skip the chart
return null;
}
boolean allSkipped = true;
for (Map.Entry<String, int[]> entry : map.entrySet()) {
if (entry.getValue().length == 0) {
continue; // Skip this invalid
}
allSkipped = false;
JSONArray categoryValues = new JSONArray();
for (int categoryValue : entry.getValue()) {
categoryValues.add(categoryValue);
}
values.put(entry.getKey(), categoryValues);
}
if (allSkipped) {
// Null = skip the chart
return null;
}
data.put("values", values);
return data;
}
}
}

View File

@ -0,0 +1,100 @@
package com.massivecraft.massivecore;
/**
* This class will allow you to create non-tps-dependent repeating tasks.
* It makes use of the Bukkit scheduler internally.
*/
public abstract class ModuloRepeatTask extends Engine {
// -------------------------------------------- //
// FIELDS: RAW
// -------------------------------------------- //
// How many milliseconds should approximately pass between each invocation?
private long delayMillis;
public long getDelayMillis() {
return this.delayMillis;
}
public void setDelayMillis(long delayMillis) {
this.delayMillis = delayMillis;
}
// When did the last invocation occur?
private long previousMillis;
public long getPreviousMillis() {
return this.previousMillis;
}
public void setPreviousMillis(long previousMillis) {
this.previousMillis = previousMillis;
}
// TODO: Convertion Dust
// private Integer taskId = null;
// -------------------------------------------- //
// INVOCATION NUMBER CALCULATION
// -------------------------------------------- //
public long getInvocation(long now) {
return now / this.getDelayMillis();
}
// -------------------------------------------- //
// CONSTRUCT
// -------------------------------------------- //
public ModuloRepeatTask() {
this(0);
}
public ModuloRepeatTask(long delayMilis) {
this(delayMilis, System.currentTimeMillis());
}
public ModuloRepeatTask(long delayMilis, long previousMillis) {
this.delayMillis = delayMilis;
this.previousMillis = previousMillis;
}
// -------------------------------------------- //
// OVERRIDE
// -------------------------------------------- //
@Override
public Long getPeriod() {
return 1L;
}
@Override
public void run() {
// So the delay millis is lower than one? (could for example be zero)
// This probably means the task should not be executed at all.
if (this.getDelayMillis() < 1) {
return;
}
long nowMillis = System.currentTimeMillis();
long previousMillis = this.getPreviousMillis();
long currentInvocation = this.getInvocation(nowMillis);
long previousInvocation = this.getInvocation(previousMillis);
if (currentInvocation == previousInvocation) {
return;
}
this.invoke(nowMillis);
this.setPreviousMillis(nowMillis);
}
// -------------------------------------------- //
// ABSTRACT
// -------------------------------------------- //
public abstract void invoke(long now);
}

View File

@ -0,0 +1,5 @@
package com.massivecraft.massivecore;
public interface Named {
String getName();
}

View File

@ -0,0 +1,53 @@
package com.massivecraft.massivecore;
import com.massivecraft.massivecore.engine.EngineMassiveCorePlayerState;
import org.bukkit.entity.Player;
import java.util.UUID;
/**
* This enumeration is used to keep track of where a player currently is within the login --> join --> play --> leave cycle.
* Bukkit does not provide this information so we forge it as well as we can by listening to LOWEST on a few different events.
* <p>
* When is this information useful?
* For example you may want to handle events differently depending on whether the player actually is online yet.
* Say you want to store last teleport position by logging it on the player teleport event.
* During the login and join phase the server teleports the player around to get the player in position.
* So for such a "last tp position" system you may want to ignore any teleports other than during player state JOINED.
* <p>
* EngineMassiveCorePlayerState takes care of updating the information.
*/
public enum PlayerState {
// -------------------------------------------- //
// ENUM
// -------------------------------------------- //
LOGASYNC, // During AsyncPlayerLoginEvent
LOGSYNC, // During PlayerLoginEvent
JOINING, // During PlayerJoinEvent
JOINED, // Regular situation. The player is online and playing.
LEAVING, // From the start of EventMassiveCorePlayerLeave till the player actually disconnects.
LEFT, // The player is fully disconnected and offline.
// END OF LIST
;
// -------------------------------------------- //
// STATIC
// -------------------------------------------- //
public static PlayerState get(UUID id) {
if (id == null) {
throw new NullPointerException("id");
}
return EngineMassiveCorePlayerState.get().getState(id);
}
public static PlayerState get(Player player) {
if (player == null) {
throw new NullPointerException("player");
}
return EngineMassiveCorePlayerState.get().getState(player);
}
}

View File

@ -0,0 +1,5 @@
package com.massivecraft.massivecore;
public interface Prioritized {
int getPriority();
}

View File

@ -0,0 +1,128 @@
package com.massivecraft.massivecore;
import com.massivecraft.massivecore.collections.MassiveList;
import com.massivecraft.massivecore.comparator.ComparatorIdentity;
import com.massivecraft.massivecore.comparator.ComparatorPrioritized;
import com.massivecraft.massivecore.mson.Mson;
import com.massivecraft.massivecore.util.FlattenUtil;
import com.massivecraft.massivecore.util.MUtil;
import java.util.Collection;
import java.util.List;
import java.util.Objects;
public class PriorityLines implements Prioritized, Comparable<PriorityLines> {
// -------------------------------------------- //
// FIELDS
// -------------------------------------------- //
private int priority;
@Override
public int getPriority() {
return this.priority;
}
public void setPriority(int priority) {
this.priority = priority;
}
private List<Mson> lines;
public List<String> getLines() {
return Mson.toPlain(this.lines, true);
}
public void setLines(Object... lines) {
Collection<Object> linesList = FlattenUtil.flatten(lines);
List<Mson> msonLines = new MassiveList<>();
// Extract the items from the array
for (Object line : linesList) {
msonLines.add(ensureMson(line));
}
this.lines = msonLines;
}
public void setLine(Object line) {
this.setLines(line);
}
public List<Mson> getLinesMson() {
return new MassiveList<>(this.lines);
}
// -------------------------------------------- //
// CONSTRUCT
// -------------------------------------------- //
public PriorityLines(int priority, Object... lines) {
this.priority = priority;
this.setLines(lines);
}
// -------------------------------------------- //
// TO STRING
// -------------------------------------------- //
@Override
public String toString() {
return MassiveCore.gson.toJson(this);
}
// -------------------------------------------- //
// COMPARABLE & EQUALS & HASHCODE
// -------------------------------------------- //
@Override
public int compareTo(PriorityLines that) {
// Create
int ret = 0;
// Fill
ret = ComparatorPrioritized.get().compare(this, that);
if (ret != 0) {
return ret;
}
ret = ComparatorIdentity.get().compare(this, that);
// Return
return ret;
}
@Override
public boolean equals(Object object) {
if (!(object instanceof PriorityLines)) {
return false;
}
PriorityLines that = (PriorityLines) object;
return MUtil.equals(
this.getPriority(), that.getPriority(),
this.getLines(), that.getLines()
);
}
@Override
public int hashCode() {
return Objects.hash(
this.getPriority(),
this.getLines()
);
}
// -------------------------------------------- //
// UTIL
// -------------------------------------------- //
private static Mson ensureMson(Object messageItem) {
if (messageItem instanceof Mson) {
return (Mson) messageItem;
}
if (messageItem instanceof String) {
return Mson.fromParsedMessage((String) messageItem);
}
throw new IllegalArgumentException(String.format("messageItem is neither an Mson or String, %s", messageItem));
}
}

View File

@ -0,0 +1,263 @@
package com.massivecraft.massivecore;
import com.massivecraft.massivecore.util.MUtil;
import com.massivecraft.massivecore.util.Txt;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
public class Progressbar {
// -------------------------------------------- //
// STANDARD INSTANCES
// -------------------------------------------- //
public static final transient Progressbar HEALTHBAR_CLASSIC = Progressbar.valueOf(1D, 30, "{c}[", "|", "&8", "|", "{c}]", 1D, "{c}", MUtil.map(
1.0D, "&2",
0.8D, "&a",
0.5D, "&e",
0.4D, "&6",
0.3D, "&c",
0.2D, "&4"
));
// -------------------------------------------- //
// FIELDS: RAW
// -------------------------------------------- //
private final double quota;
public double getQuota() {
return this.quota;
}
private final int width;
public int getWidth() {
return this.width;
}
private final String left;
public String getLeft() {
return this.left;
}
private final String solid;
public String getSolid() {
return this.solid;
}
private final String between;
public String getBetween() {
return this.between;
}
private final String empty;
public String getEmpty() {
return this.empty;
}
private final String right;
public String getRight() {
return this.right;
}
private final double solidsPerEmpty;
public double getSolidsPerEmpty() {
return this.solidsPerEmpty;
}
private final String colorTag;
public String getColorTag() {
return this.colorTag;
}
private final Map<Double, String> roofToColor;
public Map<Double, String> getRoofToColor() {
return this.roofToColor;
}
// -------------------------------------------- //
// FIELDS: WITH
// -------------------------------------------- //
public Progressbar withQuota(double quota) {
return new Progressbar(quota, width, left, solid, between, empty, right, solidsPerEmpty, colorTag, roofToColor);
}
public Progressbar withWidth(int width) {
return new Progressbar(quota, width, left, solid, between, empty, right, solidsPerEmpty, colorTag, roofToColor);
}
public Progressbar withLeft(String left) {
return new Progressbar(quota, width, left, solid, between, empty, right, solidsPerEmpty, colorTag, roofToColor);
}
public Progressbar withSolid(String solid) {
return new Progressbar(quota, width, left, solid, between, empty, right, solidsPerEmpty, colorTag, roofToColor);
}
public Progressbar withBetween(String between) {
return new Progressbar(quota, width, left, solid, between, empty, right, solidsPerEmpty, colorTag, roofToColor);
}
public Progressbar withEmpty(String empty) {
return new Progressbar(quota, width, left, solid, between, empty, right, solidsPerEmpty, colorTag, roofToColor);
}
public Progressbar withRight(String right) {
return new Progressbar(quota, width, left, solid, between, empty, right, solidsPerEmpty, colorTag, roofToColor);
}
public Progressbar withSolidsPerEmpty(double solidsPerEmpty) {
return new Progressbar(quota, width, left, solid, between, empty, right, solidsPerEmpty, colorTag, roofToColor);
}
public Progressbar withColorTag(String colorTag) {
return new Progressbar(quota, width, left, solid, between, empty, right, solidsPerEmpty, colorTag, roofToColor);
}
public Progressbar withRoofToColor(Map<Double, String> roofToColor) {
return new Progressbar(quota, width, left, solid, between, empty, right, solidsPerEmpty, colorTag, roofToColor);
}
// -------------------------------------------- //
// PRIVATE CONSTRUCTOR
// -------------------------------------------- //
private Progressbar(double quota, int width, String left, String solid, String between, String empty, String right, double solidsPerEmpty, String colorTag, Map<Double, String> roofToColor) {
this.quota = quota;
this.width = width;
this.left = left;
this.solid = solid;
this.between = between;
this.empty = empty;
this.right = right;
this.solidsPerEmpty = solidsPerEmpty;
this.colorTag = colorTag;
this.roofToColor = Collections.unmodifiableMap(roofToColor);
}
// -------------------------------------------- //
// FACTORY: VALUE OF
// -------------------------------------------- //
public static Progressbar valueOf(double quota, int width, String left, String solid, String between, String empty, String right, double solidsPerEmpty, String colorTag, Map<Double, String> roofToColor) {
return new Progressbar(quota, width, left, solid, between, empty, right, solidsPerEmpty, colorTag, roofToColor);
}
// -------------------------------------------- //
// INSTANCE METHODS
// -------------------------------------------- //
public String render() {
return render(quota, width, left, solid, between, empty, right, solidsPerEmpty, colorTag, roofToColor);
}
public List<String> renderList() {
return renderList(quota, width, left, solid, between, empty, right, solidsPerEmpty, colorTag, roofToColor);
}
// -------------------------------------------- //
// STATIC UTIL
// -------------------------------------------- //
public static String render(double quota, int width, String left, String solid, String between, String empty, String right, double solidsPerEmpty, String colorTag, Map<Double, String> roofToColor) {
return Txt.implode(renderList(quota, width, left, solid, between, empty, right, solidsPerEmpty, colorTag, roofToColor), "");
}
public static List<String> renderList(double quota, int width, String left, String solid, String between, String empty, String right, double solidsPerEmpty, String colorTag, Map<Double, String> roofToColor) {
// Create Ret
List<String> ret = new ArrayList<>();
// Ensure between 0 and 1;
quota = limit(quota);
// What color is the health bar?
String color = pick(quota, roofToColor);
// how much solid should there be?
int solidCount = (int) Math.ceil(width * quota);
// The rest is empty
int emptyCount = (int) ((width - solidCount) / solidsPerEmpty);
// Color Parse Parts
left = colorParse(left, colorTag, color);
solid = colorParse(solid, colorTag, color);
between = colorParse(between, colorTag, color);
empty = colorParse(empty, colorTag, color);
right = colorParse(right, colorTag, color);
// Combine Parts
if (left != null) {
ret.add(left);
}
if (solid != null) {
for (int i = 1; i <= solidCount; i++) {
ret.add(solid);
}
}
if (between != null) {
ret.add(between);
}
if (empty != null) {
for (int i = 1; i <= emptyCount; i++) {
ret.add(empty);
}
}
if (right != null) {
ret.add(right);
}
return ret;
}
public static String colorParse(String string, String colorTag, String color) {
if (string == null) {
throw new NullPointerException("string");
}
string = string.replace(colorTag, color);
string = Txt.parse(string);
return string;
}
public static double limit(double quota) {
if (quota > 1) {
return 1;
}
if (quota < 0) {
return 0;
}
return quota;
}
public static <T> T pick(double quota, Map<Double, T> roofToValue) {
Double currentRoof = null;
T ret = null;
for (Entry<Double, T> entry : roofToValue.entrySet()) {
double roof = entry.getKey();
T value = entry.getValue();
if (quota <= roof && (currentRoof == null || roof <= currentRoof)) {
currentRoof = roof;
ret = value;
}
}
return ret;
}
}

View File

@ -0,0 +1,5 @@
package com.massivecraft.massivecore;
public interface Registerable {
boolean isRegistered();
}

View File

@ -0,0 +1,28 @@
package com.massivecraft.massivecore;
public enum SenderPresence {
// IMP NOTE: These must be sorted, with the most strict first
// and the most loose at the end.
LOCAL, // Online and logged in on this very server.
ONLINE, // Online somewhere on the cloud. May be this server may be another server.
OFFLINE, // The opposite of online.
ANY, // Any. Local, Online or Offline.
;
// -------------------------------------------- //
// GET FROM ONLINE VALUE
// -------------------------------------------- //
public static SenderPresence fromOnline(Boolean online) {
if (online == null) {
return null;
}
return fromOnline(online.booleanValue());
}
public static SenderPresence fromOnline(boolean online) {
return online ? ONLINE : OFFLINE;
}
}

View File

@ -0,0 +1,9 @@
package com.massivecraft.massivecore;
public enum SenderType {
PLAYER, // A player. Such as Notch or Dinnerbone. @console is not a player.
NONPLAYER, // A sender which is not a player. Such as @console.
ANY, // Anyone. Both players, and nonplayers.
;
}

View File

@ -0,0 +1,90 @@
package com.massivecraft.massivecore;
import com.google.gson.Gson;
import com.massivecraft.massivecore.store.accessor.Accessor;
import com.massivecraft.massivecore.util.DiscUtil;
import org.bukkit.plugin.Plugin;
import java.io.File;
public class SimpleConfig {
// -------------------------------------------- //
// FIELDS
// -------------------------------------------- //
protected transient Plugin plugin;
protected Plugin getPlugin() {
return this.plugin;
}
protected transient File file;
protected File getFile() {
return this.file;
}
public SimpleConfig(Plugin plugin, File file) {
this.plugin = plugin;
this.file = file;
}
public SimpleConfig(Plugin plugin, String confname) {
this(plugin, new File(plugin.getDataFolder(), confname + ".json"));
}
public SimpleConfig(Plugin plugin) {
this(plugin, "conf");
}
// -------------------------------------------- //
// IO
// -------------------------------------------- //
private Gson getGson() {
if (this.plugin instanceof MassivePlugin) {
return ((MassivePlugin) this.plugin).getGson();
}
return MassiveCore.gson;
}
protected static boolean contentRequestsDefaults(String content) {
if (content == null) {
return false;
}
if (content.length() == 0) {
return false;
}
char c = content.charAt(0);
return c == 'd' || c == 'D';
}
public void load() {
if (this.getFile().isFile()) {
String content = DiscUtil.readCatch(this.getFile());
content = content.trim();
Object toShallowLoad = null;
if (contentRequestsDefaults(content)) {
try {
toShallowLoad = this.getClass().getDeclaredConstructor().newInstance();
} catch (Exception e) {
e.printStackTrace();
return;
}
} else {
toShallowLoad = this.getGson().fromJson(content, this.getClass());
}
Accessor.get(this.getClass()).copy(toShallowLoad, this);
}
save();
}
public void save() {
String content = DiscUtil.readCatch(this.getFile());
if (contentRequestsDefaults(content)) {
return;
}
content = this.getGson().toJson(this);
DiscUtil.writeCatch(file, content);
}
}

View File

@ -0,0 +1,186 @@
package com.massivecraft.massivecore;
import com.massivecraft.massivecore.command.editor.annotation.EditorName;
import com.massivecraft.massivecore.command.editor.annotation.EditorNullable;
import com.massivecraft.massivecore.command.editor.annotation.EditorType;
import com.massivecraft.massivecore.command.type.enumeration.TypeSound;
import com.massivecraft.massivecore.command.type.enumeration.TypeSoundId;
import com.massivecraft.massivecore.util.MUtil;
import org.bukkit.Location;
import org.bukkit.Sound;
import org.bukkit.entity.HumanEntity;
import org.bukkit.entity.Player;
import java.io.Serializable;
import java.util.Collection;
public final class SoundEffect implements Serializable {
private static final transient long serialVersionUID = 1L;
// -------------------------------------------- //
// FIELDS: RAW
// -------------------------------------------- //
@EditorNullable(false)
@EditorName("sound")
@EditorType(TypeSoundId.class)
private final String soundId;
public String getSoundId() {
return this.soundId;
}
public Sound getSound() {
return TypeSound.valueOf(this.getSoundId());
}
private final float volume;
public float getVolume() {
return this.volume;
}
private final float pitch;
public float getPitch() {
return this.pitch;
}
// -------------------------------------------- //
// FIELDS: WITH
// -------------------------------------------- //
public SoundEffect withSoundId(String soundId) {
return new SoundEffect(soundId, volume, pitch);
}
public SoundEffect withSound(Sound sound) {
return new SoundEffect(TypeSound.get().getId(sound), volume, pitch);
}
public SoundEffect withVolume(float volume) {
return new SoundEffect(soundId, volume, pitch);
}
public SoundEffect withPitch(float pitch) {
return new SoundEffect(soundId, volume, pitch);
}
// -------------------------------------------- //
// CONSTUCT
// -------------------------------------------- //
private SoundEffect(String soundId, float volume, float pitch) {
this.soundId = soundId;
this.volume = volume;
this.pitch = pitch;
}
private SoundEffect() {
// No Arg Constructor for GSON
this(null, 1.0f, 1.0f);
}
// -------------------------------------------- //
// VALUE OF
// -------------------------------------------- //
public static SoundEffect valueOf(String soundId, float volume, float pitch) {
return new SoundEffect(soundId, volume, pitch);
}
public static SoundEffect valueOf(Sound sound, float volume, float pitch) {
return valueOf(TypeSound.get().getId(sound), volume, pitch);
}
// -------------------------------------------- //
// RUN
// -------------------------------------------- //
public void run(Location location) {
if (location == null) {
throw new NullPointerException("location");
}
location.getWorld().playSound(location, this.getSound(), this.getVolume(), this.getPitch());
}
public void run(HumanEntity human, Location location) {
if (human == null) {
throw new NullPointerException("human");
}
if (MUtil.isntPlayer(human)) {
return;
}
Player player = (Player) human;
player.playSound(location, this.getSound(), this.getVolume(), this.getPitch());
}
public void run(HumanEntity human) {
if (human == null) {
throw new NullPointerException("human");
}
if (MUtil.isntPlayer(human)) {
return;
}
this.run(human, human.getEyeLocation());
}
// -------------------------------------------- //
// RUN ALL
// -------------------------------------------- //
public static void runAll(Collection<SoundEffect> soundEffects, Location location) {
for (SoundEffect soundEffect : soundEffects) {
soundEffect.run(location);
}
}
public static void runAll(Collection<SoundEffect> soundEffects, HumanEntity human, Location location) {
for (SoundEffect soundEffect : soundEffects) {
soundEffect.run(human, location);
}
}
public static void runAll(Collection<SoundEffect> soundEffects, HumanEntity human) {
for (SoundEffect soundEffect : soundEffects) {
soundEffect.run(human);
}
}
// -------------------------------------------- //
// EQUALS & HASHCODE
// -------------------------------------------- //
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + Float.floatToIntBits(pitch);
result = prime * result + ((soundId == null) ? 0 : soundId.hashCode());
result = prime * result + Float.floatToIntBits(volume);
return result;
}
@Override
public boolean equals(Object obj) {
if (!(obj instanceof SoundEffect)) {
return false;
}
SoundEffect other = (SoundEffect) obj;
if (Float.floatToIntBits(pitch) != Float.floatToIntBits(other.pitch)) {
return false;
}
if (soundId == null) {
if (other.soundId != null) {
return false;
}
} else if (!soundId.equals(other.soundId)) {
return false;
}
if (Float.floatToIntBits(volume) != Float.floatToIntBits(other.volume)) {
return false;
}
return true;
}
}

View File

@ -0,0 +1,138 @@
package com.massivecraft.massivecore;
import com.massivecraft.massivecore.collections.MassiveList;
import com.massivecraft.massivecore.util.Txt;
import java.util.List;
import java.util.function.Supplier;
/**
* This class is for tasks that are only run infrequently such as once a day
* and whose frequency must stay consistent between server restarts.
* An example is Faction taxing which must happen exactly once a day.
*/
public abstract class Task extends Engine {
// -------------------------------------------- //
// FIELDS
// -------------------------------------------- //
private boolean mustBeTaskServer = false;
public boolean mustBeTaskServer() {
return mustBeTaskServer;
}
public void setMustBeTaskServer(boolean mustBeTaskServer) {
this.mustBeTaskServer = mustBeTaskServer;
}
private boolean logTimeSpent = false;
public boolean isLoggingTimeSpent() {
return logTimeSpent;
}
public void setLoggingTimeSpent(boolean logTimeSpent) {
this.logTimeSpent = logTimeSpent;
}
private List<Supplier<Boolean>> conditions = new MassiveList<>();
public List<Supplier<Boolean>> getConditions() {
return conditions;
}
public void setConditions(List<Supplier<Boolean>> conditions) {
this.conditions = conditions;
}
public void addCondition(Supplier<Boolean> condition) {
this.conditions.add(condition);
}
public boolean areConditionsMet() {
return conditions.stream().map(Supplier::get).allMatch(b -> b == true);
}
// -------------------------------------------- //
// CONSTRUCT
// -------------------------------------------- //
public Task() {
this.setPeriod(60 * 20L); // Once a minute
}
// -------------------------------------------- //
// INVOKE
// -------------------------------------------- //
@Override
public void run() {
// Should it be the task server?
if (this.mustBeTaskServer() && !MassiveCore.isTaskServer()) {
return;
}
// So the delay millis is lower than one? (could for example be zero)
// This probably means the task should not be executed at all.
if (this.getPeriodMillis() < 1) {
return;
}
// Other conditions
if (!this.areConditionsMet()) {
return;
}
// INVOCATION
long nowMillis = System.currentTimeMillis();
long lastMillis = this.getPreviousMillis();
long currentInvocation = this.getInvocationFromMillis(nowMillis);
long lastInvocation = this.getInvocationFromMillis(lastMillis);
if (currentInvocation == lastInvocation) {
return;
}
// Log time spent and invoke
if (this.isLoggingTimeSpent()) {
String message = Txt.parse("<h>Running %s.", this.getClass().getSimpleName());
this.getPlugin().log(message);
}
long startNano = System.nanoTime();
this.invoke(nowMillis);
this.setPreviousMillis(nowMillis);
long endNano = System.nanoTime();
double elapsedSeconds = (endNano - startNano) / 1000_000_000D;
if (this.isLoggingTimeSpent()) {
String msg = String.format("<i>Took <h>%.2f <i>seconds.", elapsedSeconds);
msg = Txt.parse(msg);
this.getPlugin().log(msg);
}
}
public abstract void invoke(long now);
// -------------------------------------------- //
// TASK MILLIS AND INVOCATION
// -------------------------------------------- //
// The invocation is the amount of periods from UNIX time to now.
// It will increment by one when a period has passed.
public abstract long getPreviousMillis();
public abstract void setPreviousMillis(long millis);
public abstract long getPeriodMillis();
public abstract long getOffsetMillis();
// Here we accept millis from inside the period by rounding down.
private long getInvocationFromMillis(long millis) {
return (millis - this.getOffsetMillis()) / this.getPeriodMillis();
}
}

View File

@ -0,0 +1,96 @@
package com.massivecraft.massivecore;
import com.massivecraft.massivecore.util.MUtil;
import java.io.Serializable;
public class Triple<A, B, C> implements Cloneable, Serializable {
// -------------------------------------------- //
// CONSTANTS
// -------------------------------------------- //
private static final transient long serialVersionUID = 1L;
// -------------------------------------------- //
// FIELDS: RAW
// -------------------------------------------- //
private final A first;
public A getFirst() {
return this.first;
}
private final B second;
public B getSecond() {
return this.second;
}
private final C third;
public C getThird() {
return this.third;
}
// -------------------------------------------- //
// FIELDS: WITH
// -------------------------------------------- //
public Triple<A, B, C> withFirst(A first) {
return valueOf(first, second, third);
}
public Triple<A, B, C> withSecond(B second) {
return valueOf(first, second, third);
}
// -------------------------------------------- //
// CONSTRUCT
// -------------------------------------------- //
public Triple() {
this(null, null, null);
}
public Triple(A first, B second, C third) {
this.first = first;
this.second = second;
this.third = third;
}
// -------------------------------------------- //
// FACTORY: VALUE OF
// -------------------------------------------- //
public static <A, B, C> Triple<A, B, C> valueOf(A first, B second, C third) {
return new Triple<>(first, second, third);
}
// -------------------------------------------- //
// EQUALS
// -------------------------------------------- //
@Override
public boolean equals(Object object) {
if (!(object instanceof Triple<?, ?, ?>)) {
return false;
}
Triple<?, ?, ?> that = (Triple<?, ?, ?>) object;
return MUtil.equals(
this.getFirst(), that.getFirst(),
this.getSecond(), that.getSecond(),
this.getThird(), that.getThird()
);
}
// -------------------------------------------- //
// CLONE
// -------------------------------------------- //
@Override
public Triple<A, B, C> clone() {
return this;
}
}

View File

@ -0,0 +1,54 @@
package com.massivecraft.massivecore.adapter;
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonDeserializer;
import com.google.gson.JsonElement;
import com.google.gson.JsonParseException;
import com.google.gson.JsonSerializationContext;
import com.google.gson.JsonSerializer;
import com.google.gson.reflect.TypeToken;
import com.massivecraft.massivecore.collections.BackstringSet;
import com.massivecraft.massivecore.command.type.RegistryType;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Set;
public class AdapterBackstringSet implements JsonDeserializer<BackstringSet<?>>, JsonSerializer<BackstringSet<?>> {
// -------------------------------------------- //
// CONSTANTS
// -------------------------------------------- //
public final static Type stringSetType = new TypeToken<Set<String>>() {
}.getType();
// -------------------------------------------- //
// INSTANCE & CONSTRUCT
// -------------------------------------------- //
private static final AdapterBackstringSet i = new AdapterBackstringSet();
public static AdapterBackstringSet get() {
return i;
}
// -------------------------------------------- //
// OVERRIDE
// -------------------------------------------- //
@Override
public JsonElement serialize(BackstringSet<?> src, Type type, JsonSerializationContext context) {
return context.serialize(src.getStringSet(), stringSetType);
}
@SuppressWarnings({"unchecked"})
@Override
public BackstringSet<?> deserialize(JsonElement json, Type type, JsonDeserializationContext context) throws JsonParseException {
Set<String> stringSet = context.deserialize(json, stringSetType);
ParameterizedType ptype = (ParameterizedType) type;
Type[] args = ptype.getActualTypeArguments();
Class<?> clazz = (Class<?>) args[0];
return new BackstringSet(RegistryType.getType(clazz), stringSet);
}
}

View File

@ -0,0 +1,82 @@
package com.massivecraft.massivecore.adapter;
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonDeserializer;
import com.google.gson.JsonElement;
import com.google.gson.JsonNull;
import com.google.gson.JsonObject;
import com.google.gson.JsonParseException;
import com.google.gson.JsonSerializationContext;
import com.google.gson.JsonSerializer;
import com.massivecraft.massivecore.store.EntityInternal;
import com.massivecraft.massivecore.store.EntityInternalMap;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Map;
import java.util.Map.Entry;
public class AdapterEntityInternalMap implements JsonDeserializer<EntityInternalMap<?>>, JsonSerializer<EntityInternalMap<?>> {
// -------------------------------------------- //
// INSTANCE & CONSTRUCT
// -------------------------------------------- //
private static final AdapterEntityInternalMap i = new AdapterEntityInternalMap();
public static AdapterEntityInternalMap get() {
return i;
}
// -------------------------------------------- //
// OVERRIDE
// -------------------------------------------- //
@Override
public JsonElement serialize(EntityInternalMap<?> src, Type type, JsonSerializationContext context) {
// NULL
if (src == null) {
return JsonNull.INSTANCE;
}
// Get value
Map<String, ?> contents = src.getIdToEntity();
// Create ret
JsonElement ret = context.serialize(contents);
// Return Ret
return ret;
}
@Override
public EntityInternalMap<?> deserialize(JsonElement json, Type type, JsonDeserializationContext context) throws JsonParseException {
// NULL
if (json == null) {
return null;
}
if (json instanceof JsonNull) {
return null;
}
// Get type
Class<? extends EntityInternal> entityType = (Class) ((ParameterizedType) type).getActualTypeArguments()[0];
// Create ret
EntityInternalMap ret = new EntityInternalMap<>(entityType);
// Fill ret
JsonObject jsonObject = (JsonObject) json;
for (Entry<String, JsonElement> entry : jsonObject.entrySet()) {
String id = entry.getKey();
JsonElement value = entry.getValue();
EntityInternal obj = context.deserialize(value, entityType);
ret.getIdToEntityRaw().put(id, obj);
}
// Return ret
return ret;
}
}

View File

@ -0,0 +1,101 @@
package com.massivecraft.massivecore.adapter;
import com.google.gson.JsonArray;
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonDeserializer;
import com.google.gson.JsonElement;
import com.google.gson.JsonNull;
import com.google.gson.JsonParseException;
import com.google.gson.JsonSerializationContext;
import com.google.gson.JsonSerializer;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.AbstractMap.SimpleEntry;
import java.util.Map.Entry;
public class AdapterEntry implements JsonDeserializer<Entry<?, ?>>, JsonSerializer<Entry<?, ?>> {
// -------------------------------------------- //
// INSTANCE & CONSTRUCT
// -------------------------------------------- //
private static final AdapterEntry i = new AdapterEntry();
public static AdapterEntry get() {
return i;
}
// -------------------------------------------- //
// OVERRIDE
// -------------------------------------------- //
@Override
public JsonElement serialize(Entry<?, ?> src, Type type, JsonSerializationContext context) {
// NULL
if (src == null) {
return JsonNull.INSTANCE;
}
// Create Ret
JsonArray ret = new JsonArray();
// Fill Ret
Object key = src.getKey();
Object value = src.getValue();
Type keyType = getKeyType(type);
Type valueType = getValueType(type);
JsonElement keyJson = context.serialize(key, keyType);
JsonElement valueJson = context.serialize(value, valueType);
ret.add(keyJson);
ret.add(valueJson);
// Return Ret
return ret;
}
@Override
public Entry<?, ?> deserialize(JsonElement json, Type type, JsonDeserializationContext context) throws JsonParseException {
// NULL
if (json == null) {
return null;
}
if (json instanceof JsonNull) {
return null;
}
JsonArray jsonArray = (JsonArray) json;
JsonElement keyJson = jsonArray.get(0);
JsonElement valueJson = jsonArray.get(1);
Type keyType = getKeyType(type);
Type valueType = getValueType(type);
Object key = context.deserialize(keyJson, keyType);
Object value = context.deserialize(valueJson, valueType);
return new SimpleEntry<>(key, value);
}
// -------------------------------------------- //
// UTIL
// -------------------------------------------- //
public static Type getKeyType(Type type) {
return getType(type, 0);
}
public static Type getValueType(Type type) {
return getType(type, 1);
}
public static Type getType(Type type, int index) {
ParameterizedType ptype = (ParameterizedType) type;
Type[] types = ptype.getActualTypeArguments();
return types[index];
}
}

View File

@ -0,0 +1,37 @@
package com.massivecraft.massivecore.adapter;
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonDeserializer;
import com.google.gson.JsonElement;
import com.google.gson.JsonParseException;
import com.google.gson.JsonSerializationContext;
import com.google.gson.JsonSerializer;
import java.lang.reflect.Type;
public class AdapterJsonElement implements JsonDeserializer<JsonElement>, JsonSerializer<JsonElement> {
// -------------------------------------------- //
// INSTANCE & CONSTRUCT
// -------------------------------------------- //
private static final AdapterJsonElement i = new AdapterJsonElement();
public static AdapterJsonElement get() {
return i;
}
// -------------------------------------------- //
// OVERRIDE
// -------------------------------------------- //
@Override
public JsonElement serialize(JsonElement src, Type typeOfSrc, JsonSerializationContext context) {
return src;
}
@Override
public JsonElement deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
return json;
}
}

View File

@ -0,0 +1,131 @@
package com.massivecraft.massivecore.adapter;
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonDeserializer;
import com.google.gson.JsonElement;
import com.google.gson.JsonNull;
import com.google.gson.JsonParseException;
import com.google.gson.JsonPrimitive;
import com.google.gson.JsonSerializationContext;
import com.google.gson.JsonSerializer;
import java.lang.reflect.Type;
public class AdapterLowercaseEnum<T extends Enum<T>> implements JsonDeserializer<T>, JsonSerializer<T> {
// -------------------------------------------- //
// FIELDS
// -------------------------------------------- //
private final Class<T> clazz;
public Class<T> getClazz() {
return this.clazz;
}
// -------------------------------------------- //
// INSTANCE
// -------------------------------------------- //
public static <T extends Enum<T>> AdapterLowercaseEnum<T> get(Class<T> clazz) {
return new AdapterLowercaseEnum<>(clazz);
}
// -------------------------------------------- //
// CONSTRUCT
// -------------------------------------------- //
public AdapterLowercaseEnum(Class<T> clazz) {
if (clazz == null) {
throw new IllegalArgumentException("clazz is null");
}
if (!clazz.isEnum()) {
throw new IllegalArgumentException("clazz is not enum");
}
this.clazz = clazz;
}
// -------------------------------------------- //
// OVERRIDE
// -------------------------------------------- //
@Override
public JsonElement serialize(T src, Type typeOfSrc, JsonSerializationContext context) {
// Null
if (src == null) {
return JsonNull.INSTANCE;
}
String comparable = this.getComparable(src);
return new JsonPrimitive(comparable);
}
@Override
public T deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
// Null
if (json == null) {
return null;
}
if (json.equals(JsonNull.INSTANCE)) {
return null;
}
T ret = this.getEnumValueFrom(json);
return ret;
}
// -------------------------------------------- //
// GET ENUM VALUE FROM
// -------------------------------------------- //
public T getEnumValueFrom(JsonElement json) {
String string = this.getComparable(json);
return this.getEnumValueFrom(string);
}
public T getEnumValueFrom(String string) {
string = this.getComparable(string);
for (T value : this.getEnumValues()) {
String comparable = this.getComparable(value);
if (comparable.equals(string)) {
return value;
}
}
return null;
}
// -------------------------------------------- //
// GET ENUM VALUES
// -------------------------------------------- //
public T[] getEnumValues() {
Class<T> clazz = this.getClazz();
T[] ret = clazz.getEnumConstants();
return ret;
}
// -------------------------------------------- //
// GET COMPARABLE
// -------------------------------------------- //
public String getComparable(Enum<?> value) {
if (value == null) {
return null;
}
return this.getComparable(value.name());
}
public String getComparable(JsonElement json) {
if (json == null) {
return null;
}
return this.getComparable(json.getAsString());
}
public String getComparable(String string) {
if (string == null) {
return null;
}
return string.toLowerCase();
}
}

View File

@ -0,0 +1,36 @@
package com.massivecraft.massivecore.adapter;
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonElement;
import com.massivecraft.massivecore.collections.MassiveList;
import com.massivecraft.massivecore.collections.MassiveListDef;
import java.lang.reflect.Type;
import java.util.Collection;
public class AdapterMassiveList extends AdapterMassiveX<MassiveList<?>> {
// -------------------------------------------- //
// INSTANCE & CONSTRUCT
// -------------------------------------------- //
private static final AdapterMassiveList i = new AdapterMassiveList();
public static AdapterMassiveList get() {
return i;
}
// -------------------------------------------- //
// OVERRIDE
// -------------------------------------------- //
@SuppressWarnings({"rawtypes", "unchecked"})
@Override
public MassiveList<?> create(Object parent, boolean def, JsonElement json, Type typeOfT, JsonDeserializationContext context) {
if (def) {
return new MassiveListDef((Collection) parent);
} else {
return new MassiveList((Collection) parent);
}
}
}

View File

@ -0,0 +1,36 @@
package com.massivecraft.massivecore.adapter;
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonElement;
import com.massivecraft.massivecore.collections.MassiveMap;
import com.massivecraft.massivecore.collections.MassiveMapDef;
import java.lang.reflect.Type;
import java.util.Map;
public class AdapterMassiveMap extends AdapterMassiveX<MassiveMap<?, ?>> {
// -------------------------------------------- //
// INSTANCE & CONSTRUCT
// -------------------------------------------- //
private static final AdapterMassiveMap i = new AdapterMassiveMap();
public static AdapterMassiveMap get() {
return i;
}
// -------------------------------------------- //
// OVERRIDE
// -------------------------------------------- //
@SuppressWarnings({"rawtypes", "unchecked"})
@Override
public MassiveMap<?, ?> create(Object parent, boolean def, JsonElement json, Type typeOfT, JsonDeserializationContext context) {
if (def) {
return new MassiveMapDef((Map) parent);
} else {
return new MassiveMap((Map) parent);
}
}
}

View File

@ -0,0 +1,36 @@
package com.massivecraft.massivecore.adapter;
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonElement;
import com.massivecraft.massivecore.collections.MassiveSet;
import com.massivecraft.massivecore.collections.MassiveSetDef;
import java.lang.reflect.Type;
import java.util.Collection;
public class AdapterMassiveSet extends AdapterMassiveX<MassiveSet<?>> {
// -------------------------------------------- //
// INSTANCE & CONSTRUCT
// -------------------------------------------- //
private static final AdapterMassiveSet i = new AdapterMassiveSet();
public static AdapterMassiveSet get() {
return i;
}
// -------------------------------------------- //
// OVERRIDE
// -------------------------------------------- //
@SuppressWarnings({"rawtypes", "unchecked"})
@Override
public MassiveSet<?> create(Object parent, boolean def, JsonElement json, Type typeOfT, JsonDeserializationContext context) {
if (def) {
return new MassiveSetDef((Collection) parent);
} else {
return new MassiveSet((Collection) parent);
}
}
}

View File

@ -0,0 +1,45 @@
package com.massivecraft.massivecore.adapter;
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonElement;
import com.massivecraft.massivecore.collections.MassiveTreeMap;
import com.massivecraft.massivecore.collections.MassiveTreeMapDef;
import java.lang.reflect.Type;
import java.util.Map;
public class AdapterMassiveTreeMap extends AdapterMassiveX<MassiveTreeMap<?, ?, ?>> {
// -------------------------------------------- //
// INSTANCE & CONSTRUCT
// -------------------------------------------- //
private static final AdapterMassiveTreeMap i = new AdapterMassiveTreeMap();
public static AdapterMassiveTreeMap get() {
return i;
}
// -------------------------------------------- //
// OVERRIDE
// -------------------------------------------- //
@SuppressWarnings({"rawtypes", "unchecked"})
@Override
public MassiveTreeMap<?, ?, ?> create(Object parent, boolean def, JsonElement json, Type typeOfT, JsonDeserializationContext context) {
Object comparator = getComparator(typeOfT);
if (def) {
return new MassiveTreeMapDef(comparator, (Map) parent);
} else {
return new MassiveTreeMap(comparator, (Map) parent);
}
}
// -------------------------------------------- //
// GET COMPARATOR
// -------------------------------------------- //
public static Object getComparator(Type typeOfT) {
return getNewArgumentInstance(typeOfT, 2);
}
}

View File

@ -0,0 +1,45 @@
package com.massivecraft.massivecore.adapter;
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonElement;
import com.massivecraft.massivecore.collections.MassiveTreeSet;
import com.massivecraft.massivecore.collections.MassiveTreeSetDef;
import java.lang.reflect.Type;
import java.util.Collection;
public class AdapterMassiveTreeSet extends AdapterMassiveX<MassiveTreeSet<?, ?>> {
// -------------------------------------------- //
// INSTANCE & CONSTRUCT
// -------------------------------------------- //
private static final AdapterMassiveTreeSet i = new AdapterMassiveTreeSet();
public static AdapterMassiveTreeSet get() {
return i;
}
// -------------------------------------------- //
// OVERRIDE
// -------------------------------------------- //
@SuppressWarnings({"rawtypes", "unchecked"})
@Override
public MassiveTreeSet<?, ?> create(Object parent, boolean def, JsonElement json, Type typeOfT, JsonDeserializationContext context) {
Object comparator = getComparator(typeOfT);
if (def) {
return new MassiveTreeSetDef(comparator, (Collection) parent);
} else {
return new MassiveTreeSet(comparator, (Collection) parent);
}
}
// -------------------------------------------- //
// GET COMPARATOR
// -------------------------------------------- //
public static Object getComparator(Type typeOfT) {
return getNewArgumentInstance(typeOfT, 1);
}
}

View File

@ -0,0 +1,181 @@
package com.massivecraft.massivecore.adapter;
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonDeserializer;
import com.google.gson.JsonElement;
import com.google.gson.JsonNull;
import com.google.gson.JsonParseException;
import com.google.gson.JsonSerializationContext;
import com.google.gson.JsonSerializer;
import com.google.gson.internal.$Gson$Types;
import com.massivecraft.massivecore.collections.Def;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Arrays;
import java.util.Collection;
import java.util.Map;
/**
* This is the abstract adapter for all "Massive structures".
* It makes sure Def instances "handle empty as null".
* It makes sure we avoid infinite GSON recurse loops by recursing with supertype.
*/
public abstract class AdapterMassiveX<T> implements JsonDeserializer<T>, JsonSerializer<T> {
// -------------------------------------------- //
// OVERRIDE
// -------------------------------------------- //
@Override
public JsonElement serialize(T src, Type type, JsonSerializationContext context) {
ParameterizedType ptype = (ParameterizedType) type;
// Calculate def
Class<?> clazz = getClazz(ptype);
boolean def = Def.class.isAssignableFrom(clazz);
// If this is a Def ...
if (def) {
// ... and the instance is null or contains no elements ...
if (isEmpty(src)) {
// ... then serialize as a JsonNull!
return JsonNull.INSTANCE;
}
// ... and it's non null and contains something ...
else {
// ... then serialize it as if it were the regular Java collection!
// SUPER TYPE x2 EXAMPLE: MassiveListDef --> MassiveList --> ArrayList
return context.serialize(src, getSuperType(getSuperType(ptype)));
}
}
// If this a regular Massive structure and not a Def ...
else {
// ... then serialize it as if it were the regular java collection!
// SUPER TYPE x1 EXAMPLE: MassiveList --> ArrayList
return context.serialize(src, getSuperType(ptype));
}
}
@Override
public T deserialize(JsonElement json, Type type, JsonDeserializationContext context) throws JsonParseException {
ParameterizedType ptype = (ParameterizedType) type;
/*// TODO: Temporary Debug
if (MUtil.getStackTraceString().contains("com.massivecraft.factions.entity.FactionColl.init"))
{
typeDebug(ptype);
typeDebug(getSuperType(ptype));
typeDebug(getSuperType(getSuperType(ptype)));
}*/
// Calculate def
Class<?> clazz = getClazz(ptype);
boolean def = Def.class.isAssignableFrom(clazz);
// If this is a Def ...
if (def) {
// ... then deserialize it as if it were the regular Java collection!
// SUPER TYPE x2 EXAMPLE: MassiveListDef --> MassiveList --> ArrayList
Object parent = context.deserialize(json, getSuperType(getSuperType(ptype)));
return create(parent, def, json, type, context);
}
// If this a regular Massive structure and not a Def ...
else {
// ... and the json is null or a JsonNull ...
if (json == null || json instanceof JsonNull) {
// ... then deserialize as a null!
return null;
}
// ... and it's non null and contains something ...
else {
// ... then deserialize it as if it were the regular java collection!
// SUPER TYPE x1 EXAMPLE: MassiveList --> ArrayList
Object parent = context.deserialize(json, getSuperType(ptype));
return create(parent, def, json, type, context);
}
}
}
/*
public static void typeDebug(ParameterizedType ptype)
{
System.out.println("=== Type Debug Start ===");
System.out.println(ptype.toString());
ParameterizedType parameterizedType = (ParameterizedType) ptype;
System.out.println("Actual Type Arguments: " + Txt.implode(parameterizedType.getActualTypeArguments(), ", "));
System.out.println("=== Type Debug End ===");
}*/
// -------------------------------------------- //
// ABSTRACT
// -------------------------------------------- //
public abstract T create(Object parent, boolean def, JsonElement json, Type typeOfT, JsonDeserializationContext context);
// -------------------------------------------- //
// UTIL
// -------------------------------------------- //
public static Class<?> getClazz(ParameterizedType ptype) {
return (Class<?>) ptype.getRawType();
}
public static ParameterizedType getSuperType(ParameterizedType ptype) {
// ------- SELF -------
// Get args
Type[] args = ptype.getActualTypeArguments();
// Get clazz
Class<?> clazz = (Class<?>) ptype.getRawType();
// ------- SUPER -------
// Get stype
ParameterizedType sptype = (ParameterizedType) clazz.getGenericSuperclass();
// Get sargs
// NOTE: These will be broken! we can however look at the count!
Type[] sargs = sptype.getActualTypeArguments();
// Get sclazz
Class<?> sclazz = (Class<?>) sptype.getRawType();
// ------- CONSTRUCTED -------
Type[] typeArguments = Arrays.copyOfRange(args, 0, sargs.length);
return $Gson$Types.newParameterizedTypeWithOwner(null, sclazz, typeArguments);
}
public static Object getNewArgumentInstance(Type type, int index) {
ParameterizedType parameterizedType = (ParameterizedType) type;
Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
Class<?> clazz = (Class<?>) actualTypeArguments[index];
try {
return clazz.getDeclaredConstructor().newInstance();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
@SuppressWarnings("rawtypes")
public static boolean isEmpty(Object object) {
// A Map is not a Collection.
// Thus we have to use isEmpty() declared in different interfaces.
if (object == null) {
return true;
}
if (object instanceof Map) {
return ((Map) object).isEmpty();
}
if (object instanceof Collection) {
return ((Collection) object).isEmpty();
}
return false;
}
}

View File

@ -0,0 +1,91 @@
package com.massivecraft.massivecore.adapter;
import com.google.gson.Gson;
import com.google.gson.TypeAdapter;
import com.google.gson.TypeAdapterFactory;
import com.google.gson.annotations.SerializedName;
import com.google.gson.reflect.TypeToken;
import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonToken;
import com.google.gson.stream.JsonWriter;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
/**
* This type adapter and factory handles modified Java Enums.
* It's based upon: https://github.com/MassiveCraft/MassiveCore/blob/91f9ec7c0c7d9a11a35db905be520f5cf6b6743e/src/com/massivecraft/MassiveCore/xlib/gson/internal/bind/TypeAdapters.java#L670
* The only change is the try-catch around the annotation code.
* <p>
* https://github.com/MassiveCraft/MassiveCore/pull/62
* <p>
* # Problem
* The problem that was occurring is Forge modifies Vanilla Minecraft Enums
* (see https://github.com/MinecraftForge/MinecraftForge/blob/master/common/net/minecraftforge/common/EnumHelper.java)
* the way that it modifies the Enum is pure Java hackery modifying $VALUES on the underlying Enum.
* This will update the calls to Class.getEnumContants but won't update any fields on the Enum.
* So when the built-in Gson EnumTypeAdaper tries to see if any SerializedName annotations are on the fields of the Enum,
* it can't find a field with the new names and throws an exception.
* <p>
* # Reasoning
* There is really not any way that we could put any fix in on the MCPC+ side since we can't add fields to Java enums at runtime.
* <p>
* # Solution
* This ModdedEnumTypeAdapter is basically just a straight copy of the built-in one,
* but ignores when it can't find the field/annotation (which is the desired behavior in this case anyways).
* I tested this with Factions on the latest MCPC+ release and it resolves the issue that was logged.
* Hopefully this will reduce the number of people opening issues on both sides.
* If you have any questions, feel free to hit me up on IRC.
*
* @author OniBait
*/
public final class AdapterModdedEnumType<T extends Enum<T>> extends TypeAdapter<T> {
private final Map<String, T> nameToConstant = new HashMap<>();
private final Map<T, String> constantToName = new HashMap<>();
public AdapterModdedEnumType(Class<T> classOfT) {
for (T constant : classOfT.getEnumConstants()) {
String name = constant.name();
try { // MassiveCore - Ignore when the field can't be found since modified enums won't have it.
SerializedName annotation = classOfT.getField(name).getAnnotation(SerializedName.class);
if (annotation != null) {
name = annotation.value();
}
} catch (NoSuchFieldException ex) {
} // MassiveCore
nameToConstant.put(name, constant);
constantToName.put(constant, name);
}
}
public T read(JsonReader in) throws IOException {
if (in.peek() == JsonToken.NULL) {
in.nextNull();
return null;
}
return nameToConstant.get(in.nextString());
}
public void write(JsonWriter out, T value) throws IOException {
out.value(value == null ? null : constantToName.get(value));
}
public static final TypeAdapterFactory ENUM_FACTORY = newEnumTypeHierarchyFactory();
public static <TT> TypeAdapterFactory newEnumTypeHierarchyFactory() {
return new TypeAdapterFactory() {
@SuppressWarnings({"unchecked"})
public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> typeToken) {
Class<? super T> rawType = typeToken.getRawType();
if (!Enum.class.isAssignableFrom(rawType) || rawType == Enum.class) {
return null;
}
if (!rawType.isEnum()) {
rawType = rawType.getSuperclass(); // handle anonymous subclasses
}
return (TypeAdapter<T>) new AdapterModdedEnumType(rawType);
}
};
}
}

View File

@ -0,0 +1,38 @@
package com.massivecraft.massivecore.adapter;
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonDeserializer;
import com.google.gson.JsonElement;
import com.google.gson.JsonParseException;
import com.google.gson.JsonSerializationContext;
import com.google.gson.JsonSerializer;
import com.massivecraft.massivecore.mson.Mson;
import java.lang.reflect.Type;
public class AdapterMson implements JsonDeserializer<Mson>, JsonSerializer<Mson> {
// -------------------------------------------- //
// INSTANCE & CONSTRUCT
// -------------------------------------------- //
private static final AdapterMson i = new AdapterMson();
public static AdapterMson get() {
return i;
}
// -------------------------------------------- //
// OVERRIDE
// -------------------------------------------- //
@Override
public JsonElement serialize(Mson src, Type typeOfSrc, JsonSerializationContext context) {
return Mson.toJson(src);
}
@Override
public Mson deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
return Mson.fromJson(json);
}
}

View File

@ -0,0 +1,38 @@
package com.massivecraft.massivecore.adapter;
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonDeserializer;
import com.google.gson.JsonElement;
import com.google.gson.JsonParseException;
import com.google.gson.JsonSerializationContext;
import com.google.gson.JsonSerializer;
import com.massivecraft.massivecore.mson.MsonEvent;
import java.lang.reflect.Type;
public class AdapterMsonEvent implements JsonDeserializer<MsonEvent>, JsonSerializer<MsonEvent> {
// -------------------------------------------- //
// INSTANCE & CONSTRUCT
// -------------------------------------------- //
private static final AdapterMsonEvent i = new AdapterMsonEvent();
public static AdapterMsonEvent get() {
return i;
}
// -------------------------------------------- //
// OVERRIDE
// -------------------------------------------- //
@Override
public JsonElement serialize(MsonEvent src, Type typeOfSrc, JsonSerializationContext context) {
return MsonEvent.toJson(src);
}
@Override
public MsonEvent deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
return MsonEvent.fromJson(json);
}
}

View File

@ -0,0 +1,41 @@
package com.massivecraft.massivecore.adapter;
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonDeserializer;
import com.google.gson.JsonElement;
import com.google.gson.JsonParseException;
import com.google.gson.JsonSerializationContext;
import com.google.gson.JsonSerializer;
import com.massivecraft.massivecore.mson.Mson;
import com.massivecraft.massivecore.mson.MsonEvent;
import java.lang.reflect.Type;
public class AdapterMsonEventFix implements JsonDeserializer<MsonEvent>, JsonSerializer<MsonEvent> {
// -------------------------------------------- //
// INSTANCE & CONSTRUCT
// -------------------------------------------- //
private static final AdapterMsonEventFix i = new AdapterMsonEventFix();
public static AdapterMsonEventFix get() {
return i;
}
// -------------------------------------------- //
// OVERRIDE
// -------------------------------------------- //
@Override
public JsonElement serialize(MsonEvent src, Type typeOfSrc, JsonSerializationContext context) {
return Mson.getGson(false).toJsonTree(src);
}
@Override
public MsonEvent deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
MsonEvent ret = Mson.getGson(false).fromJson(json, MsonEvent.class);
ret.repair();
return ret;
}
}

View File

@ -0,0 +1,63 @@
package com.massivecraft.massivecore.adapter;
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonDeserializer;
import com.google.gson.JsonElement;
import com.google.gson.JsonNull;
import com.google.gson.JsonObject;
import com.google.gson.JsonParseException;
import com.google.gson.JsonSerializationContext;
import com.google.gson.JsonSerializer;
import java.lang.reflect.Type;
public class AdapterPolymorphic<T> implements JsonDeserializer<T>, JsonSerializer<T> {
public static final String TYPE = "type";
public static final String VALUE = "value";
@Override
public JsonElement serialize(T src, Type typeOfSrc, JsonSerializationContext context) {
if (src == null) {
return JsonNull.INSTANCE;
}
JsonObject ret = new JsonObject();
String type = src.getClass().getCanonicalName();
ret.addProperty(TYPE, type);
JsonElement value = context.serialize(src);
ret.add(VALUE, value);
return ret;
}
@Override
public T deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
if (!json.isJsonObject()) {
throw new JsonParseException("A polymorph must be an object.");
}
JsonObject jsonObject = json.getAsJsonObject();
if (!jsonObject.has(TYPE)) {
throw new JsonParseException("A polymorph must be have a \"" + TYPE + "\" field.");
}
if (!jsonObject.has(VALUE)) {
throw new JsonParseException("A polymorph must be have a \"+VALUE+\" field.");
}
String type = jsonObject.get(TYPE).getAsString();
Class<?> typeClass = null;
try {
typeClass = Class.forName(type);
} catch (ClassNotFoundException e) {
e.printStackTrace();
throw new JsonParseException(e.getMessage());
}
return context.deserialize(jsonObject.get(VALUE), typeClass);
}
}

View File

@ -0,0 +1,49 @@
package com.massivecraft.massivecore.adapter;
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonDeserializer;
import com.google.gson.JsonElement;
import com.google.gson.JsonNull;
import com.google.gson.JsonParseException;
import com.google.gson.JsonPrimitive;
import com.google.gson.JsonSerializationContext;
import com.google.gson.JsonSerializer;
import org.bukkit.Sound;
import java.lang.reflect.Type;
public class AdapterSound implements JsonDeserializer<Sound>, JsonSerializer<Sound> {
// -------------------------------------------- //
// INSTANCE & CONSTRUCT
// -------------------------------------------- //
private static final AdapterSound i = new AdapterSound();
public static AdapterSound get() {
return i;
}
// -------------------------------------------- //
// OVERRIDE
// -------------------------------------------- //
@Override
public JsonElement serialize(Sound src, Type typeOfSrc, JsonSerializationContext context) {
if (src == null) {
return JsonNull.INSTANCE;
}
return new JsonPrimitive(src.name());
}
@Override
public Sound deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
if (json == null) {
return null;
}
if (json.equals(JsonNull.INSTANCE)) {
return null;
}
return Sound.valueOf(json.getAsString());
}
}

View File

@ -0,0 +1,59 @@
package com.massivecraft.massivecore.adapter;
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonDeserializer;
import com.google.gson.JsonElement;
import com.google.gson.JsonParseException;
import com.google.gson.JsonPrimitive;
import com.google.gson.JsonSerializationContext;
import com.google.gson.JsonSerializer;
import java.lang.reflect.Type;
import java.util.UUID;
public class AdapterUUID implements JsonDeserializer<UUID>, JsonSerializer<UUID> {
// -------------------------------------------- //
// INSTANCE & CONSTRUCT
// -------------------------------------------- //
private static final AdapterUUID i = new AdapterUUID();
public static AdapterUUID get() {
return i;
}
// -------------------------------------------- //
// OVERRIDE
// -------------------------------------------- //
@Override
public JsonElement serialize(UUID src, Type typeOfSrc, JsonSerializationContext context) {
return convertUUIDToJsonPrimitive(src);
}
@Override
public UUID deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
return convertJsonElementToUUID(json);
}
// -------------------------------------------- //
// STATIC LOGIC
// -------------------------------------------- //
public static String convertUUIDToString(UUID uuid) {
return uuid.toString();
}
public static JsonPrimitive convertUUIDToJsonPrimitive(UUID uuid) {
return new JsonPrimitive(convertUUIDToString(uuid));
}
public static UUID convertStringToUUID(String string) {
return UUID.fromString(string);
}
public static UUID convertJsonElementToUUID(JsonElement jsonElement) {
return convertStringToUUID(jsonElement.getAsString());
}
}

View File

@ -0,0 +1,7 @@
package com.massivecraft.massivecore.chestgui;
import org.bukkit.event.inventory.InventoryClickEvent;
public interface ChestAction {
boolean onClick(InventoryClickEvent event);
}

View File

@ -0,0 +1,27 @@
package com.massivecraft.massivecore.chestgui;
import com.massivecraft.massivecore.util.IdUtil;
import com.massivecraft.massivecore.util.MUtil;
import org.bukkit.entity.Player;
import org.bukkit.event.inventory.InventoryClickEvent;
public class ChestActionAbstract implements ChestAction {
// -------------------------------------------- //
// OVERRIDE
// -------------------------------------------- //
@Override
public boolean onClick(InventoryClickEvent event) {
Player player = IdUtil.getAsPlayer(event.getWhoClicked());
if (MUtil.isntPlayer(player)) {
return false;
}
return onClick(event, player);
}
public boolean onClick(InventoryClickEvent event, Player player) {
return false;
}
}

View File

@ -0,0 +1,60 @@
package com.massivecraft.massivecore.chestgui;
import com.massivecraft.massivecore.mixin.MixinCommand;
import org.bukkit.entity.Player;
import org.bukkit.event.inventory.InventoryClickEvent;
import java.security.InvalidParameterException;
public class ChestActionCommand extends ChestActionAbstract {
// -------------------------------------------- //
// FIELD
// -------------------------------------------- //
protected String command = null;
public void setCommand(String command) {
if (!command.startsWith("/")) {
throw new InvalidParameterException("Commands start with \"/\". Do include the leading slash.");
}
this.command = command;
}
public String getCommand() {
return this.command;
}
public String getCommandLine() {
if (this.command == null) {
return null;
}
return this.command.substring(1);
}
// -------------------------------------------- //
// CONSTRUCT
// -------------------------------------------- //
public ChestActionCommand() {
}
public ChestActionCommand(String command) {
this.setCommand(command);
}
// -------------------------------------------- //
// OVERRIDE
// -------------------------------------------- //
@Override
public boolean onClick(InventoryClickEvent event, Player player) {
String commandLine = this.getCommandLine();
if (commandLine == null) {
return false;
}
return MixinCommand.get().dispatchCommand(player, commandLine);
}
}

View File

@ -0,0 +1,10 @@
package com.massivecraft.massivecore.chestgui;
import org.bukkit.inventory.ItemStack;
// This class is just used to construct ChestGui's
public interface ChestButton {
ChestAction getAction();
ItemStack getItem();
}

View File

@ -0,0 +1,33 @@
package com.massivecraft.massivecore.chestgui;
import org.bukkit.inventory.ItemStack;
public class ChestButtonSimple implements ChestButton {
// -------------------------------------------- //
// FIELDS
// -------------------------------------------- //
private final ChestAction action;
@Override
public ChestAction getAction() {
return this.action;
}
private final ItemStack item;
@Override
public ItemStack getItem() {
return this.item;
}
// -------------------------------------------- //
// CONSTRUCT
// -------------------------------------------- //
public ChestButtonSimple(ChestAction action, ItemStack item) {
this.action = action;
this.item = item;
}
}

View File

@ -0,0 +1,286 @@
package com.massivecraft.massivecore.chestgui;
import com.massivecraft.massivecore.SoundEffect;
import com.massivecraft.massivecore.collections.MassiveList;
import com.massivecraft.massivecore.collections.MassiveMap;
import com.massivecraft.massivecore.entity.MassiveCoreMConf;
import org.bukkit.Bukkit;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.event.inventory.InventoryEvent;
import org.bukkit.inventory.Inventory;
import java.util.List;
import java.util.Map;
public class ChestGui {
// -------------------------------------------- //
// REGISTRY
// -------------------------------------------- //
protected static final Map<Inventory, ChestGui> inventoryToGui = new MassiveMap<>();
public static Map<Inventory, ChestGui> getInventoryToGui() {
return inventoryToGui;
}
public static ChestGui get(Inventory inventory) {
return inventoryToGui.get(inventory);
}
public static ChestGui getCreative(Inventory inventory) {
if (inventory == null) {
throw new NullPointerException("inventory");
}
ChestGui gui = get(inventory);
if (gui != null) {
return gui;
}
gui = new ChestGui();
gui.setInventory(inventory);
gui.add();
return gui;
}
public static ChestGui get(InventoryEvent event) {
if (event == null) {
throw new NullPointerException("event");
}
Inventory inventory = event.getInventory();
if (inventory == null) {
return null;
}
return get(inventory);
}
private static void add(Inventory inventory, ChestGui gui) {
inventoryToGui.put(inventory, gui);
}
private static void remove(Inventory inventory) {
inventoryToGui.remove(inventory);
}
// -------------------------------------------- //
// ADD & REMOVE
// -------------------------------------------- //
// Done through instance for override possibilities.
public void add() {
add(this.getInventory(), this);
}
public void remove() {
remove(this.getInventory());
}
// -------------------------------------------- //
// INVENTORY
// -------------------------------------------- //
// It is useful to provide a link back from the GUI to the inventory.
// This way we have can look up between Inventory and ChestGui both ways.
private Inventory inventory = null;
public Inventory getInventory() {
return this.inventory;
}
public void setInventory(Inventory inventory) {
this.inventory = inventory;
}
// -------------------------------------------- //
// ACTIONS
// -------------------------------------------- //
// Actions are assigned to indexes in the inventory.
// This means the system does not care about what item is in the slot.
// It just cares about which slot it is.
// One could have imagined an approach where we looked at the item instead.
// That is however not feasible since the Bukkit ItemStack equals method is not reliable.
private Map<Integer, ChestAction> indexToAction = new MassiveMap<>();
public Map<Integer, ChestAction> getIndexToAction() {
return this.indexToAction;
}
public ChestAction setAction(int index, ChestAction action) {
return this.indexToAction.put(index, action);
}
public ChestAction setAction(int index, String command) {
return this.setAction(index, new ChestActionCommand(command));
}
public ChestAction getAction(int index) {
return this.indexToAction.get(index);
}
public ChestAction getAction(InventoryClickEvent event) {
return this.getAction(event.getSlot());
}
// -------------------------------------------- //
// LAST ACTION
// -------------------------------------------- //
// The last executed action is stored here.
// This can for example be useful in the inventory close task.
private ChestAction lastAction = null;
public ChestAction getLastAction() {
return this.lastAction;
}
public void setLastAction(ChestAction lastAction) {
this.lastAction = lastAction;
}
// -------------------------------------------- //
// META DATA
// -------------------------------------------- //
// Store your arbitrary stuff here. Might come in handy in the future.
// I don't think we are currently using this ourselves.
private final Map<String, Object> meta = new MassiveMap<>();
public Map<String, Object> getMeta() {
return this.meta;
}
// -------------------------------------------- //
// RUNNABLES
// -------------------------------------------- //
// Runnables to be executed after certain events.
// They are all delayed with one (or is it zero) ticks.
// This way we don't bug out if you open a new GUI after close.
private final List<Runnable> runnablesOpen = new MassiveList<>();
public List<Runnable> getRunnablesOpen() {
return this.runnablesOpen;
}
private final List<Runnable> runnablesClose = new MassiveList<>();
public List<Runnable> getRunnablesClose() {
return this.runnablesClose;
}
// -------------------------------------------- //
// SOUNDS
// -------------------------------------------- //
// This section contains all kinds of sounds.
// You can disable a sound by setting it to null.
// The sound you should hear when clicking an action slot.
private SoundEffect soundClick = MassiveCoreMConf.get().clickSound;
public SoundEffect getSoundClick() {
return this.soundClick;
}
public void setSoundClick(SoundEffect soundClick) {
this.soundClick = soundClick;
}
// The sound you should hear when opening the GUI.
private SoundEffect soundOpen = SoundEffect.valueOf("CHEST_OPEN", 0.75f, 1.0f);
public SoundEffect getSoundOpen() {
return this.soundOpen;
}
public void setSoundOpen(SoundEffect soundOpen) {
this.soundOpen = soundOpen;
}
// The sound you should hear when closing the GUI.
// This sound will be skipped if another inventory was opened by the GUI action.
private SoundEffect soundClose = SoundEffect.valueOf("CHEST_CLOSE", 0.75f, 1.0f);
public SoundEffect getSoundClose() {
return this.soundClose;
}
public void setSoundClose(SoundEffect soundClose) {
this.soundClose = soundClose;
}
// -------------------------------------------- //
// AUTOCLOSING
// -------------------------------------------- //
// Should the GUI be automatically closed upon clicking an action?
private boolean autoclosing = true;
public boolean isAutoclosing() {
return this.autoclosing;
}
public void setAutoclosing(boolean autoclosing) {
this.autoclosing = autoclosing;
}
// -------------------------------------------- //
// AUTOREMOVING
// -------------------------------------------- //
// Should the GUI be automatically removed upon the inventory closing?
private boolean autoremoving = true;
public boolean isAutoremoving() {
return this.autoremoving;
}
public void setAutoremoving(boolean autoremoving) {
this.autoremoving = autoremoving;
}
// -------------------------------------------- //
// ALLOWBOTTOMINVENTORY
// -------------------------------------------- //
private boolean allowBottomInventory = false;
public boolean isBottomInventoryAllowed() {
return this.allowBottomInventory;
}
public void setBottomInventoryAllow(boolean allowBottomInventory) {
this.allowBottomInventory = allowBottomInventory;
}
// -------------------------------------------- //
// CONSTRUCT
// -------------------------------------------- //
public ChestGui() {
}
public static ChestGui constructFromButtons(List<? extends ChestButton> buttons, String title) {
int size = buttons.size();
int modulo = size % 9;
if (modulo != 0) {
size = size + 9 - modulo;
}
Inventory inventory = Bukkit.createInventory(null, size, title);
ChestGui gui = getCreative(inventory);
for (int i = 0; i < buttons.size(); i++) {
ChestButton button = buttons.get(i);
inventory.setItem(i, button.getItem());
gui.setAction(i, button.getAction());
}
return gui;
}
}

View File

@ -0,0 +1,48 @@
package com.massivecraft.massivecore.cmd;
import com.massivecraft.massivecore.MassiveCore;
import com.massivecraft.massivecore.MassiveCorePerm;
import com.massivecraft.massivecore.command.MassiveCommandVersion;
import com.massivecraft.massivecore.command.editor.CommandEditAbstract;
import com.massivecraft.massivecore.command.editor.CommandEditSingleton;
import com.massivecraft.massivecore.command.requirement.RequirementHasPerm;
import com.massivecraft.massivecore.entity.MassiveCoreMConf;
import java.util.List;
public class CmdMassiveCore extends MassiveCoreCommand {
// -------------------------------------------- //
// INSTANCE
// -------------------------------------------- //
private static CmdMassiveCore i = new CmdMassiveCore();
public static CmdMassiveCore get() {
return i;
}
// -------------------------------------------- //
// FIELDS
// -------------------------------------------- //
public CmdMassiveCoreUsys cmdMassiveCoreUsys = new CmdMassiveCoreUsys();
public CmdMassiveCoreStore cmdMassiveCoreMStore = new CmdMassiveCoreStore();
public CmdMassiveCoreId cmdMassiveCoreId = new CmdMassiveCoreId();
public CmdMassiveCoreTest cmdMassiveCoreTest = new CmdMassiveCoreTest();
public CmdMassiveCoreHearsound cmdMassiveCoreHearsound = new CmdMassiveCoreHearsound();
public CmdMassiveCoreBuffer cmdMassiveCoreBuffer = new CmdMassiveCoreBuffer();
public CmdMassiveCoreCmdurl cmdMassiveCoreCmdurl = new CmdMassiveCoreCmdurl();
public CommandEditAbstract<MassiveCoreMConf, MassiveCoreMConf> cmdMassiveCoreConfig = new CommandEditSingleton<>(MassiveCoreMConf.get()).addRequirements(RequirementHasPerm.get(MassiveCorePerm.CONFIG));
public CmdMassiveCoreClick cmdMassiveCoreClick = new CmdMassiveCoreClick();
public MassiveCommandVersion cmdMassiveCoreVersion = new MassiveCommandVersion(MassiveCore.get()).addRequirements(RequirementHasPerm.get(MassiveCorePerm.VERSION));
// -------------------------------------------- //
// OVERRIDE
// -------------------------------------------- //
@Override
public List<String> getAliases() {
return MassiveCoreMConf.get().aliasesMcore;
}
}

View File

@ -0,0 +1,32 @@
package com.massivecraft.massivecore.cmd;
import com.massivecraft.massivecore.entity.MassiveCoreMConf;
import java.util.List;
public class CmdMassiveCoreBuffer extends MassiveCoreCommand {
// -------------------------------------------- //
// INSTANCE
// -------------------------------------------- //
private static CmdMassiveCoreBuffer i = new CmdMassiveCoreBuffer() {
public List<String> getAliases() {
return MassiveCoreMConf.get().aliasesBuffer;
}
};
public static CmdMassiveCoreBuffer get() {
return i;
}
// -------------------------------------------- //
// FIELDS
// -------------------------------------------- //
public CmdMassiveCoreBufferPrint cmdMassiveCoreBufferPrint = new CmdMassiveCoreBufferPrint();
public CmdMassiveCoreBufferClear cmdMassiveCoreBufferClear = new CmdMassiveCoreBufferClear();
public CmdMassiveCoreBufferSet cmdMassiveCoreBufferSet = new CmdMassiveCoreBufferSet();
public CmdMassiveCoreBufferAdd cmdMassiveCoreBufferAdd = new CmdMassiveCoreBufferAdd();
public CmdMassiveCoreBufferWhitespace cmdMassiveCoreBufferWhitespace = new CmdMassiveCoreBufferWhitespace();
}

View File

@ -0,0 +1,32 @@
package com.massivecraft.massivecore.cmd;
import com.massivecraft.massivecore.MassiveException;
import com.massivecraft.massivecore.command.type.primitive.TypeString;
import com.massivecraft.massivecore.engine.EngineMassiveCoreVariable;
public class CmdMassiveCoreBufferAdd extends MassiveCoreCommand {
// -------------------------------------------- //
// CONSTRUCT
// -------------------------------------------- //
public CmdMassiveCoreBufferAdd() {
// Parameters
this.addParameter(TypeString.get(), "text", true).setDesc("the text to add to your buffer");
}
// -------------------------------------------- //
// OVERRIDE
// -------------------------------------------- //
@Override
public void perform() throws MassiveException {
String string = this.readArg();
String buffer = EngineMassiveCoreVariable.getBuffer(sender);
buffer += string;
EngineMassiveCoreVariable.setBuffer(sender, buffer);
msg("<i>Buffer Add");
}
}

View File

@ -0,0 +1,17 @@
package com.massivecraft.massivecore.cmd;
import com.massivecraft.massivecore.engine.EngineMassiveCoreVariable;
public class CmdMassiveCoreBufferClear extends MassiveCoreCommand {
// -------------------------------------------- //
// OVERRIDE
// -------------------------------------------- //
@Override
public void perform() {
EngineMassiveCoreVariable.setBuffer(sender, "");
msg("<i>Buffer Clear");
}
}

View File

@ -0,0 +1,22 @@
package com.massivecraft.massivecore.cmd;
import com.massivecraft.massivecore.engine.EngineMassiveCoreVariable;
public class CmdMassiveCoreBufferPrint extends MassiveCoreCommand {
// -------------------------------------------- //
// OVERRIDE
// -------------------------------------------- //
@Override
public void perform() {
String buffer = EngineMassiveCoreVariable.getBuffer(sender);
if (buffer == null || buffer.length() == 0) {
msg("<i>Nothing to print. Your buffer is empty.");
return;
}
msg("<i>Printing your buffer on the line below:");
message(buffer);
}
}

View File

@ -0,0 +1,30 @@
package com.massivecraft.massivecore.cmd;
import com.massivecraft.massivecore.MassiveException;
import com.massivecraft.massivecore.command.type.primitive.TypeString;
import com.massivecraft.massivecore.engine.EngineMassiveCoreVariable;
public class CmdMassiveCoreBufferSet extends MassiveCoreCommand {
// -------------------------------------------- //
// CONSTRUCT
// -------------------------------------------- //
public CmdMassiveCoreBufferSet() {
// Parameters
this.addParameter(TypeString.get(), "text", true).setDesc("the text to set your buffer to");
}
// -------------------------------------------- //
// OVERRIDE
// -------------------------------------------- //
@Override
public void perform() throws MassiveException {
String string = this.readArg();
EngineMassiveCoreVariable.setBuffer(sender, string);
msg("<i>Buffer was Set");
}
}

View File

@ -0,0 +1,35 @@
package com.massivecraft.massivecore.cmd;
import com.massivecraft.massivecore.MassiveException;
import com.massivecraft.massivecore.command.type.primitive.TypeInteger;
import com.massivecraft.massivecore.engine.EngineMassiveCoreVariable;
import com.massivecraft.massivecore.util.Txt;
public class CmdMassiveCoreBufferWhitespace extends MassiveCoreCommand {
// -------------------------------------------- //
// CONSTRUCT
// -------------------------------------------- //
public CmdMassiveCoreBufferWhitespace() {
// Parameters
this.addParameter(1, TypeInteger.get(), "times").setDesc("the amount of whitespace to add to your buffer");
}
// -------------------------------------------- //
// OVERRIDE
// -------------------------------------------- //
@Override
public void perform() throws MassiveException {
int times = this.readArg();
String string = Txt.repeat(" ", times);
String buffer = EngineMassiveCoreVariable.getBuffer(sender);
buffer += string;
EngineMassiveCoreVariable.setBuffer(sender, buffer);
msg("<i>Buffer Whitespace");
}
}

View File

@ -0,0 +1,42 @@
package com.massivecraft.massivecore.cmd;
import com.massivecraft.massivecore.MassiveException;
import com.massivecraft.massivecore.command.type.TypeStringCommand;
import com.massivecraft.massivecore.entity.MassiveCoreMConf;
import com.massivecraft.massivecore.mixin.MixinCommand;
public class CmdMassiveCoreClick extends MassiveCoreCommand {
// -------------------------------------------- //
// INSTANCE
// -------------------------------------------- //
private static CmdMassiveCoreClick i = new CmdMassiveCoreClick();
public static CmdMassiveCoreClick get() {
return i;
}
// -------------------------------------------- //
// CONSTRUCT
// -------------------------------------------- //
public CmdMassiveCoreClick() {
// Parameters
this.addParameter(null, TypeStringCommand.get(), "command", "none", true).setDesc("the command to perform");
}
// -------------------------------------------- //
// OVERRIDE
// -------------------------------------------- //
@Override
public void perform() throws MassiveException {
MassiveCoreMConf.get().clickSound.run(me);
String command = this.readArg();
if (command == null) {
return;
}
MixinCommand.get().dispatchCommand(sender, command);
}
}

View File

@ -0,0 +1,103 @@
package com.massivecraft.massivecore.cmd;
import com.massivecraft.massivecore.MassiveCore;
import com.massivecraft.massivecore.MassiveException;
import com.massivecraft.massivecore.command.requirement.RequirementIsPlayer;
import com.massivecraft.massivecore.command.type.primitive.TypeString;
import com.massivecraft.massivecore.entity.MassiveCoreMConf;
import com.massivecraft.massivecore.mixin.MixinMessage;
import com.massivecraft.massivecore.util.WebUtil;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.List;
public class CmdMassiveCoreCmdurl extends MassiveCoreCommand {
// -------------------------------------------- //
// INSTANCE
// -------------------------------------------- //
private static CmdMassiveCoreCmdurl i = new CmdMassiveCoreCmdurl() {
public List<String> getAliases() {
return MassiveCoreMConf.get().aliasesCmdurl;
}
};
public static CmdMassiveCoreCmdurl get() {
return i;
}
// -------------------------------------------- //
// CONSTRUCT
// -------------------------------------------- //
public CmdMassiveCoreCmdurl() {
// Parameters
this.addParameter(TypeString.get(), "url").setDesc("the url to load");
// Requirements
this.addRequirements(RequirementIsPlayer.get());
}
// -------------------------------------------- //
// OVERRIDE
// -------------------------------------------- //
@Override
public void perform() throws MassiveException {
// Args
String urlString = this.readArg();
final URL url;
try {
url = new URL(urlString);
} catch (MalformedURLException e) {
msg("<b>Malformed URL: %s", e.getMessage());
return;
}
// Apply
final Player commander = me;
msg("<i>Loading <aqua>%s <i>...", urlString);
async(() -> {
try {
final List<String> lines = WebUtil.getLines(url);
sync(() -> {
MixinMessage.get().msgOne(commander, "<i>... <h>%d <i>lines loaded. Now executing ...", lines.size());
for (int i = 0; i <= lines.size() - 1; i++) {
String line = lines.get(i);
line = line.trim();
if (line.length() == 0 || line.startsWith("#")) {
MixinMessage.get().msgOne(commander, "<b>#%d: <i>%s", i, line);
// Ignore the line
} else {
MixinMessage.get().msgOne(commander, "<g>#%d: <i>%s", i, line);
// Run the line
commander.chat(line);
}
}
});
return;
} catch (final Exception e) {
sync(() -> MixinMessage.get().msgOne(commander, "<b>%s: %s", e.getClass().getSimpleName(), e.getMessage()));
return;
}
});
}
// -------------------------------------------- //
// ASYNC/SYNC SHORTHANDS
// -------------------------------------------- //
public static void sync(Runnable runnable) {
Bukkit.getScheduler().runTask(MassiveCore.get(), runnable);
}
public static void async(Runnable runnable) {
Bukkit.getScheduler().runTaskAsynchronously(MassiveCore.get(), runnable);
}
}

View File

@ -0,0 +1,40 @@
package com.massivecraft.massivecore.cmd;
import com.massivecraft.massivecore.MassiveException;
import com.massivecraft.massivecore.SoundEffect;
import com.massivecraft.massivecore.command.requirement.RequirementIsPlayer;
import com.massivecraft.massivecore.command.type.combined.TypeSoundEffect;
import com.massivecraft.massivecore.command.type.container.TypeList;
import java.util.List;
public class CmdMassiveCoreHearsound extends MassiveCoreCommand {
// -------------------------------------------- //
// CONSTRUCT
// -------------------------------------------- //
public CmdMassiveCoreHearsound() {
// Aliases
this.addAliases("hearsounds");
// Parameters
this.addParameter(TypeList.get(TypeSoundEffect.get()), "sound(s)", true).setDesc("the sounds to hear");
// Requirements
this.addRequirements(RequirementIsPlayer.get());
}
// -------------------------------------------- //
// OVERRIDE
// -------------------------------------------- //
@Override
public void perform() throws MassiveException {
// Args
List<SoundEffect> soundEffects = this.readArg();
// Apply
SoundEffect.runAll(soundEffects, me);
}
}

View File

@ -0,0 +1,15 @@
package com.massivecraft.massivecore.cmd;
import com.massivecraft.massivecore.ConfServer;
public class CmdMassiveCoreId extends MassiveCoreCommand {
// -------------------------------------------- //
// OVERRIDE
// -------------------------------------------- //
@Override
public void perform() {
this.msg("<i>The id of this server is \"<h>%s<i>\".", ConfServer.serverid);
}
}

View File

@ -0,0 +1,31 @@
package com.massivecraft.massivecore.cmd;
import com.massivecraft.massivecore.entity.MassiveCoreMConf;
import java.util.List;
public class CmdMassiveCoreStore extends MassiveCoreCommand {
// -------------------------------------------- //
// INSTANCE
// -------------------------------------------- //
private static CmdMassiveCoreStore i = new CmdMassiveCoreStore() {
public List<String> getAliases() {
return MassiveCoreMConf.get().aliasesMstore;
}
};
public static CmdMassiveCoreStore get() {
return i;
}
// -------------------------------------------- //
// FIELDS
// -------------------------------------------- //
public CmdMassiveCoreStoreStats cmdMassiveCoreStoreStats = new CmdMassiveCoreStoreStats();
public CmdMassiveCoreStoreListcolls cmdMassiveCoreStoreListcolls = new CmdMassiveCoreStoreListcolls();
public CmdMassiveCoreStoreCopydb cmdMassiveCoreStoreCopydb = new CmdMassiveCoreStoreCopydb();
public CmdMassiveCoreStoreClean cmdMassiveCoreStoreClean = new CmdMassiveCoreStoreClean();
}

View File

@ -0,0 +1,40 @@
package com.massivecraft.massivecore.cmd;
import com.massivecraft.massivecore.MassiveException;
import com.massivecraft.massivecore.command.type.container.TypeSet;
import com.massivecraft.massivecore.command.type.store.TypeColl;
import com.massivecraft.massivecore.store.Coll;
import com.massivecraft.massivecore.store.cleanable.Cleanable;
import com.massivecraft.massivecore.store.cleanable.CleaningUtil;
import com.massivecraft.massivecore.util.IdUtil;
import com.massivecraft.massivecore.util.MUtil;
import org.bukkit.command.CommandSender;
import java.util.Set;
public class CmdMassiveCoreStoreClean extends MassiveCoreCommand {
// -------------------------------------------- //
// CONSTRUCT
// -------------------------------------------- //
public CmdMassiveCoreStoreClean() {
// Parameters
this.addParameter(TypeSet.get(TypeColl.get()), "coll", true).setDesc("the coll to clean");
}
// -------------------------------------------- //
// OVERRIDE
// -------------------------------------------- //
@Override
public void perform() throws MassiveException {
Set<Coll<? extends Cleanable>> colls = this.readArg();
Set<CommandSender> receivers = MUtil.set(sender, IdUtil.getConsole());
for (Coll<? extends Cleanable> coll : colls) {
CleaningUtil.considerClean(coll, receivers);
}
}
}

View File

@ -0,0 +1,83 @@
package com.massivecraft.massivecore.cmd;
import com.google.gson.JsonObject;
import com.massivecraft.massivecore.MassiveCore;
import com.massivecraft.massivecore.MassiveException;
import com.massivecraft.massivecore.command.type.primitive.TypeString;
import com.massivecraft.massivecore.store.Coll;
import com.massivecraft.massivecore.store.Db;
import com.massivecraft.massivecore.store.Entity;
import com.massivecraft.massivecore.store.MStore;
import java.util.Collection;
import java.util.Map.Entry;
import java.util.Set;
public class CmdMassiveCoreStoreCopydb extends MassiveCoreCommand {
// -------------------------------------------- //
// CONSTRUCT
// -------------------------------------------- //
public CmdMassiveCoreStoreCopydb() {
// Parameters
this.addParameter(TypeString.get(), "from").setDesc("the database to copy from");
this.addParameter(TypeString.get(), "to").setDesc("the database to copy to");
}
// -------------------------------------------- //
// OVERRIDE
// -------------------------------------------- //
@SuppressWarnings({"rawtypes", "unchecked"})
@Override
public void perform() throws MassiveException {
// Args
final String fromAlias = this.readArg();
final Db fromDb = MStore.getDb(fromAlias);
if (fromDb == null) {
msg("<b>could not get the from-database.");
return;
}
final String toAlias = this.readArg();
final Db toDb = MStore.getDb(toAlias);
if (toDb == null) {
msg("<b>could not get the to-database.");
return;
}
// Prepare
Set<String> collnames = fromDb.getCollnames();
// Statistics
int countCollCurrent = 0;
int countCollTotal = collnames.size();
// Do it!
long before = System.currentTimeMillis();
msg("<i>Now copying database with <h>%d <i>collections.", countCollTotal);
for (String collname : fromDb.getCollnames()) {
countCollCurrent++;
final Coll fromColl = new Coll(collname, Entity.class, fromDb, MassiveCore.get());
final Coll toColl = new Coll(collname, Entity.class, toDb, MassiveCore.get());
Collection<String> ids = fromDb.getIds(fromColl);
msg("<i>Now copying collection <h>%d/%d %s <i>with <h>%d <i>documents.", countCollCurrent, countCollTotal, collname, ids.size());
// Do a load check to verify we have access to this folder.
if (ids.size() > 0 && fromDb.load(fromColl, ids.iterator().next()) == null) {
msg("<b>Skipping <h>%s <b>since could not load data.", collname);
continue;
}
for (String id : ids) {
Entry<JsonObject, Long> data = fromDb.load(fromColl, id);
toDb.save(toColl, id, data.getKey());
}
}
long after = System.currentTimeMillis();
long duration = after - before;
msg("<g>The copy is now complete. <i>It took <h>%dms<i>.", duration);
}
}

View File

@ -0,0 +1,71 @@
package com.massivecraft.massivecore.cmd;
import com.massivecraft.massivecore.ConfServer;
import com.massivecraft.massivecore.MassiveException;
import com.massivecraft.massivecore.command.type.primitive.TypeString;
import com.massivecraft.massivecore.comparator.ComparatorNaturalOrder;
import com.massivecraft.massivecore.store.Coll;
import com.massivecraft.massivecore.store.Db;
import com.massivecraft.massivecore.store.MStore;
import com.massivecraft.massivecore.util.Txt;
import java.util.Set;
import java.util.TreeSet;
public class CmdMassiveCoreStoreListcolls extends MassiveCoreCommand {
// -------------------------------------------- //
// CONSTRUCT
// -------------------------------------------- //
public CmdMassiveCoreStoreListcolls() {
// Parameters
this.addParameter(TypeString.get(), "db", ConfServer.dburi).setDesc("the database to list colls from");
}
// -------------------------------------------- //
// OVERRIDE
// -------------------------------------------- //
@Override
public void perform() throws MassiveException {
// Args
final String dbAlias = this.readArg(ConfServer.dburi);
final Db db = MStore.getDb(dbAlias);
if (db == null) {
msg("<b>could not get the database.");
return;
}
// Prepare
Set<String> collnames = new TreeSet<>(ComparatorNaturalOrder.get());
collnames.addAll(db.getCollnames());
// Do it!
message(Txt.titleize("Collections in " + db.getDbName()));
for (String collname : collnames) {
String message = Txt.parse("<h>") + collname;
Coll<?> coll = null;
for (Coll<?> collCandidate : Coll.getInstances()) {
if (!collCandidate.getName().equals(collname)) {
continue;
}
if (collCandidate.getDb() != db) {
continue;
}
coll = collCandidate;
break;
}
if (coll == null) {
message += Txt.parse(" <b>UNUSED");
} else {
message += Txt.parse(" <i>(%d documents)", coll.getIds().size());
}
message(message);
}
}
}

View File

@ -0,0 +1,80 @@
package com.massivecraft.massivecore.cmd;
import com.massivecraft.massivecore.MassiveException;
import com.massivecraft.massivecore.command.type.store.TypeColl;
import com.massivecraft.massivecore.store.Coll;
import com.massivecraft.massivecore.util.MUtil;
import com.massivecraft.massivecore.util.Txt;
import java.util.Map.Entry;
public class CmdMassiveCoreStoreStats extends MassiveCoreCommand {
// -------------------------------------------- //
// CONSTRUCT
// -------------------------------------------- //
public CmdMassiveCoreStoreStats() {
// Parameters
this.addParameter(TypeColl.get(), "coll", Coll.TOTAL).setDesc("the coll to show info about");
}
// -------------------------------------------- //
// OVERRIDE
// -------------------------------------------- //
@Override
public void perform() throws MassiveException {
if (!this.argIsSet(0) || this.argAt(0).equalsIgnoreCase(Coll.TOTAL)) {
this.performTotal();
} else {
Coll<?> coll = this.readArgAt(0);
this.performColl(coll);
}
}
public void performTotal() {
message(Txt.titleize("MStore Total Statistics"));
//msg("<k>Last Examine Duration: <v>%d<i>ms", ExamineThread.get().getLastDurationMillis());
msg("<a>== <k>Coll <a>| <k>Sync Count In <a>| <k>Sync Count Out <a>==");
for (Entry<String, Coll<?>> entry : Coll.getMap().entrySet()) {
String name = entry.getKey();
Coll<?> coll = entry.getValue();
long in = coll.getSyncCountFixed(Coll.TOTAL, true);
long out = coll.getSyncCountFixed(Coll.TOTAL, false);
msg("<v>%s <a>| <v>%d <a>| <v>%d", name, in, out);
}
}
public void performColl(Coll<?> coll) {
message(Txt.titleize("MStore " + coll.getName() + " Statistics"));
msg("<k>Basename: <v>%s", coll.getBasename());
msg("<k>Universe: <v>%s", coll.getUniverse());
msg("<k>Entity Count: <v>%d", coll.getIds().size());
msg("<k>Entity Class: <v>%s", coll.getEntityClass().getName());
msg("<k>Plugin: <v>%s", coll.getPlugin().getDescription().getFullName());
msg("<k>Database: <v>%s", coll.getDb().getDbName());
msg("<k>Driver: <v>%s", coll.getDb().getDriverName());
int limit;
msg("<a>== Sync Count In <a>==");
limit = 30;
for (Entry<String, Long> entry : MUtil.entriesSortedByValues(coll.getSyncMap(true), false)) {
if (limit-- == 0) {
break;
}
msg("<k>%s <v>%d", entry.getKey(), entry.getValue());
}
msg("<a>== Sync Count Out <a>==");
limit = 30;
for (Entry<String, Long> entry : MUtil.entriesSortedByValues(coll.getSyncMap(false), false)) {
if (limit-- == 0) {
break;
}
msg("<k>%s <v>%d", entry.getKey(), entry.getValue());
}
}
}

View File

@ -0,0 +1,86 @@
package com.massivecraft.massivecore.cmd;
import com.massivecraft.massivecore.MassiveException;
import com.massivecraft.massivecore.collections.MassiveList;
import com.massivecraft.massivecore.command.Visibility;
import com.massivecraft.massivecore.command.requirement.RequirementIsPlayer;
import com.massivecraft.massivecore.command.type.TypeItemStack;
import com.massivecraft.massivecore.command.type.primitive.TypeBooleanYes;
import com.massivecraft.massivecore.mson.Mson;
import com.massivecraft.massivecore.util.InventoryUtil;
import org.bukkit.ChatColor;
import org.bukkit.Material;
import org.bukkit.inventory.ItemStack;
import java.util.List;
public class CmdMassiveCoreTest extends MassiveCoreCommand {
// -------------------------------------------- //
// CONSTRUCT
// -------------------------------------------- //
public CmdMassiveCoreTest() {
// Parameters
this.addParameter(false, TypeBooleanYes.get(), "set", "no");
// Requirements
this.addRequirements(RequirementIsPlayer.get());
// VisibilityMode
this.setVisibility(Visibility.SECRET);
}
// -------------------------------------------- //
// OVERRIDE
// -------------------------------------------- //
@Override
public void perform() throws MassiveException {
// Args
boolean set = this.readArg();
if (set) {
InventoryUtil.setHelmet(me, new ItemStack(Material.DIAMOND_HELMET));
InventoryUtil.setChestplate(me, new ItemStack(Material.DIAMOND_CHESTPLATE));
InventoryUtil.setLeggings(me, new ItemStack(Material.DIAMOND_LEGGINGS));
InventoryUtil.setBoots(me, new ItemStack(Material.DIAMOND_BOOTS));
InventoryUtil.setWeapon(me, new ItemStack(Material.DIAMOND_SWORD));
InventoryUtil.setShield(me, new ItemStack(Material.DIRT));
}
inform("helmet", InventoryUtil.getHelmet(me));
inform("chestplate", InventoryUtil.getChestplate(me));
inform("leggings", InventoryUtil.getLeggings(me));
inform("boots", InventoryUtil.getBoots(me));
inform("weapon", InventoryUtil.getWeapon(me));
inform("shield", InventoryUtil.getShield(me));
inform("all", InventoryUtil.getContentsAll(me.getInventory()));
inform("storage", InventoryUtil.getContentsStorage(me.getInventory()));
inform("armor", InventoryUtil.getContentsArmor(me.getInventory()));
inform("extra", InventoryUtil.getContentsExtra(me.getInventory()));
}
// -------------------------------------------- //
// UTIL
// -------------------------------------------- //
public Mson visualize(ItemStack item) {
return TypeItemStack.get().getVisualMson(item, sender);
}
public Mson visualize(ItemStack... items) {
List<Mson> msons = new MassiveList<>(Mson.mson(String.valueOf(items.length)).color(ChatColor.AQUA));
for (ItemStack item : items) {
msons.add(visualize(item));
}
return Mson.implode(msons, Mson.SPACE);
}
public void inform(String key, ItemStack... items) {
message(mson(key, ": ", visualize(items)));
}
}

View File

@ -0,0 +1,30 @@
package com.massivecraft.massivecore.cmd;
import com.massivecraft.massivecore.entity.MassiveCoreMConf;
import java.util.List;
public class CmdMassiveCoreUsys extends MassiveCoreCommand {
// -------------------------------------------- //
// INSTANCE
// -------------------------------------------- //
private static CmdMassiveCoreUsys i = new CmdMassiveCoreUsys() {
public List<String> getAliases() {
return MassiveCoreMConf.get().aliasesUsys;
}
};
public static CmdMassiveCoreUsys get() {
return i;
}
// -------------------------------------------- //
// FIELDS
// -------------------------------------------- //
public CmdMassiveCoreUsysMultiverse cmdMassiveCoreUsysMultiverse = new CmdMassiveCoreUsysMultiverse();
public CmdMassiveCoreUsysUniverse cmdMassiveCoreUsysUniverse = new CmdMassiveCoreUsysUniverse();
public CmdMassiveCoreUsysWorld cmdMassiveCoreUsysWorld = new CmdMassiveCoreUsysWorld();
}

View File

@ -0,0 +1,13 @@
package com.massivecraft.massivecore.cmd;
public class CmdMassiveCoreUsysMultiverse extends MassiveCoreCommand {
// -------------------------------------------- //
// FIELDS
// -------------------------------------------- //
public CmdMassiveCoreUsysMultiverseList cmdMassiveCoreUsysMultiverseList = new CmdMassiveCoreUsysMultiverseList();
public CmdMassiveCoreUsysMultiverseShow cmdMassiveCoreUsysMultiverseShow = new CmdMassiveCoreUsysMultiverseShow();
public CmdMassiveCoreUsysMultiverseNew cmdMassiveCoreUsysMultiverseNew = new CmdMassiveCoreUsysMultiverseNew();
public CmdMassiveCoreUsysMultiverseDel cmdMassiveCoreUsysMultiverseDel = new CmdMassiveCoreUsysMultiverseDel();
}

View File

@ -0,0 +1,38 @@
package com.massivecraft.massivecore.cmd;
import com.massivecraft.massivecore.MassiveCore;
import com.massivecraft.massivecore.MassiveException;
import com.massivecraft.massivecore.command.type.store.TypeMultiverse;
import com.massivecraft.massivecore.entity.Multiverse;
public class CmdMassiveCoreUsysMultiverseDel extends MassiveCoreCommand {
// -------------------------------------------- //
// CONSTRUCT
// -------------------------------------------- //
public CmdMassiveCoreUsysMultiverseDel() {
// Parameters
this.addParameter(TypeMultiverse.get(), "multiverse").setDesc("the multiverse to delete");
}
// -------------------------------------------- //
// OVERRIDE
// -------------------------------------------- //
@Override
public void perform() throws MassiveException {
Multiverse multiverse = this.readArg();
String id = multiverse.getId();
if (id.equals(MassiveCore.DEFAULT)) {
msg("<b>You can't delete the default multiverse.");
return;
}
multiverse.detach();
msg("<g>Deleted multiverse <h>%s<g>.", id);
}
}

View File

@ -0,0 +1,37 @@
package com.massivecraft.massivecore.cmd;
import com.massivecraft.massivecore.MassiveException;
import com.massivecraft.massivecore.command.Parameter;
import com.massivecraft.massivecore.entity.Multiverse;
import com.massivecraft.massivecore.entity.MultiverseColl;
import com.massivecraft.massivecore.pager.Pager;
import com.massivecraft.massivecore.pager.Stringifier;
import com.massivecraft.massivecore.util.Txt;
public class CmdMassiveCoreUsysMultiverseList extends MassiveCoreCommand {
// -------------------------------------------- //
// CONSTRUCT
// -------------------------------------------- //
public CmdMassiveCoreUsysMultiverseList() {
// Parameters
this.addParameter(Parameter.getPage());
}
// -------------------------------------------- //
// OVERRIDE
// -------------------------------------------- //
@Override
public void perform() throws MassiveException {
// Args
int page = this.readArg();
// Pager Create
Pager<Multiverse> pager = new Pager<>(this, "Multiverse List", page, MultiverseColl.get().getAll(), (Stringifier<Multiverse>) (multiverse, index) -> Txt.parse("<h>" + multiverse.getId() + " <i>has " + Txt.implodeCommaAndDot(multiverse.getUniverses(), "<aqua>%s", "<i>, ", " <i>and ", "<i>.")));
// Pager Message
pager.message();
}
}

View File

@ -0,0 +1,35 @@
package com.massivecraft.massivecore.cmd;
import com.massivecraft.massivecore.MassiveException;
import com.massivecraft.massivecore.command.type.primitive.TypeString;
import com.massivecraft.massivecore.entity.MultiverseColl;
public class CmdMassiveCoreUsysMultiverseNew extends MassiveCoreCommand {
// -------------------------------------------- //
// CONSTRUCT
// -------------------------------------------- //
public CmdMassiveCoreUsysMultiverseNew() {
// Parameters
this.addParameter(TypeString.get(), "multiverse").setDesc("name of multiverse to create");
}
// -------------------------------------------- //
// OVERRIDE
// -------------------------------------------- //
@Override
public void perform() throws MassiveException {
String id = this.readArg();
if (MultiverseColl.get().containsId(id)) {
msg("<b>The multiverse <h>%s<b> already exists.", id);
return;
}
MultiverseColl.get().create(id);
msg("<g>Created multiverse <h>%s<g>.", id);
}
}

View File

@ -0,0 +1,40 @@
package com.massivecraft.massivecore.cmd;
import com.massivecraft.massivecore.MassiveCore;
import com.massivecraft.massivecore.MassiveException;
import com.massivecraft.massivecore.command.type.store.TypeMultiverse;
import com.massivecraft.massivecore.entity.Multiverse;
import com.massivecraft.massivecore.util.Txt;
public class CmdMassiveCoreUsysMultiverseShow extends MassiveCoreCommand {
// -------------------------------------------- //
// CONSTRUCT
// -------------------------------------------- //
public CmdMassiveCoreUsysMultiverseShow() {
// Parameters
this.addParameter(TypeMultiverse.get(), "multiverse").setDesc("the multiverse to show info about");
}
// -------------------------------------------- //
// OVERRIDE
// -------------------------------------------- //
@Override
public void perform() throws MassiveException {
Multiverse multiverse = this.readArg();
message(Txt.titleize("Multiverse: " + multiverse.getId()));
for (String universe : multiverse.getUniverses()) {
if (universe.equals(MassiveCore.DEFAULT)) {
continue;
}
msg("<aqua>" + universe + "<i>: " + Txt.implodeCommaAndDot(multiverse.getWorlds(universe), "<h>%s", "<i>, ", " <i>and ", "<i>."));
}
msg("<aqua>default<i>: for all other worlds.");
}
}

View File

@ -0,0 +1,12 @@
package com.massivecraft.massivecore.cmd;
public class CmdMassiveCoreUsysUniverse extends MassiveCoreCommand {
// -------------------------------------------- //
// FIELDS
// -------------------------------------------- //
public CmdMassiveCoreUsysUniverseNew cmdMassiveCoreUsysUniverseNew = new CmdMassiveCoreUsysUniverseNew();
public CmdMassiveCoreUsysUniverseDel cmdMassiveCoreUsysUniverseDel = new CmdMassiveCoreUsysUniverseDel();
public CmdMassiveCoreUsysUniverseClear cmdMassiveCoreUsysUniverseClear = new CmdMassiveCoreUsysUniverseClear();
}

View File

@ -0,0 +1,42 @@
package com.massivecraft.massivecore.cmd;
import com.massivecraft.massivecore.MassiveCore;
import com.massivecraft.massivecore.MassiveException;
import com.massivecraft.massivecore.command.type.primitive.TypeString;
import com.massivecraft.massivecore.command.type.store.TypeMultiverse;
import com.massivecraft.massivecore.entity.Multiverse;
public class CmdMassiveCoreUsysUniverseClear extends MassiveCoreCommand {
// -------------------------------------------- //
// CONSTRUCT
// -------------------------------------------- //
public CmdMassiveCoreUsysUniverseClear() {
// Parameters
this.addParameter(TypeString.get(), "universe").setDesc("the universe to clear");
this.addParameter(TypeMultiverse.get(), "multiverse").setDesc("the multiverse of the universe to clear");
}
// -------------------------------------------- //
// OVERRIDE
// -------------------------------------------- //
@Override
public void perform() throws MassiveException {
String universe = this.readArg();
Multiverse multiverse = this.readArg();
if (universe.equals(MassiveCore.DEFAULT)) {
msg("<b>You can't clear the default universe.");
msg("<b>It contains the worlds that aren't assigned to a universe.");
return;
}
if (multiverse.clearUniverse(universe)) {
msg("<g>Cleared universe <h>%s<g> in multiverse <h>%s<g>.", universe, multiverse.getId());
} else {
msg("<b>No universe <h>%s<b> exists in multiverse <h>%s<b>.", universe, multiverse.getId());
}
}
}

View File

@ -0,0 +1,45 @@
package com.massivecraft.massivecore.cmd;
import com.massivecraft.massivecore.MassiveCore;
import com.massivecraft.massivecore.MassiveException;
import com.massivecraft.massivecore.command.type.primitive.TypeString;
import com.massivecraft.massivecore.command.type.store.TypeMultiverse;
import com.massivecraft.massivecore.entity.Multiverse;
public class CmdMassiveCoreUsysUniverseDel extends MassiveCoreCommand {
// -------------------------------------------- //
// CONSTRUCT
// -------------------------------------------- //
public CmdMassiveCoreUsysUniverseDel() {
// Parameters
this.addParameter(TypeString.get(), "universe").setDesc("the universe to delete");
this.addParameter(TypeMultiverse.get(), "multiverse").setDesc("the multiverse of the universe to delete");
}
// -------------------------------------------- //
// OVERRIDE
// -------------------------------------------- //
@Override
public void perform() throws MassiveException {
String universe = this.readArg();
Multiverse multiverse = this.readArg();
if (universe.equals(MassiveCore.DEFAULT)) {
msg("<b>You can't remove the default universe.");
msg("<b>Each multiverse contains a default universe.");
return;
}
if (!multiverse.containsUniverse(universe)) {
msg("<b>No universe <h>%s<b> exists in multiverse <h>%s<b>.", universe, multiverse.getId());
return;
}
multiverse.delUniverse(universe);
msg("<g>Deleted universe <h>%s<g> in multiverse <h>%s<g>.", universe, multiverse.getId());
}
}

View File

@ -0,0 +1,38 @@
package com.massivecraft.massivecore.cmd;
import com.massivecraft.massivecore.MassiveException;
import com.massivecraft.massivecore.command.type.primitive.TypeString;
import com.massivecraft.massivecore.command.type.store.TypeMultiverse;
import com.massivecraft.massivecore.entity.Multiverse;
public class CmdMassiveCoreUsysUniverseNew extends MassiveCoreCommand {
// -------------------------------------------- //
// CONSTRUCT
// -------------------------------------------- //
public CmdMassiveCoreUsysUniverseNew() {
// Parameters
this.addParameter(TypeString.get(), "universe").setDesc("name of universe to create");
this.addParameter(TypeMultiverse.get(), "multiverse").setDesc("the multiverse of the universe to create");
}
// -------------------------------------------- //
// OVERRIDE
// -------------------------------------------- //
@Override
public void perform() throws MassiveException {
String universe = this.readArg();
Multiverse multiverse = this.readArg();
if (multiverse.containsUniverse(universe)) {
msg("<b>The universe <h>%s<b> already exists in multiverse <h>%s<b>.", universe, multiverse.getId());
return;
}
multiverse.newUniverse(universe);
msg("<g>Created universe <h>%s<g> in multiverse <h>%s<g>.", universe, multiverse.getId());
}
}

View File

@ -0,0 +1,44 @@
package com.massivecraft.massivecore.cmd;
import com.massivecraft.massivecore.MassiveException;
import com.massivecraft.massivecore.command.type.primitive.TypeString;
import com.massivecraft.massivecore.command.type.store.TypeMultiverse;
import com.massivecraft.massivecore.entity.Multiverse;
public class CmdMassiveCoreUsysWorld extends MassiveCoreCommand {
// -------------------------------------------- //
// CONSTRUCT
// -------------------------------------------- //
public CmdMassiveCoreUsysWorld() {
// Parameters
this.addParameter(TypeString.get(), "world").setDesc("the world to move");
this.addParameter(TypeString.get(), "universe").setDesc("the universe to move the world to");
this.addParameter(TypeMultiverse.get(), "multiverse").setDesc("the multiverse of the universe to move the world to");
}
// -------------------------------------------- //
// OVERRIDE
// -------------------------------------------- //
@Override
public void perform() throws MassiveException {
String worldName = this.readArg();
String universe = this.readArg();
Multiverse multiverse = this.readArg();
if (!multiverse.containsUniverse(universe)) {
msg("<b>No universe <h>%s<b> exists in multiverse <h>%s<b>.", universe, multiverse.getId());
return;
}
String universeOld = multiverse.getUniverseForWorldName(worldName);
if (multiverse.setWorldUniverse(worldName, universe)) {
msg("<g>World <h>%s <g>moved from <h>%s <g>to <h>%s <g>universe in multiverse <h>%s<g>.", worldName, universeOld, universe, multiverse.getId());
} else {
msg("<i>World <h>%s <i>is already in universe <h>%s <i>in multiverse <h>%s<i>.", worldName, universe, multiverse.getId());
}
}
}

View File

@ -0,0 +1,19 @@
package com.massivecraft.massivecore.cmd;
import com.massivecraft.massivecore.MassiveCorePerm;
import com.massivecraft.massivecore.command.MassiveCommand;
public class MassiveCoreCommand extends MassiveCommand {
// -------------------------------------------- //
// CONSTRUCT
// -------------------------------------------- //
public MassiveCoreCommand() {
this.setSetupEnabled(true);
this.setSetupPermClass(MassiveCorePerm.class);
// The commands are not placed in their ususal place so it can't be found automatically.
this.setSetupPermBaseClassName(CmdMassiveCore.class.getSimpleName());
}
}

View File

@ -0,0 +1,171 @@
package com.massivecraft.massivecore.collections;
import com.massivecraft.massivecore.MassiveException;
import com.massivecraft.massivecore.command.type.RegistryType;
import com.massivecraft.massivecore.command.type.Type;
import java.util.AbstractSet;
import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
public class BackstringSet<T> extends AbstractSet<T> {
// -------------------------------------------- //
// FIELDS
// -------------------------------------------- //
private final Type<T> type;
private final Set<String> stringSet;
public Set<String> getStringSet() {
return this.stringSet;
}
// -------------------------------------------- //
// CONVTERT
// -------------------------------------------- //
private T convertFromString(String string) throws MassiveException {
if (string == null) {
return null;
}
return this.type.read(string);
}
@SuppressWarnings("unchecked")
private String convertToString(Object object) {
if (object == null) {
return null;
}
if (object instanceof String) {
return (String) object;
}
return this.type.getId((T) object);
}
// -------------------------------------------- //
// CONSTRUCT
// -------------------------------------------- //
public BackstringSet(Type<T> type) {
this.type = type;
this.stringSet = new MassiveSet<>();
}
public BackstringSet(Type<T> type, Collection<?> collection) {
this(type);
if (collection != null) {
for (Object object : collection) {
String string = this.convertToString(object);
this.stringSet.add(string);
}
}
}
public BackstringSet(Type<T> type, Object... objects) {
this(type, Arrays.asList(objects));
}
// -------------------------------------------- //
// MOAR CONSTRUCT
// -------------------------------------------- //
@SuppressWarnings("unchecked")
public BackstringSet(Class<T> clazz) {
this((Type<T>) RegistryType.getType(clazz));
}
@SuppressWarnings("unchecked")
public BackstringSet(Class<T> clazz, Collection<?> collection) {
this((Type<T>) RegistryType.getType(clazz), collection);
}
@SuppressWarnings("unchecked")
public BackstringSet(Class<T> clazz, Object... objects) {
this((Type<T>) RegistryType.getType(clazz), objects);
}
// -------------------------------------------- //
// OVERRIDE
// -------------------------------------------- //
@Override
public Iterator<T> iterator() {
// Create
List<T> temporaryList = new MassiveList<>();
// Fill
for (String string : this.getStringSet()) {
try {
T value = this.convertFromString(string);
if (value != null) {
temporaryList.add(value);
}
} catch (MassiveException ignored) {
// ignored
}
}
// Return
final Iterator<T> temporaryIterator = temporaryList.iterator();
return new Iterator<T>() {
@Override
public boolean hasNext() {
return temporaryIterator.hasNext();
}
@Override
public T next() {
return temporaryIterator.next();
}
@Override
public void remove() {
String message = String.format("%s iterator does not support removal.", BackstringSet.class.getSimpleName());
throw new UnsupportedOperationException(message);
}
};
}
@Override
public int size() {
return this.stringSet.size();
}
@Override
public boolean contains(Object object) {
String string = this.convertToString(object);
return this.stringSet.contains(string);
}
@Override
public boolean add(T object) {
return this.addObject(object);
}
public boolean addString(String string) {
return this.addObject(string);
}
private boolean addObject(Object object) {
String string = this.convertToString(object);
return this.stringSet.add(string);
}
@Override
public boolean remove(Object object) {
String string = this.convertToString(object);
return this.stringSet.remove(string);
}
@Override
public void clear() {
this.stringSet.clear();
}
}

View File

@ -0,0 +1,5 @@
package com.massivecraft.massivecore.collections;
public interface Def {
}

View File

@ -0,0 +1,141 @@
package com.massivecraft.massivecore.collections;
import com.massivecraft.massivecore.command.editor.annotation.EditorType;
import com.massivecraft.massivecore.command.type.container.TypeMassiveTreeSetInsensitive;
import com.massivecraft.massivecore.comparator.ComparatorCaseInsensitive;
import com.massivecraft.massivecore.util.MUtil;
import java.util.Arrays;
import java.util.Collection;
import java.util.Objects;
public class ExceptionSet {
// -------------------------------------------- //
// FIELDS
// -------------------------------------------- //
private boolean standard = true;
public boolean isStandard() {
return this.standard;
}
public void setStandard(boolean standard) {
this.standard = standard;
}
@EditorType(TypeMassiveTreeSetInsensitive.class)
public MassiveTreeSet<String, ComparatorCaseInsensitive> exceptions = new MassiveTreeSet<>(ComparatorCaseInsensitive.get());
// -------------------------------------------- //
// CONSTRUCT
// -------------------------------------------- //
public ExceptionSet() {
}
public ExceptionSet(boolean standard) {
this.standard = standard;
}
@SafeVarargs
public <O> ExceptionSet(boolean standard, O... exceptions) {
this.standard = standard;
if (exceptions.length == 0) {
return;
}
Collection<String> strings = stringifyAll(exceptions);
this.exceptions.addAll(strings);
}
// -------------------------------------------- //
// CONTAINS
// -------------------------------------------- //
public <O> boolean contains(O object) {
if (object == null) {
return !this.standard;
}
String string = stringify(object);
if (this.exceptions.contains(string)) {
return !this.standard;
}
return this.standard;
}
// -------------------------------------------- //
// IS EMPTY
// -------------------------------------------- //
public boolean isEmpty() {
return !this.isStandard() && this.exceptions.isEmpty();
}
// -------------------------------------------- //
// STRINGIFY
// -------------------------------------------- //
public String stringify(Object object) {
if (object == null) {
return null;
}
if (object instanceof String) {
return (String) object;
}
String ret = this.stringifyInner(object);
if (ret != null) {
return ret;
}
return object.toString();
}
public String stringifyInner(Object object) {
return null;
}
// -------------------------------------------- //
// STRINGIFY ALL
// -------------------------------------------- //
public MassiveTreeSet<String, ComparatorCaseInsensitive> stringifyAll(Object... exceptions) {
return stringifyAll(Arrays.asList(exceptions));
}
public MassiveTreeSet<String, ComparatorCaseInsensitive> stringifyAll(Iterable<?> exceptions) {
MassiveTreeSet<String, ComparatorCaseInsensitive> ret = new MassiveTreeSet<>(ComparatorCaseInsensitive.get());
for (Object exception : exceptions) {
String string = stringify(exception);
ret.add(string);
}
return ret;
}
// -------------------------------------------- //
// EQUALS & HASH CODE
// -------------------------------------------- //
@Override
public boolean equals(Object object) {
if (!(object instanceof ExceptionSet)) {
return false;
}
ExceptionSet that = (ExceptionSet) object;
return MUtil.equals(
this.standard, that.standard,
this.exceptions, that.exceptions
);
}
@Override
public int hashCode() {
return Objects.hash(
this.standard,
this.exceptions
);
}
}

View File

@ -0,0 +1,69 @@
package com.massivecraft.massivecore.collections;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
/**
* This subclass adds better constructors.
*/
public class MassiveList<E> extends ArrayList<E> {
// -------------------------------------------- //
// CONSTANTS
// -------------------------------------------- //
private static final long serialVersionUID = 1L;
// -------------------------------------------- //
// CONSTRUCT: BASE
// -------------------------------------------- //
public MassiveList(int initialCapacity) {
super(initialCapacity);
}
public MassiveList() {
super();
}
@SuppressWarnings("unchecked")
public MassiveList(Collection<? extends E> c) {
// Support Null
super(c == null ? Collections.EMPTY_LIST : c);
}
// -------------------------------------------- //
// CONSTRUCT: EXTRA
// -------------------------------------------- //
@SafeVarargs
public MassiveList(E... elements) {
this(Arrays.asList(elements));
}
// -------------------------------------------- //
// OPTIMIZE: REMOVE ALL & RETAIN ALL
// -------------------------------------------- //
// This will greatly reduce the complexity in cases with big sizes.
@Override
public boolean removeAll(Collection<?> c) {
if (c instanceof List) {
c = new HashSet<Object>(c);
}
return super.removeAll(c);
}
@Override
public boolean retainAll(Collection<?> c) {
if (c instanceof List) {
c = new HashSet<Object>(c);
}
return super.retainAll(c);
}
}

View File

@ -0,0 +1,37 @@
package com.massivecraft.massivecore.collections;
import java.util.Collection;
/**
* This subclass does nothing new except implementing the Def interface.
* Def is short for "Default" and means GSON should handle "null" as "empty".
*/
public class MassiveListDef<E> extends MassiveList<E> implements Def {
// -------------------------------------------- //
// CONSTANTS
// -------------------------------------------- //
private static final long serialVersionUID = 1L;
// -------------------------------------------- //
// CONSTRUCT: SUPER
// -------------------------------------------- //
public MassiveListDef(int initialCapacity) {
super(initialCapacity);
}
public MassiveListDef() {
super();
}
public MassiveListDef(Collection<? extends E> c) {
super(c);
}
@SafeVarargs
public MassiveListDef(E... elements) {
super(elements);
}
}

View File

@ -0,0 +1,85 @@
package com.massivecraft.massivecore.collections;
import java.util.Arrays;
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;
/**
* This subclass adds better constructors.
*/
public class MassiveMap<K, V> extends LinkedHashMap<K, V> {
// -------------------------------------------- //
// CONSTANTS
// -------------------------------------------- //
private static final long serialVersionUID = 1L;
// -------------------------------------------- //
// CONSTRUCT: BASE
// -------------------------------------------- //
public MassiveMap(int initialCapacity, float loadFactor) {
super(initialCapacity, loadFactor);
}
public MassiveMap(int initialCapacity) {
super(initialCapacity);
}
public MassiveMap() {
super();
}
@SuppressWarnings("unchecked")
public MassiveMap(Map<? extends K, ? extends V> m) {
// Support Null
super(m == null ? Collections.EMPTY_MAP : m);
}
public MassiveMap(int initialCapacity, float loadFactor, boolean accessOrder) {
super(initialCapacity, loadFactor, accessOrder);
}
// -------------------------------------------- //
// CONSTRUCT: EXTRA
// -------------------------------------------- //
public MassiveMap(K key1, V value1, Object... objects) {
this(varargCreate(key1, value1, objects));
}
// -------------------------------------------- //
// UTIL
// -------------------------------------------- //
@SuppressWarnings("unchecked")
public static <K, V> MassiveMap<K, V> varargCreate(K key1, V value1, Object... objects) {
MassiveMap<K, V> ret = new MassiveMap<>();
ret.put(key1, value1);
Iterator<Object> iter = Arrays.asList(objects).iterator();
while (iter.hasNext()) {
K key = (K) iter.next();
V value = (V) iter.next();
ret.put(key, value);
}
return ret;
}
// -------------------------------------------- //
// METHODS
// -------------------------------------------- //
public V set(K key, V value) {
if (value == null) {
return this.remove(key);
} else {
return this.put(key, value);
}
}
}

View File

@ -0,0 +1,44 @@
package com.massivecraft.massivecore.collections;
import java.util.Map;
/**
* This subclass does nothing new except implementing the Def interface.
* Def is short for "Default" and means GSON should handle "null" as "empty".
*/
public class MassiveMapDef<K, V> extends MassiveMap<K, V> implements Def {
// -------------------------------------------- //
// CONSTANTS
// -------------------------------------------- //
private static final long serialVersionUID = 1L;
// -------------------------------------------- //
// CONSTRUCT: SUPER
// -------------------------------------------- //
public MassiveMapDef(int initialCapacity, float loadFactor) {
super(initialCapacity, loadFactor);
}
public MassiveMapDef(int initialCapacity) {
super(initialCapacity);
}
public MassiveMapDef() {
super();
}
public MassiveMapDef(Map<? extends K, ? extends V> m) {
super(m);
}
public MassiveMapDef(int initialCapacity, float loadFactor, boolean accessOrder) {
super(initialCapacity, loadFactor, accessOrder);
}
public MassiveMapDef(K key1, V value1, Object... objects) {
super(key1, value1, objects);
}
}

View File

@ -0,0 +1,72 @@
package com.massivecraft.massivecore.collections;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
/**
* This subclass adds better constructors.
*/
public class MassiveSet<E> extends LinkedHashSet<E> {
// -------------------------------------------- //
// CONSTANTS
// -------------------------------------------- //
private static final long serialVersionUID = 1L;
// -------------------------------------------- //
// CONSTRUCT: BASE
// -------------------------------------------- //
public MassiveSet(int initialCapacity, float loadFactor) {
super(initialCapacity, loadFactor);
}
public MassiveSet(int initialCapacity) {
super(initialCapacity);
}
public MassiveSet() {
super();
}
@SuppressWarnings("unchecked")
public MassiveSet(Collection<? extends E> c) {
// Support Null
super(c == null ? Collections.EMPTY_LIST : c);
}
// -------------------------------------------- //
// CONSTRUCT: EXTRA
// -------------------------------------------- //
@SafeVarargs
public MassiveSet(E... elements) {
this(Arrays.asList(elements));
}
// -------------------------------------------- //
// OPTIMIZE: REMOVE ALL & RETAIN ALL
// -------------------------------------------- //
// This will greatly reduce the complexity in cases with big sizes.
@Override
public boolean removeAll(Collection<?> c) {
if (c instanceof List) {
c = new HashSet<Object>(c);
}
return super.removeAll(c);
}
@Override
public boolean retainAll(Collection<?> c) {
if (c instanceof List) {
c = new HashSet<Object>(c);
}
return super.retainAll(c);
}
}

View File

@ -0,0 +1,41 @@
package com.massivecraft.massivecore.collections;
import java.util.Collection;
/**
* This subclass does nothing new except implementing the Def interface.
* Def is short for "Default" and means GSON should handle "null" as "empty".
*/
public class MassiveSetDef<E> extends MassiveSet<E> implements Def {
// -------------------------------------------- //
// CONSTANTS
// -------------------------------------------- //
private static final long serialVersionUID = 1L;
// -------------------------------------------- //
// CONSTRUCT: SUPER
// -------------------------------------------- //
public MassiveSetDef(int initialCapacity, float loadFactor) {
super(initialCapacity, loadFactor);
}
public MassiveSetDef(int initialCapacity) {
super(initialCapacity);
}
public MassiveSetDef() {
super();
}
public MassiveSetDef(Collection<? extends E> c) {
super(c);
}
@SafeVarargs
public MassiveSetDef(E... elements) {
super(elements);
}
}

View File

@ -0,0 +1,43 @@
package com.massivecraft.massivecore.collections;
import java.util.Comparator;
import java.util.Map;
import java.util.TreeMap;
/**
* This subclass adds better constructors.
* It also includes the comparator as a Generic for automatic use with GSON.
*/
public class MassiveTreeMap<K, V, C extends Comparator<? super K>> extends TreeMap<K, V> {
// -------------------------------------------- //
// CONSTANTS
// -------------------------------------------- //
private static final long serialVersionUID = 1L;
// -------------------------------------------- //
// CONSTRUCT: BASE
// -------------------------------------------- //
@SuppressWarnings("unchecked")
public MassiveTreeMap(Object comparator) {
super((comparator instanceof Comparator) ? (C) comparator : null);
}
public MassiveTreeMap(Object comparator, Map<? extends K, ? extends V> map) {
// Support Null & this(comparator)
this(comparator);
if (map != null) {
putAll(map);
}
}
// -------------------------------------------- //
// CONSTRUCT: EXTRA
// -------------------------------------------- //
public MassiveTreeMap(Object comparator, K key1, V value1, Object... objects) {
this(comparator, MassiveMap.varargCreate(key1, value1, objects));
}
}

View File

@ -0,0 +1,33 @@
package com.massivecraft.massivecore.collections;
import java.util.Comparator;
import java.util.Map;
/**
* This subclass does nothing new except implementing the Def interface.
* Def is short for "Default" and means GSON should handle "null" as "empty".
*/
public class MassiveTreeMapDef<K, V, C extends Comparator<? super K>> extends MassiveTreeMap<K, V, C> implements Def {
// -------------------------------------------- //
// CONSTANTS
// -------------------------------------------- //
private static final long serialVersionUID = 1L;
// -------------------------------------------- //
// CONSTRUCT: SUPER
// -------------------------------------------- //
public MassiveTreeMapDef(Object comparator) {
super(comparator);
}
public MassiveTreeMapDef(Object comparator, Map<? extends K, ? extends V> map) {
super(comparator, map);
}
public MassiveTreeMapDef(Object comparator, K key1, V value1, Object... objects) {
super(comparator, key1, value1, objects);
}
}

Some files were not shown because too many files have changed in this diff Show More