Skip to content

Commit e7355e3

Browse files
committed
🎉 Initial commit
0 parents  commit e7355e3

17 files changed

+1020
-0
lines changed

.gitignore

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
# Created by https://www.toptal.com/developers/gitignore/api/maven,intellij+all
2+
# Edit at https://www.toptal.com/developers/gitignore?templates=maven,intellij+all
3+
4+
### Intellij+all ###
5+
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider
6+
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
7+
8+
# User-specific stuff
9+
.idea/**/workspace.xml
10+
.idea/**/tasks.xml
11+
.idea/**/usage.statistics.xml
12+
.idea/**/dictionaries
13+
.idea/**/shelf
14+
15+
# AWS User-specific
16+
.idea/**/aws.xml
17+
18+
# Generated files
19+
.idea/**/contentModel.xml
20+
21+
# Sensitive or high-churn files
22+
.idea/**/dataSources/
23+
.idea/**/dataSources.ids
24+
.idea/**/dataSources.local.xml
25+
.idea/**/sqlDataSources.xml
26+
.idea/**/dynamic.xml
27+
.idea/**/uiDesigner.xml
28+
.idea/**/dbnavigator.xml
29+
30+
# Gradle
31+
.idea/**/gradle.xml
32+
.idea/**/libraries
33+
34+
# Gradle and Maven with auto-import
35+
# When using Gradle or Maven with auto-import, you should exclude module files,
36+
# since they will be recreated, and may cause churn. Uncomment if using
37+
# auto-import.
38+
# .idea/artifacts
39+
# .idea/compiler.xml
40+
# .idea/jarRepositories.xml
41+
# .idea/modules.xml
42+
# .idea/*.iml
43+
# .idea/modules
44+
# *.iml
45+
# *.ipr
46+
47+
# CMake
48+
cmake-build-*/
49+
50+
# Mongo Explorer plugin
51+
.idea/**/mongoSettings.xml
52+
53+
# File-based project format
54+
*.iws
55+
56+
# IntelliJ
57+
out/
58+
59+
# mpeltonen/sbt-idea plugin
60+
.idea_modules/
61+
62+
# JIRA plugin
63+
atlassian-ide-plugin.xml
64+
65+
# Cursive Clojure plugin
66+
.idea/replstate.xml
67+
68+
# SonarLint plugin
69+
.idea/sonarlint/
70+
71+
# Crashlytics plugin (for Android Studio and IntelliJ)
72+
com_crashlytics_export_strings.xml
73+
crashlytics.properties
74+
crashlytics-build.properties
75+
fabric.properties
76+
77+
# Editor-based Rest Client
78+
.idea/httpRequests
79+
80+
# Android studio 3.1+ serialized cache file
81+
.idea/caches/build_file_checksums.ser
82+
83+
### Intellij+all Patch ###
84+
# Ignore everything but code style settings and run configurations
85+
# that are supposed to be shared within teams.
86+
87+
.idea/*
88+
89+
!.idea/codeStyles
90+
!.idea/runConfigurations
91+
92+
### Maven ###
93+
target/
94+
pom.xml.tag
95+
pom.xml.releaseBackup
96+
pom.xml.versionsBackup
97+
pom.xml.next
98+
release.properties
99+
dependency-reduced-pom.xml
100+
buildNumber.properties
101+
.mvn/timing.properties
102+
# https://github.com/takari/maven-wrapper#usage-without-binary-jar
103+
.mvn/wrapper/maven-wrapper.jar
104+
105+
# Eclipse m2e generated files
106+
# Eclipse Core
107+
.project
108+
# JDT-specific (Eclipse Java Development Tools)
109+
.classpath
110+
111+
# End of https://www.toptal.com/developers/gitignore/api/maven,intellij+all

pom.xml

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
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+
<modelVersion>4.0.0</modelVersion>
6+
7+
<groupId>net.azisaba</groupId>
8+
<artifactId>GraceStopAnnouncer</artifactId>
9+
<version>1.0.0</version>
10+
<packaging>jar</packaging>
11+
12+
<name>${project.artifactId}</name>
13+
<description>Announce and gracefully stop minecraft server on Kubernetes cluster.
14+
</description>
15+
16+
<url>https://github.com/AzisabaNetwork/GraceStopAnnouncer</url>
17+
<organization>
18+
<name>AzisabaNetwork</name>
19+
<url>https://github.com/AzisabaNetwork</url>
20+
</organization>
21+
22+
<properties>
23+
<java.version>1.8</java.version>
24+
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
25+
</properties>
26+
27+
<build>
28+
<finalName>${project.name}</finalName>
29+
<defaultGoal>clean package</defaultGoal>
30+
<plugins>
31+
<plugin>
32+
<groupId>org.apache.maven.plugins</groupId>
33+
<artifactId>maven-compiler-plugin</artifactId>
34+
<version>3.10.1</version>
35+
<configuration>
36+
<source>${java.version}</source>
37+
<target>${java.version}</target>
38+
</configuration>
39+
</plugin>
40+
<plugin>
41+
<groupId>org.apache.maven.plugins</groupId>
42+
<artifactId>maven-shade-plugin</artifactId>
43+
<version>3.3.0</version>
44+
<executions>
45+
<execution>
46+
<phase>package</phase>
47+
<goals>
48+
<goal>shade</goal>
49+
</goals>
50+
<configuration>
51+
<createDependencyReducedPom>false</createDependencyReducedPom>
52+
</configuration>
53+
</execution>
54+
</executions>
55+
</plugin>
56+
</plugins>
57+
<resources>
58+
<resource>
59+
<directory>src/main/resources</directory>
60+
<filtering>true</filtering>
61+
</resource>
62+
</resources>
63+
</build>
64+
65+
<repositories>
66+
<repository>
67+
<id>papermc</id>
68+
<url>https://papermc.io/repo/repository/maven-public/</url>
69+
</repository>
70+
<repository>
71+
<id>velocity</id>
72+
<url>https://nexus.velocitypowered.com/repository/maven-public/</url>
73+
</repository>
74+
</repositories>
75+
76+
<dependencies>
77+
<dependency>
78+
<groupId>com.destroystokyo.paper</groupId>
79+
<artifactId>paper-api</artifactId>
80+
<version>1.12.2-R0.1-SNAPSHOT</version>
81+
<scope>provided</scope>
82+
</dependency>
83+
<dependency>
84+
<groupId>com.velocitypowered</groupId>
85+
<artifactId>velocity-api</artifactId>
86+
<version>3.1.0</version>
87+
<scope>provided</scope>
88+
</dependency>
89+
<dependency>
90+
<groupId>io.fabric8</groupId>
91+
<artifactId>kubernetes-client</artifactId>
92+
<version>5.12.4</version>
93+
</dependency>
94+
<dependency>
95+
<groupId>org.projectlombok</groupId>
96+
<artifactId>lombok</artifactId>
97+
<version>1.18.24</version>
98+
<scope>provided</scope>
99+
</dependency>
100+
<dependency>
101+
<groupId>org.apache.commons</groupId>
102+
<artifactId>commons-lang3</artifactId>
103+
<version>3.12.0</version>
104+
</dependency>
105+
</dependencies>
106+
</project>
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
package net.azisaba.gracestopannouncer.bukkit;
2+
3+
import java.util.ArrayList;
4+
import java.util.Arrays;
5+
import java.util.List;
6+
import lombok.RequiredArgsConstructor;
7+
import net.azisaba.gracestopannouncer.core.ServerAdapter;
8+
import net.azisaba.gracestopannouncer.core.util.MessageFormatter;
9+
import org.bukkit.Bukkit;
10+
import org.bukkit.ChatColor;
11+
import org.bukkit.plugin.java.JavaPlugin;
12+
import org.bukkit.scheduler.BukkitRunnable;
13+
14+
@RequiredArgsConstructor
15+
public class BukkitServerAdapter implements ServerAdapter {
16+
17+
private final JavaPlugin plugin;
18+
private final MessageFormatter messageFormatter;
19+
20+
@Override
21+
public void executeAsyncAfter(Runnable runnable, long delay) {
22+
long executeOn = System.currentTimeMillis() + (delay * 1000L);
23+
new BukkitRunnable() {
24+
@Override
25+
public void run() {
26+
if (System.currentTimeMillis() >= executeOn) {
27+
runnable.run();
28+
cancel();
29+
}
30+
}
31+
}.runTaskTimerAsynchronously(plugin, 0L, 20L);
32+
}
33+
34+
@Override
35+
public void notifyShutdown(int remainingTime) {
36+
if (remainingTime <= 0) {
37+
return;
38+
}
39+
40+
plugin.getLogger().info("This server will shutdown in " + remainingTime + " seconds.");
41+
42+
List<Integer> notifySeconds =
43+
new ArrayList<>(
44+
Arrays.asList(1, 2, 3, 4, 5, 10, 30, 60, 120, 180, 300, 600, 900, 1800, 2700, 3600));
45+
notifySeconds.removeIf(i -> i > remainingTime);
46+
new BukkitRunnable() {
47+
48+
private final long shutdownMillisecond = System.currentTimeMillis() + (remainingTime * 1000L);
49+
50+
@Override
51+
public void run() {
52+
if (System.currentTimeMillis() - shutdownMillisecond - 1000L > 0) {
53+
cancel();
54+
return;
55+
}
56+
57+
int remainingSecond = (int) ((shutdownMillisecond - System.currentTimeMillis()) / 1000L);
58+
59+
if (!notifySeconds.contains(remainingSecond)) {
60+
return;
61+
}
62+
63+
notifySeconds.remove((Integer) remainingSecond);
64+
String uncoloredMessage = messageFormatter.format(remainingSecond);
65+
Bukkit.broadcastMessage(ChatColor.translateAlternateColorCodes('&', uncoloredMessage));
66+
}
67+
}.runTaskTimerAsynchronously(plugin, 0, 5);
68+
}
69+
}
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
package net.azisaba.gracestopannouncer.bukkit;
2+
3+
import io.fabric8.kubernetes.client.DefaultKubernetesClient;
4+
import io.fabric8.kubernetes.client.KubernetesClient;
5+
import lombok.Getter;
6+
import net.azisaba.gracestopannouncer.core.HoldConnectionHandler;
7+
import net.azisaba.gracestopannouncer.core.PreStopHookReceiver;
8+
import net.azisaba.gracestopannouncer.core.util.MessageFormatter;
9+
import net.azisaba.gracestopannouncer.core.util.PodSelfInformation;
10+
import org.bukkit.Bukkit;
11+
import org.bukkit.plugin.java.JavaPlugin;
12+
13+
public class GraceStopAnnouncerBukkit extends JavaPlugin {
14+
15+
@Getter private KubernetesClient client;
16+
17+
private static final String POD_NAMESPACE_ENV = "POD_NAMESPACE";
18+
private static final String POD_NAME_ENV = "POD_NAME";
19+
20+
@Getter private PodSelfInformation podSelfInformation;
21+
22+
private PreStopHookReceiver receiver;
23+
24+
@Override
25+
public void onEnable() {
26+
client = new DefaultKubernetesClient();
27+
28+
String namespace = System.getenv(POD_NAMESPACE_ENV);
29+
String podName = System.getenv(POD_NAME_ENV);
30+
31+
boolean workable = true;
32+
if (namespace == null) {
33+
getLogger().warning("Environment variable \"" + POD_NAMESPACE_ENV + "\" is not set.");
34+
workable = false;
35+
}
36+
if (podName == null) {
37+
getLogger().warning("Environment variable \"" + POD_NAME_ENV + "\" is not set.");
38+
workable = false;
39+
}
40+
41+
if (!workable) {
42+
getLogger().warning("Shutdown announcing feature will not work.");
43+
} else {
44+
podSelfInformation = new PodSelfInformation(namespace, podName);
45+
}
46+
47+
saveDefaultConfig();
48+
int port = getConfig().getInt("port");
49+
String baseMessage = getConfig().getString("message.base", "&cこのサーバーは &e%time%後 &cに停止します!");
50+
String hourStr = getConfig().getString("message.hour", "%h時間");
51+
String minuteStr = getConfig().getString("message.minute", "%m分");
52+
String secondStr = getConfig().getString("message.second", "%s秒");
53+
54+
MessageFormatter messageFormatter =
55+
new MessageFormatter(baseMessage, hourStr, minuteStr, secondStr);
56+
57+
receiver =
58+
new PreStopHookReceiver(
59+
port,
60+
new HoldConnectionHandler(
61+
client, podSelfInformation, new BukkitServerAdapter(this, messageFormatter)));
62+
receiver.start();
63+
64+
Bukkit.getLogger().info(getName() + " enabled.");
65+
}
66+
67+
@Override
68+
public void onDisable() {
69+
Bukkit.getLogger().info(getName() + " disabled.");
70+
}
71+
}

0 commit comments

Comments
 (0)