Add 1.16 support & Add more syntaxes & Add 1.8-1.12 support back & Remove some syntaxes that are already in vanilla Skript
This commit is contained in:
parent
8610014c18
commit
601228594a
@ -4,6 +4,7 @@
|
|||||||
<root id="archive" name="SkStuff.jar">
|
<root id="archive" name="SkStuff.jar">
|
||||||
<element id="module-output" name="SkStuff" />
|
<element id="module-output" name="SkStuff" />
|
||||||
<element id="module-source" name="SkStuff" />
|
<element id="module-source" name="SkStuff" />
|
||||||
|
<element id="file-copy" path="$PROJECT_DIR$/plugin.yml" />
|
||||||
</root>
|
</root>
|
||||||
</artifact>
|
</artifact>
|
||||||
</component>
|
</component>
|
@ -2,31 +2,69 @@
|
|||||||
<project version="4">
|
<project version="4">
|
||||||
<component name="ChangeListManager">
|
<component name="ChangeListManager">
|
||||||
<list default="true" id="72e0643a-ea45-4e93-b5a5-734a94c41ff5" name="Default Changelist" comment="">
|
<list default="true" id="72e0643a-ea45-4e93-b5a5-734a94c41ff5" name="Default Changelist" comment="">
|
||||||
<change afterPath="$PROJECT_DIR$/src/me/TheBukor/SkStuff/pathfinders/PathfinderGoalFollow_v1_15_R1.java" afterDir="false" />
|
|
||||||
<change beforePath="$PROJECT_DIR$/.gitignore" beforeDir="false" afterPath="$PROJECT_DIR$/.gitignore" afterDir="false" />
|
|
||||||
<change beforePath="$PROJECT_DIR$/.idea/$PRODUCT_WORKSPACE_FILE$" beforeDir="false" />
|
|
||||||
<change beforePath="$PROJECT_DIR$/.idea/artifacts/SkStuff_jar.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/artifacts/SkStuff_jar.xml" afterDir="false" />
|
<change beforePath="$PROJECT_DIR$/.idea/artifacts/SkStuff_jar.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/artifacts/SkStuff_jar.xml" afterDir="false" />
|
||||||
<change beforePath="$PROJECT_DIR$/.idea/dictionaries/Govindas.xml" beforeDir="false" />
|
|
||||||
<change beforePath="$PROJECT_DIR$/.idea/uiDesigner.xml" beforeDir="false" />
|
|
||||||
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
|
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
|
||||||
<change beforePath="$PROJECT_DIR$/SkStuff.iml" beforeDir="false" afterPath="$PROJECT_DIR$/SkStuff.iml" afterDir="false" />
|
<change beforePath="$PROJECT_DIR$/SkStuff.iml" beforeDir="false" afterPath="$PROJECT_DIR$/SkStuff.iml" afterDir="false" />
|
||||||
<change beforePath="$PROJECT_DIR$/bin/me/TheBukor/SkStuff/effects/EffSetPathGoal.class" beforeDir="false" afterPath="$PROJECT_DIR$/bin/me/TheBukor/SkStuff/effects/EffSetPathGoal.class" afterDir="false" />
|
<change beforePath="$PROJECT_DIR$/bin/META-INF/SkStuff.kotlin_module" beforeDir="false" afterPath="$PROJECT_DIR$/bin/META-INF/SkStuff.kotlin_module" afterDir="false" />
|
||||||
<change beforePath="$PROJECT_DIR$/out/artifacts/SkStuff_jar/SkStuff.jar" beforeDir="false" afterPath="$PROJECT_DIR$/out/artifacts/SkStuff_jar/SkStuff.jar" afterDir="false" />
|
<change beforePath="$PROJECT_DIR$/bin/me/TheBukor/SkStuff/SkStuff$1.class" beforeDir="false" />
|
||||||
<change beforePath="$PROJECT_DIR$/src/META-INF/MANIFEST.MF" beforeDir="false" />
|
<change beforePath="$PROJECT_DIR$/bin/me/TheBukor/SkStuff/SkStuff.class" beforeDir="false" afterPath="$PROJECT_DIR$/bin/me/TheBukor/SkStuff/SkStuff.class" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/bin/me/TheBukor/SkStuff/effects/EffResourceSound.class" beforeDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/bin/me/TheBukor/SkStuff/effects/EffShowEntityEffect.class" beforeDir="false" afterPath="$PROJECT_DIR$/bin/me/TheBukor/SkStuff/effects/EffShowEntityEffect.class" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/bin/me/TheBukor/SkStuff/expressions/ExprClickedInventory.class" beforeDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/bin/me/TheBukor/SkStuff/pathfinders/PathfinderGoalFollow_v1_13_R2.class" beforeDir="false" afterPath="$PROJECT_DIR$/bin/me/TheBukor/SkStuff/pathfinders/PathfinderGoalFollow_v1_13_R2.class" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/bin/me/TheBukor/SkStuff/util/NMSInterface.class" beforeDir="false" afterPath="$PROJECT_DIR$/bin/me/TheBukor/SkStuff/util/NMSInterface.class" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/bin/me/TheBukor/SkStuff/util/NMS_v1_13_R2.class" beforeDir="false" afterPath="$PROJECT_DIR$/bin/me/TheBukor/SkStuff/util/NMS_v1_13_R2.class" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/bin/me/TheBukor/SkStuff/util/NMS_v1_14_R1.class" beforeDir="false" afterPath="$PROJECT_DIR$/bin/me/TheBukor/SkStuff/util/NMS_v1_14_R1.class" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/bin/me/TheBukor/SkStuff/util/NMS_v1_15_R1.class" beforeDir="false" afterPath="$PROJECT_DIR$/bin/me/TheBukor/SkStuff/util/NMS_v1_15_R1.class" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/bin/org/mcstats/Metrics$1.class" beforeDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/bin/org/mcstats/Metrics$Graph.class" beforeDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/bin/org/mcstats/Metrics$Plotter.class" beforeDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/bin/org/mcstats/Metrics.class" beforeDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/plugin.yml" beforeDir="false" afterPath="$PROJECT_DIR$/plugin.yml" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/src/me/TheBukor/SkStuff/SkStuff.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/me/TheBukor/SkStuff/SkStuff.java" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/src/me/TheBukor/SkStuff/effects/EffGZipFile.java" beforeDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/src/me/TheBukor/SkStuff/effects/EffResourceSound.java" beforeDir="false" />
|
||||||
<change beforePath="$PROJECT_DIR$/src/me/TheBukor/SkStuff/effects/EffSetPathGoal.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/me/TheBukor/SkStuff/effects/EffSetPathGoal.java" afterDir="false" />
|
<change beforePath="$PROJECT_DIR$/src/me/TheBukor/SkStuff/effects/EffSetPathGoal.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/me/TheBukor/SkStuff/effects/EffSetPathGoal.java" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/src/me/TheBukor/SkStuff/effects/EffShowEntityEffect.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/me/TheBukor/SkStuff/effects/EffShowEntityEffect.java" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/src/me/TheBukor/SkStuff/expressions/ExprClickedInventory.java" beforeDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/src/me/TheBukor/SkStuff/expressions/ExprGlideState.java" beforeDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/src/me/TheBukor/SkStuff/expressions/ExprInventoryOwner.java" beforeDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/src/me/TheBukor/SkStuff/expressions/ExprNoGravityState.java" beforeDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/src/me/TheBukor/SkStuff/expressions/ExprTimespanToNumber.java" beforeDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/src/me/TheBukor/SkStuff/expressions/ExprToLowerCase.java" beforeDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/src/me/TheBukor/SkStuff/expressions/ExprToUpperCase.java" beforeDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/src/me/TheBukor/SkStuff/expressions/ExprWordsToUpperCase.java" beforeDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/src/me/TheBukor/SkStuff/pathfinders/PathfinderGoalFollow_v1_13_R2.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/me/TheBukor/SkStuff/pathfinders/PathfinderGoalFollow_v1_13_R2.java" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/src/me/TheBukor/SkStuff/util/NMSInterface.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/me/TheBukor/SkStuff/util/NMSInterface.java" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/src/me/TheBukor/SkStuff/util/NMS_v1_13_R2.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/me/TheBukor/SkStuff/util/NMS_v1_13_R2.java" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/src/me/TheBukor/SkStuff/util/NMS_v1_14_R1.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/me/TheBukor/SkStuff/util/NMS_v1_14_R1.java" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/src/me/TheBukor/SkStuff/util/NMS_v1_15_R1.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/me/TheBukor/SkStuff/util/NMS_v1_15_R1.java" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/src/org/mcstats/Metrics.java" beforeDir="false" />
|
||||||
</list>
|
</list>
|
||||||
<option name="SHOW_DIALOG" value="false" />
|
<option name="SHOW_DIALOG" value="false" />
|
||||||
<option name="HIGHLIGHT_CONFLICTS" value="true" />
|
<option name="HIGHLIGHT_CONFLICTS" value="true" />
|
||||||
<option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
|
<option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
|
||||||
<option name="LAST_RESOLUTION" value="IGNORE" />
|
<option name="LAST_RESOLUTION" value="IGNORE" />
|
||||||
</component>
|
</component>
|
||||||
|
<component name="FileTemplateManagerImpl">
|
||||||
|
<option name="RECENT_TEMPLATES">
|
||||||
|
<list>
|
||||||
|
<option value="Class" />
|
||||||
|
</list>
|
||||||
|
</option>
|
||||||
|
</component>
|
||||||
|
<component name="Git.Settings">
|
||||||
|
<option name="RECENT_GIT_ROOT_PATH" value="$PROJECT_DIR$" />
|
||||||
|
</component>
|
||||||
|
<component name="ProjectId" id="1dDc5mH6vdHCfDtdCWF3TtPitSZ" />
|
||||||
<component name="ProjectViewState">
|
<component name="ProjectViewState">
|
||||||
<option name="showExcludedFiles" value="true" />
|
<option name="showExcludedFiles" value="true" />
|
||||||
<option name="showLibraryContents" value="true" />
|
<option name="showLibraryContents" value="true" />
|
||||||
</component>
|
</component>
|
||||||
<component name="PropertiesComponent">
|
<component name="PropertiesComponent">
|
||||||
|
<property name="ASKED_ADD_EXTERNAL_FILES" value="true" />
|
||||||
<property name="RunOnceActivity.ShowReadmeOnStart" value="true" />
|
<property name="RunOnceActivity.ShowReadmeOnStart" value="true" />
|
||||||
<property name="last_opened_file_path" value="$PROJECT_DIR$/../../import/Skript 2.3.7.jar!/" />
|
<property name="last_opened_file_path" value="$PROJECT_DIR$/plugin.yml" />
|
||||||
<property name="project.structure.last.edited" value="Artifacts" />
|
<property name="project.structure.last.edited" value="Artifacts" />
|
||||||
<property name="project.structure.proportion" value="0.15" />
|
<property name="project.structure.proportion" value="0.15" />
|
||||||
<property name="project.structure.side.proportion" value="0.2" />
|
<property name="project.structure.side.proportion" value="0.2" />
|
||||||
@ -34,8 +72,12 @@
|
|||||||
<component name="RecentsManager">
|
<component name="RecentsManager">
|
||||||
<key name="CopyClassDialog.RECENTS_KEY">
|
<key name="CopyClassDialog.RECENTS_KEY">
|
||||||
<recent name="me.TheBukor.SkStuff.pathfinders" />
|
<recent name="me.TheBukor.SkStuff.pathfinders" />
|
||||||
|
<recent name="me.TheBukor.SkStuff.util" />
|
||||||
</key>
|
</key>
|
||||||
</component>
|
</component>
|
||||||
|
<component name="SQLPlugin.ProjectConfiguration">
|
||||||
|
<queries />
|
||||||
|
</component>
|
||||||
<component name="ServiceViewManager">
|
<component name="ServiceViewManager">
|
||||||
<option name="viewStates">
|
<option name="viewStates">
|
||||||
<list>
|
<list>
|
||||||
@ -62,17 +104,32 @@
|
|||||||
<servers />
|
<servers />
|
||||||
</component>
|
</component>
|
||||||
<component name="WindowStateProjectService">
|
<component name="WindowStateProjectService">
|
||||||
<state x="524" y="109" key="#com.intellij.openapi.roots.ui.configuration.libraryEditor.LibraryEditorDialog" timestamp="1578912712598">
|
<state x="79" y="101" key="FileChooserDialogImpl" timestamp="1595328182010">
|
||||||
<screen x="0" y="0" width="1366" height="728" />
|
<screen x="0" y="0" width="1366" height="728" />
|
||||||
</state>
|
</state>
|
||||||
<state x="524" y="109" key="#com.intellij.openapi.roots.ui.configuration.libraryEditor.LibraryEditorDialog/0.0.1366.728@0.0.1366.728" timestamp="1578912712598" />
|
<state x="79" y="101" key="FileChooserDialogImpl/0.0.1366.728@0.0.1366.728" timestamp="1595328182010" />
|
||||||
<state x="242" y="54" key="FileChooserDialogImpl" timestamp="1578912928696">
|
<state x="348" y="62" key="NewModule_or_Project.wizard" timestamp="1592831160031">
|
||||||
<screen x="0" y="0" width="1366" height="728" />
|
<screen x="0" y="0" width="1366" height="728" />
|
||||||
</state>
|
</state>
|
||||||
<state x="242" y="54" key="FileChooserDialogImpl/0.0.1366.728@0.0.1366.728" timestamp="1578912928696" />
|
<state x="348" y="62" key="NewModule_or_Project.wizard/0.0.1366.728@0.0.1366.728" timestamp="1592831160031" />
|
||||||
<state x="174" y="0" key="SettingsEditor" timestamp="1578913041185">
|
<state x="163" y="0" key="SettingsEditor" timestamp="1595328184010">
|
||||||
<screen x="0" y="0" width="1366" height="728" />
|
<screen x="0" y="0" width="1366" height="728" />
|
||||||
</state>
|
</state>
|
||||||
<state x="174" y="0" key="SettingsEditor/0.0.1366.728@0.0.1366.728" timestamp="1578913041185" />
|
<state x="163" y="0" key="SettingsEditor/0.0.1366.728@0.0.1366.728" timestamp="1595328184010" />
|
||||||
|
<state x="0" y="0" key="com.intellij.ide.util.TipDialog" timestamp="1592831111181">
|
||||||
|
<screen x="0" y="0" width="1366" height="728" />
|
||||||
|
</state>
|
||||||
|
<state x="0" y="0" key="com.intellij.ide.util.TipDialog/0.0.1366.728@0.0.1366.728" timestamp="1592831111181" />
|
||||||
|
</component>
|
||||||
|
<component name="XDebuggerManager">
|
||||||
|
<breakpoint-manager>
|
||||||
|
<breakpoints>
|
||||||
|
<line-breakpoint enabled="true" type="java-line">
|
||||||
|
<url>jar://$PROJECT_DIR$/../../import/craftbukkit-1.13.2.jar!/net/minecraft/server/v1_13_R2/NavigationAbstract.class</url>
|
||||||
|
<line>178</line>
|
||||||
|
<option name="timeStamp" value="1" />
|
||||||
|
</line-breakpoint>
|
||||||
|
</breakpoints>
|
||||||
|
</breakpoint-manager>
|
||||||
</component>
|
</component>
|
||||||
</project>
|
</project>
|
88
SkStuff.iml
88
SkStuff.iml
@ -67,5 +67,93 @@
|
|||||||
<SOURCES />
|
<SOURCES />
|
||||||
</library>
|
</library>
|
||||||
</orderEntry>
|
</orderEntry>
|
||||||
|
<orderEntry type="module-library">
|
||||||
|
<library>
|
||||||
|
<CLASSES>
|
||||||
|
<root url="jar://$MODULE_DIR$/../../import/craftbukkit-1.12.2.jar!/" />
|
||||||
|
</CLASSES>
|
||||||
|
<JAVADOC />
|
||||||
|
<SOURCES>
|
||||||
|
<root url="jar://$MODULE_DIR$/../../import/craftbukkit-1.12.2.jar!/" />
|
||||||
|
</SOURCES>
|
||||||
|
</library>
|
||||||
|
</orderEntry>
|
||||||
|
<orderEntry type="module-library">
|
||||||
|
<library>
|
||||||
|
<CLASSES>
|
||||||
|
<root url="jar://$MODULE_DIR$/../../import/craftbukkit-1.11.2.jar!/" />
|
||||||
|
</CLASSES>
|
||||||
|
<JAVADOC />
|
||||||
|
<SOURCES>
|
||||||
|
<root url="jar://$MODULE_DIR$/../../import/craftbukkit-1.11.2.jar!/" />
|
||||||
|
</SOURCES>
|
||||||
|
</library>
|
||||||
|
</orderEntry>
|
||||||
|
<orderEntry type="module-library">
|
||||||
|
<library>
|
||||||
|
<CLASSES>
|
||||||
|
<root url="jar://$MODULE_DIR$/../../import/craftbukkit-1.10.2-R0.1-SNAPSHOT-latest.jar!/" />
|
||||||
|
</CLASSES>
|
||||||
|
<JAVADOC />
|
||||||
|
<SOURCES>
|
||||||
|
<root url="jar://$MODULE_DIR$/../../import/craftbukkit-1.10.2-R0.1-SNAPSHOT-latest.jar!/" />
|
||||||
|
</SOURCES>
|
||||||
|
</library>
|
||||||
|
</orderEntry>
|
||||||
|
<orderEntry type="module-library">
|
||||||
|
<library>
|
||||||
|
<CLASSES>
|
||||||
|
<root url="jar://$MODULE_DIR$/../../import/craftbukkit-1.9.4-R0.1-SNAPSHOT-latest.jar!/" />
|
||||||
|
</CLASSES>
|
||||||
|
<JAVADOC />
|
||||||
|
<SOURCES>
|
||||||
|
<root url="jar://$MODULE_DIR$/../../import/craftbukkit-1.9.4-R0.1-SNAPSHOT-latest.jar!/" />
|
||||||
|
</SOURCES>
|
||||||
|
</library>
|
||||||
|
</orderEntry>
|
||||||
|
<orderEntry type="module-library">
|
||||||
|
<library>
|
||||||
|
<CLASSES>
|
||||||
|
<root url="jar://$MODULE_DIR$/../../import/craftbukkit-1.8.8-R0.1-SNAPSHOT-latest.jar!/" />
|
||||||
|
</CLASSES>
|
||||||
|
<JAVADOC />
|
||||||
|
<SOURCES>
|
||||||
|
<root url="jar://$MODULE_DIR$/../../import/craftbukkit-1.8.8-R0.1-SNAPSHOT-latest.jar!/" />
|
||||||
|
</SOURCES>
|
||||||
|
</library>
|
||||||
|
</orderEntry>
|
||||||
|
<orderEntry type="module-library">
|
||||||
|
<library>
|
||||||
|
<CLASSES>
|
||||||
|
<root url="jar://$MODULE_DIR$/../../import/craftbukkit-1.9.2-R0.1-SNAPSHOT-latest.jar!/" />
|
||||||
|
</CLASSES>
|
||||||
|
<JAVADOC />
|
||||||
|
<SOURCES>
|
||||||
|
<root url="jar://$MODULE_DIR$/../../import/craftbukkit-1.9.2-R0.1-SNAPSHOT-latest.jar!/" />
|
||||||
|
</SOURCES>
|
||||||
|
</library>
|
||||||
|
</orderEntry>
|
||||||
|
<orderEntry type="module-library">
|
||||||
|
<library>
|
||||||
|
<CLASSES>
|
||||||
|
<root url="jar://$MODULE_DIR$/../../import/craftbukkit-1.15.2.jar!/" />
|
||||||
|
</CLASSES>
|
||||||
|
<JAVADOC />
|
||||||
|
<SOURCES>
|
||||||
|
<root url="jar://$MODULE_DIR$/../../import/craftbukkit-1.15.2.jar!/" />
|
||||||
|
</SOURCES>
|
||||||
|
</library>
|
||||||
|
</orderEntry>
|
||||||
|
<orderEntry type="module-library">
|
||||||
|
<library>
|
||||||
|
<CLASSES>
|
||||||
|
<root url="jar://$MODULE_DIR$/../../import/craftbukkit-1.16.1.jar!/" />
|
||||||
|
</CLASSES>
|
||||||
|
<JAVADOC />
|
||||||
|
<SOURCES>
|
||||||
|
<root url="jar://$MODULE_DIR$/../../import/craftbukkit-1.16.1.jar!/" />
|
||||||
|
</SOURCES>
|
||||||
|
</library>
|
||||||
|
</orderEntry>
|
||||||
</component>
|
</component>
|
||||||
</module>
|
</module>
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -1,6 +1,6 @@
|
|||||||
name: SkStuff
|
name: SkPathfinderGoals
|
||||||
author: [TheBukor, Govindas]
|
authors: [TheBukor, Govindas]
|
||||||
description: A Skript addon which adds extra functionalities such as pathfinder goals.
|
description: A Skript addon which adds extra functionalities such as pathfinder goals.
|
||||||
version: 1.7.0-fork-1.13-1.15
|
version: "2.0"
|
||||||
main: me.TheBukor.SkStuff.SkStuff
|
main: me.TheBukor.SkStuff.SkStuff
|
||||||
softdepend: [Skript]
|
softdepend: [Skript]
|
@ -5,6 +5,7 @@ import ch.njol.skript.lang.ExpressionType;
|
|||||||
import ch.njol.skript.lang.util.SimpleEvent;
|
import ch.njol.skript.lang.util.SimpleEvent;
|
||||||
import ch.njol.skript.registrations.EventValues;
|
import ch.njol.skript.registrations.EventValues;
|
||||||
import ch.njol.skript.util.Getter;
|
import ch.njol.skript.util.Getter;
|
||||||
|
import me.TheBukor.SkStuff.bstats.Metrics;
|
||||||
import me.TheBukor.SkStuff.effects.*;
|
import me.TheBukor.SkStuff.effects.*;
|
||||||
import me.TheBukor.SkStuff.expressions.*;
|
import me.TheBukor.SkStuff.expressions.*;
|
||||||
import me.TheBukor.SkStuff.util.*;
|
import me.TheBukor.SkStuff.util.*;
|
||||||
@ -13,7 +14,6 @@ import org.bukkit.entity.Entity;
|
|||||||
import org.bukkit.event.entity.EntityToggleGlideEvent;
|
import org.bukkit.event.entity.EntityToggleGlideEvent;
|
||||||
import org.bukkit.inventory.Inventory;
|
import org.bukkit.inventory.Inventory;
|
||||||
import org.bukkit.plugin.java.JavaPlugin;
|
import org.bukkit.plugin.java.JavaPlugin;
|
||||||
import org.mcstats.Metrics;
|
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@ -31,66 +31,24 @@ public class SkStuff extends JavaPlugin {
|
|||||||
public void onEnable() {
|
public void onEnable() {
|
||||||
if (Bukkit.getPluginManager().getPlugin("Skript") != null && Skript.isAcceptRegistrations()) {
|
if (Bukkit.getPluginManager().getPlugin("Skript") != null && Skript.isAcceptRegistrations()) {
|
||||||
Skript.registerAddon(this);
|
Skript.registerAddon(this);
|
||||||
getLogger().info("SkStuff " + this.getDescription().getVersion() + " has been successfully enabled!");
|
getLogger().info("SkPathfinderGoals " + this.getDescription().getVersion() + " has been successfully enabled!");
|
||||||
getLogger().info("Registering general non version specific stuff...");
|
getLogger().info("Registering general non version specific stuff...");
|
||||||
Skript.registerEffect(EffShowEntityEffect.class, "(display|play|show) entity effect (0¦firework[s] explo(de|sion)|1¦hurt|2¦[[iron] golem] (give|offer) (rose|poppy)|3¦[sheep] eat grass|4¦wolf shake) at %entity%");
|
Skript.registerEffect(EffShowEntityEffect.class, "(display|play|show) entity effect (0¦firework[s] explo(de|sion)|1¦hurt|2¦[[iron] golem] (give|offer) (rose|poppy)|3¦[sheep] eat grass|4¦wolf shake|5¦squid rotate|6¦totem resurrect|7¦rabbit jump) (at|on) %entity%");
|
||||||
Skript.registerExpression(ExprToUpperCase.class, String.class, ExpressionType.SIMPLE, "%string% [converted] to [all] (cap[ital]s|upper[ ]case)", "convert %string% to [all] (cap[ital]s|upper[ ]case)", "capitalize [all] [char[acter]s (of|in)] %string%");
|
|
||||||
Skript.registerExpression(ExprToLowerCase.class, String.class, ExpressionType.SIMPLE, "%string% [converted] to [all] lower[ ]case", "convert %string% to [all] lower[ ]case", "un[( |-)]capitalize [all] [char[acter]s (of|in)] %string%");
|
|
||||||
Skript.registerExpression(ExprWordsToUpperCase.class, String.class, ExpressionType.SIMPLE, "(first|1st) (letter|char[acter]) (of|in) (each word|[all] words) (of|in) %string% [converted] to (cap[ital]s|upper[ ]case) (0¦|1¦ignoring [other] upper[ ]case [(char[acter]s|letters)])", "convert (first|1st) (letter|char[acter]) (of|in) (each word|[all] words) (of|in) %string% to (cap[ital]s|upper[ ]case) (0¦|1¦ignoring [other] upper[ ]case [(char[acter]s|letters)])", "capitalize (first|1st) (letter|char[acter]) (of|in) (each word|[all] words) (of|in) %string% (0¦|1¦ignoring [other] upper[ ]case [(char[acter]s|letters)])");
|
|
||||||
Skript.registerExpression(ExprTimespanToNumber.class, Number.class, ExpressionType.SIMPLE, "%timespan% [converted] [in]to (0¦ticks|1¦sec[ond]s|2¦min[ute]s|3¦hours|4¦days)");
|
|
||||||
Skript.registerExpression(ExprClickedInventory.class, Inventory.class, ExpressionType.SIMPLE, "[skstuff] clicked inventory");
|
|
||||||
Skript.registerExpression(ExprInventoryOwner.class, Object.class, ExpressionType.PROPERTY, "[inventory] (owner|holder) of %inventory%", "%inventory%'s [inventory] (owner|holder)");
|
|
||||||
effAmount += 1;
|
|
||||||
exprAmount += 6;
|
|
||||||
if (Skript.isRunningMinecraft(1, 9)) {
|
|
||||||
Skript.registerEffect(EffResourceSound.class, "play [raw] [([resource[ ]]pack)] sound %string% (for|to) %players% at %location% [[with] volume %-number%[[(,| and)] pitch %-number%]]", "play [raw] [([resource[ ]]pack)] sound %string% for %players% at %location% [[with] pitch %-number%[[(,| and)] volume %-number%]]");
|
|
||||||
Skript.registerEvent("Elytra glide toggle", SimpleEvent.class, EntityToggleGlideEvent.class, "[entity] elytra (fl(y|ight)|glid(e|ing)) toggl(e|ing)", "[entity] toggle elytra (fl(y|ight)|glid(e|ing))");
|
|
||||||
Skript.registerExpression(ExprGlideState.class, Boolean.class, ExpressionType.PROPERTY, "elytra (fl(y|ight)|glid(e|ing)) state of %livingentity%", "%livingentity%'s elytra (fl(y|ight)|glid(e|ing)) state");
|
|
||||||
//Skript.registerExpression(ExprPlayerChargeTime.class, Float.class, ExpressionType.PROPERTY, "blah of %player%", "%player%'s blah");
|
|
||||||
//Increase exprAmount when I uncomment this
|
|
||||||
EventValues.registerEventValue(EntityToggleGlideEvent.class, Entity.class, new Getter<Entity, EntityToggleGlideEvent>() {
|
|
||||||
@Override
|
|
||||||
@Nullable
|
|
||||||
public Entity get(EntityToggleGlideEvent e) {
|
|
||||||
return e.getEntity();
|
|
||||||
}
|
|
||||||
}, 0);
|
|
||||||
effAmount += 1;
|
|
||||||
evtAmount += 1;
|
|
||||||
exprAmount += 1;
|
|
||||||
if (Skript.isRunningMinecraft(1, 10)) {
|
|
||||||
Skript.registerExpression(ExprNoGravityState.class, Boolean.class, ExpressionType.PROPERTY, "no gravity (state|mode) of %entities%", "%entities%'s no gravity (state|mode)");
|
|
||||||
exprAmount += 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (setupNMSVersion()) {
|
if (setupNMSVersion()) {
|
||||||
getLogger().info("Trying to register version specific stuff...");
|
getLogger().info("Trying to register version specific stuff...");
|
||||||
|
Skript.registerExpression(ExprStepLength.class, Number.class, ExpressionType.PROPERTY, "[the] step length of %entity%", "%entity%'s step length");
|
||||||
Skript.registerEffect(EffClearPathGoals.class, "(clear|delete) [all] pathfind[er] goals (of|from) %livingentities%");
|
Skript.registerEffect(EffClearPathGoals.class, "(clear|delete) [all] pathfind[er] goals (of|from) %livingentities%");
|
||||||
Skript.registerEffect(EffRemovePathGoal.class, "remove pathfind[er] goal (0¦(avoid|run away from) entit(y|ies)|1¦break door[s]|2¦breed|3¦eat grass|4¦(flee from the sun|seek shad(e|ow))|5¦float (in[side]|on) water|6¦follow (owner|tamer)|7¦follow (adult|parent)[s]|8¦(fight back|react to|target) (damager|attacker)|9¦o(c|z)elot jump on blocks|10¦leap at target|11¦look at entit(y|ies)|12¦melee attack entit(y|ies)|13¦move to[wards] target|14¦target nearest entity|15¦o(c|z)elot attack [chicken[s]]|16¦open door[s]|17¦(panic|flee)|18¦look around randomly|19¦(walk around randomly|wander)|20¦sit|21¦[creeper] (explode|inflate|swell)|22¦squid (swim|wander)|23¦shoot fireball[s]|24¦[silverfish] hide (in[side]|on) block[s]|25¦(wake other silverfish[es]|[silverfish] call (help|reinforcement|other [hidden] silverfish[es]))|26¦[enderm(a|e)n] pick[[ ]up] block[s]|27¦[enderm(a|e)n] place block[s]|28¦[enderman] attack player (staring|looking) [at eye[s]]|29¦ghast move to[wards] target|30¦ghast (idle move[ment]|wander|random fl(ight|y[ing]))|31¦(tempt to|follow players (holding|with)) [a[n]] item|32¦target [random] entity (if|when) (not tamed|untamed)|33¦guardian attack [entity]|34¦[z[ombie[ ]]pig[man]] attack [player[s]] (if|when) angry|35¦[z[ombie[ ]]pig[man]] (react to|fight back|target) (attacker|damager) (if|when) angry|36¦[rabbit] eat carrot crops|37¦[killer] rabbit [melee] attack|38¦slime [random] jump|39¦slime change (direction|facing) randomly|40¦slime (idle move[ment]|wander)|41¦follow [entity]|42¦bow shoot) from %livingentities%");
|
Skript.registerEffect(EffRemovePathGoal.class, "remove pathfind[er] goal (0¦(avoid|run away from) entit(y|ies)|1¦break door[s]|2¦breed|3¦eat grass|4¦(flee from the sun|seek shad(e|ow))|5¦float (in[side]|on) water|6¦follow (owner|tamer)|7¦follow (adult|parent)[s]|8¦(fight back|react to|target) (damager|attacker)|9¦o(c|z)elot jump on blocks|10¦leap at target|11¦look at entit(y|ies)|12¦melee attack entit(y|ies)|13¦move to[wards] target|14¦target nearest entity|15¦o(c|z)elot attack [chicken[s]]|16¦open door[s]|17¦(panic|flee)|18¦look around randomly|19¦(walk around randomly|wander)|20¦sit|21¦[creeper] (explode|inflate|swell)|22¦squid (swim|wander)|23¦shoot fireball[s]|24¦[silverfish] hide (in[side]|on) block[s]|25¦(wake other silverfish[es]|[silverfish] call (help|reinforcement|other [hidden] silverfish[es]))|26¦[enderm(a|e)n] pick[[ ]up] block[s]|27¦[enderm(a|e)n] place block[s]|28¦[enderman] attack player (staring|looking) [at eye[s]]|29¦ghast move to[wards] target|30¦ghast (idle move[ment]|wander|random fl(ight|y[ing]))|31¦(tempt to|follow players (holding|with)) [a[n]] item|32¦target [random] entity (if|when) (not tamed|untamed)|33¦guardian attack [entity]|34¦[z[ombie[ ]]pig[man]] attack [player[s]] (if|when) angry|35¦[z[ombie[ ]]pig[man]] (react to|fight back|target) (attacker|damager) (if|when) angry|36¦[rabbit] eat carrot crops|37¦[killer] rabbit [melee] attack|38¦slime [random] jump|39¦slime change (direction|facing) randomly|40¦slime (idle move[ment]|wander)|41¦follow [entity]|42¦bow shoot) from %livingentities%");
|
||||||
// Note to self: whenever adding a new pathfinder goal, increase the expression index for 'entities' in EffSetPathGoal
|
// Note to self: whenever adding a new pathfinder goal, increase the expression index for 'entities' in EffSetPathGoal
|
||||||
Skript.registerEffect(EffSetPathGoal.class, "add pathfind[er] goal [[with] priority %-integer%] (0¦(avoid|run away from) %*entitydatas%[, radius %-number%[, speed %-number%[, speed (if|when) (close|near) %-number%]]]|1¦break door[s]|2¦breed[,[move[ment]] speed %-number%]|3¦eat grass|4¦(flee from the sun|seek shad(e|ow))[, [move[ment]] speed %-number%]|5¦(float (in[side]|on) water|swim)|6¦follow (owner|tamer)[, speed %-number%[, min[imum] distance %-number%[, max[imum] distance %-number%]]]|7¦follow (adult|parent)[s][, [move[ment]] speed %-number%]|8¦(fight back|react to|target) (damager|attacker) [[of] type] %*entitydatas%[, call ([for] help|reinforcement) %-boolean%]|9¦o(c|z)elot jump on blocks[, [move[ment]] speed %-number%]|10¦leap at target[, [leap] height %-number%]|11¦look at %*entitydatas%[, (radius|max[imum] distance) %-number%]|12¦melee attack %*entitydatas%[, [move[ment]] speed %-number%[, (memorize|do('nt| not) forget) target [for [a] long[er] time] %-boolean%]]|13¦move to[wards] target[, [move[ment]] speed %-number%[, (radius|max[imum] distance) %-number%]]|14¦target nearest [entity [of] type] %*entitydatas%[, check sight %-boolean%]|15¦o(c|z)elot attack|16¦open door[s]|17¦(panic|flee)[, [move[ment]] speed %-number%]|18¦look around randomly|19¦(walk around randomly|wander)[, [move[ment]] speed %-number%[, min[imum] [of] %-timespan% between mov(e[ment][s]|ing)]]|20¦sit|21¦[creeper] (explode|inflate|swell)|22¦squid (swim around|wander)|23¦shoot fireball[s]|24¦[silverfish] hide (in[side]|on) block[s]|25¦((call|summon|wake) [other] [hidden] silverfish[es])|26¦[enderman] pick[[ ]up] block[s]|27¦[enderman] place block[s]|28¦[enderman] attack player (staring|looking) at [their] eye[s]]|29¦ghast move to[wards] target|30¦ghast (idle move[ment]|wander|random fl(ight|y[ing]))|31¦(tempt to|follow players (holding|with)) %-itemstack%[, [move[ment]] speed %number%[, scared of player movement %-boolean%]]|32¦target [random] %*entitydatas% (if|when) (not |un)tamed|33¦guardian attack [entities]|34¦[z[ombie[ ]]pig[man]] attack [player[s]] (if|when) angry|35¦[z[ombie[ ]]pig[man]] (react to|fight back|target) (attacker|damager) (if|when) angry|36¦[rabbit] eat carrot crops|37¦[killer] rabbit [melee] attack|38¦slime [random] jump|39¦slime change (direction|facing) randomly|40¦slime (idle move[ment]|wander)|41¦follow %*entitydatas%[, radius %-number%[, speed %-number%[, [custom[ ]]name[d] %-string%]]]|42¦bow shoot[, [move[ment]] speed %-number%[, unk[nown] param[eter] %-number%[, follow range %-number%]]])) to %livingentities%");
|
Skript.registerEffect(EffSetPathGoal.class, "add pathfind[er] goal [[with] priority %-integer%] (0¦(avoid|run away from) %*entitydatas%[, radius %-number%[, speed %-number%[, speed (if|when) (close|near) %-number%]]]|1¦break door[s]|2¦breed[,[move[ment]] speed %-number%]|3¦eat grass|4¦(flee from the sun|seek shad(e|ow))[, [move[ment]] speed %-number%]|5¦(float (in[side]|on) water|swim)|6¦follow (owner|tamer)[, speed %-number%[, min[imum] distance %-number%[, max[imum] distance %-number%]]]|7¦follow (adult|parent)[s][, [move[ment]] speed %-number%]|8¦(fight back|react to|target) (damager|attacker) [[of] type] %*entitydatas%[, call ([for] help|reinforcement) %-boolean%]|9¦o(c|z)elot jump on blocks[, [move[ment]] speed %-number%]|10¦leap at target[, [leap] height %-number%]|11¦look at %*entitydatas%[, (radius|max[imum] distance) %-number%]|12¦melee attack %*entitydatas%[, [move[ment]] speed %-number%[, (memorize|do('nt| not) forget) target [for [a] long[er] time] %-boolean%]]|13¦move to[wards] target[, [move[ment]] speed %-number%[, (radius|max[imum] distance) %-number%]]|14¦target nearest [entity [of] type] %*entitydatas%[, check sight %-boolean%]|15¦o(c|z)elot attack|16¦open door[s]|17¦(panic|flee)[, [move[ment]] speed %-number%]|18¦look around randomly|19¦(walk around randomly|wander)[, [move[ment]] speed %-number%[, min[imum] [of] %-timespan% between mov(e[ment][s]|ing)]]|20¦sit|21¦[creeper] (explode|inflate|swell)|22¦squid (swim around|wander)|23¦shoot fireball[s]|24¦[silverfish] hide (in[side]|on) block[s]|25¦((call|summon|wake) [other] [hidden] silverfish[es])|26¦[enderman] pick[[ ]up] block[s]|27¦[enderman] place block[s]|28¦[enderman] attack player (staring|looking) at [their] eye[s]]|29¦ghast move to[wards] target|30¦ghast (idle move[ment]|wander|random fl(ight|y[ing]))|31¦(tempt to|follow players (holding|with)) %-itemstack%[, [move[ment]] speed %number%[, scared of player movement %-boolean%]]|32¦target [random] %*entitydatas% (if|when) (not |un)tamed|33¦guardian attack [entities]|34¦[z[ombie[ ]]pig[man]] attack [player[s]] (if|when) angry|35¦[z[ombie[ ]]pig[man]] (react to|fight back|target) (attacker|damager) (if|when) angry|36¦[rabbit] eat carrot crops|37¦[killer] rabbit [melee] attack|38¦slime [random] jump|39¦slime change (direction|facing) randomly|40¦slime (idle move[ment]|wander)|41¦follow %*entitydatas%[, radius %-number%[, speed %-number%[, [custom[ ]]name[d] %-string%]]]|42¦bow shoot[, [move[ment]] speed %-number%[, unk[nown] param[eter] %-number%[, follow range %-number%]]])) to %livingentities%");
|
||||||
Skript.registerEffect(EffMakeJump.class, "make %livingentities% jump", "force %livingentities% to jump");
|
Skript.registerEffect(EffMakeJump.class, "make %livingentities% jump", "force %livingentities% to jump");
|
||||||
Skript.registerEffect(EffGZipFile.class, "create [a] gzip[ped] file [at] [path] %string%");
|
|
||||||
Skript.registerExpression(ExprNoClip.class, Boolean.class, ExpressionType.PROPERTY, "no[( |-)]clip (state|mode) of %entities%", "%entities%'s no[( |-)]clip (state|mode)");
|
Skript.registerExpression(ExprNoClip.class, Boolean.class, ExpressionType.PROPERTY, "no[( |-)]clip (state|mode) of %entities%", "%entities%'s no[( |-)]clip (state|mode)");
|
||||||
Skript.registerExpression(ExprFireProof.class, Boolean.class, ExpressionType.PROPERTY, "fire[ ]proof (state|mode) of %entities%", "%entities%'s fire[ ]proof (state|mode)");
|
Skript.registerExpression(ExprFireProof.class, Boolean.class, ExpressionType.PROPERTY, "fire[ ]proof (state|mode) of %entities%", "%entities%'s fire[ ]proof (state|mode)");
|
||||||
|
|
||||||
effAmount += 5;
|
|
||||||
exprAmount += 12;
|
|
||||||
// 13 with the ender blocks expression
|
|
||||||
typeAmount += 2;
|
|
||||||
}
|
}
|
||||||
effAmount += 1;
|
Metrics metrics = new Metrics(this, 1);
|
||||||
evtAmount += 1;
|
metrics.startSubmitting();
|
||||||
exprAmount += 1;
|
|
||||||
try {
|
|
||||||
Metrics metrics = new Metrics(this);
|
|
||||||
metrics.start();
|
|
||||||
getLogger().info("Hooked into Metrics! Woohoo!!");
|
getLogger().info("Hooked into Metrics! Woohoo!!");
|
||||||
} catch (IOException ex) {
|
getLogger().info("Everything's ready!");
|
||||||
getLogger().warning("Sorry, I've failed to hook SkStuff into Metrics. I'm really sorry.");
|
|
||||||
getLogger().warning("Here's an error for you: " + ex.getMessage());
|
|
||||||
}
|
|
||||||
getLogger().info("Everything ready! Loaded a total of " + condAmount + " conditions, " + effAmount + " effects, " + evtAmount + " events, " + exprAmount + " expressions and " + typeAmount + " types!");
|
|
||||||
} else {
|
} else {
|
||||||
getLogger().info("Unable to find Skript or Skript isn't accepting registrations, disabling SkStuff...");
|
getLogger().info("Unable to find Skript or Skript isn't accepting registrations, disabling SkStuff...");
|
||||||
Bukkit.getPluginManager().disablePlugin(this);
|
Bukkit.getPluginManager().disablePlugin(this);
|
||||||
@ -101,6 +59,30 @@ public class SkStuff extends JavaPlugin {
|
|||||||
String version = ReflectionUtils.getVersion();
|
String version = ReflectionUtils.getVersion();
|
||||||
|
|
||||||
switch (version) {
|
switch (version) {
|
||||||
|
case "v1_8_R3.":
|
||||||
|
nmsMethods = new NMS_v1_8_R3();
|
||||||
|
getLogger().info("It looks like you're running 1.8.8!");
|
||||||
|
break;
|
||||||
|
case "v1_9_R1.":
|
||||||
|
nmsMethods = new NMS_v1_9_R1();
|
||||||
|
getLogger().info("It looks like you're running 1.9.2!");
|
||||||
|
break;
|
||||||
|
case "v1_9_R2.":
|
||||||
|
nmsMethods = new NMS_v1_9_R2();
|
||||||
|
getLogger().info("It looks like you're running 1.9.4!");
|
||||||
|
break;
|
||||||
|
case "v1_10_R1.":
|
||||||
|
nmsMethods = new NMS_v1_10_R1();
|
||||||
|
getLogger().info("It looks like you're running 1.10.2!");
|
||||||
|
break;
|
||||||
|
case "v1_11_R1.":
|
||||||
|
nmsMethods = new NMS_v1_11_R1();
|
||||||
|
getLogger().info("It looks like you're running 1.11.2!");
|
||||||
|
break;
|
||||||
|
case "v1_12_R1.":
|
||||||
|
nmsMethods = new NMS_v1_12_R1();
|
||||||
|
getLogger().info("It looks like you're running 1.12.2!");
|
||||||
|
break;
|
||||||
case "v1_13_R2.":
|
case "v1_13_R2.":
|
||||||
nmsMethods = new NMS_v1_13_R2();
|
nmsMethods = new NMS_v1_13_R2();
|
||||||
getLogger().info("It looks like you're running 1.13.2!");
|
getLogger().info("It looks like you're running 1.13.2!");
|
||||||
@ -125,6 +107,6 @@ public class SkStuff extends JavaPlugin {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void onDisable() {
|
public void onDisable() {
|
||||||
getLogger().info("SkStuff " + this.getDescription().getVersion() + " has been successfully disabled.");
|
getLogger().info("SkPathfinderGoals " + this.getDescription().getVersion() + " has been successfully disabled.");
|
||||||
}
|
}
|
||||||
}
|
}
|
719
src/me/TheBukor/SkStuff/bstats/Metrics.java
Normal file
719
src/me/TheBukor/SkStuff/bstats/Metrics.java
Normal file
@ -0,0 +1,719 @@
|
|||||||
|
package me.TheBukor.SkStuff.bstats;
|
||||||
|
import com.google.gson.JsonArray;
|
||||||
|
import com.google.gson.JsonObject;
|
||||||
|
import com.google.gson.JsonParser;
|
||||||
|
import com.google.gson.JsonPrimitive;
|
||||||
|
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 javax.net.ssl.HttpsURLConnection;
|
||||||
|
import java.io.*;
|
||||||
|
import java.lang.reflect.InvocationTargetException;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.util.*;
|
||||||
|
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;
|
||||||
|
|
||||||
|
// The plugin id
|
||||||
|
private final int pluginId;
|
||||||
|
|
||||||
|
// A list with all custom charts
|
||||||
|
private final List<CustomChart> charts = new ArrayList<>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class constructor.
|
||||||
|
*
|
||||||
|
* @param plugin The plugin which stats should be submitted.
|
||||||
|
* @param pluginId The id of the plugin.
|
||||||
|
* It can be found at <a href="https://bstats.org/what-is-my-plugin-id">What is my plugin id?</a>
|
||||||
|
*/
|
||||||
|
public Metrics(Plugin plugin, int pluginId) {
|
||||||
|
if (plugin == null) {
|
||||||
|
throw new IllegalArgumentException("Plugin cannot be null!");
|
||||||
|
}
|
||||||
|
this.plugin = plugin;
|
||||||
|
this.pluginId = pluginId;
|
||||||
|
|
||||||
|
// 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.
|
||||||
|
*/
|
||||||
|
public 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.addProperty("pluginName", pluginName); // Append the name of the plugin
|
||||||
|
data.addProperty("id", pluginId); // Append the id of the plugin
|
||||||
|
data.addProperty("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.add("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();
|
||||||
|
String bukkitName = Bukkit.getName();
|
||||||
|
|
||||||
|
// 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.addProperty("serverUUID", serverUUID);
|
||||||
|
|
||||||
|
data.addProperty("playerAmount", playerAmount);
|
||||||
|
data.addProperty("onlineMode", onlineMode);
|
||||||
|
data.addProperty("bukkitVersion", bukkitVersion);
|
||||||
|
data.addProperty("bukkitName", bukkitName);
|
||||||
|
|
||||||
|
data.addProperty("javaVersion", javaVersion);
|
||||||
|
data.addProperty("osName", osName);
|
||||||
|
data.addProperty("osArch", osArch);
|
||||||
|
data.addProperty("osVersion", osVersion);
|
||||||
|
data.addProperty("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 {
|
||||||
|
Object plugin = provider.getService().getMethod("getPluginData").invoke(provider.getProvider());
|
||||||
|
if (plugin instanceof JsonObject) {
|
||||||
|
pluginData.add((JsonObject) plugin);
|
||||||
|
} else { // old bstats version compatibility
|
||||||
|
try {
|
||||||
|
Class<?> jsonObjectJsonSimple = Class.forName("org.json.simple.JSONObject");
|
||||||
|
if (plugin.getClass().isAssignableFrom(jsonObjectJsonSimple)) {
|
||||||
|
Method jsonStringGetter = jsonObjectJsonSimple.getDeclaredMethod("toJSONString");
|
||||||
|
jsonStringGetter.setAccessible(true);
|
||||||
|
String jsonString = (String) jsonStringGetter.invoke(plugin);
|
||||||
|
JsonObject object = new JsonParser().parse(jsonString).getAsJsonObject();
|
||||||
|
pluginData.add(object);
|
||||||
|
}
|
||||||
|
} catch (ClassNotFoundException e) {
|
||||||
|
// minecraft version 1.14+
|
||||||
|
if (logFailedRequests) {
|
||||||
|
this.plugin.getLogger().log(Level.SEVERE, "Encountered unexpected exception", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (NullPointerException | NoSuchMethodException | IllegalAccessException | InvocationTargetException ignored) { }
|
||||||
|
}
|
||||||
|
} catch (NoSuchFieldException ignored) { }
|
||||||
|
}
|
||||||
|
|
||||||
|
data.add("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);
|
||||||
|
}
|
||||||
|
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);
|
||||||
|
try (DataOutputStream outputStream = new DataOutputStream(connection.getOutputStream())) {
|
||||||
|
outputStream.write(compressedData);
|
||||||
|
}
|
||||||
|
|
||||||
|
StringBuilder builder = new StringBuilder();
|
||||||
|
try (BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(connection.getInputStream()))) {
|
||||||
|
String line;
|
||||||
|
while ((line = bufferedReader.readLine()) != null) {
|
||||||
|
builder.append(line);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (logResponseStatusText) {
|
||||||
|
plugin.getLogger().info("Sent data to bStats and received response: " + builder);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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();
|
||||||
|
try (GZIPOutputStream gzip = new GZIPOutputStream(outputStream)) {
|
||||||
|
gzip.write(str.getBytes(StandardCharsets.UTF_8));
|
||||||
|
}
|
||||||
|
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.addProperty("chartId", chartId);
|
||||||
|
try {
|
||||||
|
JsonObject data = getChartData();
|
||||||
|
if (data == null) {
|
||||||
|
// If the data is null we don't send the chart.
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
chart.add("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.addProperty("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.addProperty(entry.getKey(), entry.getValue());
|
||||||
|
}
|
||||||
|
if (allSkipped) {
|
||||||
|
// Null = skip the chart
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
data.add("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.addProperty(valueEntry.getKey(), valueEntry.getValue());
|
||||||
|
allSkipped = false;
|
||||||
|
}
|
||||||
|
if (!allSkipped) {
|
||||||
|
reallyAllSkipped = false;
|
||||||
|
values.add(entryValues.getKey(), value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (reallyAllSkipped) {
|
||||||
|
// Null = skip the chart
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
data.add("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.addProperty("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.addProperty(entry.getKey(), entry.getValue());
|
||||||
|
}
|
||||||
|
if (allSkipped) {
|
||||||
|
// Null = skip the chart
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
data.add("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(new JsonPrimitive(entry.getValue()));
|
||||||
|
values.add(entry.getKey(), categoryValues);
|
||||||
|
}
|
||||||
|
data.add("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(new JsonPrimitive(categoryValue));
|
||||||
|
}
|
||||||
|
values.add(entry.getKey(), categoryValues);
|
||||||
|
}
|
||||||
|
if (allSkipped) {
|
||||||
|
// Null = skip the chart
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
data.add("values", values);
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,49 +0,0 @@
|
|||||||
package me.TheBukor.SkStuff.effects;
|
|
||||||
|
|
||||||
import java.io.EOFException;
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.FileNotFoundException;
|
|
||||||
import java.io.FileOutputStream;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.zip.GZIPOutputStream;
|
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
|
||||||
|
|
||||||
import org.bukkit.event.Event;
|
|
||||||
|
|
||||||
import ch.njol.skript.lang.Effect;
|
|
||||||
import ch.njol.skript.lang.Expression;
|
|
||||||
import ch.njol.skript.lang.SkriptParser.ParseResult;
|
|
||||||
import ch.njol.util.Kleenean;
|
|
||||||
|
|
||||||
public class EffGZipFile extends Effect {
|
|
||||||
private Expression<String> filePath;
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
@Override
|
|
||||||
public boolean init(Expression<?>[] expr, int matchedPattern, Kleenean arg2, ParseResult result) {
|
|
||||||
filePath = (Expression<String>) expr[0];
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString(@Nullable Event e, boolean debug) {
|
|
||||||
return "create GZipped file at path " + filePath.toString(e, debug);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void execute(Event e) {
|
|
||||||
File newFile = new File(filePath.getSingle(e));
|
|
||||||
if (!newFile.exists()) {
|
|
||||||
try {
|
|
||||||
new GZIPOutputStream(new FileOutputStream(newFile)).close();
|
|
||||||
} catch (FileNotFoundException ex) {
|
|
||||||
ex.printStackTrace();
|
|
||||||
} catch (IOException ex) {
|
|
||||||
if (!(ex instanceof EOFException)) {
|
|
||||||
ex.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,57 +0,0 @@
|
|||||||
package me.TheBukor.SkStuff.effects;
|
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
|
||||||
|
|
||||||
import org.bukkit.Location;
|
|
||||||
import org.bukkit.entity.Player;
|
|
||||||
import org.bukkit.event.Event;
|
|
||||||
|
|
||||||
import ch.njol.skript.lang.Effect;
|
|
||||||
import ch.njol.skript.lang.Expression;
|
|
||||||
import ch.njol.skript.lang.SkriptParser.ParseResult;
|
|
||||||
import ch.njol.util.Kleenean;
|
|
||||||
|
|
||||||
public class EffResourceSound extends Effect {
|
|
||||||
private Expression<String> sound;
|
|
||||||
private Expression<Player> players;
|
|
||||||
private Expression<Location> location;
|
|
||||||
private Expression<Number> volume;
|
|
||||||
private Expression<Number> pitch;
|
|
||||||
|
|
||||||
private int pattern;
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
@Override
|
|
||||||
public boolean init(Expression<?>[] expr, int matchedPattern, Kleenean isDelayed, ParseResult result) {
|
|
||||||
sound = (Expression<String>) expr[0];
|
|
||||||
players = (Expression<Player>) expr[1];
|
|
||||||
location = (Expression<Location>) expr[2];
|
|
||||||
pattern = matchedPattern;
|
|
||||||
if (pattern == 0) {
|
|
||||||
volume = (Expression<Number>) expr[3];
|
|
||||||
pitch = (Expression<Number>) expr[4];
|
|
||||||
} else {
|
|
||||||
pitch = (Expression<Number>) expr[3];
|
|
||||||
volume = (Expression<Number>) expr[4];
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString(@Nullable Event e, boolean debug) {
|
|
||||||
return "play raw sound for " + players.toString(e, debug) + " at " + location.toString(e, debug) + " with " + (pattern == 0 ? "volume " + volume.toString(e, debug) : "pitch " + pitch.toString(e, debug)) + " and " + (pattern == 0 ? "pitch " + pitch.toString(e, debug) : "volume " + volume.toString(e, debug));
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("deprecation")
|
|
||||||
@Override
|
|
||||||
protected void execute(Event e) {
|
|
||||||
String s = sound.getSingle(e);
|
|
||||||
Player[] ps = players.getAll(e);
|
|
||||||
Location loc = location.getSingle(e);
|
|
||||||
float vol = (volume == null ? 1.0F : volume.getSingle(e).floatValue());
|
|
||||||
float pitch = (this.pitch == null ? 1.0F : this.pitch.getSingle(e).floatValue());
|
|
||||||
for (Player p : ps) {
|
|
||||||
p.playSound(loc, s, vol, pitch);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -538,10 +538,17 @@ public final class EffSetPathGoal extends Effect {
|
|||||||
className = "Living";
|
className = "Living";
|
||||||
}
|
}
|
||||||
Class<?> nmsClass = ReflectionUtils.getNMSClass("Entity" + className);
|
Class<?> nmsClass = ReflectionUtils.getNMSClass("Entity" + className);
|
||||||
if (version.equals("v1_13_R2.")) {
|
switch (version) {
|
||||||
|
case "v1.12_R1.":
|
||||||
|
newGoals.add(new PathfinderGoalFollow_v1_12_R1((net.minecraft.server.v1_12_R1.EntityCreature) nmsEnt, nmsClass, radius, spd, usesName, customName));
|
||||||
|
break;
|
||||||
|
case "v1.13_R2.":
|
||||||
newGoals.add(new PathfinderGoalFollow_v1_13_R2((net.minecraft.server.v1_13_R2.EntityCreature) nmsEnt, nmsClass, radius, spd, usesName, customName));
|
newGoals.add(new PathfinderGoalFollow_v1_13_R2((net.minecraft.server.v1_13_R2.EntityCreature) nmsEnt, nmsClass, radius, spd, usesName, customName));
|
||||||
} else if (version.equals("v1_14_R1.")) {
|
break;
|
||||||
|
case "v1.14_R1.":
|
||||||
newGoals.add(new PathfinderGoalFollow_v1_14_R1((net.minecraft.server.v1_14_R1.EntityCreature) nmsEnt, nmsClass, radius, spd, usesName, customName));
|
newGoals.add(new PathfinderGoalFollow_v1_14_R1((net.minecraft.server.v1_14_R1.EntityCreature) nmsEnt, nmsClass, radius, spd, usesName, customName));
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (mark == 42) {
|
} else if (mark == 42) {
|
||||||
|
@ -39,7 +39,17 @@ public class EffShowEntityEffect extends Effect {
|
|||||||
} else if (mark == 4) {
|
} else if (mark == 4) {
|
||||||
effect = EntityEffect.WOLF_SHAKE;
|
effect = EntityEffect.WOLF_SHAKE;
|
||||||
toStringMark = "wolf shake";
|
toStringMark = "wolf shake";
|
||||||
|
} else if (mark == 5) {
|
||||||
|
effect = EntityEffect.SQUID_ROTATE;
|
||||||
|
toStringMark = "squid rotate";
|
||||||
|
} else if (mark == 6) {
|
||||||
|
effect = EntityEffect.TOTEM_RESURRECT;
|
||||||
|
toStringMark = "totem resurrect";
|
||||||
|
} else if (mark == 7) {
|
||||||
|
effect = EntityEffect.RABBIT_JUMP;
|
||||||
|
toStringMark = "rabbit jump";
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,49 +0,0 @@
|
|||||||
package me.TheBukor.SkStuff.expressions;
|
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
|
||||||
|
|
||||||
import org.bukkit.event.Event;
|
|
||||||
import org.bukkit.event.inventory.InventoryClickEvent;
|
|
||||||
import org.bukkit.inventory.Inventory;
|
|
||||||
|
|
||||||
import ch.njol.skript.ScriptLoader;
|
|
||||||
import ch.njol.skript.Skript;
|
|
||||||
import ch.njol.skript.lang.Expression;
|
|
||||||
import ch.njol.skript.lang.SkriptParser.ParseResult;
|
|
||||||
import ch.njol.skript.lang.util.SimpleExpression;
|
|
||||||
import ch.njol.skript.log.ErrorQuality;
|
|
||||||
import ch.njol.util.Kleenean;
|
|
||||||
|
|
||||||
public class ExprClickedInventory extends SimpleExpression<Inventory> {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Class<? extends Inventory> getReturnType() {
|
|
||||||
return Inventory.class;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isSingle() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean init(Expression<?>[] expr, int matchedPattern, Kleenean arg2, ParseResult result) {
|
|
||||||
if (!ScriptLoader.isCurrentEvent(InventoryClickEvent.class)) {
|
|
||||||
Skript.error("The expression clicked inventory can only be used in an on inventory click event", ErrorQuality.SEMANTIC_ERROR);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString(@Nullable Event e, boolean debug) {
|
|
||||||
return "clicked inventory";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@Nullable
|
|
||||||
protected Inventory[] get(Event e) {
|
|
||||||
return new Inventory[] { ((InventoryClickEvent) e).getClickedInventory() };
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,66 +0,0 @@
|
|||||||
package me.TheBukor.SkStuff.expressions;
|
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
|
||||||
|
|
||||||
import org.bukkit.entity.LivingEntity;
|
|
||||||
import org.bukkit.event.Event;
|
|
||||||
|
|
||||||
import ch.njol.skript.classes.Changer.ChangeMode;
|
|
||||||
import ch.njol.skript.lang.Expression;
|
|
||||||
import ch.njol.skript.lang.SkriptParser.ParseResult;
|
|
||||||
import ch.njol.skript.lang.util.SimpleExpression;
|
|
||||||
import ch.njol.util.Kleenean;
|
|
||||||
import ch.njol.util.coll.CollectionUtils;
|
|
||||||
import me.TheBukor.SkStuff.SkStuff;
|
|
||||||
|
|
||||||
public class ExprGlideState extends SimpleExpression<Boolean> {
|
|
||||||
private Expression<LivingEntity> entity;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isSingle() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Class<? extends Boolean> getReturnType() {
|
|
||||||
return Boolean.class;
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
@Override
|
|
||||||
public boolean init(Expression<?>[] expr, int matchedPattern, Kleenean isDelayed, ParseResult parseResult) {
|
|
||||||
entity = (Expression<LivingEntity>) expr[0];
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString(@Nullable Event e, boolean debug) {
|
|
||||||
return "elytra gliding state of " + entity.toString(e, debug);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@Nullable
|
|
||||||
protected Boolean[] get(Event e) {
|
|
||||||
LivingEntity ent = entity.getSingle(e);
|
|
||||||
return new Boolean[] { SkStuff.getNMSMethods().getElytraGlideState(ent) };
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
@Override
|
|
||||||
@Nullable
|
|
||||||
public Class<?>[] acceptChange(ChangeMode mode) {
|
|
||||||
if (mode == ChangeMode.SET) {
|
|
||||||
return CollectionUtils.array(Boolean.class);
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void change(Event e, @Nullable Object[] delta, ChangeMode mode) {
|
|
||||||
LivingEntity ent = entity.getSingle(e);
|
|
||||||
if (mode == ChangeMode.SET) {
|
|
||||||
boolean newValue = (boolean) delta[0];
|
|
||||||
SkStuff.getNMSMethods().setElytraGlideState(ent, newValue);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,63 +0,0 @@
|
|||||||
package me.TheBukor.SkStuff.expressions;
|
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
|
||||||
|
|
||||||
import org.bukkit.block.Block;
|
|
||||||
import org.bukkit.block.BlockState;
|
|
||||||
import org.bukkit.block.DoubleChest;
|
|
||||||
import org.bukkit.entity.Entity;
|
|
||||||
import org.bukkit.event.Event;
|
|
||||||
import org.bukkit.inventory.Inventory;
|
|
||||||
import org.bukkit.inventory.InventoryHolder;
|
|
||||||
|
|
||||||
import ch.njol.skript.Skript;
|
|
||||||
import ch.njol.skript.lang.Expression;
|
|
||||||
import ch.njol.skript.lang.SkriptParser.ParseResult;
|
|
||||||
import ch.njol.skript.lang.util.SimpleExpression;
|
|
||||||
import ch.njol.util.Kleenean;
|
|
||||||
|
|
||||||
public class ExprInventoryOwner extends SimpleExpression<Object> {
|
|
||||||
private Expression<Inventory> inventory;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isSingle() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Class<? extends Object> getReturnType() {
|
|
||||||
return Object.class;
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
@Override
|
|
||||||
public boolean init(Expression<?>[] expr, int matchedPattern, Kleenean isDelayed, ParseResult parseResult) {
|
|
||||||
inventory = (Expression<Inventory>) expr[0];
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString(@Nullable Event e, boolean debug) {
|
|
||||||
return "owner of " + inventory.toString(e, debug);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@Nullable
|
|
||||||
protected Object[] get(Event e) {
|
|
||||||
if (inventory.getSingle(e) == null)
|
|
||||||
return null;
|
|
||||||
InventoryHolder holder = inventory.getSingle(e).getHolder();
|
|
||||||
if (holder instanceof Entity) {
|
|
||||||
return new Entity[] { (Entity) holder };
|
|
||||||
} else if (holder instanceof BlockState) {
|
|
||||||
return new Block[] { ((BlockState) holder).getBlock() };
|
|
||||||
} else if (holder instanceof DoubleChest) {
|
|
||||||
return new Block[] { ((DoubleChest) holder).getLocation().getBlock() };
|
|
||||||
} else {
|
|
||||||
Skript.error("Something went wrong when trying to get the owner of the specified inventory!");
|
|
||||||
Skript.error("Post the below info on the SkStuff thread in SkUnity:");
|
|
||||||
Skript.error("Class -> " + holder.getClass().getCanonicalName());
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,82 +0,0 @@
|
|||||||
package me.TheBukor.SkStuff.expressions;
|
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
|
||||||
|
|
||||||
import org.bukkit.entity.Entity;
|
|
||||||
import org.bukkit.event.Event;
|
|
||||||
|
|
||||||
import ch.njol.skript.classes.Changer.ChangeMode;
|
|
||||||
import ch.njol.skript.lang.Expression;
|
|
||||||
import ch.njol.skript.lang.SkriptParser.ParseResult;
|
|
||||||
import ch.njol.skript.lang.util.SimpleExpression;
|
|
||||||
import ch.njol.util.Kleenean;
|
|
||||||
import ch.njol.util.coll.CollectionUtils;
|
|
||||||
import me.TheBukor.SkStuff.SkStuff;
|
|
||||||
|
|
||||||
public class ExprNoGravityState extends SimpleExpression<Boolean> {
|
|
||||||
private Expression<Entity> entities;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isSingle() {
|
|
||||||
return entities.isSingle();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Class<? extends Boolean> getReturnType() {
|
|
||||||
return Boolean.class;
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
@Override
|
|
||||||
public boolean init(Expression<?>[] expr, int matchedPattern, Kleenean isDelayed, ParseResult parseResult) {
|
|
||||||
entities = (Expression<Entity>) expr[0];
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString(@Nullable Event e, boolean debug) {
|
|
||||||
return "no gravity state of " + entities.toString(e, debug);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@Nullable
|
|
||||||
protected Boolean[] get(Event e) {
|
|
||||||
Entity[] ents = entities.getAll(e);
|
|
||||||
if (ents.length == 0)
|
|
||||||
return null;
|
|
||||||
Boolean[] gravityStates = new Boolean[ents.length];
|
|
||||||
int i = 0;
|
|
||||||
for (Entity ent : ents) {
|
|
||||||
if (ent == null)
|
|
||||||
continue;
|
|
||||||
gravityStates[i] = SkStuff.getNMSMethods().getNoGravity(ent);
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
return gravityStates;
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
@Override
|
|
||||||
@Nullable
|
|
||||||
public Class<?>[] acceptChange(ChangeMode mode) {
|
|
||||||
if (mode == ChangeMode.SET) {
|
|
||||||
return CollectionUtils.array(Boolean.class);
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void change(Event e, @Nullable Object[] delta, ChangeMode mode) {
|
|
||||||
Entity[] ents = entities.getAll(e);
|
|
||||||
if (ents.length == 0)
|
|
||||||
return;
|
|
||||||
if (mode == ChangeMode.SET) {
|
|
||||||
boolean newValue = (boolean) delta[0];
|
|
||||||
for (Entity ent : ents) {
|
|
||||||
if (ent == null)
|
|
||||||
continue;
|
|
||||||
SkStuff.getNMSMethods().setNoGravity(ent, newValue);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
80
src/me/TheBukor/SkStuff/expressions/ExprStepLength.java
Normal file
80
src/me/TheBukor/SkStuff/expressions/ExprStepLength.java
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
package me.TheBukor.SkStuff.expressions;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
|
import org.bukkit.entity.Entity;
|
||||||
|
import org.bukkit.event.Event;
|
||||||
|
|
||||||
|
import ch.njol.skript.classes.Changer.ChangeMode;
|
||||||
|
import ch.njol.skript.lang.Expression;
|
||||||
|
import ch.njol.skript.lang.SkriptParser.ParseResult;
|
||||||
|
import ch.njol.skript.lang.util.SimpleExpression;
|
||||||
|
import ch.njol.util.Kleenean;
|
||||||
|
import ch.njol.util.coll.CollectionUtils;
|
||||||
|
import me.TheBukor.SkStuff.SkStuff;
|
||||||
|
|
||||||
|
public class ExprStepLength extends SimpleExpression<Number> {
|
||||||
|
private Expression<Entity> entity;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isSingle() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Class<? extends Number> getReturnType() {
|
||||||
|
return Number.class;
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
@Override
|
||||||
|
public boolean init(Expression<?>[] expr, int matchedPattern, Kleenean isDelayed, ParseResult parseResult) {
|
||||||
|
entity = (Expression<Entity>) expr[0];
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString(@Nullable Event e, boolean debug) {
|
||||||
|
return "step length of " + entity.toString(e, debug);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Nullable
|
||||||
|
protected Number[] get(Event e) {
|
||||||
|
Entity ent = entity.getSingle(e);
|
||||||
|
if (ent == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return new Number[] { SkStuff.getNMSMethods().getEntityStepLength(ent) };
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void change(Event e, @Nullable Object[] delta, ChangeMode mode) {
|
||||||
|
Entity ent = entity.getSingle(e);
|
||||||
|
if (ent == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (mode == ChangeMode.ADD) {
|
||||||
|
float toAdd = ((Number) delta[0]).floatValue();
|
||||||
|
float currentLength = SkStuff.getNMSMethods().getEntityStepLength(ent);
|
||||||
|
SkStuff.getNMSMethods().setEntityStepLength(ent, (currentLength + toAdd));
|
||||||
|
} else if (mode == ChangeMode.REMOVE) {
|
||||||
|
float toRemove = ((Number) delta[0]).floatValue();
|
||||||
|
float currentLength = SkStuff.getNMSMethods().getEntityStepLength(ent);
|
||||||
|
SkStuff.getNMSMethods().setEntityStepLength(ent, (currentLength - toRemove));
|
||||||
|
} else if (mode == ChangeMode.SET) {
|
||||||
|
float toSet = ((Number) delta[0]).floatValue();
|
||||||
|
SkStuff.getNMSMethods().setEntityStepLength(ent, toSet);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
@Override
|
||||||
|
@Nullable
|
||||||
|
public Class<?>[] acceptChange(ChangeMode mode) {
|
||||||
|
if (mode == ChangeMode.ADD || mode == ChangeMode.REMOVE || mode == ChangeMode.SET) {
|
||||||
|
return CollectionUtils.array(Number.class);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
@ -1,77 +0,0 @@
|
|||||||
package me.TheBukor.SkStuff.expressions;
|
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
|
||||||
|
|
||||||
import org.bukkit.event.Event;
|
|
||||||
|
|
||||||
import ch.njol.skript.Skript;
|
|
||||||
import ch.njol.skript.lang.Expression;
|
|
||||||
import ch.njol.skript.lang.SkriptParser.ParseResult;
|
|
||||||
import ch.njol.skript.lang.util.SimpleExpression;
|
|
||||||
import ch.njol.skript.util.Timespan;
|
|
||||||
import ch.njol.util.Kleenean;
|
|
||||||
|
|
||||||
public class ExprTimespanToNumber extends SimpleExpression<Number> {
|
|
||||||
private Expression<Timespan> time;
|
|
||||||
private String toStringMark;
|
|
||||||
private int mark;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Class<? extends Number> getReturnType() {
|
|
||||||
return Number.class;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isSingle() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
@Override
|
|
||||||
public boolean init(Expression<?>[] expr, int matchedPattern, Kleenean arg2, ParseResult result) {
|
|
||||||
time = (Expression<Timespan>) expr[0];
|
|
||||||
mark = result.mark;
|
|
||||||
if (result.mark == 0) {
|
|
||||||
toStringMark = "ticks";
|
|
||||||
} else if (result.mark == 1) {
|
|
||||||
toStringMark = "seconds";
|
|
||||||
} else if (result.mark == 2) {
|
|
||||||
toStringMark = "minutes";
|
|
||||||
} else if (result.mark == 3) {
|
|
||||||
toStringMark = "hours";
|
|
||||||
} else if (result.mark == 4) {
|
|
||||||
toStringMark = "days";
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString(@Nullable Event e, boolean debug) {
|
|
||||||
return time.toString(e, debug) + "converted to " + toStringMark;
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("deprecation")
|
|
||||||
@Override
|
|
||||||
@Nullable
|
|
||||||
protected Number[] get(Event e) {
|
|
||||||
Timespan t = time.getSingle(e);
|
|
||||||
Number ticks = null;
|
|
||||||
if (Skript.methodExists(Timespan.class, "getTicks_i")) { //Compatibility with Mirreducki's Skript patch 24+ days timespans.
|
|
||||||
ticks = t.getTicks_i();
|
|
||||||
} else { //Standard Skript timespans, limited to roughly 24 days.
|
|
||||||
ticks = t.getTicks();
|
|
||||||
}
|
|
||||||
if (mark == 0) {
|
|
||||||
return new Number[] { ticks };
|
|
||||||
} else if (mark == 1) {
|
|
||||||
return new Number[] { ticks.longValue() / 20 };
|
|
||||||
} else if (mark == 2) {
|
|
||||||
return new Number[] { ticks.longValue() / 20 / 60 };
|
|
||||||
} else if (mark == 3) {
|
|
||||||
return new Number[] { ticks.longValue() / 20 / 60 / 60 };
|
|
||||||
} else if (mark == 4) {
|
|
||||||
return new Number[] { ticks.longValue() / 20 / 60 / 60 / 24 };
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,43 +0,0 @@
|
|||||||
package me.TheBukor.SkStuff.expressions;
|
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
|
||||||
|
|
||||||
import org.bukkit.event.Event;
|
|
||||||
|
|
||||||
import ch.njol.skript.lang.Expression;
|
|
||||||
import ch.njol.skript.lang.SkriptParser.ParseResult;
|
|
||||||
import ch.njol.skript.lang.util.SimpleExpression;
|
|
||||||
import ch.njol.util.Kleenean;
|
|
||||||
|
|
||||||
public class ExprToLowerCase extends SimpleExpression<String> {
|
|
||||||
private Expression<String> text;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Class<? extends String> getReturnType() {
|
|
||||||
return String.class;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isSingle() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
@Override
|
|
||||||
public boolean init(Expression<?>[] expr, int matchedPattern, Kleenean arg2, ParseResult arg3) {
|
|
||||||
text = (Expression<String>) expr[0];
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString(@Nullable Event e, boolean debug) {
|
|
||||||
return "convert all characters in " + text.toString(e, debug) + " to lowercase";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@Nullable
|
|
||||||
protected String[] get(Event e) {
|
|
||||||
String s = text.getSingle(e);
|
|
||||||
return new String[] { s.toLowerCase() };
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,43 +0,0 @@
|
|||||||
package me.TheBukor.SkStuff.expressions;
|
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
|
||||||
|
|
||||||
import org.bukkit.event.Event;
|
|
||||||
|
|
||||||
import ch.njol.skript.lang.Expression;
|
|
||||||
import ch.njol.skript.lang.SkriptParser.ParseResult;
|
|
||||||
import ch.njol.skript.lang.util.SimpleExpression;
|
|
||||||
import ch.njol.util.Kleenean;
|
|
||||||
|
|
||||||
public class ExprToUpperCase extends SimpleExpression<String> {
|
|
||||||
private Expression<String> text;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Class<? extends String> getReturnType() {
|
|
||||||
return String.class;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isSingle() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
@Override
|
|
||||||
public boolean init(Expression<?>[] expr, int matchedPattern, Kleenean arg2, ParseResult arg3) {
|
|
||||||
text = (Expression<String>) expr[0];
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString(@Nullable Event e, boolean debug) {
|
|
||||||
return "convert all characters in " + text.toString(e, debug) + " to uppercase";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@Nullable
|
|
||||||
protected String[] get(Event e) {
|
|
||||||
String s = text.getSingle(e);
|
|
||||||
return new String[] { s.toUpperCase() };
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,56 +0,0 @@
|
|||||||
package me.TheBukor.SkStuff.expressions;
|
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
|
||||||
|
|
||||||
import org.apache.commons.lang.WordUtils;
|
|
||||||
import org.bukkit.event.Event;
|
|
||||||
|
|
||||||
import ch.njol.skript.lang.Expression;
|
|
||||||
import ch.njol.skript.lang.SkriptParser.ParseResult;
|
|
||||||
import ch.njol.skript.lang.util.SimpleExpression;
|
|
||||||
import ch.njol.util.Kleenean;
|
|
||||||
|
|
||||||
public class ExprWordsToUpperCase extends SimpleExpression<String> {
|
|
||||||
private Expression<String> text;
|
|
||||||
private Boolean fullyCapitalize = false;
|
|
||||||
private String toStringEnd;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Class<? extends String> getReturnType() {
|
|
||||||
return String.class;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isSingle() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
@Override
|
|
||||||
public boolean init(Expression<?>[] expr, int matchedPattern, Kleenean arg2, ParseResult result) {
|
|
||||||
text = (Expression<String>) expr[0];
|
|
||||||
if (result.mark == 0) {
|
|
||||||
toStringEnd = " to uppercase";
|
|
||||||
} else {
|
|
||||||
fullyCapitalize = true;
|
|
||||||
toStringEnd = " to uppercase ignoring other uppercase characters";
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString(@Nullable Event e, boolean debug) {
|
|
||||||
return "convert first character of each word in " + text.toString(e, debug) + toStringEnd;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@Nullable
|
|
||||||
protected String[] get(Event e) {
|
|
||||||
String s = text.getSingle(e);
|
|
||||||
if (fullyCapitalize) {
|
|
||||||
return new String[] { WordUtils.capitalizeFully(s) };
|
|
||||||
} else {
|
|
||||||
return new String[] { WordUtils.capitalize(s) };
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,10 +1,10 @@
|
|||||||
package me.TheBukor.SkStuff.pathfinders;
|
package me.TheBukor.SkStuff.pathfinders;
|
||||||
|
|
||||||
import net.minecraft.server.v1_13_R2.Entity;
|
import me.TheBukor.SkStuff.util.ReflectionUtils;
|
||||||
import net.minecraft.server.v1_13_R2.EntityCreature;
|
import net.minecraft.server.v1_13_R2.*;
|
||||||
import net.minecraft.server.v1_13_R2.EntityLiving;
|
|
||||||
import net.minecraft.server.v1_13_R2.PathfinderGoal;
|
|
||||||
|
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
import java.util.LinkedHashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class PathfinderGoalFollow_v1_13_R2 extends PathfinderGoal {
|
public class PathfinderGoalFollow_v1_13_R2 extends PathfinderGoal {
|
||||||
@ -64,16 +64,13 @@ public class PathfinderGoalFollow_v1_13_R2 extends PathfinderGoal {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//return follower.getNavigation().n(); // n() means hasNoPath()
|
|
||||||
return true;
|
return true;
|
||||||
// n() is now protected void and I'm not sure how to access it, so I'm just returning a boolean, this probably will cause some issues with this pathfinder goal, if you know a better solution, let me know. - Govindas.
|
// n() is now protected void and I'm not sure how to access it, so I'm just returning a boolean, this probably will cause some issues with this pathfinder goal, if you know a better solution, let me know. - Govindas.
|
||||||
}
|
}
|
||||||
|
|
||||||
// c() is execute()
|
// c() is execute()
|
||||||
@Override
|
@Override
|
||||||
public void c () {
|
public void c() {
|
||||||
follower.getNavigation().a(followed, speed); // a() means moveTo()
|
follower.getNavigation().a(followed, speed); // a() means moveTo()
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
|
||||||
|
@ -0,0 +1,79 @@
|
|||||||
|
package me.TheBukor.SkStuff.pathfinders;
|
||||||
|
|
||||||
|
import net.minecraft.server.v1_16_R1.Entity;
|
||||||
|
import net.minecraft.server.v1_16_R1.EntityCreature;
|
||||||
|
import net.minecraft.server.v1_16_R1.EntityLiving;
|
||||||
|
import net.minecraft.server.v1_16_R1.PathfinderGoal;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class PathfinderGoalFollow_v1_16_R1 extends PathfinderGoal {
|
||||||
|
private EntityCreature follower;
|
||||||
|
private EntityLiving followed;
|
||||||
|
private Class<?> followedClass;
|
||||||
|
private float radius;
|
||||||
|
private double speed;
|
||||||
|
private boolean isByName;
|
||||||
|
private String customName;
|
||||||
|
|
||||||
|
public PathfinderGoalFollow_v1_16_R1(EntityCreature follower, Class<?> followedClass, float radius, double speed, boolean isByName, String customName) {
|
||||||
|
this.follower = follower;
|
||||||
|
this.followedClass = followedClass;
|
||||||
|
this.radius = radius;
|
||||||
|
this.speed = speed;
|
||||||
|
this.isByName = isByName;
|
||||||
|
this.customName = customName;
|
||||||
|
}
|
||||||
|
|
||||||
|
// a() is shouldExecute()
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
@Override
|
||||||
|
public boolean a() {
|
||||||
|
if (followed == null) {
|
||||||
|
List<?> list = follower.world.a((Class<? extends Entity>) followedClass, follower.getBoundingBox().grow(radius, 4.0D, radius));
|
||||||
|
if (list.isEmpty()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (isByName) {
|
||||||
|
for (Object entity : list) {
|
||||||
|
if (((EntityLiving) entity).getCustomName().equals(customName)) {
|
||||||
|
followed = (EntityLiving) entity;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
followed = (EntityLiving) list.get(0);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// b() is shouldContinueExecuting()
|
||||||
|
@Override
|
||||||
|
public boolean b() {
|
||||||
|
if (followed.dead) {
|
||||||
|
followed = null;
|
||||||
|
return false;
|
||||||
|
} else if (followed.h(follower) < 9.0D || followed.h(follower) > Math.pow(radius, 2)) { // h() = distanceSquaredFrom()
|
||||||
|
return false; // if 3 blocks away or not in radius, stop moving.
|
||||||
|
//Maybe I'll add a teleport feature later.
|
||||||
|
} else if (isByName) {
|
||||||
|
if (!followed.getCustomName().equals(customName)) {
|
||||||
|
followed = null;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//return follower.getNavigation().n(); // n() means hasNoPath()
|
||||||
|
return true;
|
||||||
|
// n() is now protected void and I'm not sure how to access it, so I'm just returning a boolean, this probably will cause some issues with this pathfinder goal, if you know a better solution, let me know. - Govindas.
|
||||||
|
}
|
||||||
|
|
||||||
|
// c() is execute()
|
||||||
|
@Override
|
||||||
|
public void c () {
|
||||||
|
follower.getNavigation().a(followed, speed); // a() means moveTo()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -1,5 +1,4 @@
|
|||||||
package me.TheBukor.SkStuff.util;
|
package me.TheBukor.SkStuff.util;
|
||||||
|
|
||||||
import org.bukkit.entity.Entity;
|
import org.bukkit.entity.Entity;
|
||||||
|
|
||||||
public interface NMSInterface {
|
public interface NMSInterface {
|
||||||
@ -22,15 +21,6 @@ public interface NMSInterface {
|
|||||||
public boolean getFireProof(Entity entity);
|
public boolean getFireProof(Entity entity);
|
||||||
|
|
||||||
public void setFireProof(Entity entity, boolean fireProof);
|
public void setFireProof(Entity entity, boolean fireProof);
|
||||||
|
public float getEntityStepLength(Entity entity);
|
||||||
|
public void setEntityStepLength(Entity entity, float length);
|
||||||
|
|
||||||
|
|
||||||
public boolean getElytraGlideState(Entity entity);
|
|
||||||
|
|
||||||
public void setElytraGlideState(Entity entity, boolean glide);
|
|
||||||
|
|
||||||
public boolean getNoGravity(Entity entity);
|
|
||||||
|
|
||||||
public void setNoGravity(Entity entity, boolean noGravity);
|
|
||||||
}
|
}
|
91
src/me/TheBukor/SkStuff/util/NMS_v1_10_R1.java
Normal file
91
src/me/TheBukor/SkStuff/util/NMS_v1_10_R1.java
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
package me.TheBukor.SkStuff.util;
|
||||||
|
|
||||||
|
import net.minecraft.server.v1_10_R1.EntityInsentient;
|
||||||
|
import net.minecraft.server.v1_10_R1.PathfinderGoal;
|
||||||
|
import net.minecraft.server.v1_10_R1.PathfinderGoalSelector;
|
||||||
|
import org.bukkit.craftbukkit.v1_10_R1.entity.CraftEntity;
|
||||||
|
import org.bukkit.entity.Entity;
|
||||||
|
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.LinkedHashSet;
|
||||||
|
|
||||||
|
public class NMS_v1_10_R1 implements NMSInterface {
|
||||||
|
@Override
|
||||||
|
public void clearPathfinderGoals(Entity entity) {
|
||||||
|
EntityInsentient nmsEnt = (EntityInsentient) ((CraftEntity) entity).getHandle();
|
||||||
|
((LinkedHashSet<?>) ReflectionUtils.getField("b", PathfinderGoalSelector.class, nmsEnt.goalSelector)).clear();
|
||||||
|
((LinkedHashSet<?>) ReflectionUtils.getField("c", PathfinderGoalSelector.class, nmsEnt.goalSelector)).clear();
|
||||||
|
((LinkedHashSet<?>) ReflectionUtils.getField("b", PathfinderGoalSelector.class, nmsEnt.targetSelector)).clear();
|
||||||
|
((LinkedHashSet<?>) ReflectionUtils.getField("c", PathfinderGoalSelector.class, nmsEnt.targetSelector)).clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void removePathfinderGoal(Object entity, Class<?> goalClass, boolean isTargetSelector) {
|
||||||
|
if (entity instanceof EntityInsentient) {
|
||||||
|
((EntityInsentient) entity).setGoalTarget(null);
|
||||||
|
if (isTargetSelector) {
|
||||||
|
Iterator<?> goals = ((LinkedHashSet<?>) ReflectionUtils.getField("b", PathfinderGoalSelector.class, ((EntityInsentient) entity).targetSelector)).iterator();
|
||||||
|
while (goals.hasNext()) {
|
||||||
|
Object goal = goals.next();
|
||||||
|
if (ReflectionUtils.getField("a", goal.getClass(), goal).getClass() == goalClass) {
|
||||||
|
goals.remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Iterator<?> goals = ((LinkedHashSet<?>) ReflectionUtils.getField("b", PathfinderGoalSelector.class, ((EntityInsentient) entity).goalSelector)).iterator();
|
||||||
|
while (goals.hasNext()) {
|
||||||
|
Object goal = goals.next();
|
||||||
|
if (ReflectionUtils.getField("a", goal.getClass(), goal).getClass() == goalClass) {
|
||||||
|
goals.remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addPathfinderGoal(Object entity, int priority, Object goal, boolean isTargetSelector) {
|
||||||
|
if (entity instanceof EntityInsentient && goal instanceof PathfinderGoal) {
|
||||||
|
if (isTargetSelector)
|
||||||
|
((EntityInsentient) entity).targetSelector.a(priority, (PathfinderGoal) goal);
|
||||||
|
else
|
||||||
|
((EntityInsentient) entity).goalSelector.a(priority, (PathfinderGoal) goal);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean getNoClip(Entity entity) {
|
||||||
|
net.minecraft.server.v1_10_R1.Entity nmsEntity = ((CraftEntity) entity).getHandle();
|
||||||
|
return nmsEntity.noclip;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setNoClip(Entity entity, boolean noclip) {
|
||||||
|
net.minecraft.server.v1_10_R1.Entity nmsEntity = ((CraftEntity) entity).getHandle();
|
||||||
|
nmsEntity.noclip = noclip;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean getFireProof(Entity entity) {
|
||||||
|
net.minecraft.server.v1_10_R1.Entity nmsEntity = ((CraftEntity) entity).getHandle();
|
||||||
|
return nmsEntity.isFireProof();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setFireProof(Entity entity, boolean fireProof) {
|
||||||
|
net.minecraft.server.v1_10_R1.Entity nmsEntity = ((CraftEntity) entity).getHandle();
|
||||||
|
ReflectionUtils.setField("fireProof", nmsEntity.getClass(), nmsEntity, fireProof);
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public float getEntityStepLength(Entity entity) {
|
||||||
|
net.minecraft.server.v1_10_R1.Entity nmsEntity = ((CraftEntity) entity).getHandle();
|
||||||
|
return nmsEntity.P;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setEntityStepLength(Entity entity, float length) {
|
||||||
|
net.minecraft.server.v1_10_R1.Entity nmsEntity = ((CraftEntity) entity).getHandle();
|
||||||
|
nmsEntity.P = length;
|
||||||
|
}
|
||||||
|
}
|
91
src/me/TheBukor/SkStuff/util/NMS_v1_11_R1.java
Normal file
91
src/me/TheBukor/SkStuff/util/NMS_v1_11_R1.java
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
package me.TheBukor.SkStuff.util;
|
||||||
|
|
||||||
|
import net.minecraft.server.v1_11_R1.EntityInsentient;
|
||||||
|
import net.minecraft.server.v1_11_R1.PathfinderGoal;
|
||||||
|
import net.minecraft.server.v1_11_R1.PathfinderGoalSelector;
|
||||||
|
import org.bukkit.craftbukkit.v1_11_R1.entity.CraftEntity;
|
||||||
|
import org.bukkit.entity.Entity;
|
||||||
|
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.LinkedHashSet;
|
||||||
|
|
||||||
|
public class NMS_v1_11_R1 implements NMSInterface {
|
||||||
|
@Override
|
||||||
|
public void clearPathfinderGoals(Entity entity) {
|
||||||
|
EntityInsentient nmsEnt = (EntityInsentient) ((CraftEntity) entity).getHandle();
|
||||||
|
((LinkedHashSet<?>) ReflectionUtils.getField("b", PathfinderGoalSelector.class, nmsEnt.goalSelector)).clear();
|
||||||
|
((LinkedHashSet<?>) ReflectionUtils.getField("c", PathfinderGoalSelector.class, nmsEnt.goalSelector)).clear();
|
||||||
|
((LinkedHashSet<?>) ReflectionUtils.getField("b", PathfinderGoalSelector.class, nmsEnt.targetSelector)).clear();
|
||||||
|
((LinkedHashSet<?>) ReflectionUtils.getField("c", PathfinderGoalSelector.class, nmsEnt.targetSelector)).clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void removePathfinderGoal(Object entity, Class<?> goalClass, boolean isTargetSelector) {
|
||||||
|
if (entity instanceof EntityInsentient) {
|
||||||
|
((EntityInsentient) entity).setGoalTarget(null);
|
||||||
|
if (isTargetSelector) {
|
||||||
|
Iterator<?> goals = ((LinkedHashSet<?>) ReflectionUtils.getField("b", PathfinderGoalSelector.class, ((EntityInsentient) entity).targetSelector)).iterator();
|
||||||
|
while (goals.hasNext()) {
|
||||||
|
Object goal = goals.next();
|
||||||
|
if (ReflectionUtils.getField("a", goal.getClass(), goal).getClass() == goalClass) {
|
||||||
|
goals.remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Iterator<?> goals = ((LinkedHashSet<?>) ReflectionUtils.getField("b", PathfinderGoalSelector.class, ((EntityInsentient) entity).goalSelector)).iterator();
|
||||||
|
while (goals.hasNext()) {
|
||||||
|
Object goal = goals.next();
|
||||||
|
if (ReflectionUtils.getField("a", goal.getClass(), goal).getClass() == goalClass) {
|
||||||
|
goals.remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addPathfinderGoal(Object entity, int priority, Object goal, boolean isTargetSelector) {
|
||||||
|
if (entity instanceof EntityInsentient && goal instanceof PathfinderGoal) {
|
||||||
|
if (isTargetSelector)
|
||||||
|
((EntityInsentient) entity).targetSelector.a(priority, (PathfinderGoal) goal);
|
||||||
|
else
|
||||||
|
((EntityInsentient) entity).goalSelector.a(priority, (PathfinderGoal) goal);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean getNoClip(Entity entity) {
|
||||||
|
net.minecraft.server.v1_11_R1.Entity nmsEntity = ((CraftEntity) entity).getHandle();
|
||||||
|
return nmsEntity.noclip;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setNoClip(Entity entity, boolean noclip) {
|
||||||
|
net.minecraft.server.v1_11_R1.Entity nmsEntity = ((CraftEntity) entity).getHandle();
|
||||||
|
nmsEntity.noclip = noclip;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean getFireProof(Entity entity) {
|
||||||
|
net.minecraft.server.v1_11_R1.Entity nmsEntity = ((CraftEntity) entity).getHandle();
|
||||||
|
return nmsEntity.isFireProof();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setFireProof(Entity entity, boolean fireProof) {
|
||||||
|
net.minecraft.server.v1_11_R1.Entity nmsEntity = ((CraftEntity) entity).getHandle();
|
||||||
|
ReflectionUtils.setField("fireProof", nmsEntity.getClass(), nmsEntity, fireProof);
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public float getEntityStepLength(Entity entity) {
|
||||||
|
net.minecraft.server.v1_11_R1.Entity nmsEntity = ((CraftEntity) entity).getHandle();
|
||||||
|
return nmsEntity.P;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setEntityStepLength(Entity entity, float length) {
|
||||||
|
net.minecraft.server.v1_11_R1.Entity nmsEntity = ((CraftEntity) entity).getHandle();
|
||||||
|
nmsEntity.P = length;
|
||||||
|
}
|
||||||
|
}
|
91
src/me/TheBukor/SkStuff/util/NMS_v1_12_R1.java
Normal file
91
src/me/TheBukor/SkStuff/util/NMS_v1_12_R1.java
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
package me.TheBukor.SkStuff.util;
|
||||||
|
|
||||||
|
import net.minecraft.server.v1_12_R1.EntityInsentient;
|
||||||
|
import net.minecraft.server.v1_12_R1.PathfinderGoal;
|
||||||
|
import net.minecraft.server.v1_12_R1.PathfinderGoalSelector;
|
||||||
|
import org.bukkit.craftbukkit.v1_12_R1.entity.CraftEntity;
|
||||||
|
import org.bukkit.entity.Entity;
|
||||||
|
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.LinkedHashSet;
|
||||||
|
|
||||||
|
public class NMS_v1_12_R1 implements NMSInterface {
|
||||||
|
@Override
|
||||||
|
public void clearPathfinderGoals(Entity entity) {
|
||||||
|
EntityInsentient nmsEnt = (EntityInsentient) ((CraftEntity) entity).getHandle();
|
||||||
|
((LinkedHashSet<?>) ReflectionUtils.getField("b", PathfinderGoalSelector.class, nmsEnt.goalSelector)).clear();
|
||||||
|
((LinkedHashSet<?>) ReflectionUtils.getField("c", PathfinderGoalSelector.class, nmsEnt.goalSelector)).clear();
|
||||||
|
((LinkedHashSet<?>) ReflectionUtils.getField("b", PathfinderGoalSelector.class, nmsEnt.targetSelector)).clear();
|
||||||
|
((LinkedHashSet<?>) ReflectionUtils.getField("c", PathfinderGoalSelector.class, nmsEnt.targetSelector)).clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void removePathfinderGoal(Object entity, Class<?> goalClass, boolean isTargetSelector) {
|
||||||
|
if (entity instanceof EntityInsentient) {
|
||||||
|
((EntityInsentient) entity).setGoalTarget(null);
|
||||||
|
if (isTargetSelector) {
|
||||||
|
Iterator<?> goals = ((LinkedHashSet<?>) ReflectionUtils.getField("b", PathfinderGoalSelector.class, ((EntityInsentient) entity).targetSelector)).iterator();
|
||||||
|
while (goals.hasNext()) {
|
||||||
|
Object goal = goals.next();
|
||||||
|
if (ReflectionUtils.getField("a", goal.getClass(), goal).getClass() == goalClass) {
|
||||||
|
goals.remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Iterator<?> goals = ((LinkedHashSet<?>) ReflectionUtils.getField("b", PathfinderGoalSelector.class, ((EntityInsentient) entity).goalSelector)).iterator();
|
||||||
|
while (goals.hasNext()) {
|
||||||
|
Object goal = goals.next();
|
||||||
|
if (ReflectionUtils.getField("a", goal.getClass(), goal).getClass() == goalClass) {
|
||||||
|
goals.remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addPathfinderGoal(Object entity, int priority, Object goal, boolean isTargetSelector) {
|
||||||
|
if (entity instanceof EntityInsentient && goal instanceof PathfinderGoal) {
|
||||||
|
if (isTargetSelector)
|
||||||
|
((EntityInsentient) entity).targetSelector.a(priority, (PathfinderGoal) goal);
|
||||||
|
else
|
||||||
|
((EntityInsentient) entity).goalSelector.a(priority, (PathfinderGoal) goal);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean getNoClip(Entity entity) {
|
||||||
|
net.minecraft.server.v1_12_R1.Entity nmsEntity = ((CraftEntity) entity).getHandle();
|
||||||
|
return nmsEntity.noclip;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setNoClip(Entity entity, boolean noclip) {
|
||||||
|
net.minecraft.server.v1_12_R1.Entity nmsEntity = ((CraftEntity) entity).getHandle();
|
||||||
|
nmsEntity.noclip = noclip;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean getFireProof(Entity entity) {
|
||||||
|
net.minecraft.server.v1_12_R1.Entity nmsEntity = ((CraftEntity) entity).getHandle();
|
||||||
|
return nmsEntity.isFireProof();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setFireProof(Entity entity, boolean fireProof) {
|
||||||
|
net.minecraft.server.v1_12_R1.Entity nmsEntity = ((CraftEntity) entity).getHandle();
|
||||||
|
ReflectionUtils.setField("fireProof", nmsEntity.getClass(), nmsEntity, fireProof);
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public float getEntityStepLength(Entity entity) {
|
||||||
|
net.minecraft.server.v1_12_R1.Entity nmsEntity = ((org.bukkit.craftbukkit.v1_12_R1.entity.CraftEntity) entity).getHandle();
|
||||||
|
return nmsEntity.P;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setEntityStepLength(Entity entity, float length) {
|
||||||
|
net.minecraft.server.v1_12_R1.Entity nmsEntity = ((org.bukkit.craftbukkit.v1_12_R1.entity.CraftEntity) entity).getHandle();
|
||||||
|
nmsEntity.P = length;
|
||||||
|
}
|
||||||
|
}
|
@ -1,17 +1,12 @@
|
|||||||
package me.TheBukor.SkStuff.util;
|
package me.TheBukor.SkStuff.util;
|
||||||
|
|
||||||
|
|
||||||
|
import net.minecraft.server.v1_13_R2.EntityInsentient;
|
||||||
import net.minecraft.server.v1_13_R2.*;
|
import net.minecraft.server.v1_13_R2.PathfinderGoal;
|
||||||
import org.bukkit.Location;
|
import net.minecraft.server.v1_13_R2.PathfinderGoalSelector;
|
||||||
|
|
||||||
import org.bukkit.craftbukkit.v1_13_R2.entity.CraftEntity;
|
import org.bukkit.craftbukkit.v1_13_R2.entity.CraftEntity;
|
||||||
import org.bukkit.craftbukkit.v1_13_R2.entity.CraftLivingEntity;
|
|
||||||
|
|
||||||
import org.bukkit.entity.Entity;
|
import org.bukkit.entity.Entity;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.LinkedHashSet;
|
import java.util.LinkedHashSet;
|
||||||
|
|
||||||
@ -86,30 +81,15 @@ public class NMS_v1_13_R2 implements NMSInterface {
|
|||||||
net.minecraft.server.v1_13_R2.Entity nmsEntity = ((CraftEntity) entity).getHandle();
|
net.minecraft.server.v1_13_R2.Entity nmsEntity = ((CraftEntity) entity).getHandle();
|
||||||
ReflectionUtils.setField("fireProof", nmsEntity.getClass(), nmsEntity, fireProof);
|
ReflectionUtils.setField("fireProof", nmsEntity.getClass(), nmsEntity, fireProof);
|
||||||
}
|
}
|
||||||
|
@Override
|
||||||
|
public float getEntityStepLength(Entity entity) {
|
||||||
|
net.minecraft.server.v1_13_R2.Entity nmsEntity = ((CraftEntity) entity).getHandle();
|
||||||
|
return nmsEntity.Q;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean getElytraGlideState(Entity entity) {
|
public void setEntityStepLength(Entity entity, float length) {
|
||||||
EntityLiving nmsEntity = ((CraftLivingEntity) entity).getHandle();
|
|
||||||
return nmsEntity.getFlag(7);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setElytraGlideState(Entity entity, boolean glide) {
|
|
||||||
EntityLiving nmsEntity = ((CraftLivingEntity) entity).getHandle();
|
|
||||||
nmsEntity.setFlag(7, glide);
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean getNoGravity(Entity entity) {
|
|
||||||
net.minecraft.server.v1_13_R2.Entity nmsEntity = ((CraftEntity) entity).getHandle();
|
net.minecraft.server.v1_13_R2.Entity nmsEntity = ((CraftEntity) entity).getHandle();
|
||||||
return nmsEntity.isNoGravity();
|
nmsEntity.Q = length;
|
||||||
}
|
|
||||||
|
|
||||||
public void setNoGravity(Entity entity, boolean noGravity) {
|
|
||||||
net.minecraft.server.v1_13_R2.Entity nmsEntity = ((CraftEntity) entity).getHandle();
|
|
||||||
nmsEntity.setNoGravity(noGravity);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -2,11 +2,9 @@ package me.TheBukor.SkStuff.util;
|
|||||||
|
|
||||||
|
|
||||||
import net.minecraft.server.v1_14_R1.EntityInsentient;
|
import net.minecraft.server.v1_14_R1.EntityInsentient;
|
||||||
import net.minecraft.server.v1_14_R1.EntityLiving;
|
|
||||||
import net.minecraft.server.v1_14_R1.PathfinderGoal;
|
import net.minecraft.server.v1_14_R1.PathfinderGoal;
|
||||||
import net.minecraft.server.v1_14_R1.PathfinderGoalSelector;
|
import net.minecraft.server.v1_14_R1.PathfinderGoalSelector;
|
||||||
import org.bukkit.craftbukkit.v1_14_R1.entity.CraftEntity;
|
import org.bukkit.craftbukkit.v1_14_R1.entity.CraftEntity;
|
||||||
import org.bukkit.craftbukkit.v1_14_R1.entity.CraftLivingEntity;
|
|
||||||
import org.bukkit.entity.Entity;
|
import org.bukkit.entity.Entity;
|
||||||
|
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
@ -83,30 +81,15 @@ public class NMS_v1_14_R1 implements NMSInterface {
|
|||||||
net.minecraft.server.v1_14_R1.Entity nmsEntity = ((CraftEntity) entity).getHandle();
|
net.minecraft.server.v1_14_R1.Entity nmsEntity = ((CraftEntity) entity).getHandle();
|
||||||
ReflectionUtils.setField("fireProof", nmsEntity.getClass(), nmsEntity, fireProof);
|
ReflectionUtils.setField("fireProof", nmsEntity.getClass(), nmsEntity, fireProof);
|
||||||
}
|
}
|
||||||
|
@Override
|
||||||
|
public float getEntityStepLength(Entity entity) {
|
||||||
|
net.minecraft.server.v1_14_R1.Entity nmsEntity = ((CraftEntity) entity).getHandle();
|
||||||
|
return nmsEntity.K;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean getElytraGlideState(Entity entity) {
|
public void setEntityStepLength(Entity entity, float length) {
|
||||||
EntityLiving nmsEntity = ((CraftLivingEntity) entity).getHandle();
|
|
||||||
return nmsEntity.getFlag(7);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setElytraGlideState(Entity entity, boolean glide) {
|
|
||||||
EntityLiving nmsEntity = ((CraftLivingEntity) entity).getHandle();
|
|
||||||
nmsEntity.setFlag(7, glide);
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean getNoGravity(Entity entity) {
|
|
||||||
net.minecraft.server.v1_14_R1.Entity nmsEntity = ((CraftEntity) entity).getHandle();
|
net.minecraft.server.v1_14_R1.Entity nmsEntity = ((CraftEntity) entity).getHandle();
|
||||||
return nmsEntity.isNoGravity();
|
nmsEntity.K = length;
|
||||||
}
|
|
||||||
|
|
||||||
public void setNoGravity(Entity entity, boolean noGravity) {
|
|
||||||
net.minecraft.server.v1_14_R1.Entity nmsEntity = ((CraftEntity) entity).getHandle();
|
|
||||||
nmsEntity.setNoGravity(noGravity);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -2,11 +2,9 @@ package me.TheBukor.SkStuff.util;
|
|||||||
|
|
||||||
|
|
||||||
import net.minecraft.server.v1_15_R1.EntityInsentient;
|
import net.minecraft.server.v1_15_R1.EntityInsentient;
|
||||||
import net.minecraft.server.v1_15_R1.EntityLiving;
|
|
||||||
import net.minecraft.server.v1_15_R1.PathfinderGoal;
|
import net.minecraft.server.v1_15_R1.PathfinderGoal;
|
||||||
import net.minecraft.server.v1_15_R1.PathfinderGoalSelector;
|
import net.minecraft.server.v1_15_R1.PathfinderGoalSelector;
|
||||||
import org.bukkit.craftbukkit.v1_15_R1.entity.CraftEntity;
|
import org.bukkit.craftbukkit.v1_15_R1.entity.CraftEntity;
|
||||||
import org.bukkit.craftbukkit.v1_15_R1.entity.CraftLivingEntity;
|
|
||||||
import org.bukkit.entity.Entity;
|
import org.bukkit.entity.Entity;
|
||||||
|
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
@ -83,30 +81,14 @@ public class NMS_v1_15_R1 implements NMSInterface {
|
|||||||
net.minecraft.server.v1_15_R1.Entity nmsEntity = ((CraftEntity) entity).getHandle();
|
net.minecraft.server.v1_15_R1.Entity nmsEntity = ((CraftEntity) entity).getHandle();
|
||||||
ReflectionUtils.setField("fireProof", nmsEntity.getClass(), nmsEntity, fireProof);
|
ReflectionUtils.setField("fireProof", nmsEntity.getClass(), nmsEntity, fireProof);
|
||||||
}
|
}
|
||||||
|
public float getEntityStepLength(Entity entity) {
|
||||||
|
net.minecraft.server.v1_15_R1.Entity nmsEntity = ((CraftEntity) entity).getHandle();
|
||||||
|
return nmsEntity.H;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean getElytraGlideState(Entity entity) {
|
public void setEntityStepLength(Entity entity, float length) {
|
||||||
EntityLiving nmsEntity = ((CraftLivingEntity) entity).getHandle();
|
|
||||||
return nmsEntity.getFlag(7);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setElytraGlideState(Entity entity, boolean glide) {
|
|
||||||
EntityLiving nmsEntity = ((CraftLivingEntity) entity).getHandle();
|
|
||||||
nmsEntity.setFlag(7, glide);
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean getNoGravity(Entity entity) {
|
|
||||||
net.minecraft.server.v1_15_R1.Entity nmsEntity = ((CraftEntity) entity).getHandle();
|
net.minecraft.server.v1_15_R1.Entity nmsEntity = ((CraftEntity) entity).getHandle();
|
||||||
return nmsEntity.isNoGravity();
|
nmsEntity.H = length;
|
||||||
}
|
|
||||||
|
|
||||||
public void setNoGravity(Entity entity, boolean noGravity) {
|
|
||||||
net.minecraft.server.v1_15_R1.Entity nmsEntity = ((CraftEntity) entity).getHandle();
|
|
||||||
nmsEntity.setNoGravity(noGravity);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
94
src/me/TheBukor/SkStuff/util/NMS_v1_16_R1.java
Normal file
94
src/me/TheBukor/SkStuff/util/NMS_v1_16_R1.java
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
package me.TheBukor.SkStuff.util;
|
||||||
|
|
||||||
|
|
||||||
|
import net.minecraft.server.v1_16_R1.EntityInsentient;
|
||||||
|
import net.minecraft.server.v1_16_R1.PathfinderGoal;
|
||||||
|
import net.minecraft.server.v1_16_R1.PathfinderGoalSelector;
|
||||||
|
import org.bukkit.craftbukkit.v1_16_R1.entity.CraftEntity;
|
||||||
|
import org.bukkit.entity.Entity;
|
||||||
|
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.LinkedHashSet;
|
||||||
|
|
||||||
|
public class NMS_v1_16_R1 implements NMSInterface {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void clearPathfinderGoals(Entity entity) {
|
||||||
|
EntityInsentient nmsEnt = (EntityInsentient) ((CraftEntity) entity).getHandle();
|
||||||
|
((LinkedHashSet<?>) ReflectionUtils.getField("b", PathfinderGoalSelector.class, nmsEnt.goalSelector)).clear();
|
||||||
|
((LinkedHashSet<?>) ReflectionUtils.getField("c", PathfinderGoalSelector.class, nmsEnt.goalSelector)).clear();
|
||||||
|
((LinkedHashSet<?>) ReflectionUtils.getField("b", PathfinderGoalSelector.class, nmsEnt.targetSelector)).clear();
|
||||||
|
((LinkedHashSet<?>) ReflectionUtils.getField("c", PathfinderGoalSelector.class, nmsEnt.targetSelector)).clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void removePathfinderGoal(Object entity, Class<?> goalClass, boolean isTargetSelector) {
|
||||||
|
if (entity instanceof EntityInsentient) {
|
||||||
|
((EntityInsentient) entity).setGoalTarget(null);
|
||||||
|
if (isTargetSelector) {
|
||||||
|
Iterator<?> goals = ((LinkedHashSet<?>) ReflectionUtils.getField("b", PathfinderGoalSelector.class, ((EntityInsentient) entity).targetSelector)).iterator();
|
||||||
|
while (goals.hasNext()) {
|
||||||
|
Object goal = goals.next();
|
||||||
|
if (ReflectionUtils.getField("a", goal.getClass(), goal).getClass() == goalClass) {
|
||||||
|
goals.remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Iterator<?> goals = ((LinkedHashSet<?>) ReflectionUtils.getField("b", PathfinderGoalSelector.class, ((EntityInsentient) entity).goalSelector)).iterator();
|
||||||
|
while (goals.hasNext()) {
|
||||||
|
Object goal = goals.next();
|
||||||
|
if (ReflectionUtils.getField("a", goal.getClass(), goal).getClass() == goalClass) {
|
||||||
|
goals.remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addPathfinderGoal(Object entity, int priority, Object goal, boolean isTargetSelector) {
|
||||||
|
if (entity instanceof EntityInsentient && goal instanceof PathfinderGoal) {
|
||||||
|
if (isTargetSelector)
|
||||||
|
((EntityInsentient) entity).targetSelector.a(priority, (PathfinderGoal) goal);
|
||||||
|
else
|
||||||
|
((EntityInsentient) entity).goalSelector.a(priority, (PathfinderGoal) goal);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean getNoClip(Entity entity) {
|
||||||
|
net.minecraft.server.v1_16_R1.Entity nmsEntity = ((CraftEntity) entity).getHandle();
|
||||||
|
return nmsEntity.noclip;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setNoClip(Entity entity, boolean noclip) {
|
||||||
|
net.minecraft.server.v1_16_R1.Entity nmsEntity = ((CraftEntity) entity).getHandle();
|
||||||
|
nmsEntity.noclip = noclip;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean getFireProof(Entity entity) {
|
||||||
|
net.minecraft.server.v1_16_R1.Entity nmsEntity = ((CraftEntity) entity).getHandle();
|
||||||
|
return nmsEntity.isFireProof();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setFireProof(Entity entity, boolean fireProof) {
|
||||||
|
net.minecraft.server.v1_16_R1.Entity nmsEntity = ((CraftEntity) entity).getHandle();
|
||||||
|
ReflectionUtils.setField("fireProof", nmsEntity.getClass(), nmsEntity, fireProof);
|
||||||
|
}
|
||||||
|
public float getEntityStepLength(Entity entity) {
|
||||||
|
net.minecraft.server.v1_16_R1.Entity nmsEntity = ((CraftEntity) entity).getHandle();
|
||||||
|
return nmsEntity.G;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setEntityStepLength(Entity entity, float length) {
|
||||||
|
net.minecraft.server.v1_16_R1.Entity nmsEntity = ((CraftEntity) entity).getHandle();
|
||||||
|
nmsEntity.G = length;
|
||||||
|
}
|
||||||
|
}
|
92
src/me/TheBukor/SkStuff/util/NMS_v1_8_R3.java
Normal file
92
src/me/TheBukor/SkStuff/util/NMS_v1_8_R3.java
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
package me.TheBukor.SkStuff.util;
|
||||||
|
|
||||||
|
import net.minecraft.server.v1_8_R3.EntityInsentient;
|
||||||
|
import net.minecraft.server.v1_8_R3.PathfinderGoal;
|
||||||
|
import net.minecraft.server.v1_8_R3.PathfinderGoalSelector;
|
||||||
|
import org.bukkit.craftbukkit.v1_8_R3.entity.CraftEntity;
|
||||||
|
import org.bukkit.entity.Entity;
|
||||||
|
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class NMS_v1_8_R3 implements NMSInterface {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void clearPathfinderGoals(Entity entity) {
|
||||||
|
EntityInsentient nmsEnt = (EntityInsentient) ((CraftEntity) entity).getHandle();
|
||||||
|
((List<?>) ReflectionUtils.getField("b", PathfinderGoalSelector.class, nmsEnt.goalSelector)).clear();
|
||||||
|
((List<?>) ReflectionUtils.getField("c", PathfinderGoalSelector.class, nmsEnt.goalSelector)).clear();
|
||||||
|
((List<?>) ReflectionUtils.getField("b", PathfinderGoalSelector.class, nmsEnt.targetSelector)).clear();
|
||||||
|
((List<?>) ReflectionUtils.getField("c", PathfinderGoalSelector.class, nmsEnt.targetSelector)).clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void removePathfinderGoal(Object entity, Class<?> goalClass, boolean isTargetSelector) {
|
||||||
|
if (entity instanceof EntityInsentient) {
|
||||||
|
((EntityInsentient) entity).setGoalTarget(null);
|
||||||
|
if (isTargetSelector) {
|
||||||
|
Iterator<?> goals = ((List<?>) ReflectionUtils.getField("b", PathfinderGoalSelector.class, ((EntityInsentient) entity).targetSelector)).iterator();
|
||||||
|
while (goals.hasNext()) {
|
||||||
|
Object goal = goals.next();
|
||||||
|
if (ReflectionUtils.getField("a", goal.getClass(), goal).getClass() == goalClass) {
|
||||||
|
goals.remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Iterator<?> goals = ((List<?>) ReflectionUtils.getField("b", PathfinderGoalSelector.class, ((EntityInsentient) entity).goalSelector)).iterator();
|
||||||
|
while (goals.hasNext()) {
|
||||||
|
Object goal = goals.next();
|
||||||
|
if (ReflectionUtils.getField("a", goal.getClass(), goal).getClass() == goalClass) {
|
||||||
|
goals.remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addPathfinderGoal(Object entity, int priority, Object goal, boolean isTargetSelector) {
|
||||||
|
if (entity instanceof EntityInsentient && goal instanceof PathfinderGoal) {
|
||||||
|
if (isTargetSelector)
|
||||||
|
((EntityInsentient) entity).targetSelector.a(priority, (PathfinderGoal) goal);
|
||||||
|
else
|
||||||
|
((EntityInsentient) entity).goalSelector.a(priority, (PathfinderGoal) goal);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean getNoClip(Entity entity) {
|
||||||
|
net.minecraft.server.v1_8_R3.Entity nmsEntity = ((CraftEntity) entity).getHandle();
|
||||||
|
return nmsEntity.noclip;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setNoClip(Entity entity, boolean noclip) {
|
||||||
|
net.minecraft.server.v1_8_R3.Entity nmsEntity = ((CraftEntity) entity).getHandle();
|
||||||
|
nmsEntity.noclip = noclip;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean getFireProof(Entity entity) {
|
||||||
|
net.minecraft.server.v1_8_R3.Entity nmsEntity = ((CraftEntity) entity).getHandle();
|
||||||
|
return nmsEntity.isFireProof();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setFireProof(Entity entity, boolean fireProof) {
|
||||||
|
net.minecraft.server.v1_8_R3.Entity nmsEntity = ((CraftEntity) entity).getHandle();
|
||||||
|
ReflectionUtils.setField("fireProof", nmsEntity.getClass(), nmsEntity, fireProof);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public float getEntityStepLength(Entity entity) {
|
||||||
|
net.minecraft.server.v1_8_R3.Entity nmsEntity = ((CraftEntity) entity).getHandle();
|
||||||
|
return nmsEntity.S;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setEntityStepLength(Entity entity, float length) {
|
||||||
|
net.minecraft.server.v1_8_R3.Entity nmsEntity = ((CraftEntity) entity).getHandle();
|
||||||
|
nmsEntity.S = length;
|
||||||
|
}
|
||||||
|
}
|
91
src/me/TheBukor/SkStuff/util/NMS_v1_9_R1.java
Normal file
91
src/me/TheBukor/SkStuff/util/NMS_v1_9_R1.java
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
package me.TheBukor.SkStuff.util;
|
||||||
|
|
||||||
|
import net.minecraft.server.v1_9_R1.EntityInsentient;
|
||||||
|
import net.minecraft.server.v1_9_R1.PathfinderGoal;
|
||||||
|
import net.minecraft.server.v1_9_R1.PathfinderGoalSelector;
|
||||||
|
import org.bukkit.craftbukkit.v1_9_R1.entity.CraftEntity;
|
||||||
|
import org.bukkit.entity.Entity;
|
||||||
|
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.LinkedHashSet;
|
||||||
|
|
||||||
|
public class NMS_v1_9_R1 implements NMSInterface {
|
||||||
|
@Override
|
||||||
|
public void clearPathfinderGoals(Entity entity) {
|
||||||
|
EntityInsentient nmsEnt = (EntityInsentient) ((CraftEntity) entity).getHandle();
|
||||||
|
((LinkedHashSet<?>) ReflectionUtils.getField("b", PathfinderGoalSelector.class, nmsEnt.goalSelector)).clear();
|
||||||
|
((LinkedHashSet<?>) ReflectionUtils.getField("c", PathfinderGoalSelector.class, nmsEnt.goalSelector)).clear();
|
||||||
|
((LinkedHashSet<?>) ReflectionUtils.getField("b", PathfinderGoalSelector.class, nmsEnt.targetSelector)).clear();
|
||||||
|
((LinkedHashSet<?>) ReflectionUtils.getField("c", PathfinderGoalSelector.class, nmsEnt.targetSelector)).clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void removePathfinderGoal(Object entity, Class<?> goalClass, boolean isTargetSelector) {
|
||||||
|
if (entity instanceof EntityInsentient) {
|
||||||
|
((EntityInsentient) entity).setGoalTarget(null);
|
||||||
|
if (isTargetSelector) {
|
||||||
|
Iterator<?> goals = ((LinkedHashSet<?>) ReflectionUtils.getField("b", PathfinderGoalSelector.class, ((EntityInsentient) entity).targetSelector)).iterator();
|
||||||
|
while (goals.hasNext()) {
|
||||||
|
Object goal = goals.next();
|
||||||
|
if (ReflectionUtils.getField("a", goal.getClass(), goal).getClass() == goalClass) {
|
||||||
|
goals.remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Iterator<?> goals = ((LinkedHashSet<?>) ReflectionUtils.getField("b", PathfinderGoalSelector.class, ((EntityInsentient) entity).goalSelector)).iterator();
|
||||||
|
while (goals.hasNext()) {
|
||||||
|
Object goal = goals.next();
|
||||||
|
if (ReflectionUtils.getField("a", goal.getClass(), goal).getClass() == goalClass) {
|
||||||
|
goals.remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addPathfinderGoal(Object entity, int priority, Object goal, boolean isTargetSelector) {
|
||||||
|
if (entity instanceof EntityInsentient && goal instanceof PathfinderGoal) {
|
||||||
|
if (isTargetSelector)
|
||||||
|
((EntityInsentient) entity).targetSelector.a(priority, (PathfinderGoal) goal);
|
||||||
|
else
|
||||||
|
((EntityInsentient) entity).goalSelector.a(priority, (PathfinderGoal) goal);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean getNoClip(Entity entity) {
|
||||||
|
net.minecraft.server.v1_9_R1.Entity nmsEntity = ((CraftEntity) entity).getHandle();
|
||||||
|
return nmsEntity.noclip;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setNoClip(Entity entity, boolean noclip) {
|
||||||
|
net.minecraft.server.v1_9_R1.Entity nmsEntity = ((CraftEntity) entity).getHandle();
|
||||||
|
nmsEntity.noclip = noclip;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean getFireProof(Entity entity) {
|
||||||
|
net.minecraft.server.v1_9_R1.Entity nmsEntity = ((CraftEntity) entity).getHandle();
|
||||||
|
return nmsEntity.isFireProof();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setFireProof(Entity entity, boolean fireProof) {
|
||||||
|
net.minecraft.server.v1_9_R1.Entity nmsEntity = ((CraftEntity) entity).getHandle();
|
||||||
|
ReflectionUtils.setField("fireProof", nmsEntity.getClass(), nmsEntity, fireProof);
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public float getEntityStepLength(Entity entity) {
|
||||||
|
net.minecraft.server.v1_9_R1.Entity nmsEntity = ((CraftEntity) entity).getHandle();
|
||||||
|
return nmsEntity.P;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setEntityStepLength(Entity entity, float length) {
|
||||||
|
net.minecraft.server.v1_9_R1.Entity nmsEntity = ((CraftEntity) entity).getHandle();
|
||||||
|
nmsEntity.P = length;
|
||||||
|
}
|
||||||
|
}
|
91
src/me/TheBukor/SkStuff/util/NMS_v1_9_R2.java
Normal file
91
src/me/TheBukor/SkStuff/util/NMS_v1_9_R2.java
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
package me.TheBukor.SkStuff.util;
|
||||||
|
|
||||||
|
import net.minecraft.server.v1_9_R2.EntityInsentient;
|
||||||
|
import net.minecraft.server.v1_9_R2.PathfinderGoal;
|
||||||
|
import net.minecraft.server.v1_9_R2.PathfinderGoalSelector;
|
||||||
|
import org.bukkit.craftbukkit.v1_9_R2.entity.CraftEntity;
|
||||||
|
import org.bukkit.entity.Entity;
|
||||||
|
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.LinkedHashSet;
|
||||||
|
|
||||||
|
public class NMS_v1_9_R2 implements NMSInterface {
|
||||||
|
@Override
|
||||||
|
public void clearPathfinderGoals(Entity entity) {
|
||||||
|
EntityInsentient nmsEnt = (EntityInsentient) ((CraftEntity) entity).getHandle();
|
||||||
|
((LinkedHashSet<?>) ReflectionUtils.getField("b", PathfinderGoalSelector.class, nmsEnt.goalSelector)).clear();
|
||||||
|
((LinkedHashSet<?>) ReflectionUtils.getField("c", PathfinderGoalSelector.class, nmsEnt.goalSelector)).clear();
|
||||||
|
((LinkedHashSet<?>) ReflectionUtils.getField("b", PathfinderGoalSelector.class, nmsEnt.targetSelector)).clear();
|
||||||
|
((LinkedHashSet<?>) ReflectionUtils.getField("c", PathfinderGoalSelector.class, nmsEnt.targetSelector)).clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void removePathfinderGoal(Object entity, Class<?> goalClass, boolean isTargetSelector) {
|
||||||
|
if (entity instanceof EntityInsentient) {
|
||||||
|
((EntityInsentient) entity).setGoalTarget(null);
|
||||||
|
if (isTargetSelector) {
|
||||||
|
Iterator<?> goals = ((LinkedHashSet<?>) ReflectionUtils.getField("b", PathfinderGoalSelector.class, ((EntityInsentient) entity).targetSelector)).iterator();
|
||||||
|
while (goals.hasNext()) {
|
||||||
|
Object goal = goals.next();
|
||||||
|
if (ReflectionUtils.getField("a", goal.getClass(), goal).getClass() == goalClass) {
|
||||||
|
goals.remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Iterator<?> goals = ((LinkedHashSet<?>) ReflectionUtils.getField("b", PathfinderGoalSelector.class, ((EntityInsentient) entity).goalSelector)).iterator();
|
||||||
|
while (goals.hasNext()) {
|
||||||
|
Object goal = goals.next();
|
||||||
|
if (ReflectionUtils.getField("a", goal.getClass(), goal).getClass() == goalClass) {
|
||||||
|
goals.remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addPathfinderGoal(Object entity, int priority, Object goal, boolean isTargetSelector) {
|
||||||
|
if (entity instanceof EntityInsentient && goal instanceof PathfinderGoal) {
|
||||||
|
if (isTargetSelector)
|
||||||
|
((EntityInsentient) entity).targetSelector.a(priority, (PathfinderGoal) goal);
|
||||||
|
else
|
||||||
|
((EntityInsentient) entity).goalSelector.a(priority, (PathfinderGoal) goal);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean getNoClip(Entity entity) {
|
||||||
|
net.minecraft.server.v1_9_R2.Entity nmsEntity = ((CraftEntity) entity).getHandle();
|
||||||
|
return nmsEntity.noclip;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setNoClip(Entity entity, boolean noclip) {
|
||||||
|
net.minecraft.server.v1_9_R2.Entity nmsEntity = ((CraftEntity) entity).getHandle();
|
||||||
|
nmsEntity.noclip = noclip;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean getFireProof(Entity entity) {
|
||||||
|
net.minecraft.server.v1_9_R2.Entity nmsEntity = ((CraftEntity) entity).getHandle();
|
||||||
|
return nmsEntity.isFireProof();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setFireProof(Entity entity, boolean fireProof) {
|
||||||
|
net.minecraft.server.v1_9_R2.Entity nmsEntity = ((CraftEntity) entity).getHandle();
|
||||||
|
ReflectionUtils.setField("fireProof", nmsEntity.getClass(), nmsEntity, fireProof);
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public float getEntityStepLength(Entity entity) {
|
||||||
|
net.minecraft.server.v1_9_R2.Entity nmsEntity = ((CraftEntity) entity).getHandle();
|
||||||
|
return nmsEntity.P;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setEntityStepLength(Entity entity, float length) {
|
||||||
|
net.minecraft.server.v1_9_R2.Entity nmsEntity = ((CraftEntity) entity).getHandle();
|
||||||
|
nmsEntity.P = length;
|
||||||
|
}
|
||||||
|
}
|
@ -1,785 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2011-2013 Tyler Blair. All rights reserved.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without modification, are
|
|
||||||
* permitted provided that the following conditions are met:
|
|
||||||
*
|
|
||||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
|
||||||
* conditions and the following disclaimer.
|
|
||||||
*
|
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
|
||||||
* of conditions and the following disclaimer in the documentation and/or other materials
|
|
||||||
* provided with the distribution.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ''AS IS'' AND ANY EXPRESS OR IMPLIED
|
|
||||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR
|
|
||||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
||||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
||||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
|
||||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
|
||||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
|
||||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
*
|
|
||||||
* The views and conclusions contained in the software and documentation are those of the
|
|
||||||
* authors and contributors and should not be interpreted as representing official policies,
|
|
||||||
* either expressed or implied, of anybody else.
|
|
||||||
*/
|
|
||||||
package org.mcstats;
|
|
||||||
|
|
||||||
import org.bukkit.Bukkit;
|
|
||||||
import org.bukkit.Server;
|
|
||||||
import org.bukkit.configuration.InvalidConfigurationException;
|
|
||||||
import org.bukkit.configuration.file.YamlConfiguration;
|
|
||||||
import org.bukkit.entity.Player;
|
|
||||||
import org.bukkit.plugin.Plugin;
|
|
||||||
import org.bukkit.plugin.PluginDescriptionFile;
|
|
||||||
import org.bukkit.scheduler.BukkitTask;
|
|
||||||
|
|
||||||
import java.io.BufferedReader;
|
|
||||||
import java.io.ByteArrayOutputStream;
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStreamReader;
|
|
||||||
import java.io.OutputStream;
|
|
||||||
import java.io.UnsupportedEncodingException;
|
|
||||||
import java.lang.reflect.Method;
|
|
||||||
import java.net.Proxy;
|
|
||||||
import java.net.URL;
|
|
||||||
import java.net.URLConnection;
|
|
||||||
import java.net.URLEncoder;
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.Iterator;
|
|
||||||
import java.util.LinkedHashSet;
|
|
||||||
import java.util.Set;
|
|
||||||
import java.util.UUID;
|
|
||||||
import java.util.logging.Level;
|
|
||||||
import java.util.zip.GZIPOutputStream;
|
|
||||||
|
|
||||||
public class Metrics {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The current revision number
|
|
||||||
*/
|
|
||||||
private final static int REVISION = 7;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The base url of the metrics domain
|
|
||||||
*/
|
|
||||||
private static final String BASE_URL = "http://report.mcstats.org";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The url used to report a server's status
|
|
||||||
*/
|
|
||||||
private static final String REPORT_URL = "/plugin/%s";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Interval of time to ping (in minutes)
|
|
||||||
*/
|
|
||||||
private static final int PING_INTERVAL = 15;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The plugin this metrics submits for
|
|
||||||
*/
|
|
||||||
private final Plugin plugin;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* All of the custom graphs to submit to metrics
|
|
||||||
*/
|
|
||||||
private final Set<Graph> graphs = Collections.synchronizedSet(new HashSet<Graph>());
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The plugin configuration file
|
|
||||||
*/
|
|
||||||
private final YamlConfiguration configuration;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The plugin configuration file
|
|
||||||
*/
|
|
||||||
private final File configurationFile;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Unique server id
|
|
||||||
*/
|
|
||||||
private final String guid;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Debug mode
|
|
||||||
*/
|
|
||||||
private final boolean debug;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Lock for synchronization
|
|
||||||
*/
|
|
||||||
private final Object optOutLock = new Object();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The scheduled task
|
|
||||||
*/
|
|
||||||
private volatile BukkitTask task = null;
|
|
||||||
|
|
||||||
public Metrics(final Plugin plugin) throws IOException {
|
|
||||||
if (plugin == null) {
|
|
||||||
throw new IllegalArgumentException("Plugin cannot be null");
|
|
||||||
}
|
|
||||||
|
|
||||||
this.plugin = plugin;
|
|
||||||
|
|
||||||
// load the config
|
|
||||||
configurationFile = getConfigFile();
|
|
||||||
configuration = YamlConfiguration.loadConfiguration(configurationFile);
|
|
||||||
|
|
||||||
// add some defaults
|
|
||||||
configuration.addDefault("opt-out", false);
|
|
||||||
configuration.addDefault("guid", UUID.randomUUID().toString());
|
|
||||||
configuration.addDefault("debug", false);
|
|
||||||
|
|
||||||
// Do we need to create the file?
|
|
||||||
if (configuration.get("guid", null) == null) {
|
|
||||||
configuration.options().header("http://mcstats.org").copyDefaults(true);
|
|
||||||
configuration.save(configurationFile);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Load the guid then
|
|
||||||
guid = configuration.getString("guid");
|
|
||||||
debug = configuration.getBoolean("debug", false);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Construct and create a Graph that can be used to separate specific plotters to their own graphs on the metrics
|
|
||||||
* website. Plotters can be added to the graph object returned.
|
|
||||||
*
|
|
||||||
* @param name The name of the graph
|
|
||||||
* @return Graph object created. Will never return NULL under normal circumstances unless bad parameters are given
|
|
||||||
*/
|
|
||||||
public Graph createGraph(final String name) {
|
|
||||||
if (name == null) {
|
|
||||||
throw new IllegalArgumentException("Graph name cannot be null");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Construct the graph object
|
|
||||||
final Graph graph = new Graph(name);
|
|
||||||
|
|
||||||
// Now we can add our graph
|
|
||||||
graphs.add(graph);
|
|
||||||
|
|
||||||
// and return back
|
|
||||||
return graph;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add a Graph object to BukkitMetrics that represents data for the plugin that should be sent to the backend
|
|
||||||
*
|
|
||||||
* @param graph The name of the graph
|
|
||||||
*/
|
|
||||||
public void addGraph(final Graph graph) {
|
|
||||||
if (graph == null) {
|
|
||||||
throw new IllegalArgumentException("Graph cannot be null");
|
|
||||||
}
|
|
||||||
|
|
||||||
graphs.add(graph);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Start measuring statistics. This will immediately create an async repeating task as the plugin and send the
|
|
||||||
* initial data to the metrics backend, and then after that it will post in increments of PING_INTERVAL * 1200
|
|
||||||
* ticks.
|
|
||||||
*
|
|
||||||
* @return True if statistics measuring is running, otherwise false.
|
|
||||||
*/
|
|
||||||
public boolean start() {
|
|
||||||
synchronized (optOutLock) {
|
|
||||||
// Did we opt out?
|
|
||||||
if (isOptOut()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Is metrics already running?
|
|
||||||
if (task != null) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Begin hitting the server with glorious data
|
|
||||||
task = plugin.getServer().getScheduler().runTaskTimerAsynchronously(plugin, new Runnable() {
|
|
||||||
|
|
||||||
private boolean firstPost = true;
|
|
||||||
|
|
||||||
public void run() {
|
|
||||||
try {
|
|
||||||
// This has to be synchronized or it can collide with the disable method.
|
|
||||||
synchronized (optOutLock) {
|
|
||||||
// Disable Task, if it is running and the server owner decided to opt-out
|
|
||||||
if (isOptOut() && task != null) {
|
|
||||||
task.cancel();
|
|
||||||
task = null;
|
|
||||||
// Tell all plotters to stop gathering information.
|
|
||||||
for (Graph graph : graphs) {
|
|
||||||
graph.onOptOut();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// We use the inverse of firstPost because if it is the first time we are posting,
|
|
||||||
// it is not a interval ping, so it evaluates to FALSE
|
|
||||||
// Each time thereafter it will evaluate to TRUE, i.e PING!
|
|
||||||
postPlugin(!firstPost);
|
|
||||||
|
|
||||||
// After the first post we set firstPost to false
|
|
||||||
// Each post thereafter will be a ping
|
|
||||||
firstPost = false;
|
|
||||||
} catch (IOException e) {
|
|
||||||
if (debug) {
|
|
||||||
Bukkit.getLogger().log(Level.INFO, "[Metrics] " + e.getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}, 0, PING_INTERVAL * 1200);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Has the server owner denied plugin metrics?
|
|
||||||
*
|
|
||||||
* @return true if metrics should be opted out of it
|
|
||||||
*/
|
|
||||||
public boolean isOptOut() {
|
|
||||||
synchronized (optOutLock) {
|
|
||||||
try {
|
|
||||||
// Reload the metrics file
|
|
||||||
configuration.load(getConfigFile());
|
|
||||||
} catch (IOException ex) {
|
|
||||||
if (debug) {
|
|
||||||
Bukkit.getLogger().log(Level.INFO, "[Metrics] " + ex.getMessage());
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
} catch (InvalidConfigurationException ex) {
|
|
||||||
if (debug) {
|
|
||||||
Bukkit.getLogger().log(Level.INFO, "[Metrics] " + ex.getMessage());
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return configuration.getBoolean("opt-out", false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Enables metrics for the server by setting "opt-out" to false in the config file and starting the metrics task.
|
|
||||||
*
|
|
||||||
* @throws java.io.IOException
|
|
||||||
*/
|
|
||||||
public void enable() throws IOException {
|
|
||||||
// This has to be synchronized or it can collide with the check in the task.
|
|
||||||
synchronized (optOutLock) {
|
|
||||||
// Check if the server owner has already set opt-out, if not, set it.
|
|
||||||
if (isOptOut()) {
|
|
||||||
configuration.set("opt-out", false);
|
|
||||||
configuration.save(configurationFile);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Enable Task, if it is not running
|
|
||||||
if (task == null) {
|
|
||||||
start();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Disables metrics for the server by setting "opt-out" to true in the config file and canceling the metrics task.
|
|
||||||
*
|
|
||||||
* @throws java.io.IOException
|
|
||||||
*/
|
|
||||||
public void disable() throws IOException {
|
|
||||||
// This has to be synchronized or it can collide with the check in the task.
|
|
||||||
synchronized (optOutLock) {
|
|
||||||
// Check if the server owner has already set opt-out, if not, set it.
|
|
||||||
if (!isOptOut()) {
|
|
||||||
configuration.set("opt-out", true);
|
|
||||||
configuration.save(configurationFile);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Disable Task, if it is running
|
|
||||||
if (task != null) {
|
|
||||||
task.cancel();
|
|
||||||
task = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the File object of the config file that should be used to store data such as the GUID and opt-out status
|
|
||||||
*
|
|
||||||
* @return the File object for the config file
|
|
||||||
*/
|
|
||||||
public File getConfigFile() {
|
|
||||||
// I believe the easiest way to get the base folder (e.g craftbukkit set via -P) for plugins to use
|
|
||||||
// is to abuse the plugin object we already have
|
|
||||||
// plugin.getDataFolder() => base/plugins/PluginA/
|
|
||||||
// pluginsFolder => base/plugins/
|
|
||||||
// The base is not necessarily relative to the startup directory.
|
|
||||||
File pluginsFolder = plugin.getDataFolder().getParentFile();
|
|
||||||
|
|
||||||
// return => base/plugins/PluginMetrics/config.yml
|
|
||||||
return new File(new File(pluginsFolder, "PluginMetrics"), "config.yml");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the online player (backwards compatibility)
|
|
||||||
*
|
|
||||||
* @return online player amount
|
|
||||||
*/
|
|
||||||
private int getOnlinePlayers() {
|
|
||||||
try {
|
|
||||||
Method onlinePlayerMethod = Server.class.getMethod("getOnlinePlayers");
|
|
||||||
if(onlinePlayerMethod.getReturnType().equals(Collection.class)) {
|
|
||||||
return ((Collection<?>)onlinePlayerMethod.invoke(Bukkit.getServer())).size();
|
|
||||||
} else {
|
|
||||||
return ((Player[])onlinePlayerMethod.invoke(Bukkit.getServer())).length;
|
|
||||||
}
|
|
||||||
} catch (Exception ex) {
|
|
||||||
if (debug) {
|
|
||||||
Bukkit.getLogger().log(Level.INFO, "[Metrics] " + ex.getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Generic method that posts a plugin to the metrics website
|
|
||||||
*/
|
|
||||||
private void postPlugin(final boolean isPing) throws IOException {
|
|
||||||
// Server software specific section
|
|
||||||
PluginDescriptionFile description = plugin.getDescription();
|
|
||||||
String pluginName = description.getName();
|
|
||||||
boolean onlineMode = Bukkit.getServer().getOnlineMode(); // TRUE if online mode is enabled
|
|
||||||
String pluginVersion = description.getVersion();
|
|
||||||
String serverVersion = Bukkit.getVersion();
|
|
||||||
int playersOnline = this.getOnlinePlayers();
|
|
||||||
|
|
||||||
// END server software specific section -- all code below does not use any code outside of this class / Java
|
|
||||||
|
|
||||||
// Construct the post data
|
|
||||||
StringBuilder json = new StringBuilder(1024);
|
|
||||||
json.append('{');
|
|
||||||
|
|
||||||
// The plugin's description file containg all of the plugin data such as name, version, author, etc
|
|
||||||
appendJSONPair(json, "guid", guid);
|
|
||||||
appendJSONPair(json, "plugin_version", pluginVersion);
|
|
||||||
appendJSONPair(json, "server_version", serverVersion);
|
|
||||||
appendJSONPair(json, "players_online", Integer.toString(playersOnline));
|
|
||||||
|
|
||||||
// New data as of R6
|
|
||||||
String osname = System.getProperty("os.name");
|
|
||||||
String osarch = System.getProperty("os.arch");
|
|
||||||
String osversion = System.getProperty("os.version");
|
|
||||||
String java_version = System.getProperty("java.version");
|
|
||||||
int coreCount = Runtime.getRuntime().availableProcessors();
|
|
||||||
|
|
||||||
// normalize os arch .. amd64 -> x86_64
|
|
||||||
if (osarch.equals("amd64")) {
|
|
||||||
osarch = "x86_64";
|
|
||||||
}
|
|
||||||
|
|
||||||
appendJSONPair(json, "osname", osname);
|
|
||||||
appendJSONPair(json, "osarch", osarch);
|
|
||||||
appendJSONPair(json, "osversion", osversion);
|
|
||||||
appendJSONPair(json, "cores", Integer.toString(coreCount));
|
|
||||||
appendJSONPair(json, "auth_mode", onlineMode ? "1" : "0");
|
|
||||||
appendJSONPair(json, "java_version", java_version);
|
|
||||||
|
|
||||||
// If we're pinging, append it
|
|
||||||
if (isPing) {
|
|
||||||
appendJSONPair(json, "ping", "1");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (graphs.size() > 0) {
|
|
||||||
synchronized (graphs) {
|
|
||||||
json.append(',');
|
|
||||||
json.append('"');
|
|
||||||
json.append("graphs");
|
|
||||||
json.append('"');
|
|
||||||
json.append(':');
|
|
||||||
json.append('{');
|
|
||||||
|
|
||||||
boolean firstGraph = true;
|
|
||||||
|
|
||||||
final Iterator<Graph> iter = graphs.iterator();
|
|
||||||
|
|
||||||
while (iter.hasNext()) {
|
|
||||||
Graph graph = iter.next();
|
|
||||||
|
|
||||||
StringBuilder graphJson = new StringBuilder();
|
|
||||||
graphJson.append('{');
|
|
||||||
|
|
||||||
for (Plotter plotter : graph.getPlotters()) {
|
|
||||||
appendJSONPair(graphJson, plotter.getColumnName(), Integer.toString(plotter.getValue()));
|
|
||||||
}
|
|
||||||
|
|
||||||
graphJson.append('}');
|
|
||||||
|
|
||||||
if (!firstGraph) {
|
|
||||||
json.append(',');
|
|
||||||
}
|
|
||||||
|
|
||||||
json.append(escapeJSON(graph.getName()));
|
|
||||||
json.append(':');
|
|
||||||
json.append(graphJson);
|
|
||||||
|
|
||||||
firstGraph = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
json.append('}');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// close json
|
|
||||||
json.append('}');
|
|
||||||
|
|
||||||
// Create the url
|
|
||||||
URL url = new URL(BASE_URL + String.format(REPORT_URL, urlEncode(pluginName)));
|
|
||||||
|
|
||||||
// Connect to the website
|
|
||||||
URLConnection connection;
|
|
||||||
|
|
||||||
// Mineshafter creates a socks proxy, so we can safely bypass it
|
|
||||||
// It does not reroute POST requests so we need to go around it
|
|
||||||
if (isMineshafterPresent()) {
|
|
||||||
connection = url.openConnection(Proxy.NO_PROXY);
|
|
||||||
} else {
|
|
||||||
connection = url.openConnection();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
byte[] uncompressed = json.toString().getBytes();
|
|
||||||
byte[] compressed = gzip(json.toString());
|
|
||||||
|
|
||||||
// Headers
|
|
||||||
connection.addRequestProperty("User-Agent", "MCStats/" + REVISION);
|
|
||||||
connection.addRequestProperty("Content-Type", "application/json");
|
|
||||||
connection.addRequestProperty("Content-Encoding", "gzip");
|
|
||||||
connection.addRequestProperty("Content-Length", Integer.toString(compressed.length));
|
|
||||||
connection.addRequestProperty("Accept", "application/json");
|
|
||||||
connection.addRequestProperty("Connection", "close");
|
|
||||||
|
|
||||||
connection.setDoOutput(true);
|
|
||||||
|
|
||||||
if (debug) {
|
|
||||||
System.out.println("[Metrics] Prepared request for " + pluginName + " uncompressed=" + uncompressed.length + " compressed=" + compressed.length);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Write the data
|
|
||||||
OutputStream os = connection.getOutputStream();
|
|
||||||
os.write(compressed);
|
|
||||||
os.flush();
|
|
||||||
|
|
||||||
// Now read the response
|
|
||||||
final BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
|
|
||||||
String response = reader.readLine();
|
|
||||||
|
|
||||||
// close resources
|
|
||||||
os.close();
|
|
||||||
reader.close();
|
|
||||||
|
|
||||||
if (response == null || response.startsWith("ERR") || response.startsWith("7")) {
|
|
||||||
if (response == null) {
|
|
||||||
response = "null";
|
|
||||||
} else if (response.startsWith("7")) {
|
|
||||||
response = response.substring(response.startsWith("7,") ? 2 : 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new IOException(response);
|
|
||||||
} else {
|
|
||||||
// Is this the first update this hour?
|
|
||||||
if (response.equals("1") || response.contains("This is your first update this hour")) {
|
|
||||||
synchronized (graphs) {
|
|
||||||
final Iterator<Graph> iter = graphs.iterator();
|
|
||||||
|
|
||||||
while (iter.hasNext()) {
|
|
||||||
final Graph graph = iter.next();
|
|
||||||
|
|
||||||
for (Plotter plotter : graph.getPlotters()) {
|
|
||||||
plotter.reset();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* GZip compress a string of bytes
|
|
||||||
*
|
|
||||||
* @param input
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public static byte[] gzip(String input) {
|
|
||||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
|
||||||
GZIPOutputStream gzos = null;
|
|
||||||
|
|
||||||
try {
|
|
||||||
gzos = new GZIPOutputStream(baos);
|
|
||||||
gzos.write(input.getBytes("UTF-8"));
|
|
||||||
} catch (IOException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
} finally {
|
|
||||||
if (gzos != null) try {
|
|
||||||
gzos.close();
|
|
||||||
} catch (IOException ignore) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return baos.toByteArray();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if mineshafter is present. If it is, we need to bypass it to send POST requests
|
|
||||||
*
|
|
||||||
* @return true if mineshafter is installed on the server
|
|
||||||
*/
|
|
||||||
private boolean isMineshafterPresent() {
|
|
||||||
try {
|
|
||||||
Class.forName("mineshafter.MineServer");
|
|
||||||
return true;
|
|
||||||
} catch (Exception e) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Appends a json encoded key/value pair to the given string builder.
|
|
||||||
*
|
|
||||||
* @param json
|
|
||||||
* @param key
|
|
||||||
* @param value
|
|
||||||
* @throws UnsupportedEncodingException
|
|
||||||
*/
|
|
||||||
private static void appendJSONPair(StringBuilder json, String key, String value) throws UnsupportedEncodingException {
|
|
||||||
boolean isValueNumeric = false;
|
|
||||||
|
|
||||||
try {
|
|
||||||
if (value.equals("0") || !value.endsWith("0")) {
|
|
||||||
Double.parseDouble(value);
|
|
||||||
isValueNumeric = true;
|
|
||||||
}
|
|
||||||
} catch (NumberFormatException e) {
|
|
||||||
isValueNumeric = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (json.charAt(json.length() - 1) != '{') {
|
|
||||||
json.append(',');
|
|
||||||
}
|
|
||||||
|
|
||||||
json.append(escapeJSON(key));
|
|
||||||
json.append(':');
|
|
||||||
|
|
||||||
if (isValueNumeric) {
|
|
||||||
json.append(value);
|
|
||||||
} else {
|
|
||||||
json.append(escapeJSON(value));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Escape a string to create a valid JSON string
|
|
||||||
*
|
|
||||||
* @param text
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
private static String escapeJSON(String text) {
|
|
||||||
StringBuilder builder = new StringBuilder();
|
|
||||||
|
|
||||||
builder.append('"');
|
|
||||||
for (int index = 0; index < text.length(); index++) {
|
|
||||||
char chr = text.charAt(index);
|
|
||||||
|
|
||||||
switch (chr) {
|
|
||||||
case '"':
|
|
||||||
case '\\':
|
|
||||||
builder.append('\\');
|
|
||||||
builder.append(chr);
|
|
||||||
break;
|
|
||||||
case '\b':
|
|
||||||
builder.append("\\b");
|
|
||||||
break;
|
|
||||||
case '\t':
|
|
||||||
builder.append("\\t");
|
|
||||||
break;
|
|
||||||
case '\n':
|
|
||||||
builder.append("\\n");
|
|
||||||
break;
|
|
||||||
case '\r':
|
|
||||||
builder.append("\\r");
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
if (chr < ' ') {
|
|
||||||
String t = "000" + Integer.toHexString(chr);
|
|
||||||
builder.append("\\u" + t.substring(t.length() - 4));
|
|
||||||
} else {
|
|
||||||
builder.append(chr);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
builder.append('"');
|
|
||||||
|
|
||||||
return builder.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Encode text as UTF-8
|
|
||||||
*
|
|
||||||
* @param text the text to encode
|
|
||||||
* @return the encoded text, as UTF-8
|
|
||||||
*/
|
|
||||||
private static String urlEncode(final String text) throws UnsupportedEncodingException {
|
|
||||||
return URLEncoder.encode(text, "UTF-8");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents a custom graph on the website
|
|
||||||
*/
|
|
||||||
public static class Graph {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The graph's name, alphanumeric and spaces only :) If it does not comply to the above when submitted, it is
|
|
||||||
* rejected
|
|
||||||
*/
|
|
||||||
private final String name;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The set of plotters that are contained within this graph
|
|
||||||
*/
|
|
||||||
private final Set<Plotter> plotters = new LinkedHashSet<Plotter>();
|
|
||||||
|
|
||||||
private Graph(final String name) {
|
|
||||||
this.name = name;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the graph's name
|
|
||||||
*
|
|
||||||
* @return the Graph's name
|
|
||||||
*/
|
|
||||||
public String getName() {
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add a plotter to the graph, which will be used to plot entries
|
|
||||||
*
|
|
||||||
* @param plotter the plotter to add to the graph
|
|
||||||
*/
|
|
||||||
public void addPlotter(final Plotter plotter) {
|
|
||||||
plotters.add(plotter);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Remove a plotter from the graph
|
|
||||||
*
|
|
||||||
* @param plotter the plotter to remove from the graph
|
|
||||||
*/
|
|
||||||
public void removePlotter(final Plotter plotter) {
|
|
||||||
plotters.remove(plotter);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets an <b>unmodifiable</b> set of the plotter objects in the graph
|
|
||||||
*
|
|
||||||
* @return an unmodifiable {@link java.util.Set} of the plotter objects
|
|
||||||
*/
|
|
||||||
public Set<Plotter> getPlotters() {
|
|
||||||
return Collections.unmodifiableSet(plotters);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int hashCode() {
|
|
||||||
return name.hashCode();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals(final Object object) {
|
|
||||||
if (!(object instanceof Graph)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
final Graph graph = (Graph) object;
|
|
||||||
return graph.name.equals(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called when the server owner decides to opt-out of BukkitMetrics while the server is running.
|
|
||||||
*/
|
|
||||||
protected void onOptOut() {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Interface used to collect custom data for a plugin
|
|
||||||
*/
|
|
||||||
public static abstract class Plotter {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The plot's name
|
|
||||||
*/
|
|
||||||
private final String name;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Construct a plotter with the default plot name
|
|
||||||
*/
|
|
||||||
public Plotter() {
|
|
||||||
this("Default");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Construct a plotter with a specific plot name
|
|
||||||
*
|
|
||||||
* @param name the name of the plotter to use, which will show up on the website
|
|
||||||
*/
|
|
||||||
public Plotter(final String name) {
|
|
||||||
this.name = name;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the current value for the plotted point. Since this function defers to an external function it may or may
|
|
||||||
* not return immediately thus cannot be guaranteed to be thread friendly or safe. This function can be called
|
|
||||||
* from any thread so care should be taken when accessing resources that need to be synchronized.
|
|
||||||
*
|
|
||||||
* @return the current value for the point to be plotted.
|
|
||||||
*/
|
|
||||||
public abstract int getValue();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the column name for the plotted point
|
|
||||||
*
|
|
||||||
* @return the plotted point's column name
|
|
||||||
*/
|
|
||||||
public String getColumnName() {
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called after the website graphs have been updated
|
|
||||||
*/
|
|
||||||
public void reset() {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int hashCode() {
|
|
||||||
return getColumnName().hashCode();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals(final Object object) {
|
|
||||||
if (!(object instanceof Plotter)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
final Plotter plotter = (Plotter) object;
|
|
||||||
return plotter.name.equals(name) && plotter.getValue() == getValue();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user