Browse Source

Migrate to git.

master
Stefatorus 3 years ago
commit
533fa4fa5e
  1. 20
      .classpath
  2. 6
      .idea/misc.xml
  3. 8
      .idea/modules.xml
  4. 276
      .idea/workspace.xml
  5. 17
      .project
  6. 8
      .settings/fr.kazejiyu.discord.rpc.integration.prefs
  7. 29
      .settings/org.eclipse.core.resources.prefs
  8. 16
      .settings/org.eclipse.jdt.core.prefs
  9. 2
      .settings/org.eclipse.ltk.core.refactoring.prefs
  10. 4
      .settings/org.eclipse.m2e.core.prefs
  11. 84
      client.yml
  12. 10
      plugin.yml
  13. 740
      server.yml
  14. 199
      src/cx/sfy/LagAssist/Data.java
  15. 36
      src/cx/sfy/LagAssist/ExactTPS.java
  16. 148
      src/cx/sfy/LagAssist/Main.java
  17. 222
      src/cx/sfy/LagAssist/MonTools.java
  18. 255
      src/cx/sfy/LagAssist/Monitor.java
  19. 111
      src/cx/sfy/LagAssist/MsrExec.java
  20. 188
      src/cx/sfy/LagAssist/Physics.java
  21. 112
      src/cx/sfy/LagAssist/Redstone.java
  22. 17
      src/cx/sfy/LagAssist/api/APIManager.java
  23. 99
      src/cx/sfy/LagAssist/api/MotdAPI.java
  24. 145
      src/cx/sfy/LagAssist/chunks/ChkAnalyse.java
  25. 256
      src/cx/sfy/LagAssist/chunks/ChkLimiter.java
  26. 128
      src/cx/sfy/LagAssist/chunks/ChkStats.java
  27. 204
      src/cx/sfy/LagAssist/chunks/ChunkGenerator.java
  28. 101
      src/cx/sfy/LagAssist/chunks/DynViewer.java
  29. 86
      src/cx/sfy/LagAssist/client/ClientMain.java
  30. 85
      src/cx/sfy/LagAssist/client/ClientPacket.java
  31. 34
      src/cx/sfy/LagAssist/cmd/ClientCmdListener.java
  32. 294
      src/cx/sfy/LagAssist/cmd/CommandListener.java
  33. 49
      src/cx/sfy/LagAssist/cmd/CommandTabListener.java
  34. 78
      src/cx/sfy/LagAssist/cmd/StatsAnalyse.java
  35. 75
      src/cx/sfy/LagAssist/economy/EconomyManager.java
  36. 97
      src/cx/sfy/LagAssist/gui/AdminGUI.java
  37. 153
      src/cx/sfy/LagAssist/gui/ClientGUI.java
  38. 203
      src/cx/sfy/LagAssist/gui/DataGUI.java
  39. 196
      src/cx/sfy/LagAssist/gui/HopperGUI.java
  40. 387
      src/cx/sfy/LagAssist/hoppers/ChunkHoppers.java
  41. 209
      src/cx/sfy/LagAssist/hoppers/HopperFilter.java
  42. 91
      src/cx/sfy/LagAssist/hoppers/HopperManager.java
  43. 103
      src/cx/sfy/LagAssist/hoppers/SellHoppers.java
  44. 44
      src/cx/sfy/LagAssist/logpurger/PurgerMain.java
  45. 100
      src/cx/sfy/LagAssist/maps/TpsRender.java
  46. 708
      src/cx/sfy/LagAssist/metrics/BStats.java
  47. 64
      src/cx/sfy/LagAssist/metrics/MetricsManager.java
  48. 92
      src/cx/sfy/LagAssist/microfeatures/MicroManager.java
  49. 136
      src/cx/sfy/LagAssist/minebench/Approximate.java
  50. 43
      src/cx/sfy/LagAssist/minebench/BenchResponse.java
  51. 91
      src/cx/sfy/LagAssist/minebench/HTTPClient.java
  52. 146
      src/cx/sfy/LagAssist/minebench/SpecsGetter.java
  53. 141
      src/cx/sfy/LagAssist/minebench/SpeedTest.java
  54. 28
      src/cx/sfy/LagAssist/minebench/SysInfo.java
  55. 136
      src/cx/sfy/LagAssist/mobs/SmartMob.java
  56. 104
      src/cx/sfy/LagAssist/mobs/SpawnerMgr.java
  57. 25
      src/cx/sfy/LagAssist/packets/BlacklistHandler.java
  58. 44
      src/cx/sfy/LagAssist/packets/PacketHandler.java
  59. 137
      src/cx/sfy/LagAssist/packets/PacketInjector.java
  60. 49
      src/cx/sfy/LagAssist/packets/PacketMain.java
  61. 559
      src/cx/sfy/LagAssist/packets/Reflection.java
  62. 29
      src/cx/sfy/LagAssist/packets/ServerPackage.java
  63. 183
      src/cx/sfy/LagAssist/safety/SafetyAnticrash.java
  64. 72
      src/cx/sfy/LagAssist/safety/SafetyManager.java
  65. 322
      src/cx/sfy/LagAssist/stacker/StackChunk.java
  66. 195
      src/cx/sfy/LagAssist/stacker/StackComparer.java
  67. 270
      src/cx/sfy/LagAssist/stacker/StackManager.java
  68. 194
      src/cx/sfy/LagAssist/stacker/StackManipulator.java
  69. 286
      src/cx/sfy/LagAssist/stacker/StackMonitor.java
  70. 13
      src/cx/sfy/LagAssist/stacker/StackSpawners.java
  71. 19
      src/cx/sfy/LagAssist/superloader/SuperMain.java
  72. 190
      src/cx/sfy/LagAssist/updater/SmartUpdater.java
  73. 55
      src/cx/sfy/LagAssist/updater/UpdateCondition.java
  74. 124
      src/cx/sfy/LagAssist/updater/UpdateInfo.java
  75. 137
      src/cx/sfy/LagAssist/updater/VersionComparator.java
  76. 72
      src/cx/sfy/LagAssist/utils/Cache.java
  77. 34
      src/cx/sfy/LagAssist/utils/Chat.java
  78. 65
      src/cx/sfy/LagAssist/utils/MathUtils.java
  79. 102
      src/cx/sfy/LagAssist/utils/Others.java
  80. 61
      src/cx/sfy/LagAssist/utils/PaperOnly.java
  81. 87
      src/cx/sfy/LagAssist/utils/V1_11.java
  82. 74
      src/cx/sfy/LagAssist/utils/V1_12.java
  83. 90
      src/cx/sfy/LagAssist/utils/V1_13.java
  84. 64
      src/cx/sfy/LagAssist/utils/V1_8.java
  85. 151
      src/cx/sfy/LagAssist/utils/VersionMgr.java
  86. 38
      src/cx/sfy/LagAssist/utils/WorldMgr.java
  87. 1
      target/classes/.gitignore

20
.classpath

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry including="**/*.java" kind="src" output="target/classes" path="src">
<attributes>
<attribute name="optional" value="true"/>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8">
<attributes>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="lib" path="W:/Minecraft Versions/Paper-1.13.2-b624.jar"/>
<classpathentry kind="lib" path="W:/Minecraft Versions/Paper-1.12.2-b1618.jar"/>
<classpathentry kind="lib" path="W:/Minecraft Versions/PaperSpigot-1.8.8-R0.1-SNAPSHOT-latest.jar"/>
<classpathentry kind="lib" path="W:/Minecraft Versions/Spigot-1.15.jar"/>
<classpathentry kind="lib" path="W:/Custom Plugins/Vault.jar"/>
<classpathentry kind="output" path="target/classes"/>
</classpath>

6
.idea/misc.xml

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" project-jdk-name="1.8" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/out" />
</component>
</project>

8
.idea/modules.xml

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

276
.idea/workspace.xml

@ -0,0 +1,276 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ChangeListManager">
<list default="true" id="f3864c36-1f03-4c67-bc03-97e16bf3c609" name="Default Changelist" comment="" />
<ignored path="$PROJECT_DIR$/target/classes/" />
<option name="EXCLUDED_CONVERTED_TO_IGNORED" value="true" />
<option name="SHOW_DIALOG" value="false" />
<option name="HIGHLIGHT_CONFLICTS" value="true" />
<option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
<option name="LAST_RESOLUTION" value="IGNORE" />
</component>
<component name="FUSProjectUsageTrigger">
<session id="1423070445">
<usages-collector id="statistics.lifecycle.project">
<counts>
<entry key="project.closed" value="1" />
<entry key="project.open.time.4" value="1" />
<entry key="project.opened" value="1" />
</counts>
</usages-collector>
<usages-collector id="statistics.file.extensions.edit">
<counts>
<entry key="java" value="7" />
</counts>
</usages-collector>
<usages-collector id="statistics.file.types.edit">
<counts>
<entry key="JAVA" value="7" />
</counts>
</usages-collector>
<usages-collector id="statistics.file.extensions.open">
<counts>
<entry key="java" value="5" />
</counts>
</usages-collector>
<usages-collector id="statistics.file.types.open">
<counts>
<entry key="JAVA" value="5" />
</counts>
</usages-collector>
</session>
</component>
<component name="FileEditorManager">
<leaf>
<file pinned="false" current-in-tab="true">
<entry file="file://$PROJECT_DIR$/src/cx/sfy/LagAssist/packets/Reflection.java">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="782">
<caret line="83" lean-forward="true" selection-start-line="83" selection-end-line="83" />
</state>
</provider>
</entry>
</file>
<file pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/src/cx/sfy/LagAssist/packets/ServerPackage.java">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="68">
<caret line="4" column="12" selection-start-line="4" selection-start-column="12" selection-end-line="4" selection-end-column="12" />
</state>
</provider>
</entry>
</file>
<file pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/src/cx/sfy/LagAssist/Main.java">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="197">
<caret line="61" column="18" selection-start-line="61" selection-start-column="18" selection-end-line="61" selection-end-column="18" />
</state>
</provider>
</entry>
</file>
<file pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/src/cx/sfy/LagAssist/packets/PacketHandler.java">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="68">
<caret line="9" column="13" selection-start-line="9" selection-start-column="13" selection-end-line="9" selection-end-column="13" />
</state>
</provider>
</entry>
</file>
<file pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/src/cx/sfy/LagAssist/packets/PacketMain.java">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="170">
<caret line="19" column="75" selection-start-line="19" selection-start-column="32" selection-end-line="19" selection-end-column="75" />
</state>
</provider>
</entry>
</file>
<file pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/src/cx/sfy/LagAssist/maps/TpsRender.java">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="119">
<caret line="18" column="36" lean-forward="true" selection-start-line="18" selection-start-column="36" selection-end-line="18" selection-end-column="36" />
</state>
</provider>
</entry>
</file>
</leaf>
</component>
<component name="IdeDocumentHistory">
<option name="CHANGED_PATHS">
<list>
<option value="$PROJECT_DIR$/src/cx/sfy/LagAssist/packets/Reflection.java" />
</list>
</option>
</component>
<component name="ProjectFrameBounds" extendedState="6">
<option name="x" value="260" />
<option name="y" value="20" />
<option name="width" value="1400" />
<option name="height" value="1000" />
</component>
<component name="ProjectView">
<navigator proportions="" version="1">
<foldersAlwaysOnTop value="true" />
</navigator>
<panes>
<pane id="ProjectPane">
<subPane>
<expand>
<path>
<item name="AdvancedLagAssist" type="b2602c69:ProjectViewProjectNode" />
<item name="AdvancedLagAssist" type="462c0819:PsiDirectoryNode" />
</path>
<path>
<item name="AdvancedLagAssist" type="b2602c69:ProjectViewProjectNode" />
<item name="AdvancedLagAssist" type="462c0819:PsiDirectoryNode" />
<item name="src" type="462c0819:PsiDirectoryNode" />
</path>
<path>
<item name="AdvancedLagAssist" type="b2602c69:ProjectViewProjectNode" />
<item name="AdvancedLagAssist" type="462c0819:PsiDirectoryNode" />
<item name="src" type="462c0819:PsiDirectoryNode" />
<item name="LagAssist" type="462c0819:PsiDirectoryNode" />
</path>
<path>
<item name="AdvancedLagAssist" type="b2602c69:ProjectViewProjectNode" />
<item name="AdvancedLagAssist" type="462c0819:PsiDirectoryNode" />
<item name="src" type="462c0819:PsiDirectoryNode" />
<item name="maps" type="462c0819:PsiDirectoryNode" />
</path>
<path>
<item name="AdvancedLagAssist" type="b2602c69:ProjectViewProjectNode" />
<item name="AdvancedLagAssist" type="462c0819:PsiDirectoryNode" />
<item name="src" type="462c0819:PsiDirectoryNode" />
<item name="packets" type="462c0819:PsiDirectoryNode" />
</path>
</expand>
<select />
</subPane>
</pane>
<pane id="PackagesPane" />
<pane id="Scope" />
</panes>
</component>
<component name="RunDashboard">
<option name="ruleStates">
<list>
<RuleState>
<option name="name" value="ConfigurationTypeDashboardGroupingRule" />
</RuleState>
<RuleState>
<option name="name" value="StatusDashboardGroupingRule" />
</RuleState>
</list>
</option>
</component>
<component name="SvnConfiguration">
<configuration />
</component>
<component name="TaskManager">
<task active="true" id="Default" summary="Default task">
<changelist id="f3864c36-1f03-4c67-bc03-97e16bf3c609" name="Default Changelist" comment="" />
<created>1540072256497</created>
<option name="number" value="Default" />
<option name="presentableId" value="Default" />
<updated>1540072256497</updated>
</task>
<servers />
</component>
<component name="ToolWindowManager">
<frame x="-8" y="-8" width="1936" height="1056" extended-state="6" />
<layout>
<window_info id="Image Layers" />
<window_info id="Designer" />
<window_info id="UI Designer" />
<window_info id="Capture Tool" />
<window_info id="Favorites" side_tool="true" />
<window_info active="true" content_ui="combo" id="Project" order="0" visible="true" weight="0.25" />
<window_info id="Structure" order="1" side_tool="true" weight="0.25" />
<window_info anchor="bottom" id="Version Control" show_stripe_button="false" />
<window_info anchor="bottom" id="Terminal" />
<window_info anchor="bottom" id="Event Log" side_tool="true" />
<window_info anchor="bottom" id="Messages" weight="0.329718" />
<window_info anchor="bottom" id="Message" order="0" />
<window_info anchor="bottom" id="Find" order="1" />
<window_info anchor="bottom" id="Run" order="2" />
<window_info anchor="bottom" id="Debug" order="3" weight="0.4" />
<window_info anchor="bottom" id="Cvs" order="4" weight="0.25" />
<window_info anchor="bottom" id="Inspection" order="5" weight="0.4" />
<window_info anchor="bottom" id="TODO" order="6" />
<window_info anchor="right" id="Palette" />
<window_info anchor="right" id="Theme Preview" />
<window_info anchor="right" id="Capture Analysis" />
<window_info anchor="right" id="Palette&#9;" />
<window_info anchor="right" id="Maven Projects" />
<window_info anchor="right" id="Commander" internal_type="SLIDING" order="0" type="SLIDING" weight="0.4" />
<window_info anchor="right" id="Ant Build" order="1" weight="0.25" />
<window_info anchor="right" content_ui="combo" id="Hierarchy" order="2" weight="0.25" />
</layout>
</component>
<component name="VcsContentAnnotationSettings">
<option name="myLimit" value="2678400000" />
</component>
<component name="editorHistoryManager">
<entry file="file://$PROJECT_DIR$/src/cx/sfy/LagAssist/packets/PacketHandler.java">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="68">
<caret line="9" column="13" selection-start-line="9" selection-start-column="13" selection-end-line="9" selection-end-column="13" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/src/cx/sfy/LagAssist/maps/TpsRender.java">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="119">
<caret line="18" column="36" lean-forward="true" selection-start-line="18" selection-start-column="36" selection-end-line="18" selection-end-column="36" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/src/cx/sfy/LagAssist/Main.java">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="197">
<caret line="61" column="18" selection-start-line="61" selection-start-column="18" selection-end-line="61" selection-end-column="18" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/src/cx/sfy/LagAssist/packets/ServerPackage.java">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="68">
<caret line="4" column="12" selection-start-line="4" selection-start-column="12" selection-end-line="4" selection-end-column="12" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/src/cx/sfy/LagAssist/packets/PacketMain.java">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="170">
<caret line="19" column="75" selection-start-line="19" selection-start-column="32" selection-end-line="19" selection-end-column="75" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/src/cx/sfy/LagAssist/packets/Reflection.java">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="782">
<caret line="83" lean-forward="true" selection-start-line="83" selection-end-line="83" />
</state>
</provider>
</entry>
</component>
<component name="masterDetails">
<states>
<state key="ProjectJDKs.UI">
<settings>
<last-edited>1.8</last-edited>
<splitter-proportions>
<option name="proportions">
<list>
<option value="0.2" />
</list>
</option>
</splitter-proportions>
</settings>
</state>
</states>
</component>
</project>

17
.project

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>AdvancedLagAssist</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.jdt.core.javanature</nature>
</natures>
</projectDescription>

8
.settings/fr.kazejiyu.discord.rpc.integration.prefs

@ -0,0 +1,8 @@
PROJECT_NAME=LagAssist
RESET_ELAPSED_TIME=RESET_ELAPSED_TIME_ON_NEW_PROJECT
SHOW_ELAPSED_TIME=true
SHOW_FILE_NAME=true
SHOW_LANGUAGE_ICON=true
SHOW_PROJECT_NAME=true
USE_PROJECT_SETTINGS=false
eclipse.preferences.version=1

29
.settings/org.eclipse.core.resources.prefs

@ -0,0 +1,29 @@
eclipse.preferences.version=1
encoding//src/cx/sfy/LagAssist/MonTools.java=UTF-8
encoding//src/cx/sfy/LagAssist/Monitor.java=UTF-8
encoding//src/cx/sfy/LagAssist/Physics.java=UTF-8
encoding//src/cx/sfy/LagAssist/Redstone.java=UTF-8
encoding//src/cx/sfy/LagAssist/chunks/ChkAnalyse.java=UTF-8
encoding//src/cx/sfy/LagAssist/chunks/ChkLimiter.java=UTF-8
encoding//src/cx/sfy/LagAssist/chunks/ChkStats.java=UTF-8
encoding//src/cx/sfy/LagAssist/chunks/ChunkGenerator.java=UTF-8
encoding//src/cx/sfy/LagAssist/chunks/DynViewer.java=UTF-8
encoding//src/cx/sfy/LagAssist/client/ClientMain.java=UTF-8
encoding//src/cx/sfy/LagAssist/cmd/CommandListener.java=UTF-8
encoding//src/cx/sfy/LagAssist/cmd/StatsAnalyse.java=UTF-8
encoding//src/cx/sfy/LagAssist/gui/AdminGUI.java=UTF-8
encoding//src/cx/sfy/LagAssist/gui/DataGUI.java=UTF-8
encoding//src/cx/sfy/LagAssist/hoppers/HopperManager.java=UTF-8
encoding//src/cx/sfy/LagAssist/logpurger/PurgerMain.java=UTF-8
encoding//src/cx/sfy/LagAssist/minebench/Approximate.java=UTF-8
encoding//src/cx/sfy/LagAssist/minebench/HTTPClient.java=UTF-8
encoding//src/cx/sfy/LagAssist/minebench/SpeedTest.java=UTF-8
encoding//src/cx/sfy/LagAssist/mobs/SmartMob.java=UTF-8
encoding//src/cx/sfy/LagAssist/mobs/SpawnerMgr.java=UTF-8
encoding//src/cx/sfy/LagAssist/packets/PacketMain.java=UTF-8
encoding//src/cx/sfy/LagAssist/packets/Reflection.java=UTF-8
encoding//src/cx/sfy/LagAssist/safety/SafetyManager.java=UTF-8
encoding//src/cx/sfy/LagAssist/stacker/StackManager.java=UTF-8
encoding//src/cx/sfy/LagAssist/superloader/SuperMain.java=UTF-8
encoding//src/cx/sfy/LagAssist/updater/SmartUpdater.java=UTF-8
encoding//src/cx/sfy/LagAssist/utils/WorldMgr.java=UTF-8

16
.settings/org.eclipse.jdt.core.prefs

@ -0,0 +1,16 @@
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
org.eclipse.jdt.core.compiler.compliance=1.8
org.eclipse.jdt.core.compiler.debug.lineNumber=generate
org.eclipse.jdt.core.compiler.debug.localVariable=generate
org.eclipse.jdt.core.compiler.debug.sourceFile=generate
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=warning
org.eclipse.jdt.core.compiler.release=disabled
org.eclipse.jdt.core.compiler.source=1.8

2
.settings/org.eclipse.ltk.core.refactoring.prefs

@ -0,0 +1,2 @@
eclipse.preferences.version=1
org.eclipse.ltk.core.refactoring.enable.project.refactoring.history=false

4
.settings/org.eclipse.m2e.core.prefs

@ -0,0 +1,4 @@
activeProfiles=
eclipse.preferences.version=1
resolveWorkspaceProjects=true
version=1

84
client.yml

@ -0,0 +1,84 @@
# _ _ _
# | | /\ (_) | |
# | | __ _ __ _ / \ ___ ___ _ ___| |_
# | | / _` |/ _` | / /\ \ / __/ __| / __| __|
# | |___| (_| | (_| |/ ____ \\__ \__ \ \__ \ |_
# |______\__,_|\__, /_/ \_\___/___/_|___/\__|
# __/ |
# |___/ By Stefatorus
#
# This is the default configuration. I suggest using it as it is.
# If you need help configuring it, please add me on discord.
# DISCORD: Stefatorus#9382
#
# The Client-Side tweaks offer a nice way to improve your player's experience.
# It offers ways to hide some laggy features in minecraft and thus simplify the game
# for the players, while the server still works as normally.
#
# NOTE: THE CLIENT-SIDE TWEAKS SHOULD WORK ON 1.8-1.13.1, BUT SOME FUTURE VERSIONS
# MAY NOT WORK OUT OF THE BOX. PLEASE CONTACT ME TO UPDATE THIS SYSTEM IF
# ANY PROBLEM ARISES.
settings:
# The client-side tweaks are currently experimental. They have been tested decently,
# but not against a large range of systems and minecraft versions. Please take care.
enabled: false
# Set the command that players will use to open the client-side optimizer.
command: "optimize"
# Set the permission required for players to be able to use the client optimizer.
permission: "lagassist.clientoptimize"
# The GUI name for the client-side optimizer.
gui-name: "&0&lPerformance Settings"
# The prefix of client-side optimizer messages.
prefix: "&c&lOptimize &e» &f"
# The default cliet-side tweaks that will be enabled
defaults:
tnt: true
sand: true
particles: false
pistons: false
language:
tnt:
name: "&cTNT Optimization"
lore:
- "&f"
- "&fHides TNT entities to greatly reduce lag when"
- "&fthere's a lot of TNT exploding at the same time"
- "&f"
sand:
name: "&eFalling Block Optimization"
lore:
- "&f"
- "&fHides sand entities to improve performance"
- "&fwhen there is a lot of sand falling around."
- "&f"
particle:
name: "&dParticle Optimization"
lore:
- "&f"
- "&fDisables server-side particles"
- "&fso the client doesn't have to render them."
- "&f"
piston:
name: "&8Piston Optimization"
lore:
- "&f"
- "&fDisables Piston Animations"
- "&fin order to optimize piston extensions."
- "&f"
toggleon:
name: "&aEnable this"
lore:
- "&f"
- "&fClick Here to enable this feature."
- "&f"
toggleoff:
name: "&cDisable this"
lore:
- "&f"
- "&fClick Here to disable this feature."
- "&f"
# This allows the system to update the config if the plugin is updated.
version: 4

10
plugin.yml

@ -0,0 +1,10 @@
name: LagAssist
author: Stefatorus
version: 2.23.2
api-version: 1.13
description: LagAssist is an advanced anti-lag solution that allows server owners find and remove lag using multiple advanced and efficient methods.
main: cx.sfy.LagAssist.Main
softdepend: [Vault]
commands:
lagassist:
description: The main command of LagAssist, a Performance Analysis and Optimization Tool.

740
server.yml

@ -0,0 +1,740 @@
# _ _ _
# | | /\ (_) | |
# | | __ _ __ _ / \ ___ ___ _ ___| |_
# | | / _` |/ _` | / /\ \ / __/ __| / __| __|
# | |___| (_| | (_| |/ ____ \\__ \__ \ \__ \ |_
# |______\__,_|\__, /_/ \_\___/___/_|___/\__|
# __/ |
# |___/ By Stefatorus
#
# This is the default configuration. I suggest using it as it is.
# If you need help configuring it, please add me on discord.
# DISCORD: Stefatorus#9382
#
# Mobs that will be removed by the smart cleaner.
#
# TIP: This will not remove named mobs, even if they are in the list.
# This follows the vanilla rule - don't despawn named entities, which
# players are allready acustom to.
smart-cleaner:
# Do you want the system to be in whitelist or blacklist mode?
# TIP: Whitelist - All except these get deleted ; Blacklist is the opposite
whitelist: false
# Automatic Physics disabler will occur if tps is under this value.
# EG: If tps is under 16, lagassist will disable the physics that are
# TIP: Set to 0.0 to disable it.
maxtps-cull: 16.0
# Automatically disable mob spawning if tps is under this value.
# EG: If tps is under 14, lagassist will disable mob spawning.
maxtps-disablespawn: 14.0
# List of the mobs that will get removed by the smart-cleaner.
# Mob names: https://hub.spigotmc.org/javadocs/spigot/org/bukkit/entity/EntityType.html
mobs:
- "ZOMBIE"
- "CREEPER"
- "SKELETON"
- "WITHER_SKELETON"
- "SQUID"
- "SPIDER"
- "SILVERFISH"
- "PIG_ZOMBIE"
- "MINECART"
- "ILLUSIONER"
- "GHAST"
- "HUSK"
- "EVOKER"
- "ENDERMAN"
- "ENDERMITE"
- "ELDER_GUARDIAN"
- "CAVE_SPIDER"
- "BAT"
- "BLAZE"
# For Creative Servers
# - ARMOR_STAND
# For Factions Servers
# - PRIMED_TNT
# The smart stacker system allows you to efficiently stack mobs in a chunk based on a
# cubic chunk splitting system. This algorithm is extremely light-weight compared
# to past stacking algorithms, which means more performance left for your server.
smart-stacker:
# Should we enable the smart stacker system?
enabled: false
checks:
# Run stack check when a mob spawns.
spawn-check: true
# (!) Way more efficient than spawn check, but only works on custom tailored paper forks. You can use both for
# best performance.
# DO NOT ENABLE IF YOUR CUSTOM TAILORED FORK DOESN'T SET A TIMEOUT BEFORE RETRYING TO SPAWN ANOTHER MOB.
pre-spawn-check: false
# Should we try to stack mobs when they change splits?
# Disabling it may improve performance, but it's not recommended since it disables
# stacking when moving from one chunk to another.
split-change-check: true
gameplay:
# Should players always see stacked mob tags?
# (!) Setting to false will make it so you can only see mob stacking when hovering over a mob
tag-visibility: true
# Size is required if you want stacking to work.
tag-format: "&f{type} &cx{size}"
# What entity types don't you want to be stackable.
stackable:
# - "SKELETON"
# - "ZOMBIE"
# - "BLAZE"
# - "VINDICATOR"
# - "VILLAGER"
# - "WITCH"
# - "SPIDER"
# - "EVOKER"
technical:
# The amount of vertical splits per chunk (Must divide 256). A lower amount makes the stacking area go down and thus
# improve compatibility with farms.
# (!) Setting it under 4 is not recommended. 8, 16 recommended.
splits: 8
# Should we remove all stacked mobs when the plugin is disabled? (DISABLED FEATURE)
# (!) Highly suggested to be left on true, since it can help a lot with TPS. It
# also prevents the algorithm having to search the old mobs when the chunk issue
# empty which is a huge bonus.
# (!) If left on false, the system will do stacking on chunk enable.
# shutdown-clean: false
# Should we amplify drops to get the approximate value of what those mobs would drop
# if they were to be killed one by one?
drops-fix: true
# What's the highest amount a stack can get to? Since there's a limit of 1 stack per
# split, it's useful to keep this higher.
max-stack: 500
# This section deals with custom handling for damage for stacked mobs.
damage:
# What damage causes should be multiplied by the stack count.
# (!) This helps with farms. For example, multiplying fall damage fixes
# drop farms.
multiply:
- "CRAMMING"
- "FALL"
- "DROWNING"
- "CONTACT"
- "VOID"
- "FIRE_TICK"
- "DRYOUT"
# Entity Comparison is used to prevent 2 similar entities from being stacked together.
# Extremely useful when you want to retain vanilla-like gameplay.
comparison:
sheep: true
pig: true
slime: true
villager: false
tameable: true
horse: true
# Checks for the age of the mob approximatively
ageable: false
# This is a simple mob modifier. It changes how some mobs behave to improve the server
# performance.
mob-manager:
# Disable armorstand gravity. This might help with creative servers which have a lot of armorstands.
no-armorstand-gravity: false
# Disable slime splitting, approximating the drops and health of a vanilla confrontation. This is very
# useful for larger than vanilla slimes.
# NOTE: This also helps for vanilla slimes, but shouldn't (in my opinion) be used unless there is lag from
# NOTE: slimes.
simple-slime: false
# Micro features represent simple yet effective ways to reduce lag. It generally includes simple to implement
# features that would otherwise not need their own section.
microfeatures:
# Optimize farms by automatically destroying crops that are near a piston facing them.
# Helps reduce the need of redstone for these farms. Really useful on 1.8.8 factions servers.
optimize-growable-farms:
enable: false
blocks:
- "PUMPKIN"
# Two versions (flattening and pre)
- "MELON_BLOCK"
- "MELON"
# Laggy Chunk detection. You can fiddle around and find the best settings for your
# server.
#
# TIP: Find what kind of tiles or entities lag your server and set them a proper lag score
# here. The default values should be fine, but finding the best settings for yourself is allways
# the best way.
chunkanalyse:
# Teleport command that will be issued when you click the text.
# PLACEHOLDERS: {x}, {y}, {z}, {chunkx}, {chunkz} {world}
#
# TIP: Set it to a command that you like. This can be used to automatically clear lag in chunks, unload it, etc.
tp-cmd: "lagassist tpchunk {world} {chunkx} {chunkz}"
# Score at wich the server will consider the chunk laggy and make it appear in the list. You should fiddle around with it so it only shows
# the chunks that you want it to find.
#
# TIP: The amount of chunks /lagassist chunkanalyse will show.
# (It will always show the top (amount value) laggiest chunks.)
ammount: 10
# Entity & Material names for laggy values.
#
# materials: https://hub.spigotmc.org/javadocs/spigot/org/bukkit/Material.html
# entities: https://hub.spigotmc.org/javadocs/spigot/org/bukkit/entity/EntityType.html
# tile entities: https://minecraft.gamepedia.com/Block_entity
#
# TIP: Only detects Tile entities & entities. Normal blocks aren't ticked. This means that it would lag if i were to check the normal blocks.
# At the same time, normal blocks don't lag the server.
values:
# -------------
# TILE ENTITIES
# -------------
chest: 1
trapped_chest: 2
burning_furnace: 3
sign: 1
# Beacons don't really lag the server, but they usually appear in laggy chunks due to them being placed near grinders & automatic farms.
# High score due to their rarity.
beacon: 35
hopper: 6
note_block: 4
piston_extension: 5
dispenser: 10
# Mob spawners really lag the server. I suggest setting a high score related to them.
mob_spawner: 60
# --------------
# NORMAL ENTITIES
# --------------
# Players themselves. They have a decent score due to them being a lag cause (they create farms, afk at them, etc)
player: 15
# Normal mobs that are found in a chunk. Set the value to a moderate one. They don't lag the server so much.
# Creeper score slightly higher due to the explosion that could lag the server a bit.
zombie: 2
spider: 2
skeleton: 2
creeper: 3
# Passive mobs. Might signal some custom spawner farms. They are pretty optimised in AdvancedSpigotTweaks though.
cow: 1
pig: 1
# Thrown items. Don't pose a huge issue due to them being optimised by AdvancedSpigotTweaks. The endereye (ender_signal) might
# mean there is a end portal nearby, that might mean more activity (and thus, lag). Egg can spawn mobs and such has a higher score.
ender_signal: 5
egg: 3
fishing_hook: 2
ender_pearl: 2
snowball: 2
arrow: 1
# Static entities might lag the server, but it all depends. They usually signal a big player city, and such is related to lag.
painting: 2
item_frame: 3
armor_stand: 4
# Stacked items & XP do not lag the server as much. If you use AdvancedSpigotTweaks, keep that in mind.
# Fireworks might lag the server, especially if they have big explosions.
dropped_item: 2
experience_orb: 3
firework: 8
# Bosses have complex abilities that might lag your server. The ability entities can also offer additional proof the
# bosses are actively fighting.
ender_dragon: 85
ender_crystal: 10
wither: 55
wither_skull: 20
# Tnt is a severe lag issue. I recommend setting primed tnt (activated tnt) to a higher score. Remember that a tnt by
# itself doesn't lag as much, but they are used in mass numbers in cannons, etc.
# Minecart-TNTS are evem bigger of an issue due to their moving mechanics.
primed_tnt: 7
minecart_tnt: 15
# Highly active entities. Includes entities that do many checks, and are used for mechanics.
minecart_hopper: 20
minecart_mob_spawner: 80
endermite: 5
# Chunk-Manager System.
chunk-manager:
# Should we enable the chunk-manager? It can highly help with memory issues if you have too many loaded chunks.
# NOTE: You need to have the max view distance set in your server.properties file.
#
# (!) This feature will only work on PaperSpigot servers.
enabled: false
# How many chunks should all players load at the same time.
# TIP: The view distance is calculated using this formula:
# SQRT(MAX-CHUNKS / PLAYERS / 4).
# EG: If the max chunks are at 6500, and you have 100 players online
# your view distance would be at 4.
# (!) In order for this to work, please set your view distance in
# both server.properties & spigot.yml to the minimum view distance you
# want to set.
max-chunks: 5000
# (!) Try making it larger progressively. Sometimes it's safe to limit it
# at a smaller view distance.
max-view: 12
#LagMeasures Config
lag-measures:
# Lag measures automatically runs anti-lag actions if the server has
# under a set amount of TPS. To configure the tps values, look for
# the maxtps setting in all lagassist systems.
#
# Announce the lag cleaning in the console and chat.
announce:
# Show players that the lag-cleaning has occured.
enabled: false
# Should we show the staff a different, more exact message of lag-measures?
# Permission node: lagassist.notify
staffmsg: true
message: "&c&lLag&f&lAssist &e» &fRemoving server lag..."
# Set the time between the lag-cleaning cycles.
# I suggest keeping it on 6000 as the fact that it disables redstone
# machines might annoy some players if it is done too often.
#
# TIP: Time is measured in ticks. 1 second has a tick
# (For 10 second interval, set to 200)
timer: 6000
# RedstoneCuller Tweaks
redstone-culler:
# Chance from 1 to 100 for the redstone to break. If you don't think
# redstone could lag your server, disable it.
#
# The breaker system griefs some redstone from Players' contraptions in
# order to prolongue the effect of the cull. If it is set to 0, it will
# be harder to get rid of redsotne lag, because players can just start
# their farms & Lag Machines back up in a matter of seconds.
#
# TIP: The chance doesn't need to be too big in order for their farms to
# break. The system triggers for all of the active redstone trails and will
# break X percent of the track. Remember that even if you have chance 2, if
# we have 100 redstone, you will still have an effect on them.
#
# (!) TO disable set chance to 0.
chance: 3
#
# What blocks do you want to be affected by the redstone culler. This allows you
# to prevent pressure plates or other valuable blocks that don't necessarily cause
# lag to be protected from the culler.
affected-materials:
- "REDSTONE"
- "REDSTONE_WIRE"
- "REDSTONE_COMPARATOR"
- "REDSTONE_COMPARATOR_OFF"
- "REDSTONE_COMPARATOR_ON"
- "REDSTONE_TORCH_OFF"
- "REDSTONE_TORCH_ON"
- "REDSTONE_TORCH"
- "DIODE"
#
# How many ticks should the redstone be culled if the signal changes. A too small value
# will not stop clocks, and a too large value will make destructive checks less effective.
#
# TIP: The recommmended value for destructive checks is 10-30; and 50-70 without.
ticks: 60
# Destructive checks. Implemented to combat Observer lagmachines, which can bring
# a I7-4770k machine to it's knees quite easily. It listens for singal changes and
# removes all observers that go over a set value.
# Lag-Machine example: http://stefatorus.go.ro/img/SpigotTweaks/ObserverFix.gif
#
# (!) This should be safe, but at the same time, don't enable it without any reason.
# These lag machines are not found very often, and there is no reason to try fix them
# if everything works fine.
destructive:
# Should we enable destructive checks?
enabled: false
# How many updates should the observer do in order to remove it? I recommend the default value.
value: 16
#
# Automatic Redstone culling will occur if tps is under this value.
# EG: If tps is under 19, lagassist will cull redstone each time the monitor runs.
# TIP: Set to 0.0 to disable it.
maxtps: 19.0
# Disable hopper crafting. Hoppers are one of the issues non-minigame server owners have to face. Enabling this
# check allows you to make hoppers more rare. This won't really affect farms, but will make them more efficient.
#
# Hoppers are easy to craft in vanilla minecraft, and this makes them to get overused (>100 HOPPERS/FARM)
hopper-check:
enabled: false
reason: "&c&lLag&f&lAssist &e» &fHopper crafting has been disabled."
# Sabotage hoppers in order to defer players from using them. This
# will break huge farms in a while, and has a bigger chance of destroying
# large hopper lines instead of single hoppers. (multyply by how many)
#
# TIP: This is is not percent, it is per10mille (X in 10000 chance).
# Don't set it too big. If you set it to 1 or 2, it will make sure
# huge afk farms will break and won't lag your server for actually
# active players, while also not annoying the less-extreme players.
#
# Disable by setting it to 0.
chance: 0
# Make item drops go directly into hoppers. This was designed with
# factions servers in order to replace plugins like crophoppers and
# in general improve performance for many hopper drops.
chunk-hoppers:
# Should we enable chunk hoppers? They will catch all items
# that aren't dropped by players and are ine items list and
# place it in the chosen hopper.
enabled: true
# What mode do you want to use for chunk hopper additions
# FIRST - Uses first hopper that is available
# RANDOM - Get a random hopper (may help with logistic speed)
# CLOSEST - Uses hoppers in ordered by their range to the item.
mode: "RANDOM"
# How do you want chunk-hoppers to be defined?
# DEFAULT - All hoppers become chunk-hoppers. Useful for already
# established servers that haven't used them in the current
# season or wipe.
# NAME - Hoppers being named customly are chunk-hoppers. Will reduce
# the amount of hoppers that need sorted and thus will possibly
# improve performance (if they are properly advertised on the server)
define: "&eChunk &fHopper"
# The filter system allows you to give players the ability to filter what items the chunk hoppers will pick. It is really useful
# for creating simple & performance efficient filters, along with incentivizing people to use chunk hoppers.
filter:
# The default items that chunk hoppers should pick up. This is used in case a hopper doesn't have a custom filter.\
# (!) In case you use the custom hopper filter, please make sure to set the slots larger than the amount of slots in default.
default:
- "IRON_ORE"
- "ROTTEN_FLESH"
- "BONE"
- "ARROW"
gui:
# The name that the filtering GUI should have. This can be used to customize the looks of the
# filter system.
name: "&d&lHopper Filter"
# This represents the size of the GUI that the filter represents. Tweaking these settings allows
# you to choose how complex a filter can get.
# (!) Must be a multiple of 9.
size: 18
# Mob hoppers allow people to instanly funnel spawner mob drops to chunk hoppers. It works using the filter that is found above.
# Players will have to add a mob spawnegg to the hopper to allow it to catch the respective mob.
mob-hopper:
# (!) Note: Mob Hoppers currently only work on 1.13+ servers.
#
# This check can be used to alleviate lag during extreme lag sessions, or used temporarily. While i suggest
# keeping it on all the times, if your players don't mind having to have their grinder account for it, you can
# make it only run when the server lags.
# (!) To disable mob hoppers from working, just set max-tps to 0.
# I suggest 17 if you want it temporary, or 20 if you want it permanent.
maxtps: 0.0
# The reasons that the mob hopper will work for. This allows you to exclude normal mob
# spawns from being funneled to the chunk hopper.
spawn-reasons:
- "SPAWNER"
- "NETHER_PORTAL"
# Multiplying the drop amount can help you fiddle with mob spawns without changing the
# amount players win from a hopper, effectively tuning performance drastically without
# negatively affecting the players.
multiplier: 1
# Entity Materials represent the materials that will allow their respective mobs to
# get caught in mob hoppers.
filter-items:
zombie: "ROTTEN_FLESH"
creeper: "GUNPOWDER"
skeleton: "BONE"
# Automatically sell items that appear in this list before attempting to place them in the chunkhopper.
# Useful and efficient replacement for autosell chests. Requires Vault to function.
sell-hopper:
# Should we enable the sellhopper system?
# (!) To enable, please also add the "lagassist.sellhopper.PERCENTAGE" permission to the player.
# Example: lagassist.sellhopper.70 gives the player 70% of the price.
#
enabled: false
# The amount users will be paid at the end of the payout session. The payout session is used to prevent
# lag.
prices:
ROTTEN_FLESH: 10
GUNPOWDER: 5.3
BONE: 1
# The limiter allows you to limit the amount of mobs & tiles there are on a single chunk.
# This system can be used to deny abusing spawning mobs, minecarts, etc.
#
# The soft-limit represents the limit to where mobs will be allowed to spawn in the chunk.
# The hard-limit represents the limts to where mobs will be removed when brought from other chunks (eg: Water slides or rails)
#
# This allows you to limit mobs while also allowing them to move between chunks.
limiter:
# The amount of time between chunk cleans. Setting it to a small amount can make your server have more lag, while a larger amount may mean slower
# responses
timer-time: 1200
mobs:
# The maximum limit of mobs that can spawn per chunk. Set this to a larger number, and use
# the per-limit system to set limits for certain types of mobs.
total-limit: -1
soft-limit:
# Dropped items are here because we don't want dropped items not to spawn.
dropped_item: 200
entity2: -1
#armor_stand: 20
hard-limit:
entity1: 100
#armor_stand: 100
tiles:
# The maximum limit of tile entities that can be placed per chunk. Note that there are
# very many types of tile entities, and they don't produce so much lag. This has limited
# uses for lag prevention, but may be used for other tasks.
# (!) Set to '-1' to disable it.
total-limit: -1
per-limit:
#crafthopper: 16
#craftchest: 128
tileentity1: -1
tileentity2: -1
# Anti Spawner-Lag implementation for large servers with a lot of spawners.
spawner-check:
# Should we enable the spawner check?
enabled: true
# Should we break spawners with a set chance (permille)? This highly helps
# severs where spawners are very easily procured.
breaker: false
# What chance (permille) should we have.
# EG: If you set it to 5, the chance will be 5/1000 which is 1/200;
chance: 5
# Custom spawner implementation. This should work with all spawner
# plugins, like EpicSpawners or SilkSpawners.
custom-settings:
# Delay in ticks between mob spawner spawns.
delay: 300
# (!) 1.12 ONLY FEATURES
# How many mobs should we spawn. This can greatly lower the mob lag
# from mob-spawners.
amount:
min: 1
max: 2
# How spread out we should spawn the entities. I recommend keeping it lower.
spawnrange: 3
# The maximum distance a player can be in order for the spawner to be active.
player-range: 10
# Automatic Spawner-Check activator. This will have no effect if the check is
# disabled.
# EG: If tps is under 19, lagassist will start modifying how the spawners work.
# TIP: Set to 0.0 to disable it.
maxtps: 16.0
# The Physics system disables laggy or ununsed game mechanics that might lag your server. The physics system can
# be set to be enabled on start or by using /lagassist.
#
# TIP: Disabling it here won't actually remove the checks when you use /lagassist. If you want some checks to
# work, please add them here.
deny-physics:
# Should we disable physics just as the server starts?
# TIP: It can be used to modify gameplay features.
# For example, you can disable decay, fire & melting for a build server.
enabled: false
# Automatic Physics disabler will occur if tps is under this value.
# EG: If tps is under 16, lagassist will disable the physics that are
# TIP: Set to 0.0 to disable it.
maxtps: 17.0
# What should we disable? Please make sure this fits your game perfectly. If you have a cannoning server,
# disabling explosions would be useless. At the same time, you shouldn't enable them for a survival server.
systems:
physics: false
explosions: true
grassspread: true
melting: true
pistons: true
fire: true
liquidspread: true
decay: true
redstone: true
# Had reports of noteblock & observer machines to lag the server significantly
noteblock: true
benchmark:
# Benchmarking can be used to approximate the max players your server will be able
# to sustain.
#
# TIP: If you want more accurate results (and don't mind waiting longer), change the
# ftp link under here.
# Placeholders: %RND% - Generate random name (useful for upload testing).
#
# (!) The size for upload is in bytes. A MB = 1.000.000 bytes. Default is 50MB
download:
link: "ftp://speedtest.tele2.net/50MB.zip"
upload:
link: "ftp://speedtest.tele2.net/upload/%RND%.bin"
size: 50000000
blacklisted-worlds:
# Worlds where this plugin will have no effect. All lag-measures will simply be disabled.
# (!) Analysis features are not disabled. (LagMonitor, LagMap)
enabled: false
list:
- blacklisted1name
- blacklisted2name
safety-manager:
# The safety manager tries to lower the chances of a server crash when the server
# is under extreme load or doesn't have enough resources to run.
#
# It will safely shut down the server whenever the respective settings are met.
# (!) This is an experimental feature and is still not recommended by default.
enabled: false
# Triggered when the system's space is not enough for a minecraft server. Shutting
# down the server prevents glitched chunks from forming.
no-space:
# Space for the server to start up in bytes. The default is 50 MB.
startup-space: 50000000
# Threshold under which server will safely shutdown th server. Default is 20MB.
shutdown-space: 20000000
# The anti-crasher module helps prevent players from crashing the server by spamming packets.
#
# It does so by limiting the amount of packets sent per second, along with their size.
anti-crasher:
# Useful against book crashers.
settings:
# When debug mode is on, you can see the serialized packets. Useful for analysing crash clients
# and solving them properly.
# (!) Only shows for packets that have a config location.
debug: false
packets:
packetplayinsetcreativeslot:
# The amount of packets recorded before the player gets dropped.
drop-threshold: 350
# The amount of packets to 'forget' each second.
decay: 80
# The max size of packet allowed. Useful for huge pages, etc.
size: 10000
# Illegal values in the packet. The values are found using deserialzation.
illegals:
- "THIS IS A TEST ILLEGAL VALUE"
# Fixing custom payload spam. May cause issues with bungee if you have some strange plugins. (Check size)
packetplayincustompayload:
drop-threshold: 25
decay: 15
size: 15000
illegals: []
packetplayinuseentity:
drop-threshold: 25
decay: 21
size: 5500
illegals: []
packetplayinuseitem:
drop-threshold: 25
decay: 21
size: 5500
illegals: []
packetplayinblockdig:
drop-threshold: 25
decay: 21
size: 2500
illegals: []
packetplayinblockplace:
drop-threshold: 25
decay: 21
size: 22000
illegals: []
packetplayinwindowclick:
drop-threshold: 25
decay: 21
size: 19000
illegals: []
packetplayinchat:
drop-threshold: 30
decay: 20
size: 10000
illegals: []
logcleaner:
# The Log-Cleaner cleans old logs from the directories that you select. You can use this feature to get rid of old
# logs.
#
# maxsize = Max size (in megabytes) that the log needs to have in order to be cleaned.
# maxage = Max time (in days) that the log needs to have in order to get removed.
#
# (!) Both of these settings are independent. If any of these conditions are met, the
# (!) file will get removed.
enabled: true
list:
- "logs/"
conditions:
maxsize: 30
maxage: 7
# (!) Highly Experimental! - May cause irreversible damage to your server. Please use with care.
super-loader:
# The super loader feature allows LagAssist and other plugins to implement so called "NMS Expansions".
# NMS Expansions allow the modification of minecraft classes during runtime.
enabled: false
stats-bar:
# The statsbar can be accessed using /lagassist statsbar. You can configure it to better show your server
# performance, or to better resemble your server's design choices.
# PLACEHOLDERS: {TPS} {CHKS} {MEM} {ENT}
message: "&c&l⬛ &fTPS: &a{TPS} &7&m|&r &fMEM: &a{MEM}GB &7&m|&r &fCHKS: &a{CHKS} &7&m|&r &fENT: &a{ENT} &c&l⬛"
# The interval in which the tps average is created. A lower value will be more acurrate but will fluctuate a lot.
# I suggest setting it around 6-12 for it to be the most precise.
tps-interval: 10
# How often should we refresh the statsbar? A lower value will look nicer and is more accurate, but might take more
# (yet a minuscule difference) processing power to show.
show-delay: 5
# The system that creates the lagmap.
lag-map:
# Do you want us to fully reserve filled_map:0? This will allow for placing lagmaps in spawns and giving them to players.
fully-reserve: false
# The lagassist API provides tools for other plugins to get information from your server using
# unconventional methods such as server-icon serialization. This provides several improvements
# over plugin messaging.
#
# (!) Currently used in the EntryRise.com Monitoring tool.
api:
# Config section for server icon data.
server-icon:
# THE IPS allowed to use this api. Empty to disable
# this feature.
# (!) Star matches everything
allowed-ips:
- "1.2.3.4"
- "9.9.9.9.*"
# This system allows you to configure the SmartUpdater Reminder. This
# system was developed to better notify users of important changes to
# the plugin and alert people using old and maybe inefficient ways of
# using the plugin.
smart-updater:
# This feature allows you to choose which updates you will get
# notified for. The default should only announce stable versions.
enabled: true
announce:
# Don't announce updates that have been flagged as unsafe due to
# major issues that have been detected.
unsafe: false
# Minimum likes received for the update post. Likes are usually
# given when a large bug has been fixed or i've added a new feature.
min-likes: 1
# Minimum downloads to announce the update.
min-downloads: 10
# Minimum rating. Note that unrated counts as 5 stars.
min-rating: 3.95
settings:
# Tooltips notify you when something may be broken in the current LagAssist version along with
# information to help you to remedy the issue.
tooltips: true
# The untested system notifies you if you are using the plugin on untested versions in order
# to prevent misuse.
untested: true
# Controls for plugins lagassist hooks into.
hooks:
# Vault is used for paying money to users.
vault:
# How much should the money be cached before being paid. A smaller value means faster payments at the expense of performance.
cache-duration: 1200
# What message should show up to players that get paid. %amount% for paid amount.
message: "&c&lLag&f&lAssist &e» &fYou were paid %amount% in the paywave."
# This allows the system to update the config if the plugin is updated.
version: 29

199
src/cx/sfy/LagAssist/Data.java

@ -0,0 +1,199 @@
package cx.sfy.LagAssist;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.UUID;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.OfflinePlayer;
import org.bukkit.block.Hopper;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.entity.Player;
import org.bukkit.map.MapView;
import cx.sfy.LagAssist.hoppers.SellHoppers;
import cx.sfy.LagAssist.packets.Reflection;
import cx.sfy.LagAssist.utils.WorldMgr;
public class Data {
private static File dataf = new File(Main.p.getDataFolder(), "data.yml");
private static FileConfiguration data = new YamlConfiguration();
public static void Enabler() {
try {
if (!dataf.exists()) {
dataf.createNewFile();
}
data.load(dataf);
} catch (Exception e) {
e.printStackTrace();
}
if (!data.contains("version")) {
if (data.contains("hoppers")) {
for (String rawh : data.getConfigurationSection("hoppers").getKeys(false)) {
String loc = "hoppers." + rawh;
List<String> values = data.getStringList(loc);
data.set(loc, null);
data.set(loc + ".materials", values);
}
}
data.set("version", 1);
saveData();
}
}
private static void saveData() {
//
// if (System.currentTimeMillis() - last < 1000) {
// return;
// }
//
//
// Bukkit.getScheduler().runTaskAsynchronously(Main.p, () -> {
try {
data.save(dataf);
} catch (IOException e) {
e.printStackTrace();
}
// });
}
private static short genMapId() {
MapView newe = Bukkit.createMap(Bukkit.getWorlds().get(0));
short mapid = (short) Reflection.getId(newe);
data.set("data.mapid", mapid);
saveData();
return mapid;
}
public static short getMapId() {
if (data.contains("data.mapid")) {
int mapid = data.getInt("data.mapid");
// if (Reflection.getMapView(mapid) == null) {
// return genMapId();
// } else {
// return mapid;
// }
return (short) mapid;
} else {
return genMapId();
}
}
public static void deleteHopper(Hopper h) {
String cloc = "hoppers." + WorldMgr.serializeLocation(h.getLocation());
data.set(cloc, null);
saveData();
}
public static boolean isSellHopper(Location loc) {
String cloc = "hoppers." + WorldMgr.serializeLocation(loc);
return data.getBoolean(cloc + ".sellhopper", false);
}
public static boolean toggleSellHopper(Player p, Location loc) {
String cloc = "hoppers." + WorldMgr.serializeLocation(loc);
String owner = data.getString(cloc + ".owner", "NONE");
if (!(p.getUniqueId().toString().equals(owner) || p.hasPermission("lagassist.hopper.bypass"))) {
p.sendMessage(Main.PREFIX + "You can't toggle selling for a hopper not owned by you");
return false;
}
String percentage = "§e" + SellHoppers.getMultiplierPercentage(Bukkit.getOfflinePlayer(p.getUniqueId())) + "%";
if (isSellHopper(loc)) {
data.set(cloc + ".sellhopper", false);
p.sendMessage(Main.PREFIX + "This sellhopper has been §cdisabled§f at " + percentage + "§f.");
saveData();
return true;
} else {
data.set(cloc + ".sellhopper", true);
p.sendMessage(Main.PREFIX + "This sellhopper has been §aenabled§f at " + percentage + "§f.");
saveData();
return true;
}
}
public static OfflinePlayer getOwningPlayer(Location loc) {
String cloc = "hoppers." + WorldMgr.serializeLocation(loc);
if (data.contains(cloc + ".owner")) {
return Bukkit.getOfflinePlayer(UUID.fromString(data.getString(cloc + ".owner")));
}
return null;
}
public static void setOwningPlayer(Location loc, OfflinePlayer owner) {
String cloc = "hoppers." + WorldMgr.serializeLocation(loc);
data.set(cloc + ".owner", owner.getUniqueId().toString());
saveData();
}
public static Set<Material> getFilterWhitelist(Location loc) {
String cloc = "hoppers." + WorldMgr.serializeLocation(loc);
List<String> found = null;
if (data.contains(cloc + ".materials")) {
found = data.getStringList(cloc + ".materials");
}
Set<Material> allowed = new HashSet<Material>();
if (found == null) {
return allowed;
}
for (String stg : found) {
allowed.add(Material.getMaterial(stg));
}
return allowed;
}
public static void saveFilterWhitelist(Location loc, Set<Material> mats) {
String cloc = "hoppers." + WorldMgr.serializeLocation(loc) + ".materials";
if (mats == null) {
data.set(cloc, null);
saveData();
return;
}
List<String> allowed = new ArrayList<String>();
for (Material mat : mats) {
allowed.add(mat.name());
}
data.set(cloc, allowed);
saveData();
}
}

36
src/cx/sfy/LagAssist/ExactTPS.java

@ -0,0 +1,36 @@
package cx.sfy.LagAssist;
public class ExactTPS implements Runnable {
public static int TICK_COUNT = 0;
public static long[] TICKS = new long[600];
public static long LAST_TICK = 0L;
public static double getTPS() {
return getTPS(100);
}
public static double getTPS(int ticks) {
if (TICK_COUNT - 1 < ticks) {
return 20.0D;
}
int target = (TICK_COUNT - 1 - ticks) % TICKS.length;
long elapsed = System.currentTimeMillis() - TICKS[target];
return ticks / (elapsed / 1000.0D);
}
public static long getElapsed(int tickID) {
if (TICK_COUNT - tickID >= TICKS.length) {
}
long time = TICKS[(tickID % TICKS.length)];
return System.currentTimeMillis() - time;
}
@Override
public void run() {
TICKS[(TICK_COUNT % TICKS.length)] = System.currentTimeMillis();
TICK_COUNT += 1;
}
}

148
src/cx/sfy/LagAssist/Main.java

@ -0,0 +1,148 @@
package cx.sfy.LagAssist;
import java.io.File;
import org.bukkit.Bukkit;
import org.bukkit.command.CommandSender;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.entity.Player;
import org.bukkit.event.Listener;
import org.bukkit.plugin.java.JavaPlugin;
import cx.sfy.LagAssist.api.APIManager;
import cx.sfy.LagAssist.chunks.ChkAnalyse;
import cx.sfy.LagAssist.chunks.ChkLimiter;
import cx.sfy.LagAssist.chunks.DynViewer;
import cx.sfy.LagAssist.client.ClientMain;
import cx.sfy.LagAssist.cmd.CommandListener;
import cx.sfy.LagAssist.cmd.CommandTabListener;
import cx.sfy.LagAssist.cmd.StatsAnalyse;
import cx.sfy.LagAssist.economy.EconomyManager;
import cx.sfy.LagAssist.gui.DataGUI;
import cx.sfy.LagAssist.hoppers.HopperManager;
import cx.sfy.LagAssist.logpurger.PurgerMain;
import cx.sfy.LagAssist.metrics.MetricsManager;
import cx.sfy.LagAssist.microfeatures.MicroManager;
import cx.sfy.LagAssist.mobs.SmartMob;
import cx.sfy.LagAssist.mobs.SpawnerMgr;
import cx.sfy.LagAssist.packets.PacketInjector;
import cx.sfy.LagAssist.packets.PacketMain;
import cx.sfy.LagAssist.packets.Reflection;
import cx.sfy.LagAssist.safety.SafetyManager;
import cx.sfy.LagAssist.stacker.StackManager;
import cx.sfy.LagAssist.updater.SmartUpdater;
import cx.sfy.LagAssist.utils.Others;
import cx.sfy.LagAssist.utils.VersionMgr;
import cx.sfy.LagAssist.utils.WorldMgr;
public class Main extends JavaPlugin implements Listener {
public static String USER = "%%__USER__%%";
public static final String PREFIX = "§c§lLag§f§lAssist §e» §f";
public static JavaPlugin p;
public static boolean paper = false;
// Debug mode means people will get verbose info.
public static int debug = 0;
private static File file;
public static FileConfiguration config = new YamlConfiguration();
@Override
public void onEnable() {
p = this;
file = new File(getDataFolder(), "server.yml");
config = Others.getConfig(file, 29);
paper = VersionMgr.isPaper();
// Start Smart updater to check for updates.
SmartUpdater.Enabler();
Bukkit.getLogger().info(Main.PREFIX + "Enabling Systems:");
EnableClasses(false);
getServer().getPluginManager().registerEvents(this, this);
getCommand("lagassist").setExecutor(new CommandListener());
getCommand("lagassist").setTabCompleter(new CommandTabListener());
}
private static void EnableClasses(boolean reload) {
EconomyManager.Enabler(reload);
SafetyManager.Enabler(reload);
Reflection.Enabler();
Data.Enabler();
SmartMob.Enabler(reload);
MicroManager.Enabler(reload);
HopperManager.Enabler(reload);
StackManager.Enabler(reload);
Redstone.Enabler(reload);
Physics.Enabler(reload);
Monitor.Enabler(reload);
MonTools.Enabler(reload);
WorldMgr.Enabler();
ChkAnalyse.Enabler();
ChkLimiter.Enabler(reload);
StatsAnalyse.Enabler(reload);
PurgerMain.Enabler();
SpawnerMgr.Enabler(reload);
DynViewer.Enabler(reload);
ClientMain.Enabler();
DataGUI.Enabler(reload);
MetricsManager.Enabler(reload);
PacketMain.Enabler(reload);
// API ICON
APIManager.Enabler(reload);
}
public static void ReloadPlugin(CommandSender s) {
config = Others.getConfig(file, 29);
Bukkit.getLogger().info(Main.PREFIX + "Reloading Systems:");
EnableClasses(true);
s.sendMessage(Main.PREFIX + "Reloaded the config successfully.");
}
@Override
public void onDisable() {
if (PacketMain.isPacketEnabled()) {
PacketInjector.Disabler();
}
StackManager.Disabler();
}
public static void sendDebug(String msg, int mindebug) {
if (mindebug > debug) {
return;
}
for (Player p : Bukkit.getOnlinePlayers()) {
if (!p.hasPermission("lagassist.debug")) {
continue;
}
p.sendMessage(msg + "(MINDEBUG: " + mindebug + ")");
}
if (debug == 2) {
try {
throw new Exception(msg);
} catch (Exception e) {
e.printStackTrace();
}
return;
}
}
}

222
src/cx/sfy/LagAssist/MonTools.java

@ -0,0 +1,222 @@
package cx.sfy.LagAssist;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.World;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerItemHeldEvent;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.PlayerInventory;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.map.MapView;
import cx.sfy.LagAssist.maps.TpsRender;
import cx.sfy.LagAssist.minebench.SpecsGetter;
import cx.sfy.LagAssist.packets.Reflection;
import cx.sfy.LagAssist.utils.VersionMgr;
public class MonTools implements Listener {
public static ItemStack mapitem = VersionMgr.getMap();
public static ItemMeta mapitemmeta = mapitem.getItemMeta();
public static List<UUID> actionmon = new ArrayList<UUID>();
public static List<UUID> mapusers = new ArrayList<UUID>();
private static DecimalFormat format = new DecimalFormat("#0.00");
private static String stbmsg = Main.config.getString("stats-bar.message");
private static int stbinterv = Main.config.getInt("stats-bar.tps-interval");
private static int stbshowdl = Main.config.getInt("stats-bar.show-delay");
public static void Enabler(boolean reload) {
if (!reload) {
Main.p.getServer().getPluginManager().registerEvents(new MonTools(), Main.p);
}
Bukkit.getLogger().info(" §e[§a✔§e] §fMapVisualizer.");
mapitemmeta.setDisplayName("§c§lLag§f§lAssist §e§lMonitor");
mapitem.setItemMeta(mapitemmeta);
int mapid = VersionMgr.getMapId(mapitem);
MapView view = Reflection.getMapView(mapid);
if (view != null) {
view.getRenderers().clear();
view.addRenderer(new TpsRender());
}
StatsBar();
}
public static void StatsBar() {
Bukkit.getScheduler().runTaskTimer(Main.p, () -> {
if (actionmon.size() == 0) {
return;
}
boolean found = false;
for (int i = 0; i<actionmon.size();i++) {
if (Bukkit.getPlayer(actionmon.get(i)) != null) {
found = true;
break;
}
}
if (!found) {
return;
}
double tpsraw = (ExactTPS.getTPS(10) > 20) ? 20 : ExactTPS.getTPS(stbinterv);
String chunks = String.valueOf(getChunkCount());
String ents = String.valueOf(getEntCount());
Bukkit.getScheduler().runTaskAsynchronously(Main.p, () -> {
if (actionmon.isEmpty()) {
return;
}
String tps;
if (tpsraw > 18) {
tps = "§a" + format.format(tpsraw);
} else if (tpsraw > 15) {
tps = "§e" + format.format(tpsraw);
} else {
tps = "§c" + format.format(tpsraw);
}
String s = ChatColor.translateAlternateColorCodes('&',
stbmsg.replaceAll("\\{TPS\\}", tps)
.replaceAll("\\{MEM\\}", format.format(SpecsGetter.FreeRam() / 1024))
.replaceAll("\\{CHKS\\}", chunks)
.replaceAll("\\{ENT\\}", ents));
for (UUID u : actionmon) {
Player p = Bukkit.getPlayer(u);
if (p == null) {
continue;
}
Reflection.sendAction(p, s);
}
});
}, stbshowdl, stbshowdl);
}
public static int getEntCount() {
int lng = 0;
for (World w : Bukkit.getWorlds()) {
lng += w.getEntities().size();
}
return lng;
}
public static int getChunkCount() {
int lng = 0;
for (World w : Bukkit.getWorlds()) {
lng += w.getLoadedChunks().length;
}
return lng;
}
@EventHandler
public void onSlotChange(PlayerItemHeldEvent e) {
Player p = e.getPlayer();
ItemStack old = p.getInventory().getItem(e.getPreviousSlot());
ItemStack nw = p.getInventory().getItem(e.getNewSlot());
if (runNew(nw, p)) {
return;
}
runOld(old, p);
}
// @EventHandler(priority = EventPriority.LOWEST)
// public void onMapLoad(MapInitializeEvent e) {
// Main.p.getLogger().warning("0");
// MapView view = e.getMap();
//
// if (Reflection.getMapId(e.get) != Data.getMapId()) {
// return;
// }
//
// Main.p.getLogger().warning("1");
//
// view.addRenderer(new TpsRender());
// }
public static void giveMap(Player p) {
PlayerInventory inv = p.getInventory();
int slot = inv.getHeldItemSlot();
inv.setItem(slot, MonTools.mapitem);
UUID UUID = p.getUniqueId();
if (!mapusers.contains(UUID)) {
mapusers.add(UUID);
}
}
private static void runOld(ItemStack old, Player p) {
if (old == null) {
return;
}
if (!old.hasItemMeta()) {
return;
}
ItemMeta ometa = old.getItemMeta();
if (!ometa.hasDisplayName()) {
return;
}
if (ometa.getDisplayName() != mapitemmeta.getDisplayName()) {
return;
}
UUID UUID = p.getUniqueId();
if (!mapusers.contains(UUID)) {
mapusers.add(UUID);
}
}
private static boolean runNew(ItemStack nw, Player p) {
if (!p.hasPermission("lagassist.use")) {
return false;
}
if (nw == null) {
return false;
}
if (!nw.hasItemMeta()) {
return false;
}
ItemMeta nwmeta = nw.getItemMeta();
if (!nwmeta.hasDisplayName()) {
return false;
}
if (nwmeta.getDisplayName() != mapitemmeta.getDisplayName()) {
return false;
}
UUID UUID = p.getUniqueId();
if (!mapusers.contains(UUID)) {
mapusers.add(UUID);
}
return true;
}
}

255
src/cx/sfy/LagAssist/Monitor.java

@ -0,0 +1,255 @@
package cx.sfy.LagAssist;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.text.DecimalFormat;
import java.util.Arrays;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.entity.Player;
import org.bukkit.scheduler.BukkitTask;
import cx.sfy.LagAssist.hoppers.ChunkHoppers;
import cx.sfy.LagAssist.mobs.SmartMob;
import cx.sfy.LagAssist.mobs.SpawnerMgr;
public class Monitor {
private final static String name = Bukkit.getServer().getClass().getPackage().getName();
private final static String version = name.substring(name.lastIndexOf('.') + 1);
private static DecimalFormat format = new DecimalFormat("##.##");
private static Object serverInstance;
private static Field tpsField;
public static Runtime Rtm = Runtime.getRuntime();
public static byte[][] colors = new byte[129][129];
public static double exactTPS = 20.0;
public static int mondelay;
private static BukkitTask btk;
public static void Enabler(boolean reload) {
Bukkit.getLogger().info(" §e[§a✔§e] §fLag Monitor.");
for (byte[] row : colors)
Arrays.fill(row, (byte) 34);
mondelay = Main.config.getInt("lag-measures.timer");
if (!reload) {
Bukkit.getServer().getScheduler().scheduleSyncRepeatingTask(Main.p, new ExactTPS(), 100L, 1L);
LagDetect();
GetExactTPS();
createGraph();
}
try {
serverInstance = getNMSClass("MinecraftServer").getMethod("getServer").invoke(null);
tpsField = serverInstance.getClass().getField("recentTps");
} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException | NoSuchMethodException
| SecurityException | NoSuchFieldException e) {
e.printStackTrace();
}
}
private static void LagMeasures(double d) {
float tps = (float) (Math.floor(d * 100) / 100);
SmartMob.Spawning = true;
Physics.denyphysics = false;
SpawnerMgr.active = false;
ChunkHoppers.mobhoppers = false;
String stg = Main.PREFIX + "LagMeasures executed: §e";
if (tps <= Main.config.getDouble("smart-cleaner.maxtps-cull")) {
SmartMob.MobCuller();
stg += "Culled Mobs, ";
}
if (tps <= Main.config.getDouble("smart-cleaner.maxtps-disablespawn")) {
SmartMob.Spawning = false;
stg += "Disabled MobSpawn, ";
}
if (tps <= Main.config.getDouble("redstone-culler.maxtps")) {
Redstone.CullRedstone();
stg += "Culled Redstone, ";
}
if (tps <= Main.config.getDouble("deny-physics.maxtps")) {
Physics.denyphysics = true;
stg += "Disabled physics, ";
}
if (tps <= Main.config.getDouble("spawner-check.maxtps")) {
SpawnerMgr.active = true;
stg += "Optimizing Spawners, ";
}
if (tps <= Main.config.getDouble("hopper-check.chunk-hoppers.mob-hopper.maxtps")) {
ChunkHoppers.mobhoppers = true;
stg += "Mob Hoppers.";
}
if (Main.config.getBoolean("lag-measures.announce.enabled")) {
for (Player player : Bukkit.getOnlinePlayers()) {
if (Main.config.getBoolean("lag-measures.announce.staffmsg")) {
if (player.hasPermission("lagassist.notify")) {
if (stg.equals(Main.PREFIX + "LagMeasures executed: §e")) {
player.sendMessage(Main.PREFIX + "No LagMeasures Executed");
} else {
player.sendMessage(stg);
}
} else {
player.sendMessage(ChatColor.translateAlternateColorCodes('&',
Main.config.getString("lag-measures.announce.message")));
}
} else {
player.sendMessage(ChatColor.translateAlternateColorCodes('&',
Main.config.getString("lag-measures.announce.message")));
}
}
}
// if (tps < 19.5) {
// Bukkit.getLogger().info(Main.PREFIX + "TPS under 19.5!
// Culling redstone.");
// Redstone.CullRedstone();
// SmartMob.Spawning = true;
// if (!Main.config.getBoolean("deny-physics.enabled")) {
// Physics.denyphysics = false;
// }
// } else if (tps < 18.5) {
// Bukkit.getLogger().info(Main.PREFIX + "TPS under 18.5!
// Culling redstone & disabling Physics");
// SmartMob.Spawning = true;
// if (!Main.config.getBoolean("deny-physics.enabled")) {
// Physics.denyphysics = true;
// }
// Redstone.CullRedstone();
// } else if (tps < 15) {
// Bukkit.getLogger().info(Main.PREFIX + "TPS under 15.0!
// Aggresive systems has been activated");
// if (!Main.config.getBoolean("deny-physics.enabled")) {
// Physics.denyphysics = true;
// }
// Redstone.CullRedstone();
// SmartMob.MobCuller();
// SmartMob.Spawning = false;
// } else {
// SmartMob.Spawning = true;
// if (!Main.config.getBoolean("deny-physics.enabled")) {
// Physics.denyphysics = false;
// }
// }
}
public static void LagDetect() {
Bukkit.getScheduler().runTaskTimerAsynchronously(Main.p, new Runnable() {
@Override
public void run() {
Bukkit.getScheduler().scheduleSyncDelayedTask(Main.p, new Runnable() {
@Override
public void run() {
if (Main.config.getBoolean("lag-measures.announce.enabled")) {
Bukkit.getLogger().info(" §e[§a☯§e] §fRunning lag check task.");
}
LagMeasures(Double.valueOf(getTPS(0)));
}
}, 0L);
}
}, mondelay, mondelay);
}
public static void GetExactTPS() {
btk = Bukkit.getScheduler().runTaskTimerAsynchronously(Main.p, new Runnable() {
@Override
public void run() {
try {
Bukkit.getScheduler().scheduleSyncDelayedTask(Main.p, new Runnable() {
@Override
public void run() {
double ext = ExactTPS.getTPS();
if (ext > 20 || ext == 0) {
ext = 20;
}
exactTPS = ext;
}
}, 0L);
} catch (IllegalStateException e) {
btk.cancel();
}
}
}, 60L, 1L);
}
public static long freeMEM() {
return Rtm.freeMemory() / 1048576;
}
public static String getTPS(int time) {
try {
double[] tps = ((double[]) tpsField.get(serverInstance));
return format.format(tps[time]).replace(',', '.');
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
}
}
public static void createGraph() {
Bukkit.getScheduler().runTaskTimerAsynchronously(Main.p, new Runnable() {
@Override
public void run() {
double ctps = ExactTPS.getTPS(20);
double medtps = Double.valueOf(getTPS(1));
if (medtps > 15) {
medtps = 15.0;
}
if (ctps > 20) {
ctps = 20.0;
}
double min = medtps - 5;
double ntps = 89 - (ctps - min) * 8;
// Bukkit.getLogger().info(String.valueOf(ntps));
for (int i = 89; i > 9; i--) {
if (i == (int) ntps) {
colors[124][i] = 18;
} else if (i == (int) ntps + 1) {
colors[124][i] = -124;
} else if (i > ntps) {
colors[124][i] = -122;
} else {
colors[124][i] = 32;
}
}
// BEGIN GRAPHING
for (int i = 3; i < 124; i++) {
for (int j = 3; j < 90; j++) {
colors[i][j] = colors[i + 1][j];
}
}
}
}, 7L, 7L);
}
private static Class<?> getNMSClass(String className) {
try {
return Class.forName("net.minecraft.server." + version + "." + className);
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
}
}
}

111
src/cx/sfy/LagAssist/MsrExec.java

@ -0,0 +1,111 @@
package cx.sfy.LagAssist;
import org.bukkit.Bukkit;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import cx.sfy.LagAssist.chunks.ChkAnalyse;
import cx.sfy.LagAssist.hoppers.ChunkHoppers;
import cx.sfy.LagAssist.mobs.SmartMob;
import cx.sfy.LagAssist.mobs.SpawnerMgr;
import cx.sfy.LagAssist.utils.MathUtils;
public class MsrExec {
public static void togglePhysics(CommandSender sender) {
if (Physics.denyphysics) {
sender.sendMessage(Main.PREFIX + "Physics were enabled.");
Physics.denyphysics = false;
} else {
sender.sendMessage(Main.PREFIX + "Physics were disabled.");
Physics.denyphysics = true;
}
}
public static void toggleMobs(CommandSender sender) {
if (SmartMob.Spawning) {
sender.sendMessage(Main.PREFIX + "Mob spawning was disabled.");
SmartMob.Spawning = false;
} else {
sender.sendMessage(Main.PREFIX + "Mob spawning was enabled.");
SmartMob.Spawning = true;
}
}
public static void toggleSpawnerOptimization(CommandSender sender) {
if (SpawnerMgr.active) {
sender.sendMessage(Main.PREFIX + "Spawners are no longer optimized.");
SpawnerMgr.active = false;
} else {
sender.sendMessage(Main.PREFIX + "Spawners are now optimized.");
SpawnerMgr.active = true;
}
}
public static void cullRedstone(CommandSender sender) {
Redstone.CullRedstone();
sender.sendMessage(Main.PREFIX + "Starting to cull Redstone Changes...");
}
public static void cullMobs(CommandSender sender) {
SmartMob.MobCuller();
sender.sendMessage(Main.PREFIX + "Clearing mobs...");
}
public static void showVersion(CommandSender sender) {
sender.sendMessage(Main.PREFIX + "Lagassist version: §e" + Main.p.getDescription().getVersion());
}
public static void giveMap(CommandSender sender) {
if (sender instanceof Player) {
Player p = (Player) sender;
sender.sendMessage(Main.PREFIX + "You have received a monitor map.");
MonTools.giveMap(p);
} else {
sender.sendMessage(Main.PREFIX + "You cannot get the map from console.");
}
}
public static void giveChunkHopper(CommandSender sender, String[] args) {
Player p = Bukkit.getPlayer(args[1]);
if (p == null) {
sender.sendMessage(Main.PREFIX + "There is no player with that name online.");
return;
}
if (!MathUtils.isInt(args[2])) {
sender.sendMessage(Main.PREFIX + "The amount must be a number.");
return;
}
ChunkHoppers.giveChunkHopper(p, Integer.valueOf(args[2]));
}
public static void analyseChunks(CommandSender sender, String[] args) {
if (args.length == 2 && args[1].equals("this")) {
ChkAnalyse.analyseCurrentChunk(sender);
} else {
if (sender instanceof Player) {
Player p = (Player) sender;
ChkAnalyse.analyseChunks(p);
} else {
ChkAnalyse.analyseChunks(sender);
}
}
}
public static boolean physics() {
return !Physics.denyphysics;
}
public static boolean mobSpawning() {
return SmartMob.Spawning;
}
public static boolean spawnerOptimization() {
return SpawnerMgr.active;
}
}

188
src/cx/sfy/LagAssist/Physics.java

@ -0,0 +1,188 @@
package cx.sfy.LagAssist;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
import org.bukkit.Bukkit;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.block.BlockExplodeEvent;
import org.bukkit.event.block.BlockFadeEvent;
import org.bukkit.event.block.BlockFormEvent;
import org.bukkit.event.block.BlockFromToEvent;
import org.bukkit.event.block.BlockIgniteEvent;
import org.bukkit.event.block.BlockPhysicsEvent;
import org.bukkit.event.block.BlockPistonExtendEvent;
import org.bukkit.event.block.BlockPistonRetractEvent;
import org.bukkit.event.block.BlockRedstoneEvent;
import org.bukkit.event.block.BlockSpreadEvent;
import org.bukkit.event.block.LeavesDecayEvent;
import org.bukkit.event.block.NotePlayEvent;
import cx.sfy.LagAssist.utils.WorldMgr;
public class Physics implements Listener {
public static boolean denyphysics = false;
private static Set<String> mats = new HashSet<String>(Arrays.asList("REDSTONE_WIRE", "NOTE_BLOCK", "PISTON", "PISTON_HEAD", "DIODE", "REPEATER", "COMPARATOR", "REDSTONE_COMPARATOR", "REDSTONE_COMPARATOR_ON", "REDSTONE_COMPARATOR_OFF"));
public static void Enabler(boolean reload) {
if (!reload) {
Main.p.getServer().getPluginManager().registerEvents(new Physics(), Main.p);
}
Bukkit.getLogger().info(" §e[§a✔§e] §fPhysics-Tweaker.");
denyphysics = Main.config.getBoolean("deny-physics.enabled");
}
@EventHandler(priority = EventPriority.LOWEST)
public void disablePhysics(BlockPhysicsEvent e) {
if (Main.config.getBoolean("deny-physics.systems.physics") && denyphysics) {
if (WorldMgr.blacklist.contains(e.getBlock().getWorld().getName())) {
return;
}
if (mats.contains(e.getChangedType().toString().toUpperCase())) {
return;
}
e.setCancelled(true);
}
}
@EventHandler(priority = EventPriority.LOWEST)
public void disableExplosions(BlockExplodeEvent e) {
if (Main.config.getBoolean("deny-physics.systems.explosions") && denyphysics) {
if (WorldMgr.blacklist.contains(e.getBlock().getWorld().getName())) {
return;
}
e.setCancelled(true);
}
}
@EventHandler(priority = EventPriority.LOWEST)
public void pistonBrkRetract(BlockPistonRetractEvent e) {
if (Main.config.getBoolean("deny-physics.systems.pistons") && denyphysics) {
if (WorldMgr.blacklist.contains(e.getBlock().getWorld().getName())) {
return;
}
e.setCancelled(true);
}
}
@EventHandler(priority = EventPriority.LOWEST)
public void pistonBrkPush(BlockPistonExtendEvent e) {
if (Main.config.getBoolean("deny-physics.systems.pistons") && denyphysics) {
if (WorldMgr.blacklist.contains(e.getBlock().getWorld().getName())) {
return;
}
e.setCancelled(true);
}
}
@EventHandler(priority = EventPriority.LOWEST)
public void itemMelt(BlockFadeEvent e) {
if (Main.config.getBoolean("deny-physics.systems.melting") && denyphysics) {
if (WorldMgr.blacklist.contains(e.getBlock().getWorld().getName())) {
return;
}
e.setCancelled(true);
}
}
@EventHandler(priority = EventPriority.LOWEST)
public void grassSpread(BlockFormEvent e) {
if (Main.config.getBoolean("deny-physics.systems.grassspread") && denyphysics) {
if (WorldMgr.blacklist.contains(e.getBlock().getWorld().getName())) {
return;
}
e.setCancelled(true);
}
}
@EventHandler(priority = EventPriority.LOWEST)
public void grassSpread(BlockSpreadEvent e) {
if (Main.config.getBoolean("deny-physics.systems.grassspread") && denyphysics) {
if (WorldMgr.blacklist.contains(e.getBlock().getWorld().getName())) {
return;
}
e.setCancelled(true);
}
}
@EventHandler(priority = EventPriority.LOWEST)
public void fire(BlockIgniteEvent e) {
if (Main.config.getBoolean("deny-physics.systems.fire") && denyphysics) {
if (WorldMgr.blacklist.contains(e.getBlock().getWorld().getName())) {
return;
}
e.setCancelled(true);
}
}
@EventHandler(priority = EventPriority.LOWEST)
public void liquid(BlockFromToEvent e) {
if (Main.config.getBoolean("deny-physics.systems.liquidspread") && denyphysics) {
if (WorldMgr.blacklist.contains(e.getBlock().getWorld().getName())) {
return;
}
e.setCancelled(true);
}
}
@EventHandler(priority = EventPriority.LOWEST)
public void leaves(LeavesDecayEvent e) {
if (Main.config.getBoolean("deny-physics.systems.decay") && denyphysics) {
if (WorldMgr.blacklist.contains(e.getBlock().getWorld().getName())) {
return;
}
e.setCancelled(true);
}
}
@EventHandler(priority = EventPriority.LOWEST)
public void onNoteBlocks(NotePlayEvent e) {
if (Main.config.getBoolean("deny-physics.systems.noteblock") && denyphysics) {
if (WorldMgr.blacklist.contains(e.getBlock().getWorld().getName())) {
return;
}
e.setCancelled(true);
}
}
@EventHandler(priority = EventPriority.LOWEST)
public void onRedstone(BlockRedstoneEvent e) {
if (Main.config.getBoolean("deny-physics.systems.redstone") && denyphysics) {
if (WorldMgr.blacklist.contains(e.getBlock().getWorld().getName())) {
return;
}
e.setNewCurrent(0);
}
}
// public static ItemStack filterItem(ItemStack itm) {
// if (itm == null) {
// return null;
// }
// ItemStack unfiltered = itm.clone();
//
// Material type = unfiltered.getType();
// int amount = Math.min(type.getMaxStackSize(), Math.max(unfiltered.getAmount(), 0));
//
//
// ItemStack filtered = new ItemStack(type, amount, unfiltered.getDurability());
// return filtered;
// }
//
// @EventHandler(priority = EventPriority.MONITOR)
// public void onCreativeItem(InventoryCreativeEvent e) {
// if (e.isCancelled()) {
// return;
// }
//
// e.setCurrentItem(filterItem(e.getCurrentItem()));
// e.setCursor(filterItem(e.getCursor()));
// }
}

112
src/cx/sfy/LagAssist/Redstone.java

@ -0,0 +1,112 @@
package cx.sfy.LagAssist;
import java.util.SplittableRandom;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.block.BlockPhysicsEvent;
import org.bukkit.event.block.BlockRedstoneEvent;
import org.bukkit.scheduler.BukkitRunnable;
import org.bukkit.scheduler.BukkitTask;
import cx.sfy.LagAssist.utils.V1_11;
import cx.sfy.LagAssist.utils.VersionMgr;
import cx.sfy.LagAssist.utils.WorldMgr;
public class Redstone implements Listener {
SplittableRandom sr = new SplittableRandom();
public static boolean redstoneculler;
private static boolean destructives;
private static int chance;
private static int ticks;
private static BukkitTask br;
public static void Enabler(boolean reload) {
redstoneculler = false;
destructives = Main.config.getBoolean("redstone-culler.destructive.enabled");
chance = Main.config.getInt("redstone-culler.chance");
ticks = Main.config.getInt("redstone-culler.ticks");
if (!reload) {
Main.p.getServer().getPluginManager().registerEvents(new Redstone(), Main.p);
}
Bukkit.getLogger().info(" §e[§a✔§e] §fRedstone Culler.");
}
public static void CullRedstone() {
if (!redstoneculler) {
redstoneculler = true;
setTimer();
} else if (Bukkit.getScheduler().isCurrentlyRunning(br.getTaskId())) {
br.cancel();
setTimer();
}
}
private static void setTimer() {
br = new BukkitRunnable() {
@Override
public void run() {
redstoneculler = false;
if (VersionMgr.isV1_11()) {
V1_11.ObserverBreaker();
}
}
}.runTaskLater(Main.p, ticks);
}
@EventHandler
public void RedstoneCuller(BlockRedstoneEvent e) {
if (!redstoneculler) {
return;
}
if (WorldMgr.isBlacklisted(e.getBlock().getWorld())) {
return;
}
e.setNewCurrent(0);
if (chance < 0) {
return;
}
Block b = e.getBlock();
if (!Main.config.getStringList("redstone-culler.affected-materials").contains(b.getType().toString().toUpperCase())) {
return;
}
int rand = sr.nextInt(100);
if (rand > chance) {
return;
}
b.setType(Material.AIR);
}
@EventHandler
public void ObserverCuller(BlockPhysicsEvent e) {
if (redstoneculler) {
if (WorldMgr.isBlacklisted(e.getBlock().getWorld())) {
return;
}
if (VersionMgr.isV1_11()) {
if (destructives) {
V1_11.ObserverAdd(e.getBlock());
}
if (V1_11.isObserver(e.getBlock())) {
e.setCancelled(true);
}
}
}
}
}

17
src/cx/sfy/LagAssist/api/APIManager.java

@ -0,0 +1,17 @@
package cx.sfy.LagAssist.api;
import org.bukkit.Bukkit;
import cx.sfy.LagAssist.Main;
public class APIManager {
public static void Enabler(boolean reload) {
Bukkit.getLogger().info(" §e[§a✔§e] §fAPI Tools.");
if (!reload) {
Main.p.getServer().getPluginManager().registerEvents(new MotdAPI(), Main.p);
}
}
}

99
src/cx/sfy/LagAssist/api/MotdAPI.java

@ -0,0 +1,99 @@
package cx.sfy.LagAssist.api;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.net.InetAddress;
import java.util.regex.Pattern;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.server.ServerListPingEvent;
import org.bukkit.util.CachedServerIcon;
import cx.sfy.LagAssist.Main;
import cx.sfy.LagAssist.Monitor;
import cx.sfy.LagAssist.utils.MathUtils;
public class MotdAPI implements Listener {
@EventHandler(priority = EventPriority.HIGHEST)
public void onServerPing(ServerListPingEvent e) {
InetAddress addr = e.getAddress();
String saddr = addr.getHostAddress();
Main.sendDebug("Received ping from " + saddr, 1);
boolean found = false;
for (String stg : Main.config.getStringList("api.server-icon.allowed-ips")) {
Pattern pat = Pattern.compile(stg.replace("*", "(.*.)"));
found = pat.matcher(saddr).find();
if (found) {
break;
}
}
if (!found) {
return;
}
Main.sendDebug("API ping response to " + saddr, 1);
try {
e.setServerIcon(generateIcon());
} catch (Exception ex) {
ex.printStackTrace();
}
}
private static CachedServerIcon generateIcon() throws Exception{
ByteArrayOutputStream baos = new ByteArrayOutputStream();
DataOutputStream dos = new DataOutputStream(baos);
float tps[] = new float[]{(Double.valueOf(Monitor.getTPS(0)).floatValue()), (Double.valueOf(Monitor.getTPS(1)).floatValue()), (Double.valueOf(Monitor.getTPS(2)).floatValue())};
for (int i = 0; i< tps.length; i++) {
System.out.println(tps[i]);
dos.writeFloat(tps[i]);
}
dos.flush();
baos.flush();
return new CachedServerIcon() {
@Override
public String getData() {
return javax.xml.bind.DatatypeConverter.printBase64Binary(baos.toByteArray());
}
};
}
public static BufferedImage convertBytesToImage(byte[] bts) {
int[] pixels = MathUtils.bytesToIntegers(bts);
int size = 64;
BufferedImage img = new BufferedImage(size, size, BufferedImage.TYPE_4BYTE_ABGR);
img.setRGB(0, 0, bts.length);
int pixel;
for (pixel = 1; pixel <= pixels.length; pixel++) {
int x = pixel%size;
int y = pixel/size;
img.setRGB(x, y, pixels[pixel-1]);
}
return img;
}
}

145
src/cx/sfy/LagAssist/chunks/ChkAnalyse.java

@ -0,0 +1,145 @@
package cx.sfy.LagAssist.chunks;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.bukkit.Bukkit;
import org.bukkit.Chunk;
import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.block.BlockState;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;
import cx.sfy.LagAssist.Main;
public class ChkAnalyse {
protected static int ammoshow = Main.config.getInt("chunkanalyse.ammount");
protected static Map<String, Integer> values = new HashMap<String, Integer>();
private static List<ChkStats> scores = new ArrayList<ChkStats>();
public static void Enabler() {
Bukkit.getLogger().info(" §e[§a✔§e] §fChunk Analyser.");
Set<String> slist = Main.config.getConfigurationSection("chunkanalyse.values").getKeys(false);
for (String s : slist) {
int value = Main.config.getInt("chunkanalyse.values." + s);
values.put(s.toLowerCase(), value);
}
}
public static void analyseChunks(Player p) {
scores.clear();
for (World w : Bukkit.getWorlds()) {
for (Chunk ch : w.getLoadedChunks()) {
scores.add(new ChkStats(ch, false));
}
}
Bukkit.getScheduler().runTaskAsynchronously(Main.p, new Runnable() {
@Override
public void run() {
for (ChkStats ch : scores) {
ch.genScores();
}
Collections.sort(scores);
p.sendMessage("");
p.sendMessage("§c§l⬛⬛⬛⬛⬛⬛ §f§lCHUNKANALYSER §c§l⬛⬛⬛⬛⬛⬛");
p.sendMessage("");
for (int i = 0; i < ammoshow; i++) {
ChkStats cs = scores.get(i);
p.spigot().sendMessage(cs.genText());
}
p.sendMessage("");
p.sendMessage("§c§l⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛");
}
});
}
public static void analyseChunks(CommandSender p) {
Map<Chunk, Integer> chunkscore = new HashMap<Chunk, Integer>();
for (World w : Bukkit.getWorlds()) {
for (Chunk ch : w.getLoadedChunks()) {
if (!chunkscore.containsKey(ch)) {
chunkscore.put(ch, 0);
}
BlockState[] tiles = ch.getTileEntities();
for (BlockState blkst : tiles) {
String m = blkst.getType().toString().toLowerCase();
if (values.containsKey(m)) {
chunkscore.put(ch, chunkscore.get(ch) + values.get(m));
}
}
Entity[] ents = ch.getEntities();
for (Entity e : ents) {
String et = e.getType().toString().toLowerCase();
if (values.containsKey(et)) {
chunkscore.put(ch, chunkscore.get(ch) + values.get(et));
}
}
}
}
p.sendMessage("");
p.sendMessage("⬛⬛⬛⬛⬛⬛ §f§lCHUNKANALYSER ⬛⬛⬛⬛⬛⬛");
p.sendMessage("");
Stream<Map.Entry<Chunk, Integer>> sorted = chunkscore.entrySet().stream()
.sorted(Collections.reverseOrder(Map.Entry.comparingByValue()));
Map<Chunk, Integer> topTen = sorted.limit(ammoshow)
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (e1, e2) -> e1, LinkedHashMap::new));
for (Chunk ch : topTen.keySet()) {
int score = chunkscore.get(ch);
p.sendMessage(" ✸ Chunk (" + String.valueOf(ch.getX()) + " " + String.valueOf(ch.getZ()) + ") - Score "
+ String.valueOf(score));
}
p.sendMessage("");
p.sendMessage("⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛");
}
public static void analyseCurrentChunk(CommandSender s) {
if (!(s instanceof Player)) {
s.sendMessage(Main.PREFIX + "You cannot analyse the current chunk from console.");
return;
}
Player p = (Player) s;
Location l = p.getLocation();
ChkStats stats = new ChkStats(l.getChunk(), true);
int coords[] = stats.getCoords();
String crds = String.valueOf(coords[0]) + " " + String.valueOf(coords[1]);
String cmd = "lagassist tpchunk " + p.getWorld().getName() + " " + String.valueOf(coords[0]) + " "
+ String.valueOf(coords[1]);
p.sendMessage("§c§l⬛⬛⬛⬛⬛⬛ §f§lCHUNK STATS §c§l⬛⬛⬛⬛⬛⬛");
p.sendMessage("");
p.sendMessage(" §c✸ §fChunk coordonates: §e" + crds);
p.sendMessage("");
p.sendMessage(" §c✸ §fEntity Amount: §e" + stats.getEnts().length);
p.sendMessage(" §c✸ §fTiles Amount: §e" + stats.getTiles().length);
p.sendMessage("");
p.spigot().sendMessage(stats.genMobCount(" §c✸ §fDetailed Info §e(HOVER)", cmd));
p.sendMessage("");
p.sendMessage("§c§l⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛");
}
}

256
src/cx/sfy/LagAssist/chunks/ChkLimiter.java

@ -0,0 +1,256 @@
package cx.sfy.LagAssist.chunks;
import java.util.HashMap;
import java.util.Map;
import org.bukkit.Bukkit;
import org.bukkit.Chunk;
import org.bukkit.World;
import org.bukkit.block.Block;
import org.bukkit.block.BlockState;
import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.Vehicle;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.block.BlockPlaceEvent;
import org.bukkit.event.entity.EntitySpawnEvent;
import org.bukkit.event.vehicle.VehicleCreateEvent;
import cx.sfy.LagAssist.Main;
import cx.sfy.LagAssist.utils.Cache;
public class ChkLimiter implements Listener {
private static Cache<Chunk, Entity[]> entcache = new Cache<Chunk, Entity[]>(30);
private static Cache<Chunk, BlockState[]> tilecache = new Cache<Chunk, BlockState[]>(100);
private static int moblimit = -1;
private static int tilelimit = -1;
public static void Enabler(boolean reload) {
if (!reload) {
Main.p.getServer().getPluginManager().registerEvents(new ChkLimiter(), Main.p);
runTask();
}
Bukkit.getLogger().info(" §e[§a✔§e] §fChunk Limiter.");
moblimit = Main.config.getInt("limiter.mobs.total-limit");
tilelimit = Main.config.getInt("limiter.tiles.total-limit");
}
static int i = 0;
private static void runTask() {
Bukkit.getScheduler().scheduleSyncRepeatingTask(Main.p, () -> {
i++;
if (i % Main.config.getInt("limiter.timer-time") == 0) {
for (World w : Bukkit.getWorlds()) {
for (Chunk chk : w.getLoadedChunks()) {
Map<EntityType, Integer> counts = new HashMap<EntityType, Integer>();
for (Entity ent : chk.getEntities()) {
EntityType type = ent.getType();
int allowed = getMobMaxHard(type);
if (allowed == -1) {
continue;
}
int count = counts.getOrDefault(ent.getType(), 0);
// Over 30 bye
if (count < allowed) {
counts.put(type, count + 1);
continue;
}
ent.remove();
}
}
}
}
tilecache.tick();
entcache.tick();
}, 1L, 1L);
}
private static int getMobMaxHard(EntityType entype) {
String location = "limiter.mobs.hard-limit." + entype.toString().toLowerCase();
if (Main.config.contains(location)) {
return Main.config.getInt(location);
}
return -1;
}
private static int getMobMaxSoft(EntityType entype) {
String location = "limiter.mobs.soft-limit." + entype.toString().toLowerCase();
if (Main.config.contains(location)) {
return Main.config.getInt(location);
}
return -1;
}
private static int getMobMaxSoft(Entity ent) {
return getMobMaxSoft(ent.getType());
}
private static int getTileMax(Class<?> cls) {
String location = "limiter.tiles.per-limit." + cls.getSimpleName().toLowerCase();
if (Main.config.contains(location)) {
return Main.config.getInt(location);
}
return -1;
}
private static int getTileMax(Block b) {
return getTileMax(b.getState().getClass());
}
private static int getMobCount(Chunk chk, EntityType entype) {
int ents = 0;
if (!entcache.isCached(chk)) {
entcache.putCached(chk, chk.getEntities());
}
for (Entity ent : entcache.getCached(chk)) {
if (ent == null) {
continue;
}
if (ent.getType() != entype) {
continue;
}
ents++;
}
return ents;
}
private static int getMobCount(Chunk chk) {
return chk.getEntities().length;
}
private static int getTileCount(Chunk chk, Class<?> type) {
int tls = 0;
if (!tilecache.isCached(chk)) {
tilecache.putCached(chk, chk.getTileEntities());
}
for (BlockState tle : tilecache.getCached(chk)) {
if (tle == null) {
continue;
}
if (!tle.getClass().equals(type)) {
continue;
}
tls++;
}
return tls;
}
private static int getTileCount(Chunk chk) {
return chk.getTileEntities().length;
}
// VERIFIERS (CODE QUALITY IMPROVERS)
private static boolean isDeniedMob(Entity ent) {
EntityType etype = ent.getType();
// Fix issues with destroying player objects.
if (etype == EntityType.PLAYER) {
return false;
}
Chunk chk = ent.getLocation().getChunk();
int current = getMobCount(chk, etype);
int maximum = getMobMaxSoft(ent);
if (maximum < 0) {
current = getMobCount(chk);
maximum = moblimit;
}
if (maximum < 0) {
return false;
}
if (current < maximum) {
return false;
}
return true;
}
private static boolean isDeniedTile(Block b) {
Chunk chk = b.getLocation().getChunk();
Class<?> type = b.getState().getClass();
String typename = type.getSimpleName().toLowerCase();
Main.sendDebug("isDeniedTile: " + typename, 1);
if (typename.equals("craftblockstate")) {
return false;
}
int current = getTileCount(chk, type);
int maximum = getTileMax(b);
if (maximum < 0) {
current = getTileCount(chk);
maximum = tilelimit;
}
if (maximum < 0) {
return false;
}
if (current < maximum) {
return false;
}
return true;
}
@EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true)
public void onVehicleSpawn(VehicleCreateEvent e) {
Vehicle ent = e.getVehicle();
// 1.8 doesn't support cancel. Fuk
if (isDeniedMob(ent)) {
ent.remove();
}
}
@EventHandler(priority = EventPriority.LOWEST)
public void onSpawn(EntitySpawnEvent e) {
if (e.isCancelled()) {
return;
}
Entity ent = e.getEntity();
e.setCancelled(isDeniedMob(ent));
}
@EventHandler(priority = EventPriority.LOWEST)
public void onPlace(BlockPlaceEvent e) {
if (e.isCancelled()) {
return;
}
Block b = e.getBlock();
e.setCancelled(isDeniedTile(b));
}
}

128
src/cx/sfy/LagAssist/chunks/ChkStats.java

@ -0,0 +1,128 @@
package cx.sfy.LagAssist.chunks;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.bukkit.Chunk;
import org.bukkit.block.BlockState;
import org.bukkit.entity.Entity;
import cx.sfy.LagAssist.utils.Chat;
import net.md_5.bungee.api.chat.TextComponent;
public class ChkStats implements Comparable<ChkStats> {
private int score = 0;
private int coords[] = new int[2];
private BlockState[] tiles;
private Entity[] ents;
private String world;
private Map<String, Integer> amount = new HashMap<String, Integer>();
public ChkStats(Chunk ch, boolean genscores) {
tiles = ch.getTileEntities();
ents = ch.getEntities();
world = ch.getWorld().getName();
coords[0] = ch.getX();
coords[1] = ch.getZ();
if (genscores) {
genScores();
}
}
public void genScores() {
for (BlockState blkst : tiles) {
String m = blkst.getType().toString().toLowerCase();
if (ChkAnalyse.values.containsKey(m)) {
score += ChkAnalyse.values.get(m);
if (!amount.containsKey(m)) {
amount.put(m, 0);
}
amount.put(m, amount.get(m) + 1);
}
}
for (Entity ent : ents) {
String m = ent.getType().toString().toLowerCase();
if (ChkAnalyse.values.containsKey(m)) {
score += ChkAnalyse.values.get(m);
if (!amount.containsKey(m)) {
amount.put(m, 0);
}
amount.put(m, amount.get(m) + 1);
}
}
}
public int getScore() {
return score;
}
public int getX() {
return coords[0];
}
public int getZ() {
return coords[1];
}
public int[] getCoords() {
return coords;
}
public Entity[] getEnts() {
return ents;
}
public BlockState[] getTiles() {
return tiles;
}
public TextComponent genMobCount(String s, String click) {
Stream<Map.Entry<String, Integer>> sorted = amount.entrySet().stream()
.sorted(Collections.reverseOrder(Map.Entry.comparingByValue()));
Map<String, Integer> tops = sorted.limit(ChkAnalyse.ammoshow)
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (e1, e2) -> e1, LinkedHashMap::new));
String regionfile = "r." + String.valueOf(coords[0] >> 5) + "." + String.valueOf(coords[1] >> 5) + ".mca";
String empt = "\n§c✸ §fClick to teleport!\n\n§fChunk Information:\n §c✸ §fWorld:§e "
+ Chat.capitalize(world.toLowerCase()) + "\n §c✸ §fRegion File:§e " + regionfile
+ "\n\n§fMost often appearances:";
for (String stg : tops.keySet()) {
empt = empt + "\n" + " §c✸ §f" + Chat.capitalize(stg.replace('_', ' ')) + ": §e"
+ String.valueOf(tops.get(stg));
}
empt = empt + "\n";
return Chat.genHoverAndRunCommandTextComponent(s, empt, click);
}
public TextComponent genText() {
String name = " §c✸ §fChunk §c(" + String.valueOf(coords[0]) + " " + String.valueOf(coords[1])
+ ")§f Score: §e" + String.valueOf(score);
String cmd = "lagassist tpchunk " + world + " " + String.valueOf(coords[0]) + " " + String.valueOf(coords[1]);
return genMobCount(name, cmd);
}
@Override
public int compareTo(ChkStats from) {
int compareQuantity = from.getScore();
return compareQuantity - score;
}
}

204
src/cx/sfy/LagAssist/chunks/ChunkGenerator.java

@ -0,0 +1,204 @@
package cx.sfy.LagAssist.chunks;
import java.util.ArrayList;
import java.util.List;
import org.bukkit.Bukkit;
import org.bukkit.Chunk;
import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.WorldBorder;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.bukkit.scheduler.BukkitTask;
import cx.sfy.LagAssist.Main;
import cx.sfy.LagAssist.packets.Reflection;
import cx.sfy.LagAssist.utils.Chat;
import cx.sfy.LagAssist.utils.MathUtils;
import cx.sfy.LagAssist.utils.VersionMgr;
public class ChunkGenerator {
private static Object chunkProvider;
private static World world;
private static BukkitTask gentask;
// WORLDBORDER VALUES
private static int maxx;
private static int maxz;
private static int minx;
private static int minz;
// WORLDBORDER VALUES END
private static int currenti;
public static void pregenWorld(CommandSender s, String[] args) {
if (!(s instanceof Player)) {
s.sendMessage(Main.PREFIX + "You need to execute this command as a player");
return;
}
if (args.length != 2) {
s.sendMessage(Main.PREFIX + "Correct usage: §c/lagassist pregench [Max-Millis-Per-Tick]");
return;
}
if (!MathUtils.isInt(args[1])) {
s.sendMessage(Main.PREFIX + "Please input a correct ammount of milliseconds.");
return;
}
if (gentask != null) {
s.sendMessage(
Main.PREFIX + "The world is already pregenerating. Please wait for it to finish or cancel it.");
return;
}
int millis = Integer.valueOf(args[1]);
Player p = (Player) s;
World w = p.getWorld();
if (w.getWorldBorder().getSize() > 50000) {
s.sendMessage(Main.PREFIX + "The max worldborder size is 50k.");
return;
}
pregenWorld(w, millis);
}
public static void stopGen(CommandSender s) {
if (gentask == null) {
s.sendMessage(Main.PREFIX + "There is no active world pregeneration.");
return;
}
gentask.cancel();
gentask = null;
s.sendMessage(Main.PREFIX + "Pregeneration task cancelled.");
}
private static void pregenWorld(World w, int millis) {
// PREPARING ENVIRONMENT
if (!VersionMgr.isNewMaterials()) {
chunkProvider = Reflection.getChunkProvider(Reflection.getWorldServer(Reflection.getCraftWorld(w)));
}
world = w;
// PREPARING WORLDBORDER CHECK
WorldBorder wb = w.getWorldBorder();
Location center = wb.getCenter();
double radius = wb.getSize() / 2;
maxx = (int) ((center.getX() + radius) / 16);
maxz = (int) ((center.getZ() + radius) / 16);
minx = (int) ((center.getX() - radius) / 16);
minz = (int) ((center.getZ() - radius) / 16);
Chunk spawn = world.getSpawnLocation().getChunk();
int xfin = spawn.getX();
int zfin = spawn.getZ();
// Prepare list of chunks to pregenerate. It will further be used to pregenerate
// the world.
Bukkit.getScheduler().runTaskAsynchronously(Main.p, new Runnable() {
@Override
public void run() {
List<int[]> chunks = new ArrayList<int[]>();
int x = xfin;
int z = zfin;
int i = 1;
while (isInside(x, z)) {
for (int temp = x + 1; temp <= x + i; temp++) {
chunks.add(new int[] { x, z });
}
x += i;
for (int temp = z - 1; temp >= z - i; temp--) {
chunks.add(new int[] { x, temp });
}
z -= i;
i++;
for (int temp = x - 1; temp >= x - i; temp--) {
chunks.add(new int[] { temp, z });
}
x -= i;
for (int temp = z + 1; temp <= z + i; temp++) {
chunks.add(new int[] { x, temp });
}
z += i;
i++;
}
startGen(chunks, millis);
}
});
}
private static void startGen(List<int[]> chunks, int millis) {
currenti = 0;
gentask = Bukkit.getScheduler().runTaskTimer(Main.p, new Runnable() {
@Override
public void run() {
long time = System.currentTimeMillis();
for (int i = currenti; i < chunks.size(); i++) {
pregenChunk(chunks.get(i));
if (i % 300 == 0 && i != 0) {
int percent = (int) ((double) i / chunks.size() * 100);
Bukkit.getLogger()
.info("§e[§a✪§e] §fThe pregeneration of the §c"
+ Chat.capitalize(world.getName()) + " §fworld is at §a" + percent
+ "% completion.");
}
if (i % 20 == 0 && i != 0) {
long curr = System.currentTimeMillis();
if (time + millis < curr) {
currenti = i;
return;
}
}
}
gentask.cancel();
gentask = null;
Bukkit.getLogger()
.info("§e[§a✪§e] §fThe pregeneration of the §c" + Chat.capitalize(world.getName())
+ " §fworld is finished. Thank you for your patience.");
}
}, 1L, 1L);
}
private static void pregenChunk(int[] cords) {
pregenChunk(cords[0], cords[1]);
}
private static void pregenChunk(int x, int z) {
if (VersionMgr.isChunkGenerated(world, chunkProvider, x, z)) {
return;
}
VersionMgr.loadChunk(world, x, z);
}
private static boolean isInside(int x, int z) {
if (x < minx || x > maxx) {
return false;
}
if (z < minz || z > maxz) {
return false;
}
return true;
}
}

101
src/cx/sfy/LagAssist/chunks/DynViewer.java

@ -0,0 +1,101 @@
package cx.sfy.LagAssist.chunks;
import org.bukkit.Bukkit;
import org.bukkit.World;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerJoinEvent;
import cx.sfy.LagAssist.Main;
import cx.sfy.LagAssist.utils.PaperOnly;
import cx.sfy.LagAssist.utils.VersionMgr;
import cx.sfy.LagAssist.utils.WorldMgr;
public class DynViewer implements Listener {
private static int maxChunks;
private static int maxView;
private static int currChunks = 0;
public static void Enabler(boolean reload) {
boolean enabled = Main.config.getBoolean("chunk-manager.enabled");
if (!enabled) {
return;
}
if (!Main.paper) {
Bukkit.getLogger().info(" §e[§a✖§e] §fChunkManager - No PaperSpigot found");
return;
}
maxChunks = Main.config.getInt("chunk-manager.max-chunks");
maxView = Main.config.getInt("chunk-manager.max-view");
if (!reload) {
Main.p.getServer().getPluginManager().registerEvents(new DynViewer(), Main.p);
runTask();
}
Bukkit.getLogger().info(" §e[§a✔§e] §fChunkManager.");
}
private static void runTask() {
Bukkit.getScheduler().runTaskTimer(Main.p, () -> setViews(), 0, 600);
}
public static void setViews() {
Main.sendDebug("Attempting to set dynamic view distance...", 1);
// Get a value that is at least the minimum view distance and at max the spigot
// view distance.
int pl = Bukkit.getOnlinePlayers().size();
if (pl == 0) {
return;
}
int vd = (int) Math.sqrt(maxChunks / pl / 4);
int newchunks = Math.max(Math.min(maxView, vd), Bukkit.getViewDistance());
if (currChunks == newchunks) {
return;
}
currChunks = newchunks;
for (World w : Bukkit.getWorlds()) {
if (WorldMgr.blacklist.contains(w.getName())) {
continue;
}
PaperOnly.setViewDistance(w, currChunks);
}
}
@EventHandler(priority = EventPriority.LOWEST)
private void onJoin(PlayerJoinEvent e) {
Player p = e.getPlayer();
Main.sendDebug("Join detected for " + p.getName(), 1);
if (VersionMgr.isNewMaterials()) {
Main.sendDebug("Is new materials in dynviewer for " + p.getName() + ". Returning... ", 1);
return;
}
// TODO: FIX Dynamic view
Bukkit.getScheduler().runTaskLater(Main.p, () -> PaperOnly.setViewDistance(p, currChunks), 25);
}
}

86
src/cx/sfy/LagAssist/client/ClientMain.java

@ -0,0 +1,86 @@
package cx.sfy.LagAssist.client;
import java.io.File;
import java.util.List;
import org.bukkit.Bukkit;
import org.bukkit.command.PluginCommand;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.entity.Entity;
import org.bukkit.event.Listener;
import org.bukkit.inventory.ItemStack;
import cx.sfy.LagAssist.Main;
import cx.sfy.LagAssist.cmd.ClientCmdListener;
import cx.sfy.LagAssist.gui.DataGUI;
import cx.sfy.LagAssist.packets.Reflection;
import cx.sfy.LagAssist.utils.Others;
import net.md_5.bungee.api.ChatColor;
public class ClientMain implements Listener {
private static File clf = new File(Main.p.getDataFolder(), "client.yml");
public static YamlConfiguration clcnf = new YamlConfiguration();
private static String command;
public static boolean enabled;
public static String prefix;
public static String perm;
public static String guiname;
public static boolean[] defaults = new boolean[4];
protected static Entity last;
public static void Enabler() {
clcnf = Others.getConfig(clf, 4);
enabled = clcnf.getBoolean("settings.enabled");
command = clcnf.getString("settings.command");
perm = clcnf.getString("settings.permission");
// Color Translated Special Messages
prefix = ChatColor.translateAlternateColorCodes('&', clcnf.getString("settings.prefix"));
guiname = ChatColor.translateAlternateColorCodes('&', clcnf.getString("settings.gui-name"));
defaults[0] = clcnf.getBoolean("defaults.tnt");
defaults[1] = clcnf.getBoolean("defaults.sand");
defaults[2] = clcnf.getBoolean("defaults.particles");
defaults[3] = clcnf.getBoolean("defaults.pistons");
}
public static void configureIcon(ItemStack s, String type) {
String loc = "language." + type;
String raw = clcnf.getString(loc + ".name");
List<String> rawlore = clcnf.getStringList(loc + ".lore");
DataGUI.customizeItem(s, raw, false, rawlore);
}
public static void secondaryEnabler(boolean reload) {
if (!enabled) {
return;
}
if (reload) {
return;
}
Main.p.getServer().getPluginManager().registerEvents(new ClientMain(), Main.p);
PluginCommand cmd = Reflection.getCommand(command, Main.p);
if (Reflection.getCommandMap().getCommand(ClientMain.command) != null) {
Bukkit.getLogger().info(" §e[§a✖§e] §fClient Optimizer - The command is already registered");
return;
}
Reflection.getCommandMap().register(Main.p.getDescription().getName(), cmd);
Main.p.getCommand(ClientMain.command).setExecutor(new ClientCmdListener());
Bukkit.getLogger().info(" §e[§a✔§e] §fClient Optimizer.");
}
}

85
src/cx/sfy/LagAssist/client/ClientPacket.java

@ -0,0 +1,85 @@
package cx.sfy.LagAssist.client;
import java.util.UUID;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;
import cx.sfy.LagAssist.gui.ClientGUI;
import cx.sfy.LagAssist.gui.ClientGUI.ToggleState;
import cx.sfy.LagAssist.packets.Reflection;
import cx.sfy.LagAssist.utils.VersionMgr;
import cx.sfy.LagAssist.utils.WorldMgr;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelPromise;
public class ClientPacket {
public static boolean hidePacket(Player p, ChannelHandlerContext ctx, Object msg, ChannelPromise promise) {
if (!ClientMain.enabled) {
return false;
}
if (WorldMgr.isBlacklisted(p.getWorld())) {
return false;
}
try {
String name = msg.getClass().getSimpleName().toLowerCase();
if (name.equals("packetplayoutspawnentity")
&& (ClientGUI.isOn(ToggleState.TNT, p) || ClientGUI.isOn(ToggleState.SAND, p))) {
Entity ent;
if (VersionMgr.isV1_8()) {
int x = ((int) Reflection.getFieldValue(msg, "b")) / 32;
int y = ((int) Reflection.getFieldValue(msg, "c")) / 32;
int z = ((int) Reflection.getFieldValue(msg, "d")) / 32;
Location loc = new Location(p.getWorld(), x, y, z);
ent = Reflection.getEntity(loc);
} else if (VersionMgr.isV1_13() || VersionMgr.isV1_14()) {
UUID u = (UUID) Reflection.getFieldValue(msg, "b");
ent = Bukkit.getEntity(u);
} else {
double x = ((double) Reflection.getFieldValue(msg, "c"));
double y = ((double) Reflection.getFieldValue(msg, "d"));
double z = ((double) Reflection.getFieldValue(msg, "e"));
Location loc = new Location(p.getWorld(), x, y, z);
ent = Reflection.getEntity(loc);
}
if (ent == null) {
return false;
}
String type = ent.getType().toString();
if (type == "PRIMED_TNT") {
return ClientGUI.isOn(ToggleState.TNT, p);
} else if (type == "FALLING_BLOCK") {
return ClientGUI.isOn(ToggleState.SAND, p);
}
} else if (name.equals("packetplayoutworldparticles")) {
return ClientGUI.isOn(ToggleState.PARTICLES, p);
} else if (name.equals("packetplayoutblockaction")) {
Object block = Reflection.getFieldValue(msg, "d");
String type = block.getClass().getSimpleName().toLowerCase();
if (type.equals("blockpiston")) {
return ClientGUI.isOn(ToggleState.PISTONS, p);
}
} else if (name.equals("packetplayoutentitystatus")) {
// int ent = (int) Reflection.getFieldValue(msg, "a");
byte status = (byte) Reflection.getFieldValue(msg, "b");
if (status == 3) {
return true;
}
}
return false;
} catch (Exception e) {
e.printStackTrace();
}
return false;
}
}

34
src/cx/sfy/LagAssist/cmd/ClientCmdListener.java

@ -0,0 +1,34 @@
package cx.sfy.LagAssist.cmd;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import cx.sfy.LagAssist.client.ClientMain;
import cx.sfy.LagAssist.gui.ClientGUI;
public class ClientCmdListener implements CommandExecutor {
@Override
public boolean onCommand(CommandSender s, Command cmd, String label, String[] args) {
if (!s.hasPermission(ClientMain.perm)) {
s.sendMessage(ClientMain.prefix + "You are not allowed to use the control panel!");
return true;
}
if (!(s instanceof Player)) {
s.sendMessage(ClientMain.prefix + "You cannot use the client optimizer from the console!");
return true;
}
Player p = (Player) s;
s.sendMessage(ClientMain.prefix + "Opening your ClientOptimizer. Please Wait.");
ClientGUI.show(p);
return false;
}
}

294
src/cx/sfy/LagAssist/cmd/CommandListener.java

@ -0,0 +1,294 @@
package cx.sfy.LagAssist.cmd;
import java.util.Arrays;
import java.util.Map.Entry;
import java.util.UUID;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import cx.sfy.LagAssist.Main;
import cx.sfy.LagAssist.MonTools;
import cx.sfy.LagAssist.MsrExec;
import cx.sfy.LagAssist.chunks.ChunkGenerator;
import cx.sfy.LagAssist.gui.AdminGUI;
import cx.sfy.LagAssist.minebench.Approximate;
import cx.sfy.LagAssist.minebench.SpeedTest;
import cx.sfy.LagAssist.packets.Reflection;
import cx.sfy.LagAssist.updater.SmartUpdater;
import cx.sfy.LagAssist.utils.Chat;
import cx.sfy.LagAssist.utils.MathUtils;
public class CommandListener implements CommandExecutor {
@Override
public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) {
if ((cmd.getName().equalsIgnoreCase("lagassist"))) {
if (!sender.hasPermission("lagassist.use")) {
if (args.length == 1) {
sender.sendMessage(Main.PREFIX + "Plugin bought by " + Main.USER);
} else {
sender.sendMessage(Main.PREFIX + "You don't have permission to run this command!");
}
return true;
}
if (args.length == 0) {
if (sender instanceof Player) {
Player p = (Player) sender;
AdminGUI.show(p);
} else {
sendHelp(sender);
}
} else if (args.length <= 2) {
String arg = args[0];
if (arg.equalsIgnoreCase("mobculler")) {
} else if (arg.equalsIgnoreCase("version")) {
MsrExec.showVersion(sender);
} else if (arg.equalsIgnoreCase("redstoneculler")) {
MsrExec.cullRedstone(sender);
} else if (arg.equalsIgnoreCase("togglespawning")) {
MsrExec.toggleMobs(sender);
} else if (arg.equalsIgnoreCase("togglephysics")) {
MsrExec.togglePhysics(sender);
} else if (arg.equalsIgnoreCase("optimizespawners")) {
MsrExec.toggleSpawnerOptimization(sender);
} else if (arg.equalsIgnoreCase("getmap")) {
MsrExec.giveMap(sender);
} else if (arg.equalsIgnoreCase("benchmark")) {
Approximate.showBenchmark(sender);
} else if (arg.equalsIgnoreCase("chunkanalyse") && sender.hasPermission("lagassist.chunkanalyse")) {
MsrExec.analyseChunks(sender, args);
} else if (arg.equalsIgnoreCase("pregench") && sender.hasPermission("lagassist.generatechunks")) {
ChunkGenerator.pregenWorld(sender, args);
} else if (arg.equalsIgnoreCase("stopgen") && sender.hasPermission("lagassist.generatechunks")) {
ChunkGenerator.stopGen(sender);
} else if (arg.equalsIgnoreCase("tpchunk")) {
sender.sendMessage(Main.PREFIX + "Correct usage: §c/lagassist tpchunk [WORLD] [X] [Z]");
} else if (arg.equalsIgnoreCase("reload") && sender.hasPermission("lagassist.reload")) {
Main.ReloadPlugin(sender);
} else if (arg.equalsIgnoreCase("changelog")) {
SmartUpdater.showChangelog(sender);
} else if (arg.equalsIgnoreCase("statsbar")) {
if (sender instanceof Player) {
UUID p = ((Player) sender).getUniqueId();
if (MonTools.actionmon.contains(p)) {
MonTools.actionmon.remove(p);
sender.sendMessage(Main.PREFIX + "StatsBar §cDisabled.");
Reflection.sendAction(Bukkit.getPlayer(p), "");
} else {
MonTools.actionmon.add(p);
sender.sendMessage(Main.PREFIX + "StatsBar §aEnabled.");
}
} else {
sender.sendMessage(Main.PREFIX + "You cannot see a statsbar from the console.");
}
} else if (arg.equalsIgnoreCase("ping")) {
SpeedTest.pingBenchmark(sender);
} else if (arg.equalsIgnoreCase("threadanalyse")) {
for (Entry<Thread, StackTraceElement[]> entry : Thread.getAllStackTraces().entrySet()) {
Main.p.getLogger().info(Arrays.stream(entry.getValue()).skip(0).map(StackTraceElement::toString)
.reduce((s1, s2) -> s1 + "\n" + s2).orElse("NOT FOUND"));
}
} else if (arg.equalsIgnoreCase("debugmode")) {
Main.debug = Main.debug >= 2 ? 0 : Main.debug+1;
sender.sendMessage(Main.PREFIX + "Debug setting currently at: " + Main.debug);
} else {
sendHelp(sender);
}
} else if (args.length == 3) {
if (args[0].equalsIgnoreCase("chunkhopper")) {
MsrExec.giveChunkHopper(sender, args);
} else {
sendHelp(sender);
}
} else if (args.length == 4) {
if (args[0].equalsIgnoreCase("tpchunk") && sender.hasPermission("lagassist.chunkanalyse")) {
if (sender instanceof Player) {
Player p = (Player) sender;
World w = Bukkit.getWorld(args[1]);
if ((w != null) && MathUtils.isInt(args[2]) && MathUtils.isInt(args[3])) {
int x = Integer.parseInt(args[2]) * 16 + 8;
int z = Integer.parseInt(args[3]) * 16 + 8;
int y = w.getHighestBlockYAt(x, z) + 10;
p.teleport(new Location(w, x, y, z));
p.sendMessage(Main.PREFIX + "You have been teleported to the desired chunk.");
} else {
sender.sendMessage(Main.PREFIX + "Correct usage: §c/lagassist tpchunk [WORLD] [X] [Z]");
}
} else {
sender.sendMessage(Main.PREFIX + "You cannot tp to laggy chunks from console.");
}
} else {
sendHelp(sender);
}
} else {
sendHelp(sender);
}
}
return false;
}
private static void help18(CommandSender s) {
if (s instanceof Player) {
Player p = (Player) s;
p.spigot().sendMessage(Chat.genHoverAndSuggestTextComponent(
" §c✸ §fLagAssist MobCuller §c- §eClear the configured mobs",
"§fClears the mobs that you have set to remove\nin the configuration file.\n\n§c(!) It won't remove named mobs.",
"LagAssist MobCuller"));
p.spigot().sendMessage(Chat.genHoverAndSuggestTextComponent(
" §c✸ §fLagAssist RedstoneCuller §c- §eDisables Redstone",
"§fDisables all the redstone that has been triggered in 30 ticks.\n\nIt can be used to temporarily disable lag-machines\nor to even break them, if you configure it to do so.\nIt also breaks lag-machines that don't use redstone wire!",
"LagAssist RedstoneCuller"));
p.spigot().sendMessage(Chat.genHoverAndSuggestTextComponent(
" §c✸ §fLagAssist ToggleSpawning §c- §eToggles mob spawning",
"§fDisables all mob-spawning once it is toggled on.\n\nIt can be used when many players are online,\nand your server is not keeping up to all the mobs.",
"LagAssist ToggleSpawning"));
p.spigot().sendMessage(Chat.genHoverAndSuggestTextComponent(
" §c✸ §fLagAssist TogglePhyisics §c- §eToggles physics events.",
"§fIt disables all physics events that are enabled\nin the config.\n\nIt can be used to drastically reduce lag on non-minigame servers.",
"LagAssist TogglePhysics"));
p.spigot().sendMessage(Chat.genHoverAndSuggestTextComponent(
" §c✸ §fLagAssist ChunkAnalyse §c- §eFind the laggiest chunks",
"§fOutput the first X laggiest chunks, based on a score table.\n\nIt can be fully configured, from how many chunks to show to\nhow much score each entity or tile-entity has.",
"LagAssist ChunkAnalyse"));
p.spigot().sendMessage(Chat.genHoverAndSuggestTextComponent(
" §c✸ §fLagAssist GetMap §c- §eGet a graph of server TPS",
"§fGives you a map that can help find lagspikes.\n§c(!) It exaggerates lag so it is more visible.\n§c(!) do not get alarmed.\n\n§fYou can use it along a cronometer\n§fto find how often the lagspikes happen. Then, you can\nuse your timings report to find a plugin that runs\nTasks at that interval.",
"LagAssist GetMap"));
p.spigot().sendMessage(Chat.genHoverAndSuggestTextComponent(
" §c✸ §fLagAssist Benchmark §c- §eGenerates a performance report",
"§fIt can be used to approximate how many players your server\ncan run without lagging, based on collected information.\nIt can also be used to find if hosts are overselling, and how much.",
"LagAssist Benchmark"));
p.spigot().sendMessage(Chat.genHoverAndSuggestTextComponent(
" §c✸ §fLagAssist StatsBar §c- §eGet a simple action-bar TPS Meter",
"§fShows a simple action-bar showing data that\nis related to lag.\n\nIf you have rare lagspikes, this can help\npinpoint when they happen without having\nto stop doing something else.",
"LagAssist StatsBar"));
p.spigot().sendMessage(Chat.genHoverAndSuggestTextComponent(
" §c✸ §fLagAssist TpChunk §c- §eTeleport to a chunk",
"§f/LagAssist TpChunk [World] [X] [Z].\n\n§c(!) The X and Z variables are not F3 coords.\n\n",
"LagAssist TpChunk"));
p.spigot().sendMessage(Chat.genHoverAndSuggestTextComponent(
" §c✸ §fLagAssist PreGenCH §c- §ePre-Generate chunks",
"§f/LagAssist PreGenCH [Radius] [Delay] [Amount]\n\n§c(!) This doesn't have any failsafes.\n§c(!) If you don't know how to use it, ask me first.",
"LagAssist PreGenCH"));
p.spigot()
.sendMessage(Chat.genHoverAndSuggestTextComponent(
" §c✸ §fLagAssist ChunkHopper §c- §eGet Chunk Hoppers",
"§f/LagAssist chunkhopper [Player] [Amount]\n\n§fTGive a player a chunk hopper.",
"LagAssist ChunkHopper"));
p.spigot().sendMessage(Chat.genHoverAndSuggestTextComponent(
" §c✸ §fLagAssist Changelog §c- §eCheck Version info.",
"§fThis tool will show you the changelog in an update.\nIt is really useful if you haven't checked the changelog in the updates page already.",
"LagAssist Changelog"));
p.spigot().sendMessage(Chat.genHoverAndSuggestTextComponent(
" §c✸ §fLagAssist Version §c- §eShows you the plugin version.",
"§fThis should be used when reporting bugs.\nYou should allways update first when having a bug,\nas I fix bugs quite fast once i find them.",
"LagAssist Version"));
p.spigot().sendMessage(
Chat.genHoverAndSuggestTextComponent(" §c✸ §fLagAssist Reload §c- §eReloads the config",
"§fUse it when you changed the config", "LagAssist Reload"));
} else {
s.sendMessage(" ✸ LagAssist MobCuller - Clear the configured mobs");
s.sendMessage(" ✸ LagAssist RedstoneCuller - Disables Redstone");
s.sendMessage(" ✸ LagAssist ToggleSpawning - Toggles mob spawning");
s.sendMessage(" ✸ LagAssist TogglePhyisics - Toggles physics events.");
s.sendMessage(" ✸ LagAssist ChunkAnalyse - Find the laggiest chunks");
s.sendMessage(" ✸ LagAssist GetMap - Get a graph of server TPS");
s.sendMessage(" ✸ LagAssist Benchmark - Generates a performance report");
s.sendMessage(" ✸ LagAssist Ping - Shows a ping benchmark");
s.sendMessage(" ✸ LagAssist StatsBar - Get a simple action-bar TPS Meter");
s.sendMessage(" ✸ LagAssist TpChunk - Teleport to a chunk");
s.sendMessage(" ✸ LagAssist PreGenCH - Pre-Generate chunks");
s.sendMessage(" ✸ LagAssist ChunkHopper - Get Chunk Hoppers");
s.sendMessage(" ✸ LagAssist Version - Shows you the plugin version.");
s.sendMessage(" ✸ LagAssist Reload - Reloads the config");
}
}
private static void helpnew(CommandSender p) {
p.spigot().sendMessage(Chat.genHoverAndSuggestTextComponent(
" §c✸ §fLagAssist MobCuller §c- §eClear the configured mobs",
"§fClears the mobs that you have set to remove\nin the configuration file.\n\n§c(!) It won't remove named mobs.",
"LagAssist MobCuller"));
p.spigot().sendMessage(Chat.genHoverAndSuggestTextComponent(
" §c✸ §fLagAssist RedstoneCuller §c- §eDisables Redstone",
"§fDisables all the redstone that has been triggered in 30 ticks.\n\nIt can be used to temporarily disable lag-machines\nor to even break them, if you configure it to do so.\nIt also breaks lag-machines that don't use redstone wire!",
"LagAssist RedstoneCuller"));
p.spigot().sendMessage(Chat.genHoverAndSuggestTextComponent(
" §c✸ §fLagAssist ToggleSpawning §c- §eToggles mob spawning",
"§fDisables all mob-spawning once it is toggled on.\n\nIt can be used when many players are online,\nand your server is not keeping up to all the mobs.",
"LagAssist ToggleSpawning"));
p.spigot().sendMessage(Chat.genHoverAndSuggestTextComponent(
" §c✸ §fLagAssist TogglePhyisics §c- §eToggles physics events.",
"§fIt disables all physics events that are enabled\nin the config.\n\nIt can be used to drastically reduce lag on non-minigame servers.",
"LagAssist TogglePhysics"));
p.spigot().sendMessage(Chat.genHoverAndSuggestTextComponent(
" §c✸ §fLagAssist ChunkAnalyse §c- §eFind the laggiest chunks",
"§fOutput the first X laggiest chunks, based on a score table.\n\nIt can be fully configured, from how many chunks to show to\nhow much score each entity or tile-entity has.",
"LagAssist ChunkAnalyse"));
p.spigot().sendMessage(Chat.genHoverAndSuggestTextComponent(
" §c✸ §fLagAssist GetMap §c- §eGet a graph of server TPS",
"§fGives you a map that can help find lagspikes.\n§c(!) It exaggerates lag so it is more visible.\n§c(!) do not get alarmed.\n\n§fYou can use it along a cronometer\n§fto find how often the lagspikes happen. Then, you can\nuse your timings report to find a plugin that runs\nTasks at that interval.",
"LagAssist GetMap"));
p.spigot().sendMessage(Chat.genHoverAndSuggestTextComponent(
" §c✸ §fLagAssist Benchmark §c- §eGenerates a performance report",
"§fIt can be used to approximate how many players your server\ncan run without lagging, based on collected information.\nIt can also be used to find if hosts are overselling, and how much.",
"LagAssist Benchmark"));
p.spigot().sendMessage(Chat.genHoverAndSuggestTextComponent(
" §c✸ §fLagAssist Ping §c- §eShows a ping benchmark",
"§fIt can be used to find the best location to host your server\nbased on what the player ping is.\nThe recommended ping value is under 90ms.",
"LagAssist Ping"));
p.spigot().sendMessage(Chat.genHoverAndSuggestTextComponent(
" §c✸ §fLagAssist StatsBar §c- §eGet a simple action-bar TPS Meter",
"§fShows a simple action-bar showing data that\nis related to lag.\n\nIf you have rare lagspikes, this can help\npinpoint when they happen without having\nto stop doing something else.",
"LagAssist StatsBar"));
p.spigot()
.sendMessage(Chat.genHoverAndSuggestTextComponent(
" §c✸ §fLagAssist TpChunk §c- §eTeleport to a chunk",
"§f/LagAssist TpChunk [World] [X] [Z].\n\n§c(!) The X and Z variables are not F3 coords.\n\n",
"LagAssist TpChunk"));
p.spigot().sendMessage(Chat.genHoverAndSuggestTextComponent(
" §c✸ §fLagAssist PreGenCH §c- §ePre-Generate chunks",
"§f/LagAssist PreGenCH [Radius] [Delay] [Amount]\n\n§c(!) This doesn't have any failsafes.\n§c(!) If you don't know how to use it, ask me first.",
"LagAssist PreGenCH"));
p.spigot().sendMessage(Chat.genHoverAndSuggestTextComponent(
" §c✸ §fLagAssist Changelog §c- §eCheck Version info.",
"§fThis tool will show you the changelog in an update.\nIt is really useful if you haven't checked the changelog in the updates page already.",
"LagAssist Changelog"));
p.spigot().sendMessage(Chat.genHoverAndSuggestTextComponent(
" §c✸ §fLagAssist Version §c- §eShows you the plugin version.",
"§fThis should be used when reporting bugs.\nYou should allways update first when having a bug,\nas I fix bugs quite fast once i find them.",
"LagAssist Version"));
p.spigot().sendMessage(
Chat.genHoverAndSuggestTextComponent(" §c✸ §fLagAssist Reload §c- §eReloads the config",
"§fUse it when you changed the config", "LagAssist Reload"));
}
private static void sendHelp(CommandSender p) {
boolean oldvers = Bukkit.getVersion().contains("1.8");
p.sendMessage("§c§l⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛§f§l LAG ASSIST §c§l⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛");
p.sendMessage("");
if (oldvers) {
help18(p);
} else {
helpnew(p);
}
p.sendMessage("");
p.sendMessage("§c§l⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛");
}
}

49
src/cx/sfy/LagAssist/cmd/CommandTabListener.java

@ -0,0 +1,49 @@
package cx.sfy.LagAssist.cmd;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.bukkit.Bukkit;
import org.bukkit.World;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.command.TabCompleter;
import org.bukkit.util.StringUtil;
public class CommandTabListener implements TabCompleter {
private static List<String> argl1 = Arrays.asList("mobculler", "redstoneculler", "togglespawning", "benchmark",
"togglephysics", "chunkanalyse", "ping", "getmap", "statsbar", "tpchunk", "pregench", "stopgen", "version",
"reload", "optimizespawners", "chunkhopper");
@Override
public List<String> onTabComplete(CommandSender sender, Command cmd, String alias, String[] args) {
List<String> response = new ArrayList<String>();
if (cmd.getName().equalsIgnoreCase("lagassist")) {
if (args.length == 1) {
StringUtil.copyPartialMatches(args[0], argl1, response);
return response;
} else if (args.length == 2) {
if (args[0].equalsIgnoreCase("pregench")) {
response.add("10");
response.add("20");
response.add("35");
return response;
} else if (args[0].equalsIgnoreCase("tpchunk")) {
for (World w : Bukkit.getWorlds()) {
response.add(w.getName());
}
return response;
} else if (args[0].equalsIgnoreCase("chunkanalyse")) {
response.add("this");
}
}
}
return response;
}
}

78
src/cx/sfy/LagAssist/cmd/StatsAnalyse.java

@ -0,0 +1,78 @@
package cx.sfy.LagAssist.cmd;
import java.text.DecimalFormat;
import org.bukkit.Bukkit;
import org.bukkit.World;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerCommandPreprocessEvent;
import cx.sfy.LagAssist.Main;
import cx.sfy.LagAssist.Monitor;
import cx.sfy.LagAssist.minebench.SpecsGetter;
import net.md_5.bungee.api.chat.ComponentBuilder;
import net.md_5.bungee.api.chat.HoverEvent;
import net.md_5.bungee.api.chat.TextComponent;
public class StatsAnalyse implements Listener {
public static void Enabler(boolean reload) {
if (!reload) {
Main.p.getServer().getPluginManager().registerEvents(new StatsAnalyse(), Main.p);
}
Bukkit.getLogger().info(" §e[§a✔§e] §fStatsAnalyse.");
}
public static TextComponent genOverview() {
String msgstrg = Main.PREFIX + "Hover over this message for a lag overview.";
TextComponent msg = new TextComponent(msgstrg);
int ent = 0, chk = 0;
for (World w : Bukkit.getWorlds()) {
ent += w.getEntities().size();
chk += w.getLoadedChunks().length;
}
DecimalFormat df = new DecimalFormat("0.000");
int crs = SpecsGetter.threadCount();
double load = SpecsGetter.getSystemLoad();
String crstg = String.valueOf(crs);
if (crs == -1) {
crstg = "NOT AVAILABLE";
}
String loadstg = df.format(load);
if (load == -1) {
crstg = "NOT AVAILABLE";
}
String stats = "\n\n §c✸ §fExact TPS: §c" + df.format(Monitor.exactTPS) + "\n\n §c✸ §fEntities: §c"
+ String.valueOf(ent) + "\n §c✸ §fLoaded Chunks: §c" + String.valueOf(chk)
+ "\n\n §c✸ §fFree Memory: §c" + String.valueOf(Monitor.freeMEM()) + "MB"
+ "\n §c✸ §fCPU Cores: §c" + crstg + "\n §c✸ §fLoad Average: §c" + loadstg
+ "\n §c✸ §fDisk Space: §c" + String.valueOf((Main.p.getDataFolder().getUsableSpace() / 1073741824))
+ "GB\n";
msg.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new ComponentBuilder(stats).create()));
return msg;
}
@EventHandler(priority = EventPriority.HIGH)
public void onTpsCmd(PlayerCommandPreprocessEvent e) {
Player p = e.getPlayer();
if (!p.hasPermission("lagassist.use")) {
return;
}
String cmd = e.getMessage();
if (cmd.startsWith("/tps")) {
p.spigot().sendMessage(genOverview());
}
}
}

75
src/cx/sfy/LagAssist/economy/EconomyManager.java

@ -0,0 +1,75 @@
package cx.sfy.LagAssist.economy;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.OfflinePlayer;
import org.bukkit.entity.Player;
import org.bukkit.plugin.RegisteredServiceProvider;
import cx.sfy.LagAssist.Main;
import net.milkbowl.vault.economy.Economy;
public class EconomyManager {
public static Map<OfflinePlayer, Double> cache = new HashMap<OfflinePlayer, Double>();
public static Economy econ;
public static void Enabler(boolean reload) {
if (setupEconomy() && !reload) {
runPayTask();
}
Bukkit.getLogger().info(" §e[§a✔§e] §fEconomy manager");
}
private static boolean setupEconomy() {
if (Bukkit.getServer().getPluginManager().getPlugin("Vault") == null) {
return false;
}
RegisteredServiceProvider<Economy> rsp = Bukkit.getServer().getServicesManager().getRegistration(Economy.class);
if (rsp == null) {
return false;
}
econ = rsp.getProvider();
return econ != null;
}
public static void payPlayer(Player p, double amount) {
payPlayer(Bukkit.getOfflinePlayer(p.getUniqueId()), amount);
}
public static void payPlayer(OfflinePlayer p, double amount) {
cache.compute(p, (player, adder) -> (adder == null) ? amount : amount + adder);
}
private static final String MSGLOC = "hooks.vault.message";
public static void runPayTask() {
if (econ == null) {
return;
}
Bukkit.getScheduler().runTaskTimer(Main.p, () -> {
for (Entry<OfflinePlayer, Double> entr : cache.entrySet()) {
OfflinePlayer pl =entr.getKey();
double amount = entr.getValue();
String msg = Main.config.getString(MSGLOC, "");
if (pl.isOnline() && !msg.isEmpty()) {
pl.getPlayer().sendMessage(ChatColor.translateAlternateColorCodes('&', msg.replace("%amount%", String.format("%.2f", amount))));
}
econ.depositPlayer(pl, amount);
}
cache.clear();
}, 100, Main.config.getLong("hooks.vault.cache-duration"));
}
}

97
src/cx/sfy/LagAssist/gui/AdminGUI.java

@ -0,0 +1,97 @@
package cx.sfy.LagAssist.gui;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.Material;
import org.bukkit.entity.HumanEntity;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import cx.sfy.LagAssist.MsrExec;
import cx.sfy.LagAssist.chunks.ChkAnalyse;
import cx.sfy.LagAssist.minebench.Approximate;
import cx.sfy.LagAssist.minebench.SpeedTest;
public class AdminGUI implements Listener {
private static Inventory inv = Bukkit.createInventory(null, 54, "§0§lLagAssist Tools");
public static void Enabler() {
// Make Square borders
DataGUI.setBorders(inv);
// Add Category panes
inv.setItem(2, DataGUI.anp);
inv.setItem(4, DataGUI.optp);
inv.setItem(6, DataGUI.agp);
// Add Measures
inv.setItem(11, DataGUI.bnchie);
inv.setItem(20, DataGUI.lagmap);
inv.setItem(29, DataGUI.chkanalyse);
inv.setItem(38, DataGUI.ping);
inv.setItem(13, DataGUI.physics);
inv.setItem(22, DataGUI.mobspawning);
inv.setItem(31, DataGUI.spawners);
inv.setItem(15, DataGUI.rcull);
inv.setItem(24, DataGUI.mobcull);
}
public static void show(Player p) {
p.openInventory(inv);
}
@EventHandler
public void onInventoryClick(InventoryClickEvent e) {
HumanEntity hm = e.getWhoClicked();
if (!(hm instanceof Player)) {
return;
}
Player p = (Player) e.getWhoClicked();
ItemStack itm = e.getCurrentItem();
if (itm == null) {
return;
}
if (!ChatColor.stripColor(e.getView().getTitle()).equals("LagAssist Tools")) {
return;
}
e.setCancelled(true);
Material i = itm.getType();
if (i == DataGUI.bnchie.getType()) {
Approximate.showBenchmark(p);
} else if (i == DataGUI.lagmap.getType()) {
MsrExec.giveMap(p);
} else if (i == DataGUI.chkanalyse.getType()) {
ChkAnalyse.analyseChunks(p);
} else if (i == DataGUI.ping.getType()) {
SpeedTest.pingBenchmark(p);
} else if (i == DataGUI.physics.getType()) {
MsrExec.togglePhysics(p);
} else if (i == DataGUI.mobspawning.getType()) {
MsrExec.toggleMobs(p);
} else if (i == DataGUI.spawners.getType()) {
MsrExec.toggleSpawnerOptimization(p);
} else if (i == DataGUI.rcull.getType()) {
MsrExec.cullRedstone(p);
} else if (i == DataGUI.mobcull.getType()) {
MsrExec.cullMobs(p);
}
}
}

153
src/cx/sfy/LagAssist/gui/ClientGUI.java

@ -0,0 +1,153 @@
package cx.sfy.LagAssist.gui;
import java.util.HashMap;
import java.util.Map;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.Material;
import org.bukkit.entity.HumanEntity;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import cx.sfy.LagAssist.client.ClientMain;
public class ClientGUI implements Listener {
private static Map<String, Inventory> invs = new HashMap<String, Inventory>();
public static Inventory getInventory(Player p) {
return getInventory(p.getName());
}
public static boolean existsAlready(Player p) {
return existsAlready(p.getName());
}
public static boolean existsAlready(String name) {
return invs.containsKey(name);
}
public static Inventory getInventory(String name) {
if (existsAlready(name)) {
return invs.get(name);
} else {
return createInventory(name);
}
}
private static Inventory createInventory(String name) {
Inventory inv = Bukkit.createInventory(null, 54, ClientMain.guiname);
DataGUI.setBorders(inv);
setToggles(inv);
invs.put(name, inv);
return inv;
}
private static void setToggles(Inventory inv) {
boolean[] def = ClientMain.defaults;
inv.setItem(ToggleState.TNT.nr, DataGUI.tnt);
inv.setItem(ToggleState.SAND.nr, DataGUI.sand);
inv.setItem(ToggleState.PARTICLES.nr, DataGUI.particle);
inv.setItem(ToggleState.PISTONS.nr, DataGUI.piston);
inv.setItem(ToggleState.TNT.nr + 9, DataGUI.getToggler(def[0]));
inv.setItem(ToggleState.SAND.nr + 9, DataGUI.getToggler(def[1]));
inv.setItem(ToggleState.PARTICLES.nr + 9, DataGUI.getToggler(def[2]));
inv.setItem(ToggleState.PISTONS.nr + 9, DataGUI.getToggler(def[3]));
}
private static boolean getDefault(ToggleState t) {
boolean[] def = ClientMain.defaults;
if (t == ToggleState.TNT) {
return def[0];
}
if (t == ToggleState.SAND) {
return def[1];
}
if (t == ToggleState.PARTICLES) {
return def[2];
}
if (t == ToggleState.PISTONS) {
return def[3];
}
return false;
}
public static void show(Player p) {
p.openInventory(getInventory(p));
}
public static boolean isOn(ToggleState t, Player p) {
if (!existsAlready(p)) {
return getDefault(t);
}
Inventory inv = getInventory(p);
ItemStack s = inv.getItem(t.getNr() + 9);
if (s.equals(DataGUI.toggleoff)) {
return true;
} else {
return false;
}
}
@EventHandler
public void onInventoryClick(InventoryClickEvent e) {
HumanEntity hm = e.getWhoClicked();
if (!(hm instanceof Player)) {
return;
}
Inventory invent = e.getInventory();
ItemStack itm = e.getCurrentItem();
if (itm == null) {
return;
}
if (!(ChatColor.stripColor(e.getView().getTitle())).equals(ChatColor.stripColor(ClientMain.guiname))) {
return;
}
e.setCancelled(true);
Material i = itm.getType();
int slot = e.getSlot();
if (i == DataGUI.toggleon.getType()) {
invent.setItem(slot, DataGUI.toggleoff);
} else if (i == DataGUI.toggleoff.getType()) {
invent.setItem(slot, DataGUI.toggleon);
}
}
public enum ToggleState {
TNT(20), SAND(21), PARTICLES(23), PISTONS(24);
private final int nr;
private ToggleState(int nr) {
this.nr = nr;
}
public int getNr() {
return nr;
}
}
}

203
src/cx/sfy/LagAssist/gui/DataGUI.java

@ -0,0 +1,203 @@
package cx.sfy.LagAssist.gui;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemFlag;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import cx.sfy.LagAssist.Main;
import cx.sfy.LagAssist.client.ClientMain;
import cx.sfy.LagAssist.utils.VersionMgr;
public class DataGUI {
// Glass Items
protected static ItemStack gp;
protected static ItemStack anp;
protected static ItemStack optp;
protected static ItemStack agp;
// Analyse Items
protected static ItemStack bnchie;
protected static ItemStack lagmap;
protected static ItemStack chkanalyse;
protected static ItemStack ping;
// Optimise Items
protected static ItemStack physics;
protected static ItemStack mobspawning;
protected static ItemStack spawners;
// Energise Items
protected static ItemStack rcull;
protected static ItemStack mobcull;
// ClientGUI Items
protected static ItemStack tnt;
protected static ItemStack sand;
protected static ItemStack particle;
protected static ItemStack piston;
// ClientGUI Toggles
protected static ItemStack toggleon;
protected static ItemStack toggleoff;
public static void Enabler(boolean reload) {
setItems();
if (!reload) {
Main.p.getServer().getPluginManager().registerEvents(new AdminGUI(), Main.p);
Main.p.getServer().getPluginManager().registerEvents(new ClientGUI(), Main.p);
Main.p.getServer().getPluginManager().registerEvents(new HopperGUI(), Main.p);
}
AdminGUI.Enabler();
Bukkit.getLogger().info(" §e[§a✔§e] §fGUI.");
}
private static void setItems() {
ItemStack[] pnes = VersionMgr.getStatics();
gp = pnes[0];
anp = pnes[1];
optp = pnes[2];
agp = pnes[3];
bnchie = pnes[4];
chkanalyse = pnes[5];
lagmap = pnes[6];
ping = pnes[7];
physics = pnes[8];
rcull = pnes[9];
mobspawning = pnes[10];
spawners = pnes[11];
mobcull = pnes[12];
tnt = pnes[13];
sand = pnes[14];
particle = pnes[15];
piston = pnes[16];
toggleon = pnes[17];
toggleoff = pnes[18];
customizeItem(gp, "&f", false);
customizeItem(anp, "&5&lAnalyse", false, Arrays.asList("&f", "&dAnalysis tools provide a good way",
"&dof finding lag-sources and checking performance.", "&f"));
customizeItem(optp, "&6&lOptimise", false,
Arrays.asList("&f", "&eOptimisation tools offer ways of improving performance by",
"&echanging how the game works and behaves.", "&f"));
customizeItem(agp, "&4&lEnergise", false,
Arrays.asList("&f", "&cEnergyser tools are made to jolt performance, and will aggresively",
"&cget rid of lag-sources.", "&f"));
customizeItem(bnchie, "&dBenchmark System", false, Arrays.asList("&f", "&fGet a benchmark of your system",
"&fthat can highly help you approximate", "&fthe capabilities of your system,", "&f"));
customizeItem(lagmap, "&dLag Map", false, Arrays.asList("&f", "&fGet a higly accurate map",
"&fthat graphs the amount of TPS", "&fyour server has.", "&f"));
customizeItem(chkanalyse, "&dAnalyse chunks", false, Arrays.asList("&f", "&fGet a higly accurate map",
"&fthat graphs the amount of TPS", "&fyour server has.", "&f"));
customizeItem(ping, "&dPing Statistics", false,
Arrays.asList("&f", "&fGet statistics of the Player's ping values.",
"&fThis is highly helpful for finding the optimal location", "&fwhere to host your server",
"&f"));
customizeItem(physics, "&eToggle Physics", false,
Arrays.asList("&f", "&fToggle Physics that have been enabled in the config.",
"&fPhysics might be a large cause of lag, even though",
"&fthey are not essential for the server.", "&f"));
customizeItem(mobspawning, "&eToggle Mob Spawning", false,
Arrays.asList("&f", "&fToggle the creation of new mobs.",
"&fThis may help in some situations, but should only be", "&fused as a last resort.", "&f"));
customizeItem(spawners, "&eOptimise Spawners", false,
Arrays.asList("&f", "&fToggle the Spawner Optimizations.",
"&fThis may highly help in situations where mobs from.",
"&fMob-Spawners cause lag on the server.", "&f"));
customizeItem(rcull, "&cCull Redstone", false,
Arrays.asList("&f", "&fCull active redstone machines.",
"&fThis will highly help with redstone lag-machines, and can even",
"&fhelp prevent lag-machines from starting.", "&f"));
customizeItem(mobcull, "&cCull Mobs", false,
Arrays.asList("&f", "&fClear Mobs.", "&fThis may help when you have a lot of issues with mobs,",
"&fbut if you need this it usually means", "&fthat the server has been misconfigured", "&f"));
// Do the Clientside stuff.
ClientMain.configureIcon(tnt, "tnt");
ClientMain.configureIcon(sand, "sand");
ClientMain.configureIcon(particle, "particle");
ClientMain.configureIcon(piston, "piston");
ClientMain.configureIcon(toggleon, "toggleon");
ClientMain.configureIcon(toggleoff, "toggleoff");
}
public static void setBorders(Inventory inv) {
for (int i = 4; i <= 49; i += 9) {
inv.setItem(i - 4, gp);
inv.setItem(i + 4, gp);
}
for (int i = 1; i <= 7; i++) {
inv.setItem(i, gp);
inv.setItem(i + 45, gp);
}
}
public static void customizeItem(ItemStack s, String raw, boolean shining) {
customizeItem(s, raw, shining, null);
return;
}
public static void customizeItem(ItemStack s, String raw, boolean shining, List<String> rlore) {
setShine(s, shining);
String name = ChatColor.translateAlternateColorCodes('&', raw);
ItemMeta smeta = s.getItemMeta();
smeta.setDisplayName(name);
if (rlore != null) {
List<String> lore = new ArrayList<String>();
for (String stg : rlore) {
lore.add(ChatColor.translateAlternateColorCodes('&', stg));
}
smeta.setLore(lore);
}
s.setItemMeta(smeta);
}
public static void setShine(ItemStack s, boolean shining) {
ItemMeta smeta = s.getItemMeta();
if (shining) {
smeta.addEnchant(Enchantment.DURABILITY, 1, true);
smeta.addItemFlags(ItemFlag.HIDE_ENCHANTS, ItemFlag.HIDE_ATTRIBUTES);
}
s.setItemMeta(smeta);
}
public static ItemStack getToggler(boolean bl) {
return (bl) ? toggleoff : toggleon;
}
}

196
src/cx/sfy/LagAssist/gui/HopperGUI.java

@ -0,0 +1,196 @@
package cx.sfy.LagAssist.gui;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.entity.HumanEntity;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.inventory.ClickType;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.event.inventory.InventoryCloseEvent;
import org.bukkit.event.inventory.InventoryDragEvent;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import cx.sfy.LagAssist.hoppers.HopperFilter;
public class HopperGUI implements Listener {
private static Map<Inventory, Location> locs = new HashMap<Inventory, Location>();
public static Inventory getInventory(Player p, Location loc) {
return createInventory(p.getName(), loc);
}
private static Inventory createInventory(String name, Location loc) {
Inventory inv = Bukkit.createInventory(null, HopperFilter.filtersize, HopperFilter.guiname);
addFilter(inv, loc);
return inv;
}
private static void addFilter(Inventory inv, Location loc) {
int i = 0;
for (Material mat : HopperFilter.getFilter(loc)) {
inv.setItem(i++, new ItemStack(mat));
}
}
public static void show(Player p, Location loc) {
Inventory inv = getInventory(p, loc);
locs.put(inv, loc);
p.openInventory(inv);
}
public static void exit(Location loc) {
lastclosed.clear();
if (!locs.containsValue(loc)) {
return;
}
Set<Inventory> removables = new HashSet<Inventory>();
for (Inventory inv : locs.keySet()) {
Location iloc = locs.get(inv);
if (iloc.equals(loc)) {
removables.add(inv);
}
for (HumanEntity viewer : inv.getViewers()) {
viewer.closeInventory();
lastclosed.add(inv);
}
}
locs.keySet().removeAll(removables);
}
private static Set<Inventory> lastclosed = new HashSet<Inventory>();;
// Save filter when player closes the inventory.
@EventHandler
public void onInventoryClose(InventoryCloseEvent e) {
Inventory inv = e.getInventory();
// Closed because of block break.
if (lastclosed.contains(inv)) {
return;
}
HumanEntity hm = e.getPlayer();
if (!(hm instanceof Player)) {
return;
}
if (locs.containsKey(inv)) {
HopperFilter.saveFilter(inv, locs.get(inv));
locs.remove(inv);
}
}
@SuppressWarnings("deprecation")
@EventHandler
public void onInventoryClick(InventoryClickEvent e) {
HumanEntity hm = e.getWhoClicked();
if (!(hm instanceof Player)) {
return;
}
if (e.getRawSlot() < 0) {
return;
}
Inventory clicked = e.getClickedInventory();
Inventory invent = e.getView().getTopInventory();
Inventory bottom = e.getView().getBottomInventory();
// Click outside inv.
if (invent == null) {
return;
}
ItemStack hand = e.getCursor();
ItemStack itm = e.getCurrentItem();
if (!(e.getView().getTitle()).equals(HopperFilter.guiname)) {
return;
}
if (!locs.containsKey(invent)) {
return;
}
// Attempt to fix dupe.
if (clicked.equals(bottom) && e.getClick() == ClickType.DOUBLE_CLICK) {
e.setCancelled(true);
return;
}
if (clicked.equals(invent) && !(e.getClick() == ClickType.LEFT || e.getClick() == ClickType.RIGHT)) {
e.setCancelled(true);
return;
}
if (clicked.equals(bottom)) {
return;
}
if (hand == null && itm != null) {
e.setCurrentItem(null);
} else if (hand != null) {
e.setCurrentItem(new ItemStack(hand.getType()));
}
e.setCursor(hand);
e.setCancelled(true);
}
@EventHandler
public void onInventoryDrag(InventoryDragEvent e) {
HumanEntity hm = e.getWhoClicked();
if (!(hm instanceof Player)) {
return;
}
Inventory invent = e.getView().getTopInventory();
// Click outside inv.
if (invent == null) {
return;
}
if (!(e.getView().getTitle()).equals(HopperFilter.guiname)) {
return;
}
if (!locs.containsKey(invent)) {
return;
}
e.setCancelled(true);
}
}

387
src/cx/sfy/LagAssist/hoppers/ChunkHoppers.java

@ -0,0 +1,387 @@
package cx.sfy.LagAssist.hoppers;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.Chunk;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.block.BlockState;
import org.bukkit.block.Hopper;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.Item;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.block.BlockBreakEvent;
import org.bukkit.event.block.BlockPlaceEvent;
import org.bukkit.event.entity.CreatureSpawnEvent;
import org.bukkit.event.entity.ItemSpawnEvent;
import org.bukkit.event.player.PlayerDropItemEvent;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemFlag;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import cx.sfy.LagAssist.Data;
import cx.sfy.LagAssist.Main;
import cx.sfy.LagAssist.utils.Cache;
import cx.sfy.LagAssist.utils.Others;
import cx.sfy.LagAssist.utils.V1_12;
import cx.sfy.LagAssist.utils.V1_13;
import cx.sfy.LagAssist.utils.V1_8;
import cx.sfy.LagAssist.utils.VersionMgr;
public class ChunkHoppers implements Listener {
// The Cachetime represents how often the cache should be removed
// and the tiles rechecked.
private static Cache<Chunk, BlockState[]> tilecache = new Cache<Chunk, BlockState[]>(40);
public static boolean mobhoppers;
private static double multiplier;
private static List<String> reasons;
private static String hoppermode;
public static String customname;
private static Item dropplayer;
private class HopperComparator implements Comparator<Hopper> {
Location initial;
public HopperComparator(Location initial) {
this.initial = initial;
}
@Override
public int compare(Hopper h1, Hopper h2) {
return (int) h1.getLocation().distance(initial) - (int) h2.getLocation().distance(initial);
}
}
public static void Enabler(boolean reload) {
hoppermode = Main.config.getString("hopper-check.chunk-hoppers.mode");
mobhoppers = Main.config.getDouble("hopper-check.chunk-hoppers.mob-hopper.maxtps") >= 20;
multiplier = Main.config.getDouble("hopper-check.chunk-hoppers.mob-hopper.multiplier");
reasons = Main.config.getStringList("hopper-check.chunk-hoppers.mob-hopper.spawn-reasons");
customname = ChatColor.translateAlternateColorCodes('&',
Main.config.getString("hopper-check.chunk-hoppers.define"));
tilecache.clear();
if (!reload) {
Main.p.getServer().getPluginManager().registerEvents(new ChunkHoppers(), Main.p);
runTask();
}
HopperFilter.Enabler(reload);
SellHoppers.Enabler(reload);
}
private static void runTask() {
Bukkit.getScheduler().scheduleSyncRepeatingTask(Main.p, new Runnable() {
@Override
public void run() {
tilecache.tick();
}
}, 1L, 1L);
}
public static void giveChunkHopper(Player p, int amount) {
Inventory inv = p.getInventory();
ItemStack itm = getCustomHopper(amount);
int empty = inv.firstEmpty();
if (empty == -1) {
p.getLocation().getWorld().dropItem(p.getLocation(), itm);
return;
}
p.getInventory().addItem(itm);
}
private static Material getMaterial(EntityType et) {
String loc = "hopper-check.chunk-hoppers.mob-hopper.filter-items." + et.toString().toLowerCase();
if (!Main.config.contains(loc)) {
return null;
}
return Material.valueOf(Main.config.getString(loc));
}
private List<Hopper> getHoppers(Chunk chk, Material mat) {
List<Hopper> hoppers = new ArrayList<Hopper>();
if (!tilecache.isCached(chk)) {
tilecache.putCached(chk, chk.getTileEntities());
}
for (BlockState b : tilecache.getCached(chk)) {
if (!(b instanceof Hopper)) {
continue;
}
Hopper h = (Hopper) b;
String stg = VersionMgr.isV1_8() ? V1_8.getHopperName(h) : V1_12.getHopperName(h);
// Check if not default; and if it isn't default; check if the string is null or
// it isn't custom and continue.
if (!customname.equalsIgnoreCase("DEFAULT") && (stg == null || !stg.equals(customname))) {
continue;
}
if (!HopperFilter.isAllowed(h.getLocation(), mat)) {
continue;
}
hoppers.add((Hopper) b);
}
return hoppers;
}
private ItemStack spreadItemInHoppers(List<Hopper> hoppers, ItemStack itm, Location loc) {
ItemStack remainder = itm.clone();
if (isCustomHopper(remainder)) {
return remainder;
}
if (hoppermode.equalsIgnoreCase("RANDOM")) {
Collections.shuffle(hoppers);
} else if (hoppermode.equalsIgnoreCase("CLOSEST")) {
Collections.sort(hoppers, new HopperComparator(loc));
}
for (Hopper hopper : hoppers) {
Inventory inv = hopper.getInventory();
if (SellHoppers.attemptSell(hopper, itm)) {
return null;
}
Map<Integer, ItemStack> remainers = inv.addItem(remainder);
if (remainers.size() < 1) {
return null;
}
remainder = remainers.get(0);
if (remainder == null) {
return null;
}
}
return remainder;
}
private static ItemStack chopper;
public static boolean isCustomHopper(ItemStack itm) {
if (chopper == null) {
chopper = getCustomHopper(1);
}
itm = itm.clone();
itm.setAmount(1);
return itm.isSimilar(chopper);
}
public static ItemStack getCustomHopper(int amount) {
ItemStack itm = new ItemStack(Material.valueOf("HOPPER"), amount);
ItemMeta imeta = itm.getItemMeta();
if (!customname.equalsIgnoreCase("DEFAULT")) {
imeta.setDisplayName(customname);
}
// Make it work with the unbreakable check.
VersionMgr.setUnbreakable(imeta, true);
imeta.addItemFlags(ItemFlag.HIDE_UNBREAKABLE);
itm.setItemMeta(imeta);
return itm;
}
@EventHandler(priority = EventPriority.HIGHEST)
public void onPlace(BlockPlaceEvent e) {
if (e.isCancelled()) {
return;
}
if (customname.equalsIgnoreCase("DEFAULT")) {
return;
}
ItemStack itm = e.getItemInHand();
if (itm == null) {
return;
}
if (!itm.hasItemMeta()) {
return;
}
ItemMeta imeta = itm.getItemMeta();
if (!imeta.hasDisplayName()) {
return;
}
String name = imeta.getDisplayName();
if (!name.equalsIgnoreCase(customname)) {
return;
}
if (!VersionMgr.isUnbreakable(imeta)) {
e.setCancelled(true);
return;
}
// System.out.println("SET OWNER");
// Set owner
Data.setOwningPlayer(e.getBlockPlaced().getLocation(), e.getPlayer());
tilecache.remove(e.getBlockPlaced().getChunk());
}
@EventHandler(priority = EventPriority.HIGHEST)
public void onBreak(BlockBreakEvent e) {
if (e.isCancelled()) {
return;
}
if (customname.equalsIgnoreCase("DEFAULT")) {
return;
}
Block b = e.getBlock();
BlockState bstate = b.getState();
if (!(bstate instanceof Hopper)) {
return;
}
Hopper h = (Hopper) bstate;
String stg = VersionMgr.isV1_8() ? V1_8.getHopperName(h) : V1_12.getHopperName(h);
if (stg == null) {
return;
}
if (!stg.equals(customname)) {
return;
}
Data.deleteHopper(h);
b.setType(Material.AIR);
// dropplayer = b.getWorld().dropItemNaturally(b.getLocation(), getCustomHopper(1));
dropplayer = Others.giveOrDrop(e.getPlayer(), getCustomHopper(1));
// e.getPlayer().getInventory().addItem(getCustomHopper(1));
tilecache.remove(b.getChunk());
}
@EventHandler
public void playerDrop(PlayerDropItemEvent e) {
if (e.isCancelled()) {
return;
}
dropplayer = e.getItemDrop();
}
@EventHandler
public void onItemDrop(ItemSpawnEvent e) {
if (e.isCancelled()) {
return;
}
Item itm = e.getEntity();
ItemStack its = itm.getItemStack();
Material mat = its.getType();
if (itm.equals(dropplayer)) {
return;
}
Chunk chk = itm.getLocation().getChunk();
List<Hopper> hoppers = getHoppers(chk, mat);
if (hoppers.size() < 1) {
return;
}
ItemStack remainder = spreadItemInHoppers(hoppers, itm.getItemStack(), itm.getLocation());
if (remainder == null) {
e.setCancelled(true);
return;
}
itm.setItemStack(remainder);
}
@EventHandler
public void onCreatureSpawn(CreatureSpawnEvent e) {
if (e.isCancelled()) {
return;
}
if (!reasons.contains(e.getSpawnReason().toString())) {
return;
}
if (!mobhoppers) {
return;
}
LivingEntity ent = e.getEntity();
Material mat = getMaterial(ent.getType());
if (mat == null) {
return;
}
Chunk chk = ent.getLocation().getChunk();
List<Hopper> hoppers = getHoppers(chk, mat);
for (ItemStack itm : V1_13.getLootTable(ent)) {
ItemStack buffed = itm.clone();
buffed.setAmount((int) (itm.getAmount() * multiplier));
spreadItemInHoppers(hoppers, buffed, ent.getLocation());
}
e.setCancelled(true);
// TODO: FINISH CHECK
}
}

209
src/cx/sfy/LagAssist/hoppers/HopperFilter.java

@ -0,0 +1,209 @@
package cx.sfy.LagAssist.hoppers;
import java.util.HashSet;
import java.util.Set;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.block.Hopper;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.block.Action;
import org.bukkit.event.block.BlockBreakEvent;
import org.bukkit.event.player.PlayerInteractEvent;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import cx.sfy.LagAssist.Data;
import cx.sfy.LagAssist.Main;
import cx.sfy.LagAssist.gui.HopperGUI;
import cx.sfy.LagAssist.utils.Cache;
import cx.sfy.LagAssist.utils.V1_12;
import cx.sfy.LagAssist.utils.V1_8;
import cx.sfy.LagAssist.utils.VersionMgr;
public class HopperFilter implements Listener {
private static Cache<Location, Set<Material>> filtercache = new Cache<Location, Set<Material>>(50);
// HopperGUI data
public static String guiname;
public static int filtersize;
// Default Filter
public static Set<Material> defaultfilter;
public static void Enabler(boolean reload) {
guiname = ChatColor.translateAlternateColorCodes('&', Main.config.getString("hopper-check.chunk-hoppers.filter.gui.name"));
filtersize = Main.config.getInt("hopper-check.chunk-hoppers.filter.gui.size");
defaultfilter = new HashSet<Material>();
for (String stg : Main.config.getStringList("hopper-check.chunk-hoppers.filter.default")) {
defaultfilter.add(Material.getMaterial(stg));
}
if (!reload) {
Main.p.getServer().getPluginManager().registerEvents(new HopperFilter(), Main.p);
runTask();
}
}
private static void runTask() {
Bukkit.getScheduler().scheduleSyncRepeatingTask(Main.p, new Runnable() {
@Override
public void run() {
filtercache.tick();
}
}, 1L, 1L);
}
public static Set<Material> getFilter(Location loc) {
Set<Material> cnf = Data.getFilterWhitelist(loc);
if (cnf == null) {
cnf = defaultfilter;
}
return cnf;
}
public static void saveFilter(Inventory inv, Location loc) {
Set<Material> mats = new HashSet<Material>();
for (ItemStack itm : inv.getContents()) {
if (itm == null) {
continue;
}
Material mat = itm.getType();
mats.add(mat);
}
Data.saveFilterWhitelist(loc, mats);
}
public static Set<Material> getAllowedMaterials(Location loc) {
if (!filtercache.isCached(loc)) {
filtercache.putCached(loc, getFilter(loc));
}
return filtercache.getCached(loc);
}
public static boolean isAllowed(Location loc, Material mat) {
Set<Material> mats = getAllowedMaterials(loc);
if (mats.isEmpty()) {
return true;
}
return mats.contains(mat);
}
@EventHandler(priority = EventPriority.LOWEST)
public void onBreak(BlockBreakEvent e) {
if (e.isCancelled()) {
return;
}
Block b = e.getBlock();
if (b.getType() != Material.HOPPER) {
return;
}
Hopper h = (Hopper) b.getState();
String stg = VersionMgr.isV1_8() ? V1_8.getHopperName(h) : V1_12.getHopperName(h);
// Check if not default; and if it isn't default; check if the string is null or it isn't custom and continue.
if (!ChunkHoppers.customname.equalsIgnoreCase("DEFAULT") && (stg == null || !stg.equals(ChunkHoppers.customname))) {
return;
}
if (!HopperManager.chunkhoppers) {
return;
}
Location l = b.getLocation();
HopperGUI.exit(l);
Data.saveFilterWhitelist(l, null);
filtercache.remove(l);
}
@EventHandler
public void onInteract(PlayerInteractEvent e) {
if (e.isCancelled()) {
return;
}
// Not activated
if (!HopperManager.chunkhoppers) {
return;
}
// Not sneaking.
Player p = e.getPlayer();
if (!p.isSneaking()) {
return;
}
// No permission
// if (!p.hasPermission("lagassist.customfilter")) {
// return;
// }
// Not having an empty hand
ItemStack itm = e.getItem();
if (itm != null) {
return;
}
// Not clicking a hopper.
Block b = e.getClickedBlock();
if (b.getType() != Material.HOPPER) {
return;
}
Hopper h = (Hopper) b.getState();
String stg = VersionMgr.isV1_8() ? V1_8.getHopperName(h) : V1_12.getHopperName(h);
// Check if not default; and if it isn't default; check if the string is null or it isn't custom and continue.
if (!ChunkHoppers.customname.equalsIgnoreCase("DEFAULT") && (stg == null || !stg.equals(ChunkHoppers.customname))) {
return;
}
// Not right clicking a block.
Action a = e.getAction();
if (a == Action.RIGHT_CLICK_BLOCK && p.hasPermission("lagassist.hoppers.customfilter")) {
// Opening filter inventory.
HopperGUI.show(p, b.getLocation());
e.setCancelled(true);
} else if (a == Action.LEFT_CLICK_BLOCK && p.hasPermission("lagassist.hoppers.togglesell")) {
Data.toggleSellHopper(p, b.getLocation());
e.setCancelled(true);
}
}
}

91
src/cx/sfy/LagAssist/hoppers/HopperManager.java

@ -0,0 +1,91 @@
package cx.sfy.LagAssist.hoppers;
import java.util.SplittableRandom;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.Material;
import org.bukkit.block.Hopper;
import org.bukkit.entity.HumanEntity;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.inventory.CraftItemEvent;
import org.bukkit.event.inventory.InventoryMoveItemEvent;
import org.bukkit.inventory.InventoryHolder;
import cx.sfy.LagAssist.Main;
import cx.sfy.LagAssist.utils.V1_12;
import cx.sfy.LagAssist.utils.V1_8;
import cx.sfy.LagAssist.utils.VersionMgr;
import cx.sfy.LagAssist.utils.WorldMgr;
public class HopperManager implements Listener {
private static SplittableRandom r = new SplittableRandom();
public static boolean chunkhoppers;
public static boolean denyhoppers = false;
public static void Enabler(boolean reload) {
denyhoppers = Main.config.getBoolean("hopper-check.enabled");
chunkhoppers = Main.config.getBoolean("hopper-check.chunk-hoppers.enabled");
if (!reload) {
Main.p.getServer().getPluginManager().registerEvents(new HopperManager(), Main.p);
}
if (chunkhoppers) {
ChunkHoppers.Enabler(reload);
}
Bukkit.getLogger().info(" §e[§a✔§e] §fHopper Manager.");
}
@EventHandler
public void disableCraft(CraftItemEvent e) {
if (e.getRecipe().getResult().getType().equals(Material.HOPPER) && denyhoppers == true) {
e.setCancelled(true);
for (HumanEntity human : e.getViewers())
if (human instanceof Player) {
Player p = Bukkit.getPlayer(human.getName());
p.sendMessage(
ChatColor.translateAlternateColorCodes('&', Main.config.getString("hopper-check.reason")));
}
}
}
@EventHandler
public void hopperBoom(InventoryMoveItemEvent e) {
InventoryHolder holder = e.getInitiator().getHolder();
if (!(holder instanceof Hopper)) {
return;
}
Hopper h = (Hopper) holder;
if (WorldMgr.blacklist.contains(h.getWorld().getName())) {
return;
}
if (Main.config.getInt("hopper-check.chance") <= 0) {
return;
}
String stg = VersionMgr.isV1_8() ? V1_8.getHopperName(h) : V1_12.getHopperName(h);
if (!(stg.equalsIgnoreCase("container.hopper"))) {
return;
}
int rand = r.nextInt(10000 - 1) + 1;
int chance = Main.config.getInt("hopper-check.chance");
Hopper hopp = (Hopper) e.getInitiator().getHolder();
if (rand <= chance) {
hopp.getBlock().setType(Material.STONE);
}
}
}

103
src/cx/sfy/LagAssist/hoppers/SellHoppers.java

@ -0,0 +1,103 @@
package cx.sfy.LagAssist.hoppers;
import java.util.HashMap;
import java.util.Map;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.OfflinePlayer;
import org.bukkit.block.Hopper;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.bukkit.permissions.PermissionAttachmentInfo;
import cx.sfy.LagAssist.Data;
import cx.sfy.LagAssist.Main;
import cx.sfy.LagAssist.economy.EconomyManager;
import cx.sfy.LagAssist.utils.MathUtils;
public class SellHoppers {
private static Map<Material, Double> prices = new HashMap<Material, Double>();
private static boolean enabled;
public static void Enabler(boolean reload) {
enabled = Main.config.getBoolean("hopper-check.chunk-hoppers.sell-hopper.enabled");
if (!enabled) {
return;
}
String loc = "hopper-check.chunk-hoppers.sell-hopper.prices";
prices.clear();
for (String stg : Main.config.getConfigurationSection(loc).getKeys(false)) {
prices.put(Material.getMaterial(stg), Main.config.getDouble(loc + "." + stg));
}
Bukkit.getLogger().info(" §e[§a✔§e] §fSellHopper System");
}
public static double getMultiplierPercentage(OfflinePlayer pl) {
if (!pl.isOnline()) {
return 0;
}
Player p = pl.getPlayer();
int multiplier = 100;
for (PermissionAttachmentInfo permi : p.getEffectivePermissions()) {
String perm = permi.getPermission();
if (!perm.startsWith("lagassist.sellhopper.")) {
continue;
}
perm = perm.replace("lagassist.sellhopper.", "");
if (!MathUtils.isInt(perm)) {
continue;
}
multiplier = Math.max(multiplier, Integer.valueOf(perm));
}
return multiplier;
}
public static boolean attemptSell(Hopper h, ItemStack itm) {
if (!enabled) {
return false;
}
Location loc = h.getLocation();
OfflinePlayer owner = Data.getOwningPlayer(loc);
if (owner == null) {
return false;
}
if (!Data.isSellHopper(loc)) {
return false;
}
if (!prices.containsKey(itm.getType())) {
return false;
}
double price = prices.get(itm.getType()) * itm.getAmount() * getMultiplierPercentage(owner) / 100d;
if (price == 0) {
return false;
}
EconomyManager.payPlayer(owner, price);
return true;
}
}

44
src/cx/sfy/LagAssist/logpurger/PurgerMain.java

@ -0,0 +1,44 @@
package cx.sfy.LagAssist.logpurger;
import java.io.File;
import org.bukkit.Bukkit;
import cx.sfy.LagAssist.Main;
import cx.sfy.LagAssist.utils.MathUtils;
public class PurgerMain {
public static void Enabler() {
if (!Main.config.getBoolean("logcleaner.enabled")) {
return;
}
for (String directories : Main.config.getStringList("logcleaner.list")) {
File f = new File(directories);
if (f.exists() && f.isDirectory()) {
File[] fls = f.listFiles();
for (File fl : fls) {
if (isOld(fl) && fl.canWrite()) {
fl.delete();
}
}
}
}
Bukkit.getLogger().info(" §e[§a✔§e] §fLogCleaner System.");
}
public static boolean isOld(File fl) {
int maxsize = Main.config.getInt("logcleaner.conditions.maxsize");
int maxage = Main.config.getInt("logcleaner.conditions.maxage");
boolean sizereq = (MathUtils.toMegaByte(fl.length()) > maxsize);
boolean agereq = (((System.currentTimeMillis() - fl.lastModified()) / 86400000) > maxage);
return (sizereq || agereq);
}
}

100
src/cx/sfy/LagAssist/maps/TpsRender.java

@ -0,0 +1,100 @@
package cx.sfy.LagAssist.maps;
import java.text.DecimalFormat;
import java.util.SplittableRandom;
import org.bukkit.entity.Player;
import org.bukkit.map.MapCanvas;
import org.bukkit.map.MapCursorCollection;
import org.bukkit.map.MapRenderer;
import org.bukkit.map.MapView;
import org.bukkit.map.MinecraftFont;
import cx.sfy.LagAssist.Main;
import cx.sfy.LagAssist.MonTools;
import cx.sfy.LagAssist.Monitor;
public class TpsRender extends MapRenderer {
public static byte yellow = 74;
public static byte green = -122;
private static boolean fullrder = Main.config.getBoolean("lag-map.fully-reserve");
private static DecimalFormat fmt = new DecimalFormat("##.###");
private static SplittableRandom r = new SplittableRandom();
@Override
public void render(MapView mapView, MapCanvas mapCanvas, Player p) {
if (!MonTools.mapusers.contains(p.getUniqueId()) && !fullrder) {
return;
}
MapCursorCollection crs = mapCanvas.getCursors();
// Should delete all cursors smart
while (crs.size() > 0) {
crs.removeCursor(crs.getCursor(0));
}
// BEGIN GRAPHING
for (int i = 3; i < 125; i++) {
for (int j = 3; j < 90; j++) {
if (Monitor.colors[i][j] == 32) {
int cul = r.nextInt(2);
if (cul == 1) {
mapCanvas.setPixel(i, j, (byte) 32);
} else {
mapCanvas.setPixel(i, j, (byte) 34);
}
} else {
mapCanvas.setPixel(i, j, Monitor.colors[i][j]);
}
}
}
// YELLOW DOWN
for (int i = 0; i < 128; i++) {
for (int j = 93; j < 128; j++) {
mapCanvas.setPixel(i, j, yellow);
}
}
// BLUE LINES
for (int y = 0; y < 90; y++) {
mapCanvas.setPixel(125, y, (byte) 20);
mapCanvas.setPixel(126, y, (byte) 20);
mapCanvas.setPixel(127, y, (byte) 20);
}
for (int y = 0; y < 90; y++) {
mapCanvas.setPixel(0, y, (byte) 20);
mapCanvas.setPixel(1, y, (byte) 20);
mapCanvas.setPixel(2, y, (byte) 20);
}
for (int i = 0; i < 128; i++) {
mapCanvas.setPixel(i, 90, (byte) 20);
mapCanvas.setPixel(i, 91, (byte) 20);
mapCanvas.setPixel(i, 92, (byte) 20);
}
for (int i = 0; i < 128; i++) {
mapCanvas.setPixel(i, 0, (byte) 20);
mapCanvas.setPixel(i, 1, (byte) 20);
mapCanvas.setPixel(i, 2, (byte) 20);
}
// TEXTAREA
String TPS = "TPS: " + fmt.format(Monitor.exactTPS);
String FREEMEM = "FREE MEM: " + String.valueOf(Monitor.freeMEM() + "MB");
mapCanvas.drawText(5, 115, MinecraftFont.Font, TPS);
mapCanvas.drawText(5, 100, MinecraftFont.Font, FREEMEM);
}
public static void Enabler() {
}
}

708
src/cx/sfy/LagAssist/metrics/BStats.java

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

64
src/cx/sfy/LagAssist/metrics/MetricsManager.java

@ -0,0 +1,64 @@
package cx.sfy.LagAssist.metrics;
import org.bukkit.Bukkit;
import org.bukkit.Chunk;
import org.bukkit.World;
import cx.sfy.LagAssist.ExactTPS;
import cx.sfy.LagAssist.Main;
import cx.sfy.LagAssist.minebench.SpecsGetter;
public class MetricsManager {
private static BStats stats;
public static void Enabler(boolean reload) {
if (reload) {
return;
}
stats = new BStats(Main.p);
stats.addCustomChart(new BStats.SimplePie("tps_base", () -> String.valueOf(Math.round(ExactTPS.getTPS(600)))));
stats.addCustomChart(new BStats.SimplePie("cpu_used", () -> getProcessor()));
stats.addCustomChart(new BStats.SingleLineChart("tile_entities", () -> getTileEntitiesCount()));
stats.addCustomChart(new BStats.SingleLineChart("normal_entities", () -> getEntitiesCount()));
stats.addCustomChart(new BStats.SingleLineChart("chunks_count", () -> getChunksCount()));
}
private static int getEntitiesCount() {
int ents = 0;
for (World w : Bukkit.getWorlds()) {
ents+=w.getEntities().size();
}
return ents;
}
private static int getTileEntitiesCount() {
int tents = 0;
for (World w : Bukkit.getWorlds()) {
for (Chunk chk : w.getLoadedChunks()) {
tents += chk.getTileEntities().length;
}
}
return tents;
}
private static int getChunksCount() {
int chks = 0;
for (World w : Bukkit.getWorlds()) {
chks+=w.getLoadedChunks().length;
}
return chks;
}
private static String getProcessor() {
return SpecsGetter.getCPU(SpecsGetter.getOS());
}
}

92
src/cx/sfy/LagAssist/microfeatures/MicroManager.java

@ -0,0 +1,92 @@
package cx.sfy.LagAssist.microfeatures;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
import org.bukkit.block.BlockState;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.block.BlockGrowEvent;
import org.bukkit.material.MaterialData;
import org.bukkit.material.PistonBaseMaterial;
import cx.sfy.LagAssist.Main;
@SuppressWarnings("deprecation")
public class MicroManager implements Listener {
public static void Enabler(boolean reload) {
Bukkit.getLogger().info(" §e[§a✔§e] §fMicroFeatures.");
if (!reload) {
runTask();
}
Main.p.getServer().getPluginManager().registerEvents(new MicroManager(), Main.p);
}
private static void runTask() {
Bukkit.getScheduler().runTaskTimer(Main.p, () -> {
for (BlockState b : breakables) {
b.getBlock().breakNaturally();
}
breakables.clear();
}, 5, 5);
}
private static List<BlockState> breakables = new ArrayList<>();
private static final List<BlockFace> growablefaces = Arrays.asList(BlockFace.EAST, BlockFace.WEST, BlockFace.NORTH,
BlockFace.SOUTH);
@EventHandler(priority = EventPriority.HIGHEST)
public void onGrowableGrow(BlockGrowEvent e) {
if (!Main.config.getBoolean("microfeatures.optimize-growable-farms.enable")) {
return;
}
if (e.isCancelled()) {
return;
}
BlockState b = e.getNewState();
Material mat = b.getType();
if (!Main.config.getStringList("microfeatures.optimize-growable-farms.blocks").contains(mat.toString())) {
return;
}
for (BlockFace face : growablefaces) {
Block piston = b.getBlock().getRelative(face);
if (piston == null) {
continue;
}
MaterialData mdata = piston.getState().getData();
if (!(mdata instanceof PistonBaseMaterial)) {
continue;
}
PistonBaseMaterial pdata = (PistonBaseMaterial) mdata;
if (pdata.getFacing().getOppositeFace() != face) {
continue;
}
breakables.add(b);
return;
}
}
}

136
src/cx/sfy/LagAssist/minebench/Approximate.java

@ -0,0 +1,136 @@
package cx.sfy.LagAssist.minebench;
import java.util.ArrayList;
import java.util.List;
import org.bukkit.Bukkit;
import org.bukkit.command.CommandSender;
import cx.sfy.LagAssist.Main;
public class Approximate {
private static boolean inuse = false;
private static List<CommandSender> receivers = new ArrayList<CommandSender>();
public static int approximatePlayers(BenchResponse br) {
int mem = SpecsGetter.MaxRam();
int singlescore = br.getSinglethread();
int multiscore = br.getMultithread();
if (singlescore == -1 || multiscore == -1) {
return -1;
}
return Math.min(getMaxSTH(singlescore), getMaxMemo(mem));
}
private static int getMaxMemo(int mem) {
int plgmnt = Bukkit.getPluginManager().getPlugins().length;
int remmem = (int) (mem - plgmnt * 3.2f);
return remmem / 50;
}
private static int getMaxSTH(int sthread) {
String vers = Bukkit.getVersion();
int max = 0;
if (vers.contains("1.8")) {
max = sthread / 10;
} else if (vers.contains("1.9")) {
max = sthread / 13;
} else if (vers.contains("1.10")) {
max = sthread / 14;
} else if (vers.contains("1.11")) {
max = sthread / 16;
} else if (vers.contains("1.12")) {
max = sthread / 18;
} else if (vers.contains("1.13")) {
max = sthread / 25;
} else {
max = sthread / 37;
}
return max;
}
public static void showBenchmark(CommandSender s) {
if (!receivers.contains(s)) {
receivers.add(s);
}
if (inuse) {
s.sendMessage(
Main.PREFIX + "You have been added to the receivers list. Please wait for the benchmark to finish.");
return;
}
s.sendMessage(
Main.PREFIX + "We are getting the benchmark results. This may take a while depending on your download speed. Please wait....");
Bukkit.getScheduler().runTaskAsynchronously(Main.p, new Runnable() {
@Override
public void run() {
inuse = true;
BenchResponse br = SpecsGetter.getBenchmark();
int perthread = approximatePlayers(br);
int multithread = perthread * SpecsGetter.threadCount();
String cpuname = SpecsGetter.getCPU(SpecsGetter.getOS());
String singleapprox = String.valueOf(perthread * 4 / 5) + "-" + String.valueOf(perthread * 6 / 5);
String multiapprox = String.valueOf(multithread * 4 / 5) + "-" + String.valueOf(multithread * 6 / 5);
int tries = 0;
float dspeed;
float upspeed;
do {
dspeed = SpeedTest.getDownSpeed();
tries++;
} while (dspeed == -1 && tries < 10);
do {
upspeed = SpeedTest.getUpSpeed();
tries++;
} while (upspeed == -1 && tries < 10);
String MBDL = SpeedTest.df.format(dspeed);
String MIBDL = SpeedTest.df.format(dspeed * 8.0f);
String MBUP = SpeedTest.df.format(upspeed);
String MIBUP = SpeedTest.df.format(upspeed * 8.0f);
Bukkit.getScheduler().runTask(Main.p, new Runnable() {
@Override
public void run() {
for (CommandSender cs : receivers) {
cs.sendMessage("");
cs.sendMessage("§c§l⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛§f§l BENCHMARK RESULTS §c§l⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛");
cs.sendMessage("");
cs.sendMessage(" §c✸ §fCPU Name: §e" + cpuname);
cs.sendMessage("");
cs.sendMessage(" §c✸ §fCPU Score (SINGLE): §e" + br.getStringifiedSth());
cs.sendMessage(" §c✸ §fCPU Score (MULTI): §e" + br.getStringifiedMth());
cs.sendMessage("");
cs.sendMessage(" §c✸ §fDownload Speed: §e" + MIBDL + " Mib/s (" + MBDL + "MB/s)");
cs.sendMessage(" §c✸ §fUpload Speed: §e" + MIBUP + " Mib/s (" + MBUP + " MB/s)");
cs.sendMessage("");
cs.sendMessage(" §c✸ §fMax Players (SINGLE): §e" + singleapprox);
cs.sendMessage(" §c✸ §fMax Players (GLOBAL): §e" + multiapprox);
cs.sendMessage("");
cs.sendMessage("§c§l⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛");
}
receivers.clear();
inuse = false;
}
});
}
});
}
}

43
src/cx/sfy/LagAssist/minebench/BenchResponse.java

@ -0,0 +1,43 @@
package cx.sfy.LagAssist.minebench;
public class BenchResponse {
private int singlethread;
private int multithread;
public BenchResponse(int sth, int mth) {
singlethread = sth;
multithread = mth;
}
public int getMultithread() {
return multithread;
}
public void setMultithread(int multithread) {
this.multithread = multithread;
}
public int getSinglethread() {
return singlethread;
}
public String getStringifiedSth() {
if (singlethread < 0) {
return "Unknown Score";
}
return String.valueOf(singlethread);
}
public String getStringifiedMth() {
if (multithread < 0) {
return "Unknown Score";
}
return String.valueOf(multithread);
}
public void setSinglethread(int singlethread) {
this.singlethread = singlethread;
}
}

91
src/cx/sfy/LagAssist/minebench/HTTPClient.java

@ -0,0 +1,91 @@
package cx.sfy.LagAssist.minebench;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.bukkit.Bukkit;
import cx.sfy.LagAssist.utils.Others;
public class HTTPClient {
private InputStream is;
public HTTPClient(String url) {
is = getInputStream(url);
}
private static InputStream getInputStream(String url) {
HttpURLConnection cnn;
try {
URL ur = new URL(url);
cnn = (HttpURLConnection) ur.openConnection();
cnn.setRequestProperty("User-Agent",
"Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.4; en-US; rv:1.9.2.2) Gecko/20100316 Firefox/3.6.2");
cnn.addRequestProperty("Referer", "google.com");
cnn.connect();
String header = cnn.getHeaderField("location");
if (header != null) {
HttpURLConnection redur = (HttpURLConnection) new URL(header.replaceAll("http", "https"))
.openConnection();
redur.setRequestProperty("User-Agent",
"Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.4; en-US; rv:1.9.2.2) Gecko/20100316 Firefox/3.6.2");
redur.connect();
return redur.getInputStream();
} else {
return cnn.getInputStream();
}
} catch (IOException e) {
Bukkit.getLogger().warning("§e[§a✖§e] §fCouldn't connect to PassMark Data.");
return null;
}
}
private static int getMultiThread(String s) {
String regex = "<span style=\"font-family: Arial, Helvetica, sans-serif;font-size: 44px; font-weight: bold; color: #F48A18;\">(.*.)<\\/span>";
final Pattern pattern = Pattern.compile(regex, Pattern.MULTILINE);
final Matcher matcher = pattern.matcher(s);
if (!matcher.find()) {
return -1;
}
return Integer.valueOf(matcher.group(1));
}
private static int getSingleThread(String s) {
String regex = "Single Thread Rating: <\\/strong>(.*.)<br>";
final Pattern pattern = Pattern.compile(regex, Pattern.MULTILINE);
final Matcher matcher = pattern.matcher(s);
if (!matcher.find()) {
return -1;
}
float fl = Float.valueOf(matcher.group(1));
return (int) fl;
}
public BenchResponse getBenchmark() {
if (is == null) {
return new BenchResponse(-1, -1);
}
String s = Others.readInputStreamAsString(is);
return new BenchResponse(getSingleThread(s), getMultiThread(s));
}
}

146
src/cx/sfy/LagAssist/minebench/SpecsGetter.java

@ -0,0 +1,146 @@
package cx.sfy.LagAssist.minebench;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.lang.management.ManagementFactory;
import java.lang.management.OperatingSystemMXBean;
import java.net.URLEncoder;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import cx.sfy.LagAssist.utils.Others;
public class SpecsGetter {
private static OperatingSystemMXBean osmx = ManagementFactory.getOperatingSystemMXBean();
private static String getLinuxCPU() {
final String regex = "model name : (.*\\n)";
File fl = new File("/proc/cpuinfo");
if (!fl.exists()) {
return "unknown";
}
if (!fl.canRead()) {
return "unknown";
}
try {
String stg = Others.readInputStreamAsString(new FileInputStream(fl));
final Pattern pattern = Pattern.compile(regex, Pattern.MULTILINE);
final Matcher matcher = pattern.matcher(stg);
matcher.find();
return matcher.group(1).replaceAll("\n", "");
} catch (IOException e) {
e.printStackTrace();
return "unknown";
}
}
private static String getWindowsCPU() {
Runtime rt = Runtime.getRuntime();
try {
Process proc = rt.exec("wmic cpu get name");
BufferedReader reader = new BufferedReader(new InputStreamReader(proc.getInputStream()));
reader.readLine();
reader.readLine();
return reader.readLine();
} catch (IOException e) {
return "unknown";
}
}
private static String getMacCPU() {
Runtime rt = Runtime.getRuntime();
try {
Process proc = rt.exec("sysctl -n machdep.cpu.brand_string");
BufferedReader reader = new BufferedReader(new InputStreamReader(proc.getInputStream()));
return reader.readLine();
} catch (IOException e) {
return "unknown";
}
}
public static String getCPU(String OS) {
if (OS.equals("windows")) {
return getWindowsCPU();
} else if (OS.equals("linux")) {
return getLinuxCPU();
} else if (OS.equals("mac")) {
return getMacCPU();
} else {
return "unknown";
}
}
public static String getOS() {
String OS = System.getProperty("os.name").toLowerCase();
if (OS.contains("linux")) {
return "linux";
} else if (OS.contains("win")) {
return "windows";
} else if (OS.contains("mac")) {
return "mac";
} else {
return "other";
}
}
public static int MaxRam() {
return (int) (Runtime.getRuntime().maxMemory() / 1024 / 1024);
}
public static double FreeRam() {
return (double) Runtime.getRuntime().freeMemory() / 1024 / 1024;
}
public static int threadCount() {
return osmx.getAvailableProcessors();
}
public static float getSystemLoad() {
return (float) osmx.getSystemLoadAverage();
}
public static BenchResponse getBenchmark() {
String cpu = getCPU(getOS());
if (cpu.equals("unknown")) {
return new BenchResponse(-1, -1);
}
HTTPClient conn;
try {
conn = new HTTPClient("https://www.cpubenchmark.net/cpu.php?cpu=" + URLEncoder.encode(cpu, "UTF-8"));
return conn.getBenchmark();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return null;
}
public static int getSingleThreadScore() {
return getBenchmark().getSinglethread();
}
public static int getMultiThreadScore() {
return getBenchmark().getMultithread();
}
}

141
src/cx/sfy/LagAssist/minebench/SpeedTest.java

@ -0,0 +1,141 @@
package cx.sfy.LagAssist.minebench;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.URL;
import java.net.URLConnection;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.SplittableRandom;
import java.util.UUID;
import org.bukkit.Bukkit;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import cx.sfy.LagAssist.Main;
import cx.sfy.LagAssist.packets.Reflection;
public class SpeedTest {
protected static DecimalFormat df = new DecimalFormat("0.0");
private static SplittableRandom sr = new SplittableRandom();
protected static float getDownSpeed() {
URLConnection ftp;
try {
URL ftpdlur = new URL(Main.config.getString("benchmark.download.link"));
ftp = ftpdlur.openConnection();
ftp.connect();
InputStream dloader = ftp.getInputStream();
BufferedInputStream bis = new BufferedInputStream(dloader);
long begin = System.currentTimeMillis();
while (bis.read() != -1) {
// Waste time while reading.
}
float taken = (System.currentTimeMillis() - begin) / 1000.0f;
dloader.close();
return 50.0f / taken;
} catch (IOException e) {
return -1;
}
}
protected static float getUpSpeed() {
URLConnection ftp;
try {
long dlsize = Main.config.getLong("benchmark.upload.size");
URL ftpupur = new URL(
Main.config.getString("benchmark.upload.link").replaceAll("%RND%", UUID.randomUUID().toString()));
ftp = ftpupur.openConnection();
ftp.connect();
OutputStream of = ftp.getOutputStream();
BufferedOutputStream bof = new BufferedOutputStream(of);
long begin = System.currentTimeMillis();
for (int i = 0; i < dlsize; i+=4) {
int a = sr.nextInt(0, Integer.MAX_VALUE);
of.write((a >> 0) & 0xff);
of.write((a >> 8) & 0xff);
of.write((a >> 16) & 0xff);
of.write((a >> 24) & 0xff);
}
bof.flush();
float taken = (System.currentTimeMillis() - begin) / 1000.0f;
bof.close();
of.close();
return dlsize / 1000000 / taken;
} catch (IOException e) {
return -1;
}
}
public static void pingBenchmark(CommandSender s) {
List<InetAddress> ips = new ArrayList<InetAddress>();
int med = 0;
int nr = 0;
int max = -1;
int min = -1;
String namemax = "";
String namemin = "";
for (Player p : Bukkit.getOnlinePlayers()) {
int pping = Reflection.getPing(p);
med += pping;
nr++;
if (max == -1) {
max = pping;
namemax = p.getName();
} else if (max < pping) {
max = pping;
namemax = p.getName();
}
if (min == -1) {
min = pping;
namemin = p.getName();
} else if (min > pping) {
min = pping;
namemin = p.getName();
}
ips.add(p.getAddress().getAddress());
}
s.sendMessage("");
s.sendMessage("§c§l⬛⬛⬛⬛⬛⬛§f§l PINGTEST RESULTS §c§l⬛⬛⬛⬛⬛⬛");
s.sendMessage("");
s.sendMessage(" §c✸ §fLowest Ping: §e" + String.valueOf(min) + "ms §c(" + namemin + ")");
s.sendMessage(" §c✸ §fHighest Ping: §e" + String.valueOf(max) + "ms §c(" + namemax + ")");
s.sendMessage("");
s.sendMessage(" §c✸ §fAverage Ping: §e" + df.format((double) (med / nr)) + "ms");
s.sendMessage("");
s.sendMessage("§c§l⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛");
}
}

28
src/cx/sfy/LagAssist/minebench/SysInfo.java

@ -0,0 +1,28 @@
package cx.sfy.LagAssist.minebench;
import org.bukkit.command.CommandSender;
import cx.sfy.LagAssist.Main;
public class SysInfo {
public static void sendInfo(CommandSender s) {
String os = System.getProperty("os.name").toLowerCase();
String arch = System.getProperty("os.arch").toLowerCase();
String java = System.getProperty("java.version");
String CPU = SpecsGetter.getCPU(SpecsGetter.getOS());
String cores = String.valueOf(Runtime.getRuntime().availableProcessors());
String load = String.valueOf(SpecsGetter.getSystemLoad());
String freespace = "FREE: " + String.valueOf(Main.p.getDataFolder().getFreeSpace()) + " USABLE: "
+ Main.p.getDataFolder().getUsableSpace();
s.sendMessage(os);
s.sendMessage(arch);
s.sendMessage(java);
s.sendMessage(CPU);
s.sendMessage(cores);
s.sendMessage(load);
s.sendMessage(freespace);
;
}
}

136
src/cx/sfy/LagAssist/mobs/SmartMob.java

@ -0,0 +1,136 @@
package cx.sfy.LagAssist.mobs;
import java.util.ArrayList;
import java.util.List;
import java.util.SplittableRandom;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.entity.ArmorStand;
import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.Slime;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.entity.CreatureSpawnEvent;
import org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason;
import org.bukkit.event.entity.EntityDeathEvent;
import org.bukkit.inventory.ItemStack;
import cx.sfy.LagAssist.Main;
import cx.sfy.LagAssist.stacker.StackManager;
import cx.sfy.LagAssist.utils.PaperOnly;
import cx.sfy.LagAssist.utils.VersionMgr;
import cx.sfy.LagAssist.utils.WorldMgr;
public class SmartMob implements Listener {
private static SplittableRandom rand = new SplittableRandom();
public static boolean Spawning;
public static List<String> mobs = new ArrayList<String>();
public static boolean Whitelist;
private static boolean nogravityastand;
private static boolean simpleslime;
public static void Enabler(boolean reload) {
if (!reload) {
Main.p.getServer().getPluginManager().registerEvents(new SmartMob(), Main.p);
}
Bukkit.getLogger().info(" §e[§a✔§e] §fSmart Mob Tools.");
mobs = Main.config.getStringList("smart-cleaner.mobs");
Whitelist = Main.config.getBoolean("smart-cleaner.whitelist");
Spawning = true;
nogravityastand = Main.config.getBoolean("mob-manager.no-armorstand-gravity");
simpleslime = Main.config.getBoolean("mob-manager.simple-slime");
}
@SuppressWarnings("deprecation")
public static void MobCuller() {
for (World w : Bukkit.getWorlds()) {
if (!WorldMgr.blacklist.contains(w.getName())) {
for (Entity e : w.getEntities()) {
if (Whitelist) {
if (isRemovable(e)) {
if (e.getCustomName() == null && e.getPassenger() == null) {
e.remove();
}
}
} else if (mobs.contains(e.getType().toString())) {
if (isRemovable(e)) {
e.remove();
}
}
}
}
}
}
private static boolean isRemovable(Entity ent) {
String name = ent.getCustomName();
if (name == null || (name != null && StackManager.isStacked(ent))) {
return true;
}
if (!VersionMgr.hasPassengers(ent)) {
return true;
}
return false;
}
@EventHandler(priority = EventPriority.LOWEST)
public void DeathListener(EntityDeathEvent e) {
Entity ent = e.getEntity();
if (simpleslime && ent instanceof Slime) {
Slime slm = (Slime) ent;
e.getDrops().clear();
int items = rand.nextInt(slm.getSize() * 2, slm.getSize() * 4);
int xp = rand.nextInt(slm.getSize() * 4, slm.getSize() * 7);
e.setDroppedExp(xp);
e.getDrops().add(new ItemStack(Material.SLIME_BALL, items));
}
}
@EventHandler(priority = EventPriority.LOWEST)
public void SpawnListener(CreatureSpawnEvent e) {
if (!Spawning) {
if (!WorldMgr.blacklist.contains(e.getEntity().getWorld().getName())) {
e.setCancelled(true);
}
return;
}
Entity ent = e.getEntity();
SpawnReason reason = e.getSpawnReason();
if (nogravityastand && (ent.getType() == EntityType.ARMOR_STAND)) {
Bukkit.getScheduler().scheduleSyncDelayedTask(Main.p, new Runnable() {
@Override
public void run() {
if (Main.paper) {
PaperOnly.freezeArmorstand((ArmorStand) e.getEntity());
} else {
ent.setGravity(false);
}
}
}, 40L);
}
if (simpleslime && (reason == SpawnReason.SLIME_SPLIT)) {
e.setCancelled(true);
}
}
}

104
src/cx/sfy/LagAssist/mobs/SpawnerMgr.java

@ -0,0 +1,104 @@
package cx.sfy.LagAssist.mobs;
import java.util.SplittableRandom;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.block.CreatureSpawner;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.entity.SpawnerSpawnEvent;
import cx.sfy.LagAssist.Main;
import cx.sfy.LagAssist.utils.V1_12;
import cx.sfy.LagAssist.utils.VersionMgr;
import cx.sfy.LagAssist.utils.WorldMgr;
public class SpawnerMgr implements Listener {
private static boolean enabled;
public static boolean active = false;
private static int chance;
private static boolean breaker;
private static int delay;
private static int countmin;
private static int countmax;
private static int spawnrange;
private static int playerrange;
private static SplittableRandom rand = new SplittableRandom();
public static void Enabler(boolean reload) {
enabled = Main.config.getBoolean("spawner-check.enabled");
if (!enabled) {
return;
}
if (!reload) {
Main.p.getServer().getPluginManager().registerEvents(new SpawnerMgr(), Main.p);
}
breaker = Main.config.getBoolean("spawner-check.breaker");
chance = Main.config.getInt("spawner-check.chance");
delay = Main.config.getInt("spawner-check.custom-settings.delay");
countmin = Main.config.getInt("spawner-check.custom-settings.amount.min");
countmax = Main.config.getInt("spawner-check.custom-settings.amount.max");
spawnrange = Main.config.getInt("spawner-check.custom-settings.spawnrange");
int ntsqrt = Main.config.getInt("spawner-check.custom-settings.player-range");
playerrange = ntsqrt * ntsqrt;
Bukkit.getLogger().info(" §e[§a✔§e] §fSpawner Manager.");
}
@EventHandler(priority = EventPriority.LOWEST)
public void onMSpawn(SpawnerSpawnEvent e) {
CreatureSpawner cs = e.getSpawner();
if (!enabled) {
return;
}
if (!active) {
return;
}
if (cs == null) {
return;
}
if (WorldMgr.isBlacklisted(cs.getWorld())) {
return;
}
if (breaker) {
Block b = cs.getBlock();
int rando = rand.nextInt(0, 1000);
if (rando < chance) {
b.setType(Material.AIR);
}
}
boolean updated = false;
if (cs.getDelay() != delay) {
cs.setDelay(delay);
updated = true;
}
if (VersionMgr.isV1_12()) {
updated = V1_12.modifySpawner(cs, rand.nextInt(countmin, countmax + 1), spawnrange, playerrange);
}
if (updated) {
cs.update();
}
}
}

25
src/cx/sfy/LagAssist/packets/BlacklistHandler.java

@ -0,0 +1,25 @@
package cx.sfy.LagAssist.packets;
import cx.sfy.LagAssist.safety.SafetyAnticrash;
import io.netty.channel.Channel;
import io.netty.channel.ChannelDuplexHandler;
import io.netty.channel.ChannelHandlerContext;
/*
* Used for outright removal of packets from the moment the player was a bad boy.
*
* Makes sure to prevent other plugins (ProtocolLib) from being spammed with bad packets.
*/
public class BlacklistHandler extends ChannelDuplexHandler {
@Override
public void channelRead(ChannelHandlerContext ctx, Object arg1) throws Exception {
Channel ch = ctx.channel();
if (SafetyAnticrash.isDropped(ch)) {
ch.disconnect().get();
return;
}
super.channelRead(ctx, arg1);
}
}

44
src/cx/sfy/LagAssist/packets/PacketHandler.java

@ -0,0 +1,44 @@
package cx.sfy.LagAssist.packets;
import org.bukkit.entity.Player;
import cx.sfy.LagAssist.client.ClientPacket;
import cx.sfy.LagAssist.safety.SafetyAnticrash;
import io.netty.channel.ChannelDuplexHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelPromise;
public class PacketHandler extends ChannelDuplexHandler {
private Player p;
public PacketHandler(final Player p) {
this.p = p;
}
// OUTPUT MANGLER
@Override
public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {
if (SafetyAnticrash.isDropped(ctx.channel())) {
return;
}
if (ClientPacket.hidePacket(p, ctx, msg, promise)) {
return;
}
super.write(ctx, msg, promise);
}
// INPUT MANGLER
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
if (SafetyAnticrash.isDropped(ctx.channel())) {
return;
}
if (SafetyAnticrash.isBlocked(p, msg, ctx.channel())) {
return;
}
super.channelRead(ctx, msg);
}
}

137
src/cx/sfy/LagAssist/packets/PacketInjector.java

@ -0,0 +1,137 @@
package cx.sfy.LagAssist.packets;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import cx.sfy.LagAssist.client.ClientMain;
import cx.sfy.LagAssist.safety.SafetyManager;
import io.netty.channel.Channel;
public class PacketInjector {
private static Field channel;
private static Field networkManager;
private static Field playerConnection;
public static void Enabler() {
if (!PacketMain.isPacketEnabled()) {
return;
}
try {
PacketInjector.playerConnection = Reflection.getClass("{nms}.EntityPlayer").getField("playerConnection");
PacketInjector.networkManager = Reflection.getClass("{nms}.PlayerConnection").getField("networkManager");
PacketInjector.channel = Reflection.getClass("{nms}.NetworkManager").getField("channel");
PacketInjector.refreshSessions();
} catch (Exception e) {
e.printStackTrace();
}
}
public static void Disabler() {
for (Player p : Bukkit.getOnlinePlayers()) {
removePlayer(p);
}
}
public static void addPlayer(final Player p) {
if (p == null) {
return;
}
try {
final Channel channel = PacketInjector
.getChannel(PacketInjector.getNetworkManager(Reflection.getNmsPlayer(p)));
if (channel == null) {
return;
}
if (channel.pipeline().get("LagAssist_Handler") == null) {
final PacketHandler packetHandler = new PacketHandler(p);
final BlacklistHandler blacklistHandler = new BlacklistHandler();
// channel.pipeline().addLast("LagAssistPck", packetHandler);
if (ClientMain.enabled) {
channel.pipeline().addBefore("packet_handler", "LagAssist_Handler", packetHandler);
}
if (SafetyManager.enabled) {
channel.pipeline().addAfter("splitter", "LagAssist_Blacklist", blacklistHandler);
}
}
// System.out.println("PIPES");
// for(String stg : channel.pipeline().toMap().keySet()) {
// System.out.println(stg);
// }
} catch (final Exception t) {
t.printStackTrace();
}
}
private static Channel getChannel(final Object networkManager) {
if (networkManager == null) {
return null;
}
Channel channel = null;
try {
channel = (Channel) PacketInjector.channel.get(networkManager);
} catch (final Exception e) {
e.printStackTrace();
}
return channel;
}
private static Object getNetworkManager(final Object entityPlayer) {
if (entityPlayer == null) {
return null;
}
Object networkManager = null;
try {
networkManager = PacketInjector.networkManager.get(PacketInjector.playerConnection.get(entityPlayer));
} catch (Exception e) {
e.printStackTrace();
}
return networkManager;
}
public static void refreshSessions() {
for (final Player player : Bukkit.getOnlinePlayers()) {
PacketInjector.removePlayer(player);
PacketInjector.addPlayer(player);
}
}
public static void removePlayer(final Player p) {
if (p == null) {
return;
}
if (!p.isOnline()) {
return;
}
try {
final Channel channel = PacketInjector
.getChannel(PacketInjector.getNetworkManager(Reflection.getNmsPlayer(p)));
if (channel == null) {
return;
}
List<String> oldnames = new ArrayList<>(channel.pipeline().names());
for (String pipe : oldnames) {
if (!pipe.contains("LagAssist")) {
continue;
}
channel.pipeline().remove(pipe);
}
// if (channel.pipeline().get("LagAssist_Handler") != null) {
// channel.pipeline().remove("LagAssist_Handler");
// }
// if (channel.pipeline().get("LagAssist_Blacklist") != null) {
// channel.pipeline().remove("LagAssist_Blacklist");
// }
} catch (Exception e) {
// e.printStackTrace();
}
}
}

49
src/cx/sfy/LagAssist/packets/PacketMain.java

@ -0,0 +1,49 @@
package cx.sfy.LagAssist.packets;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.event.player.PlayerQuitEvent;
import cx.sfy.LagAssist.Main;
import cx.sfy.LagAssist.client.ClientMain;
import cx.sfy.LagAssist.safety.SafetyManager;
public class PacketMain implements Listener {
public static void Enabler(boolean reload) {
PacketInjector.Enabler();
ClientMain.secondaryEnabler(reload);
if (!reload) {
Main.p.getServer().getPluginManager().registerEvents(new PacketMain(), Main.p);
}
Bukkit.getLogger().info(" §e[§a✔§e] §fInjecting PacketListener.");
}
public static boolean isPacketEnabled() {
return ClientMain.enabled || SafetyManager.enabled;
}
@EventHandler(priority = EventPriority.LOWEST)
public void onJoin(PlayerJoinEvent e) {
if (!isPacketEnabled()) {
return;
}
Player p = e.getPlayer();
PacketInjector.addPlayer(p);
}
@EventHandler(priority = EventPriority.LOWEST)
public void onQuit(PlayerQuitEvent e) {
if (!isPacketEnabled()) {
return;
}
Player p = e.getPlayer();
PacketInjector.removePlayer(p);
}
}

559
src/cx/sfy/LagAssist/packets/Reflection.java

@ -0,0 +1,559 @@
package cx.sfy.LagAssist.packets;
import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.block.Block;
import org.bukkit.command.CommandMap;
import org.bukkit.command.PluginCommand;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.MapMeta;
import org.bukkit.map.MapView;
import org.bukkit.plugin.Plugin;
import org.bukkit.plugin.SimplePluginManager;
import org.bukkit.scoreboard.Scoreboard;
import org.json.simple.JSONObject;
import cx.sfy.LagAssist.Main;
import cx.sfy.LagAssist.utils.V1_8;
import cx.sfy.LagAssist.utils.VersionMgr;
import net.md_5.bungee.api.ChatMessageType;
import net.md_5.bungee.api.chat.ComponentBuilder;
public class Reflection {
private static Map<Class<?>, Field[]> cached = new HashMap<Class<?>, Field[]>();
private static String version = ServerPackage.getServerVersion();
public static enum Classes {
CraftWorld(), CraftBlock(), CraftPlayer(), Material(), MapMeta(), WorldServer(), ChunkProviderServer(),
PacketPlayOutTitle(), IChatBaseComponent(), World();
private Class<?> type;
public Class<?> getType() {
return type;
}
}
public static enum Methods {
setMapId(), getMapId(), getPlayerHandle(), getBlockType(), getChunkProviderServer(), chunkExists(),
getIChatBaseComponent(), setViewDistance();
private Method mthd;
public Method getMethod() {
return mthd;
}
}
public static void Enabler() {
// PUTTING CLASSES IN ENUM.
Classes.CraftWorld.type = getClass("{cb}.CraftWorld");
Classes.World.type = getClass("{b}.World");
Classes.CraftBlock.type = getClass("{cb}.block.CraftBlock");
Classes.CraftPlayer.type = getClass("{cb}.entity.CraftPlayer");
Classes.Material.type = getClass("{b}.Material");
Classes.MapMeta.type = getClass("{b}.inventory.meta.MapMeta");
Classes.WorldServer.type = getClass("{nms}.WorldServer");
Classes.ChunkProviderServer.type = getClass("{nms}.ChunkProviderServer");
Classes.IChatBaseComponent.type = getClass("{nms}.IChatBaseComponent");
Classes.PacketPlayOutTitle.type = getClass("{nms}.PacketPlayOutTitle");
// PUTTING METHODS IN ENUM.
Methods.setMapId.mthd = getMethod(Classes.MapMeta.getType(), "setMapId", int.class);
Methods.getMapId.mthd = getMethod(Classes.MapMeta.getType(), "getMapId");
Methods.getPlayerHandle.mthd = getMethod(Classes.CraftPlayer.getType(), "getHandle");
Methods.getBlockType.mthd = getMethod(Classes.CraftBlock.getType(), "getType");
Methods.getChunkProviderServer.mthd = getMethod(Classes.WorldServer.getType(), "getChunkProviderServer");
Methods.getIChatBaseComponent.mthd = getMethod(Classes.IChatBaseComponent.getType(), "a", String.class);
Methods.chunkExists.mthd = getMethod(Classes.ChunkProviderServer.getType(), VersionMgr.ChunkExistsName(),
int.class, int.class);
Methods.setViewDistance.mthd = getMethod(Classes.World.getType(), "setViewDistance", int.class);
}
@SuppressWarnings("deprecation")
public static void sendAction(Player player, String s) {
if (Bukkit.getVersion().contains("1.8")) {
V1_8.sendActionbar(player, s);
} else {
player.spigot().sendMessage(ChatMessageType.ACTION_BAR, new ComponentBuilder(s).create());
}
}
public void sendTitle(Player p, int fadein, int stay, int fadeout, String title, String subtitle) {
try {
Object enumTitle = Classes.PacketPlayOutTitle.getType().getDeclaredClasses()[0].getField("TITLE").get(null);
Object enumSubtitle = Classes.PacketPlayOutTitle.getType().getDeclaredClasses()[0].getField("SUBTITLE")
.get(null);
Object titlebase = runMethod(null, Methods.getIChatBaseComponent.getMethod(),
"{\"text\": \"" + title + "\"}");
Object subtitlebase = runMethod(null, Methods.getIChatBaseComponent.getMethod(),
"{\"text\": \"" + subtitle + "\"}");
Class<?> packetcls = Classes.PacketPlayOutTitle.getType();
Constructor<?> constr = packetcls.getConstructor(
Classes.PacketPlayOutTitle.getType().getDeclaredClasses()[0], Classes.IChatBaseComponent.getType(),
int.class, int.class, int.class);
Object packetTitle = constr.newInstance(enumTitle, titlebase, fadein, stay, fadeout);
Object packetSubtitle = constr.newInstance(enumSubtitle, subtitlebase, fadein, stay, fadeout);
sendPlayerPacket(p, packetTitle);
sendPlayerPacket(p, packetSubtitle);
}
catch (Exception e) {
e.printStackTrace();
}
}
public static MapView getMapView(int i) {
Class<?> buk = Bukkit.class;
try {
Method getMap = buk.getDeclaredMethod("getMap", VersionMgr.isNewMaterials() ? int.class : short.class);
return (MapView) (VersionMgr.isNewMaterials() ? getMap.invoke(null, i) : getMap.invoke(null, (short) i));
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
public static int getId(MapView view) {
if (view == null) {
return 0;
}
Class<?> mv = MapView.class;
try {
Method getMap = mv.getDeclaredMethod("getId");
Object obj = getMap.invoke(view);
if (obj instanceof Short) {
return (short) obj;
} else if (obj instanceof Integer) {
return (int) obj;
}
} catch (Exception e) {
e.printStackTrace();
}
return 0;
}
@SuppressWarnings("unchecked")
static JSONObject convert(String text) {
JSONObject json = new JSONObject();
json.put("text", text);
return json;
}
public static Class<?> getClass(String classname) {
try {
String path = classname.replace("{nms}", "net.minecraft.server." + version)
.replace("{nm}", "net.minecraft." + version).replace("{cb}", "org.bukkit.craftbukkit." + version)
.replace("{b}", "org.bukkit");
return Class.forName(path);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
public static Object getCraftWorld(World w) {
Class<?> crwclass = Classes.CraftWorld.getType();
System.out.println(crwclass.getName());
Object craftworld = crwclass.cast(w);
return craftworld;
}
public static Object getWorldServer(Object craftWorld) {
try {
return getFieldValue(craftWorld, "world");
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
public static Object getChunkProvider(Object worldServer) {
try {
return runMethod(worldServer, Methods.getChunkProviderServer.getMethod());
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
public static boolean isChunkExistent(Object chunkProvider, int x, int z) {
try {
return (boolean) runMethod(chunkProvider, Methods.chunkExists.getMethod(), x, z);
} catch (Exception e) {
e.printStackTrace();
}
// NOTE: ASSUMING TRUE IN ORDER TO IGNORE IF EXCEPTION POPS UP.
return true;
}
public static boolean isTile(Block b) {
return !b.getState().getClass().getSimpleName().toLowerCase().contains("craftblockstate");
}
public static Entity getEntity(Location l) {
try {
Collection<Entity> ents = l.getWorld().getNearbyEntities(l, 1, 1, 1);
for (Entity ent : ents) {
return ent;
}
} catch (Exception e) {
return null;
}
return null;
}
public static void setmapId(ItemStack s, int id) {
MapMeta mapm = (MapMeta) s.getItemMeta();
try {
runMethod(mapm, Methods.setMapId.getMethod(), id);
} catch (Exception e) {
e.printStackTrace();
}
s.setItemMeta(mapm);
}
public static int getMapId(ItemStack s) {
MapMeta mapm = (MapMeta) s.getItemMeta();
try {
return (int) runMethod(mapm, Methods.getMapId.getMethod());
} catch (Exception e) {
e.printStackTrace();
}
return 0;
}
public static Object getNmsPlayer(Player p) {
if (p == null) {
return null;
}
Method getHandle;
try {
getHandle = p.getClass().getMethod("getHandle");
return getHandle.invoke(p);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
public static Object getNmsScoreboard(Scoreboard s) throws Exception {
Method getHandle = s.getClass().getMethod("getHandle");
return getHandle.invoke(s);
}
public static String getObjectSerialized(Object obj) {
YamlConfiguration conf = new YamlConfiguration();
Class<?> cls = obj.getClass();
String loc = cls.getSimpleName();
createObjectSerialized(conf, loc, obj, 0);
return conf.saveToString();
}
public static void createObjectSerialized(YamlConfiguration conf, String loc, Object obj, int recursiveness) {
Class<?> cls = obj.getClass();
if (!cached.containsKey(cls)) {
cached.put(cls, cls.getDeclaredFields());
}
for (Field fl : cached.get(cls)) {
fl.setAccessible(true);
Object newobj = getFieldValue(fl, obj);
if (newobj == null) {
continue;
}
String name = fl.getName();
String type = newobj.getClass().getSimpleName();
String newloc = loc + "." + type + "." + name;
if (isSimple(newobj) || recursiveness > 1) {
conf.set(newloc, convertToString(newobj));
continue;
}
createObjectSerialized(conf, newloc, newobj, recursiveness + 1);
}
}
// public static long getObjectSize(Object obj, int recursiveness) {
// if (obj == null) {
// return 0;
// }
//
//
// if (obj instanceof Serializable) {
// return getSerializedSize((Serializable) obj);
// }
//
// Class<?> cls = obj.getClass();
//
// long size = 0;
//
// if (!cached.containsKey(cls)) {
// cached.put(cls, cls.getDeclaredFields());
// }
//
// for (Field fl : cached.get(cls)) {
// fl.setAccessible(true);
// Object nobj = getFieldValue(fl, obj);
// size+=getObjectSize(nobj, recursiveness+1);
// }
//
// return size;
// }
//
// private static long getSerializedSize(Serializable obj) {
//
// try {
// ByteArrayOutputStream bos = new ByteArrayOutputStream();
// ObjectOutputStream oos = new ObjectOutputStream(bos);
// oos.writeObject(obj);
// oos.flush();
// byte[] data = bos.toByteArray();
//
// return data.length;
// } catch (Exception e) {
// return 0;
// }
// }
public static Object getFieldValue(Object instance, String fieldName) throws Exception {
Field field = instance.getClass().getDeclaredField(fieldName);
field.setAccessible(true);
return field.get(instance);
}
@SuppressWarnings("unchecked")
public static <T> T getFieldValue(Field field, Object obj) {
try {
return (T) field.get(obj);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
public static Field getField(Class<?> clazz, String fieldName) throws Exception {
Field field = clazz.getDeclaredField(fieldName);
field.setAccessible(true);
return field;
}
public static Method getMethod(Class<?> clazz, String methodName, Class<?>... resl) {
Method method;
try {
method = clazz.getDeclaredMethod(methodName, resl);
method.setAccessible(true);
return method;
} catch (Exception e) {
return null;
}
}
public static Object runMethod(Object obj, Method m, Object... resl) throws Exception {
return m.invoke(obj, resl);
}
public static Object runMethod(Object obj, String name, Object... resl) throws Exception {
Class<?>[] classes = new Class<?>[resl.length];
for (int i = 0; i < resl.length; i++) {
classes[i] = resl[i].getClass();
}
return getMethod(obj.getClass(), name, classes).invoke(obj, resl);
}
public static void setValue(Object instance, String field, Object value) {
try {
Field f = instance.getClass().getDeclaredField(field);
f.setAccessible(true);
f.set(instance, value);
} catch (Throwable t) {
t.printStackTrace();
}
}
public static void sendAllPacket(Object packet) throws Exception {
for (Player p : Bukkit.getOnlinePlayers()) {
Object nmsPlayer = getNmsPlayer(p);
Object connection = nmsPlayer.getClass().getField("playerConnection").get(nmsPlayer);
connection.getClass().getMethod("sendPacket", getClass("{nms}.Packet")).invoke(connection, packet);
}
}
public static int getPing(Player p) {
try {
Object entityPlayer = Methods.getPlayerHandle.getMethod().invoke(p);
return (int) getFieldValue(entityPlayer, "ping");
} catch (Exception e) {
return -1;
}
}
public static void sendListPacket(List<String> players, Object packet) {
try {
for (String name : players) {
Object nmsPlayer = getNmsPlayer(Bukkit.getPlayer(name));
Object connection = nmsPlayer.getClass().getField("playerConnection").get(nmsPlayer);
connection.getClass().getMethod("sendPacket", getClass("{nms}.Packet")).invoke(connection, packet);
}
} catch (Exception e) {
e.printStackTrace();
}
}
public static void sendPlayerPacket(Player p, Object packet) throws Exception {
Object nmsPlayer = getNmsPlayer(p);
Object connection = nmsPlayer.getClass().getField("playerConnection").get(nmsPlayer);
connection.getClass().getMethod("sendPacket", getClass("{nms}.Packet")).invoke(connection, packet);
}
public static PluginCommand getCommand(String name, Plugin plugin) {
PluginCommand command = null;
try {
Constructor<PluginCommand> c = PluginCommand.class.getDeclaredConstructor(String.class, Plugin.class);
c.setAccessible(true);
command = c.newInstance(name, plugin);
} catch (Exception e) {
e.printStackTrace();
}
return command;
}
public static CommandMap getCommandMap() {
CommandMap commandMap = null;
try {
if (Bukkit.getPluginManager() instanceof SimplePluginManager) {
Field f = SimplePluginManager.class.getDeclaredField("commandMap");
f.setAccessible(true);
commandMap = (CommandMap) f.get(Bukkit.getPluginManager());
}
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
return commandMap;
}
private static String convertToString(Object obj) {
Class<?> cls = obj.getClass();
if (cls.isArray()) {
String stg = "";
int length = Array.getLength(obj);
for (int i = 0; i < length; i++) {
stg += convertToString(Array.get(obj, i));
}
return stg;
}
return obj.toString();
}
private static boolean isSimple(Object obj) {
Class<?> cls = obj.getClass();
if (cls.isPrimitive()) {
return true;
}
if (cls.isEnum()) {
return true;
}
if (cls == Integer.class) {
return true;
}
if (cls == Boolean.class) {
return true;
}
if (cls == String.class) {
return true;
}
if (cls == Character.class) {
return true;
}
if (cls == Byte.class) {
return true;
}
if (cls == Short.class) {
return true;
}
if (cls == Float.class) {
return true;
}
if (cls == Double.class) {
return true;
}
if (cls == Long.class) {
return true;
}
return false;
}
public static void setViewDistance(World w, int amount) {
try {
runMethod(w, Methods.setViewDistance.mthd, amount);
Main.sendDebug("Succesfully set view distance at " + amount + " in world " + w.getName(), 1);
} catch (Exception e) {
Main.sendDebug("Exception at setViewDistance (" + w.getName() + ", " + amount + ")", 1);
}
}
}

29
src/cx/sfy/LagAssist/packets/ServerPackage.java

@ -0,0 +1,29 @@
package cx.sfy.LagAssist.packets;
import org.bukkit.Bukkit;
public enum ServerPackage {
MINECRAFTSERVER("net.minecraft.server." + getServerVersion()),
CRAFTBUKKIT("org.bukkit.craftbukkit." + getServerVersion()), MINECRAFT("net.minecraft." + getServerVersion());
private final String path;
ServerPackage(String path) {
this.path = path;
}
public static String getServerVersion() {
return Bukkit.getServer().getClass().getPackage().getName().substring(23);
}
@Override
public String toString() {
return path;
}
public Class<?> getClass(String className) throws ClassNotFoundException {
return Class.forName(this.toString() + "." + className);
}
}

183
src/cx/sfy/LagAssist/safety/SafetyAnticrash.java

@ -0,0 +1,183 @@
package cx.sfy.LagAssist.safety;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import com.google.common.collect.Maps;
import cx.sfy.LagAssist.Main;
import cx.sfy.LagAssist.packets.Reflection;
import io.netty.channel.Channel;
public class SafetyAnticrash {
private static Set<Channel> dropped = new HashSet<Channel>();
public static Map<Player, Map<String, PacketData>> packetdata = Maps.newConcurrentMap();
public static boolean isBlocked(Player p, Object msg, Channel ch) {
if (!SafetyManager.enabled) {
return false;
}
// if (WorldMgr.isBlacklisted(p.getWorld())) {
// return false;
// }
if (isDropped(ch)) {
return true;
}
try {
String packet = msg.getClass().getSimpleName().toLowerCase();
String loc = "safety-manager.anti-crasher.packets." + packet;
if (!Main.config.contains(loc)) {
return false;
}
String val = Reflection.getObjectSerialized(msg);
long size = val.length();
long count = getPacketCount(p, packet);
String temp;
if (SafetyManager.crash_debug) {
System.out.println("===== " + packet.toUpperCase() + " =====");
System.out.println("PACKET SIZE: " + size);
System.out.println("PACKET COUNT: " + count);
System.out.println("PACKET CONT:");
System.out.println(val);
System.out.println("======================");
} else if (count > Main.config.getLong(loc + ".drop-threshold")) {
dropPlayer(p, ch, packet.toUpperCase() + " TRESHOLD REACHED");
return true;
} else if (size > Main.config.getLong(loc + ".size")) {
dropPlayer(p, ch, packet.toUpperCase() + " SIZE OVERFLOW - ");
return true;
} else if ((temp = isDenied(val, loc)) != null) {
dropPlayer(p, ch, packet.toUpperCase() + " ILLEGAL VALUE - " + temp);
return true;
}
return false;
} catch (Exception e) {
e.printStackTrace();
}
return false;
}
private static int getPacketCount(Player p, String packet) {
if (!packetdata.containsKey(p)) {
packetdata.put(p, Maps.newConcurrentMap());
}
Map<String, PacketData> packets = packetdata.get(p);
if (!packets.containsKey(packet)) {
packets.put(packet, new PacketData());
}
PacketData data = packets.get(packet);
return data.incrementCount(Main.config.getInt("safety-manager.anti-crasher.packets." + packet + ".decay"));
}
private static void dropPlayer(Player p, Channel ch, String reason) {
Main.p.getLogger().warning("Player " + p.getName() + " dropped for malicious packets: " + reason);
Bukkit.getScheduler().runTask(Main.p, () -> {
p.kickPlayer("Malicious Packets - " + reason);
});
dropped.add(ch);
}
public static boolean isDropped(Channel ch) {
if (!SafetyManager.enabled) {
return false;
}
return ch == null || dropped.contains(ch);
}
protected static void startTask(Player p) {
//
// long fix = lastfix.get(p);
//
// if (fix + 1000 > System.currentTimeMillis()) {
// return;
// }
//
// fix = System.currentTimeMillis();
// lastfix.put(p, fix);
//
// Map<String, Integer> vals = packetdata.get(p);
//
// for (String packet : vals) {
// vals.put(packet, Math.max(0,
// vals.get(packet) - Main.config.getInt("safety-manager.anti-crasher." + packet + ".decay")));
// }
// Bukkit.getScheduler().runTaskTimerAsynchronously(Main.p, new Runnable() {
// @Override
// public void run() {
// for (Map<String, Integer> vals : packetdata.values()) {
// for (String packet : vals.keySet()) {
// vals.put(packet, Math.max(0, vals.get(packet)-Main.config.getInt("safety-manager.anti-crasher." + packet + ".decay")));
// }
// }
// }
//
// }, 20L, 20L);
}
private static String isDenied(String val, String loc) {
loc = loc + ".illegals";
for (String illegal : Main.config.getStringList(loc)) {
if (!val.contains(illegal)) {
continue;
}
return illegal;
}
return null;
}
protected static class PacketData {
private int count;
private long lastclean = System.currentTimeMillis();
public long getLastclean() {
return lastclean;
}
public void setClean() {
long time = System.currentTimeMillis();
if (lastclean + 1000 > time) {
return;
}
lastclean = time;
}
public int getCount() {
return count;
}
public int incrementCount(int decay) {
long old = lastclean;
setClean();
decay = (int) (((lastclean-old) / 1000) * decay);
this.count = (int) Math.max(0, count + 1 - decay);
return count;
}
}
}

72
src/cx/sfy/LagAssist/safety/SafetyManager.java

@ -0,0 +1,72 @@
package cx.sfy.LagAssist.safety;
import java.io.File;
import java.io.IOException;
import org.bukkit.Bukkit;
import cx.sfy.LagAssist.Main;
public class SafetyManager {
public static boolean enabled = false;
public static boolean crash_debug = false;
public static void Enabler(boolean reload) {
enabled = Main.config.getBoolean("safety-manager.enabled");
crash_debug = Main.config.getBoolean("safety-manager.anti-crasher.settings.debug");
if (!enabled) {
return;
}
if (!reload) {
try {
long bytes = new File(".").getCanonicalFile().getUsableSpace();
if (Main.config.getLong("safety-manager.no-space.startup-space") > bytes) {
Bukkit.getLogger().warning("NOT ENOUGH MEMORY TO START SERVER. SHUTTING DOWN.");
Bukkit.getServer().shutdown();
}
} catch (IOException e) {
e.printStackTrace();
}
// SafetyAnticrash.startTask();
startTask();
}
Bukkit.getLogger().info(" §e[§a✔§e] §fSafety Manager.");
}
public static void startTask() {
Bukkit.getScheduler().runTaskTimerAsynchronously(Main.p, new Runnable() {
@Override
public void run() {
long bytes;
try {
bytes = new File(".").getCanonicalFile().getUsableSpace();
if (Main.config.getLong("safety-manager.no-space.shutdown-space") < bytes) {
return;
}
Bukkit.getScheduler().scheduleSyncDelayedTask(Main.p, new Runnable() {
@Override
public void run() {
Bukkit.getLogger().warning(
"Server doesn't have enough memory to keep running. Shutting down server!");
Bukkit.getServer().shutdown();
}
}, 0L);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}, 60L, 1L);
}
}

322
src/cx/sfy/LagAssist/stacker/StackChunk.java

@ -0,0 +1,322 @@
package cx.sfy.LagAssist.stacker;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.Chunk;
import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.LivingEntity;
import org.bukkit.event.entity.EntityDeathEvent;
import org.bukkit.inventory.ItemStack;
import cx.sfy.LagAssist.Main;
import cx.sfy.LagAssist.utils.MathUtils;
import cx.sfy.LagAssist.utils.Others;
import cx.sfy.LagAssist.utils.WorldMgr;
public class StackChunk {
private static Map<Chunk, StackChunk> chunks = new HashMap<Chunk, StackChunk>();
public static String nameformat = "";
public static String regexpat = "";
private static int splits = 8;
private Map<EntityType, ArrayList<Entity>>[] ents;
public static void Enabler() {
splits = Main.config.getInt("smart-stacker.technical.splits");
nameformat = ChatColor.translateAlternateColorCodes('&',
Main.config.getString("smart-stacker.gameplay.tag-format"));
regexpat = nameformat.replace("{size}", "(.*.)");
}
@SuppressWarnings("unchecked")
public StackChunk(Chunk chk) {
ents = (Map<EntityType, ArrayList<Entity>>[]) new HashMap[256 / splits];
for (int i = 0; i < 256 / splits; i++) {
ents[i] = new HashMap<EntityType, ArrayList<Entity>>();
}
}
// Returns true if mob is consumed in the process, and false if the mob will be
// kept alive.
public static boolean tryStacking(Location loc, EntityType type, Entity optional) {
Chunk chk = loc.getChunk();
StackChunk stchk;
if (chunks.containsKey(chk)) {
stchk = chunks.get(chk);
} else {
stchk = new StackChunk(chk);
chunks.put(chk, stchk);
}
int split = getSplit(loc);
cleanSplit(chk, split, type);
boolean consumed = false;
int size = 0;
if (optional != null) {
if (!StackManager.isStackable(optional)) {
return false;
}
} else {
size++;
}
Entity free = getMatch(stchk.ents[split], loc, type, optional);
size += getStack(free);
Main.sendDebug("FINAL SIZE: " + size, 2);
consumed = (free.equals(optional)) ? false : true;
if (optional != null && consumed) {
size += getStack(optional);
}
Main.sendDebug("FINAL OPT: " + size, 2);
// if (stchk.ents[split].containsKey(type)) {
// free = stchk.ents[split].get(type);
// // Check if they are simmilar to avoid stacks of (for example) different color sheep.
// if (optional != null && !StackComparer.isSimilar(free, optional)) {
// return false;
// }
// size += getStack(free);
// consumed = true;
// } else if (optional != null) {
// free = optional;
// stchk.ents[split].put(type, optional);
// consumed = false;
// } else {
// free = loc.getWorld().spawnEntity(loc, type);
// consumed = true;
// }
// increase stack size due to new mob.
setSize(free, size);
return consumed;
}
private static Entity getMatch(Map<EntityType, ArrayList<Entity>> ents, Location loc, EntityType type,
Entity optional) {
if (!ents.containsKey(type)) {
ents.put(type, new ArrayList<Entity>());
}
List<Entity> list = ents.get(type);
Entity ideal = null;
if (optional == null) {
if (list.isEmpty()) {
ideal = loc.getWorld().spawnEntity(loc, type);
list.add(ideal);
return ideal;
} else {
return list.get(0);
}
}
for (Entity ent : list) {
boolean similar = StackComparer.isSimilar(ent, optional);
if (similar) {
return ent;
}
}
list.add(optional);
return optional;
}
public static int getStack(Entity ent) {
if (!StackManager.smartstacker) {
return 0;
}
if (ent == null) {
return 0;
}
String name = ent.getCustomName();
if (name == null) {
return 1;
}
Pattern pat = Pattern.compile(regexpat.replace("{type}", Others.firstHighcase(ent.getType().toString())),
Pattern.MULTILINE);
Matcher match = pat.matcher(name);
if (!match.find()) {
return -1;
}
String count = match.group(1);
if (!MathUtils.isInt(count)) {
return 1;
}
return Integer.valueOf(count);
}
public static void setSize(Entity ent, int size) {
String formatted = nameformat.replace("{type}", Others.firstHighcase(ent.getType().toString()))
.replace("{size}", "" + Math.min(size, Main.config.getInt("smart-stacker.technical.max-stack")));
ent.setCustomName(formatted);
ent.setCustomNameVisible(Main.config.getBoolean("smart-stacker.gameplay.tag-visibility"));
}
public static void setDrops(EntityDeathEvent e) {
Entity ent = e.getEntity();
// Clean in case it does and is main mob.
// int split =getSplit(loc);
// cleanSplit(chk, split, ent.getType(), true);
int stack = getStack(ent);
if (stack < 2) {
return;
}
List<ItemStack> drops = new ArrayList<ItemStack>();
for (ItemStack itm : e.getDrops()) {
int amount = itm.getAmount() * stack;
while (amount > 0) {
ItemStack cl = itm.clone();
cl.setAmount(Math.min(amount, cl.getMaxStackSize()));
amount -= cl.getAmount();
drops.add(cl);
}
}
e.getDrops().clear();
e.getDrops().addAll(drops);
e.setDroppedExp(e.getDroppedExp()*stack);
}
public static void runShutdown() {
if (!Main.config.getBoolean("smart-stacker.technical.shutdown-clean")) {
return;
}
for (StackChunk chk : chunks.values()) {
for (int i = 0; i < splits; i++) {
for (List<Entity> elist : chk.ents[i].values()) {
for (Entity ent : elist) {
ent.remove();
}
}
}
}
}
public static void runStart() {
if (Main.config.getBoolean("smarshot-stacker.technical.shutdown-clean")) {
return;
}
for (World w : Bukkit.getWorlds()) {
if (WorldMgr.isBlacklisted(w)) {
continue;
}
for (Chunk chk : w.getLoadedChunks()) {
loadChunk(chk);
}
}
}
public static void loadChunk(Chunk chk) {
Entity[] ents = chk.getEntities();
for (Entity ent : ents) {
if (!(ent instanceof LivingEntity)) {
continue;
}
if (StackChunk.tryStacking(ent.getLocation(), ent.getType(), ent)) {
ent.remove();
}
}
}
public static void unloadChunk(Chunk chk) {
StackChunk stack = chunks.get(chk);
if (stack == null) {
return;
}
for (Map<EntityType, ArrayList<Entity>> m : stack.ents) {
for (ArrayList<Entity> types : m.values()) {
for (Entity ent : types) {
ent.remove();
}
}
}
chunks.remove(chk);
}
// Setting clean to true makes it force it;
public static void cleanSplit(Chunk chk, int split, EntityType ent) {
if (!chunks.containsKey(chk)) {
return;
}
StackChunk stchk = chunks.get(chk);
if (!stchk.ents[split].containsKey(ent)) {
return;
}
boolean clean;
for (Entity entity : stchk.ents[split].get(ent)) {
clean = false;
if (entity == null || entity.isDead()) {
clean = true;
} else if (!entity.getLocation().getChunk().equals(chk)) {
clean = true;
} else if (getSplit(entity.getLocation()) != split) {
clean = true;
}
if (!clean) {
continue;
}
stchk.ents[split].remove(ent);
}
}
public static int getSplit(Location loc) {
return Math.max(0, Math.min(loc.getBlockY(), 255)) / splits;
}
}

195
src/cx/sfy/LagAssist/stacker/StackComparer.java

@ -0,0 +1,195 @@
package cx.sfy.LagAssist.stacker;
import java.util.ArrayList;
import java.util.List;
import org.bukkit.entity.AbstractHorse;
import org.bukkit.entity.Ageable;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Horse;
import org.bukkit.entity.Pig;
import org.bukkit.entity.Sheep;
import org.bukkit.entity.Slime;
import org.bukkit.entity.Tameable;
import org.bukkit.entity.Villager;
import cx.sfy.LagAssist.Main;
public class StackComparer {
private static List<EntityComparator> comparators = new ArrayList<EntityComparator>();
public static void Enabler(boolean reload) {
EntityComparator sheep = (ent1, ent2) -> {
if (ent1 instanceof Sheep && ent2 instanceof Sheep) {
Sheep s1 = (Sheep) ent1;
Sheep s2 = (Sheep) ent2;
if (s1.getColor() != s2.getColor()) {
return false;
}
if (s1.isSheared() != s2.isSheared()) {
return false;
}
}
return true;
};
EntityComparator slime = (ent1, ent2) -> {
if (ent1 instanceof Slime && ent2 instanceof Slime) {
Slime s1 = (Slime) ent1;
Slime s2 = (Slime) ent2;
if (s1.getSize() != s2.getSize()) {
return false;
}
}
return true;
};
EntityComparator pig = (ent1, ent2) -> {
if (ent1 instanceof Pig && ent2 instanceof Pig) {
Pig s1 = (Pig) ent1;
Pig s2 = (Pig) ent2;
// So no mountable pigs stack.
if (s1.hasSaddle() || s2.hasSaddle()) {
return false;
}
}
return true;
};
EntityComparator villager = (ent1, ent2) -> {
if (ent1 instanceof Villager && ent2 instanceof Villager) {
Villager s1 = (Villager) ent1;
Villager s2 = (Villager) ent2;
if (s1.getProfession() != s2.getProfession()) {
return false;
}
}
return true;
};
EntityComparator horse = (ent1, ent2) -> {
if (ent1 instanceof Horse && ent2 instanceof Horse) {
Horse s1 = (Horse) ent1;
Horse s2 = (Horse) ent2;
if (s1.getColor() != s2.getColor()) {
return false;
}
if (s2.getStyle() != s2.getStyle()) {
return false;
}
}
return true;
};
try {
EntityComparator abstracthorse = (ent1, ent2) -> {
if (ent1 instanceof AbstractHorse && ent2 instanceof AbstractHorse) {
AbstractHorse s1 = (AbstractHorse) ent1;
AbstractHorse s2 = (AbstractHorse) ent2;
if (s1.getDomestication() != s2.getDomestication()) {
return false;
}
if (s2.getJumpStrength() != s2.getJumpStrength()) {
return false;
}
}
return true;
};
comparators.add(abstracthorse);
} catch (Exception e) {
e.printStackTrace();
}
try {
EntityComparator ageable = (ent1, ent2) -> {
if (ent1 instanceof Ageable && ent2 instanceof Ageable) {
Ageable s1 = (Ageable) ent1;
Ageable s2 = (Ageable) ent2;
if (s1.isAdult() != s2.isAdult()) {
return false;
}
}
return true;
};
if (Main.config.getBoolean("smart-stacker.technical.comparison.ageable")) {
comparators.add(ageable);
}
} catch (Exception e) {
e.printStackTrace();
}
EntityComparator tameable = (ent1, ent2) -> {
if (ent1 instanceof Tameable && ent2 instanceof Tameable) {
Tameable s1 = (Tameable) ent1;
Tameable s2 = (Tameable) ent2;
if (s1.isTamed() != s2.isTamed()) {
return false;
}
}
return true;
};
comparators.clear();
if (Main.config.getBoolean("smart-stacker.technical.comparison.sheep")) {
comparators.add(sheep);
}
if (Main.config.getBoolean("smart-stacker.technical.comparison.pig")) {
comparators.add(pig);
}
if (Main.config.getBoolean("smart-stacker.technical.comparison.slime")) {
comparators.add(slime);
}
if (Main.config.getBoolean("smart-stacker.technical.comparison.villager")) {
comparators.add(villager);
}
if (Main.config.getBoolean("smart-stacker.technical.comparison.tameable")) {
comparators.add(tameable);
}
if (Main.config.getBoolean("smart-stacker.technical.comparison.horse")) {
comparators.add(horse);
}
}
public static boolean isSimilar(Entity ent1, Entity ent2) {
if (ent1 == null || ent2 == null) {
return false;
}
if (ent1.isDead() || ent2.isDead()) {
return false;
}
if (ent1.getType() != ent2.getType()) {
return false;
}
for (EntityComparator comp : comparators) {
if (!comp.isSimilar(ent1, ent2)) {
return false;
}
}
return true;
}
@FunctionalInterface
public interface EntityComparator {
public boolean isSimilar(Entity ent1, Entity ent2);
}
}

270
src/cx/sfy/LagAssist/stacker/StackManager.java

@ -0,0 +1,270 @@
package cx.sfy.LagAssist.stacker;
import java.util.EnumSet;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.bukkit.Bukkit;
import org.bukkit.Chunk;
import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.Player;
import org.bukkit.event.Cancellable;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.entity.EntityDeathEvent;
import org.bukkit.event.entity.EntitySpawnEvent;
import org.bukkit.event.inventory.PrepareAnvilEvent;
import org.bukkit.event.world.ChunkLoadEvent;
import org.bukkit.event.world.ChunkUnloadEvent;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import cx.sfy.LagAssist.Main;
import cx.sfy.LagAssist.stacker.StackMonitor.SplitChangeEvent;
import cx.sfy.LagAssist.utils.WorldMgr;
public class StackManager implements Listener {
protected static boolean smartstacker = false;
public static void Enabler(boolean reload) {
smartstacker = Main.config.getBoolean("smart-stacker.enabled");
if (!smartstacker) {
return;
}
StackChunk.Enabler();
StackMonitor.Enabler(reload);
StackComparer.Enabler(reload);
if (!reload) {
Main.p.getServer().getPluginManager().registerEvents(new StackManager(), Main.p);
Main.p.getServer().getPluginManager().registerEvents(new StackManipulator(), Main.p);
if (Main.paper) {
Main.p.getServer().getPluginManager().registerEvents(new PaperOnly(), Main.p);
}
}
StackChunk.runStart();
Bukkit.getLogger().info(" §e[§a✔§e] §fSmart Mob Stacker.");
}
public static boolean isStacked(Entity ent) {
return StackChunk.getStack(ent) > 1;
}
public static void Disabler() {
StackChunk.runShutdown();
}
@EventHandler(priority = EventPriority.HIGH)
public void onSpawn(EntitySpawnEvent e) {
if (e.isCancelled()) {
return;
}
if (!smartstacker) {
return;
}
if (WorldMgr.isBlacklisted(e.getLocation().getWorld())) {
return;
}
if(StackManipulator.isDeadEntity()) {
return;
}
if (!Main.config.getBoolean("smart-stacker.checks.spawn-check")) {
return;
}
Entity ent = e.getEntity();
// if (!(ent instanceof LivingEntity)) {
// return;
// }
if (StackChunk.tryStacking(ent.getLocation(), ent.getType(), ent)) {
e.setCancelled(true);
}
}
@EventHandler(priority = EventPriority.HIGH)
public void onDeath(EntityDeathEvent e) {
if (e instanceof Cancellable && ((Cancellable) e).isCancelled()) {
return;
}
if (!smartstacker) {
return;
}
if (!Main.config.getBoolean("smart-stacker.technical.drops-fix")) {
return;
}
StackChunk.setDrops(e);
}
private static class PaperOnly implements Listener {
// Ugly so it hopefully doesn't break.
@EventHandler(priority = EventPriority.HIGH)
public void onPreSpawn(com.destroystokyo.paper.event.entity.PreCreatureSpawnEvent e) {
if (e.isCancelled()) {
return;
}
if (!smartstacker) {
return;
}
if (WorldMgr.isBlacklisted(e.getSpawnLocation().getWorld())) {
return;
}
if(StackManipulator.isDeadEntity()) {
return;
}
if (!Main.config.getBoolean("smart-stacker.checks.pre-spawn-check")) {
return;
}
if (StackChunk.tryStacking(e.getSpawnLocation(), e.getType(), null)) {
e.setCancelled(true);
}
}
@EventHandler(priority = EventPriority.HIGH)
public void onAnvil(PrepareAnvilEvent e) {
if (!smartstacker) {
return;
}
ItemStack result = e.getResult();
if (result == null) {
return;
}
if (!result.hasItemMeta()) {
return;
}
ItemMeta imeta = result.getItemMeta();
if (!imeta.hasDisplayName()) {
return;
}
Pattern pat = Pattern.compile(StackChunk.regexpat.replace("{type}", "(.*.)"), Pattern.MULTILINE);
Matcher mtch = pat.matcher(imeta.getDisplayName());
if (!mtch.find()) {
return;
}
e.setResult(null);
}
}
private EnumSet<EntityType> illegal = EnumSet.of(EntityType.PLAYER);
@EventHandler(priority = EventPriority.HIGH)
public void onSplitChange(SplitChangeEvent e) {
if (!smartstacker) {
return;
}
if (!Main.config.getBoolean("smart-stacker.checks.split-change-check")) {
return;
}
if (WorldMgr.isBlacklisted(e.getFrom().getWorld())) {
return;
}
Entity ent = e.getEntity();
EntityType etype = ent.getType();
if (illegal.contains(etype)) {
return;
}
// Not a stackable entity.
// if (!(ent instanceof LivingEntity)) {
// return;
// }
StackChunk.cleanSplit(e.getFrom().getChunk(), StackChunk.getSplit(e.getFrom()), ent.getType());
if (StackChunk.tryStacking(e.getTo(), etype, ent)) {
ent.remove();
}
}
public void onChunkLoad(ChunkLoadEvent e) {
if (!smartstacker) {
return;
}
if (Main.config.getBoolean("smart-stacker.technical.shutdown-clean")) {
return;
}
if (WorldMgr.isBlacklisted(e.getWorld())) {
return;
}
Chunk chk = e.getChunk();
StackChunk.loadChunk(chk);
}
public void onChunkLoad(ChunkUnloadEvent e) {
if (!smartstacker) {
return;
}
if (WorldMgr.isBlacklisted(e.getWorld())) {
return;
}
Chunk chk = e.getChunk();
StackChunk.unloadChunk(chk);
}
public static boolean isStackable(Entity ent) {
if (ent == null) {
return false;
}
// if (!(ent instanceof LivingEntity)) {
// return false;
// }
if (ent instanceof Player) {
return false;
}
if (StackChunk.getStack(ent) < 0) {
return false;
}
if (!Main.config.getStringList("smart-stacker.gameplay.stackable").contains(ent.getType().toString().toUpperCase())) {
return false;
}
return true;
}
}

194
src/cx/sfy/LagAssist/stacker/StackManipulator.java

@ -0,0 +1,194 @@
package cx.sfy.LagAssist.stacker;
import org.bukkit.Location;
import org.bukkit.entity.Entity;
import org.bukkit.entity.LivingEntity;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.entity.EntityDamageByEntityEvent;
import org.bukkit.event.entity.EntityDamageEvent;
import org.bukkit.event.entity.EntityDamageEvent.DamageCause;
import cx.sfy.LagAssist.Main;
import cx.sfy.LagAssist.utils.VersionMgr;
public class StackManipulator implements Listener {
private static boolean deadentity = false;
protected static boolean isDeadEntity() {
return deadentity;
}
@EventHandler(priority=EventPriority.HIGHEST)
public void onDamage(EntityDamageEvent e) {
if (e.isCancelled()) {
return;
}
Entity eraw = e.getEntity();
if (!(eraw instanceof LivingEntity)) {
return;
}
LivingEntity ent = (LivingEntity) eraw;
int dmg = (int) getModifierDamage(e);
int maxhealth = (int) VersionMgr.getMaxHealth(ent);
int stack = StackChunk.getStack(ent);
// Not a stacked mob. We don't do anything on it.
if (stack < 2) {
return;
}
// Add damage dealt from before (in case it's not enough to kill).
dmg+=maxhealth-ent.getHealth();
int nextdamage = dmg % maxhealth;
int killed = dmg / maxhealth;
// Handled differently, so cancel damage event.
// Plugins shouldn't oof since it's on HIGHEST.
e.setDamage(0);
// Set health for this or next subject to account for dmg dealt.
ent.setHealth(maxhealth-nextdamage);
if (killed >= stack) {
killed = stack;
ent.setHealth(0);
return;
}
Entity damager = (e instanceof EntityDamageByEntityEvent) ? ((EntityDamageByEntityEvent) e).getDamager() : null;
if (killed > 0) {
spawnDeadEntity(ent.getLocation(), ent.getClass(), killed, damager);
}
StackChunk.setSize(ent, stack-killed);
}
private double getModifierDamage(EntityDamageEvent e) {
Entity eraw = e.getEntity();
int stack = StackChunk.getStack(eraw);
double initial = e.getFinalDamage();
DamageCause dc = e.getCause();
if (Main.config.getStringList("smart-stacker.technical.damage.multiply").contains(dc.toString().toUpperCase())) {
initial*=stack;
}
return initial;
}
private void spawnDeadEntity(Location loc, Class<? extends Entity> ent, int amount, Entity cause) {
deadentity = true;
LivingEntity spawned = (LivingEntity) loc.getWorld().spawn(loc, ent);
StackChunk.setSize(spawned, amount);
deadentity = false;
// if (spawned instanceof Damageable) {
// damage = spawned.getAttribute(Attribute.GENERIC_MAX_HEALTH).getBaseValue()+5;
// }
if (cause == null) {
spawned.damage(5000);
return;
}
spawned.damage(5000, cause);
}
// @EventHandler(priority=EventPriority.HIGHEST)
// public void onItemSpawn(ItemSpawnEvent e) {
// if (e.isCancelled()) {
// return;
// }
//
// Item ent = e.getEntity();
// ItemStack item = ent.getItemStack();
//
// runItemStacker(ent, item);
// }
//
// @EventHandler(priority=EventPriority.HIGHEST)
//
// public void onPlayerPickUp(PlayerPickupItemEvent e) {
// if (e.isCancelled()) {
// return;
// }
//
// if(runPickupAttempt(e.getItem(), e.getPlayer().getInventory())) {
// e.setCancelled(true);
// }
// }
//
// @EventHandler(priority=EventPriority.HIGHEST)
// public void onInventoryPickup(InventoryPickupItemEvent e) {
// if (e.isCancelled()) {
// return;
// }
//
// if(runPickupAttempt(e.getItem(), e.getInventory())) {
// e.setCancelled(true);
// }
// }
// private boolean runPickupAttempt(Item ent, Inventory inv) {
// ItemStack item = ent.getItemStack();
//
// int stack = StackChunk.getStack(ent);
//
//
// if (stack < 2) {
// return false;
// }
//
// int remaining = stack - item.getMaxStackSize();
//
// ItemStack adder = item.clone();
// adder.setAmount(remaining);
//
// Map<Integer, ItemStack> result = inv.addItem(adder);
//
// if (result.isEmpty()) {
//
// return false;
// }
//
// ItemStack fin = result.get(0);
// ent.setItemStack(fin);
// runItemStacker(ent, item);
// return true;
//
//
// }
// private static void runItemStacker(Item ent, ItemStack item) {
// if (item.getAmount() <= item.getMaxStackSize()) {
// return;
// }
//
// StackChunk.setSize(ent, item.getAmount());
// item.setAmount(item.getMaxStackSize());
//
// ent.setItemStack(item);
// }
}

286
src/cx/sfy/LagAssist/stacker/StackMonitor.java

@ -0,0 +1,286 @@
package cx.sfy.LagAssist.stacker;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.WeakHashMap;
import java.util.concurrent.CopyOnWriteArrayList;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.entity.Entity;
import org.bukkit.entity.HumanEntity;
import org.bukkit.entity.LivingEntity;
import org.bukkit.event.Event;
import org.bukkit.event.HandlerList;
import cx.sfy.LagAssist.Main;
public class StackMonitor {
private static Map<Entity, Location> entities = Collections.synchronizedMap(new WeakHashMap<Entity, Location>());
private static CopyOnWriteArrayList<SplitChangeEvent> events = new CopyOnWriteArrayList<SplitChangeEvent>();
public static void Enabler(boolean reload) {
if (!reload) {
runTask();
}
}
private static void runTask() {
// Synchronizer tool.
Bukkit.getScheduler().runTaskTimer(Main.p, () -> {
List<Entity> ents = new ArrayList<Entity>();
for (World w : Bukkit.getWorlds()) {
ents.addAll(w.getEntities());
}
// for (Entity ent : ents) {
// if (ent == null) {
// continue;
// }
//
// if (!(ent instanceof LivingEntity)) {
// continue;
// }
//
// if (ent instanceof HumanEntity) {
// continue;
// }
//
// Location old = null;
// if (entities.containsKey(ent)) {
// old = entities.get(ent);
// }
// Location loc = ent.getLocation();
//
// if (loc.equals(old)) {
// continue;
// }
//
// entities.put(ent, loc);
//
// if (!runMove(old, loc)) {
// continue;
// }
//
// events.add(new SplitChangeEvent(ent, old, loc));
//
// for (SplitChangeEvent event : events) {
// Bukkit.getPluginManager().callEvent(event);
// }
// events.clear();
// }
Bukkit.getScheduler().runTaskAsynchronously(Main.p, () -> {
for (Entity ent : ents) {
if (ent == null) {
continue;
}
if (!(ent instanceof LivingEntity)) {
continue;
}
if (ent instanceof HumanEntity) {
continue;
}
Location old = null;
if (entities.containsKey(ent)) {
old = entities.get(ent);
}
Location loc = ent.getLocation();
if (loc.equals(old)) {
continue;
}
entities.put(ent, loc);
if (!runMove(old, loc)) {
continue;
}
events.add(new SplitChangeEvent(ent, old, loc));
}
});
for (SplitChangeEvent event : events) {
Bukkit.getPluginManager().callEvent(event);
}
events.clear();
}, 5, 5);
// Creator tool.
}
public static boolean runMove(Location from, Location to) {
if (!Main.config.getBoolean("smart-stacker.checks.split-change-check")) {
return false;
}
if (from == null || to == null) {
return false;
}
from = from.clone();
to = to.clone();
// if (!from.getWorld().getName().equals(to.getWorld().getName())) {
// return true;
// }
// int fromx = from.getBlockX() / 16;
// int tox = to.getBlockX() / 16;
//
// int fromz = from.getBlockZ() / 16;
// int toz = to.getBlockZ() / 16;
//
//
// if (fromx != tox) {
// return true;
// }
//
// if (fromz != toz) {
// return true;
// }
// Chunk chk = to.getChunk();
//
// if (chk == null) {
// return false;
// }
//
// if (!chk.isLoaded()) {
// return false;
// }
// Chunk chk1 = from.getChunk();
// Chunk chk2 = to.getChunk();
// if (!chk1.equals(chk2)) {
// return true;
// }
// int sp1 = StackChunk.getSplit(from);
// int sp2 = StackChunk.getSplit(to);
return new Split(from).equals(new Split(to));
}
public static class Split {
private String world;
private int x;
private int z;
private int split;
public Split(Location loc) {
setWorld(loc.getWorld().getName());
setX(loc.getBlockX() / 16);
setZ(loc.getBlockZ() / 16);
setSplit(StackChunk.getSplit(loc));
}
public int getSplit() {
return split;
}
public void setSplit(int split) {
this.split = split;
}
public int getZ() {
return z;
}
public void setZ(int z) {
this.z = z;
}
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public String getWorld() {
return world;
}
public void setWorld(String world) {
this.world = world;
}
public boolean equals(Split other) {
if (getX() != other.getX()) {
// System.out.println("X NOT SAME");
return false;
}
if (getZ() != other.getZ()) {
// System.out.println("Z NOT SAME");
return false;
}
if (getSplit() != other.getSplit()) {
// System.out.println("SPLIT NOT SAME");
return false;
}
if (!getWorld().equalsIgnoreCase(other.getWorld())) {
// System.out.println("WORLD NOT SAME");
return false;
}
return true;
}
}
public static class SplitChangeEvent extends Event {
private static final HandlerList HANDLERS = new HandlerList();
private Entity ent;
private Location from;
private Location to;
public SplitChangeEvent(Entity ent, Location from, Location to) {
this.ent = ent;
this.from = from;
this.to = to;
}
public HandlerList getHandlers() {
return HANDLERS;
}
public static HandlerList getHandlerList() {
return HANDLERS;
}
public Entity getEntity() {
return ent;
}
public Location getFrom() {
return from;
}
public Location getTo() {
return to;
}
}
}

13
src/cx/sfy/LagAssist/stacker/StackSpawners.java

@ -0,0 +1,13 @@
package cx.sfy.LagAssist.stacker;
import java.util.regex.Pattern;
public class StackSpawners {
public static Pattern itemformat;
public static void Enabler(boolean reload) {
}
}

19
src/cx/sfy/LagAssist/superloader/SuperMain.java

@ -0,0 +1,19 @@
package cx.sfy.LagAssist.superloader;
import org.bukkit.Bukkit;
import cx.sfy.LagAssist.Main;
public class SuperMain {
public static void Enabler(boolean reload) {
if (!Main.config.getBoolean("super-loader.enabled")) {
return;
}
Bukkit.getLogger().info(" §e[§a✔§e] §fSuperLoader.");
}
}

190
src/cx/sfy/LagAssist/updater/SmartUpdater.java

@ -0,0 +1,190 @@
package cx.sfy.LagAssist.updater;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.stream.Collectors;
import org.bukkit.Bukkit;
import org.bukkit.command.CommandSender;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.json.simple.JSONValue;
import cx.sfy.LagAssist.Main;
public class SmartUpdater {
private static String updatesurl = "https://api.spiget.org/v2/resources/56399/updates?size=15&sort=-date";
private static String versionurl = "https://api.spiget.org/v2/resources/56399/versions?size=15&sort=-releaseDate";
public static UpdateInfo ui = null;
public static void Enabler() {
if (!Main.config.getBoolean("smart-updater.enabled")) {
return;
}
UpdateCondition.Enabler();
Bukkit.getScheduler().runTaskAsynchronously(Main.p, new Runnable() {
@Override
public void run() {
ui = getNextUpdate();
if (ui == null) {
Bukkit.getLogger().info("§c§lLag§f§lAssist §e» §fYou are up to date with LagAssist.");
return;
}
Bukkit.getLogger().info("§c§lLag§f§lAssist §e» §fWe found a newer LagAssist version:");
if (ui.isUnsafe()) {
Bukkit.getLogger().warning("§c§lLag§f§lAssist §e» §fThis version is considered Unsafe!");
}
Bukkit.getLogger().info(" §c[§e֍§c] §fVersion: " + ui.getVersion());
Bukkit.getLogger().info(" §c[§e֍§c] §fReviews: " + ((int) (ui.getRating() * 100)) / 100f + "§e★");
Bukkit.getLogger().info(" §c[§e֍§c] §fDownloads: " + ui.getDownloads());
Bukkit.getLogger().info(" §c[§e֍§c] §fFor more info, use §c/lagassist changelog");
}
});
}
private static UpdateInfo getNextUpdate() {
try {
URL uurl = new URL(updatesurl);
URL vurl = new URL(versionurl);
JSONArray updateData = getWebData(uurl);
JSONArray versionData = getWebData(vurl);
if (updateData == null) {
return null;
}
if (versionData == null) {
return null;
}
Map<Long, UpdateInfo> updates = new HashMap<Long, UpdateInfo>();
Map<Long, UpdateInfo> filteredupdates = new HashMap<Long, UpdateInfo>();
// GET all update posts (update messages, etc) and create a rudimentary
// UpdateInfo.
for (int i = 0; i < updateData.size(); i++) {
JSONObject obj = (JSONObject) updateData.get(i);
String title = (String) obj.get("title");
String description = (java.lang.String) obj.get("description");
long date = (long) obj.get("date");
long likes = (long) obj.get("likes");
UpdateInfo up = new UpdateInfo();
up.setTitle(title);
up.setDescription(description);
up.setDate(date);
up.setLikes((int) likes);
updates.put(date, up);
}
// Fill UpdateInfo with reviews and other useful information.
for (int i = 0; i < versionData.size(); i++) {
JSONObject obj = (JSONObject) versionData.get(i);
long date = (long) obj.get("releaseDate");
if (!updates.containsKey(date)) {
continue;
}
String version = (String) obj.get("name");
long downloads = (long) obj.get("downloads");
double rating = Double.valueOf(String.valueOf(((JSONObject) obj.get("rating")).get("average")));
long id = (long) obj.get("id");
UpdateInfo up = updates.get(date);
up.setId(id);
up.setVersion(version);
up.setRating((int) rating);
up.setDownloads((int) downloads);
filteredupdates.put(date, up);
}
// Sort map and do other juicy stuff.
LinkedHashMap<Long, UpdateInfo> sorted = filteredupdates.entrySet().stream()
.sorted(Collections.reverseOrder(Map.Entry.comparingByKey()))
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (oldValue, newValue) -> oldValue,
LinkedHashMap::new));
for (long key : sorted.keySet()) {
UpdateInfo up = updates.get(key);
if (UpdateCondition.shouldUpgrade(up)) {
return up;
}
}
} catch (Exception e) {
e.printStackTrace();
Bukkit.getLogger().warning("§e[§a✖§e] §fCouldn't recognize Update data.");
}
return null;
}
private static JSONArray getWebData(URL u) {
InputStream is;
try {
is = u.openStream();
return (JSONArray) JSONValue.parse(new InputStreamReader(is));
} catch (IOException e) {
Bukkit.getLogger().warning("§e[§a✖§e] §fCouldn't connect to Update Data.");
}
return null;
}
private static String getFormattedDesc() {
if (ui == null) {
return null;
}
return ui.getDescription().substring(0, Math.min(ui.getDescription().length(), 1000)).replace('\n', ' ');
}
public static void showChangelog(CommandSender s) {
if (ui == null) {
s.sendMessage("§c§lLag§f§lAssist §e» §fThere is no new recommended version available.");
return;
}
String formatdesc = getFormattedDesc();
s.sendMessage("§c§l⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛§f§l LAGASSIST CHANGELOG §c§l⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛");
s.sendMessage("");
s.sendMessage(" §c✸ §fNew Version: §e" + ui.getVersion());
s.sendMessage("");
s.sendMessage(" §c✸ §fTitle:");
s.sendMessage(" §e" + ui.getTitle());
s.sendMessage("");
s.sendMessage(" §c✸ §fDescription:");
s.sendMessage(" §e" + formatdesc);
s.sendMessage("");
s.sendMessage(" §c✸ §fRating: §e" + ui.getRating() + "★");
s.sendMessage(" §c✸ §fDownloads: §e" + ui.getDownloads());
s.sendMessage(" §c✸ §fLikes: §e" + ui.getLikes());
s.sendMessage("");
s.sendMessage("§c§l⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛");
}
}

55
src/cx/sfy/LagAssist/updater/UpdateCondition.java

@ -0,0 +1,55 @@
package cx.sfy.LagAssist.updater;
import cx.sfy.LagAssist.Main;
public class UpdateCondition {
private static int mindownloads = 0;
private static int minlikes = 0;
private static float minrating = 0;
private static boolean unsafe = true;
private static VersionComparator vc = new VersionComparator();
public static void Enabler() {
unsafe = Main.config.getBoolean("smart-updater.announce.unsafe");
minlikes = Main.config.getInt("smart-updater.announce.min-likes");
mindownloads = Main.config.getInt("smart-updater.announce.min-downloads");
minrating = (float) Main.config.getDouble("smart-updater.announce.min-rating");
}
public static boolean shouldUpgrade(UpdateInfo info) {
if (info.isUnsafe() && !unsafe) {
return false;
}
String currentver = Main.p.getDescription().getVersion();
String newver = info.getVersion();
if (newver == null || currentver == null) {
return false;
}
if (vc.compare(currentver, newver) > 0) {
return false;
}
if (info.getLikes() < minlikes) {
return false;
}
if (info.getDownloads() < mindownloads) {
return false;
}
if (info.getRating() < minrating) {
return false;
}
return true;
}
}

124
src/cx/sfy/LagAssist/updater/UpdateInfo.java

@ -0,0 +1,124 @@
package cx.sfy.LagAssist.updater;
import java.util.Base64;
public class UpdateInfo {
// INFO HOLDERS
private String title;
private String description;
// IDENTIFIERS
private String version;
private long date;
private long id;
private boolean unsafe = false;
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = html2text(new String(Base64.getDecoder().decode(description)));
;
}
public String getVersion() {
return version;
}
public void setVersion(String version) {
this.version = version;
}
public long getDate() {
return date;
}
public void setDate(long date) {
this.date = date;
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public int getLikes() {
return likes;
}
public void setLikes(int likes) {
this.likes = likes;
}
public int getDownloads() {
return downloads;
}
public void setDownloads(int downloads) {
this.downloads = downloads;
}
public float getRating() {
return rating;
}
public void setRating(int rating) {
this.rating = rating;
}
// UPDATE QUALITY DATA
private int likes;
private int downloads;
private int rating;
public UpdateInfo() {
}
private static String html2text(String html) {
return html.replaceAll("\\<[^>]*>", "");
}
public UpdateInfo(String title, String description, String version, long date, int id, int likes, int downloads,
int rating) {
// Show all the data required for analysis by the plugin.
this.title = title;
this.description = html2text(new String(Base64.getDecoder().decode(description)));
this.version = version;
this.date = date;
this.id = id;
// Data required for analysing databastanagaur.
this.likes = likes;
this.downloads = downloads;
if (rating == 0) {
rating = 5;
}
this.rating = rating;
// Check if it is unsafe
if (this.description.contains("(!) UNSAFE VERSION")) {
unsafe = true;
}
}
public boolean isUnsafe() {
return unsafe;
}
}

137
src/cx/sfy/LagAssist/updater/VersionComparator.java

@ -0,0 +1,137 @@
package cx.sfy.LagAssist.updater;
import java.util.Comparator;
public class VersionComparator implements Comparator<String> {
public boolean equals(String version1, String version2) {
return compare(version1, version2) == 0;
}
@Override
public int compare(String version1, String version2) {
VersionTokenizer tokenizer1 = new VersionTokenizer(version1);
VersionTokenizer tokenizer2 = new VersionTokenizer(version2);
int number1 = 0, number2 = 0;
String suffix1 = "", suffix2 = "";
while (tokenizer1.MoveNext()) {
if (!tokenizer2.MoveNext()) {
do {
number1 = tokenizer1.getNumber();
suffix1 = tokenizer1.getSuffix();
if (number1 != 0 || suffix1.length() != 0) {
// Version one is longer than number two, and non-zero
return 1;
}
} while (tokenizer1.MoveNext());
// Version one is longer than version two, but zero
return 0;
}
number1 = tokenizer1.getNumber();
suffix1 = tokenizer1.getSuffix();
number2 = tokenizer2.getNumber();
suffix2 = tokenizer2.getSuffix();
if (number1 < number2) {
// Number one is less than number two
return -1;
}
if (number1 > number2) {
// Number one is greater than number two
return 1;
}
boolean empty1 = suffix1.length() == 0;
boolean empty2 = suffix2.length() == 0;
if (empty1 && empty2)
continue; // No suffixes
if (empty1)
return 1; // First suffix is empty (1.2 > 1.2b)
if (empty2)
return -1; // Second suffix is empty (1.2a < 1.2)
// Lexical comparison of suffixes
int result = suffix1.compareTo(suffix2);
if (result != 0)
return result;
}
if (tokenizer2.MoveNext()) {
do {
number2 = tokenizer2.getNumber();
suffix2 = tokenizer2.getSuffix();
if (number2 != 0 || suffix2.length() != 0) {
// Version one is longer than version two, and non-zero
return -1;
}
} while (tokenizer2.MoveNext());
// Version two is longer than version one, but zero
return 0;
}
return 0;
}
private class VersionTokenizer {
private final String _versionString;
private final int _length;
private int _position;
private int _number;
private String _suffix;
public int getNumber() {
return _number;
}
public String getSuffix() {
return _suffix;
}
public VersionTokenizer(String versionString) {
if (versionString == null)
throw new IllegalArgumentException("versionString is null");
_versionString = versionString;
_length = versionString.length();
}
public boolean MoveNext() {
_number = 0;
_suffix = "";
// No more characters
if (_position >= _length)
return false;
while (_position < _length) {
char c = _versionString.charAt(_position);
if (c < '0' || c > '9')
break;
_number = _number * 10 + (c - '0');
_position++;
}
int suffixStart = _position;
while (_position < _length) {
char c = _versionString.charAt(_position);
if (c == '.')
break;
_position++;
}
_suffix = _versionString.substring(suffixStart, _position);
if (_position < _length)
_position++;
return true;
}
}
}

72
src/cx/sfy/LagAssist/utils/Cache.java

@ -0,0 +1,72 @@
package cx.sfy.LagAssist.utils;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
public class Cache<S, T> {
protected class Cachebox {
protected T cached;
protected int time;
protected Cachebox(T cached, int time) {
this.cached = cached;
this.time = time;
}
protected boolean tick() {
time--;
return time <= 0;
}
}
private int cachetime;
private Map<S, Cachebox> cachestorage = new HashMap<S, Cachebox>();
public Cache(int cachetime) {
this.cachetime = cachetime;
}
public void putCached(S key, T cached) {
cachestorage.put(key, new Cachebox(cached, cachetime));
}
public boolean isCached(S key) {
return cachestorage.containsKey(key);
}
public T getCached(S key) {
if (isCached(key)) {
return cachestorage.get(key).cached;
}
return null;
}
public void tick() {
Set<S> removables = new HashSet<S>();
for (S key : cachestorage.keySet()) {
Cachebox box = cachestorage.get(key);
if (!box.tick()) {
continue;
}
removables.add(key);
}
cachestorage.keySet().removeAll(removables);
}
public void clear() {
cachestorage.clear();
}
public boolean remove(S key) {
return cachestorage.remove(key) != null;
}
}

34
src/cx/sfy/LagAssist/utils/Chat.java

@ -0,0 +1,34 @@
package cx.sfy.LagAssist.utils;
import net.md_5.bungee.api.chat.ClickEvent;
import net.md_5.bungee.api.chat.ComponentBuilder;
import net.md_5.bungee.api.chat.HoverEvent;
import net.md_5.bungee.api.chat.TextComponent;
public class Chat {
public static TextComponent genHoverAndSuggestTextComponent(String show, String hover, String click) {
TextComponent msg = new TextComponent(show);
msg.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new ComponentBuilder(hover).create()));
msg.setClickEvent(new ClickEvent(ClickEvent.Action.SUGGEST_COMMAND, "/" + click));
return msg;
}
public static TextComponent genHoverAndRunCommandTextComponent(String show, String hover, String click) {
TextComponent msg = new TextComponent(show);
msg.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new ComponentBuilder(hover).create()));
msg.setClickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/" + click));
return msg;
}
public static TextComponent genHoverTextComponent(String show, String hover) {
TextComponent msg = new TextComponent(show);
msg.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new ComponentBuilder(hover).create()));
return msg;
}
public static String capitalize(String stg) {
return stg.substring(0, 1).toUpperCase() + stg.substring(1);
}
}

65
src/cx/sfy/LagAssist/utils/MathUtils.java

@ -0,0 +1,65 @@
package cx.sfy.LagAssist.utils;
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.IntBuffer;
import java.util.List;
public class MathUtils {
public static int toMegaByte(long bytes) {
return (int) (bytes / 1048576);
}
public static boolean isInt(String str) {
try {
int d = Integer.parseInt(str);
d = d + 1;
} catch (NumberFormatException nfe) {
return false;
}
return true;
}
public static byte[] integersToBytes(List<Integer> values, int length) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
DataOutputStream wrt = new DataOutputStream(baos);
try {
for (int i : values) {
wrt.writeInt(i);
}
wrt.flush();
wrt.close();
} catch (IOException e) {
e.printStackTrace();
}
byte[] good = new byte[length];
System.arraycopy(baos.toByteArray(), 0, good, 0, length);
return good;
}
public static int[] bytesToIntegers(byte[] raw) {
int rst = raw.length % 4;
byte[] bts = new byte[raw.length + 4 - rst];
System.arraycopy(raw, 0, bts, 0, raw.length);
IntBuffer intBuf = ByteBuffer.wrap(bts).order(ByteOrder.BIG_ENDIAN).asIntBuffer();
int[] pixels = new int[intBuf.remaining()];
intBuf.get(pixels);
return pixels;
}
}

102
src/cx/sfy/LagAssist/utils/Others.java

@ -0,0 +1,102 @@
package cx.sfy.LagAssist.utils;
import java.io.BufferedInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import org.apache.commons.lang.RandomStringUtils;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.WorldBorder;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.entity.Item;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.PlayerInventory;
import cx.sfy.LagAssist.Main;
public class Others {
public static boolean isInsideBorder(Location loc) {
WorldBorder border = loc.getWorld().getWorldBorder();
double radius = border.getSize() / 2;
Location location = loc, center = border.getCenter();
return center.distanceSquared(location) < (radius * radius);
}
public static YamlConfiguration getConfig(File f, int version) {
YamlConfiguration fc = new YamlConfiguration();
if (!f.exists()) {
f.getParentFile().mkdirs();
Main.p.saveResource(f.getName(), false);
}
try {
fc.load(f);
if (fc.contains("version")) {
if (fc.getInt("version") != version) {
Bukkit.getLogger().info("�c�lLag�f�lAssist �e� �fUpdating " + f.getName() + " file!");
f.renameTo(getOldFile(f));
Main.p.saveResource(f.getName(), false);
fc.load(f);
}
} else {
Bukkit.getLogger().info("�c�lLag�f�lAssist �e� �fUpdating " + f.getName() + " file!");
f.renameTo(getOldFile(f));
Main.p.saveResource(f.getName(), false);
fc.load(f);
}
} catch (Exception e) {
e.printStackTrace();
}
return fc;
}
private static File getOldFile(File f) {
return new File(f.getParentFile(), f.getName() + "." + RandomStringUtils.randomAlphanumeric(3) + ".old");
}
public static String readInputStreamAsString(InputStream in) {
try {
BufferedInputStream bis = new BufferedInputStream(in);
ByteArrayOutputStream buf = new ByteArrayOutputStream();
int result = bis.read();
while (result != -1) {
byte b = (byte) result;
buf.write(b);
result = bis.read();
}
return buf.toString();
} catch (IOException e) {
return null;
}
}
public static String firstHighcase(String stg) {
String nw = stg.toLowerCase();
return nw.substring(0, 1).toUpperCase() + nw.substring(1);
}
public static Item giveOrDrop(Player p, ItemStack itm) {
PlayerInventory pinv = p.getInventory();
if (pinv.firstEmpty() != 1) {
pinv.addItem(itm);
return null;
}
return p.getLocation().getWorld().dropItem(p.getLocation(), itm);
}
}

61
src/cx/sfy/LagAssist/utils/PaperOnly.java

@ -0,0 +1,61 @@
package cx.sfy.LagAssist.utils;
import org.bukkit.Chunk;
import org.bukkit.World;
import org.bukkit.World.ChunkLoadCallback;
import org.bukkit.entity.ArmorStand;
import org.bukkit.entity.Player;
import cx.sfy.LagAssist.Main;
@SuppressWarnings("deprecation")
public class PaperOnly {
public static void freezeArmorstand(ArmorStand arm) {
arm.setCanMove(false);
}
public static void setViewDistance(Player p, int view) {
ViewDistance.setPerViewDistance(p, view);
}
public static void setViewDistance(World w, int view) {
if (VersionMgr.isNewMaterials()) {
V1_13.setViewDistance(w, view);
} else {
ViewDistance.setViewDistance(w, view);
}
}
public static void loadChunkAsync(World world, int x, int z) {
world.getChunkAtAsync(x, z, new ChunkLoadCallback() {
@Override
public void onLoad(Chunk chk) {
chk.unload();
}
});
}
public static class ViewDistance {
public static void setPerViewDistance(Player p, int amount) {
p.setViewDistance(amount);
Main.sendDebug("Set viewdistance to " + p.getName() + " to " + amount, 1);
}
public static void setViewDistance(World w, int amount) {
Main.sendDebug("Attempting to set view distance on players in world " + w.getName(), 1);
for (Player p : w.getPlayers()) {
if (p.getViewDistance() == amount) {
continue;
}
p.setViewDistance(amount);
setPerViewDistance(p, amount);
}
}
}
}

87
src/cx/sfy/LagAssist/utils/V1_11.java

@ -0,0 +1,87 @@
package cx.sfy.LagAssist.utils;
import java.util.HashMap;
import java.util.Map;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
import org.bukkit.material.Observer;
import cx.sfy.LagAssist.Main;
public class V1_11 {
public static Map<Block, Integer> removable = new HashMap<Block, Integer>();
public static void ObserverAdd(Block b) {
if (b.getType().equals(Material.OBSERVER)) {
if (removable.containsKey(b)) {
removable.put(b, removable.get(b) + 1);
} else {
removable.put(b, 1);
}
}
}
public static void ObserverBreaker() {
int min = Main.config.getInt("redstone-culler.destructive.value");
for (Block bs : removable.keySet()) {
if (removable.get(bs) > min) {
bs.setType(Material.AIR);
}
}
removable.clear();
}
public static BlockFace getFace(Block b) {
Observer obs = (Observer) b.getState().getData();
return obs.getFacing();
}
// public static void ObserverFix(Block b) {
// if (b.getType().equals(Material.OBSERVER)) {
// MaterialData md = b.getState().getData();
// if (!(md instanceof Observer)) {
// return;
// }
// Observer orw = (Observer) md;
// BlockFace bf = orw.getFacing();
// b.setType(Material.OBSERVER);
// BlockState bstate = b.getState();
// Observer bs = (Observer) bstate.getData();
// bs.setFacingDirection(bf);
// bstate.update();
// System.out.println(bs.isPowered());
// if (!Main.config.getBoolean("redstone-culler.destructive")) {
// return;
// }
// Block b1 = b.getLocation().add(0, -1, 0).getBlock();
// Block b2 = b.getLocation().add(0, -2, 0).getBlock();
// Block b3 = b.getLocation().add(0, -3, 0).getBlock();
// Block b4 = b.getLocation().add(0, 1, 0).getBlock();
// Block b5 = b.getLocation().add(0, 2, 0).getBlock();
// Block b6 = b.getLocation().add(0, 3, 0).getBlock();
// if (b1.getType().equals(Material.OBSERVER) &&
// b2.getType().equals(Material.OBSERVER)) {
// b1.setType(Material.STONE);
// b2.setType(Material.STONE);
// b3.setType(Material.STONE);
// }
// if (b4.getType().equals(Material.OBSERVER) &&
// b5.getType().equals(Material.OBSERVER)) {
// b4.setType(Material.STONE);
// b5.setType(Material.STONE);
// b6.setType(Material.STONE);
// }
// }
// }
public static boolean isObserver(Block b) {
if (b.getType().equals(Material.OBSERVER)) {
return true;
}
return false;
}
}

74
src/cx/sfy/LagAssist/utils/V1_12.java

@ -0,0 +1,74 @@
package cx.sfy.LagAssist.utils;
import org.bukkit.Material;
import org.bukkit.block.CreatureSpawner;
import org.bukkit.block.Hopper;
import org.bukkit.inventory.ItemStack;
import cx.sfy.LagAssist.Data;
@SuppressWarnings("deprecation")
public class V1_12 {
public static ItemStack[] getStatics() {
Material pane = Material.getMaterial("STAINED_GLASS_PANE");
ItemStack[] pnes = new ItemStack[19];
pnes[0] = new ItemStack(pane, 1, (short) 5);
pnes[1] = new ItemStack(pane, 1, (short) 10);
pnes[2] = new ItemStack(pane, 1, (short) 4);
pnes[3] = new ItemStack(pane, 1, (short) 14);
pnes[4] = new ItemStack(Material.getMaterial("COMMAND"), 1);
pnes[5] = new ItemStack(Material.getMaterial("MAP"), 1);
pnes[6] = new ItemStack(Material.getMaterial("GRASS"), 1);
pnes[7] = new ItemStack(Material.getMaterial("SOUL_SAND"), 1);
pnes[8] = new ItemStack(Material.getMaterial("PISTON_BASE"), 1);
pnes[9] = new ItemStack(Material.getMaterial("REDSTONE_BLOCK"), 1);
pnes[10] = new ItemStack(Material.getMaterial("EMERALD_ORE"), 1);
pnes[11] = new ItemStack(Material.getMaterial("MOB_SPAWNER"), 1);
pnes[12] = new ItemStack(Material.getMaterial("SEA_LANTERN"), 1);
pnes[13] = new ItemStack(Material.getMaterial("TNT"), 1);
pnes[14] = new ItemStack(Material.getMaterial("SAND"), 1);
pnes[15] = new ItemStack(Material.getMaterial("PUMPKIN_SEEDS"), 1);
pnes[16] = new ItemStack(Material.getMaterial("PISTON_BASE"), 1);
pnes[17] = new ItemStack(Material.getMaterial("REDSTONE_BLOCK"), 1);
pnes[18] = new ItemStack(Material.getMaterial("EMERALD_BLOCK"), 1);
return pnes;
}
public static ItemStack getLagMap() {
return new ItemStack(Material.getMaterial("MAP"), 1, Data.getMapId());
}
public static int getMapId(ItemStack s) {
return s.getDurability();
}
public static boolean modifySpawner(CreatureSpawner cs, int spawncount, int spawnrange, int playerrange) {
boolean changed = false;
if (cs.getRequiredPlayerRange() != playerrange) {
cs.setRequiredPlayerRange(playerrange);
changed = true;
}
if (cs.getSpawnCount() != spawncount) {
cs.setSpawnCount(spawncount);
changed = true;
}
if (cs.getSpawnRange() != spawnrange) {
cs.setSpawnRange(spawnrange);
changed = true;
}
return changed;
}
public static String getHopperName(Hopper h) {
return h.getCustomName() == null ? "container.hopper" : h.getCustomName();
}
}

90
src/cx/sfy/LagAssist/utils/V1_13.java

@ -0,0 +1,90 @@
package cx.sfy.LagAssist.utils;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.entity.Entity;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.loot.LootContext;
import org.bukkit.loot.LootTables;
import cx.sfy.LagAssist.Data;
import cx.sfy.LagAssist.packets.Reflection;
public class V1_13 {
private static Random r = new Random();
public static ItemStack getLagMap() {
ItemStack map = new ItemStack(Material.getMaterial("FILLED_MAP"), 1);
Reflection.setmapId(map, Data.getMapId());
return map;
}
public static ItemStack[] getStatics() {
ItemStack[] pnes = new ItemStack[19];
pnes[0] = new ItemStack(Material.getMaterial("LIME_STAINED_GLASS_PANE"));
pnes[1] = new ItemStack(Material.getMaterial("MAGENTA_STAINED_GLASS_PANE"));
pnes[2] = new ItemStack(Material.getMaterial("YELLOW_STAINED_GLASS_PANE"));
pnes[3] = new ItemStack(Material.getMaterial("RED_STAINED_GLASS_PANE"));
pnes[4] = new ItemStack(Material.getMaterial("COMMAND_BLOCK"), 1);
pnes[5] = new ItemStack(Material.getMaterial("FILLED_MAP"), 1);
pnes[6] = new ItemStack(Material.getMaterial("GRASS"), 1);
pnes[7] = new ItemStack(Material.getMaterial("SOUL_SAND"), 1);
pnes[8] = new ItemStack(Material.getMaterial("PISTON"), 1);
pnes[9] = new ItemStack(Material.getMaterial("REDSTONE_BLOCK"), 1);
pnes[10] = new ItemStack(Material.getMaterial("EMERALD_BLOCK"), 1);
pnes[11] = new ItemStack(Material.getMaterial("SPAWNER"), 1);
pnes[12] = new ItemStack(Material.getMaterial("SEA_LANTERN"), 1);
pnes[13] = new ItemStack(Material.getMaterial("TNT"), 1);
pnes[14] = new ItemStack(Material.getMaterial("SAND"), 1);
pnes[15] = new ItemStack(Material.getMaterial("PUMPKIN_SEEDS"), 1);
pnes[16] = new ItemStack(Material.getMaterial("PISTON"), 1);
pnes[17] = new ItemStack(Material.getMaterial("REDSTONE_BLOCK"), 1);
pnes[18] = new ItemStack(Material.getMaterial("EMERALD_BLOCK"), 1);
return pnes;
}
public static int getMapId(ItemStack s) {
return Reflection.getMapId(s);
}
public static boolean isChunkGenerated(World w, int x, int z) {
return w.isChunkGenerated(x, z);
}
public static List<ItemStack> getLootTable(Entity ent) {
LootTables lt = LootTables.valueOf(ent.getType().toString());
List<ItemStack> itms = new ArrayList<ItemStack>();
if (lt == null) {
return itms;
}
itms.addAll(lt.getLootTable().populateLoot(r, new LootContext.Builder(ent.getLocation()).build()));
return itms;
}
public static Object setUnbreakable(ItemMeta imeta, boolean unbreakable) {
imeta.setUnbreakable(unbreakable);
return null;
}
public static boolean isUnbreakable(ItemMeta imeta) {
return imeta.isUnbreakable();
}
public static void setViewDistance(World w, int amount) {
Reflection.setViewDistance(w, amount);
}
}

64
src/cx/sfy/LagAssist/utils/V1_8.java

@ -0,0 +1,64 @@
package cx.sfy.LagAssist.utils;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import org.bukkit.block.Hopper;
import org.bukkit.craftbukkit.v1_8_R3.entity.CraftPlayer;
import org.bukkit.entity.Player;
import org.bukkit.inventory.meta.ItemMeta;
import cx.sfy.LagAssist.Main;
import net.minecraft.server.v1_8_R3.IChatBaseComponent;
import net.minecraft.server.v1_8_R3.IChatBaseComponent.ChatSerializer;
import net.minecraft.server.v1_8_R3.PacketPlayOutChat;
@SuppressWarnings("deprecation")
public class V1_8 {
private static Method hoppername = null;
private static boolean checked = false;
public static void sendActionbar(Player player, String s) {
IChatBaseComponent cbc = ChatSerializer.a("{\"text\": \"" + s + "\"}");
PacketPlayOutChat ppoc = new PacketPlayOutChat(cbc, (byte) 2);
CraftPlayer cfp = (CraftPlayer) player;
cfp.getHandle().playerConnection.sendPacket(ppoc);
}
public static String getHopperName(Hopper h) {
Class<?> hoppers = h.getClass();
if (checked == false && hoppername == null) {
checked = true;
try {
hoppername = hoppers.getMethod("getCustomName");
} catch (Exception e) {
Main.sendDebug("Hopper getCustomName not found! Falling back to getInventory().getName()", 1);
}
}
if (hoppername == null) {
return h.getInventory().getName();
}
try {
return (String) hoppername.invoke(h);
} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
e.printStackTrace();
return "container.hopper";
}
}
public static Object setUnbreakable(ItemMeta imeta, boolean unbreakable) {
imeta.spigot().setUnbreakable(unbreakable);
return null;
}
public static boolean isUnbreakable(ItemMeta imeta) {
return imeta.spigot().isUnbreakable();
}
}

151
src/cx/sfy/LagAssist/utils/VersionMgr.java

@ -0,0 +1,151 @@
package cx.sfy.LagAssist.utils;
import org.bukkit.Bukkit;
import org.bukkit.Chunk;
import org.bukkit.World;
import org.bukkit.attribute.Attribute;
import org.bukkit.entity.Entity;
import org.bukkit.entity.LivingEntity;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import cx.sfy.LagAssist.packets.Reflection;
@SuppressWarnings("deprecation")
public class VersionMgr {
public static ItemStack getMap() {
return (isNewMaterials() ? V1_13.getLagMap() : V1_12.getLagMap());
}
public static int getMapId(ItemStack s) {
return (isNewMaterials()) ? (int) V1_13.getMapId(s) : V1_12.getMapId(s);
}
public static ItemStack[] getStatics() {
if (VersionMgr.isNewMaterials()) {
return V1_13.getStatics();
} else {
return V1_12.getStatics();
}
}
public static boolean isV1_8() {
return Bukkit.getVersion().contains("1.8");
}
public static boolean isV1_9() {
return Bukkit.getVersion().contains("1.9");
}
public static boolean isV1_10() {
return Bukkit.getVersion().contains("1.10");
}
public static boolean isV1_11() {
return Bukkit.getVersion().contains("1.11");
}
public static boolean isV1_12() {
return Bukkit.getVersion().contains("1.12");
}
public static boolean isV1_13() {
return Bukkit.getVersion().contains("1.13");
}
public static boolean isV1_14() {
return Bukkit.getVersion().contains("1.14");
}
public static boolean isNewMaterials() {
if (isV1_8()) {
return false;
}
if (isV1_9()) {
return false;
}
if (isV1_10()) {
return false;
}
if (isV1_11()) {
return false;
}
if (isV1_12()) {
return false;
}
return true;
}
public static boolean isPaper() {
try {
Class.forName("com.destroystokyo.paper.PaperConfig");
} catch (ClassNotFoundException e) {
return false;
}
return true;
}
public static String ChunkExistsName() {
return isNewMaterials() ? "f" : "e";
}
// private static HashSet<EntityType> exceptions = Sets.newHashSet(EntityType.ARMOR_STAND, EntityType.VILLAGER, EntityType.ENDER_DRAGON, EntityType.ITEM_FRAME, EntityType.PAINTING);
// private static SplittableRandom sr = new SplittableRandom();
public static void loadChunk(World world, int x, int z) {
Chunk chk = world.getChunkAt(x, z);
// for (Entity e : chk.getEntities()) {
// if (e.getCustomName() != null) {
// continue;
// }
// if (exceptions.contains(e.getType())) {
// continue;
// }
// if (sr.nextInt(100) > 75) {
// continue;
// }
// e.remove();
// }
//
chk.unload();
}
public static Object setUnbreakable(ItemMeta imeta, boolean unbreakable) {
return (isNewMaterials() || isV1_12()) ? V1_13.setUnbreakable(imeta, unbreakable) : V1_8.setUnbreakable(imeta, unbreakable);
}
public static boolean isUnbreakable(ItemMeta imeta) {
return (isNewMaterials() || isV1_12()) ? V1_13.isUnbreakable(imeta) : V1_8.isUnbreakable(imeta);
}
public static boolean isChunkGenerated(World world, Object provider, int x, int z) {
return isNewMaterials() ? V1_13.isChunkGenerated(world, x, z) : Reflection.isChunkExistent(provider, x, z);
}
public static boolean hasPassengers(Entity ent) {
if (isV1_8()) {
return ent.getPassenger() != null;
} else {
return !ent.getPassengers().isEmpty();
}
}
public static double getMaxHealth(LivingEntity ent) {
if (isV1_8()) {
return ent.getMaxHealth();
} else {
return ent.getAttribute(Attribute.GENERIC_MAX_HEALTH).getBaseValue();
}
}
}

38
src/cx/sfy/LagAssist/utils/WorldMgr.java

@ -0,0 +1,38 @@
package cx.sfy.LagAssist.utils;
import java.util.ArrayList;
import java.util.List;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.World;
import cx.sfy.LagAssist.Main;
public class WorldMgr {
public static List<String> blacklist = new ArrayList<String>();
public static void Enabler() {
if (Main.config.getBoolean("blacklisted-worlds.enabled")) {
Bukkit.getLogger().info(" §e[§a✔§e] §fWorldManager.");
blacklist = Main.config.getStringList("blacklisted-worlds.list");
}
}
public static boolean isBlacklisted(World w) {
return blacklist.contains(w.getName());
}
public static String serializeLocation(Location loc) {
return loc.getWorld().getName() + "," + loc.getBlockX() + "," + loc.getBlockY() + "," + loc.getBlockZ();
}
public static Location deserializeLocation(String stg) {
String[] raw = stg.split(",");
return new Location(Bukkit.getWorld(raw[0]), Double.valueOf(raw[1]), Double.valueOf(raw[2]), Double.valueOf(raw[3]));
}
}

1
target/classes/.gitignore

@ -0,0 +1 @@
/cx/
Loading…
Cancel
Save