alexmcs
/
ServerStopper
Archived
0
0
Fork 0

First commit under new maven driven system.

(manual artifact builds are lame. :P)
master
(someone) 6 years ago
commit 7a06abf5b0

2
.gitignore vendored

@ -0,0 +1,2 @@
target/
.idea/libraries

@ -0,0 +1,7 @@
image: maven-3-jdk-8
build:
script: "mvn clean package"
artifacts:
paths:
- "target/*.jar"

@ -0,0 +1 @@
ServerStopper

@ -0,0 +1,32 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="CompilerConfiguration">
<resourceExtensions />
<wildcardResourcePatterns>
<entry name="!?*.java" />
<entry name="!?*.form" />
<entry name="!?*.class" />
<entry name="!?*.groovy" />
<entry name="!?*.scala" />
<entry name="!?*.flex" />
<entry name="!?*.kt" />
<entry name="!?*.clj" />
<entry name="!?*.aj" />
</wildcardResourcePatterns>
<annotationProcessing>
<profile default="true" name="Default" enabled="false">
<processorPath useClasspath="true" />
</profile>
<profile default="false" name="Maven default annotation processors profile" enabled="true">
<sourceOutputDir name="target/generated-sources/annotations" />
<sourceTestOutputDir name="target/generated-test-sources/test-annotations" />
<outputRelativeToContentRoot value="true" />
<processorPath useClasspath="true" />
<module name="ServerStopper-maven" />
</profile>
</annotationProcessing>
<bytecodeTargetLevel>
<module name="ServerStopper-maven" target="1.7" />
</bytecodeTargetLevel>
</component>
</project>

@ -0,0 +1,3 @@
<component name="CopyrightManager">
<settings default="" />
</component>

@ -0,0 +1,104 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="EntryPointsManager">
<entry_points version="2.0" />
</component>
<component name="MavenProjectsManager">
<option name="originalFiles">
<list>
<option value="$PROJECT_DIR$/pom.xml" />
</list>
</option>
</component>
<component name="ProjectInspectionProfilesVisibleTreeState">
<entry key="Project Default">
<profile-state>
<expanded-state>
<State>
<id />
</State>
<State>
<id>Android</id>
</State>
<State>
<id>Android &gt; Lint &gt; Correctness</id>
</State>
<State>
<id>Android Lint for Kotlin</id>
</State>
<State>
<id>Class structureJava</id>
</State>
<State>
<id>Code maturity issuesJava</id>
</State>
<State>
<id>Java</id>
</State>
<State>
<id>Java language level migration aidsJava</id>
</State>
<State>
<id>Javadoc issuesJava</id>
</State>
<State>
<id>Performance issuesJava</id>
</State>
<State>
<id>TestNGJava</id>
</State>
<State>
<id>Threading issuesJava</id>
</State>
</expanded-state>
<selected-state>
<State>
<id>Class structureJava</id>
</State>
</selected-state>
</profile-state>
</entry>
</component>
<component name="ProjectLevelVcsManager" settingsEditedManually="false">
<OptionsSetting value="true" id="Add" />
<OptionsSetting value="true" id="Remove" />
<OptionsSetting value="true" id="Checkout" />
<OptionsSetting value="true" id="Update" />
<OptionsSetting value="true" id="Status" />
<OptionsSetting value="true" id="Edit" />
<ConfirmationsSetting value="0" id="Add" />
<ConfirmationsSetting value="0" id="Remove" />
</component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" default="true" assert-keyword="true" jdk-15="true" project-jdk-name="1.8" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/out" />
</component>
<component name="SvnConfiguration">
<configuration>$USER_HOME$/.subversion</configuration>
</component>
<component name="masterDetails">
<states>
<state key="Copyright.UI">
<settings>
<splitter-proportions>
<option name="proportions">
<list>
<option value="0.2" />
</list>
</option>
</splitter-proportions>
</settings>
</state>
<state key="ScopeChooserConfigurable.UI">
<settings>
<splitter-proportions>
<option name="proportions">
<list>
<option value="0.2" />
</list>
</option>
</splitter-proportions>
</settings>
</state>
</states>
</component>
</project>

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/ServerStopper-maven.iml" filepath="$PROJECT_DIR$/ServerStopper-maven.iml" />
</modules>
</component>
</project>

@ -0,0 +1,582 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ChangeListManager">
<list default="true" id="0300ce80-9676-462a-a7fb-c40ef96687cc" name="Default" comment="" />
<ignored path="ServerStopper.iws" />
<ignored path=".idea/workspace.xml" />
<ignored path="$PROJECT_DIR$/out/" />
<ignored path="$PROJECT_DIR$/target/" />
<option name="EXCLUDED_CONVERTED_TO_IGNORED" value="true" />
<option name="TRACKING_ENABLED" value="true" />
<option name="SHOW_DIALOG" value="false" />
<option name="HIGHLIGHT_CONFLICTS" value="true" />
<option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
<option name="LAST_RESOLUTION" value="IGNORE" />
</component>
<component name="CreatePatchCommitExecutor">
<option name="PATCH_PATH" value="" />
</component>
<component name="ExecutionTargetManager" SELECTED_TARGET="default_target" />
<component name="FavoritesManager">
<favorites_list name="ServerStopper" />
</component>
<component name="FileEditorManager">
<leaf>
<file leaf-file-name="pom.xml" pinned="false" current-in-tab="true">
<entry file="file://$PROJECT_DIR$/pom.xml">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="144">
<caret line="8" column="29" selection-start-line="8" selection-start-column="29" selection-end-line="8" selection-end-column="29" />
<folding />
</state>
</provider>
</entry>
</file>
<file leaf-file-name="plugin.yml" pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/src/main/resources/plugin.yml">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="18">
<caret line="1" column="25" selection-start-line="1" selection-start-column="25" selection-end-line="1" selection-end-column="25" />
<folding />
</state>
</provider>
</entry>
</file>
<file leaf-file-name="StopManager.java" pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/src/main/java/net/alexmcs/bukkit/serverstopper/StopManager.java">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="738">
<caret line="121" column="118" selection-start-line="121" selection-start-column="118" selection-end-line="121" selection-end-column="118" />
<folding />
</state>
</provider>
</entry>
</file>
</leaf>
</component>
<component name="GradleLocalSettings">
<option name="externalProjectsViewState">
<projects_view />
</option>
</component>
<component name="IdeDocumentHistory">
<option name="CHANGED_PATHS">
<list>
<option value="$PROJECT_DIR$/src/main/java/net/alexmcs/bukkit/serverstopper/StopManager.java" />
<option value="$PROJECT_DIR$/pom.xml" />
<option value="$PROJECT_DIR$/src/main/resources/plugin.yml" />
</list>
</option>
</component>
<component name="MavenImportPreferences">
<option name="generalSettings">
<MavenGeneralSettings>
<option name="mavenHome" value="Bundled (Maven 3)" />
</MavenGeneralSettings>
</option>
</component>
<component name="MavenProjectNavigator">
<treeState>
<PATH>
<PATH_ELEMENT>
<option name="myItemId" value="" />
<option name="myItemType" value="org.jetbrains.idea.maven.navigator.MavenProjectsStructure$RootNode" />
</PATH_ELEMENT>
<PATH_ELEMENT>
<option name="myItemId" value="ServerStopper" />
<option name="myItemType" value="org.jetbrains.idea.maven.navigator.MavenProjectsStructure$ProjectNode" />
</PATH_ELEMENT>
</PATH>
<PATH>
<PATH_ELEMENT>
<option name="myItemId" value="" />
<option name="myItemType" value="org.jetbrains.idea.maven.navigator.MavenProjectsStructure$RootNode" />
</PATH_ELEMENT>
<PATH_ELEMENT>
<option name="myItemId" value="ServerStopper" />
<option name="myItemType" value="org.jetbrains.idea.maven.navigator.MavenProjectsStructure$ProjectNode" />
</PATH_ELEMENT>
<PATH_ELEMENT>
<option name="myItemId" value="Lifecycle" />
<option name="myItemType" value="org.jetbrains.idea.maven.navigator.MavenProjectsStructure$LifecycleNode" />
</PATH_ELEMENT>
</PATH>
</treeState>
</component>
<component name="ProjectFrameBounds">
<option name="y" value="-1" />
<option name="width" value="1920" />
<option name="height" value="1063" />
</component>
<component name="ProjectLevelVcsManager" settingsEditedManually="false">
<OptionsSetting value="true" id="Add" />
<OptionsSetting value="true" id="Remove" />
<OptionsSetting value="true" id="Checkout" />
<OptionsSetting value="true" id="Update" />
<OptionsSetting value="true" id="Status" />
<OptionsSetting value="true" id="Edit" />
<ConfirmationsSetting value="0" id="Add" />
<ConfirmationsSetting value="0" id="Remove" />
</component>
<component name="ProjectView">
<navigator currentView="ProjectPane" proportions="" version="1">
<flattenPackages />
<showMembers />
<showModules />
<showLibraryContents />
<hideEmptyPackages />
<abbreviatePackageNames />
<autoscrollToSource />
<autoscrollFromSource />
<sortByType />
<manualOrder />
<foldersAlwaysOnTop value="true" />
</navigator>
<panes>
<pane id="PackagesPane" />
<pane id="Scope" />
<pane id="Scratches" />
<pane id="ProjectPane">
<subPane>
<PATH>
<PATH_ELEMENT>
<option name="myItemId" value="ServerStopper" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.ProjectViewProjectNode" />
</PATH_ELEMENT>
</PATH>
<PATH>
<PATH_ELEMENT>
<option name="myItemId" value="ServerStopper" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.ProjectViewProjectNode" />
</PATH_ELEMENT>
<PATH_ELEMENT>
<option name="myItemId" value="ServerStopper-maven" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
</PATH_ELEMENT>
</PATH>
<PATH>
<PATH_ELEMENT>
<option name="myItemId" value="ServerStopper" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.ProjectViewProjectNode" />
</PATH_ELEMENT>
<PATH_ELEMENT>
<option name="myItemId" value="ServerStopper-maven" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
</PATH_ELEMENT>
<PATH_ELEMENT>
<option name="myItemId" value="src" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
</PATH_ELEMENT>
</PATH>
<PATH>
<PATH_ELEMENT>
<option name="myItemId" value="ServerStopper" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.ProjectViewProjectNode" />
</PATH_ELEMENT>
<PATH_ELEMENT>
<option name="myItemId" value="ServerStopper-maven" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
</PATH_ELEMENT>
<PATH_ELEMENT>
<option name="myItemId" value="src" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
</PATH_ELEMENT>
<PATH_ELEMENT>
<option name="myItemId" value="main" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
</PATH_ELEMENT>
<PATH_ELEMENT>
<option name="myItemId" value="resources" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
</PATH_ELEMENT>
</PATH>
<PATH>
<PATH_ELEMENT>
<option name="myItemId" value="ServerStopper" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.ProjectViewProjectNode" />
</PATH_ELEMENT>
<PATH_ELEMENT>
<option name="myItemId" value="ServerStopper-maven" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
</PATH_ELEMENT>
<PATH_ELEMENT>
<option name="myItemId" value="src" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
</PATH_ELEMENT>
<PATH_ELEMENT>
<option name="myItemId" value="main" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
</PATH_ELEMENT>
<PATH_ELEMENT>
<option name="myItemId" value="java" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
</PATH_ELEMENT>
<PATH_ELEMENT>
<option name="myItemId" value="serverstopper" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
</PATH_ELEMENT>
</PATH>
</subPane>
</pane>
</panes>
</component>
<component name="PropertiesComponent">
<property name="settings.editor.selected.configurable" value="reference.settings.project.maven.importing" />
<property name="settings.editor.splitter.proportion" value="0.2" />
</component>
<component name="RunManager">
<configuration default="true" type="#org.jetbrains.idea.devkit.run.PluginConfigurationType" factoryName="Plugin">
<module name="" />
<option name="VM_PARAMETERS" value="-Xmx512m -Xms256m -XX:MaxPermSize=250m -ea" />
<option name="PROGRAM_PARAMETERS" />
<method />
</configuration>
<configuration default="true" type="AndroidRunConfigurationType" factoryName="Android Application">
<module name="" />
<option name="DEPLOY" value="true" />
<option name="ARTIFACT_NAME" value="" />
<option name="PM_INSTALL_OPTIONS" value="" />
<option name="ACTIVITY_EXTRA_FLAGS" value="" />
<option name="MODE" value="default_activity" />
<option name="TARGET_SELECTION_MODE" value="SHOW_DIALOG" />
<option name="PREFERRED_AVD" value="" />
<option name="CLEAR_LOGCAT" value="false" />
<option name="SHOW_LOGCAT_AUTOMATICALLY" value="true" />
<option name="SKIP_NOOP_APK_INSTALLATIONS" value="true" />
<option name="FORCE_STOP_RUNNING_APP" value="true" />
<option name="DEBUGGER_TYPE" value="Java" />
<option name="USE_LAST_SELECTED_DEVICE" value="false" />
<option name="PREFERRED_AVD" value="" />
<Java />
<Profilers>
<option name="GAPID_DISABLE_PCS" value="false" />
</Profilers>
<option name="DEEP_LINK" value="" />
<option name="ACTIVITY_CLASS" value="" />
<method />
</configuration>
<configuration default="true" type="AndroidTestRunConfigurationType" factoryName="Android Tests">
<module name="" />
<option name="TESTING_TYPE" value="0" />
<option name="INSTRUMENTATION_RUNNER_CLASS" value="" />
<option name="METHOD_NAME" value="" />
<option name="CLASS_NAME" value="" />
<option name="PACKAGE_NAME" value="" />
<option name="EXTRA_OPTIONS" value="" />
<option name="TARGET_SELECTION_MODE" value="SHOW_DIALOG" />
<option name="PREFERRED_AVD" value="" />
<option name="CLEAR_LOGCAT" value="false" />
<option name="SHOW_LOGCAT_AUTOMATICALLY" value="true" />
<option name="SKIP_NOOP_APK_INSTALLATIONS" value="true" />
<option name="FORCE_STOP_RUNNING_APP" value="true" />
<option name="DEBUGGER_TYPE" value="Java" />
<option name="USE_LAST_SELECTED_DEVICE" value="false" />
<option name="PREFERRED_AVD" value="" />
<Java />
<Profilers>
<option name="GAPID_DISABLE_PCS" value="false" />
</Profilers>
<method />
</configuration>
<configuration default="true" type="Applet" factoryName="Applet">
<option name="HTML_USED" value="false" />
<option name="WIDTH" value="400" />
<option name="HEIGHT" value="300" />
<option name="POLICY_FILE" value="$APPLICATION_HOME_DIR$/bin/appletviewer.policy" />
<module />
<method />
</configuration>
<configuration default="true" type="Application" factoryName="Application">
<extension name="coverage" enabled="false" merge="false" sample_coverage="true" runner="idea" />
<option name="MAIN_CLASS_NAME" />
<option name="VM_PARAMETERS" />
<option name="PROGRAM_PARAMETERS" />
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$" />
<option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
<option name="ALTERNATIVE_JRE_PATH" />
<option name="ENABLE_SWING_INSPECTOR" value="false" />
<option name="ENV_VARIABLES" />
<option name="PASS_PARENT_ENVS" value="true" />
<module name="" />
<envs />
<method />
</configuration>
<configuration default="true" type="GradleRunConfiguration" factoryName="Gradle">
<ExternalSystemSettings>
<option name="executionName" />
<option name="externalProjectPath" />
<option name="externalSystemIdString" value="GRADLE" />
<option name="scriptParameters" />
<option name="taskDescriptions">
<list />
</option>
<option name="taskNames">
<list />
</option>
<option name="vmOptions" />
</ExternalSystemSettings>
<method />
</configuration>
<configuration default="true" type="JUnit" factoryName="JUnit">
<extension name="coverage" enabled="false" merge="false" sample_coverage="true" runner="idea" />
<module name="" />
<option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
<option name="ALTERNATIVE_JRE_PATH" />
<option name="PACKAGE_NAME" />
<option name="MAIN_CLASS_NAME" />
<option name="METHOD_NAME" />
<option name="TEST_OBJECT" value="class" />
<option name="VM_PARAMETERS" value="-ea" />
<option name="PARAMETERS" />
<option name="WORKING_DIRECTORY" value="$MODULE_DIR$" />
<option name="ENV_VARIABLES" />
<option name="PASS_PARENT_ENVS" value="true" />
<option name="TEST_SEARCH_SCOPE">
<value defaultName="singleModule" />
</option>
<envs />
<patterns />
<method />
</configuration>
<configuration default="true" type="JUnitTestDiscovery" factoryName="JUnit Test Discovery" changeList="All">
<extension name="coverage" enabled="false" merge="false" sample_coverage="true" runner="idea" />
<module name="" />
<option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
<option name="ALTERNATIVE_JRE_PATH" />
<option name="PACKAGE_NAME" />
<option name="MAIN_CLASS_NAME" />
<option name="METHOD_NAME" />
<option name="TEST_OBJECT" value="class" />
<option name="VM_PARAMETERS" />
<option name="PARAMETERS" />
<option name="WORKING_DIRECTORY" />
<option name="ENV_VARIABLES" />
<option name="PASS_PARENT_ENVS" value="true" />
<option name="TEST_SEARCH_SCOPE">
<value defaultName="singleModule" />
</option>
<envs />
<patterns />
<method />
</configuration>
<configuration default="true" type="JarApplication" factoryName="JAR Application">
<extension name="coverage" enabled="false" merge="false" sample_coverage="true" runner="idea" />
<envs />
<method />
</configuration>
<configuration default="true" type="Java Scratch" factoryName="Java Scratch">
<extension name="coverage" enabled="false" merge="false" sample_coverage="true" runner="idea" />
<option name="SCRATCH_FILE_ID" value="0" />
<option name="MAIN_CLASS_NAME" />
<option name="VM_PARAMETERS" />
<option name="PROGRAM_PARAMETERS" />
<option name="WORKING_DIRECTORY" />
<option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
<option name="ALTERNATIVE_JRE_PATH" />
<option name="ENABLE_SWING_INSPECTOR" value="false" />
<option name="ENV_VARIABLES" />
<option name="PASS_PARENT_ENVS" value="true" />
<module name="" />
<envs />
<method />
</configuration>
<configuration default="true" type="JetRunConfigurationType" factoryName="Kotlin">
<extension name="coverage" enabled="false" merge="false" sample_coverage="true" runner="idea" />
<option name="MAIN_CLASS_NAME" />
<option name="VM_PARAMETERS" />
<option name="PROGRAM_PARAMETERS" />
<option name="WORKING_DIRECTORY" />
<option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
<option name="ALTERNATIVE_JRE_PATH" />
<option name="PASS_PARENT_ENVS" value="true" />
<module name="ServerStopper-maven" />
<envs />
<method />
</configuration>
<configuration default="true" type="KotlinStandaloneScriptRunConfigurationType" factoryName="Kotlin script">
<extension name="coverage" enabled="false" merge="false" sample_coverage="true" runner="idea" />
<option name="filePath" />
<option name="vmParameters" />
<option name="alternativeJrePath" />
<option name="programParameters" />
<option name="passParentEnvs" value="true" />
<option name="workingDirectory" />
<option name="isAlternativeJrePathEnabled" value="false" />
<envs />
<method />
</configuration>
<configuration default="true" type="MavenRunConfiguration" factoryName="Maven">
<MavenSettings>
<option name="myGeneralSettings" />
<option name="myRunnerSettings" />
<option name="myRunnerParameters">
<MavenRunnerParameters>
<option name="profiles">
<set />
</option>
<option name="goals">
<list />
</option>
<option name="profilesMap">
<map />
</option>
<option name="resolveToWorkspace" value="false" />
<option name="workingDirPath" value="" />
</MavenRunnerParameters>
</option>
</MavenSettings>
<method />
</configuration>
<configuration default="true" type="Remote" factoryName="Remote">
<option name="USE_SOCKET_TRANSPORT" value="true" />
<option name="SERVER_MODE" value="false" />
<option name="SHMEM_ADDRESS" value="javadebug" />
<option name="HOST" value="localhost" />
<option name="PORT" value="5005" />
<method />
</configuration>
<configuration default="true" type="TestNG" factoryName="TestNG">
<extension name="coverage" enabled="false" merge="false" sample_coverage="true" runner="idea" />
<module name="" />
<option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
<option name="ALTERNATIVE_JRE_PATH" />
<option name="SUITE_NAME" />
<option name="PACKAGE_NAME" />
<option name="MAIN_CLASS_NAME" />
<option name="METHOD_NAME" />
<option name="GROUP_NAME" />
<option name="TEST_OBJECT" value="CLASS" />
<option name="VM_PARAMETERS" value="-ea" />
<option name="PARAMETERS" />
<option name="WORKING_DIRECTORY" value="$MODULE_DIR$" />
<option name="OUTPUT_DIRECTORY" />
<option name="ANNOTATION_TYPE" />
<option name="ENV_VARIABLES" />
<option name="PASS_PARENT_ENVS" value="true" />
<option name="TEST_SEARCH_SCOPE">
<value defaultName="singleModule" />
</option>
<option name="USE_DEFAULT_REPORTERS" value="false" />
<option name="PROPERTIES_FILE" />
<envs />
<properties />
<listeners />
<method />
</configuration>
<configuration default="true" type="TestNGTestDiscovery" factoryName="TestNG Test Discovery" changeList="All">
<extension name="coverage" enabled="false" merge="false" sample_coverage="true" runner="idea" />
<module name="" />
<option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
<option name="ALTERNATIVE_JRE_PATH" />
<option name="SUITE_NAME" />
<option name="PACKAGE_NAME" />
<option name="MAIN_CLASS_NAME" />
<option name="METHOD_NAME" />
<option name="GROUP_NAME" />
<option name="TEST_OBJECT" value="CLASS" />
<option name="VM_PARAMETERS" />
<option name="PARAMETERS" />
<option name="WORKING_DIRECTORY" />
<option name="OUTPUT_DIRECTORY" />
<option name="ANNOTATION_TYPE" />
<option name="ENV_VARIABLES" />
<option name="PASS_PARENT_ENVS" value="true" />
<option name="TEST_SEARCH_SCOPE">
<value defaultName="singleModule" />
</option>
<option name="USE_DEFAULT_REPORTERS" value="false" />
<option name="PROPERTIES_FILE" />
<envs />
<properties />
<listeners />
<method />
</configuration>
</component>
<component name="ShelveChangesManager" show_recycled="false">
<option name="remove_strategy" value="false" />
</component>
<component name="TaskManager">
<task active="true" id="Default" summary="Default task">
<changelist id="0300ce80-9676-462a-a7fb-c40ef96687cc" name="Default" comment="" />
<created>1476709660656</created>
<option name="number" value="Default" />
<option name="presentableId" value="Default" />
<updated>1476709660656</updated>
</task>
<servers />
</component>
<component name="ToolWindowManager">
<frame x="0" y="-1" width="1920" height="1063" extended-state="7" />
<editor active="false" />
<layout>
<window_info id="Palette" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="-1" side_tool="false" content_ui="tabs" />
<window_info id="TODO" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="6" side_tool="false" content_ui="tabs" />
<window_info id="Palette&#9;" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="-1" side_tool="false" content_ui="tabs" />
<window_info id="Capture Analysis" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="-1" side_tool="false" content_ui="tabs" />
<window_info id="Event Log" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="-1" side_tool="true" content_ui="tabs" />
<window_info id="Maven Projects" active="true" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="true" show_stripe_button="true" weight="0.099574015" sideWeight="0.5" order="-1" side_tool="false" content_ui="tabs" />
<window_info id="Run" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="true" show_stripe_button="true" weight="0.23809524" sideWeight="0.5" order="2" side_tool="false" content_ui="tabs" />
<window_info id="Version Control" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="-1" side_tool="false" content_ui="tabs" />
<window_info id="Terminal" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="-1" side_tool="false" content_ui="tabs" />
<window_info id="Capture Tool" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="-1" side_tool="false" content_ui="tabs" />
<window_info id="Designer" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="-1" side_tool="false" content_ui="tabs" />
<window_info id="Project" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="true" show_stripe_button="true" weight="0.13365282" sideWeight="0.5" order="0" side_tool="false" content_ui="combo" />
<window_info id="Structure" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.25" sideWeight="0.5" order="1" side_tool="false" content_ui="tabs" />
<window_info id="Ant Build" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.2496318" sideWeight="0.5" order="1" side_tool="false" content_ui="tabs" />
<window_info id="UI Designer" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="-1" side_tool="false" content_ui="tabs" />
<window_info id="Debug" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.4" sideWeight="0.5" order="3" side_tool="false" content_ui="tabs" />
<window_info id="Favorites" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="-1" side_tool="true" content_ui="tabs" />
<window_info id="Cvs" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.25" sideWeight="0.5" order="4" side_tool="false" content_ui="tabs" />
<window_info id="Hierarchy" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.25" sideWeight="0.5" order="2" side_tool="false" content_ui="combo" />
<window_info id="Message" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="0" side_tool="false" content_ui="tabs" />
<window_info id="Commander" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.4" sideWeight="0.5" order="0" side_tool="false" content_ui="tabs" />
<window_info id="Find" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="1" side_tool="false" content_ui="tabs" />
<window_info id="Inspection" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.4" sideWeight="0.5" order="5" side_tool="false" content_ui="tabs" />
</layout>
</component>
<component name="Vcs.Log.UiProperties">
<option name="RECENTLY_FILTERED_USER_GROUPS">
<collection />
</option>
<option name="RECENTLY_FILTERED_BRANCH_GROUPS">
<collection />
</option>
</component>
<component name="VcsContentAnnotationSettings">
<option name="myLimit" value="2678400000" />
</component>
<component name="XDebuggerManager">
<breakpoint-manager />
<watches-manager />
</component>
<component name="antWorkspaceConfiguration">
<option name="IS_AUTOSCROLL_TO_SOURCE" value="false" />
<option name="FILTER_TARGETS" value="false" />
</component>
<component name="editorHistoryManager">
<entry file="file://$PROJECT_DIR$/src/main/java/net/alexmcs/bukkit/serverstopper/StopManager.java">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="738">
<caret line="121" column="118" selection-start-line="121" selection-start-column="118" selection-end-line="121" selection-end-column="118" />
<folding />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/src/main/resources/plugin.yml">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="18">
<caret line="1" column="25" selection-start-line="1" selection-start-column="25" selection-end-line="1" selection-end-column="25" />
<folding />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/pom.xml">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="144">
<caret line="8" column="29" selection-start-line="8" selection-start-column="29" selection-end-line="8" selection-end-column="29" />
<folding />
</state>
</provider>
</entry>
</component>
</project>

@ -0,0 +1,3 @@
Copyright (c) 2016 AlexMCS. All rights reserved.
We will open source this later.

@ -0,0 +1 @@
ServerStopper

@ -0,0 +1,25 @@
<?xml version="1.0" encoding="UTF-8"?>
<module org.jetbrains.idea.maven.project.MavenProjectsManager.isMavenModule="true" type="JAVA_MODULE" version="4">
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_7" inherit-compiler-output="false">
<output url="file://$MODULE_DIR$/target/classes" />
<output-test url="file://$MODULE_DIR$/target/test-classes" />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src/main/java" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/main/resources" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/test/java" isTestSource="true" />
<excludeFolder url="file://$MODULE_DIR$/target" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="library" scope="PROVIDED" name="Maven: org.bukkit:bukkit:1.10.2-R0.1-SNAPSHOT" level="project" />
<orderEntry type="library" scope="PROVIDED" name="Maven: commons-lang:commons-lang:2.6" level="project" />
<orderEntry type="library" scope="PROVIDED" name="Maven: com.googlecode.json-simple:json-simple:1.1.1" level="project" />
<orderEntry type="library" scope="PROVIDED" name="Maven: junit:junit:4.10" level="project" />
<orderEntry type="library" scope="PROVIDED" name="Maven: org.hamcrest:hamcrest-core:1.1" level="project" />
<orderEntry type="library" scope="PROVIDED" name="Maven: com.google.guava:guava:17.0" level="project" />
<orderEntry type="library" scope="PROVIDED" name="Maven: com.google.code.gson:gson:2.2.4" level="project" />
<orderEntry type="library" scope="PROVIDED" name="Maven: org.avaje:ebean:2.8.1" level="project" />
<orderEntry type="library" scope="PROVIDED" name="Maven: javax.persistence:persistence-api:1.0" level="project" />
<orderEntry type="library" scope="PROVIDED" name="Maven: org.yaml:snakeyaml:1.15" level="project" />
</component>
</module>

@ -0,0 +1,49 @@
<?xml version="1.0" encoding="UTF-8"?>
<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>
<groupId>net.alexmcs.bukkit</groupId>
<artifactId>ServerStopper</artifactId>
<version>1.0a-prerelease1</version>
<repositories>
<repository>
<id>spigot-repo</id>
<url>https://hub.spigotmc.org/nexus/content/repositories/snapshots/</url>
</repository>
</repositories>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.5.1</version>
<configuration>
<source>1.7</source>
<target>1.7</target>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>org.bukkit</groupId>
<artifactId>bukkit</artifactId>
<version>1.10.2-R0.1-SNAPSHOT</version>
<type>jar</type>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.bukkit</groupId>
<artifactId>bukkit</artifactId>
<version>1.10.2-R0.1-SNAPSHOT</version>
<type>javadoc</type>
<scope>provided</scope>
</dependency>
</dependencies>
</project>

@ -0,0 +1,35 @@
package net.alexmcs.bukkit.serverstopper;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
/**
* Servertopper
* net.alexmcs.bukkit.serverstopper.CommandCancelstop
* Command handler for /cancelstop.
* Cancels a server stop. This method is depreciated and /stop cancel should be used instead.
*/
class CommandCancelstop implements CommandExecutor {
@Override
public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) {
// Verify that there are no arguments.
if (args.length == 0) {
// Alias to serverstopper:stop cancel
Bukkit.dispatchCommand(sender, "serverstopper:stop cancel");
return true;
}
// Error for unknown commands.
else {
sender.sendMessage(ChatColor.translateAlternateColorCodes('&', "&4&lERROR&r: Unknown command."));
return false;
}
}
}

@ -0,0 +1,79 @@
package net.alexmcs.bukkit.serverstopper;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
/**
* Servertopper
* net.alexmcs.bukkit.serverstopper.CommandServerstopper
* Command handler for /serverstopper.
* Gives information about ServerStopper and help on how to use it.
*/
class CommandServerstopper implements CommandExecutor {
@Override
public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) {
// Parse the first argument
String arg1;
if(args.length == 0) {
arg1 = "";
} else {
arg1 = args[0];
}
// Handle the reload command
if (arg1.equalsIgnoreCase("reload")) {
/**
* In a future version of ServerStopper, there will be translation and configuration files. This feature is
* not implemented yet, but when it is, there will be a call here to re-initialize the part of the plugin
* that handles those files. This way, you can change that configuration on the fly without restarting the
* server.
*/
sender.sendMessage(ChatColor.translateAlternateColorCodes('&', "&4&lERROR&r: This feature is not implemented yet."));
return false;
}
// The info command spits out some basic information about ServerStopper. Nothing too interesting here.
else if (arg1.equalsIgnoreCase("info") || arg1.equalsIgnoreCase("version") || arg1.equalsIgnoreCase("")) {
if (sender.hasPermission("serverstopper.info")) {
sender.sendMessage(ChatColor.translateAlternateColorCodes('&', "&6&lServer&4&lStopper&a&l v" + Bukkit.getPluginManager().getPlugin("ServerStopper").getDescription().getVersion()));
sender.sendMessage(ChatColor.translateAlternateColorCodes('&', "By &2&lAlex&6&lMCS&r / &b&lColton&4&lDRG&r"));
sender.sendMessage(ChatColor.translateAlternateColorCodes('&', "&aTo learn how to use ServerStopper, do &b&l/serverstopper help&a."));
sender.sendMessage(ChatColor.translateAlternateColorCodes('&', "&cMore information: &9http://gitlab.com/AlexMCS/ServerStopper/"));
} else {
sender.sendMessage(ChatColor.translateAlternateColorCodes('&', "&4&lERROR&r: You do not have permission to do that."));
}
return true;
}
// The help command spits out information on how to properly use ServerStopper. Nothing too interesting here.
else if (arg1.equalsIgnoreCase("help")) {
if (sender.hasPermission("serverstopper.help")) {
sender.sendMessage(ChatColor.translateAlternateColorCodes('&', "&6&lServer&4&lStopper&a&l v" + Bukkit.getPluginManager().getPlugin("ServerStopper").getDescription().getVersion()));
sender.sendMessage(ChatColor.translateAlternateColorCodes('&', "&cTo stop the server, use &b&l/stop"));
sender.sendMessage(ChatColor.translateAlternateColorCodes('&', "&cTo stop the server immediately, use &b&l/stop now"));
sender.sendMessage(ChatColor.translateAlternateColorCodes('&', "&cTo cancel a pending server stop, use &b&l/stop cancel"));
sender.sendMessage(ChatColor.translateAlternateColorCodes('&', "&cTo stop the server in five minutes, use &b&l/stop 5"));
sender.sendMessage(ChatColor.translateAlternateColorCodes('&', "&cTo stop the server in one hour, use &b&l/stop 60"));
sender.sendMessage(ChatColor.translateAlternateColorCodes('&', "&cTo stop the server in any given number of minutes, use &b&l/stop <minutes>"));
sender.sendMessage(ChatColor.translateAlternateColorCodes('&', "&cTo learn more about ServerStopper, use &b&l/serverstopper info"));
} else {
sender.sendMessage(ChatColor.translateAlternateColorCodes('&', "&4&lERROR&r: You do not have permission to do that."));
}
return true;
}
// Error for unknown commands.
else {
sender.sendMessage(ChatColor.translateAlternateColorCodes('&', "&4&lERROR&r: Unknown command."));
return false;
}
}
}

@ -0,0 +1,134 @@
package net.alexmcs.bukkit.serverstopper;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
/**
* Servertopper
* net.alexmcs.bukkit.serverstopper.CommandStop
* Command handler for /stop.
* This class handles all the main commands that interact with StopManager to stop the server.
*/
class CommandStop implements CommandExecutor {
@Override
public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) {
// Determine if the stop request was sent by a player or the console and parse their username
String senderName;
if (sender instanceof Player) {
Player player = (Player) sender;
senderName = player.getDisplayName();
} else if (sender == Bukkit.getConsoleSender()) {
senderName = "Console";
} else {
Bukkit.getLogger().warning("An invalid sender has issued the /stop command.");
senderName = "??????";
}
// Parse the first argument
String arg1;
if(args.length == 0) {
arg1 = "";
} else {
arg1 = args[0];
}
// The cancel command cancels a pending server stop. This is done by setting the clock in the StopManager class to -1.
if (arg1.equalsIgnoreCase("cancel") || arg1.equalsIgnoreCase("-1")) {
if (sender.hasPermission("serverstopper.cancel")) {
// Check if the clock is already -1. If so, the server should not be stopping, so there's nothing to cancel.
if (StopManager.clock == -1) {
sender.sendMessage("" + ChatColor.DARK_RED + ChatColor.BOLD + "ERROR" + ChatColor.RESET + ": The server is not stopping, there is nothing to cancel!");
} else {
// Send a call to the StopManager.initStop() method to cancel the stop.
StopManager.initStop(senderName, -1);
}
} else {
sender.sendMessage("" + ChatColor.DARK_RED + ChatColor.BOLD + "ERROR" + ChatColor.RESET + ": You do not have permission to cancel stopping the server.");
}
return true;
}
// The help command is a simple alias for /serverstopper help
else if (arg1.equalsIgnoreCase("help")) {
Bukkit.dispatchCommand(sender, "serverstopper:serverstopper help");
return true;
}
// For any other command, permission for serverstopper.stop is checked first. I know this seems odd, but it makes for a more efficient workflow.
else if (sender.hasPermission("serverstopper.stop")) {
// The now command will stop the server immediately. This is done by setting the clock in the StopManager class to 0.
if (arg1.equalsIgnoreCase("now") || arg1.equalsIgnoreCase("0")) {
if (sender.hasPermission("serverstopper.stop.now")) {
StopManager.initStop(senderName, 0);
} else {
sender.sendMessage("" + ChatColor.DARK_RED + ChatColor.BOLD + "ERROR" + ChatColor.RESET + ": You do not have permission to stop the server immediately.");
}
return true;
}
// If the first argument is an integer, the server will be scheduled to stop in that many minutes. This is done by multiplying the integer by 60 and setting the clock in the StopManager class to that value.
else if (isInteger(arg1)) {
if (sender.hasPermission("serverstopper.stop.time")) {
int stopTime = Integer.valueOf(arg1) * 60;
// See doInitStop()
doInitStop(sender, senderName, stopTime);
} else {
sender.sendMessage("" + ChatColor.DARK_RED + ChatColor.BOLD + "ERROR" + ChatColor.RESET + ": You do not have permission to stop the server in a custom amount of time.");
}
return true;
}
// If no first argument is provided, the server will be scheduled to stop in one minute. This is done by setting the clock in the StopManager class to 60.
else if (arg1.equalsIgnoreCase("")) {
// See doInitStop()
doInitStop(sender, senderName, 60);
return true;
}
// Error for unknown commands.
else {
sender.sendMessage(ChatColor.translateAlternateColorCodes('&', "&4&lERROR&r: Unknown command."));
return false;
}
} else { // this is the else from the serverstopper.stop permission check way up there. :)
sender.sendMessage("" + ChatColor.DARK_RED + ChatColor.BOLD + "ERROR" + ChatColor.RESET + ": You do not have permission to stop the server.");
return true;
}
}
// This method seems a little redundant, but I felt it was the most effective way to handle the error detailed below.
private static void doInitStop(CommandSender sender, String senderName, int stopTime) {
// If the server is already stopping (this is determined by checking if the clock in StopManager class is any other value than -1), display an error.
if (StopManager.clock != -1) {
sender.sendMessage(ChatColor.translateAlternateColorCodes('&', "&4&lERROR&r: The server is already stopping. If you wish to change the stop perameters, use &b&l/stop cancel&r to cancel the old stop before starting another one."));
} else {
// Send a call to the StopManager.initStop() method to stop the server in the given number of seconds.
StopManager.initStop(senderName, stopTime);
}
}
// This basically does some math to determine if a given string can be safely converted to an integer.
private static boolean isInteger(String s) {
if(s.isEmpty()) return false;
for(int i = 0; i < s.length(); i++) {
if(i == 0 && s.charAt(i) == '-') {
if(s.length() == 1) return false;
else continue;
}
if(Character.digit(s.charAt(i),10) < 0) return false;
}
return true;
}
}

@ -0,0 +1,40 @@
package net.alexmcs.bukkit.serverstopper;
import org.bukkit.event.Listener;
import org.bukkit.plugin.java.JavaPlugin;
/**
* Servertopper
* net.alexmcs.bukkit.serverstopper.MainClass
* Main class for ServerStopper
*/
public class MainClass extends JavaPlugin implements Listener {
// This method is called when the plugin is enabled. (duh!) It registers the commands and does some other cool stuff.
// There is a little bit of processing done here, but much of it is just spitting out information to the console.
@Override
public void onEnable() {
// Set up commands (registration is done in plugin.yml)
this.getCommand("stop").setExecutor(new CommandStop());
this.getCommand("cancelstop").setExecutor(new CommandCancelstop());
this.getCommand("serverstopper").setExecutor(new CommandServerstopper());
// Informational
getLogger().info("Enabled ServerStopper");
getLogger().info("Minecraft ServerStopper v" + getDescription().getVersion());
getLogger().info("for Bukkit/Spigot/Paper");
getLogger().info("ServerStopper replaces Minecraft's /stop command with a better version that warns users before the server shuts down.");
getLogger().info("https://gitlab.com/AlexMCS/ServerStopper");
}
// This method is called when the plugin is disabled. (i.e. when the server is shutting down) I only use it for informational purposes here.
@Override
public void onDisable() {
getLogger().info("The server is shutting down.");
getLogger().info("Thank you for using ServerStopper! Goodbye.");
getLogger().info("Disabled ServerStopper");
}
}

@ -0,0 +1,127 @@
package net.alexmcs.bukkit.serverstopper;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.scheduler.BukkitRunnable;
/**
* Servertopper
* net.alexmcs.bukkit.serverstopper.StopManager
* ServerStopper StopManager class.
* This class is the meat and potatoes of ServerStopper. It does all the heavy lifting, as well as telling users about
* the impending shutdown.
*/
class StopManager {
// Defining some stuff for later use. ;3
static int clock = -1;
private static String broadcastPrefix = "" + ChatColor.GOLD + "[" + ChatColor.DARK_RED + "Broadcast" + ChatColor.GOLD.toString() + "]" + ChatColor.GREEN.toString() + " ";
private static String preNumberTranslation = "" + ChatColor.DARK_RED + ChatColor.BOLD + "ATTENTION: " + ChatColor.GREEN + "The server will be restarting in ";
private static String numberColor = "" + ChatColor.GOLD + ChatColor.BOLD;
private static String resetColor = "" + ChatColor.GREEN;
private static String postNumberTranslation = "" + ChatColor.GREEN + " seconds!";
// The grand finale. https://youtu.be/j0h2u87JwyA (The method that does all the dirty work)
private static void stopLoop() {
// Not really sure why I try wrapped the whole thing. Whatever.
try {
// This loop runs as long as the clock is not "stopped", which is an integer equal to -1.
while (clock != -1) {
switch (clock) {
// Display notifications at certain intervals.
case 3600: // One hour
case 1800: // A half an hour
case 900: // 15 minutes
case 600: // Ten minutes
case 300: // Five minutes
case 60: // One minute
case 30: // Thirty seconds
case 15: // 15 seconds
// IT'S THE FINAL COUNTDOWN! https://youtu.be/9jK-NcRmVcw (lol memes)
case 10: // Ten
case 9: // Nine
case 8: // Eight
case 7: // Seven
case 6: // Six
case 5: // Five
case 4: // Four
case 3: // Three
case 2: // Two
case 1: // One
// At all of the above intervals, call doCountdownBroadcast()
doCountdownBroadcast(clock);
break;
// When the clock strikes 0, stop the server.
case 0:
// Do one last doCountdownBroadcast(), just for old times sake.
doCountdownBroadcast(clock);
// Get back onto the main thread. Accessing the Bukkit API from asynchronous threads is *super dangerous*!
new BukkitRunnable(){
@Override
public void run() {
// Issue the "minecraft:stop" command from the console.
Bukkit.dispatchCommand(Bukkit.getConsoleSender(), "minecraft:stop");
}
}.runTask(Bukkit.getPluginManager().getPlugin("ServerStopper"));
break;
}
// Subtract one from the clock...
clock = clock - 1;
// ... and wait one second before looping again.
Thread.sleep(1000);
}
} catch (InterruptedException ex) {
Thread.currentThread().interrupt();
}
}
// This method is called by the other classes to actually process any operations.
static void initStop(String heWhoStoppedTheServer, int time) {
// If the integer passed for time is -1, the user intended to cancel the pending stop.
if (time == -1) {
if (clock != -1) {
// Tell all server users that the stop was canceled.
Bukkit.broadcastMessage(broadcastPrefix + heWhoStoppedTheServer + resetColor + " has cancelled the server restart. The server will not restart.");
// Cancel the stop. Simply setting the clock to -1 is fine, as this will abort the while loop.
clock = -1;
}
}
// Schedule a server stop.
else {
// Notify all server users that someone has scheduled a stop.
Bukkit.broadcastMessage(broadcastPrefix + heWhoStoppedTheServer + resetColor + " has initiated a server restart. The server will restart in " + numberColor + Integer.toString(time / 60) + resetColor + " minutes.");
// Set the clock to the integer passed for time. This will reflect seconds in real world time.
clock = time;
// We run the while loop asynchronously. This is because we do a lot of Thread.sleep() in order to determine how much real world time has passed. Obviously, doing this on the main thread would hang the server and make it unresponsive.
new BukkitRunnable() {
@Override
public void run() {
// Wait one second
try {
Thread.sleep(1000);
} catch (InterruptedException ex) {
Thread.currentThread().interrupt();
}
// Call the stopLoop() method to get the while loop started.
StopManager.stopLoop();
}
}.runTaskAsynchronously(Bukkit.getPluginManager().getPlugin("ServerStopper"));
}
}
// This simply warns users about the waning remaining time on the clock when called.
static private void doCountdownBroadcast(int time) {
final int remain = time; // Hokey way of dealing with inner-class issue.
// Run this synchronously. It should be safe to access the chat API asynchronously, but better safe than sorry.
new BukkitRunnable(){
@Override
public void run() {
// Do a broadcast. :)
Bukkit.broadcastMessage(broadcastPrefix + preNumberTranslation + numberColor + Integer.toString(remain) + postNumberTranslation);
}
}.runTask(Bukkit.getPluginManager().getPlugin("ServerStopper"));
}
}

@ -0,0 +1,36 @@
name: ServerStopper
version: 1.0a-prerelease1
author: ColtonDRG / AlexMCS
main: net.alexmcs.bukkit.serverstopper.MainClass
website: https://gitlab.com/AlexMCS/ServerStopper/
# Register commands
commands:
stop:
description: Schedule a server shutdown. Use /stop cancel to stop the server from stopping.
usage: /<command> [cancel|now|<minutes>|help]
aliases: [ssstop,restart,reboot,ssrestart,ssreboot]
cancelstop:
description: Same as /stop cancel
usage: /<command>
aliases: [sscancel,sscancelstop,cancelrestart,cancelreboot,sscancelrestart,sscancelreboot]
serverstopper:
description: ServerStopper info, help, or reload
usage: /<command> [info|version|help|reload]
aliases: [ssserverstopper]
# Register default and inherited permissions
permissions:
serverstopper.admin:
default: op
children:
serverstopper.stop: true
serverstopper.cancel: true
serverstopper.stop.time: true
serverstopper.info: true
serverstopper.help: true
serverstopper.reload: true
description: Ops are given serverstopper.admin, which grants all permissions except serverstopper.stop.now.
serverstopper.stop.now:
default: op
description: By default, ops are allowed to stop the server immediately, but those with only serverstopper.admin are not.