Skip to content

Commit 9f4d2c6

Browse files
committed
Initial commit
0 parents  commit 9f4d2c6

File tree

96 files changed

+4980
-0
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

96 files changed

+4980
-0
lines changed

.gitignore

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
.idea
2+
*.iml
3+
dependency-reduced-pom.xml
4+
**/target/**
5+
pom.xml.versionsBackup
6+
**/spigot/**
7+
!**/archetype-resources/spigot/**

.maven.xml

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
<settings xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/SETTINGS/1.0.0" xsi:schemalocation="http://maven.apache.org/SETTINGS/1.0.0
2+
http://maven.apache.org/xsd/settings-1.0.0.xsd">
3+
<servers>
4+
<server>
5+
<id>ossrh</id>
6+
<username>${env.SONATYPE_USERNAME}</username>
7+
<password>${env.SONATYPE_PASSWORD}</password>
8+
</server>
9+
</servers>
10+
11+
<profiles>
12+
<profile>
13+
<id>ossrh</id>
14+
<activation>
15+
<activeByDefault>true</activeByDefault>
16+
</activation>
17+
<properties>
18+
<gpg.executable>gpg</gpg.executable>
19+
<!-- <gpg.keyname>${env.GPG_KEY_NAME}</gpg.keyname>-->
20+
<gpg.passphrase>${env.GPG_PASSPHRASE}</gpg.passphrase>
21+
</properties>
22+
</profile>
23+
</profiles>
24+
</settings>

.travis.yml

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
language: java
2+
jdk: openjdk8
3+
before_install:
4+
- echo $GPG_SECRET_KEYS | base64 --decode | $GPG_EXECUTABLE --import
5+
- echo $GPG_OWNERTRUST | base64 --decode | $GPG_EXECUTABLE --import-ownertrust
6+
- export MAVEN_OPTS=-Dorg.slf4j.simpleLogger.log.org.apache.maven.cli.transfer.Slf4jMavenTransferListener=warn
7+
before_deploy:
8+
- mvn help:evaluate -N -Dexpression=project.version|grep -v '\['
9+
- export project_version=$(mvn help:evaluate -N -Dexpression=project.version|grep -v '\[')
10+
deploy:
11+
provider: script
12+
skip_cleanup: true
13+
## Build and release to maven central on tagged version
14+
script: mvn deploy --settings .maven.xml -DskipTests=true -B -U -Prelease
15+
on:
16+
tags: true
17+
branch: master
18+
name: $project_version
19+
install:
20+
mvn --settings .maven.xml clean install -DskipTests=true -Dgpg.skip -Dmaven.javadoc.skip=true -B -V

README.md

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
# mcspring [![Build Status](https://travis-ci.org/kylepls/mcspring.svg?branch=master)](https://travis-ci.org/kylepls/mcspring) ![Maven Central](https://img.shields.io/maven-central/v/in.kyle.mcspring/mcspring)
2+
3+
Writing Bukkit plugins is a nightmare. I often lay awake in my bed late at night unable to sleep
4+
because Bukkit made events an annotation but commands are created by implementing a class.
5+
The plugin.yml is useless and main classes that extend JavaPlugin are cluttered piles of shit.
6+
7+
{insert your horror story/gripe here}
8+
9+
These are solved problems. Spring Boot took care of this issue ages ago.
10+
So how about we ditch this ridiculous programming model and hop on the Spring train.
11+
12+
```java
13+
@Component
14+
class Test { // We don't have to extend JavaPlugin. The plugin.yml is also generated for us.
15+
16+
@Command("test")
17+
String playerSender(Player sender, String command) {
18+
// parameters are automatically injected
19+
// injects: Player, Label, String[] args (no specific order required)
20+
// also injects any Spring beans such as Plugin (no specific order required)
21+
return command + " works!";
22+
}
23+
24+
@Scheduled(fixedDelay = 10000)
25+
void interval() { // runs every 10 seconds
26+
Bukkit.broadcastMessage("REMEMBER TO DONATE");
27+
}
28+
29+
@EventHandler
30+
void onMove(PlayerMoveEvent e) { // Events automatically registered
31+
getLogger().info(e.getPlayer().getName() + " moved");
32+
}
33+
34+
// sub-commands example
35+
// first we define the structure of the command (how it's parsed)
36+
// then we define the execution of the command (how it runs)
37+
// structure `/plot tp 10 20`
38+
@Command("plot")
39+
void plot(PluginCommand command) {
40+
command.on("tp", this::plotTp); // calls this method when "tp" is passed
41+
command.otherwise("Usage: plot <tp>"); // if no methods were called, fallback to this message
42+
}
43+
44+
private void tp(PluginCommand command) {
45+
command.withInt("Parameter must be an integer"); // parse 1 integer from the command, otherwise show the message parameter
46+
command.withInt("Parameter must be an integer"); // parse 1 integer from the command, otherwise show the message parameter
47+
command.then(this::executeTp); // if everything is okay so far, run the executor
48+
command.otherwise("Usage: plot tp <x> <y>"); // if not enough args (or too many) were passed, show this message
49+
}
50+
51+
// parameters are injected from the #with arguments
52+
// injects the CommandSender, Label, and String[] args
53+
// Spring beans are also injected
54+
private void executeTp(Player sender, int x, int y) {
55+
// sender corresponds to the player that sent the command, the argument position doesn't matter
56+
// x and y correspond to the 2 parameters that were parsed using the #withInt method
57+
sender.teleportToPlot(x, y);
58+
}
59+
}
60+
```
61+
62+
---
63+
64+
## What's in the sauce?
65+
* Main plugin class is generated automatically, you don't need to interact with it.
66+
* The `plugin.yml` is also a thing of the past. May it rest in peace.
67+
* Have two plugins? Want to share a Bean or two? Go for it. It's all taken care of.
68+
* Commands are now registered with `@Command`. Put it anywhere and forget about it.
69+
* Schedulers are defined with `@Scheduler`. Another thing to schlep away somewhere.
70+
* `@EventHandler` now registers itself. About damn time.
71+
* Like money? Vault support is in the box `in.kyle.mcspring.economy.EconomyService`
72+
* Want my hot take on sub-command handing? We've got you covered (see the wiki)
73+
74+
## Getting Started
75+
I went ahead and wrote a full tutorial series for you newcomers. Get started [here](https://github.com/kylepls/mcspring/wiki/Getting-Setup)
76+
77+
If you think you're too smart for the beginner tutorial; go to the
78+
[wiki](https://github.com/kylepls/mcspring/wiki) and piece it together.
79+
80+
If you're really really smart; check out the example plugins in the `mcspring-example` folder.
81+
82+
---
83+
84+
##### Final Notes
85+
Thanks to https://github.com/Alan-Gomes/mcspring-boot/ for the inspiration of this project!

mcspring-api/mcspring-base/pom.xml

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<project xmlns="http://maven.apache.org/POM/4.0.0"
3+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
5+
<parent>
6+
<artifactId>mcspring-api</artifactId>
7+
<groupId>in.kyle.mcspring</groupId>
8+
<version>0.0.8</version>
9+
</parent>
10+
11+
<modelVersion>4.0.0</modelVersion>
12+
13+
<artifactId>mcspring-base</artifactId>
14+
15+
<repositories>
16+
<repository>
17+
<id>spigot-repo</id>
18+
<url>https://hub.spigotmc.org/nexus/content/repositories/snapshots/</url>
19+
</repository>
20+
</repositories>
21+
22+
<dependencies>
23+
<dependency>
24+
<groupId>org.spigotmc</groupId>
25+
<artifactId>spigot-api</artifactId>
26+
</dependency>
27+
<dependency>
28+
<groupId>in.kyle.mcspring</groupId>
29+
<artifactId>mcspring-jar-loader</artifactId>
30+
<version>${project.version}</version>
31+
</dependency>
32+
<dependency>
33+
<groupId>org.springframework.boot</groupId>
34+
<artifactId>spring-boot-loader</artifactId>
35+
</dependency>
36+
<dependency>
37+
<groupId>org.springframework.boot</groupId>
38+
<artifactId>spring-boot-starter</artifactId>
39+
<exclusions>
40+
<exclusion>
41+
<groupId>org.springframework.boot</groupId>
42+
<artifactId>spring-boot-starter-logging</artifactId>
43+
</exclusion>
44+
</exclusions>
45+
</dependency>
46+
<dependency>
47+
<groupId>org.apache.logging.log4j</groupId>
48+
<artifactId>log4j-core</artifactId>
49+
<version>2.12.1</version>
50+
<scope>provided</scope>
51+
</dependency>
52+
<dependency>
53+
<groupId>org.springframework.boot</groupId>
54+
<artifactId>spring-boot-starter-aop</artifactId>
55+
</dependency>
56+
<dependency>
57+
<groupId>org.springframework.boot</groupId>
58+
<artifactId>spring-boot-starter-test</artifactId>
59+
<scope>test</scope>
60+
</dependency>
61+
<dependency>
62+
<groupId>org.projectlombok</groupId>
63+
<artifactId>lombok</artifactId>
64+
</dependency>
65+
</dependencies>
66+
67+
<build>
68+
<plugins>
69+
<plugin>
70+
<groupId>org.apache.maven.plugins</groupId>
71+
<artifactId>maven-source-plugin</artifactId>
72+
</plugin>
73+
<plugin>
74+
<groupId>org.apache.maven.plugins</groupId>
75+
<artifactId>maven-javadoc-plugin</artifactId>
76+
</plugin>
77+
</plugins>
78+
</build>
79+
</project>
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
package in.kyle.mcspring;
2+
3+
import org.apache.logging.log4j.Level;
4+
import org.apache.logging.log4j.LogManager;
5+
import org.apache.logging.log4j.core.Logger;
6+
import org.bukkit.plugin.Plugin;
7+
import org.springframework.boot.Banner;
8+
import org.springframework.boot.builder.SpringApplicationBuilder;
9+
import org.springframework.context.ConfigurableApplicationContext;
10+
import org.springframework.core.io.DefaultResourceLoader;
11+
import org.springframework.core.io.ResourceLoader;
12+
13+
import java.util.Arrays;
14+
import java.util.LinkedHashMap;
15+
import java.util.Map;
16+
17+
import lombok.Getter;
18+
import lombok.RequiredArgsConstructor;
19+
20+
@RequiredArgsConstructor
21+
public class SpringPlugin {
22+
23+
private static final LinkedHashMap<Plugin, SpringPlugin> SETUP_PLUGINS = new LinkedHashMap<>();
24+
25+
private final Plugin plugin;
26+
@Getter
27+
private ConfigurableApplicationContext context;
28+
29+
public static void setup(Plugin plugin, Class<?> config) {
30+
setupLogger();
31+
SpringPlugin springPlugin = new SpringPlugin(plugin);
32+
springPlugin.initSpring(config);
33+
SETUP_PLUGINS.put(plugin, springPlugin);
34+
}
35+
36+
public static void teardown(Plugin plugin) {
37+
SpringPlugin springPlugin = SETUP_PLUGINS.remove(plugin);
38+
if (springPlugin != null) {
39+
springPlugin.onDisable(plugin);
40+
}
41+
}
42+
43+
public final void onDisable(Plugin plugin) {
44+
if (context != null) {
45+
context.close();
46+
context = null;
47+
SETUP_PLUGINS.remove(plugin);
48+
}
49+
}
50+
51+
private void initSpring(Class<?> config) {
52+
SpringApplicationBuilder builder = new SpringApplicationBuilder();
53+
ClassLoader classLoader = plugin.getClass().getClassLoader();
54+
ResourceLoader loader = new DefaultResourceLoader(classLoader);
55+
Class<?>[] sources = new Class[]{config, SpringSpigotSupport.class};
56+
if (!SETUP_PLUGINS.isEmpty()) {
57+
SpringPlugin parent = findParentCandidate();
58+
builder.parent(parent.getContext());
59+
sources = Arrays.copyOfRange(sources, 0, 1);
60+
}
61+
context = builder.sources(sources)
62+
.resourceLoader(loader)
63+
.bannerMode(Banner.Mode.OFF)
64+
.properties("spigot.plugin=" + plugin.getName())
65+
.logStartupInfo(true)
66+
.run();
67+
}
68+
69+
private static void setupLogger() {
70+
if (SETUP_PLUGINS.isEmpty()) {
71+
Logger rootLogger = (Logger) LogManager.getRootLogger();
72+
rootLogger.setLevel(Level.ALL);
73+
}
74+
}
75+
76+
private SpringPlugin findParentCandidate() {
77+
return SETUP_PLUGINS.entrySet()
78+
.stream()
79+
.reduce((a, b) -> b)
80+
.map(Map.Entry::getValue)
81+
.orElse(null);
82+
}
83+
}
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
package in.kyle.mcspring;
2+
3+
import org.bukkit.Bukkit;
4+
import org.bukkit.Server;
5+
import org.bukkit.configuration.file.FileConfiguration;
6+
import org.bukkit.plugin.Plugin;
7+
import org.bukkit.plugin.PluginDescriptionFile;
8+
import org.bukkit.plugin.PluginLoader;
9+
import org.bukkit.plugin.PluginManager;
10+
import org.bukkit.plugin.messaging.Messenger;
11+
import org.bukkit.scheduler.BukkitScheduler;
12+
import org.bukkit.scoreboard.ScoreboardManager;
13+
import org.springframework.beans.factory.annotation.Value;
14+
import org.springframework.context.annotation.Bean;
15+
import org.springframework.context.annotation.ComponentScan;
16+
import org.springframework.context.annotation.Configuration;
17+
import org.springframework.context.annotation.EnableAspectJAutoProxy;
18+
import org.springframework.scheduling.annotation.EnableScheduling;
19+
20+
import java.util.logging.Logger;
21+
22+
@Configuration
23+
@ComponentScan(basePackageClasses = SpringPlugin.class)
24+
@EnableScheduling
25+
@EnableAspectJAutoProxy
26+
class SpringSpigotSupport {
27+
28+
@Bean
29+
Plugin plugin(@Value("${spigot.plugin}") String pluginName) {
30+
return Bukkit.getPluginManager().getPlugin(pluginName);
31+
}
32+
33+
@Bean(destroyMethod = "")
34+
Server server(Plugin plugin) {
35+
return plugin.getServer();
36+
}
37+
38+
@Bean
39+
Logger logger(Plugin plugin) {
40+
return plugin.getLogger();
41+
}
42+
43+
@Bean
44+
PluginManager pluginManager(Server server) {
45+
return server.getPluginManager();
46+
}
47+
48+
@Bean
49+
ScoreboardManager scoreboardManager(Server server) {
50+
return server.getScoreboardManager();
51+
}
52+
53+
@Bean
54+
Messenger messenger(Server server) {
55+
return server.getMessenger();
56+
}
57+
58+
@Bean
59+
FileConfiguration configuration(Plugin plugin) {
60+
return plugin.getConfig();
61+
}
62+
63+
@Bean
64+
PluginDescriptionFile description(Plugin plugin) {
65+
return plugin.getDescription();
66+
}
67+
68+
@Bean
69+
BukkitScheduler scheduler(Server server) {
70+
return server.getScheduler();
71+
}
72+
73+
@Bean
74+
PluginLoader pluginLoader(Plugin plugin) {
75+
return plugin.getPluginLoader();
76+
}
77+
}

0 commit comments

Comments
 (0)