forked from SteamWar/SteamWar
Format code
This commit is contained in:
@@ -31,9 +31,11 @@ java {
|
||||
}
|
||||
|
||||
tasks.withType<JavaCompile>().configureEach {
|
||||
options.compilerArgs.addAll(listOf(
|
||||
"--add-exports", "java.base/jdk.internal.misc=ALL-UNNAMED"
|
||||
))
|
||||
options.compilerArgs.addAll(
|
||||
listOf(
|
||||
"--add-exports", "java.base/jdk.internal.misc=ALL-UNNAMED"
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
tasks.withType<Test>().configureEach {
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
#
|
||||
LOCAL_CHAT=§eLocal §r{0}§8»§7 {1}
|
||||
LOCAL_CHAT = §eLocal §r{0}§8»§7 {1}
|
||||
|
||||
COMMAND_SYSTEM_ERROR = §cError executing the command!
|
||||
|
||||
@@ -25,86 +25,86 @@ SWLISINV_NEXT_PAGE_INACTIVE = §7Next page
|
||||
SWLISINV_PREVIOUS_PAGE_ACTIVE = §ePrevious page
|
||||
SWLISINV_PREVIOUS_PAGE_INACTIVE = §7Previous page
|
||||
|
||||
SCHEM_SELECTOR_TITLE={0} selection: {1}
|
||||
SCHEM_SELECTOR_BACK=§eBack
|
||||
SCHEM_SELECTOR_DIR=§9Directory
|
||||
SCHEM_SELECTOR_RANK=§8Rank {0}
|
||||
SCHEM_SELECTOR_OWN=§7Own schematics
|
||||
SCHEM_SELECTOR_PUB=§7Public schematics
|
||||
SCHEM_SELECTOR_SEL_DIR=§7Select directory
|
||||
SCHEM_SELECTOR_NEW_DIR=§7New directory
|
||||
SCHEM_SELECTOR_FILTER=§7Filter
|
||||
SCHEM_SELECTOR_SORTING=§7Order by
|
||||
SCHEM_SELECTOR_SORTING_CURRENT=§7Current: §e{0}
|
||||
SCHEM_SELECTOR_SORTING_NAME=Name
|
||||
SCHEM_SELECTOR_SORTING_TYPE=Schematic type
|
||||
SCHEM_SELECTOR_SORTING_UPDATE=Last update
|
||||
SCHEM_SELECTOR_SORTING_DIRECTION=§e{0} §7order
|
||||
SCHEM_SELECTOR_SORTING_ASC=Ascending
|
||||
SCHEM_SELECTOR_SORTING_DSC=Descending
|
||||
SCHEM_SELECTOR_CLICK_BACK=§7Click to go back
|
||||
SCHEM_SELECTOR_TITLE = {0} selection: {1}
|
||||
SCHEM_SELECTOR_BACK = §eBack
|
||||
SCHEM_SELECTOR_DIR = §9Directory
|
||||
SCHEM_SELECTOR_RANK = §8Rank {0}
|
||||
SCHEM_SELECTOR_OWN = §7Own schematics
|
||||
SCHEM_SELECTOR_PUB = §7Public schematics
|
||||
SCHEM_SELECTOR_SEL_DIR = §7Select directory
|
||||
SCHEM_SELECTOR_NEW_DIR = §7New directory
|
||||
SCHEM_SELECTOR_FILTER = §7Filter
|
||||
SCHEM_SELECTOR_SORTING = §7Order by
|
||||
SCHEM_SELECTOR_SORTING_CURRENT = §7Current: §e{0}
|
||||
SCHEM_SELECTOR_SORTING_NAME = Name
|
||||
SCHEM_SELECTOR_SORTING_TYPE = Schematic type
|
||||
SCHEM_SELECTOR_SORTING_UPDATE = Last update
|
||||
SCHEM_SELECTOR_SORTING_DIRECTION = §e{0} §7order
|
||||
SCHEM_SELECTOR_SORTING_ASC = Ascending
|
||||
SCHEM_SELECTOR_SORTING_DSC = Descending
|
||||
SCHEM_SELECTOR_CLICK_BACK = §7Click to go back
|
||||
|
||||
SCHEM_SELECTOR_ITEM_NAME=§e{0}
|
||||
SCHEM_SELECTOR_ITEM_NAME_FILTER=§7{0}
|
||||
SCHEM_SELECTOR_ITEM_REPLACE=§e{0}§7
|
||||
SCHEM_SELECTOR_ITEM_LORE_TYPE=§7{0}
|
||||
SCHEM_SELECTOR_ITEM_NAME = §e{0}
|
||||
SCHEM_SELECTOR_ITEM_NAME_FILTER = §7{0}
|
||||
SCHEM_SELECTOR_ITEM_REPLACE = §e{0}§7
|
||||
SCHEM_SELECTOR_ITEM_LORE_TYPE = §7{0}
|
||||
|
||||
SCHEM_SELECTOR_CREATE_DIR_TITLE=Create directory
|
||||
SCHEM_SELECTOR_CREATE_DIR_TITLE = Create directory
|
||||
|
||||
SCHEM_SELECTOR_FILTER_TITLE=Filter
|
||||
SCHEM_SELECTOR_FILTER_ENTER_NAME=Insert name
|
||||
SCHEM_SELECTOR_FILTER_NAME=§7Search by name...
|
||||
SCHEM_SELECTOR_FILTER_NAME_SEARCH=§7Search term: §e{0}
|
||||
SCHEM_SELECTOR_FILTER_ENTER_OWNER=Choose owner
|
||||
SCHEM_SELECTOR_FILTER_OWNER=§7Search by owner...
|
||||
SCHEM_SELECTOR_FILTER_OWNER_SEARCH=§7Owner: §e{0}
|
||||
SCHEM_SELECTOR_FILTER_SEL_TYPE=Choose type...
|
||||
SCHEM_SELECTOR_FILTER_TYPE=§7Search by type...
|
||||
SCHEM_SELECTOR_FILTER_TYPE_SEARCH=§7Type: §e{0}
|
||||
SCHEM_SELECTOR_FILTER_MAT=§7Filter by item...
|
||||
SCHEM_SELECTOR_FILTER_MAT_SEARCH=§7Item: §e{0}
|
||||
SCHEM_SELECTOR_CANCEL=§eCancel
|
||||
SCHEM_SELECTOR_GO=§eSearch...
|
||||
SCHEM_SELECTOR_SCHEMATIC=Schematic
|
||||
SCHEM_SELECTOR_DIRECTORY=Directory
|
||||
SCHEM_SELECTOR_SCHEMATIC_NODE=Schematic/Directory
|
||||
SCHEM_SELECTOR_FILTER_TITLE = Filter
|
||||
SCHEM_SELECTOR_FILTER_ENTER_NAME = Insert name
|
||||
SCHEM_SELECTOR_FILTER_NAME = §7Search by name...
|
||||
SCHEM_SELECTOR_FILTER_NAME_SEARCH = §7Search term: §e{0}
|
||||
SCHEM_SELECTOR_FILTER_ENTER_OWNER = Choose owner
|
||||
SCHEM_SELECTOR_FILTER_OWNER = §7Search by owner...
|
||||
SCHEM_SELECTOR_FILTER_OWNER_SEARCH = §7Owner: §e{0}
|
||||
SCHEM_SELECTOR_FILTER_SEL_TYPE = Choose type...
|
||||
SCHEM_SELECTOR_FILTER_TYPE = §7Search by type...
|
||||
SCHEM_SELECTOR_FILTER_TYPE_SEARCH = §7Type: §e{0}
|
||||
SCHEM_SELECTOR_FILTER_MAT = §7Filter by item...
|
||||
SCHEM_SELECTOR_FILTER_MAT_SEARCH = §7Item: §e{0}
|
||||
SCHEM_SELECTOR_CANCEL = §eCancel
|
||||
SCHEM_SELECTOR_GO = §eSearch...
|
||||
SCHEM_SELECTOR_SCHEMATIC = Schematic
|
||||
SCHEM_SELECTOR_DIRECTORY = Directory
|
||||
SCHEM_SELECTOR_SCHEMATIC_NODE = Schematic/Directory
|
||||
|
||||
SCHEM_SELECTOR_FILTER_TITLE_SINGLE=§eSingle Filter
|
||||
SCHEM_SELECTOR_FILTER_TITLE_MULTI=§e{0} Filters
|
||||
SCHEM_SELECTOR_FILTER_TITLE_EMPTY=§eNo Filters
|
||||
SCHEM_SELECTOR_FILTER_EMPTY=§7Empty
|
||||
SCHEM_SELECTOR_FILTER_TITLE_SINGLE = §eSingle Filter
|
||||
SCHEM_SELECTOR_FILTER_TITLE_MULTI = §e{0} Filters
|
||||
SCHEM_SELECTOR_FILTER_TITLE_EMPTY = §eNo Filters
|
||||
SCHEM_SELECTOR_FILTER_EMPTY = §7Empty
|
||||
|
||||
MATERIAL_SELECTOR_TITLE=Select material
|
||||
MATERIAL_SELECTOR_TITLE = Select material
|
||||
|
||||
BAN_TEAM={0} §e{1} §7was §e§lbanned§7 by §e{2} {3}§8: §f{4}
|
||||
BAN_PERMA=§7You are §e§lbanned §epermanently§8: §e{0}
|
||||
BAN_UNTIL=§7You are §e§lbanned §euntil {0}§8: §e{1}
|
||||
UNBAN_ERROR=§cThe player isn't banned.
|
||||
UNBAN=§7You have §e§lunbanned §e{0}.
|
||||
BAN_TEAM = {0} §e{1} §7was §e§lbanned§7 by §e{2} {3}§8: §f{4}
|
||||
BAN_PERMA = §7You are §e§lbanned §epermanently§8: §e{0}
|
||||
BAN_UNTIL = §7You are §e§lbanned §euntil {0}§8: §e{1}
|
||||
UNBAN_ERROR = §cThe player isn't banned.
|
||||
UNBAN = §7You have §e§lunbanned §e{0}.
|
||||
|
||||
MUTE_TEAM={0} §e{1} §7was §e§lmuted§7 by §e{2} {3}§8: §f{4}
|
||||
MUTE_PERMA=§7You are §epermanently §e§lmuted§8: §e{0}
|
||||
MUTE_UNTIL=§7You are §e§lmuted §euntil {0}§8: §e{1}
|
||||
UNMUTE_ERROR=§cThe player isn't muted.
|
||||
UNMUTE=§7You have §e§lunmuted §e{0}.
|
||||
MUTE_TEAM = {0} §e{1} §7was §e§lmuted§7 by §e{2} {3}§8: §f{4}
|
||||
MUTE_PERMA = §7You are §epermanently §e§lmuted§8: §e{0}
|
||||
MUTE_UNTIL = §7You are §e§lmuted §euntil {0}§8: §e{1}
|
||||
UNMUTE_ERROR = §cThe player isn't muted.
|
||||
UNMUTE = §7You have §e§lunmuted §e{0}.
|
||||
|
||||
NOSCHEMRECEIVING_TEAM={0} §e{1} §7was excluded from §e{2} {3} §7from §e§lrecieving schematics§8: §f{4}
|
||||
NOSCHEMRECEIVING_PERMA=§7You are §epermanently§7 excluded from receiving §e§lschematics§8: §e{0}
|
||||
NOSCHEMRECEIVING_UNTIL=§7You are excluded from receiving §e§lschematics §euntil {0}§8: §e{1}
|
||||
UNNOSCHEMRECEIVING_ERROR=§cThe player is not excluded from receiving schematics.
|
||||
UNNOSCHEMRECEIVING=§e{0} §7may now receive §e§lschematics§7 again§8.
|
||||
NOSCHEMRECEIVING_TEAM = {0} §e{1} §7was excluded from §e{2} {3} §7from §e§lrecieving schematics§8: §f{4}
|
||||
NOSCHEMRECEIVING_PERMA = §7You are §epermanently§7 excluded from receiving §e§lschematics§8: §e{0}
|
||||
NOSCHEMRECEIVING_UNTIL = §7You are excluded from receiving §e§lschematics §euntil {0}§8: §e{1}
|
||||
UNNOSCHEMRECEIVING_ERROR = §cThe player is not excluded from receiving schematics.
|
||||
UNNOSCHEMRECEIVING = §e{0} §7may now receive §e§lschematics§7 again§8.
|
||||
|
||||
NOSCHEMSHARING_TEAM={0} §e{1} §7was excluded from §e{2} {3} §7from §e§lsharing schematics§8: §f{4}
|
||||
NOSCHEMSHARING_PERMA=§7You are §epermanently§7 excluded from sharing §e§lschematics§8: §e{0}
|
||||
NOSCHEMSHARING_UNTIL=§7You are excluded from sharing §e§lschematics §euntil {0}§8: §e{1}
|
||||
UNNOSCHEMSHARING_ERROR=§cThe player is not excluded from sharing schematics.
|
||||
UNNOSCHEMSHARING=§e{0} §7may now share §e§lschematics§7 again§8.
|
||||
NOSCHEMSHARING_TEAM = {0} §e{1} §7was excluded from §e{2} {3} §7from §e§lsharing schematics§8: §f{4}
|
||||
NOSCHEMSHARING_PERMA = §7You are §epermanently§7 excluded from sharing §e§lschematics§8: §e{0}
|
||||
NOSCHEMSHARING_UNTIL = §7You are excluded from sharing §e§lschematics §euntil {0}§8: §e{1}
|
||||
UNNOSCHEMSHARING_ERROR = §cThe player is not excluded from sharing schematics.
|
||||
UNNOSCHEMSHARING = §e{0} §7may now share §e§lschematics§7 again§8.
|
||||
|
||||
NOSCHEMSUBMITTING_TEAM={0} §e{1} §7was excluded from §e{2} {3} §7from §e§lsubmitting schematics§8: §f{4}
|
||||
NOSCHEMSUBMITTING_PERMA=§7You are §epermanently§7 excluded from submitting §e§lschematics§8: §e{0}
|
||||
NOSCHEMSUBMITTING_UNTIL=§7You are excluded from submitting §e§lschematics §euntil {0}§8: §e{1}
|
||||
UNNOSCHEMSUBMITTING_ERROR=§cThe player is not excluded from submitting schematics.
|
||||
UNNOSCHEMSUBMITTING=§e{0} §7may now submit §e§lschematics§7 again§8.
|
||||
NOSCHEMSUBMITTING_TEAM = {0} §e{1} §7was excluded from §e{2} {3} §7from §e§lsubmitting schematics§8: §f{4}
|
||||
NOSCHEMSUBMITTING_PERMA = §7You are §epermanently§7 excluded from submitting §e§lschematics§8: §e{0}
|
||||
NOSCHEMSUBMITTING_UNTIL = §7You are excluded from submitting §e§lschematics §euntil {0}§8: §e{1}
|
||||
UNNOSCHEMSUBMITTING_ERROR = §cThe player is not excluded from submitting schematics.
|
||||
UNNOSCHEMSUBMITTING = §e{0} §7may now submit §e§lschematics§7 again§8.
|
||||
|
||||
WORLDEDIT_CUI_TITLE = WorldEdit CUI
|
||||
WORLDEDIT_CUI_TITLE_SUBMENU = WorldEdit CUI - {0}
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
#
|
||||
LOCAL_CHAT=§eLokal §r{0}§8»§7 {1}
|
||||
LOCAL_CHAT = §eLokal §r{0}§8»§7 {1}
|
||||
|
||||
COMMAND_SYSTEM_ERROR = §cFehler beim Ausführen des Befehls!
|
||||
|
||||
@@ -25,81 +25,81 @@ SWLISINV_NEXT_PAGE_INACTIVE = §7Seite vor
|
||||
SWLISINV_PREVIOUS_PAGE_ACTIVE = §eSeite zurück
|
||||
SWLISINV_PREVIOUS_PAGE_INACTIVE = §7Seite zurück
|
||||
|
||||
SCHEM_SELECTOR_TITLE={0} auswählen: {1}
|
||||
SCHEM_SELECTOR_BACK=§eZurück
|
||||
SCHEM_SELECTOR_DIR=§9Ordner
|
||||
SCHEM_SELECTOR_RANK=§8Rang {0}
|
||||
SCHEM_SELECTOR_OWN=§7Eigene Schematics
|
||||
SCHEM_SELECTOR_PUB=§7Public Schematics
|
||||
SCHEM_SELECTOR_SEL_DIR=§7Ordner auswählen
|
||||
SCHEM_SELECTOR_NEW_DIR=§7Neuer Ordner
|
||||
SCHEM_SELECTOR_FILTER=§7Filter
|
||||
SCHEM_SELECTOR_SORTING=§7Sortierung
|
||||
SCHEM_SELECTOR_SORTING_CURRENT=§7Aktuell: §e{0}
|
||||
SCHEM_SELECTOR_SORTING_NAME=Name
|
||||
SCHEM_SELECTOR_SORTING_TYPE=Schematic-Typ
|
||||
SCHEM_SELECTOR_SORTING_UPDATE=Letztes Update
|
||||
SCHEM_SELECTOR_SORTING_DIRECTION=§7Richtung: §e{0}
|
||||
SCHEM_SELECTOR_SORTING_ASC=Aufsteigend
|
||||
SCHEM_SELECTOR_SORTING_DSC=Absteigend
|
||||
SCHEM_SELECTOR_CLICK_BACK=§7Klicke hier, um zurückzugehen
|
||||
SCHEM_SELECTOR_TITLE = {0} auswählen: {1}
|
||||
SCHEM_SELECTOR_BACK = §eZurück
|
||||
SCHEM_SELECTOR_DIR = §9Ordner
|
||||
SCHEM_SELECTOR_RANK = §8Rang {0}
|
||||
SCHEM_SELECTOR_OWN = §7Eigene Schematics
|
||||
SCHEM_SELECTOR_PUB = §7Public Schematics
|
||||
SCHEM_SELECTOR_SEL_DIR = §7Ordner auswählen
|
||||
SCHEM_SELECTOR_NEW_DIR = §7Neuer Ordner
|
||||
SCHEM_SELECTOR_FILTER = §7Filter
|
||||
SCHEM_SELECTOR_SORTING = §7Sortierung
|
||||
SCHEM_SELECTOR_SORTING_CURRENT = §7Aktuell: §e{0}
|
||||
SCHEM_SELECTOR_SORTING_NAME = Name
|
||||
SCHEM_SELECTOR_SORTING_TYPE = Schematic-Typ
|
||||
SCHEM_SELECTOR_SORTING_UPDATE = Letztes Update
|
||||
SCHEM_SELECTOR_SORTING_DIRECTION = §7Richtung: §e{0}
|
||||
SCHEM_SELECTOR_SORTING_ASC = Aufsteigend
|
||||
SCHEM_SELECTOR_SORTING_DSC = Absteigend
|
||||
SCHEM_SELECTOR_CLICK_BACK = §7Klicke hier, um zurückzugehen
|
||||
|
||||
SCHEM_SELECTOR_CREATE_DIR_TITLE=Ordner erstellen
|
||||
SCHEM_SELECTOR_CREATE_DIR_TITLE = Ordner erstellen
|
||||
|
||||
SCHEM_SELECTOR_FILTER_TITLE=Filter
|
||||
SCHEM_SELECTOR_FILTER_ENTER_NAME=Name eingeben
|
||||
SCHEM_SELECTOR_FILTER_NAME=§7Nach Namen suchen...
|
||||
SCHEM_SELECTOR_FILTER_NAME_SEARCH=§7Suchbegriff: §e{0}
|
||||
SCHEM_SELECTOR_FILTER_ENTER_OWNER=Besitzer eingeben
|
||||
SCHEM_SELECTOR_FILTER_OWNER=§7Nach Besitzer suchen...
|
||||
SCHEM_SELECTOR_FILTER_OWNER_SEARCH=§7Besitzer: §e{0}
|
||||
SCHEM_SELECTOR_FILTER_SEL_TYPE=Typ wählen...
|
||||
SCHEM_SELECTOR_FILTER_TYPE=§7Nach Typ filtern...
|
||||
SCHEM_SELECTOR_FILTER_TYPE_SEARCH=§7Typ: §e{0}
|
||||
SCHEM_SELECTOR_FILTER_MAT=§7Nach Item filtern...
|
||||
SCHEM_SELECTOR_FILTER_MAT_SEARCH=§7Item: §e{0}
|
||||
SCHEM_SELECTOR_CANCEL=§eAbbrechen
|
||||
SCHEM_SELECTOR_GO=§eSuchen...
|
||||
SCHEM_SELECTOR_SCHEMATIC=Schematic
|
||||
SCHEM_SELECTOR_DIRECTORY=Ordner
|
||||
SCHEM_SELECTOR_SCHEMATIC_NODE=Schematic/Ordner
|
||||
SCHEM_SELECTOR_FILTER_TITLE = Filter
|
||||
SCHEM_SELECTOR_FILTER_ENTER_NAME = Name eingeben
|
||||
SCHEM_SELECTOR_FILTER_NAME = §7Nach Namen suchen...
|
||||
SCHEM_SELECTOR_FILTER_NAME_SEARCH = §7Suchbegriff: §e{0}
|
||||
SCHEM_SELECTOR_FILTER_ENTER_OWNER = Besitzer eingeben
|
||||
SCHEM_SELECTOR_FILTER_OWNER = §7Nach Besitzer suchen...
|
||||
SCHEM_SELECTOR_FILTER_OWNER_SEARCH = §7Besitzer: §e{0}
|
||||
SCHEM_SELECTOR_FILTER_SEL_TYPE = Typ wählen...
|
||||
SCHEM_SELECTOR_FILTER_TYPE = §7Nach Typ filtern...
|
||||
SCHEM_SELECTOR_FILTER_TYPE_SEARCH = §7Typ: §e{0}
|
||||
SCHEM_SELECTOR_FILTER_MAT = §7Nach Item filtern...
|
||||
SCHEM_SELECTOR_FILTER_MAT_SEARCH = §7Item: §e{0}
|
||||
SCHEM_SELECTOR_CANCEL = §eAbbrechen
|
||||
SCHEM_SELECTOR_GO = §eSuchen...
|
||||
SCHEM_SELECTOR_SCHEMATIC = Schematic
|
||||
SCHEM_SELECTOR_DIRECTORY = Ordner
|
||||
SCHEM_SELECTOR_SCHEMATIC_NODE = Schematic/Ordner
|
||||
|
||||
SCHEM_SELECTOR_FILTER_TITLE_SINGLE=§eEinzelfilter
|
||||
SCHEM_SELECTOR_FILTER_TITLE_MULTI=§e{0} §e§lMehrfachfilter
|
||||
SCHEM_SELECTOR_FILTER_TITLE_EMPTY=§eKeine Filter
|
||||
SCHEM_SELECTOR_FILTER_EMPTY=§7Leer
|
||||
SCHEM_SELECTOR_FILTER_TITLE_SINGLE = §eEinzelfilter
|
||||
SCHEM_SELECTOR_FILTER_TITLE_MULTI = §e{0} §e§lMehrfachfilter
|
||||
SCHEM_SELECTOR_FILTER_TITLE_EMPTY = §eKeine Filter
|
||||
SCHEM_SELECTOR_FILTER_EMPTY = §7Leer
|
||||
|
||||
MATERIAL_SELECTOR_TITLE=Material auswählen
|
||||
MATERIAL_SELECTOR_TITLE = Material auswählen
|
||||
|
||||
BAN_TEAM={0} §e{1} §7wurde von §e{2} {3} §e§lgebannt§8: §f{4}
|
||||
BAN_PERMA=§7Du bist §epermanent §e§lgebannt§8: §e{0}
|
||||
BAN_UNTIL=§7Du bist §ebis zum {0} §e§lgebannt§8: §e{1}
|
||||
UNBAN_ERROR=§cDer Spieler ist nicht gebannt.
|
||||
UNBAN=§7Du hast §e{0} §e§lentbannt.
|
||||
BAN_TEAM = {0} §e{1} §7wurde von §e{2} {3} §e§lgebannt§8: §f{4}
|
||||
BAN_PERMA = §7Du bist §epermanent §e§lgebannt§8: §e{0}
|
||||
BAN_UNTIL = §7Du bist §ebis zum {0} §e§lgebannt§8: §e{1}
|
||||
UNBAN_ERROR = §cDer Spieler ist nicht gebannt.
|
||||
UNBAN = §7Du hast §e{0} §e§lentbannt.
|
||||
|
||||
MUTE_TEAM={0} §e{1} §7wurde von §e{2} {3} §e§lgemuted§8: §f{4}
|
||||
MUTE_PERMA=§7Du bist §epermanent §e§lgemuted§8: §e{0}
|
||||
MUTE_UNTIL=§7Du bist §ebis zum {0} §e§lgemuted§8: §e{1}
|
||||
UNMUTE_ERROR=§cDer Spieler ist nicht gemuted.
|
||||
UNMUTE=§7Du hast §e{0} §e§lentmuted.
|
||||
MUTE_TEAM = {0} §e{1} §7wurde von §e{2} {3} §e§lgemuted§8: §f{4}
|
||||
MUTE_PERMA = §7Du bist §epermanent §e§lgemuted§8: §e{0}
|
||||
MUTE_UNTIL = §7Du bist §ebis zum {0} §e§lgemuted§8: §e{1}
|
||||
UNMUTE_ERROR = §cDer Spieler ist nicht gemuted.
|
||||
UNMUTE = §7Du hast §e{0} §e§lentmuted.
|
||||
|
||||
NOSCHEMRECEIVING_TEAM={0} §e{1} §7wurde von §e{2} {3} §7vom §e§lSchematicerhalten§7 ausgeschlossen§8: §f{4}
|
||||
NOSCHEMRECEIVING_PERMA=§7Du bist §epermanent §7vom Erhalten von §e§lSchematics§7 ausgeschlossen§8: §e{0}
|
||||
NOSCHEMRECEIVING_UNTIL=§7Du bist §ebis zum {0} §7vom Erhalten von §e§lSchematics§7 ausgeschlossen§8: §e{1}
|
||||
UNNOSCHEMRECEIVING_ERROR=§cDer Spieler ist nicht vom Erhalten von Schematics ausgeschlossen.
|
||||
UNNOSCHEMRECEIVING=§e{0} §7darf nun wieder §e§lSchematics§7 erhalten§8.
|
||||
NOSCHEMRECEIVING_TEAM = {0} §e{1} §7wurde von §e{2} {3} §7vom §e§lSchematicerhalten§7 ausgeschlossen§8: §f{4}
|
||||
NOSCHEMRECEIVING_PERMA = §7Du bist §epermanent §7vom Erhalten von §e§lSchematics§7 ausgeschlossen§8: §e{0}
|
||||
NOSCHEMRECEIVING_UNTIL = §7Du bist §ebis zum {0} §7vom Erhalten von §e§lSchematics§7 ausgeschlossen§8: §e{1}
|
||||
UNNOSCHEMRECEIVING_ERROR = §cDer Spieler ist nicht vom Erhalten von Schematics ausgeschlossen.
|
||||
UNNOSCHEMRECEIVING = §e{0} §7darf nun wieder §e§lSchematics§7 erhalten§8.
|
||||
|
||||
NOSCHEMSHARING_TEAM={0} §e{1} §7wurde von §e{2} {3} §7vom §e§lSchematicverteilen§7 ausgeschlossen§8: §f{4}
|
||||
NOSCHEMSHARING_PERMA=§7Du bist §epermanent §7vom §e§lVerteilen von Schematics§7 ausgeschlossen§8: §e{0}
|
||||
NOSCHEMSHARING_UNTIL=§7Du bist §ebis zum {0} §7vom §e§lVerteilen von Schematics§7 ausgeschlossen§8: §e{1}
|
||||
UNNOSCHEMSHARING_ERROR=§cDer Spieler ist nicht vom Verteilen von Schematics ausgeschlossen.
|
||||
UNNOSCHEMSHARING=§e{0} §7darf nun wieder §e§lSchematics§7 verteilen§8.
|
||||
NOSCHEMSHARING_TEAM = {0} §e{1} §7wurde von §e{2} {3} §7vom §e§lSchematicverteilen§7 ausgeschlossen§8: §f{4}
|
||||
NOSCHEMSHARING_PERMA = §7Du bist §epermanent §7vom §e§lVerteilen von Schematics§7 ausgeschlossen§8: §e{0}
|
||||
NOSCHEMSHARING_UNTIL = §7Du bist §ebis zum {0} §7vom §e§lVerteilen von Schematics§7 ausgeschlossen§8: §e{1}
|
||||
UNNOSCHEMSHARING_ERROR = §cDer Spieler ist nicht vom Verteilen von Schematics ausgeschlossen.
|
||||
UNNOSCHEMSHARING = §e{0} §7darf nun wieder §e§lSchematics§7 verteilen§8.
|
||||
|
||||
NOSCHEMSUBMITTING_TEAM={0} §e{1} §7wurde von §e{2} {3} §7vom §e§lSchematiceinsenden§7 ausgeschlossen§8: §f{4}
|
||||
NOSCHEMSUBMITTING_PERMA=§7Du bist §epermanent §7vom §e§lEinsenden von Schematics§7 ausgeschlossen§8: §e{0}
|
||||
NOSCHEMSUBMITTING_UNTIL=§7Du bist §ebis zum {0} §7vom §e§lEinsenden von Schematics§7 ausgeschlossen§8: §e{1}
|
||||
UNNOSCHEMSUBMITTING_ERROR=§cDer Spieler ist nicht vom Einsenden von Schematics ausgeschlossen.
|
||||
UNNOSCHEMSUBMITTING=§e{0} §7darf nun wieder §e§lSchematis§7 einsenden§8.
|
||||
NOSCHEMSUBMITTING_TEAM = {0} §e{1} §7wurde von §e{2} {3} §7vom §e§lSchematiceinsenden§7 ausgeschlossen§8: §f{4}
|
||||
NOSCHEMSUBMITTING_PERMA = §7Du bist §epermanent §7vom §e§lEinsenden von Schematics§7 ausgeschlossen§8: §e{0}
|
||||
NOSCHEMSUBMITTING_UNTIL = §7Du bist §ebis zum {0} §7vom §e§lEinsenden von Schematics§7 ausgeschlossen§8: §e{1}
|
||||
UNNOSCHEMSUBMITTING_ERROR = §cDer Spieler ist nicht vom Einsenden von Schematics ausgeschlossen.
|
||||
UNNOSCHEMSUBMITTING = §e{0} §7darf nun wieder §e§lSchematis§7 einsenden§8.
|
||||
|
||||
WORLDEDIT_CUI_SELECTION = Eigene Auswahl
|
||||
WORLDEDIT_CUI_CLIPBOARD = Eigene Kopie
|
||||
|
||||
@@ -52,445 +52,445 @@ import java.util.logging.Level;
|
||||
* @author Kristian
|
||||
*/
|
||||
public class TinyProtocol {
|
||||
// Speedup channel lookup
|
||||
private Map<String, Channel> channelLookup = new MapMaker().weakValues().makeMap();
|
||||
private Listener listener;
|
||||
|
||||
// Channels that have already been removed
|
||||
private Set<Channel> uninjectedChannels = Collections.newSetFromMap(new MapMaker().weakKeys().<Channel, Boolean>makeMap());
|
||||
|
||||
// List of network markers
|
||||
public List<Connection> networkManagers;
|
||||
|
||||
// Injected channel handlers
|
||||
private List<Channel> serverChannels = new ArrayList<>();
|
||||
private ChannelInboundHandlerAdapter serverChannelHandler;
|
||||
private ChannelInitializer<Channel> beginInitProtocol;
|
||||
private ChannelInitializer<Channel> endInitProtocol;
|
||||
|
||||
// Current handler name
|
||||
private static final String HANDLER_NAME = "tiny-steamwar";
|
||||
|
||||
protected volatile boolean closed;
|
||||
protected Plugin plugin;
|
||||
|
||||
public static final TinyProtocol instance = new TinyProtocol(Core.getInstance());
|
||||
private final Map<Class<?>, List<BiFunction<Player, Object, Object>>> packetFilters = new HashMap<>();
|
||||
|
||||
public static void init() {
|
||||
// enforce init
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a new instance of TinyProtocol, and start intercepting packets for all connected clients and future clients.
|
||||
* <p>
|
||||
* You can construct multiple instances per plugin.
|
||||
*
|
||||
* @param plugin - the plugin.
|
||||
*/
|
||||
private TinyProtocol(final Plugin plugin) {
|
||||
this.plugin = plugin;
|
||||
|
||||
// Prepare existing players
|
||||
registerBukkitEvents();
|
||||
|
||||
try {
|
||||
registerChannelHandler();
|
||||
registerPlayers(plugin);
|
||||
} catch (IllegalArgumentException ex) {
|
||||
// Damn you, late bind
|
||||
plugin.getLogger().info("[TinyProtocol] Delaying server channel injection due to late bind.");
|
||||
|
||||
new BukkitRunnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
registerChannelHandler();
|
||||
registerPlayers(plugin);
|
||||
plugin.getLogger().info("[TinyProtocol] Late bind injection successful.");
|
||||
}
|
||||
}.runTask(plugin);
|
||||
}
|
||||
}
|
||||
|
||||
private void createServerChannelHandler() {
|
||||
// Handle connected channels
|
||||
endInitProtocol = new ChannelInitializer<Channel>() {
|
||||
|
||||
@Override
|
||||
protected void initChannel(Channel channel) throws Exception {
|
||||
try {
|
||||
// This can take a while, so we need to stop the main thread from interfering
|
||||
synchronized (networkManagers) {
|
||||
// Stop injecting channels
|
||||
if (!closed) {
|
||||
channel.eventLoop().submit(() -> injectChannelInternal(channel));
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
plugin.getLogger().log(Level.SEVERE, "Cannot inject incomming channel " + channel, e);
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
// This is executed before Minecraft's channel handler
|
||||
beginInitProtocol = new ChannelInitializer<Channel>() {
|
||||
|
||||
@Override
|
||||
protected void initChannel(Channel channel) throws Exception {
|
||||
channel.pipeline().addLast(endInitProtocol);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
serverChannelHandler = new ChannelInboundHandlerAdapter() {
|
||||
|
||||
@Override
|
||||
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
|
||||
Channel channel = (Channel) msg;
|
||||
|
||||
// Prepare to initialize ths channel
|
||||
channel.pipeline().addFirst(beginInitProtocol);
|
||||
ctx.fireChannelRead(msg);
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Register bukkit events.
|
||||
*/
|
||||
private void registerBukkitEvents() {
|
||||
listener = new Listener() {
|
||||
|
||||
@EventHandler(priority = EventPriority.LOWEST)
|
||||
public final void onPlayerLogin(PlayerLoginEvent e) {
|
||||
if (closed)
|
||||
return;
|
||||
|
||||
Channel channel = getChannel(e.getPlayer());
|
||||
|
||||
// Don't inject players that have been explicitly uninjected
|
||||
if (!uninjectedChannels.contains(channel)) {
|
||||
injectPlayer(e.getPlayer());
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public final void onPluginDisable(PluginDisableEvent e) {
|
||||
if (e.getPlugin().equals(plugin)) {
|
||||
close();
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
plugin.getServer().getPluginManager().registerEvents(listener, plugin);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private void registerChannelHandler() {
|
||||
ServerConnectionListener serverConnection = MinecraftServer.getServer().getConnection();
|
||||
networkManagers = serverConnection.getConnections();
|
||||
// We need to synchronize against this list
|
||||
createServerChannelHandler();
|
||||
|
||||
// Find the correct list, or implicitly throw an exception
|
||||
boolean looking = true;
|
||||
for (int i = 0; looking; i++) {
|
||||
List<Object> list = Reflection.getField(serverConnection.getClass(), List.class, i).get(serverConnection);
|
||||
|
||||
for (Object item : list) {
|
||||
if (!(item instanceof ChannelFuture))
|
||||
break;
|
||||
|
||||
// Channel future that contains the server connection
|
||||
Channel serverChannel = ((ChannelFuture) item).channel();
|
||||
|
||||
serverChannels.add(serverChannel);
|
||||
serverChannel.pipeline().addFirst(serverChannelHandler);
|
||||
looking = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void unregisterChannelHandler() {
|
||||
if (serverChannelHandler == null)
|
||||
return;
|
||||
|
||||
for (Channel serverChannel : serverChannels) {
|
||||
final ChannelPipeline pipeline = serverChannel.pipeline();
|
||||
|
||||
// Remove channel handler
|
||||
serverChannel.eventLoop().execute(new Runnable() {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
pipeline.remove(serverChannelHandler);
|
||||
} catch (NoSuchElementException e) {
|
||||
// That's fine
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private void registerPlayers(Plugin plugin) {
|
||||
for (Player player : plugin.getServer().getOnlinePlayers()) {
|
||||
injectPlayer(player);
|
||||
}
|
||||
}
|
||||
|
||||
public <T> void addTypedFilter(Class<T> packetType, BiFunction<Player, ? super T, Object> filter) {
|
||||
packetFilters.computeIfAbsent(packetType, c -> new CopyOnWriteArrayList<>()).add((BiFunction) filter);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public void addFilter(Class<?> packetType, BiFunction<Player, Object, Object> filter) {
|
||||
packetFilters.computeIfAbsent(packetType, c -> new CopyOnWriteArrayList<>()).add(filter);
|
||||
}
|
||||
|
||||
public void removeFilter(Class<?> packetType, BiFunction<Player, ?, Object> filter) {
|
||||
packetFilters.getOrDefault(packetType, Collections.emptyList()).remove(filter);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a packet to a particular player.
|
||||
*
|
||||
* @param player - the destination player.
|
||||
* @param packet - the packet to send.
|
||||
*/
|
||||
public void sendPacket(Player player, Packet<?> packet) {
|
||||
sendPacket(getChannel(player), packet);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public void sendPacket(Player player, Object object) {
|
||||
if (object instanceof Packet<?> packet) {
|
||||
sendPacket(getChannel(player), packet);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a packet to a particular client.
|
||||
*
|
||||
* @param channel - client identified by a channel.
|
||||
* @param packet - the packet to send.
|
||||
*/
|
||||
public void sendPacket(Channel channel, Packet<?> packet) {
|
||||
channel.pipeline().writeAndFlush(packet);
|
||||
}
|
||||
|
||||
/**
|
||||
* Pretend that a given packet has been received from a player.
|
||||
*
|
||||
* @param player - the player that sent the packet.
|
||||
* @param packet - the packet that will be received by the server.
|
||||
*/
|
||||
public void receivePacket(Player player, Packet<?> packet) {
|
||||
receivePacket(getChannel(player), packet);
|
||||
}
|
||||
|
||||
/**
|
||||
* Pretend that a given packet has been received from a given client.
|
||||
*
|
||||
* @param channel - client identified by a channel.
|
||||
* @param packet - the packet that will be received by the server.
|
||||
*/
|
||||
public void receivePacket(Channel channel, Packet<?> packet) {
|
||||
channel.pipeline().context("encoder").fireChannelRead(packet);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a custom channel handler to the given player's channel pipeline, allowing us to intercept sent and received packets.
|
||||
* <p>
|
||||
* This will automatically be called when a player has logged in.
|
||||
*
|
||||
* @param player - the player to inject.
|
||||
*/
|
||||
public void injectPlayer(Player player) {
|
||||
injectChannelInternal(getChannel(player)).player = player;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a custom channel handler to the given channel.
|
||||
*
|
||||
* @param channel - the channel to inject.
|
||||
* @return The intercepted channel, or NULL if it has already been injected.
|
||||
*/
|
||||
public void injectChannel(Channel channel) {
|
||||
injectChannelInternal(channel);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a custom channel handler to the given channel.
|
||||
*
|
||||
* @param channel - the channel to inject.
|
||||
* @return The packet interceptor.
|
||||
*/
|
||||
private PacketInterceptor injectChannelInternal(Channel channel) {
|
||||
try {
|
||||
PacketInterceptor interceptor = (PacketInterceptor) channel.pipeline().get(HANDLER_NAME);
|
||||
|
||||
// Inject our packet interceptor
|
||||
if (interceptor == null) {
|
||||
interceptor = new PacketInterceptor();
|
||||
channel.pipeline().addBefore("packet_handler", HANDLER_NAME, interceptor);
|
||||
uninjectedChannels.remove(channel);
|
||||
}
|
||||
|
||||
return interceptor;
|
||||
} catch (IllegalArgumentException e) {
|
||||
// Try again
|
||||
return (PacketInterceptor) channel.pipeline().get(HANDLER_NAME);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the Netty channel associated with a player. This is cached.
|
||||
*
|
||||
* @param player - the player.
|
||||
* @return The Netty channel.
|
||||
*/
|
||||
public Channel getChannel(Player player) {
|
||||
Channel channel = channelLookup.get(player.getName());
|
||||
|
||||
// Lookup channel again
|
||||
if (channel == null) {
|
||||
Channel playerChannel = ((CraftPlayer) player).getHandle().connection.connection.channel;
|
||||
channelLookup.put(player.getName(), channel = playerChannel);
|
||||
}
|
||||
|
||||
return channel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Uninject a specific player.
|
||||
*
|
||||
* @param player - the injected player.
|
||||
*/
|
||||
public void uninjectPlayer(Player player) {
|
||||
uninjectChannel(getChannel(player));
|
||||
}
|
||||
|
||||
/**
|
||||
* Uninject a specific channel.
|
||||
* <p>
|
||||
* This will also disable the automatic channel injection that occurs when a player has properly logged in.
|
||||
*
|
||||
* @param channel - the injected channel.
|
||||
*/
|
||||
public void uninjectChannel(final Channel channel) {
|
||||
// No need to guard against this if we're closing
|
||||
if (!closed) {
|
||||
uninjectedChannels.add(channel);
|
||||
}
|
||||
|
||||
// See ChannelInjector in ProtocolLib, line 590
|
||||
channel.eventLoop().execute(new Runnable() {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
channel.pipeline().remove(HANDLER_NAME);
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the given player has been injected by TinyProtocol.
|
||||
*
|
||||
* @param player - the player.
|
||||
* @return TRUE if it is, FALSE otherwise.
|
||||
*/
|
||||
public boolean hasInjected(Player player) {
|
||||
return hasInjected(getChannel(player));
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the given channel has been injected by TinyProtocol.
|
||||
*
|
||||
* @param channel - the channel.
|
||||
* @return TRUE if it is, FALSE otherwise.
|
||||
*/
|
||||
public boolean hasInjected(Channel channel) {
|
||||
return channel.pipeline().get(HANDLER_NAME) != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Cease listening for packets. This is called automatically when your plugin is disabled.
|
||||
*/
|
||||
public final void close() {
|
||||
if (!closed) {
|
||||
closed = true;
|
||||
|
||||
// Remove our handlers
|
||||
for (Player player : plugin.getServer().getOnlinePlayers()) {
|
||||
uninjectPlayer(player);
|
||||
}
|
||||
|
||||
// Clean up Bukkit
|
||||
HandlerList.unregisterAll(listener);
|
||||
unregisterChannelHandler();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Channel handler that is inserted into the player's channel pipeline, allowing us to intercept sent and received packets.
|
||||
*
|
||||
* @author Kristian
|
||||
*/
|
||||
private final class PacketInterceptor extends ChannelDuplexHandler {
|
||||
// Updated by the login event
|
||||
public volatile Player player;
|
||||
|
||||
@Override
|
||||
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
|
||||
// Intercept channel
|
||||
final Channel channel = ctx.channel();
|
||||
handleLoginStart(channel, msg);
|
||||
|
||||
try {
|
||||
msg = filterPacket(player, msg);
|
||||
} catch (Exception e) {
|
||||
plugin.getLogger().log(Level.SEVERE, "Error in onPacketInAsync().", e);
|
||||
}
|
||||
|
||||
if (msg != null) {
|
||||
super.channelRead(ctx, msg);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {
|
||||
try {
|
||||
msg = filterPacket(player, msg);
|
||||
} catch (Exception e) {
|
||||
plugin.getLogger().log(Level.SEVERE, "Error in onPacketOutAsync().", e);
|
||||
}
|
||||
|
||||
if (msg != null) {
|
||||
super.write(ctx, msg, promise);
|
||||
}
|
||||
}
|
||||
|
||||
private void handleLoginStart(Channel channel, Object packet) {
|
||||
if (packet instanceof ServerboundHelloPacket(String name, UUID packetId)) {
|
||||
channelLookup.put(name, channel);
|
||||
}
|
||||
}
|
||||
|
||||
private Object filterPacket(Player player, Object packet) {
|
||||
List<BiFunction<Player, Object, Object>> filters = packetFilters.getOrDefault(packet.getClass(), Collections.emptyList());
|
||||
|
||||
for(BiFunction<Player, Object, Object> filter : filters) {
|
||||
packet = filter.apply(player, packet);
|
||||
if(packet == null) break;
|
||||
}
|
||||
|
||||
return packet;
|
||||
}
|
||||
}
|
||||
// Speedup channel lookup
|
||||
private Map<String, Channel> channelLookup = new MapMaker().weakValues().makeMap();
|
||||
private Listener listener;
|
||||
|
||||
// Channels that have already been removed
|
||||
private Set<Channel> uninjectedChannels = Collections.newSetFromMap(new MapMaker().weakKeys().<Channel, Boolean>makeMap());
|
||||
|
||||
// List of network markers
|
||||
public List<Connection> networkManagers;
|
||||
|
||||
// Injected channel handlers
|
||||
private List<Channel> serverChannels = new ArrayList<>();
|
||||
private ChannelInboundHandlerAdapter serverChannelHandler;
|
||||
private ChannelInitializer<Channel> beginInitProtocol;
|
||||
private ChannelInitializer<Channel> endInitProtocol;
|
||||
|
||||
// Current handler name
|
||||
private static final String HANDLER_NAME = "tiny-steamwar";
|
||||
|
||||
protected volatile boolean closed;
|
||||
protected Plugin plugin;
|
||||
|
||||
public static final TinyProtocol instance = new TinyProtocol(Core.getInstance());
|
||||
private final Map<Class<?>, List<BiFunction<Player, Object, Object>>> packetFilters = new HashMap<>();
|
||||
|
||||
public static void init() {
|
||||
// enforce init
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a new instance of TinyProtocol, and start intercepting packets for all connected clients and future clients.
|
||||
* <p>
|
||||
* You can construct multiple instances per plugin.
|
||||
*
|
||||
* @param plugin - the plugin.
|
||||
*/
|
||||
private TinyProtocol(final Plugin plugin) {
|
||||
this.plugin = plugin;
|
||||
|
||||
// Prepare existing players
|
||||
registerBukkitEvents();
|
||||
|
||||
try {
|
||||
registerChannelHandler();
|
||||
registerPlayers(plugin);
|
||||
} catch (IllegalArgumentException ex) {
|
||||
// Damn you, late bind
|
||||
plugin.getLogger().info("[TinyProtocol] Delaying server channel injection due to late bind.");
|
||||
|
||||
new BukkitRunnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
registerChannelHandler();
|
||||
registerPlayers(plugin);
|
||||
plugin.getLogger().info("[TinyProtocol] Late bind injection successful.");
|
||||
}
|
||||
}.runTask(plugin);
|
||||
}
|
||||
}
|
||||
|
||||
private void createServerChannelHandler() {
|
||||
// Handle connected channels
|
||||
endInitProtocol = new ChannelInitializer<Channel>() {
|
||||
|
||||
@Override
|
||||
protected void initChannel(Channel channel) throws Exception {
|
||||
try {
|
||||
// This can take a while, so we need to stop the main thread from interfering
|
||||
synchronized (networkManagers) {
|
||||
// Stop injecting channels
|
||||
if (!closed) {
|
||||
channel.eventLoop().submit(() -> injectChannelInternal(channel));
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
plugin.getLogger().log(Level.SEVERE, "Cannot inject incomming channel " + channel, e);
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
// This is executed before Minecraft's channel handler
|
||||
beginInitProtocol = new ChannelInitializer<Channel>() {
|
||||
|
||||
@Override
|
||||
protected void initChannel(Channel channel) throws Exception {
|
||||
channel.pipeline().addLast(endInitProtocol);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
serverChannelHandler = new ChannelInboundHandlerAdapter() {
|
||||
|
||||
@Override
|
||||
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
|
||||
Channel channel = (Channel) msg;
|
||||
|
||||
// Prepare to initialize ths channel
|
||||
channel.pipeline().addFirst(beginInitProtocol);
|
||||
ctx.fireChannelRead(msg);
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Register bukkit events.
|
||||
*/
|
||||
private void registerBukkitEvents() {
|
||||
listener = new Listener() {
|
||||
|
||||
@EventHandler(priority = EventPriority.LOWEST)
|
||||
public final void onPlayerLogin(PlayerLoginEvent e) {
|
||||
if (closed)
|
||||
return;
|
||||
|
||||
Channel channel = getChannel(e.getPlayer());
|
||||
|
||||
// Don't inject players that have been explicitly uninjected
|
||||
if (!uninjectedChannels.contains(channel)) {
|
||||
injectPlayer(e.getPlayer());
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public final void onPluginDisable(PluginDisableEvent e) {
|
||||
if (e.getPlugin().equals(plugin)) {
|
||||
close();
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
plugin.getServer().getPluginManager().registerEvents(listener, plugin);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private void registerChannelHandler() {
|
||||
ServerConnectionListener serverConnection = MinecraftServer.getServer().getConnection();
|
||||
networkManagers = serverConnection.getConnections();
|
||||
// We need to synchronize against this list
|
||||
createServerChannelHandler();
|
||||
|
||||
// Find the correct list, or implicitly throw an exception
|
||||
boolean looking = true;
|
||||
for (int i = 0; looking; i++) {
|
||||
List<Object> list = Reflection.getField(serverConnection.getClass(), List.class, i).get(serverConnection);
|
||||
|
||||
for (Object item : list) {
|
||||
if (!(item instanceof ChannelFuture))
|
||||
break;
|
||||
|
||||
// Channel future that contains the server connection
|
||||
Channel serverChannel = ((ChannelFuture) item).channel();
|
||||
|
||||
serverChannels.add(serverChannel);
|
||||
serverChannel.pipeline().addFirst(serverChannelHandler);
|
||||
looking = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void unregisterChannelHandler() {
|
||||
if (serverChannelHandler == null)
|
||||
return;
|
||||
|
||||
for (Channel serverChannel : serverChannels) {
|
||||
final ChannelPipeline pipeline = serverChannel.pipeline();
|
||||
|
||||
// Remove channel handler
|
||||
serverChannel.eventLoop().execute(new Runnable() {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
pipeline.remove(serverChannelHandler);
|
||||
} catch (NoSuchElementException e) {
|
||||
// That's fine
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private void registerPlayers(Plugin plugin) {
|
||||
for (Player player : plugin.getServer().getOnlinePlayers()) {
|
||||
injectPlayer(player);
|
||||
}
|
||||
}
|
||||
|
||||
public <T> void addTypedFilter(Class<T> packetType, BiFunction<Player, ? super T, Object> filter) {
|
||||
packetFilters.computeIfAbsent(packetType, c -> new CopyOnWriteArrayList<>()).add((BiFunction) filter);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public void addFilter(Class<?> packetType, BiFunction<Player, Object, Object> filter) {
|
||||
packetFilters.computeIfAbsent(packetType, c -> new CopyOnWriteArrayList<>()).add(filter);
|
||||
}
|
||||
|
||||
public void removeFilter(Class<?> packetType, BiFunction<Player, ?, Object> filter) {
|
||||
packetFilters.getOrDefault(packetType, Collections.emptyList()).remove(filter);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a packet to a particular player.
|
||||
*
|
||||
* @param player - the destination player.
|
||||
* @param packet - the packet to send.
|
||||
*/
|
||||
public void sendPacket(Player player, Packet<?> packet) {
|
||||
sendPacket(getChannel(player), packet);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public void sendPacket(Player player, Object object) {
|
||||
if (object instanceof Packet<?> packet) {
|
||||
sendPacket(getChannel(player), packet);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a packet to a particular client.
|
||||
*
|
||||
* @param channel - client identified by a channel.
|
||||
* @param packet - the packet to send.
|
||||
*/
|
||||
public void sendPacket(Channel channel, Packet<?> packet) {
|
||||
channel.pipeline().writeAndFlush(packet);
|
||||
}
|
||||
|
||||
/**
|
||||
* Pretend that a given packet has been received from a player.
|
||||
*
|
||||
* @param player - the player that sent the packet.
|
||||
* @param packet - the packet that will be received by the server.
|
||||
*/
|
||||
public void receivePacket(Player player, Packet<?> packet) {
|
||||
receivePacket(getChannel(player), packet);
|
||||
}
|
||||
|
||||
/**
|
||||
* Pretend that a given packet has been received from a given client.
|
||||
*
|
||||
* @param channel - client identified by a channel.
|
||||
* @param packet - the packet that will be received by the server.
|
||||
*/
|
||||
public void receivePacket(Channel channel, Packet<?> packet) {
|
||||
channel.pipeline().context("encoder").fireChannelRead(packet);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a custom channel handler to the given player's channel pipeline, allowing us to intercept sent and received packets.
|
||||
* <p>
|
||||
* This will automatically be called when a player has logged in.
|
||||
*
|
||||
* @param player - the player to inject.
|
||||
*/
|
||||
public void injectPlayer(Player player) {
|
||||
injectChannelInternal(getChannel(player)).player = player;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a custom channel handler to the given channel.
|
||||
*
|
||||
* @param channel - the channel to inject.
|
||||
* @return The intercepted channel, or NULL if it has already been injected.
|
||||
*/
|
||||
public void injectChannel(Channel channel) {
|
||||
injectChannelInternal(channel);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a custom channel handler to the given channel.
|
||||
*
|
||||
* @param channel - the channel to inject.
|
||||
* @return The packet interceptor.
|
||||
*/
|
||||
private PacketInterceptor injectChannelInternal(Channel channel) {
|
||||
try {
|
||||
PacketInterceptor interceptor = (PacketInterceptor) channel.pipeline().get(HANDLER_NAME);
|
||||
|
||||
// Inject our packet interceptor
|
||||
if (interceptor == null) {
|
||||
interceptor = new PacketInterceptor();
|
||||
channel.pipeline().addBefore("packet_handler", HANDLER_NAME, interceptor);
|
||||
uninjectedChannels.remove(channel);
|
||||
}
|
||||
|
||||
return interceptor;
|
||||
} catch (IllegalArgumentException e) {
|
||||
// Try again
|
||||
return (PacketInterceptor) channel.pipeline().get(HANDLER_NAME);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the Netty channel associated with a player. This is cached.
|
||||
*
|
||||
* @param player - the player.
|
||||
* @return The Netty channel.
|
||||
*/
|
||||
public Channel getChannel(Player player) {
|
||||
Channel channel = channelLookup.get(player.getName());
|
||||
|
||||
// Lookup channel again
|
||||
if (channel == null) {
|
||||
Channel playerChannel = ((CraftPlayer) player).getHandle().connection.connection.channel;
|
||||
channelLookup.put(player.getName(), channel = playerChannel);
|
||||
}
|
||||
|
||||
return channel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Uninject a specific player.
|
||||
*
|
||||
* @param player - the injected player.
|
||||
*/
|
||||
public void uninjectPlayer(Player player) {
|
||||
uninjectChannel(getChannel(player));
|
||||
}
|
||||
|
||||
/**
|
||||
* Uninject a specific channel.
|
||||
* <p>
|
||||
* This will also disable the automatic channel injection that occurs when a player has properly logged in.
|
||||
*
|
||||
* @param channel - the injected channel.
|
||||
*/
|
||||
public void uninjectChannel(final Channel channel) {
|
||||
// No need to guard against this if we're closing
|
||||
if (!closed) {
|
||||
uninjectedChannels.add(channel);
|
||||
}
|
||||
|
||||
// See ChannelInjector in ProtocolLib, line 590
|
||||
channel.eventLoop().execute(new Runnable() {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
channel.pipeline().remove(HANDLER_NAME);
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the given player has been injected by TinyProtocol.
|
||||
*
|
||||
* @param player - the player.
|
||||
* @return TRUE if it is, FALSE otherwise.
|
||||
*/
|
||||
public boolean hasInjected(Player player) {
|
||||
return hasInjected(getChannel(player));
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the given channel has been injected by TinyProtocol.
|
||||
*
|
||||
* @param channel - the channel.
|
||||
* @return TRUE if it is, FALSE otherwise.
|
||||
*/
|
||||
public boolean hasInjected(Channel channel) {
|
||||
return channel.pipeline().get(HANDLER_NAME) != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Cease listening for packets. This is called automatically when your plugin is disabled.
|
||||
*/
|
||||
public final void close() {
|
||||
if (!closed) {
|
||||
closed = true;
|
||||
|
||||
// Remove our handlers
|
||||
for (Player player : plugin.getServer().getOnlinePlayers()) {
|
||||
uninjectPlayer(player);
|
||||
}
|
||||
|
||||
// Clean up Bukkit
|
||||
HandlerList.unregisterAll(listener);
|
||||
unregisterChannelHandler();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Channel handler that is inserted into the player's channel pipeline, allowing us to intercept sent and received packets.
|
||||
*
|
||||
* @author Kristian
|
||||
*/
|
||||
private final class PacketInterceptor extends ChannelDuplexHandler {
|
||||
// Updated by the login event
|
||||
public volatile Player player;
|
||||
|
||||
@Override
|
||||
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
|
||||
// Intercept channel
|
||||
final Channel channel = ctx.channel();
|
||||
handleLoginStart(channel, msg);
|
||||
|
||||
try {
|
||||
msg = filterPacket(player, msg);
|
||||
} catch (Exception e) {
|
||||
plugin.getLogger().log(Level.SEVERE, "Error in onPacketInAsync().", e);
|
||||
}
|
||||
|
||||
if (msg != null) {
|
||||
super.channelRead(ctx, msg);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {
|
||||
try {
|
||||
msg = filterPacket(player, msg);
|
||||
} catch (Exception e) {
|
||||
plugin.getLogger().log(Level.SEVERE, "Error in onPacketOutAsync().", e);
|
||||
}
|
||||
|
||||
if (msg != null) {
|
||||
super.write(ctx, msg, promise);
|
||||
}
|
||||
}
|
||||
|
||||
private void handleLoginStart(Channel channel, Object packet) {
|
||||
if (packet instanceof ServerboundHelloPacket(String name, UUID packetId)) {
|
||||
channelLookup.put(name, channel);
|
||||
}
|
||||
}
|
||||
|
||||
private Object filterPacket(Player player, Object packet) {
|
||||
List<BiFunction<Player, Object, Object>> filters = packetFilters.getOrDefault(packet.getClass(), Collections.emptyList());
|
||||
|
||||
for (BiFunction<Player, Object, Object> filter : filters) {
|
||||
packet = filter.apply(player, packet);
|
||||
if (packet == null) break;
|
||||
}
|
||||
|
||||
return packet;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -35,277 +35,280 @@ import java.util.Map;
|
||||
@UtilityClass
|
||||
public final class Reflection {
|
||||
|
||||
public static final int MAJOR_VERSION;
|
||||
public static final int MINOR_VERSION;
|
||||
static {
|
||||
String[] version = Bukkit.getServer().getBukkitVersion().split("-")[0].split("\\.");
|
||||
MAJOR_VERSION = Integer.parseInt(version[1]);
|
||||
MINOR_VERSION = version.length > 2 ? Integer.parseInt(version[2]) : 0;
|
||||
}
|
||||
public static final int MAJOR_VERSION;
|
||||
public static final int MINOR_VERSION;
|
||||
|
||||
private static final String ORG_BUKKIT_CRAFTBUKKIT = Bukkit.getServer().getClass().getPackage().getName();
|
||||
public static final String LEGACY_NET_MINECRAFT_SERVER = ORG_BUKKIT_CRAFTBUKKIT.replace("org.bukkit.craftbukkit", "net.minecraft.server");
|
||||
static {
|
||||
String[] version = Bukkit.getServer().getBukkitVersion().split("-")[0].split("\\.");
|
||||
MAJOR_VERSION = Integer.parseInt(version[1]);
|
||||
MINOR_VERSION = version.length > 2 ? Integer.parseInt(version[2]) : 0;
|
||||
}
|
||||
|
||||
private static final Map<String, String> spigotClassnames = new HashMap<>();
|
||||
static {
|
||||
// See https://mappings.dev for complete mappings
|
||||
spigotClassnames.put("net.minecraft.Util", "net.minecraft.SystemUtils");
|
||||
private static final String ORG_BUKKIT_CRAFTBUKKIT = Bukkit.getServer().getClass().getPackage().getName();
|
||||
public static final String LEGACY_NET_MINECRAFT_SERVER = ORG_BUKKIT_CRAFTBUKKIT.replace("org.bukkit.craftbukkit", "net.minecraft.server");
|
||||
|
||||
spigotClassnames.put("net.minecraft.core.BlockPos", "net.minecraft.core.BlockPosition");
|
||||
spigotClassnames.put("net.minecraft.core.DefaultedRegistry", "net.minecraft.core.RegistryBlocks");
|
||||
spigotClassnames.put("net.minecraft.core.IdMapper", "net.minecraft.core.RegistryBlockID");
|
||||
spigotClassnames.put("net.minecraft.core.Vec3i", "net.minecraft.core.BaseBlockPosition");
|
||||
private static final Map<String, String> spigotClassnames = new HashMap<>();
|
||||
|
||||
spigotClassnames.put("net.minecraft.nbt.CompoundTag", "net.minecraft.nbt.NBTTagCompound");
|
||||
static {
|
||||
// See https://mappings.dev for complete mappings
|
||||
spigotClassnames.put("net.minecraft.Util", "net.minecraft.SystemUtils");
|
||||
|
||||
spigotClassnames.put("net.minecraft.network.Connection", "net.minecraft.network.NetworkManager");
|
||||
spigotClassnames.put("net.minecraft.core.BlockPos", "net.minecraft.core.BlockPosition");
|
||||
spigotClassnames.put("net.minecraft.core.DefaultedRegistry", "net.minecraft.core.RegistryBlocks");
|
||||
spigotClassnames.put("net.minecraft.core.IdMapper", "net.minecraft.core.RegistryBlockID");
|
||||
spigotClassnames.put("net.minecraft.core.Vec3i", "net.minecraft.core.BaseBlockPosition");
|
||||
|
||||
spigotClassnames.put("net.minecraft.network.chat.Component", "net.minecraft.network.chat.IChatBaseComponent");
|
||||
spigotClassnames.put("net.minecraft.nbt.CompoundTag", "net.minecraft.nbt.NBTTagCompound");
|
||||
|
||||
spigotClassnames.put("net.minecraft.network.protocol.game.ClientboundAddEntityPacket", "net.minecraft.network.protocol.game.PacketPlayOutSpawnEntity");
|
||||
spigotClassnames.put("net.minecraft.network.protocol.game.ClientboundAddPlayerPacket", "net.minecraft.network.protocol.game.PacketPlayOutNamedEntitySpawn");
|
||||
spigotClassnames.put("net.minecraft.network.protocol.game.ClientboundAnimatePacket", "net.minecraft.network.protocol.game.PacketPlayOutAnimation");
|
||||
spigotClassnames.put("net.minecraft.network.protocol.game.ClientboundBlockDestructionPacket", "net.minecraft.network.protocol.game.PacketPlayOutBlockBreak");
|
||||
spigotClassnames.put("net.minecraft.network.protocol.game.ClientboundBlockEntityDataPacket", "net.minecraft.network.protocol.game.PacketPlayOutTileEntityData");
|
||||
spigotClassnames.put("net.minecraft.network.protocol.game.ClientboundBlockEventPacket", "net.minecraft.network.protocol.game.PacketPlayOutBlockAction");
|
||||
spigotClassnames.put("net.minecraft.network.protocol.game.ClientboundBlockUpdatePacket", "net.minecraft.network.protocol.game.PacketPlayOutBlockChange");
|
||||
spigotClassnames.put("net.minecraft.network.protocol.game.ClientboundContainerClosePacket", "net.minecraft.network.protocol.game.PacketPlayOutCloseWindow");
|
||||
spigotClassnames.put("net.minecraft.network.protocol.game.ClientboundEntityEventPacket", "net.minecraft.network.protocol.game.PacketPlayOutEntityStatus");
|
||||
spigotClassnames.put("net.minecraft.network.protocol.game.ClientboundExplodePacket", "net.minecraft.network.protocol.game.PacketPlayOutExplosion");
|
||||
spigotClassnames.put("net.minecraft.network.protocol.game.ClientboundGameEventPacket", "net.minecraft.network.protocol.game.PacketPlayOutGameStateChange");
|
||||
spigotClassnames.put("net.minecraft.network.protocol.game.ClientboundLevelChunkPacketData$BlockEntityInfo", "net.minecraft.network.protocol.game.ClientboundLevelChunkPacketData$a");
|
||||
spigotClassnames.put("net.minecraft.network.protocol.game.ClientboundLevelEventPacket", "net.minecraft.network.protocol.game.PacketPlayOutWorldEvent");
|
||||
spigotClassnames.put("net.minecraft.network.protocol.game.ClientboundLevelParticlesPacket", "net.minecraft.network.protocol.game.PacketPlayOutWorldParticles");
|
||||
spigotClassnames.put("net.minecraft.network.protocol.game.ClientboundMoveEntityPacket", "net.minecraft.network.protocol.game.PacketPlayOutEntity");
|
||||
spigotClassnames.put("net.minecraft.network.protocol.game.ClientboundMoveEntityPacket$Pos", "net.minecraft.network.protocol.game.PacketPlayOutEntity$PacketPlayOutRelEntityMove");
|
||||
spigotClassnames.put("net.minecraft.network.protocol.game.ClientboundMoveEntityPacket$PosRot", "net.minecraft.network.protocol.game.PacketPlayOutEntity$PacketPlayOutRelEntityMoveLook");
|
||||
spigotClassnames.put("net.minecraft.network.protocol.game.ClientboundMoveEntityPacket$Rot", "net.minecraft.network.protocol.game.PacketPlayOutEntity$PacketPlayOutEntityLook");
|
||||
spigotClassnames.put("net.minecraft.network.protocol.game.ClientboundOpenSignEditorPacket", "net.minecraft.network.protocol.game.PacketPlayOutOpenSignEditor");
|
||||
spigotClassnames.put("net.minecraft.network.protocol.game.ClientboundRemoveEntitiesPacket", "net.minecraft.network.protocol.game.PacketPlayOutEntityDestroy");
|
||||
spigotClassnames.put("net.minecraft.network.protocol.game.ClientboundRotateHeadPacket", "net.minecraft.network.protocol.game.PacketPlayOutEntityHeadRotation");
|
||||
spigotClassnames.put("net.minecraft.network.protocol.game.ClientboundSectionBlocksUpdatePacket", "net.minecraft.network.protocol.game.PacketPlayOutMultiBlockChange");
|
||||
spigotClassnames.put("net.minecraft.network.protocol.game.ClientboundSetEntityDataPacket", "net.minecraft.network.protocol.game.PacketPlayOutEntityMetadata");
|
||||
spigotClassnames.put("net.minecraft.network.protocol.game.ClientboundSetEntityMotionPacket", "net.minecraft.network.protocol.game.PacketPlayOutEntityVelocity");
|
||||
spigotClassnames.put("net.minecraft.network.protocol.game.ClientboundSetEquipmentPacket", "net.minecraft.network.protocol.game.PacketPlayOutEntityEquipment");
|
||||
spigotClassnames.put("net.minecraft.network.protocol.game.ClientboundSetObjectivePacket", "net.minecraft.network.protocol.game.PacketPlayOutScoreboardObjective");
|
||||
spigotClassnames.put("net.minecraft.network.protocol.game.ClientboundSetScorePacket", "net.minecraft.network.protocol.game.PacketPlayOutScoreboardScore");
|
||||
spigotClassnames.put("net.minecraft.network.protocol.game.ClientboundSoundPacket", "net.minecraft.network.protocol.game.PacketPlayOutNamedSoundEffect");
|
||||
spigotClassnames.put("net.minecraft.network.protocol.game.ClientboundTeleportEntityPacket", "net.minecraft.network.protocol.game.PacketPlayOutEntityTeleport");
|
||||
spigotClassnames.put("net.minecraft.network.protocol.game.ServerboundContainerClickPacket", "net.minecraft.network.protocol.game.PacketPlayInWindowClick");
|
||||
spigotClassnames.put("net.minecraft.network.protocol.game.ServerboundInteractPacket", "net.minecraft.network.protocol.game.PacketPlayInUseEntity");
|
||||
spigotClassnames.put("net.minecraft.network.protocol.game.ServerboundInteractPacket$Action", "net.minecraft.network.protocol.game.PacketPlayInUseEntity$EnumEntityUseAction");
|
||||
spigotClassnames.put("net.minecraft.network.protocol.game.ServerboundInteractPacket$ActionType", "net.minecraft.network.protocol.game.PacketPlayInUseEntity$b");
|
||||
spigotClassnames.put("net.minecraft.network.protocol.game.ServerboundMovePlayerPacket$Pos", "net.minecraft.network.protocol.game.PacketPlayInFlying$PacketPlayInPosition");
|
||||
spigotClassnames.put("net.minecraft.network.protocol.game.ServerboundMovePlayerPacket$PosRot", "net.minecraft.network.protocol.game.PacketPlayInFlying$PacketPlayInPositionLook");
|
||||
spigotClassnames.put("net.minecraft.network.protocol.game.ServerboundMovePlayerPacket$Rot", "net.minecraft.network.protocol.game.PacketPlayInFlying$PacketPlayInLook");
|
||||
spigotClassnames.put("net.minecraft.network.protocol.game.ServerboundPlayerActionPacket", "net.minecraft.network.protocol.game.PacketPlayInBlockDig");
|
||||
spigotClassnames.put("net.minecraft.network.protocol.game.ServerboundSetCreativeModeSlotPacket", "net.minecraft.network.protocol.game.PacketPlayInSetCreativeSlot");
|
||||
spigotClassnames.put("net.minecraft.network.protocol.game.ServerboundSignUpdatePacket", "net.minecraft.network.protocol.game.PacketPlayInUpdateSign");
|
||||
spigotClassnames.put("net.minecraft.network.protocol.game.ServerboundUseItemPacket", "net.minecraft.network.protocol.game.PacketPlayInBlockPlace");
|
||||
spigotClassnames.put("net.minecraft.network.protocol.game.ServerboundUseItemOnPacket", "net.minecraft.network.protocol.game.PacketPlayInUseItem");
|
||||
spigotClassnames.put("net.minecraft.network.Connection", "net.minecraft.network.NetworkManager");
|
||||
|
||||
spigotClassnames.put("net.minecraft.network.syncher.EntityDataAccessor", "net.minecraft.network.syncher.DataWatcherObject");
|
||||
spigotClassnames.put("net.minecraft.network.syncher.EntityDataSerializer", "net.minecraft.network.syncher.DataWatcherSerializer");
|
||||
spigotClassnames.put("net.minecraft.network.syncher.EntityDataSerializers", "net.minecraft.network.syncher.DataWatcherRegistry");
|
||||
spigotClassnames.put("net.minecraft.network.syncher.SynchedEntityData$DataItem", "net.minecraft.network.syncher.DataWatcher$Item");
|
||||
spigotClassnames.put("net.minecraft.network.chat.Component", "net.minecraft.network.chat.IChatBaseComponent");
|
||||
|
||||
spigotClassnames.put("net.minecraft.server.ServerScoreboard$Method", "net.minecraft.server.ScoreboardServer$Action");
|
||||
spigotClassnames.put("net.minecraft.network.protocol.game.ClientboundAddEntityPacket", "net.minecraft.network.protocol.game.PacketPlayOutSpawnEntity");
|
||||
spigotClassnames.put("net.minecraft.network.protocol.game.ClientboundAddPlayerPacket", "net.minecraft.network.protocol.game.PacketPlayOutNamedEntitySpawn");
|
||||
spigotClassnames.put("net.minecraft.network.protocol.game.ClientboundAnimatePacket", "net.minecraft.network.protocol.game.PacketPlayOutAnimation");
|
||||
spigotClassnames.put("net.minecraft.network.protocol.game.ClientboundBlockDestructionPacket", "net.minecraft.network.protocol.game.PacketPlayOutBlockBreak");
|
||||
spigotClassnames.put("net.minecraft.network.protocol.game.ClientboundBlockEntityDataPacket", "net.minecraft.network.protocol.game.PacketPlayOutTileEntityData");
|
||||
spigotClassnames.put("net.minecraft.network.protocol.game.ClientboundBlockEventPacket", "net.minecraft.network.protocol.game.PacketPlayOutBlockAction");
|
||||
spigotClassnames.put("net.minecraft.network.protocol.game.ClientboundBlockUpdatePacket", "net.minecraft.network.protocol.game.PacketPlayOutBlockChange");
|
||||
spigotClassnames.put("net.minecraft.network.protocol.game.ClientboundContainerClosePacket", "net.minecraft.network.protocol.game.PacketPlayOutCloseWindow");
|
||||
spigotClassnames.put("net.minecraft.network.protocol.game.ClientboundEntityEventPacket", "net.minecraft.network.protocol.game.PacketPlayOutEntityStatus");
|
||||
spigotClassnames.put("net.minecraft.network.protocol.game.ClientboundExplodePacket", "net.minecraft.network.protocol.game.PacketPlayOutExplosion");
|
||||
spigotClassnames.put("net.minecraft.network.protocol.game.ClientboundGameEventPacket", "net.minecraft.network.protocol.game.PacketPlayOutGameStateChange");
|
||||
spigotClassnames.put("net.minecraft.network.protocol.game.ClientboundLevelChunkPacketData$BlockEntityInfo", "net.minecraft.network.protocol.game.ClientboundLevelChunkPacketData$a");
|
||||
spigotClassnames.put("net.minecraft.network.protocol.game.ClientboundLevelEventPacket", "net.minecraft.network.protocol.game.PacketPlayOutWorldEvent");
|
||||
spigotClassnames.put("net.minecraft.network.protocol.game.ClientboundLevelParticlesPacket", "net.minecraft.network.protocol.game.PacketPlayOutWorldParticles");
|
||||
spigotClassnames.put("net.minecraft.network.protocol.game.ClientboundMoveEntityPacket", "net.minecraft.network.protocol.game.PacketPlayOutEntity");
|
||||
spigotClassnames.put("net.minecraft.network.protocol.game.ClientboundMoveEntityPacket$Pos", "net.minecraft.network.protocol.game.PacketPlayOutEntity$PacketPlayOutRelEntityMove");
|
||||
spigotClassnames.put("net.minecraft.network.protocol.game.ClientboundMoveEntityPacket$PosRot", "net.minecraft.network.protocol.game.PacketPlayOutEntity$PacketPlayOutRelEntityMoveLook");
|
||||
spigotClassnames.put("net.minecraft.network.protocol.game.ClientboundMoveEntityPacket$Rot", "net.minecraft.network.protocol.game.PacketPlayOutEntity$PacketPlayOutEntityLook");
|
||||
spigotClassnames.put("net.minecraft.network.protocol.game.ClientboundOpenSignEditorPacket", "net.minecraft.network.protocol.game.PacketPlayOutOpenSignEditor");
|
||||
spigotClassnames.put("net.minecraft.network.protocol.game.ClientboundRemoveEntitiesPacket", "net.minecraft.network.protocol.game.PacketPlayOutEntityDestroy");
|
||||
spigotClassnames.put("net.minecraft.network.protocol.game.ClientboundRotateHeadPacket", "net.minecraft.network.protocol.game.PacketPlayOutEntityHeadRotation");
|
||||
spigotClassnames.put("net.minecraft.network.protocol.game.ClientboundSectionBlocksUpdatePacket", "net.minecraft.network.protocol.game.PacketPlayOutMultiBlockChange");
|
||||
spigotClassnames.put("net.minecraft.network.protocol.game.ClientboundSetEntityDataPacket", "net.minecraft.network.protocol.game.PacketPlayOutEntityMetadata");
|
||||
spigotClassnames.put("net.minecraft.network.protocol.game.ClientboundSetEntityMotionPacket", "net.minecraft.network.protocol.game.PacketPlayOutEntityVelocity");
|
||||
spigotClassnames.put("net.minecraft.network.protocol.game.ClientboundSetEquipmentPacket", "net.minecraft.network.protocol.game.PacketPlayOutEntityEquipment");
|
||||
spigotClassnames.put("net.minecraft.network.protocol.game.ClientboundSetObjectivePacket", "net.minecraft.network.protocol.game.PacketPlayOutScoreboardObjective");
|
||||
spigotClassnames.put("net.minecraft.network.protocol.game.ClientboundSetScorePacket", "net.minecraft.network.protocol.game.PacketPlayOutScoreboardScore");
|
||||
spigotClassnames.put("net.minecraft.network.protocol.game.ClientboundSoundPacket", "net.minecraft.network.protocol.game.PacketPlayOutNamedSoundEffect");
|
||||
spigotClassnames.put("net.minecraft.network.protocol.game.ClientboundTeleportEntityPacket", "net.minecraft.network.protocol.game.PacketPlayOutEntityTeleport");
|
||||
spigotClassnames.put("net.minecraft.network.protocol.game.ServerboundContainerClickPacket", "net.minecraft.network.protocol.game.PacketPlayInWindowClick");
|
||||
spigotClassnames.put("net.minecraft.network.protocol.game.ServerboundInteractPacket", "net.minecraft.network.protocol.game.PacketPlayInUseEntity");
|
||||
spigotClassnames.put("net.minecraft.network.protocol.game.ServerboundInteractPacket$Action", "net.minecraft.network.protocol.game.PacketPlayInUseEntity$EnumEntityUseAction");
|
||||
spigotClassnames.put("net.minecraft.network.protocol.game.ServerboundInteractPacket$ActionType", "net.minecraft.network.protocol.game.PacketPlayInUseEntity$b");
|
||||
spigotClassnames.put("net.minecraft.network.protocol.game.ServerboundMovePlayerPacket$Pos", "net.minecraft.network.protocol.game.PacketPlayInFlying$PacketPlayInPosition");
|
||||
spigotClassnames.put("net.minecraft.network.protocol.game.ServerboundMovePlayerPacket$PosRot", "net.minecraft.network.protocol.game.PacketPlayInFlying$PacketPlayInPositionLook");
|
||||
spigotClassnames.put("net.minecraft.network.protocol.game.ServerboundMovePlayerPacket$Rot", "net.minecraft.network.protocol.game.PacketPlayInFlying$PacketPlayInLook");
|
||||
spigotClassnames.put("net.minecraft.network.protocol.game.ServerboundPlayerActionPacket", "net.minecraft.network.protocol.game.PacketPlayInBlockDig");
|
||||
spigotClassnames.put("net.minecraft.network.protocol.game.ServerboundSetCreativeModeSlotPacket", "net.minecraft.network.protocol.game.PacketPlayInSetCreativeSlot");
|
||||
spigotClassnames.put("net.minecraft.network.protocol.game.ServerboundSignUpdatePacket", "net.minecraft.network.protocol.game.PacketPlayInUpdateSign");
|
||||
spigotClassnames.put("net.minecraft.network.protocol.game.ServerboundUseItemPacket", "net.minecraft.network.protocol.game.PacketPlayInBlockPlace");
|
||||
spigotClassnames.put("net.minecraft.network.protocol.game.ServerboundUseItemOnPacket", "net.minecraft.network.protocol.game.PacketPlayInUseItem");
|
||||
|
||||
spigotClassnames.put("net.minecraft.server.level.ChunkMap", "net.minecraft.server.level.PlayerChunkMap");
|
||||
spigotClassnames.put("net.minecraft.server.level.ChunkMap$TrackedEntity", "net.minecraft.server.level.PlayerChunkMap$EntityTracker");
|
||||
spigotClassnames.put("net.minecraft.server.level.ServerChunkCache", "net.minecraft.server.level.ChunkProviderServer");
|
||||
spigotClassnames.put("net.minecraft.server.level.ServerLevel", "net.minecraft.server.level.WorldServer");
|
||||
spigotClassnames.put("net.minecraft.server.level.ServerPlayer", "net.minecraft.server.level.EntityPlayer");
|
||||
spigotClassnames.put("net.minecraft.network.syncher.EntityDataAccessor", "net.minecraft.network.syncher.DataWatcherObject");
|
||||
spigotClassnames.put("net.minecraft.network.syncher.EntityDataSerializer", "net.minecraft.network.syncher.DataWatcherSerializer");
|
||||
spigotClassnames.put("net.minecraft.network.syncher.EntityDataSerializers", "net.minecraft.network.syncher.DataWatcherRegistry");
|
||||
spigotClassnames.put("net.minecraft.network.syncher.SynchedEntityData$DataItem", "net.minecraft.network.syncher.DataWatcher$Item");
|
||||
|
||||
spigotClassnames.put("net.minecraft.server.network.ServerConnectionListener", "net.minecraft.server.network.ServerConnection");
|
||||
spigotClassnames.put("net.minecraft.server.ServerScoreboard$Method", "net.minecraft.server.ScoreboardServer$Action");
|
||||
|
||||
spigotClassnames.put("net.minecraft.world.InteractionHand", "net.minecraft.world.EnumHand");
|
||||
spigotClassnames.put("net.minecraft.server.level.ChunkMap", "net.minecraft.server.level.PlayerChunkMap");
|
||||
spigotClassnames.put("net.minecraft.server.level.ChunkMap$TrackedEntity", "net.minecraft.server.level.PlayerChunkMap$EntityTracker");
|
||||
spigotClassnames.put("net.minecraft.server.level.ServerChunkCache", "net.minecraft.server.level.ChunkProviderServer");
|
||||
spigotClassnames.put("net.minecraft.server.level.ServerLevel", "net.minecraft.server.level.WorldServer");
|
||||
spigotClassnames.put("net.minecraft.server.level.ServerPlayer", "net.minecraft.server.level.EntityPlayer");
|
||||
|
||||
spigotClassnames.put("net.minecraft.world.entity.EntityType", "net.minecraft.world.entity.EntityTypes");
|
||||
spigotClassnames.put("net.minecraft.world.entity.Pose", "net.minecraft.world.entity.EntityPose");
|
||||
spigotClassnames.put("net.minecraft.server.network.ServerConnectionListener", "net.minecraft.server.network.ServerConnection");
|
||||
|
||||
spigotClassnames.put("net.minecraft.world.entity.item.PrimedTnt", "net.minecraft.world.entity.item.EntityTNTPrimed");
|
||||
spigotClassnames.put("net.minecraft.world.InteractionHand", "net.minecraft.world.EnumHand");
|
||||
|
||||
spigotClassnames.put("net.minecraft.world.entity.projectile.AbstractArrow", "net.minecraft.world.entity.projectile.EntityArrow");
|
||||
spigotClassnames.put("net.minecraft.world.entity.EntityType", "net.minecraft.world.entity.EntityTypes");
|
||||
spigotClassnames.put("net.minecraft.world.entity.Pose", "net.minecraft.world.entity.EntityPose");
|
||||
|
||||
spigotClassnames.put("net.minecraft.world.level.GameType", "net.minecraft.world.level.EnumGamemode");
|
||||
spigotClassnames.put("net.minecraft.world.level.LevelAccessor", "net.minecraft.world.level.GeneratorAccess");
|
||||
spigotClassnames.put("net.minecraft.world.entity.item.PrimedTnt", "net.minecraft.world.entity.item.EntityTNTPrimed");
|
||||
|
||||
spigotClassnames.put("net.minecraft.world.level.block.state.BlockState", "net.minecraft.world.level.block.state.IBlockData");
|
||||
spigotClassnames.put("net.minecraft.world.level.block.state.StateDefinition", "net.minecraft.world.level.block.state.BlockStateList");
|
||||
spigotClassnames.put("net.minecraft.world.entity.projectile.AbstractArrow", "net.minecraft.world.entity.projectile.EntityArrow");
|
||||
|
||||
spigotClassnames.put("net.minecraft.world.level.chunk.LevelChunk", "net.minecraft.world.level.chunk.Chunk");
|
||||
spigotClassnames.put("net.minecraft.world.level.GameType", "net.minecraft.world.level.EnumGamemode");
|
||||
spigotClassnames.put("net.minecraft.world.level.LevelAccessor", "net.minecraft.world.level.GeneratorAccess");
|
||||
|
||||
spigotClassnames.put("net.minecraft.world.level.material.FlowingFluid", "net.minecraft.world.level.material.FluidTypeFlowing");
|
||||
spigotClassnames.put("net.minecraft.world.level.material.Fluids", "net.minecraft.world.level.material.FluidTypes");
|
||||
spigotClassnames.put("net.minecraft.world.level.material.FluidState", "net.minecraft.world.level.material.Fluid");
|
||||
spigotClassnames.put("net.minecraft.world.level.block.state.BlockState", "net.minecraft.world.level.block.state.IBlockData");
|
||||
spigotClassnames.put("net.minecraft.world.level.block.state.StateDefinition", "net.minecraft.world.level.block.state.BlockStateList");
|
||||
|
||||
spigotClassnames.put("net.minecraft.world.phys.BlockHitResult", "net.minecraft.world.phys.MovingObjectPositionBlock");
|
||||
spigotClassnames.put("net.minecraft.world.phys.Vec3", "net.minecraft.world.phys.Vec3D");
|
||||
spigotClassnames.put("net.minecraft.world.level.chunk.LevelChunk", "net.minecraft.world.level.chunk.Chunk");
|
||||
|
||||
spigotClassnames.put("net.minecraft.resources.ResourceLocation", "net.minecraft.resources.MinecraftKey");
|
||||
spigotClassnames.put("net.minecraft.world.level.material.FlowingFluid", "net.minecraft.world.level.material.FluidTypeFlowing");
|
||||
spigotClassnames.put("net.minecraft.world.level.material.Fluids", "net.minecraft.world.level.material.FluidTypes");
|
||||
spigotClassnames.put("net.minecraft.world.level.material.FluidState", "net.minecraft.world.level.material.Fluid");
|
||||
|
||||
spigotClassnames.put("net.minecraft.util.ProgressListener", "net.minecraft.util.IProgressUpdate");
|
||||
}
|
||||
spigotClassnames.put("net.minecraft.world.phys.BlockHitResult", "net.minecraft.world.phys.MovingObjectPositionBlock");
|
||||
spigotClassnames.put("net.minecraft.world.phys.Vec3", "net.minecraft.world.phys.Vec3D");
|
||||
|
||||
public static Class<?> getClass(String name) {
|
||||
try {
|
||||
if(name.startsWith("org.bukkit.craftbukkit")) {
|
||||
return Class.forName(ORG_BUKKIT_CRAFTBUKKIT + name.substring(22));
|
||||
} else if(MAJOR_VERSION < 17 && name.startsWith("net.minecraft")) {
|
||||
return Class.forName(LEGACY_NET_MINECRAFT_SERVER + "." + spigotClassnames.getOrDefault(name, name).split("[.](?=[^.]*$)")[1]);
|
||||
} else if(MAJOR_VERSION < 21 || MINOR_VERSION < 4) {
|
||||
return Class.forName(spigotClassnames.getOrDefault(name, name));
|
||||
} else {
|
||||
Class<?> clazz = null;
|
||||
try {
|
||||
clazz = Class.forName(name);
|
||||
} catch (ClassNotFoundException e) {}
|
||||
if (clazz != null && clazz.getName().equals(name)) {
|
||||
return clazz;
|
||||
}
|
||||
spigotClassnames.put("net.minecraft.resources.ResourceLocation", "net.minecraft.resources.MinecraftKey");
|
||||
|
||||
try {
|
||||
return Core.class.getClassLoader().getParent().loadClass(name);
|
||||
} catch (ClassNotFoundException e) {
|
||||
if (clazz == null) {
|
||||
throw e;
|
||||
}
|
||||
spigotClassnames.put("net.minecraft.util.ProgressListener", "net.minecraft.util.IProgressUpdate");
|
||||
}
|
||||
|
||||
return clazz;
|
||||
}
|
||||
}
|
||||
} catch (ClassNotFoundException e) {
|
||||
throw new IllegalArgumentException("Cannot find " + name, e);
|
||||
}
|
||||
}
|
||||
public static Class<?> getClass(String name) {
|
||||
try {
|
||||
if (name.startsWith("org.bukkit.craftbukkit")) {
|
||||
return Class.forName(ORG_BUKKIT_CRAFTBUKKIT + name.substring(22));
|
||||
} else if (MAJOR_VERSION < 17 && name.startsWith("net.minecraft")) {
|
||||
return Class.forName(LEGACY_NET_MINECRAFT_SERVER + "." + spigotClassnames.getOrDefault(name, name).split("[.](?=[^.]*$)")[1]);
|
||||
} else if (MAJOR_VERSION < 21 || MINOR_VERSION < 4) {
|
||||
return Class.forName(spigotClassnames.getOrDefault(name, name));
|
||||
} else {
|
||||
Class<?> clazz = null;
|
||||
try {
|
||||
clazz = Class.forName(name);
|
||||
} catch (ClassNotFoundException e) {
|
||||
}
|
||||
if (clazz != null && clazz.getName().equals(name)) {
|
||||
return clazz;
|
||||
}
|
||||
|
||||
@AllArgsConstructor
|
||||
public static class Field<T> {
|
||||
private final java.lang.reflect.Field f;
|
||||
try {
|
||||
return Core.class.getClassLoader().getParent().loadClass(name);
|
||||
} catch (ClassNotFoundException e) {
|
||||
if (clazz == null) {
|
||||
throw e;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public T get(Object target) {
|
||||
try {
|
||||
return (T) f.get(target);
|
||||
} catch (IllegalAccessException e) {
|
||||
throw new IllegalArgumentException("Cannot read field", e);
|
||||
}
|
||||
}
|
||||
return clazz;
|
||||
}
|
||||
}
|
||||
} catch (ClassNotFoundException e) {
|
||||
throw new IllegalArgumentException("Cannot find " + name, e);
|
||||
}
|
||||
}
|
||||
|
||||
public void set(Object target, Object value) {
|
||||
try {
|
||||
f.set(target, value);
|
||||
} catch (IllegalAccessException e) {
|
||||
throw new IllegalArgumentException("Cannot write field", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@AllArgsConstructor
|
||||
public static class Field<T> {
|
||||
private final java.lang.reflect.Field f;
|
||||
|
||||
public static <T> Field<T> getField(Class<?> target, String name, Class<T> fieldType) {
|
||||
return getField(target, name, fieldType, 0);
|
||||
}
|
||||
@SuppressWarnings("unchecked")
|
||||
public T get(Object target) {
|
||||
try {
|
||||
return (T) f.get(target);
|
||||
} catch (IllegalAccessException e) {
|
||||
throw new IllegalArgumentException("Cannot read field", e);
|
||||
}
|
||||
}
|
||||
|
||||
public static <T> Field<T> getField(Class<?> target, Class<T> fieldType, int index) {
|
||||
return getField(target, null, fieldType, index);
|
||||
}
|
||||
public void set(Object target, Object value) {
|
||||
try {
|
||||
f.set(target, value);
|
||||
} catch (IllegalAccessException e) {
|
||||
throw new IllegalArgumentException("Cannot write field", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static <T> Field<T> getField(Class<?> target, Class<T> fieldType, int index, Class<?>... parameters) {
|
||||
return getField(target, null, fieldType, index, parameters);
|
||||
}
|
||||
public static <T> Field<T> getField(Class<?> target, String name, Class<T> fieldType) {
|
||||
return getField(target, name, fieldType, 0);
|
||||
}
|
||||
|
||||
private static <T> Field<T> getField(Class<?> target, String name, Class<T> fieldType, int index, Class<?>... parameters) {
|
||||
for (final java.lang.reflect.Field field : target.getDeclaredFields()) {
|
||||
if(matching(field, name, fieldType, parameters) && index-- <= 0) {
|
||||
field.setAccessible(true);
|
||||
return new Field<>(field);
|
||||
}
|
||||
}
|
||||
public static <T> Field<T> getField(Class<?> target, Class<T> fieldType, int index) {
|
||||
return getField(target, null, fieldType, index);
|
||||
}
|
||||
|
||||
// Search in parent classes
|
||||
if (target.getSuperclass() != null)
|
||||
return getField(target.getSuperclass(), name, fieldType, index);
|
||||
public static <T> Field<T> getField(Class<?> target, Class<T> fieldType, int index, Class<?>... parameters) {
|
||||
return getField(target, null, fieldType, index, parameters);
|
||||
}
|
||||
|
||||
throw new IllegalArgumentException("Cannot find field with type " + fieldType);
|
||||
}
|
||||
private static <T> Field<T> getField(Class<?> target, String name, Class<T> fieldType, int index, Class<?>... parameters) {
|
||||
for (final java.lang.reflect.Field field : target.getDeclaredFields()) {
|
||||
if (matching(field, name, fieldType, parameters) && index-- <= 0) {
|
||||
field.setAccessible(true);
|
||||
return new Field<>(field);
|
||||
}
|
||||
}
|
||||
|
||||
private static <T> boolean matching(java.lang.reflect.Field field, String name, Class<T> fieldType, Class<?>... parameters) {
|
||||
if(name != null && !field.getName().equals(name))
|
||||
return false;
|
||||
// Search in parent classes
|
||||
if (target.getSuperclass() != null)
|
||||
return getField(target.getSuperclass(), name, fieldType, index);
|
||||
|
||||
if(!fieldType.isAssignableFrom(field.getType()))
|
||||
return false;
|
||||
throw new IllegalArgumentException("Cannot find field with type " + fieldType);
|
||||
}
|
||||
|
||||
if(parameters.length > 0) {
|
||||
Type[] arguments = ((ParameterizedType)field.getGenericType()).getActualTypeArguments();
|
||||
private static <T> boolean matching(java.lang.reflect.Field field, String name, Class<T> fieldType, Class<?>... parameters) {
|
||||
if (name != null && !field.getName().equals(name))
|
||||
return false;
|
||||
|
||||
for(int i = 0; i < parameters.length; i++) {
|
||||
if(arguments[i] instanceof ParameterizedType ? ((ParameterizedType) arguments[i]).getRawType() != parameters[i] : arguments[i] != parameters[i])
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
if (!fieldType.isAssignableFrom(field.getType()))
|
||||
return false;
|
||||
|
||||
@AllArgsConstructor
|
||||
public static class Method {
|
||||
private final java.lang.reflect.Method m;
|
||||
if (parameters.length > 0) {
|
||||
Type[] arguments = ((ParameterizedType) field.getGenericType()).getActualTypeArguments();
|
||||
|
||||
public Object invoke(Object target, Object... arguments) {
|
||||
try {
|
||||
return m.invoke(target, arguments);
|
||||
} catch (Exception e) {
|
||||
throw new IllegalArgumentException("Cannot invoke method " + m, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < parameters.length; i++) {
|
||||
if (arguments[i] instanceof ParameterizedType ? ((ParameterizedType) arguments[i]).getRawType() != parameters[i] : arguments[i] != parameters[i])
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static Method getTypedMethod(Class<?> clazz, String methodName, Class<?> returnType, Class<?>... params) {
|
||||
for (final java.lang.reflect.Method method : clazz.getDeclaredMethods()) {
|
||||
if ((methodName == null || method.getName().equals(methodName))
|
||||
&& (returnType == null || method.getReturnType().equals(returnType))
|
||||
&& Arrays.equals(method.getParameterTypes(), params)) {
|
||||
method.setAccessible(true);
|
||||
return new Method(method);
|
||||
}
|
||||
}
|
||||
@AllArgsConstructor
|
||||
public static class Method {
|
||||
private final java.lang.reflect.Method m;
|
||||
|
||||
// Search in every superclass
|
||||
if (clazz.getSuperclass() != null)
|
||||
return getTypedMethod(clazz.getSuperclass(), methodName, returnType, params);
|
||||
public Object invoke(Object target, Object... arguments) {
|
||||
try {
|
||||
return m.invoke(target, arguments);
|
||||
} catch (Exception e) {
|
||||
throw new IllegalArgumentException("Cannot invoke method " + m, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
throw new IllegalArgumentException(String.format("Cannot find method %s (%s).", methodName, Arrays.asList(params)));
|
||||
}
|
||||
public static Method getTypedMethod(Class<?> clazz, String methodName, Class<?> returnType, Class<?>... params) {
|
||||
for (final java.lang.reflect.Method method : clazz.getDeclaredMethods()) {
|
||||
if ((methodName == null || method.getName().equals(methodName))
|
||||
&& (returnType == null || method.getReturnType().equals(returnType))
|
||||
&& Arrays.equals(method.getParameterTypes(), params)) {
|
||||
method.setAccessible(true);
|
||||
return new Method(method);
|
||||
}
|
||||
}
|
||||
|
||||
@AllArgsConstructor
|
||||
public static class Constructor {
|
||||
private final java.lang.reflect.Constructor<?> c;
|
||||
// Search in every superclass
|
||||
if (clazz.getSuperclass() != null)
|
||||
return getTypedMethod(clazz.getSuperclass(), methodName, returnType, params);
|
||||
|
||||
public Object invoke(Object... arguments) {
|
||||
try {
|
||||
return c.newInstance(arguments);
|
||||
} catch (Exception e) {
|
||||
throw new IllegalArgumentException("Cannot invoke constructor " + c, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
throw new IllegalArgumentException(String.format("Cannot find method %s (%s).", methodName, Arrays.asList(params)));
|
||||
}
|
||||
|
||||
public static Constructor getConstructor(Class<?> clazz, Class<?>... params) {
|
||||
for (final java.lang.reflect.Constructor<?> constructor : clazz.getDeclaredConstructors()) {
|
||||
if (Arrays.equals(constructor.getParameterTypes(), params)) {
|
||||
constructor.setAccessible(true);
|
||||
return new Constructor(constructor);
|
||||
}
|
||||
}
|
||||
@AllArgsConstructor
|
||||
public static class Constructor {
|
||||
private final java.lang.reflect.Constructor<?> c;
|
||||
|
||||
throw new IllegalStateException(String.format("Unable to find constructor for %s (%s).", clazz, Arrays.asList(params)));
|
||||
}
|
||||
public Object invoke(Object... arguments) {
|
||||
try {
|
||||
return c.newInstance(arguments);
|
||||
} catch (Exception e) {
|
||||
throw new IllegalArgumentException("Cannot invoke constructor " + c, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static Object newInstance(Class<?> clazz) {
|
||||
try {
|
||||
return Unsafe.getUnsafe().allocateInstance(clazz);
|
||||
} catch (InstantiationException e) {
|
||||
throw new SecurityException("Could not create object", e);
|
||||
}
|
||||
}
|
||||
public static Constructor getConstructor(Class<?> clazz, Class<?>... params) {
|
||||
for (final java.lang.reflect.Constructor<?> constructor : clazz.getDeclaredConstructors()) {
|
||||
if (Arrays.equals(constructor.getParameterTypes(), params)) {
|
||||
constructor.setAccessible(true);
|
||||
return new Constructor(constructor);
|
||||
}
|
||||
}
|
||||
|
||||
throw new IllegalStateException(String.format("Unable to find constructor for %s (%s).", clazz, Arrays.asList(params)));
|
||||
}
|
||||
|
||||
public static Object newInstance(Class<?> clazz) {
|
||||
try {
|
||||
return Unsafe.getUnsafe().allocateInstance(clazz);
|
||||
} catch (InstantiationException e) {
|
||||
throw new SecurityException("Could not create object", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -139,7 +139,8 @@ public class SWCommand extends AbstractSWCommand<CommandSender> {
|
||||
}
|
||||
if (args.length == 0 || atomicInteger.get() == commandList.size()) {
|
||||
commandList.forEach(subCommand -> {
|
||||
if (subCommand.validator == null || subCommand.validator.validate(p, p, (s, args1) -> {})) {
|
||||
if (subCommand.validator == null || subCommand.validator.validate(p, p, (s, args1) -> {
|
||||
})) {
|
||||
send(p, subCommand);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -41,12 +41,13 @@ public class BountifulWrapper {
|
||||
}
|
||||
|
||||
public void sendMessage(Player player, ChatMessageType type, BaseComponent... msg) {
|
||||
if(type == ChatMessageType.CHAT) type = ChatMessageType.SYSTEM;
|
||||
if (type == ChatMessageType.CHAT) type = ChatMessageType.SYSTEM;
|
||||
player.spigot().sendMessage(type, msg);
|
||||
}
|
||||
|
||||
private static final Class<?> dataWatcherRegistry = EntityDataSerializers.class;
|
||||
private static final Class<?> dataWatcherSerializer = EntityDataSerializer.class;
|
||||
|
||||
public Object getDataWatcherObject(int index, Class<?> type) {
|
||||
return new EntityDataAccessor<>(index, (EntityDataSerializer<Object>) Reflection.getField(dataWatcherRegistry, dataWatcherSerializer, 0, type).get(null));
|
||||
}
|
||||
@@ -64,8 +65,8 @@ public class BountifulWrapper {
|
||||
};
|
||||
} catch (IllegalArgumentException e) {
|
||||
Reflection.Field<Double> posX = Reflection.getField(packetClass, double.class, fieldOffset);
|
||||
Reflection.Field<Double> posY = Reflection.getField(packetClass, double.class, fieldOffset+1);
|
||||
Reflection.Field<Double> posZ = Reflection.getField(packetClass, double.class, fieldOffset+2);
|
||||
Reflection.Field<Double> posY = Reflection.getField(packetClass, double.class, fieldOffset + 1);
|
||||
Reflection.Field<Double> posZ = Reflection.getField(packetClass, double.class, fieldOffset + 2);
|
||||
boolean isByteClass = packetClass.getSimpleName().contains("PacketPlayOutEntityTeleport") || packetClass.getSimpleName().contains("PacketPlayOutNamedEntitySpawn");
|
||||
Class<?> pitchYawType = isByteClass ? byte.class : int.class;
|
||||
Reflection.Field<?> lookYaw = Reflection.getField(packetClass, pitchYawType, isByteClass ? 0 : 1);
|
||||
@@ -76,11 +77,11 @@ public class BountifulWrapper {
|
||||
posY.set(packet, y);
|
||||
posZ.set(packet, z);
|
||||
if (isByteClass) {
|
||||
lookYaw.set(packet, (byte) (yaw*256/360));
|
||||
lookPitch.set(packet, (byte) (pitch*256/360));
|
||||
lookYaw.set(packet, (byte) (yaw * 256 / 360));
|
||||
lookPitch.set(packet, (byte) (pitch * 256 / 360));
|
||||
} else {
|
||||
lookYaw.set(packet, (int) (yaw*256/360));
|
||||
lookPitch.set(packet, (int) (pitch*256/360));
|
||||
lookYaw.set(packet, (int) (yaw * 256 / 360));
|
||||
lookPitch.set(packet, (int) (pitch * 256 / 360));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -20,7 +20,8 @@
|
||||
package de.steamwar.core;
|
||||
|
||||
public class CheckpointUtils {
|
||||
private CheckpointUtils() {}
|
||||
private CheckpointUtils() {
|
||||
}
|
||||
|
||||
public static void signalHandler() {
|
||||
try {
|
||||
|
||||
@@ -44,7 +44,8 @@ import java.util.logging.Level;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
class CheckpointUtilsJ9 {
|
||||
private CheckpointUtilsJ9() {}
|
||||
private CheckpointUtilsJ9() {
|
||||
}
|
||||
|
||||
static void signalHandler() {
|
||||
Signal.handle(new Signal("USR1"), signal -> Bukkit.getScheduler().runTask(Core.getInstance(), CheckpointUtils::freeze));
|
||||
@@ -52,7 +53,7 @@ class CheckpointUtilsJ9 {
|
||||
|
||||
static void freeze() {
|
||||
String checkpointFile = System.getProperty("checkpoint");
|
||||
if(!CRIUSupport.isCheckpointAllowed() || checkpointFile == null) {
|
||||
if (!CRIUSupport.isCheckpointAllowed() || checkpointFile == null) {
|
||||
Bukkit.shutdown();
|
||||
return;
|
||||
}
|
||||
@@ -60,7 +61,7 @@ class CheckpointUtilsJ9 {
|
||||
Bukkit.getOnlinePlayers().forEach(player -> player.kickPlayer(null));
|
||||
|
||||
List<?> networkManagers = TinyProtocol.instance.networkManagers;
|
||||
if(!Bukkit.getOnlinePlayers().isEmpty() || !networkManagers.isEmpty()) {
|
||||
if (!Bukkit.getOnlinePlayers().isEmpty() || !networkManagers.isEmpty()) {
|
||||
Core.getInstance().getLogger().log(Level.INFO, "Waiting for players to disconnect for checkpointing");
|
||||
Bukkit.getScheduler().runTaskLater(Core.getInstance(), CheckpointUtils::freeze, 1);
|
||||
return;
|
||||
@@ -72,7 +73,7 @@ class CheckpointUtilsJ9 {
|
||||
freezeInternal(path);
|
||||
} catch (Exception e) {
|
||||
String message = e.getMessage() != null ? e.getMessage() : "";
|
||||
if(message.contains("Connected TCP socket")) {
|
||||
if (message.contains("Connected TCP socket")) {
|
||||
Core.getInstance().getLogger().log(Level.INFO, "Connected TCP socket, waiting for checkpointing");
|
||||
Bukkit.getScheduler().runTaskLater(Core.getInstance(), CheckpointUtils::freeze, 1);
|
||||
return;
|
||||
@@ -80,7 +81,7 @@ class CheckpointUtilsJ9 {
|
||||
|
||||
Bukkit.shutdown();
|
||||
|
||||
if(!message.contains("Can't dump ghost file") && !message.contains("Can't create link remap")) // File/Jar has been updated
|
||||
if (!message.contains("Can't dump ghost file") && !message.contains("Can't create link remap")) // File/Jar has been updated
|
||||
throw new SecurityException(e);
|
||||
} finally {
|
||||
// Delete checkpoint
|
||||
@@ -94,6 +95,7 @@ class CheckpointUtilsJ9 {
|
||||
|
||||
|
||||
private static final Reflection.Field<List> channelFutures = Reflection.getField(ServerConnectionListener.class, List.class, 0, ChannelFuture.class);
|
||||
|
||||
private static void freezeInternal(Path path) throws Exception {
|
||||
Bukkit.getPluginManager().callEvent(new CRIUSleepEvent());
|
||||
|
||||
@@ -105,7 +107,7 @@ class CheckpointUtilsJ9 {
|
||||
// Close socket
|
||||
ServerConnectionListener serverConnection = MinecraftServer.getServer().getConnection();
|
||||
List<?> channels = channelFutures.get(serverConnection);
|
||||
for(Object future : channels) {
|
||||
for (Object future : channels) {
|
||||
((ChannelFuture) future).channel().close().syncUninterruptibly();
|
||||
}
|
||||
channels.clear();
|
||||
@@ -125,7 +127,7 @@ class CheckpointUtilsJ9 {
|
||||
criu.checkpointJVM();
|
||||
} catch (JVMCRIUException e) {
|
||||
Path logfile = path.resolve("criu.log");
|
||||
if(logfile.toFile().exists()) {
|
||||
if (logfile.toFile().exists()) {
|
||||
throw new IllegalStateException("Could not create checkpoint, criu log:\n" + new String(Files.readAllBytes(logfile)), e);
|
||||
}
|
||||
|
||||
@@ -140,7 +142,7 @@ class CheckpointUtilsJ9 {
|
||||
|
||||
// Reopen socket
|
||||
serverConnection.startTcpServerListener(InetAddress.getLoopbackAddress(), port);
|
||||
for(Object future : channels) {
|
||||
for (Object future : channels) {
|
||||
((ChannelFuture) future).channel().config().setAutoRead(true);
|
||||
}
|
||||
|
||||
|
||||
@@ -47,53 +47,53 @@ import java.util.logging.Level;
|
||||
|
||||
public class Core extends JavaPlugin {
|
||||
|
||||
public static final Message MESSAGE = new Message("SpigotCore", Core.class.getClassLoader());
|
||||
public static final Message MESSAGE = new Message("SpigotCore", Core.class.getClassLoader());
|
||||
|
||||
@Deprecated
|
||||
public static int getVersion(){
|
||||
return Reflection.MAJOR_VERSION;
|
||||
}
|
||||
@Deprecated
|
||||
public static int getVersion() {
|
||||
return Reflection.MAJOR_VERSION;
|
||||
}
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
private static JavaPlugin instance;
|
||||
@Getter
|
||||
@Setter
|
||||
private static JavaPlugin instance;
|
||||
|
||||
@Getter
|
||||
private static String serverName = "";
|
||||
@Getter
|
||||
private static String serverName = "";
|
||||
|
||||
public static void setServerName(String serverName) {
|
||||
if (Core.serverName.isEmpty()) {
|
||||
Core.serverName = serverName;
|
||||
}
|
||||
}
|
||||
public static void setServerName(String serverName) {
|
||||
if (Core.serverName.isEmpty()) {
|
||||
Core.serverName = serverName;
|
||||
}
|
||||
}
|
||||
|
||||
private ErrorHandler errorHandler;
|
||||
private CrashDetector crashDetector;
|
||||
private ErrorHandler errorHandler;
|
||||
private CrashDetector crashDetector;
|
||||
|
||||
@Override
|
||||
public void onLoad() {
|
||||
setInstance(this);
|
||||
serverName = System.getProperty("serverName", "");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEnable() {
|
||||
new PlayerVersion();
|
||||
@Override
|
||||
public void onLoad() {
|
||||
setInstance(this);
|
||||
serverName = System.getProperty("serverName", "");
|
||||
}
|
||||
|
||||
errorHandler = new ErrorHandler();
|
||||
crashDetector = new CrashDetector();
|
||||
@Override
|
||||
public void onEnable() {
|
||||
new PlayerVersion();
|
||||
|
||||
SWCommandUtils.init((SWTypeMapperCreator<TypeMapper<Object>, CommandSender, Object>) (mapper, tabCompleter) -> new TypeMapper<Object>() {
|
||||
@Override
|
||||
public Object map(CommandSender commandSender, String[] previousArguments, String s) {
|
||||
return mapper.apply(s);
|
||||
}
|
||||
errorHandler = new ErrorHandler();
|
||||
crashDetector = new CrashDetector();
|
||||
|
||||
@Override
|
||||
public Collection<String> tabCompletes(CommandSender sender, String[] previousArguments, String s) {
|
||||
return tabCompleter.apply(sender, s);
|
||||
}
|
||||
});
|
||||
SWCommandUtils.init((SWTypeMapperCreator<TypeMapper<Object>, CommandSender, Object>) (mapper, tabCompleter) -> new TypeMapper<Object>() {
|
||||
@Override
|
||||
public Object map(CommandSender commandSender, String[] previousArguments, String s) {
|
||||
return mapper.apply(s);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<String> tabCompletes(CommandSender sender, String[] previousArguments, String s) {
|
||||
return tabCompleter.apply(sender, s);
|
||||
}
|
||||
});
|
||||
|
||||
SpigotLinker spigotLinker = new SpigotLinker(this, MESSAGE);
|
||||
try {
|
||||
@@ -104,34 +104,34 @@ public class Core extends JavaPlugin {
|
||||
return;
|
||||
}
|
||||
|
||||
if(!Statement.productionDatabase()) {
|
||||
getServer().getPluginManager().registerEvents(new LocaleChangeWrapper(), this);
|
||||
}
|
||||
if (!Statement.productionDatabase()) {
|
||||
getServer().getPluginManager().registerEvents(new LocaleChangeWrapper(), this);
|
||||
}
|
||||
|
||||
getServer().getMessenger().registerIncomingPluginChannel(this, "sw:bridge", new NetworkReceiver());
|
||||
getServer().getMessenger().registerOutgoingPluginChannel(this, "sw:bridge");
|
||||
getServer().getMessenger().registerIncomingPluginChannel(this, "sw:bridge", new NetworkReceiver());
|
||||
getServer().getMessenger().registerOutgoingPluginChannel(this, "sw:bridge");
|
||||
|
||||
SteamwarGameProfileRepository.impl.inject();
|
||||
SteamwarGameProfileRepository.impl.inject();
|
||||
|
||||
TinyProtocol.init();
|
||||
CheckpointUtils.signalHandler();
|
||||
TinyProtocol.init();
|
||||
CheckpointUtils.signalHandler();
|
||||
|
||||
Bukkit.getScheduler().runTaskTimer(this, TabCompletionCache::invalidateOldEntries, 20, 20);
|
||||
Bukkit.getScheduler().runTaskTimer(Core.getInstance(), SteamwarUser::clear, 72000, 72000);
|
||||
Bukkit.getScheduler().runTaskTimer(Core.getInstance(), SchematicNode::clear, 20L * 30, 20L * 30);
|
||||
Bukkit.getScheduler().runTaskTimer(this, TabCompletionCache::invalidateOldEntries, 20, 20);
|
||||
Bukkit.getScheduler().runTaskTimer(Core.getInstance(), SteamwarUser::clear, 72000, 72000);
|
||||
Bukkit.getScheduler().runTaskTimer(Core.getInstance(), SchematicNode::clear, 20L * 30, 20L * 30);
|
||||
|
||||
try {
|
||||
getLogger().log(Level.INFO, "Running on: " + new BufferedReader(new InputStreamReader(Runtime.getRuntime().exec("hostname").getInputStream())).readLine());
|
||||
} catch (IOException e) {
|
||||
throw new SecurityException("Could not load Hostname", e);
|
||||
}
|
||||
}
|
||||
try {
|
||||
getLogger().log(Level.INFO, "Running on: " + new BufferedReader(new InputStreamReader(Runtime.getRuntime().exec("hostname").getInputStream())).readLine());
|
||||
} catch (IOException e) {
|
||||
throw new SecurityException("Could not load Hostname", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDisable() {
|
||||
TinyProtocol.instance.close();
|
||||
errorHandler.unregister();
|
||||
if(crashDetector.onMainThread())
|
||||
Statement.closeAll();
|
||||
}
|
||||
@Override
|
||||
public void onDisable() {
|
||||
TinyProtocol.instance.close();
|
||||
errorHandler.unregister();
|
||||
if (crashDetector.onMainThread())
|
||||
Statement.closeAll();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,7 +37,7 @@ public class CrashDetector {
|
||||
|
||||
private boolean run = true;
|
||||
|
||||
public CrashDetector () {
|
||||
public CrashDetector() {
|
||||
Bukkit.getScheduler().runTaskTimer(Core.getInstance(), () -> {
|
||||
lastTick.set(System.nanoTime());
|
||||
lastMessage.set(System.nanoTime());
|
||||
@@ -60,11 +60,11 @@ public class CrashDetector {
|
||||
SWException.init();
|
||||
while (run) {
|
||||
long curTime = System.nanoTime();
|
||||
if(curTime - 4*TIMEOUT >= lastTick.get()) {
|
||||
if (curTime - 4 * TIMEOUT >= lastTick.get()) {
|
||||
SWException.log("Server did not recover in " + ((curTime - lastTick.get()) / 1000000.0) + "ms, unclean server stop", "");
|
||||
hardStop();
|
||||
} else if(curTime - TIMEOUT > lastMessage.get()) {
|
||||
if(mainThread.isAlive()) {
|
||||
} else if (curTime - TIMEOUT > lastMessage.get()) {
|
||||
if (mainThread.isAlive()) {
|
||||
SWException.log("Server hung for " + ((curTime - lastTick.get()) / 1000000.0) + "ms", Arrays.stream(mainThread.getStackTrace()).map(StackTraceElement::toString).collect(Collectors.joining("\n")));
|
||||
} else {
|
||||
SWException.log("Server thread already dead, unclean server stop", "Core enabled: " + Core.getInstance().isEnabled());
|
||||
@@ -81,7 +81,7 @@ public class CrashDetector {
|
||||
}
|
||||
|
||||
private void hardStop() {
|
||||
if(Core.getInstance().isEnabled()) {
|
||||
if (Core.getInstance().isEnabled()) {
|
||||
Core.getInstance().onDisable();
|
||||
}
|
||||
Statement.closeAll();
|
||||
|
||||
@@ -37,7 +37,7 @@ public class ErrorHandler extends Handler {
|
||||
|
||||
private final long watchdogThreadId;
|
||||
|
||||
public ErrorHandler(){
|
||||
public ErrorHandler() {
|
||||
Logger.getLogger("").addHandler(this);
|
||||
|
||||
Reflection.Field<WatchdogThread> getInstance = Reflection.getField(WatchdogThread.class, WatchdogThread.class, 0);
|
||||
@@ -51,28 +51,28 @@ public class ErrorHandler extends Handler {
|
||||
@Override
|
||||
@SuppressWarnings("deprecation")
|
||||
public void publish(LogRecord logRecord) {
|
||||
if(logRecord.getLevel().intValue() < Level.WARNING.intValue())
|
||||
if (logRecord.getLevel().intValue() < Level.WARNING.intValue())
|
||||
return;
|
||||
|
||||
if(watchdogThreadId == logRecord.getThreadID())
|
||||
if (watchdogThreadId == logRecord.getThreadID())
|
||||
return;
|
||||
|
||||
String message = logRecord.getMessage() != null ? logRecord.getMessage() : "";
|
||||
for(String reason : ignoreStartsWith)
|
||||
if(message.startsWith(reason))
|
||||
for (String reason : ignoreStartsWith)
|
||||
if (message.startsWith(reason))
|
||||
return;
|
||||
for(String reason : ignoreContains)
|
||||
if(message.contains(reason))
|
||||
for (String reason : ignoreContains)
|
||||
if (message.contains(reason))
|
||||
return;
|
||||
|
||||
ByteArrayOutputStream stacktraceOutput = new ByteArrayOutputStream();
|
||||
if(logRecord.getThrown() != null)
|
||||
if (logRecord.getThrown() != null)
|
||||
logRecord.getThrown().printStackTrace(new PrintStream(stacktraceOutput));
|
||||
String stacktrace = stacktraceOutput.toString();
|
||||
if(stacktrace.contains("POI data mismatch") || stacktrace.contains("Newer version! Server downgrades are not supported!"))
|
||||
if (stacktrace.contains("POI data mismatch") || stacktrace.contains("Newer version! Server downgrades are not supported!"))
|
||||
return;
|
||||
|
||||
if(message.isEmpty() && stacktrace.isEmpty())
|
||||
if (message.isEmpty() && stacktrace.isEmpty())
|
||||
return;
|
||||
|
||||
try {
|
||||
|
||||
@@ -33,7 +33,7 @@ import java.util.EnumSet;
|
||||
public class ProtocolWrapper {
|
||||
|
||||
public Object playerInfoPacketConstructor(PlayerInfoAction action, GameProfile profile, GameMode mode) {
|
||||
if(action == PlayerInfoAction.REMOVE) {
|
||||
if (action == PlayerInfoAction.REMOVE) {
|
||||
return new ClientboundPlayerInfoRemovePacket(Collections.singletonList(profile.getId()));
|
||||
}
|
||||
|
||||
|
||||
@@ -144,7 +144,7 @@ public class SWPlayer {
|
||||
return this;
|
||||
}
|
||||
|
||||
private ThreadLocal<Message> messageThreadLocal = ThreadLocal.withInitial(() -> null);
|
||||
private ThreadLocal<Message> messageThreadLocal = ThreadLocal.withInitial(() -> null);
|
||||
|
||||
public SWPlayer using(Message message) {
|
||||
this.messageThreadLocal.set(message);
|
||||
@@ -153,7 +153,8 @@ public class SWPlayer {
|
||||
|
||||
private Message getMessage() {
|
||||
Message message = this.messageThreadLocal.get();
|
||||
if (message == null) throw new IllegalStateException("Use #using(Message) before sending or parsing a message!");
|
||||
if (message == null)
|
||||
throw new IllegalStateException("Use #using(Message) before sending or parsing a message!");
|
||||
return message;
|
||||
}
|
||||
|
||||
|
||||
@@ -89,7 +89,7 @@ public class WorldEditRenderer implements Listener {
|
||||
|
||||
private void renderRegion(Player player, LocalSession session, boolean scheduled) {
|
||||
World world = session.getSelectionWorld();
|
||||
if(world != null) {
|
||||
if (world != null) {
|
||||
RegionSelector regionSelector = session.getRegionSelector(world);
|
||||
try {
|
||||
Region region = regionSelector.getRegion();
|
||||
@@ -102,7 +102,7 @@ public class WorldEditRenderer implements Listener {
|
||||
|
||||
private void drawCuboid(Vector min, Vector max, boolean scheduled, boolean clipboard, Player owner) {
|
||||
//noinspection deprecation
|
||||
if(owner.getItemInHand().getType() != WAND) {
|
||||
if (owner.getItemInHand().getType() != WAND) {
|
||||
WorldEditRendererWrapper.impl.hide(owner, true, true);
|
||||
WorldEditRendererWrapper.impl.hide(owner, false, true);
|
||||
} else {
|
||||
@@ -114,7 +114,7 @@ public class WorldEditRenderer implements Listener {
|
||||
|
||||
@EventHandler
|
||||
public void onPlayerMove(PlayerMoveEvent event) {
|
||||
if(event.getPlayer().getItemInHand().getType() == WAND) {
|
||||
if (event.getPlayer().getItemInHand().getType() == WAND) {
|
||||
WorldEditRendererWrapper.impl.tick(event.getPlayer());
|
||||
}
|
||||
renderClipboard(event.getPlayer(), we.getSession(event.getPlayer()), false);
|
||||
|
||||
@@ -104,10 +104,10 @@ public class WorldEditRendererCUIEditor implements Listener {
|
||||
|
||||
@AllArgsConstructor
|
||||
public enum Width {
|
||||
HUGE(15, "WORLDEDIT_CUI_WIDTH_HUGE", 2/16f),
|
||||
LARGE(8, "WORLDEDIT_CUI_WIDTH_LARGE", 1/16f),
|
||||
MEDIUM(4, "WORLDEDIT_CUI_WIDTH_MEDIUM", 1/32f),
|
||||
SLIM(0, "WORLDEDIT_CUI_WIDTH_SLIM", 1/64f);
|
||||
HUGE(15, "WORLDEDIT_CUI_WIDTH_HUGE", 2 / 16f),
|
||||
LARGE(8, "WORLDEDIT_CUI_WIDTH_LARGE", 1 / 16f),
|
||||
MEDIUM(4, "WORLDEDIT_CUI_WIDTH_MEDIUM", 1 / 32f),
|
||||
SLIM(0, "WORLDEDIT_CUI_WIDTH_SLIM", 1 / 64f);
|
||||
|
||||
public final int lightLevel;
|
||||
public final String name;
|
||||
|
||||
@@ -187,7 +187,7 @@ public class WorldEditWrapper {
|
||||
}
|
||||
|
||||
Clipboard clipboard = clipboardHolder.getClipboard();
|
||||
if(clipboard == null)
|
||||
if (clipboard == null)
|
||||
throw new NoClipboardException();
|
||||
|
||||
PipedOutputStream outputStream = new PipedOutputStream();
|
||||
|
||||
+3
-3
@@ -48,16 +48,16 @@ public class SteamwarGameProfileRepository implements GameProfileRepository {
|
||||
@Override
|
||||
public void findProfilesByNames(String[] strings, ProfileLookupCallback profileLookupCallback) {
|
||||
List<String> unknownNames = new ArrayList<>();
|
||||
for (String name:strings) {
|
||||
for (String name : strings) {
|
||||
SteamwarUser user = SteamwarUser.get(name);
|
||||
if(user == null) {
|
||||
if (user == null) {
|
||||
unknownNames.add(name);
|
||||
continue;
|
||||
}
|
||||
|
||||
profileLookupCallback.onProfileLookupSucceeded(new GameProfile(user.getUUID(), user.getUserName()));
|
||||
}
|
||||
if(!unknownNames.isEmpty()) {
|
||||
if (!unknownNames.isEmpty()) {
|
||||
fallback.findProfilesByNames(unknownNames.toArray(new String[0]), profileLookupCallback);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -71,18 +71,19 @@ public class AntiNocom implements Listener {
|
||||
|
||||
private static final Class<?> blockDig = ServerboundPlayerActionPacket.class;
|
||||
private static final Reflection.Field<?> digPosition = Reflection.getField(blockDig, TechHider.blockPosition, 0);
|
||||
|
||||
private Object onDig(Player player, Object packet) {
|
||||
Object pos = digPosition.get(packet);
|
||||
return isValid(player, "Dig", TechHider.blockPositionX.get(pos), TechHider.blockPositionZ.get(pos)) ? packet : null;
|
||||
}
|
||||
|
||||
private boolean isValid(Player player, String type, int x, int z) {
|
||||
if((x == 0 && z == 0) || player.getWorld().isChunkLoaded(ProtocolUtils.posToChunk(x), ProtocolUtils.posToChunk(z)))
|
||||
if ((x == 0 && z == 0) || player.getWorld().isChunkLoaded(ProtocolUtils.posToChunk(x), ProtocolUtils.posToChunk(z)))
|
||||
return true;
|
||||
|
||||
int amount = flags.compute(player, (p, a) -> a == null ? 1 : a+1);
|
||||
if(amount % 8 == 0) { // Only after 8 and every 8 to reduce false flags and spam
|
||||
if(amount == 8) // Schedule player kick only once
|
||||
int amount = flags.compute(player, (p, a) -> a == null ? 1 : a + 1);
|
||||
if (amount % 8 == 0) { // Only after 8 and every 8 to reduce false flags and spam
|
||||
if (amount == 8) // Schedule player kick only once
|
||||
Bukkit.getScheduler().runTask(Core.getInstance(), () -> player.kickPlayer(null));
|
||||
|
||||
SWException.log(player.getName() + " kicked for potential NoCom-DOS attack", x + " " + z + " " + type + " " + amount);
|
||||
|
||||
@@ -29,9 +29,9 @@ import org.bukkit.event.player.AsyncPlayerChatEvent;
|
||||
@Linked
|
||||
public class ChattingEvent implements Listener {
|
||||
|
||||
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
|
||||
private void onChat(AsyncPlayerChatEvent event) {
|
||||
event.setCancelled(true);
|
||||
Core.MESSAGE.broadcastPrefixless("LOCAL_CHAT", event.getPlayer().getDisplayName(), event.getMessage());
|
||||
}
|
||||
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
|
||||
private void onChat(AsyncPlayerChatEvent event) {
|
||||
event.setCancelled(true);
|
||||
Core.MESSAGE.broadcastPrefixless("LOCAL_CHAT", event.getPlayer().getDisplayName(), event.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,28 +34,29 @@ import org.bukkit.event.player.PlayerJoinEvent;
|
||||
import org.bukkit.event.player.PlayerQuitEvent;
|
||||
|
||||
@Linked
|
||||
public class PlayerJoinedEvent implements Listener{
|
||||
public class PlayerJoinedEvent implements Listener {
|
||||
|
||||
@EventHandler(priority = EventPriority.LOWEST)
|
||||
private void onJoin(PlayerJoinEvent event) {
|
||||
Player player = event.getPlayer();
|
||||
SteamwarUser user = Statement.productionDatabase() ? SteamwarUser.get(player.getUniqueId()) : SteamwarUser.getOrCreate(player.getUniqueId(), player.getName(), uuid -> {});
|
||||
@EventHandler(priority = EventPriority.LOWEST)
|
||||
private void onJoin(PlayerJoinEvent event) {
|
||||
Player player = event.getPlayer();
|
||||
SteamwarUser user = Statement.productionDatabase() ? SteamwarUser.get(player.getUniqueId()) : SteamwarUser.getOrCreate(player.getUniqueId(), player.getName(), uuid -> {
|
||||
});
|
||||
|
||||
UserPerm.Prefix prefix = user.prefix();
|
||||
if(prefix != UserPerm.emptyPrefix) {
|
||||
player.setDisplayName(prefix.getColorCode() + prefix.getChatPrefix() + " " + player.getName() + "§r");
|
||||
} else
|
||||
player.setDisplayName(prefix.getColorCode() + player.getName() + "§r");
|
||||
UserPerm.Prefix prefix = user.prefix();
|
||||
if (prefix != UserPerm.emptyPrefix) {
|
||||
player.setDisplayName(prefix.getColorCode() + prefix.getChatPrefix() + " " + player.getName() + "§r");
|
||||
} else
|
||||
player.setDisplayName(prefix.getColorCode() + player.getName() + "§r");
|
||||
|
||||
event.setJoinMessage("§a§l» §r" + player.getDisplayName());
|
||||
AuditLog.createJoin(Core.getServerName(), BauServerInfo.getOwnerUser(), user);
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.LOWEST)
|
||||
private void onQuit(PlayerQuitEvent event) {
|
||||
Player player = event.getPlayer();
|
||||
event.setJoinMessage("§a§l» §r" + player.getDisplayName());
|
||||
AuditLog.createJoin(Core.getServerName(), BauServerInfo.getOwnerUser(), user);
|
||||
}
|
||||
|
||||
event.setQuitMessage("§c§l« §r" + player.getDisplayName());
|
||||
AuditLog.createLeave(Core.getServerName(), BauServerInfo.getOwnerUser(), SteamwarUser.get(player.getUniqueId()));
|
||||
}
|
||||
@EventHandler(priority = EventPriority.LOWEST)
|
||||
private void onQuit(PlayerQuitEvent event) {
|
||||
Player player = event.getPlayer();
|
||||
|
||||
event.setQuitMessage("§c§l« §r" + player.getDisplayName());
|
||||
AuditLog.createLeave(Core.getServerName(), BauServerInfo.getOwnerUser(), SteamwarUser.get(player.getUniqueId()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,8 +28,8 @@ import org.bukkit.event.world.WorldInitEvent;
|
||||
public class WorldLoadEvent implements Listener {
|
||||
|
||||
@EventHandler
|
||||
public void onWorldInit(WorldInitEvent e){
|
||||
if(Integer.parseInt(System.getProperty("fightID", "0")) != -1) // On testarenas not
|
||||
public void onWorldInit(WorldInitEvent e) {
|
||||
if (Integer.parseInt(System.getProperty("fightID", "0")) != -1) // On testarenas not
|
||||
e.getWorld().setKeepSpawnInMemory(false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -126,6 +126,7 @@ public class CLine extends CEntity {
|
||||
}
|
||||
|
||||
private RBlockDisplay startLine;
|
||||
|
||||
private void updateStart() {
|
||||
Vector vec = to.clone().subtract(from).toVector();
|
||||
if (vec.length() > 35) vec.normalize().multiply(35);
|
||||
@@ -145,6 +146,7 @@ public class CLine extends CEntity {
|
||||
}
|
||||
|
||||
private RBlockDisplay middleLine;
|
||||
|
||||
private void updateMiddle() {
|
||||
Vector vec = to.clone().subtract(from).toVector();
|
||||
if (vec.length() <= 70) {
|
||||
@@ -228,6 +230,7 @@ public class CLine extends CEntity {
|
||||
}
|
||||
|
||||
private RBlockDisplay endLine;
|
||||
|
||||
private void updateEnd() {
|
||||
Vector vec = to.clone().subtract(from).toVector();
|
||||
if (vec.length() <= 35) {
|
||||
|
||||
@@ -44,7 +44,7 @@ public class RArmorStand extends REntity {
|
||||
void spawn(Consumer<Object> packetSink) {
|
||||
super.spawn(packetSink);
|
||||
|
||||
if(size != null && size != Size.NORMAL)
|
||||
if (size != null && size != Size.NORMAL)
|
||||
packetSink.accept(getDataWatcherPacket(sizeWatcher, size.value));
|
||||
}
|
||||
|
||||
|
||||
@@ -60,6 +60,7 @@ public class RBlockDisplay extends RDisplay {
|
||||
}
|
||||
|
||||
private static final EntityDataAccessor<BlockState> blockWatcher = new EntityDataAccessor<>(23, EntityDataSerializers.BLOCK_STATE);
|
||||
|
||||
private void getBlock(boolean ignoreDefault, BiConsumer<Object, Object> packetSink) {
|
||||
if (ignoreDefault || !block.getAsString(true).equals(DEFAULT_BLOCK.getAsString(true))) {
|
||||
packetSink.accept(blockWatcher, ((CraftBlockData) block).getState());
|
||||
|
||||
@@ -94,15 +94,15 @@ public class REntity {
|
||||
protected final Map<Object, ItemStack> itemSlots;
|
||||
|
||||
public REntity(REntityServer server, EntityType entityType, Location location) {
|
||||
this(server,entityType,location,0);
|
||||
this(server, entityType, location, 0);
|
||||
server.addEntity(this);
|
||||
}
|
||||
|
||||
protected REntity(REntityServer server, EntityType entityType, Location location,int objectData) {
|
||||
this(server, entityType, new UUID(random.nextLong() & -61441L | 16384L, random.nextLong() & 4611686018427387903L | -9223372036854775808L), location,objectData);
|
||||
protected REntity(REntityServer server, EntityType entityType, Location location, int objectData) {
|
||||
this(server, entityType, new UUID(random.nextLong() & -61441L | 16384L, random.nextLong() & 4611686018427387903L | -9223372036854775808L), location, objectData);
|
||||
}
|
||||
|
||||
protected REntity(REntityServer server, EntityType entityType, UUID uuid, Location location,int objectData) {
|
||||
protected REntity(REntityServer server, EntityType entityType, UUID uuid, Location location, int objectData) {
|
||||
this.server = server;
|
||||
this.entityType = entityType;
|
||||
this.entityId = entityIdCounter--;
|
||||
@@ -123,10 +123,10 @@ public class REntity {
|
||||
}
|
||||
|
||||
public void hide(boolean hide) {
|
||||
if(hidden == hide)
|
||||
if (hidden == hide)
|
||||
return;
|
||||
|
||||
if(hide) {
|
||||
if (hide) {
|
||||
despawn(packet -> server.updateEntity(this, packet));
|
||||
hidden = true;
|
||||
} else {
|
||||
@@ -140,6 +140,7 @@ public class REntity {
|
||||
}
|
||||
|
||||
private static final double MAX_REL_MOVE = 8.0;
|
||||
|
||||
public void move(double locX, double locY, double locZ, float pitch, float yaw, byte headYaw) {
|
||||
server.preEntityMove(this, locX, locZ);
|
||||
|
||||
@@ -156,16 +157,16 @@ public class REntity {
|
||||
this.yaw = rotToByte(yaw);
|
||||
this.pitch = rotToByte(pitch);
|
||||
|
||||
if(Math.abs(diffX) < MAX_REL_MOVE && Math.abs(diffY) < MAX_REL_MOVE && Math.abs(diffZ) < MAX_REL_MOVE) {
|
||||
Object packet = getMoveLookPacket(diffX, diffY, diffZ,rotEq);
|
||||
if (Math.abs(diffX) < MAX_REL_MOVE && Math.abs(diffY) < MAX_REL_MOVE && Math.abs(diffZ) < MAX_REL_MOVE) {
|
||||
Object packet = getMoveLookPacket(diffX, diffY, diffZ, rotEq);
|
||||
|
||||
if(packet != null)
|
||||
if (packet != null)
|
||||
server.updateEntity(this, packet);
|
||||
} else {
|
||||
server.updateEntity(this, getTeleportPacket());
|
||||
}
|
||||
|
||||
if(this.headYaw != headYaw) {
|
||||
if (this.headYaw != headYaw) {
|
||||
this.headYaw = headYaw;
|
||||
server.updateEntity(this, getHeadRotationPacket());
|
||||
}
|
||||
@@ -176,6 +177,7 @@ public class REntity {
|
||||
private static final Class<?> animationPacket = ClientboundAnimatePacket.class;
|
||||
private static final Reflection.Field<Integer> animationEntity = Reflection.getField(animationPacket, int.class, 5);
|
||||
private static final Reflection.Field<Integer> animationAnimation = Reflection.getField(animationPacket, int.class, 6);
|
||||
|
||||
public void showAnimation(byte animation) {
|
||||
Object packet = Reflection.newInstance(animationPacket);
|
||||
animationEntity.set(packet, entityId);
|
||||
@@ -190,6 +192,7 @@ public class REntity {
|
||||
private static final Class<?> statusPacket = ClientboundEntityEventPacket.class;
|
||||
private static final Reflection.Field<Integer> statusEntity = Reflection.getField(statusPacket, int.class, 0);
|
||||
private static final Reflection.Field<Byte> statusStatus = Reflection.getField(statusPacket, byte.class, 0);
|
||||
|
||||
public void showDamage() {
|
||||
Object packet = Reflection.newInstance(statusPacket);
|
||||
statusEntity.set(packet, entityId);
|
||||
@@ -240,12 +243,12 @@ public class REntity {
|
||||
|
||||
public void setNoGravity(boolean noGravity) {
|
||||
this.noGravity = noGravity;
|
||||
server.updateEntity(this,getDataWatcherPacket(noGravityDataWatcher,noGravity));
|
||||
server.updateEntity(this, getDataWatcherPacket(noGravityDataWatcher, noGravity));
|
||||
}
|
||||
|
||||
public void setGlowing(boolean glowing) {
|
||||
this.isGlowing = glowing;
|
||||
server.updateEntity(this,getDataWatcherPacket(entityStatusWatcher,getEntityStatus()));
|
||||
server.updateEntity(this, getDataWatcherPacket(entityStatusWatcher, getEntityStatus()));
|
||||
}
|
||||
|
||||
private static final Function<REntity, Object> spawnPacketGenerator = entitySpawnPacketGenerator(ClientboundAddEntityPacket.class, 2);
|
||||
@@ -268,38 +271,38 @@ public class REntity {
|
||||
}
|
||||
|
||||
protected void postSpawn(Consumer<Object> packetSink) {
|
||||
if(headYaw != 0) {
|
||||
if (headYaw != 0) {
|
||||
packetSink.accept(getHeadRotationPacket());
|
||||
}
|
||||
|
||||
if(pose != Pose.STANDING) {
|
||||
if (pose != Pose.STANDING) {
|
||||
packetSink.accept(getDataWatcherPacket(poseDataWatcher, pose));
|
||||
}
|
||||
|
||||
byte status = getEntityStatus();
|
||||
if(status != 0) {
|
||||
if (status != 0) {
|
||||
packetSink.accept(getDataWatcherPacket(entityStatusWatcher, getEntityStatus()));
|
||||
}
|
||||
|
||||
if(displayName != null) {
|
||||
if (displayName != null) {
|
||||
packetSink.accept(getDataWatcherPacket(nameWatcher, FlatteningWrapper.formatDisplayName(displayName), nameVisibleWatcher, true));
|
||||
}
|
||||
|
||||
if(noGravity) {
|
||||
if (noGravity) {
|
||||
packetSink.accept(getDataWatcherPacket(noGravityDataWatcher, true));
|
||||
}
|
||||
}
|
||||
|
||||
void tick() {
|
||||
if(fireTick > 0) {
|
||||
if (fireTick > 0) {
|
||||
fireTick--;
|
||||
if(fireTick == 0) {
|
||||
if (fireTick == 0) {
|
||||
server.updateEntity(this, getDataWatcherPacket(entityStatusWatcher, getEntityStatus()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void despawn(Consumer<Object> packetSink){
|
||||
void despawn(Consumer<Object> packetSink) {
|
||||
packetSink.accept(new ClientboundRemoveEntitiesPacket(new IntArrayList(new int[]{entityId})));
|
||||
}
|
||||
|
||||
@@ -318,13 +321,13 @@ public class REntity {
|
||||
private byte getEntityStatus() {
|
||||
byte status = 0;
|
||||
|
||||
if(fireTick != 0)
|
||||
if (fireTick != 0)
|
||||
status |= 1;
|
||||
if(pose == Pose.CROUCHING)
|
||||
if (pose == Pose.CROUCHING)
|
||||
status |= 2;
|
||||
if(invisible)
|
||||
if (invisible)
|
||||
status |= 0x20;
|
||||
if(isGlowing)
|
||||
if (isGlowing)
|
||||
status |= 0x40;
|
||||
|
||||
return status;
|
||||
@@ -332,27 +335,27 @@ public class REntity {
|
||||
|
||||
protected Object getDataWatcherPacket(Object... dataWatcherKeyValues) {
|
||||
ArrayList<SynchedEntityData.DataValue<?>> nativeWatchers = new ArrayList<>(1);
|
||||
for(int i = 0; i < dataWatcherKeyValues.length; i+=2) {
|
||||
nativeWatchers.add(((SynchedEntityData.DataItem<?>) BountifulWrapper.impl.getDataWatcherItem(dataWatcherKeyValues[i], dataWatcherKeyValues[i+1])).value());
|
||||
for (int i = 0; i < dataWatcherKeyValues.length; i += 2) {
|
||||
nativeWatchers.add(((SynchedEntityData.DataItem<?>) BountifulWrapper.impl.getDataWatcherItem(dataWatcherKeyValues[i], dataWatcherKeyValues[i + 1])).value());
|
||||
}
|
||||
|
||||
return new ClientboundSetEntityDataPacket(entityId, nativeWatchers);
|
||||
}
|
||||
|
||||
private Object getTeleportPacket(){
|
||||
private Object getTeleportPacket() {
|
||||
PositionMoveRotation rot = new PositionMoveRotation(new Vec3(x, y, z), Vec3.ZERO, pitch, yaw);
|
||||
return new ClientboundTeleportEntityPacket(entityId, rot, Collections.emptySet(), false);
|
||||
}
|
||||
|
||||
private Object getMoveLookPacket(double diffX, double diffY, double diffZ, boolean rotEq) {
|
||||
short x = (short)(this.x*4096);
|
||||
short y = (short)(this.y*4096);
|
||||
short z = (short)(this.z*4096);
|
||||
byte yaw = (byte)(this.yaw*256/360);
|
||||
byte pitch = (byte)(this.pitch*256/360);
|
||||
short x = (short) (this.x * 4096);
|
||||
short y = (short) (this.y * 4096);
|
||||
short z = (short) (this.z * 4096);
|
||||
byte yaw = (byte) (this.yaw * 256 / 360);
|
||||
byte pitch = (byte) (this.pitch * 256 / 360);
|
||||
|
||||
if(diffX == 0 && diffY == 0 && diffZ == 0) {
|
||||
if(rotEq) return null;
|
||||
if (diffX == 0 && diffY == 0 && diffZ == 0) {
|
||||
if (rotEq) return null;
|
||||
return new ClientboundMoveEntityPacket.Rot(entityId, pitch, yaw, false);
|
||||
} else if (rotEq) {
|
||||
return new ClientboundMoveEntityPacket.Pos(entityId, x, y, z, false);
|
||||
@@ -364,7 +367,8 @@ public class REntity {
|
||||
private static final Class<?> headRotationPacket = ClientboundRotateHeadPacket.class;
|
||||
private static final Reflection.Field<Integer> headRotationEntity = Reflection.getField(headRotationPacket, int.class, 0);
|
||||
private static final Reflection.Field<Byte> headRotationYaw = Reflection.getField(headRotationPacket, byte.class, 0);
|
||||
private Object getHeadRotationPacket(){
|
||||
|
||||
private Object getHeadRotationPacket() {
|
||||
Object packet = Reflection.newInstance(headRotationPacket);
|
||||
headRotationEntity.set(packet, entityId);
|
||||
headRotationYaw.set(packet, headYaw);
|
||||
@@ -376,6 +380,7 @@ public class REntity {
|
||||
}
|
||||
|
||||
private static final Reflection.Field<net.minecraft.world.entity.EntityType> spawnType = Reflection.getField(ClientboundAddEntityPacket.class, net.minecraft.world.entity.EntityType.class, 0);
|
||||
|
||||
private static Function<REntity, Object> entitySpawnPacketGenerator(Class<?> spawnPacket, int posOffset) {
|
||||
BountifulWrapper.UUIDSetter uuid = BountifulWrapper.impl.getUUIDSetter(spawnPacket);
|
||||
Function<REntity, Object> packetGenerator = spawnPacketGenerator(spawnPacket, posOffset);
|
||||
@@ -402,10 +407,10 @@ public class REntity {
|
||||
}
|
||||
|
||||
private byte rotToByte(float rot) {
|
||||
return (byte)((int)(rot * 256.0F / 360.0F));
|
||||
return (byte) ((int) (rot * 256.0F / 360.0F));
|
||||
}
|
||||
|
||||
private int calcVelocity(double value) {
|
||||
return (int)(Math.max(-3.9, Math.min(value, 3.9)) * 8000);
|
||||
return (int) (Math.max(-3.9, Math.min(value, 3.9)) * 8000);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -79,7 +79,7 @@ public class REntityServer implements Listener {
|
||||
boolean uninitialized = this.callback == null;
|
||||
this.callback = callback;
|
||||
|
||||
if(uninitialized)
|
||||
if (uninitialized)
|
||||
TinyProtocol.instance.addTypedFilter(ServerboundInteractPacket.class, filter);
|
||||
}
|
||||
|
||||
@@ -104,7 +104,7 @@ public class REntityServer implements Listener {
|
||||
|
||||
public void close() {
|
||||
TinyProtocol.instance.removeFilter(ServerboundInteractPacket.class, filter);
|
||||
for(Player player : lastLocation.keySet().toArray(new Player[0])) {
|
||||
for (Player player : lastLocation.keySet().toArray(new Player[0])) {
|
||||
removePlayer(player);
|
||||
}
|
||||
HandlerList.unregisterAll(this);
|
||||
@@ -120,10 +120,10 @@ public class REntityServer implements Listener {
|
||||
void preEntityMove(REntity entity, double toX, double toZ) {
|
||||
long fromId = entityToId(entity);
|
||||
long toId = posToId(toX, toZ);
|
||||
if(fromId == toId)
|
||||
if (fromId == toId)
|
||||
return;
|
||||
|
||||
if(!entity.isHidden())
|
||||
if (!entity.isHidden())
|
||||
onMissing(players.get(fromId), players.get(toId), entity::despawn);
|
||||
onMissing(players.get(fromId), players.get(toId), entity::delist);
|
||||
removeEntityFromChunk(entity);
|
||||
@@ -132,20 +132,20 @@ public class REntityServer implements Listener {
|
||||
void postEntityMove(REntity entity, double fromX, double fromZ) {
|
||||
long fromId = posToId(fromX, fromZ);
|
||||
long toId = entityToId(entity);
|
||||
if(fromId == toId)
|
||||
if (fromId == toId)
|
||||
return;
|
||||
|
||||
addEntityToChunk(entity);
|
||||
onMissing(players.get(toId), players.get(fromId), entity::list);
|
||||
if(!entity.isHidden())
|
||||
if (!entity.isHidden())
|
||||
onMissing(players.get(toId), players.get(fromId), entity::spawn);
|
||||
}
|
||||
|
||||
void updateEntity(REntity entity, Object packet) {
|
||||
if(entity.isHidden())
|
||||
if (entity.isHidden())
|
||||
return;
|
||||
|
||||
for(Player player : players.getOrDefault(entityToId(entity), emptyPlayers)) {
|
||||
for (Player player : players.getOrDefault(entityToId(entity), emptyPlayers)) {
|
||||
TinyProtocol.instance.sendPacket(player, packet);
|
||||
}
|
||||
}
|
||||
@@ -174,7 +174,7 @@ public class REntityServer implements Listener {
|
||||
HashSet<REntity> entitiesInChunk = entities.get(id);
|
||||
if (entitiesInChunk == null) return;
|
||||
entitiesInChunk.remove(entity);
|
||||
if(entitiesInChunk.isEmpty())
|
||||
if (entitiesInChunk.isEmpty())
|
||||
entities.remove(id);
|
||||
}
|
||||
|
||||
@@ -183,28 +183,28 @@ public class REntityServer implements Listener {
|
||||
Player player = e.getPlayer();
|
||||
Location from = lastLocation.get(player);
|
||||
Location to = e.getTo();
|
||||
if(from == null || to == null)
|
||||
if (from == null || to == null)
|
||||
return;
|
||||
|
||||
int fromX = posToChunk(from.getX());
|
||||
int fromZ = posToChunk(from.getZ());
|
||||
int toX = posToChunk(to.getX());
|
||||
int toZ = posToChunk(to.getZ());
|
||||
if(fromX == toX && fromZ == toZ)
|
||||
if (fromX == toX && fromZ == toZ)
|
||||
return;
|
||||
|
||||
lastLocation.put(player, to);
|
||||
|
||||
int toViewDistance = viewRadius(player);
|
||||
forChunkInView(player, from, (x, z) -> {
|
||||
if(Math.abs(x - toX) > toViewDistance || Math.abs(z - toZ) > toViewDistance) {
|
||||
if (Math.abs(x - toX) > toViewDistance || Math.abs(z - toZ) > toViewDistance) {
|
||||
removePlayerFromChunk(player, x, z);
|
||||
}
|
||||
});
|
||||
|
||||
int fromViewDistance = this.viewDistance.put(player, toViewDistance);
|
||||
forChunkInView(player, to, (x, z) -> {
|
||||
if(Math.abs(x - fromX) > fromViewDistance || Math.abs(z - fromZ) > fromViewDistance) {
|
||||
if (Math.abs(x - fromX) > fromViewDistance || Math.abs(z - fromZ) > fromViewDistance) {
|
||||
addPlayerToChunk(player, x, z);
|
||||
}
|
||||
});
|
||||
@@ -214,25 +214,25 @@ public class REntityServer implements Listener {
|
||||
public void onQuit(PlayerQuitEvent e) {
|
||||
Player player = e.getPlayer();
|
||||
Location location = lastLocation.remove(player);
|
||||
if(location == null)
|
||||
if (location == null)
|
||||
return;
|
||||
|
||||
forChunkInView(player, location, (x, z) -> {
|
||||
long id = chunkToId(x, z);
|
||||
Set<Player> playersInChunk = players.get(id);
|
||||
playersInChunk.remove(player);
|
||||
if(playersInChunk.isEmpty())
|
||||
if (playersInChunk.isEmpty())
|
||||
players.remove(id);
|
||||
});
|
||||
viewDistance.remove(player);
|
||||
}
|
||||
|
||||
private void onMissing(Set<Player> of, Set<Player> in, Consumer<Consumer<Object>> packetProvider) {
|
||||
if(of == null)
|
||||
if (of == null)
|
||||
return;
|
||||
|
||||
for(Player player : of) {
|
||||
if(in == null || !in.contains(player)) {
|
||||
for (Player player : of) {
|
||||
if (in == null || !in.contains(player)) {
|
||||
packetProvider.accept(packet -> TinyProtocol.instance.sendPacket(player, packet));
|
||||
}
|
||||
}
|
||||
@@ -243,8 +243,8 @@ public class REntityServer implements Listener {
|
||||
int chunkZ = posToChunk(location.getZ());
|
||||
int viewDistance = this.viewDistance.get(player);
|
||||
|
||||
for(int x = chunkX - viewDistance; x <= chunkX + viewDistance; x++) {
|
||||
for(int z = chunkZ - viewDistance; z <= chunkZ + viewDistance; z++) {
|
||||
for (int x = chunkX - viewDistance; x <= chunkX + viewDistance; x++) {
|
||||
for (int z = chunkZ - viewDistance; z <= chunkZ + viewDistance; z++) {
|
||||
func.accept(x, z);
|
||||
}
|
||||
}
|
||||
@@ -253,9 +253,9 @@ public class REntityServer implements Listener {
|
||||
private void addPlayerToChunk(Player player, int x, int z) {
|
||||
long id = chunkToId(x, z);
|
||||
players.computeIfAbsent(id, i -> new HashSet<>()).add(player);
|
||||
for(REntity entity : entities.getOrDefault(id, emptyEntities)) {
|
||||
for (REntity entity : entities.getOrDefault(id, emptyEntities)) {
|
||||
entity.list(packet -> TinyProtocol.instance.sendPacket(player, packet));
|
||||
if(!entity.isHidden())
|
||||
if (!entity.isHidden())
|
||||
entity.spawn(packet -> TinyProtocol.instance.sendPacket(player, packet));
|
||||
}
|
||||
}
|
||||
@@ -265,11 +265,11 @@ public class REntityServer implements Listener {
|
||||
|
||||
Set<Player> playersInChunk = players.get(id);
|
||||
playersInChunk.remove(player);
|
||||
if(playersInChunk.isEmpty())
|
||||
if (playersInChunk.isEmpty())
|
||||
players.remove(id);
|
||||
|
||||
for(REntity entity : entities.getOrDefault(id, emptyEntities)) {
|
||||
if(!entity.isHidden())
|
||||
for (REntity entity : entities.getOrDefault(id, emptyEntities)) {
|
||||
if (!entity.isHidden())
|
||||
entity.despawn(packet -> TinyProtocol.instance.sendPacket(player, packet));
|
||||
entity.delist(packet -> TinyProtocol.instance.sendPacket(player, packet));
|
||||
}
|
||||
@@ -282,7 +282,7 @@ public class REntityServer implements Listener {
|
||||
}
|
||||
|
||||
private int posToChunk(double coord) {
|
||||
return (int)(coord / 16) - (coord < 0 ? 1 : 0);
|
||||
return (int) (coord / 16) - (coord < 0 ? 1 : 0);
|
||||
}
|
||||
|
||||
private int viewRadius(Player player) {
|
||||
|
||||
@@ -26,7 +26,7 @@ import org.bukkit.Material;
|
||||
import org.bukkit.entity.EntityType;
|
||||
|
||||
@Getter
|
||||
public class RFallingBlockEntity extends REntity{
|
||||
public class RFallingBlockEntity extends REntity {
|
||||
|
||||
private final Material material;
|
||||
|
||||
|
||||
@@ -62,6 +62,7 @@ public class RItemDisplay extends RDisplay {
|
||||
}
|
||||
|
||||
private static final EntityDataAccessor<net.minecraft.world.item.ItemStack> itemStackWatcher = new EntityDataAccessor<>(23, EntityDataSerializers.ITEM_STACK);
|
||||
|
||||
private void getItemStack(boolean ignoreDefault, BiConsumer<Object, Object> packetSink) {
|
||||
if (ignoreDefault || !itemStack.equals(DEFAULT_ITEM_STACK)) {
|
||||
packetSink.accept(itemStackWatcher, CraftItemStack.asNMSCopy(itemStack));
|
||||
@@ -69,6 +70,7 @@ public class RItemDisplay extends RDisplay {
|
||||
}
|
||||
|
||||
private static final EntityDataAccessor<Byte> itemDisplayTransformWatcher = new EntityDataAccessor<>(24, EntityDataSerializers.BYTE);
|
||||
|
||||
public void setItemDisplayTransform(ItemDisplay.ItemDisplayTransform itemDisplayTransform) {
|
||||
this.itemDisplayTransform = itemDisplayTransform;
|
||||
sendPacket(updatePacketSink, this::getItemDisplayTransform);
|
||||
|
||||
@@ -49,7 +49,7 @@ public class RPlayer extends REntity {
|
||||
private final String name;
|
||||
|
||||
public RPlayer(REntityServer server, UUID uuid, String name, Location location) {
|
||||
super(server, EntityType.PLAYER, UUID.nameUUIDFromBytes(uuid.toString().getBytes(StandardCharsets.UTF_8)), location,0);
|
||||
super(server, EntityType.PLAYER, UUID.nameUUIDFromBytes(uuid.toString().getBytes(StandardCharsets.UTF_8)), location, 0);
|
||||
this.actualUUID = uuid;
|
||||
this.name = name;
|
||||
server.addEntity(this);
|
||||
|
||||
@@ -76,6 +76,7 @@ public class RTextDisplay extends RDisplay {
|
||||
}
|
||||
|
||||
private static final EntityDataAccessor<Component> textWatcher = new EntityDataAccessor<>(23, EntityDataSerializers.COMPONENT);
|
||||
|
||||
private void getText(boolean ignoreDefault, BiConsumer<Object, Object> packetSink) {
|
||||
if (ignoreDefault || !text.isEmpty()) {
|
||||
packetSink.accept(textWatcher, MutableComponent.create(PlainTextContents.create(text)));
|
||||
@@ -88,6 +89,7 @@ public class RTextDisplay extends RDisplay {
|
||||
}
|
||||
|
||||
private static final EntityDataAccessor<Integer> lineWidthWatcher = new EntityDataAccessor<>(24, EntityDataSerializers.INT);
|
||||
|
||||
private void getLineWidth(boolean ignoreDefault, BiConsumer<Object, Object> packetSink) {
|
||||
if (ignoreDefault || lineWidth != 200) {
|
||||
packetSink.accept(lineWidthWatcher, lineWidth);
|
||||
@@ -100,6 +102,7 @@ public class RTextDisplay extends RDisplay {
|
||||
}
|
||||
|
||||
private static final EntityDataAccessor<Byte> textOpacityWatcher = new EntityDataAccessor<>(26, EntityDataSerializers.BYTE);
|
||||
|
||||
private void getTextOpacity(boolean ignoreDefault, BiConsumer<Object, Object> packetSink) {
|
||||
if (ignoreDefault || textOpacity != (byte) -1) {
|
||||
packetSink.accept(textOpacityWatcher, textOpacity);
|
||||
@@ -122,6 +125,7 @@ public class RTextDisplay extends RDisplay {
|
||||
}
|
||||
|
||||
private static final EntityDataAccessor<Integer> backgroundColorWatcher = new EntityDataAccessor<>(25, EntityDataSerializers.INT);
|
||||
|
||||
private void getBackgroundColor(boolean ignoreDefault, BiConsumer<Object, Object> packetSink) {
|
||||
if (ignoreDefault || backgroundColor != null) {
|
||||
packetSink.accept(backgroundColorWatcher, backgroundColor);
|
||||
@@ -141,6 +145,7 @@ public class RTextDisplay extends RDisplay {
|
||||
}
|
||||
|
||||
private static final EntityDataAccessor<Byte> textStatusWatcher = new EntityDataAccessor<>(27, EntityDataSerializers.BYTE);
|
||||
|
||||
private void getTextStatus(boolean ignoreDefault, BiConsumer<Object, Object> packetSink) {
|
||||
byte status = 0;
|
||||
|
||||
|
||||
@@ -57,7 +57,7 @@ public class SWAnvilInv {
|
||||
}
|
||||
|
||||
public void setItem(Material m, List<String> lore, boolean e) {
|
||||
setItem(m, (byte)0, lore, e);
|
||||
setItem(m, (byte) 0, lore, e);
|
||||
}
|
||||
|
||||
public void setItem(Material m, byte meta, List<String> lore, boolean e) {
|
||||
@@ -82,15 +82,15 @@ public class SWAnvilInv {
|
||||
}
|
||||
|
||||
private List<AnvilGUI.ResponseAction> onResult(Integer slot, AnvilGUI.StateSnapshot state) {
|
||||
if(slot != AnvilGUI.Slot.OUTPUT) {
|
||||
if(slot == AnvilGUI.Slot.INPUT_LEFT && leftCallback != null)
|
||||
if (slot != AnvilGUI.Slot.OUTPUT) {
|
||||
if (slot == AnvilGUI.Slot.INPUT_LEFT && leftCallback != null)
|
||||
leftCallback.run();
|
||||
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
String s = state.getText();
|
||||
if(s.startsWith("»"))
|
||||
if (s.startsWith("»"))
|
||||
s = s.substring(1);
|
||||
callback.accept(s);
|
||||
player.setLevel(0);
|
||||
|
||||
@@ -79,7 +79,7 @@ public class SWInventory implements Listener {
|
||||
|
||||
public void setItem(int pos, ItemStack itemStack, InvCallback c) {
|
||||
inventory.setItem(pos, itemStack);
|
||||
if(c != null) {
|
||||
if (c != null) {
|
||||
callbacks.put(pos, inventoryClickEvent -> c.clicked(inventoryClickEvent.getClick()));
|
||||
} else {
|
||||
callbacks.remove(pos);
|
||||
@@ -94,11 +94,11 @@ public class SWInventory implements Listener {
|
||||
setItem(pos, item.getItemStack(), item.getCallback());
|
||||
}
|
||||
|
||||
public void setItem(int pos, Material m, String name, InvCallback c){
|
||||
public void setItem(int pos, Material m, String name, InvCallback c) {
|
||||
setItem(pos, m, name, new ArrayList<>(), false, c);
|
||||
}
|
||||
|
||||
public void setItem(int pos, Material m, byte meta, String name, InvCallback c){
|
||||
public void setItem(int pos, Material m, byte meta, String name, InvCallback c) {
|
||||
setItem(pos, m, meta, name, new ArrayList<>(), false, c);
|
||||
}
|
||||
|
||||
@@ -147,7 +147,7 @@ public class SWInventory implements Listener {
|
||||
InventoryView view = player.openInventory(inventory);
|
||||
title = view.getTitle();
|
||||
Core.getInstance().getLogger().info("[SWINV] Opened " + title + " for " + player.getName());
|
||||
if(!open) {
|
||||
if (!open) {
|
||||
Bukkit.getPluginManager().registerEvents(this, Core.getInstance());
|
||||
open = true;
|
||||
}
|
||||
@@ -168,14 +168,14 @@ public class SWInventory implements Listener {
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onInventoryClose(InventoryCloseEvent e){
|
||||
if(!player.equals(e.getPlayer()))
|
||||
public void onInventoryClose(InventoryCloseEvent e) {
|
||||
if (!player.equals(e.getPlayer()))
|
||||
return;
|
||||
|
||||
InventoryClickEvent.getHandlerList().unregister(this);
|
||||
InventoryCloseEvent.getHandlerList().unregister(this);
|
||||
Core.getInstance().getLogger().info("[SWINV] " + player.getName() + " closed " + title);
|
||||
if(callbacks.containsKey(-1)) {
|
||||
if (callbacks.containsKey(-1)) {
|
||||
callbacks.get(-1).accept(null);
|
||||
}
|
||||
open = false;
|
||||
|
||||
@@ -43,11 +43,11 @@ public class SWItem {
|
||||
private ItemMeta itemMeta;
|
||||
private InvCallback callback;
|
||||
|
||||
public static SWItem getPlayerSkull(OfflinePlayer player){
|
||||
public static SWItem getPlayerSkull(OfflinePlayer player) {
|
||||
return getPlayerSkull(player.getName());
|
||||
}
|
||||
|
||||
public static SWItem getPlayerSkull(String playerName){
|
||||
public static SWItem getPlayerSkull(String playerName) {
|
||||
SWItem p = new SWItem();
|
||||
ItemStack head = new ItemStack(Material.PLAYER_HEAD, 1);
|
||||
head.editMeta(SkullMeta.class, skullMeta -> {
|
||||
@@ -64,10 +64,10 @@ public class SWItem {
|
||||
return p;
|
||||
}
|
||||
|
||||
public static Material getMaterial(String material){
|
||||
try{
|
||||
public static Material getMaterial(String material) {
|
||||
try {
|
||||
return Material.valueOf(material);
|
||||
}catch(IllegalArgumentException e){
|
||||
} catch (IllegalArgumentException e) {
|
||||
return Material.BARRIER;
|
||||
}
|
||||
}
|
||||
@@ -78,31 +78,31 @@ public class SWItem {
|
||||
hideAttributes();
|
||||
}
|
||||
|
||||
public SWItem(Material material, String name){
|
||||
this(material, (byte)0, name, new ArrayList<>(), false, null);
|
||||
public SWItem(Material material, String name) {
|
||||
this(material, (byte) 0, name, new ArrayList<>(), false, null);
|
||||
}
|
||||
|
||||
public SWItem(Material material, String name, InvCallback c){
|
||||
this(material, (byte)0, name, new ArrayList<>(), false, c);
|
||||
public SWItem(Material material, String name, InvCallback c) {
|
||||
this(material, (byte) 0, name, new ArrayList<>(), false, c);
|
||||
}
|
||||
|
||||
public SWItem(Material material, byte meta, String name){
|
||||
public SWItem(Material material, byte meta, String name) {
|
||||
this(material, meta, name, new ArrayList<>(), false, null);
|
||||
}
|
||||
|
||||
public SWItem(Material material, byte meta, String name, InvCallback c){
|
||||
public SWItem(Material material, byte meta, String name, InvCallback c) {
|
||||
this(material, meta, name, new ArrayList<>(), false, c);
|
||||
}
|
||||
|
||||
public SWItem(Material material, String name, List<String> lore, boolean enchanted, InvCallback c) {
|
||||
this(material, (byte)0, name, lore, enchanted, c);
|
||||
this(material, (byte) 0, name, lore, enchanted, c);
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
public SWItem(Material material, byte meta, String name, List<String> lore, boolean enchanted, InvCallback c) {
|
||||
|
||||
try {
|
||||
itemStack = new ItemStack(material, 1, (short)0, meta);
|
||||
itemStack = new ItemStack(material, 1, (short) 0, meta);
|
||||
} catch (IllegalArgumentException e) {
|
||||
itemStack = new ItemStack(material, 1);
|
||||
}
|
||||
@@ -124,17 +124,17 @@ public class SWItem {
|
||||
SWItem item = null;
|
||||
try {
|
||||
item = new SWItem(SWItem.getMaterial(itemJson.get("material").getAsString()), itemJson.get("title").getAsString());
|
||||
}catch (IllegalArgumentException e) {
|
||||
} catch (IllegalArgumentException e) {
|
||||
item = new SWItem(Material.STONE, itemJson.get("title").getAsString());
|
||||
}
|
||||
if(itemJson.has("skullOwner")) {
|
||||
if (itemJson.has("skullOwner")) {
|
||||
item = SWItem.getPlayerSkull(itemJson.get("skullOwner").getAsString());
|
||||
item.setName(itemJson.get("title").getAsString());
|
||||
}
|
||||
|
||||
if(itemJson.has("enchanted"))
|
||||
if (itemJson.has("enchanted"))
|
||||
item.setEnchanted(true);
|
||||
if(itemJson.has("lore")) {
|
||||
if (itemJson.has("lore")) {
|
||||
List<String> lore = new ArrayList<>();
|
||||
JsonArray loreArray = itemJson.getAsJsonArray("lore");
|
||||
loreArray.forEach(jsonElement -> lore.add(jsonElement.getAsString()));
|
||||
@@ -204,7 +204,7 @@ public class SWItem {
|
||||
}
|
||||
|
||||
public SWItem setEnchanted(boolean enchanted) {
|
||||
if (enchanted){
|
||||
if (enchanted) {
|
||||
itemMeta.addEnchant(Enchantment.UNBREAKING, 10, true);
|
||||
} else {
|
||||
itemMeta.removeEnchant(Enchantment.UNBREAKING);
|
||||
|
||||
@@ -41,11 +41,11 @@ public class SWListInv<T> extends SWInventory {
|
||||
private int page;
|
||||
private boolean opened = false;
|
||||
|
||||
public SWListInv(Player p, String t, List<SWListEntry<T>> l, ListCallback<T> c){
|
||||
public SWListInv(Player p, String t, List<SWListEntry<T>> l, ListCallback<T> c) {
|
||||
this(p, t, true, l, c);
|
||||
}
|
||||
|
||||
public SWListInv(Player p, String t, boolean dynamicSize, List<SWListEntry<T>> l, ListCallback<T> c){
|
||||
public SWListInv(Player p, String t, boolean dynamicSize, List<SWListEntry<T>> l, ListCallback<T> c) {
|
||||
super(p, dynamicSize ? dynamicSize(l.size()) : 54, t);
|
||||
callback = c;
|
||||
elements = l;
|
||||
@@ -54,11 +54,11 @@ public class SWListInv<T> extends SWInventory {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void open(){
|
||||
public void open() {
|
||||
opened = true;
|
||||
inventory.clear();
|
||||
callbacks.keySet().stream().filter(i -> i >= 0).collect(Collectors.toList()).forEach(callbacks::remove);
|
||||
if(!callbacks.containsKey(-999)) {
|
||||
if (!callbacks.containsKey(-999)) {
|
||||
setCallback(-999, (ClickType click) -> player.closeInventory());
|
||||
}
|
||||
|
||||
@@ -109,20 +109,20 @@ public class SWListInv<T> extends SWInventory {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setItem(int pos, SWItem item){
|
||||
public void setItem(int pos, SWItem item) {
|
||||
super.setItem(pos, item);
|
||||
if(!opened)
|
||||
if (!opened)
|
||||
customItems.put(pos, item);
|
||||
}
|
||||
|
||||
public void setCallback(ListCallback<T> c){
|
||||
public void setCallback(ListCallback<T> c) {
|
||||
callback = c;
|
||||
}
|
||||
|
||||
public static List<SWListEntry<UUID>> createPlayerList(UUID without){
|
||||
public static List<SWListEntry<UUID>> createPlayerList(UUID without) {
|
||||
List<SWListEntry<UUID>> onlinePlayers = new ArrayList<>();
|
||||
for(Player player : Bukkit.getOnlinePlayers()){
|
||||
if(without != null && player.getUniqueId().equals(without))
|
||||
for (Player player : Bukkit.getOnlinePlayers()) {
|
||||
if (without != null && player.getUniqueId().equals(without))
|
||||
continue;
|
||||
|
||||
onlinePlayers.add(new SWListEntry<>(SWItem.getPlayerSkull(player), player.getUniqueId()));
|
||||
@@ -130,54 +130,54 @@ public class SWListInv<T> extends SWInventory {
|
||||
return onlinePlayers;
|
||||
}
|
||||
|
||||
public static List<SWListEntry<SchematicNode>> getSchemnodeList(SchematicType type, int steamwarUserId){
|
||||
public static List<SWListEntry<SchematicNode>> getSchemnodeList(SchematicType type, int steamwarUserId) {
|
||||
List<SWListEntry<SchematicNode>> schemList = new ArrayList<>();
|
||||
|
||||
List<SchematicNode> schems;
|
||||
if(type == null)
|
||||
if (type == null)
|
||||
schems = SchematicNode.getAllSchematicsAccessibleByUser(steamwarUserId);
|
||||
else
|
||||
schems = SchematicNode.getAllAccessibleSchematicsOfType(steamwarUserId, type.toDB());
|
||||
|
||||
for(SchematicNode s : schems){
|
||||
for (SchematicNode s : schems) {
|
||||
Material m;
|
||||
if(s.getItem().isEmpty())
|
||||
if (s.getItem().isEmpty())
|
||||
m = Material.CAULDRON;
|
||||
else
|
||||
m = SWItem.getMaterial(s.getItem());
|
||||
SWItem item = new SWItem(m,"§e" + s.getName());
|
||||
SWItem item = new SWItem(m, "§e" + s.getName());
|
||||
item.setEnchanted(s.isDir());
|
||||
schemList.add(new SWListEntry<>(item, s));
|
||||
}
|
||||
return schemList;
|
||||
}
|
||||
|
||||
private boolean sizeBiggerMax(){
|
||||
|
||||
private boolean sizeBiggerMax() {
|
||||
return dynamicSize ? elements.size() > 54 : elements.size() > 45;
|
||||
}
|
||||
|
||||
private static int dynamicSize(int size){
|
||||
return (size>45) ? 54 : (size + 9-size%9);
|
||||
private static int dynamicSize(int size) {
|
||||
return (size > 45) ? 54 : (size + 9 - size % 9);
|
||||
}
|
||||
|
||||
public interface ListCallback<T>{
|
||||
public interface ListCallback<T> {
|
||||
void clicked(ClickType click, T element);
|
||||
}
|
||||
|
||||
public static class SWListEntry<T>{
|
||||
public static class SWListEntry<T> {
|
||||
final SWItem item;
|
||||
final T object;
|
||||
|
||||
public SWListEntry(SWItem item, T object){
|
||||
public SWListEntry(SWItem item, T object) {
|
||||
this.item = item;
|
||||
this.object = object;
|
||||
}
|
||||
|
||||
public SWItem getItem(){
|
||||
public SWItem getItem() {
|
||||
return item;
|
||||
}
|
||||
|
||||
public T getObject(){
|
||||
public T getObject() {
|
||||
return object;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -83,7 +83,7 @@ public class SchematicSelector {
|
||||
|
||||
public void open() {
|
||||
injectable.onSelectorCreate(this);
|
||||
if(publicMode == PublicMode.PUBLIC_ONLY) {
|
||||
if (publicMode == PublicMode.PUBLIC_ONLY) {
|
||||
this.user = SteamwarUser.byId(0);
|
||||
}
|
||||
openList(null);
|
||||
@@ -103,9 +103,9 @@ public class SchematicSelector {
|
||||
|
||||
private void openList(SchematicNode parent) {
|
||||
lastParent = parent;
|
||||
List<SchematicNode> nodes = applySorting(filter != null?getFilteredSchematics():getSchematicList(parent));
|
||||
List<SchematicNode> nodes = applySorting(filter != null ? getFilteredSchematics() : getSchematicList(parent));
|
||||
|
||||
if(sdoTrigger) {
|
||||
if (sdoTrigger) {
|
||||
sdoTrigger = false;
|
||||
openList(nodes.get(0));
|
||||
return;
|
||||
@@ -113,18 +113,19 @@ public class SchematicSelector {
|
||||
|
||||
List<SWListInv.SWListEntry<SchematicNode>> list = new ArrayList<>();
|
||||
|
||||
if(depth != 0) {
|
||||
list.add(new SWListInv.SWListEntry<>(new SWItem(Material.ARROW, Core.MESSAGE.parse("SCHEM_SELECTOR_BACK", player), clickType -> {}).setCustomModelData(CMDs.BACK), null));
|
||||
if (depth != 0) {
|
||||
list.add(new SWListInv.SWListEntry<>(new SWItem(Material.ARROW, Core.MESSAGE.parse("SCHEM_SELECTOR_BACK", player), clickType -> {
|
||||
}).setCustomModelData(CMDs.BACK), null));
|
||||
}
|
||||
|
||||
for (SchematicNode node : nodes) {
|
||||
if(node.getName().equals("//copy")) continue;
|
||||
if (node.getName().equals("//copy")) continue;
|
||||
list.add(renderItem(node));
|
||||
}
|
||||
|
||||
SWListInv<SchematicNode> inv = new SWListInv<>(player, MessageFormat.format(injectable.createTitle(player), target.target.getName(player), (filter == null || filter.getName() == null)?(parent == null?"/":parent.generateBreadcrumbs(user)):filter.getName()), false, list, (clickType, node) -> handleClick(node, parent));
|
||||
if(publicMode == PublicMode.ALL) {
|
||||
if(user.getId() == 0) {
|
||||
SWListInv<SchematicNode> inv = new SWListInv<>(player, MessageFormat.format(injectable.createTitle(player), target.target.getName(player), (filter == null || filter.getName() == null) ? (parent == null ? "/" : parent.generateBreadcrumbs(user)) : filter.getName()), false, list, (clickType, node) -> handleClick(node, parent));
|
||||
if (publicMode == PublicMode.ALL) {
|
||||
if (user.getId() == 0) {
|
||||
inv.setItem(48, new SWItem(Material.BUCKET, Core.MESSAGE.parse("SCHEM_SELECTOR_OWN", player), clickType -> {
|
||||
this.user = SteamwarUser.get(player.getUniqueId());
|
||||
openList(null);
|
||||
@@ -136,21 +137,21 @@ public class SchematicSelector {
|
||||
}).setCustomModelData(CMDs.Schematic.PUBLIC_SCHEMS));
|
||||
}
|
||||
}
|
||||
if(target.target.dirs) {
|
||||
if (target.target.dirs) {
|
||||
inv.setItem(49, Material.LIME_DYE, Core.MESSAGE.parse("SCHEM_SELECTOR_SEL_DIR", player), clickType -> {
|
||||
player.closeInventory();
|
||||
callback.accept(parent);
|
||||
});
|
||||
}
|
||||
if(user.getId() != 0) {
|
||||
if (user.getId() != 0) {
|
||||
inv.setItem(50, new SWItem(Material.CHEST, Core.MESSAGE.parse("SCHEM_SELECTOR_NEW_DIR", player), clickType -> createFolderIn(parent)).setCustomModelData(CMDs.Schematic.NEW_DIR));
|
||||
}
|
||||
inv.setItem(51, new SWItem(Material.NAME_TAG, Core.MESSAGE.parse("SCHEM_SELECTOR_FILTER", player), clickType -> openFilter()).setCustomModelData(CMDs.Schematic.FILTER));
|
||||
inv.setItem(47, new SWItem(sorting.mat, Core.MESSAGE.parse("SCHEM_SELECTOR_SORTING", player), Arrays.asList(
|
||||
Core.MESSAGE.parse("SCHEM_SELECTOR_SORTING_CURRENT", player, sorting.parseName(player)),
|
||||
Core.MESSAGE.parse("SCHEM_SELECTOR_SORTING_DIRECTION", player, Core.MESSAGE.parse(invertSorting?"SCHEM_SELECTOR_SORTING_DSC":"SCHEM_SELECTOR_SORTING_ASC", player))
|
||||
Core.MESSAGE.parse("SCHEM_SELECTOR_SORTING_DIRECTION", player, Core.MESSAGE.parse(invertSorting ? "SCHEM_SELECTOR_SORTING_DSC" : "SCHEM_SELECTOR_SORTING_ASC", player))
|
||||
), invertSorting, click -> {
|
||||
if(click.isLeftClick()) {
|
||||
if (click.isLeftClick()) {
|
||||
cycleSorting();
|
||||
} else {
|
||||
invertSorting = !invertSorting;
|
||||
@@ -163,13 +164,13 @@ public class SchematicSelector {
|
||||
}
|
||||
|
||||
private SchematicNode dirUp(SchematicNode parent) {
|
||||
if(parent == null) {
|
||||
if (parent == null) {
|
||||
// Gracefully handle unexpected Updir in Root Folder
|
||||
depth = 0;
|
||||
return null;
|
||||
}
|
||||
if(!singleDirOpen) {
|
||||
if(NodeMember.getNodeMember(parent.getId(), user.getId()) != null) {
|
||||
if (!singleDirOpen) {
|
||||
if (NodeMember.getNodeMember(parent.getId(), user.getId()) != null) {
|
||||
return NodeMember.getNodeMember(parent.getId(), user.getId()).getParent().map(integer -> SchematicNode.byIdAndUser(user, integer)).orElse(null);
|
||||
} else {
|
||||
return getParent(parent).orElse(null);
|
||||
@@ -179,7 +180,7 @@ public class SchematicSelector {
|
||||
do {
|
||||
sdoTrigger = false;
|
||||
currentParent = currentParent.flatMap(this::getParent);
|
||||
if(!currentParent.isPresent()) {
|
||||
if (!currentParent.isPresent()) {
|
||||
break;
|
||||
}
|
||||
getSchematicList(currentParent.get());
|
||||
@@ -189,13 +190,13 @@ public class SchematicSelector {
|
||||
}
|
||||
|
||||
private void handleClick(SchematicNode node, SchematicNode parent) {
|
||||
if(node == null) {
|
||||
if (node == null) {
|
||||
depth--;
|
||||
openList(dirUp(parent));
|
||||
return;
|
||||
}
|
||||
if(node.isDir()) {
|
||||
if(filter != null && target.target.dirs) {
|
||||
if (node.isDir()) {
|
||||
if (filter != null && target.target.dirs) {
|
||||
player.closeInventory();
|
||||
callback.accept(node);
|
||||
return;
|
||||
@@ -211,19 +212,19 @@ public class SchematicSelector {
|
||||
|
||||
private void cycleSorting() {
|
||||
int next = sorting.ordinal() + 1;
|
||||
if(next >= all_sortings.length) {
|
||||
if (next >= all_sortings.length) {
|
||||
next = 0;
|
||||
}
|
||||
sorting = all_sortings[next];
|
||||
}
|
||||
|
||||
private List<SchematicNode> applySorting(List<SchematicNode> nodes) {
|
||||
if(sorting == Sorting.NAME && !invertSorting) {
|
||||
if (sorting == Sorting.NAME && !invertSorting) {
|
||||
return nodes;
|
||||
}
|
||||
|
||||
Comparator<SchematicNode> comparator = sorting.comparator;
|
||||
if(invertSorting) {
|
||||
if (invertSorting) {
|
||||
comparator = comparator.reversed();
|
||||
}
|
||||
|
||||
@@ -234,15 +235,15 @@ public class SchematicSelector {
|
||||
private SWListInv.SWListEntry<SchematicNode> renderItem(SchematicNode node) {
|
||||
Material m = SWItem.getMaterial(node.getItem());
|
||||
|
||||
String name = Core.MESSAGE.parse((filter != null && filter.name == null)?"SCHEM_SELECTOR_ITEM_NAME":"SCHEM_SELECTOR_ITEM_NAME_FILTER", player, node.getName());
|
||||
String name = Core.MESSAGE.parse((filter != null && filter.name == null) ? "SCHEM_SELECTOR_ITEM_NAME" : "SCHEM_SELECTOR_ITEM_NAME_FILTER", player, node.getName());
|
||||
|
||||
if(filter != null && filter.getName() != null) {
|
||||
if (filter != null && filter.getName() != null) {
|
||||
name = name.replace(filter.getName(), Core.MESSAGE.parse("SCHEM_SELECTOR_ITEM_REPLACE", player, filter.getName()));
|
||||
}
|
||||
|
||||
SWItem item = new SWItem(m, name, Collections.singletonList(node.isDir() ? (Core.MESSAGE.parse("SCHEM_SELECTOR_DIR", player)) : Core.MESSAGE.parse("SCHEM_SELECTOR_ITEM_LORE_TYPE", player, node.getSchemtype().name())), !node.isDir() && !node.getSchemtype().writeable(), click -> {
|
||||
});
|
||||
if(!node.isDir() && node.getRank() > 0) {
|
||||
if (!node.isDir() && node.getRank() > 0) {
|
||||
item.setLore(Arrays.asList(Core.MESSAGE.parse("SCHEM_SELECTOR_ITEM_LORE_TYPE", player, node.getSchemtype().name()), Core.MESSAGE.parse("SCHEM_SELECTOR_RANK", player, node.getRank())));
|
||||
}
|
||||
return new SWListInv.SWListEntry<>(item, node);
|
||||
@@ -251,7 +252,7 @@ public class SchematicSelector {
|
||||
private void addLeftCloseAction(SWAnvilInv inv, Runnable runnable) {
|
||||
AtomicBoolean wasLeft = new AtomicBoolean(false);
|
||||
inv.addCloseCallback(() -> {
|
||||
if(injectable.onAnvilInvCloseAction(this) == SchematicSelectorInjectable.AnvilInvCloseAction.REOPEN && !wasLeft.get()) {
|
||||
if (injectable.onAnvilInvCloseAction(this) == SchematicSelectorInjectable.AnvilInvCloseAction.REOPEN && !wasLeft.get()) {
|
||||
player.closeInventory();
|
||||
Bukkit.getScheduler().runTaskLater(Core.getInstance(), runnable, 1);
|
||||
}
|
||||
@@ -266,9 +267,9 @@ public class SchematicSelector {
|
||||
SWAnvilInv inv = new SWAnvilInv(player, Core.MESSAGE.parse("SCHEM_SELECTOR_CREATE_DIR_TITLE", player));
|
||||
inv.setItem(Material.CHEST, Collections.singletonList(Core.MESSAGE.parse("SCHEM_SELECTOR_CLICK_BACK", player)), false);
|
||||
inv.setCallback(s -> {
|
||||
if(!SchematicNode.invalidSchemName(new String[] {s})) {
|
||||
if(injectable.onFolderCreate(this, s)) {
|
||||
SchematicNode.createSchematicDirectory(user.getId(), s, parent==null?0:parent.getId());
|
||||
if (!SchematicNode.invalidSchemName(new String[]{s})) {
|
||||
if (injectable.onFolderCreate(this, s)) {
|
||||
SchematicNode.createSchematicDirectory(user.getId(), s, parent == null ? 0 : parent.getId());
|
||||
openList(parent);
|
||||
}
|
||||
return;
|
||||
@@ -286,7 +287,7 @@ public class SchematicSelector {
|
||||
|
||||
SWInventory inv = new SWInventory(player, 9 * 2, Core.MESSAGE.parse("SCHEM_SELECTOR_FILTER_TITLE", player));
|
||||
InvCallback nameCallback = clickType -> {
|
||||
if(clickType.isRightClick()) {
|
||||
if (clickType.isRightClick()) {
|
||||
filter = filter.withName(null);
|
||||
openFilter();
|
||||
} else {
|
||||
@@ -300,21 +301,21 @@ public class SchematicSelector {
|
||||
swAnvilInv.open();
|
||||
}
|
||||
};
|
||||
if(filter.getName() == null) {
|
||||
if (filter.getName() == null) {
|
||||
inv.setItem(0, Material.NAME_TAG, Core.MESSAGE.parse("SCHEM_SELECTOR_FILTER_NAME", player), nameCallback);
|
||||
} else {
|
||||
inv.setItem(0, Material.NAME_TAG, Core.MESSAGE.parse("SCHEM_SELECTOR_FILTER_NAME", player), Collections.singletonList(Core.MESSAGE.parse("SCHEM_SELECTOR_FILTER_NAME_SEARCH", player, filter.getName())), true, nameCallback);
|
||||
}
|
||||
|
||||
InvCallback ownerCallback = clickType -> {
|
||||
if(clickType.isRightClick()) {
|
||||
if (clickType.isRightClick()) {
|
||||
filter = filter.withOwner(null);
|
||||
openFilter();
|
||||
} else {
|
||||
SWAnvilInv swAnvilInv = new SWAnvilInv(player, Core.MESSAGE.parse("SCHEM_SELECTOR_FILTER_ENTER_OWNER", player));
|
||||
swAnvilInv.setItem(Material.SKELETON_SKULL, (byte) 3, Collections.singletonList(Core.MESSAGE.parse("SCHEM_SELECTOR_CLICK_BACK", player)), false);
|
||||
swAnvilInv.setCallback(s -> {
|
||||
if(SteamwarUser.get(s) != null) {
|
||||
if (SteamwarUser.get(s) != null) {
|
||||
filter = filter.withOwner(SteamwarUser.get(s).getId());
|
||||
}
|
||||
openFilter();
|
||||
@@ -323,7 +324,7 @@ public class SchematicSelector {
|
||||
swAnvilInv.open();
|
||||
}
|
||||
};
|
||||
if(filter.getOwner() == null) {
|
||||
if (filter.getOwner() == null) {
|
||||
inv.setItem(1, Material.SKELETON_SKULL, (byte) 3, Core.MESSAGE.parse("SCHEM_SELECTOR_FILTER_OWNER", player), ownerCallback);
|
||||
} else {
|
||||
SteamwarUser tUser = SteamwarUser.byId(filter.getOwner());
|
||||
@@ -335,14 +336,15 @@ public class SchematicSelector {
|
||||
inv.setItem(1, item);
|
||||
}
|
||||
|
||||
if(target.target != Target.SCHEMATIC_TYPE) {
|
||||
if (target.target != Target.SCHEMATIC_TYPE) {
|
||||
InvCallback schemTypeCallback = clickType -> {
|
||||
if(clickType.isRightClick()) {
|
||||
if (clickType.isRightClick()) {
|
||||
filter = filter.withType(null);
|
||||
openFilter();
|
||||
} else {
|
||||
List<SWListInv.SWListEntry<SchematicType>> types = new ArrayList<>();
|
||||
SchematicType.values().forEach(schematicType -> types.add(new SWListInv.SWListEntry<>(new SWItem(SWItem.getMaterial(schematicType.getMaterial()), "§e" + schematicType.name(), Collections.emptyList(), schematicType.fightType(), n -> {}), schematicType)));
|
||||
SchematicType.values().forEach(schematicType -> types.add(new SWListInv.SWListEntry<>(new SWItem(SWItem.getMaterial(schematicType.getMaterial()), "§e" + schematicType.name(), Collections.emptyList(), schematicType.fightType(), n -> {
|
||||
}), schematicType)));
|
||||
SWListInv<SchematicType> listInv = new SWListInv<>(player, Core.MESSAGE.parse("SCHEM_SELECTOR_FILTER_SEL_TYPE", player), types, (clickType1, schematicType) -> {
|
||||
filter = filter.withType(schematicType);
|
||||
openFilter();
|
||||
@@ -351,7 +353,7 @@ public class SchematicSelector {
|
||||
}
|
||||
};
|
||||
|
||||
if(filter.getType() == null) {
|
||||
if (filter.getType() == null) {
|
||||
inv.setItem(2, SWItem.getMaterial(SchematicType.Normal.getMaterial()), Core.MESSAGE.parse("SCHEM_SELECTOR_FILTER_TYPE", player), schemTypeCallback);
|
||||
} else {
|
||||
inv.setItem(2, SWItem.getMaterial(filter.getType().getMaterial()), Core.MESSAGE.parse("SCHEM_SELECTOR_FILTER_TYPE", player), Collections.singletonList(Core.MESSAGE.parse("SCHEM_SELECTOR_FILTER_TYPE_SEARCH", player, filter.getType().name())), true, schemTypeCallback);
|
||||
@@ -359,7 +361,7 @@ public class SchematicSelector {
|
||||
}
|
||||
|
||||
InvCallback materialCallback = clickType -> {
|
||||
if(clickType.isRightClick()) {
|
||||
if (clickType.isRightClick()) {
|
||||
filter = filter.withItem(null);
|
||||
openFilter();
|
||||
} else {
|
||||
@@ -370,9 +372,9 @@ public class SchematicSelector {
|
||||
}
|
||||
};
|
||||
|
||||
final int iSlot = target.target == Target.SCHEMATIC_TYPE?2:3;
|
||||
final int iSlot = target.target == Target.SCHEMATIC_TYPE ? 2 : 3;
|
||||
|
||||
if(filter.getItem() == null) {
|
||||
if (filter.getItem() == null) {
|
||||
inv.setItem(iSlot, Material.STONE, Core.MESSAGE.parse("SCHEM_SELECTOR_FILTER_MAT", player), materialCallback);
|
||||
} else {
|
||||
inv.setItem(iSlot, filter.getItem(), Core.MESSAGE.parse("SCHEM_SELECTOR_FILTER_MAT", player), Collections.singletonList(Core.MESSAGE.parse("SCHEM_SELECTOR_FILTER_MAT_SEARCH", player, filter.getItem().name())), true, materialCallback);
|
||||
@@ -397,7 +399,8 @@ public class SchematicSelector {
|
||||
for (int i = 0; i < filters.length; i++) {
|
||||
SelectorFilter filterCached = filters[i];
|
||||
if (filterCached == null) {
|
||||
inv.setItem(i + 9, new SWItem(Material.BARRIER, Core.MESSAGE.parse("SCHEM_SELECTOR_FILTER_EMPTY", player), click -> {}));
|
||||
inv.setItem(i + 9, new SWItem(Material.BARRIER, Core.MESSAGE.parse("SCHEM_SELECTOR_FILTER_EMPTY", player), click -> {
|
||||
}));
|
||||
} else {
|
||||
SWItem item = filterCached.toItemStack(player);
|
||||
item.setEnchanted(filterCached.equals(filter));
|
||||
@@ -416,11 +419,11 @@ public class SchematicSelector {
|
||||
inv.setItem(8, Material.LIME_DYE, Core.MESSAGE.parse("SCHEM_SELECTOR_GO", player), clickType -> {
|
||||
if (!filter.equals(filters[0])) {
|
||||
for (int i = filters.length - 1; i > 0; i--) {
|
||||
filters[i] = filters[i-1];
|
||||
filters[i] = filters[i - 1];
|
||||
if (filter.equals(filters[i])) {
|
||||
filters[i] = null;
|
||||
for (int j = i; j < filters.length - 1; j++) {
|
||||
filters[j] = filters[j+1];
|
||||
filters[j] = filters[j + 1];
|
||||
}
|
||||
filters[filters.length - 1] = null;
|
||||
}
|
||||
@@ -455,10 +458,10 @@ public class SchematicSelector {
|
||||
injectable.onNodeFilter(this, node);
|
||||
return !filter.matches(node);
|
||||
});
|
||||
if(target.target == Target.DIRECTORY) {
|
||||
if (target.target == Target.DIRECTORY) {
|
||||
nodes.removeIf(node -> !node.isDir());
|
||||
}
|
||||
if(target.target == Target.SCHEMATIC_TYPE) {
|
||||
if (target.target == Target.SCHEMATIC_TYPE) {
|
||||
nodes.removeIf(node -> node.isDir() || !node.getSchemtype().equals(target.type));
|
||||
}
|
||||
return nodes;
|
||||
@@ -472,13 +475,13 @@ public class SchematicSelector {
|
||||
nodes.removeIf(node -> !node.isDir());
|
||||
break;
|
||||
case SCHEMATIC_TYPE:
|
||||
nodes.addAll(SchematicNode.accessibleByUserTypeParent(user, target.type, parent==null?null:parent.getId()));
|
||||
nodes.addAll(SchematicNode.accessibleByUserTypeParent(user, target.type, parent == null ? null : parent.getId()));
|
||||
break;
|
||||
default:
|
||||
nodes.addAll(SchematicNode.list(user, parent == null?null:parent.getId()));
|
||||
nodes.addAll(SchematicNode.list(user, parent == null ? null : parent.getId()));
|
||||
}
|
||||
|
||||
if(singleDirOpen && nodes.size() == 1 && nodes.get(0).isDir()) {
|
||||
if (singleDirOpen && nodes.size() == 1 && nodes.get(0).isDir()) {
|
||||
sdoTrigger = true;
|
||||
}
|
||||
return nodes;
|
||||
@@ -553,22 +556,22 @@ public class SchematicSelector {
|
||||
public boolean matches(SchematicNode node) {
|
||||
boolean matches = name == null || node.getName().contains(name);
|
||||
|
||||
if(owner != null && node.getOwner() != owner) {
|
||||
if (owner != null && node.getOwner() != owner) {
|
||||
matches = false;
|
||||
}
|
||||
|
||||
if(type != null && (node.isDir() || !node.getSchemtype().equals(type))) {
|
||||
if (type != null && (node.isDir() || !node.getSchemtype().equals(type))) {
|
||||
matches = false;
|
||||
}
|
||||
|
||||
if(item != null) {
|
||||
if (item != null) {
|
||||
String i;
|
||||
if(node.getItem().isEmpty()) {
|
||||
i = node.isDir()?"CHEST":"CAULDRON";
|
||||
if (node.getItem().isEmpty()) {
|
||||
i = node.isDir() ? "CHEST" : "CAULDRON";
|
||||
} else {
|
||||
i = node.getItem();
|
||||
}
|
||||
if(!item.name().equals(i)) {
|
||||
if (!item.name().equals(i)) {
|
||||
matches = false;
|
||||
}
|
||||
}
|
||||
@@ -581,16 +584,16 @@ public class SchematicSelector {
|
||||
|
||||
public List<String> getItemLore(Player player) {
|
||||
List<String> lore = new ArrayList<>(4);
|
||||
if(name != null) {
|
||||
if (name != null) {
|
||||
lore.add(Core.MESSAGE.parse("SCHEM_SELECTOR_FILTER_NAME_SEARCH", player, name));
|
||||
}
|
||||
if(owner != null) {
|
||||
if (owner != null) {
|
||||
lore.add(Core.MESSAGE.parse("SCHEM_SELECTOR_FILTER_OWNER_SEARCH", player, SteamwarUser.byId(owner).getUserName()));
|
||||
}
|
||||
if(type != null) {
|
||||
if (type != null) {
|
||||
lore.add(Core.MESSAGE.parse("SCHEM_SELECTOR_FILTER_TYPE_SEARCH", player, type.name()));
|
||||
}
|
||||
if(item != null) {
|
||||
if (item != null) {
|
||||
lore.add(Core.MESSAGE.parse("SCHEM_SELECTOR_FILTER_MAT_SEARCH", player, item.name()));
|
||||
}
|
||||
|
||||
@@ -604,18 +607,22 @@ public class SchematicSelector {
|
||||
List<String> lore = getItemLore(player);
|
||||
|
||||
if (name != null) {
|
||||
return new SWItem(Material.NAME_TAG, itemName, lore, false, click -> {});
|
||||
return new SWItem(Material.NAME_TAG, itemName, lore, false, click -> {
|
||||
});
|
||||
} else if (owner != null) {
|
||||
SWItem playerSkull = SWItem.getPlayerSkull(SteamwarUser.byId(owner).getUserName());
|
||||
playerSkull.setName(itemName);
|
||||
playerSkull.setLore(lore);
|
||||
return playerSkull;
|
||||
} else if (type != null) {
|
||||
return new SWItem(SWItem.getMaterial(type.getMaterial()), itemName, lore, false, n -> {});
|
||||
return new SWItem(SWItem.getMaterial(type.getMaterial()), itemName, lore, false, n -> {
|
||||
});
|
||||
} else if (item != null) {
|
||||
return new SWItem(item, itemName, lore, false, click -> {});
|
||||
return new SWItem(item, itemName, lore, false, click -> {
|
||||
});
|
||||
} else {
|
||||
return new SWItem(Material.BARRIER, Core.MESSAGE.parse("SCHEM_SELECTOR_FILTER_TITLE_EMPTY", player), Collections.emptyList(), false, click -> {});
|
||||
return new SWItem(Material.BARRIER, Core.MESSAGE.parse("SCHEM_SELECTOR_FILTER_TITLE_EMPTY", player), Collections.emptyList(), false, click -> {
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -623,8 +630,8 @@ public class SchematicSelector {
|
||||
JsonObject object = new JsonObject();
|
||||
object.addProperty("name", name);
|
||||
object.addProperty("owner", owner);
|
||||
object.addProperty("type", type == null?null:type.toDB());
|
||||
object.addProperty("item", item == null?null:item.name());
|
||||
object.addProperty("type", type == null ? null : type.toDB());
|
||||
object.addProperty("item", item == null ? null : item.name());
|
||||
|
||||
return object;
|
||||
}
|
||||
@@ -640,7 +647,7 @@ public class SchematicSelector {
|
||||
private enum Sorting {
|
||||
NAME(Material.PAPER, "SCHEM_SELECTOR_SORTING_NAME", Comparator.comparing(SchematicNode::getName)),
|
||||
TYPE(Material.CAULDRON, "SCHEM_SELECTOR_SORTING_TYPE", (o1, o2) -> {
|
||||
if(o1.isDir() || o2.isDir()) {
|
||||
if (o1.isDir() || o2.isDir()) {
|
||||
return Boolean.compare(o1.isDir(), o2.isDir());
|
||||
} else {
|
||||
return o1.getSchemtype().name().compareTo(o2.getSchemtype().name());
|
||||
|
||||
+20
-9
@@ -25,27 +25,38 @@ import org.bukkit.entity.Player;
|
||||
|
||||
public interface SchematicSelectorInjectable {
|
||||
|
||||
SchematicSelectorInjectable DEFAULT = new SchematicSelectorInjectable() {};
|
||||
SchematicSelectorInjectable DEFAULT = new SchematicSelectorInjectable() {
|
||||
};
|
||||
|
||||
default String createTitle(Player player) {
|
||||
return Core.MESSAGE.parse("SCHEM_SELECTOR_TITLE", player);
|
||||
}
|
||||
|
||||
default void onSelectorCreate(SchematicSelector selector) {}
|
||||
default void onSelectorCreate(SchematicSelector selector) {
|
||||
}
|
||||
|
||||
default void onListRender(SchematicSelector selector, SWListInv<SchematicNode> inv, SchematicNode parent) {}
|
||||
default void onListRender(SchematicSelector selector, SWListInv<SchematicNode> inv, SchematicNode parent) {
|
||||
}
|
||||
|
||||
default void onFilterRender(SchematicSelector selector, SWInventory inventory) {}
|
||||
default void onFilterRender(SchematicSelector selector, SWInventory inventory) {
|
||||
}
|
||||
|
||||
default void onFilterApply(SchematicSelector selector) {}
|
||||
default void onFilterApply(SchematicSelector selector) {
|
||||
}
|
||||
|
||||
default boolean onFolderCreate(SchematicSelector selector, String name) {return true;}
|
||||
default boolean onFolderCreate(SchematicSelector selector, String name) {
|
||||
return true;
|
||||
}
|
||||
|
||||
default void onNodeFilter(SchematicSelector selector, SchematicNode node) {}
|
||||
default void onNodeFilter(SchematicSelector selector, SchematicNode node) {
|
||||
}
|
||||
|
||||
default void onSelectorOpen(SchematicSelector selector, OpenFrom from) {}
|
||||
default void onSelectorOpen(SchematicSelector selector, OpenFrom from) {
|
||||
}
|
||||
|
||||
default AnvilInvCloseAction onAnvilInvCloseAction(SchematicSelector selector) {return AnvilInvCloseAction.CLOSE;}
|
||||
default AnvilInvCloseAction onAnvilInvCloseAction(SchematicSelector selector) {
|
||||
return AnvilInvCloseAction.CLOSE;
|
||||
}
|
||||
|
||||
enum OpenFrom {
|
||||
FRESH,
|
||||
|
||||
@@ -37,11 +37,11 @@ public class UtilGui {
|
||||
|
||||
public static void openMaterialSelector(Player player, String title, Consumer<Material> callback) {
|
||||
List<SWListInv.SWListEntry<Material>> materials = new LinkedList<>();
|
||||
for(Material material : Material.values()){
|
||||
if(material.name().startsWith(Material.LEGACY_PREFIX) || !material.isItem())
|
||||
for (Material material : Material.values()) {
|
||||
if (material.name().startsWith(Material.LEGACY_PREFIX) || !material.isItem())
|
||||
continue;
|
||||
SWItem item = new SWItem(material, "§7" + material.name());
|
||||
if(item.getItemMeta() != null && material.isItem()) {
|
||||
if (item.getItemMeta() != null && material.isItem()) {
|
||||
materials.add(new SWListInv.SWListEntry<>(item, material));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,35 +37,35 @@ public class Message {
|
||||
private final String resourceBundleName;
|
||||
private final ClassLoader classLoader;
|
||||
|
||||
public Message(String resourceBundleName, ClassLoader classLoader){
|
||||
public Message(String resourceBundleName, ClassLoader classLoader) {
|
||||
this.resourceBundleName = resourceBundleName;
|
||||
this.classLoader = classLoader;
|
||||
}
|
||||
|
||||
/* Parsing input to a message */
|
||||
|
||||
public TextComponent parseToComponent(String message, boolean prefixed, CommandSender sender, Object... params){
|
||||
public TextComponent parseToComponent(String message, boolean prefixed, CommandSender sender, Object... params) {
|
||||
return new TextComponent(TextComponent.fromLegacyText(parse(message, prefixed, sender, params)));
|
||||
}
|
||||
|
||||
public String parsePrefixed(String message, CommandSender sender, Object... params){
|
||||
public String parsePrefixed(String message, CommandSender sender, Object... params) {
|
||||
return parse(message, true, sender, params);
|
||||
}
|
||||
|
||||
public String parse(String message, CommandSender sender, Object... params){
|
||||
public String parse(String message, CommandSender sender, Object... params) {
|
||||
return parse(message, false, sender, params);
|
||||
}
|
||||
|
||||
private String parse(String message, boolean prefixed, CommandSender sender, Object... params){
|
||||
private String parse(String message, boolean prefixed, CommandSender sender, Object... params) {
|
||||
Locale locale;
|
||||
if(sender instanceof Player)
|
||||
if (sender instanceof Player)
|
||||
locale = getLocale((Player) sender);
|
||||
else
|
||||
locale = Locale.getDefault();
|
||||
|
||||
ResourceBundle resourceBundle = ResourceBundle.getBundle(resourceBundleName, locale, classLoader);
|
||||
String pattern = "";
|
||||
if(prefixed)
|
||||
if (prefixed)
|
||||
pattern = fromRB(resourceBundle, "PREFIX") + " ";
|
||||
pattern += fromRB(resourceBundle, message);
|
||||
|
||||
@@ -83,78 +83,78 @@ public class Message {
|
||||
return bundle.getString(key);
|
||||
}
|
||||
|
||||
private Locale getLocale(Player player){
|
||||
private Locale getLocale(Player player) {
|
||||
return SteamwarUser.get(player.getUniqueId()).getLocale();
|
||||
}
|
||||
|
||||
/* Send a message to one player */
|
||||
|
||||
public void send(String message, CommandSender sender, Object... params){
|
||||
public void send(String message, CommandSender sender, Object... params) {
|
||||
send(message, true, sender, ChatMessageType.SYSTEM, null, null, params);
|
||||
}
|
||||
|
||||
public void sendPrefixless(String message, CommandSender sender, Object... params){
|
||||
public void sendPrefixless(String message, CommandSender sender, Object... params) {
|
||||
send(message, false, sender, ChatMessageType.SYSTEM, null, null, params);
|
||||
}
|
||||
|
||||
public void send(String message, CommandSender sender, ChatMessageType type, Object... params){
|
||||
public void send(String message, CommandSender sender, ChatMessageType type, Object... params) {
|
||||
send(message, true, sender, type, null, null, params);
|
||||
}
|
||||
|
||||
public void sendPrefixless(String message, CommandSender sender, ChatMessageType type, Object... params){
|
||||
public void sendPrefixless(String message, CommandSender sender, ChatMessageType type, Object... params) {
|
||||
send(message, false, sender, type, null, null, params);
|
||||
}
|
||||
|
||||
public void send(String message, CommandSender sender, String onHover, ClickEvent onClick, Object... params){
|
||||
public void send(String message, CommandSender sender, String onHover, ClickEvent onClick, Object... params) {
|
||||
send(message, true, sender, ChatMessageType.SYSTEM, onHover, onClick, params);
|
||||
}
|
||||
|
||||
public void sendPrefixless(String message, CommandSender sender, String onHover, ClickEvent onClick, Object... params){
|
||||
public void sendPrefixless(String message, CommandSender sender, String onHover, ClickEvent onClick, Object... params) {
|
||||
send(message, false, sender, ChatMessageType.SYSTEM, onHover, onClick, params);
|
||||
}
|
||||
|
||||
public void send(String message, boolean prefixed, CommandSender sender, ChatMessageType type, String onHover, ClickEvent onClick, Object... params){
|
||||
public void send(String message, boolean prefixed, CommandSender sender, ChatMessageType type, String onHover, ClickEvent onClick, Object... params) {
|
||||
TextComponent msg = parseToComponent(message, prefixed, sender, params);
|
||||
if(onHover != null)
|
||||
if (onHover != null)
|
||||
msg.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, TextComponent.fromLegacyText(onHover)));
|
||||
if(onClick != null)
|
||||
if (onClick != null)
|
||||
msg.setClickEvent(onClick);
|
||||
|
||||
if(sender instanceof Player)
|
||||
BountifulWrapper.impl.sendMessage((Player)sender, type, msg);
|
||||
if (sender instanceof Player)
|
||||
BountifulWrapper.impl.sendMessage((Player) sender, type, msg);
|
||||
else
|
||||
sender.sendMessage(msg.toPlainText());
|
||||
}
|
||||
|
||||
/* Send message to all players */
|
||||
|
||||
public void broadcastPrefixless(String message, String onHover, ClickEvent onClick, Object... params){
|
||||
for(Player player : Bukkit.getOnlinePlayers())
|
||||
public void broadcastPrefixless(String message, String onHover, ClickEvent onClick, Object... params) {
|
||||
for (Player player : Bukkit.getOnlinePlayers())
|
||||
sendPrefixless(message, player, parse(onHover, false, player), onClick, params);
|
||||
}
|
||||
|
||||
public void broadcastPrefixless(String message, Object... params){
|
||||
for(Player player : Bukkit.getOnlinePlayers())
|
||||
public void broadcastPrefixless(String message, Object... params) {
|
||||
for (Player player : Bukkit.getOnlinePlayers())
|
||||
sendPrefixless(message, player, ChatMessageType.SYSTEM, params);
|
||||
}
|
||||
|
||||
public void broadcastActionbar(String message, Object... params){
|
||||
for(Player player : Bukkit.getOnlinePlayers())
|
||||
public void broadcastActionbar(String message, Object... params) {
|
||||
for (Player player : Bukkit.getOnlinePlayers())
|
||||
send(message, player, ChatMessageType.ACTION_BAR, params);
|
||||
}
|
||||
|
||||
public void broadcast(String message, String onHover, ClickEvent onClick, Object... params){
|
||||
for(Player player : Bukkit.getOnlinePlayers())
|
||||
public void broadcast(String message, String onHover, ClickEvent onClick, Object... params) {
|
||||
for (Player player : Bukkit.getOnlinePlayers())
|
||||
send(message, player, parse(onHover, false, player), onClick, params);
|
||||
}
|
||||
|
||||
public void broadcast(String message, Object... params){
|
||||
for(Player player : Bukkit.getOnlinePlayers())
|
||||
public void broadcast(String message, Object... params) {
|
||||
for (Player player : Bukkit.getOnlinePlayers())
|
||||
send(message, player, ChatMessageType.SYSTEM, params);
|
||||
}
|
||||
|
||||
public void chat(String message, Object... params){
|
||||
for(Player player : Bukkit.getOnlinePlayers())
|
||||
public void chat(String message, Object... params) {
|
||||
for (Player player : Bukkit.getOnlinePlayers())
|
||||
sendPrefixless(message, player, ChatMessageType.CHAT, params);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -67,7 +67,7 @@ public class CoreNetworkHandler extends PacketHandler {
|
||||
@Handler
|
||||
public void handlePingPacket(PingPacket packet) {
|
||||
UUID uuid = SteamwarUser.byId(packet.getId()).getUUID();
|
||||
if(Bukkit.getPlayer(uuid) != null) {
|
||||
if (Bukkit.getPlayer(uuid) != null) {
|
||||
Player player = Bukkit.getPlayer(uuid);
|
||||
BountifulWrapper.impl.playPling(player);
|
||||
}
|
||||
|
||||
@@ -51,7 +51,7 @@ public class InventoryHandler extends PacketHandler {
|
||||
|
||||
SWInventory inventory = new SWInventory(player, packet.getSize(), packet.getTitle(), items);
|
||||
inventory.addCloseCallback(click -> {
|
||||
if(player.getOpenInventory().getType() != InventoryType.CHEST)
|
||||
if (player.getOpenInventory().getType() != InventoryType.CHEST)
|
||||
NetworkSender.send(InventoryCallbackPacket.builder().owner(packet.getPlayer()).type(InventoryCallbackPacket.CallbackType.CLOSE).build(), player);
|
||||
});
|
||||
inventory.open();
|
||||
|
||||
@@ -28,7 +28,8 @@ public class BauServerInfo {
|
||||
static {
|
||||
try {
|
||||
bauOwner = Integer.parseInt(Bukkit.getWorlds().get(0).getName());
|
||||
} catch (NumberFormatException ignored) {}
|
||||
} catch (NumberFormatException ignored) {
|
||||
}
|
||||
}
|
||||
|
||||
public static Integer getOwnerId() {
|
||||
|
||||
@@ -38,7 +38,7 @@ public class SWScoreboard {
|
||||
|
||||
static {
|
||||
Bukkit.getScheduler().runTaskTimer(Core.getInstance(), () -> {
|
||||
for(Map.Entry<Player, ScoreboardCallback> scoreboard : playerBoards.entrySet()) {
|
||||
for (Map.Entry<Player, ScoreboardCallback> scoreboard : playerBoards.entrySet()) {
|
||||
render(scoreboard.getKey(), scoreboard.getValue());
|
||||
}
|
||||
}, 10, 5);
|
||||
|
||||
@@ -48,12 +48,12 @@ public class PersonalKit {
|
||||
return kit.getRawArmor();
|
||||
}
|
||||
|
||||
public ItemStack[] getInventory(){
|
||||
public ItemStack[] getInventory() {
|
||||
YamlConfiguration config = YamlConfiguration.loadConfiguration(new StringReader(getRawInventory()));
|
||||
return Objects.requireNonNull(config.getList("Inventory")).toArray(new ItemStack[0]);
|
||||
}
|
||||
|
||||
public ItemStack[] getArmor(){
|
||||
public ItemStack[] getArmor() {
|
||||
YamlConfiguration config = YamlConfiguration.loadConfiguration(new StringReader(getRawArmor()));
|
||||
return Objects.requireNonNull(config.getList("Armor")).toArray(new ItemStack[4]);
|
||||
}
|
||||
@@ -79,25 +79,25 @@ public class PersonalKit {
|
||||
kit.delete();
|
||||
}
|
||||
|
||||
public static List<PersonalKit> get(int userID, String gamemode){
|
||||
public static List<PersonalKit> get(int userID, String gamemode) {
|
||||
return InternalKit.get(userID, gamemode).stream().map(PersonalKit::new).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
public static PersonalKit get(int userID, String gamemode, String name) {
|
||||
InternalKit kit = InternalKit.get(userID, gamemode, name);
|
||||
if(kit == null)
|
||||
if (kit == null)
|
||||
return null;
|
||||
return new PersonalKit(kit);
|
||||
}
|
||||
|
||||
public static PersonalKit create(int userID, String gamemode, String name, ItemStack[] inventory, ItemStack[] armor){
|
||||
public static PersonalKit create(int userID, String gamemode, String name, ItemStack[] inventory, ItemStack[] armor) {
|
||||
InternalKit kit = InternalKit.create(userID, gamemode, name, saveInvConfig("Inventory", inventory), saveInvConfig("Armor", armor));
|
||||
return new PersonalKit(kit);
|
||||
}
|
||||
|
||||
public static PersonalKit getKitInUse(int userID, String gamemode) {
|
||||
InternalKit kit = InternalKit.getKitInUse(userID, gamemode);
|
||||
if(kit == null)
|
||||
if (kit == null)
|
||||
return null;
|
||||
return new PersonalKit(kit);
|
||||
}
|
||||
|
||||
@@ -32,12 +32,12 @@ public class SchematicData {
|
||||
|
||||
public SchematicData(SchematicNode node) {
|
||||
this.data = NodeData.getLatest(node);
|
||||
if(node.isDir())
|
||||
if (node.isDir())
|
||||
throw new SecurityException("Node is Directory");
|
||||
}
|
||||
|
||||
public SchematicData(SchematicNode node, int revision) {
|
||||
if(node.isDir())
|
||||
if (node.isDir())
|
||||
throw new SecurityException("Node is Directory");
|
||||
|
||||
if (revision < 1) {
|
||||
|
||||
@@ -40,14 +40,15 @@ public class BlockIds {
|
||||
|
||||
private static final FluidState water = Fluids.WATER.getSource(false);
|
||||
private static final Iterable<BlockState> registryBlockId = (Iterable<BlockState>) Reflection.getField(TechHider.block, IdMapper.class, 0).get(null);
|
||||
|
||||
public Set<Integer> materialToAllIds(Material material) {
|
||||
Set<Integer> ids = new HashSet<>();
|
||||
for(BlockState data : getBlock(material).getStateDefinition().getPossibleStates()) {
|
||||
for (BlockState data : getBlock(material).getStateDefinition().getPossibleStates()) {
|
||||
ids.add(getCombinedId(data));
|
||||
}
|
||||
|
||||
if(material == Material.WATER) {
|
||||
for(BlockState data : registryBlockId) {
|
||||
if (material == Material.WATER) {
|
||||
for (BlockState data : registryBlockId) {
|
||||
if (data.getFluidState() == water) {
|
||||
ids.add(getCombinedId(data));
|
||||
}
|
||||
|
||||
@@ -67,12 +67,12 @@ public class ChunkHider {
|
||||
Object dataWrapper = chunkDataCloner.apply(chunkData.get(packet));
|
||||
|
||||
Set<String> hiddenBlockEntities = techHider.getHiddenBlockEntities();
|
||||
tileEntities.set(dataWrapper, ((List<?>)tileEntities.get(dataWrapper)).stream().filter(te -> tileEntityVisible(hiddenBlockEntities, te)).collect(Collectors.toList()));
|
||||
tileEntities.set(dataWrapper, ((List<?>) tileEntities.get(dataWrapper)).stream().filter(te -> tileEntityVisible(hiddenBlockEntities, te)).collect(Collectors.toList()));
|
||||
|
||||
ByteBuf in = Unpooled.wrappedBuffer(dataField.get(dataWrapper));
|
||||
ByteBuf out = Unpooled.buffer(in.readableBytes() + 64);
|
||||
for(int yOffset = p.getWorld().getMinHeight(); yOffset < p.getWorld().getMaxHeight(); yOffset += 16) {
|
||||
SectionHider section = new SectionHider(p, techHider, in, out, chunkX, yOffset/16, chunkZ);
|
||||
for (int yOffset = p.getWorld().getMinHeight(); yOffset < p.getWorld().getMaxHeight(); yOffset += 16) {
|
||||
SectionHider section = new SectionHider(p, techHider, in, out, chunkX, yOffset / 16, chunkZ);
|
||||
section.copyBlockCount();
|
||||
|
||||
blocks(section);
|
||||
@@ -96,6 +96,7 @@ public class ChunkHider {
|
||||
private static final Reflection.Method getKey = Reflection.getTypedMethod(Reflection.getClass("net.minecraft.core.Registry"), "getKey", ResourceLocation.class, Object.class);
|
||||
public static final Class<?> tileEntity = Reflection.getClass("net.minecraft.network.protocol.game.ClientboundLevelChunkPacketData$BlockEntityInfo");
|
||||
protected static final Reflection.Field<BlockEntityType> entityType = Reflection.getField(tileEntity, BlockEntityType.class, 0);
|
||||
|
||||
protected boolean tileEntityVisible(Set<String> hiddenBlockEntities, Object tile) {
|
||||
BlockEntityType type = entityType.get(tile);
|
||||
String path = ((ResourceLocation) getKey.invoke(registry, type)).getPath();
|
||||
@@ -151,9 +152,9 @@ public class ChunkHider {
|
||||
|
||||
private void biomes(SectionHider section) {
|
||||
section.copyBitsPerBlock();
|
||||
if(section.getBitsPerBlock() == 0) {
|
||||
if (section.getBitsPerBlock() == 0) {
|
||||
section.copyVarInt();
|
||||
} else if(section.getBitsPerBlock() < 6) {
|
||||
} else if (section.getBitsPerBlock() < 6) {
|
||||
section.skipPalette();
|
||||
section.skipNewDataArray(64);
|
||||
} else {
|
||||
@@ -193,9 +194,9 @@ public class ChunkHider {
|
||||
this.chunkX = chunkX;
|
||||
this.chunkY = chunkY;
|
||||
this.chunkZ = chunkZ;
|
||||
this.offsetX = 16*chunkX;
|
||||
this.offsetY = 16*chunkY;
|
||||
this.offsetZ = 16*chunkZ;
|
||||
this.offsetX = 16 * chunkX;
|
||||
this.offsetY = 16 * chunkY;
|
||||
this.offsetZ = 16 * chunkZ;
|
||||
this.skipSection = techHider.getLocationEvaluator().skipChunkSection(player, chunkX, chunkY, chunkZ);
|
||||
|
||||
this.paletted = false;
|
||||
@@ -210,7 +211,7 @@ public class ChunkHider {
|
||||
}
|
||||
|
||||
public TechHider.State test(int x, int y, int z) {
|
||||
return techHider.getLocationEvaluator().check(player, offsetX+x, offsetY+y, offsetZ+z);
|
||||
return techHider.getLocationEvaluator().check(player, offsetX + x, offsetY + y, offsetZ + z);
|
||||
}
|
||||
|
||||
public void copyBlockCount() {
|
||||
@@ -231,32 +232,32 @@ public class ChunkHider {
|
||||
|
||||
public void skipPalette() {
|
||||
int paletteLength = copyVarInt();
|
||||
for(int i = 0; i < paletteLength; i++)
|
||||
for (int i = 0; i < paletteLength; i++)
|
||||
copyVarInt();
|
||||
}
|
||||
|
||||
public void processPalette() {
|
||||
if(skipSection) {
|
||||
if (skipSection) {
|
||||
skipPalette();
|
||||
return;
|
||||
}
|
||||
|
||||
int paletteLength = copyVarInt();
|
||||
if(paletteLength == 0)
|
||||
if (paletteLength == 0)
|
||||
return;
|
||||
|
||||
paletted = true;
|
||||
air = 0;
|
||||
target = 0;
|
||||
|
||||
for(int i = 0; i < paletteLength; i++) {
|
||||
for (int i = 0; i < paletteLength; i++) {
|
||||
int entry = ProtocolUtils.readVarInt(in);
|
||||
if(obfuscate.contains(entry))
|
||||
if (obfuscate.contains(entry))
|
||||
entry = techHider.getObfuscationTargetId();
|
||||
|
||||
if(entry == TechHider.AIR_ID)
|
||||
if (entry == TechHider.AIR_ID)
|
||||
air = i;
|
||||
else if(entry == techHider.getObfuscationTargetId())
|
||||
else if (entry == techHider.getObfuscationTargetId())
|
||||
target = i;
|
||||
|
||||
ProtocolUtils.writeVarInt(out, entry);
|
||||
@@ -266,7 +267,7 @@ public class ChunkHider {
|
||||
|
||||
public void skipDataArray() {
|
||||
int dataArrayLength = copyVarInt();
|
||||
out.writeBytes(in, dataArrayLength*8);
|
||||
out.writeBytes(in, dataArrayLength * 8);
|
||||
}
|
||||
|
||||
public void skipNewDataArray(int entries) {
|
||||
@@ -274,14 +275,14 @@ public class ChunkHider {
|
||||
return;
|
||||
}
|
||||
|
||||
char valuesPerLong = (char)(64 / bitsPerBlock);
|
||||
char valuesPerLong = (char) (64 / bitsPerBlock);
|
||||
int i1 = (entries + valuesPerLong - 1) / valuesPerLong;
|
||||
out.writeBytes(in, i1 * Long.BYTES);
|
||||
}
|
||||
|
||||
public long[] readDataArray() {
|
||||
long[] array = new long[copyVarInt()];
|
||||
for(int i = 0; i < array.length; i++)
|
||||
for (int i = 0; i < array.length; i++)
|
||||
array[i] = in.readLong();
|
||||
|
||||
return array;
|
||||
@@ -295,14 +296,14 @@ public class ChunkHider {
|
||||
char valuesPerLong = (char) (64 / bitsPerBlock);
|
||||
int i1 = (entries + valuesPerLong - 1) / valuesPerLong;
|
||||
long[] array = new long[i1];
|
||||
for(int i = 0; i < i1; i++)
|
||||
for (int i = 0; i < i1; i++)
|
||||
array[i] = in.readLong();
|
||||
|
||||
return array;
|
||||
}
|
||||
|
||||
public void writeDataArray(long[] array) {
|
||||
for(long l : array)
|
||||
for (long l : array)
|
||||
out.writeLong(l);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,7 +33,8 @@ import java.util.function.BiFunction;
|
||||
import java.util.function.UnaryOperator;
|
||||
|
||||
public class ProtocolUtils {
|
||||
private ProtocolUtils() {}
|
||||
private ProtocolUtils() {
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public static BiFunction<Object, UnaryOperator<Object>, Object> arrayCloneGenerator(Class<?> elementClass) {
|
||||
@@ -41,7 +42,7 @@ public class ProtocolUtils {
|
||||
int length = Array.getLength(array);
|
||||
Object result = Array.newInstance(elementClass, length);
|
||||
|
||||
for(int i = 0; i < length; i++)
|
||||
for (int i = 0; i < length; i++)
|
||||
Array.set(result, i, worker.apply(Array.get(array, i)));
|
||||
|
||||
return result;
|
||||
@@ -69,14 +70,15 @@ public class ProtocolUtils {
|
||||
}
|
||||
|
||||
private static BiConsumer<Object, Object> shallowFill(Class<?> clazz) {
|
||||
if(clazz == null)
|
||||
return (source, clone) -> {};
|
||||
if (clazz == null)
|
||||
return (source, clone) -> {
|
||||
};
|
||||
|
||||
BiConsumer<Object, Object> superFiller = shallowFill(clazz.getSuperclass());
|
||||
|
||||
Field[] fds = clazz.getDeclaredFields();
|
||||
List<Field> fields = new ArrayList<>();
|
||||
for(Field field : fds) {
|
||||
for (Field field : fds) {
|
||||
if (Modifier.isStatic(field.getModifiers()))
|
||||
continue;
|
||||
|
||||
@@ -87,7 +89,7 @@ public class ProtocolUtils {
|
||||
return (source, clone) -> {
|
||||
superFiller.accept(source, clone);
|
||||
try {
|
||||
for(Field field : fields) {
|
||||
for (Field field : fields) {
|
||||
field.set(clone, field.get(source));
|
||||
}
|
||||
} catch (IllegalAccessException e) {
|
||||
@@ -97,9 +99,9 @@ public class ProtocolUtils {
|
||||
};
|
||||
}
|
||||
|
||||
public static int posToChunk(int c){
|
||||
public static int posToChunk(int c) {
|
||||
int chunk = c / 16;
|
||||
if(c < 0)
|
||||
if (c < 0)
|
||||
chunk--;
|
||||
return chunk;
|
||||
}
|
||||
@@ -170,7 +172,7 @@ public class ProtocolUtils {
|
||||
public static byte[] writeVarInt(int value) {
|
||||
List<Byte> buffer = new ArrayList<>(5);
|
||||
do {
|
||||
byte temp = (byte)(value & 0b01111111);
|
||||
byte temp = (byte) (value & 0b01111111);
|
||||
// Note: >>> means that the sign bit is shifted with the rest of the number rather than being left alone
|
||||
value >>>= 7;
|
||||
if (value != 0) {
|
||||
@@ -182,20 +184,20 @@ public class ProtocolUtils {
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public static class ChunkPos{
|
||||
public static class ChunkPos {
|
||||
final int x;
|
||||
final int z;
|
||||
|
||||
public ChunkPos(int x, int z){
|
||||
public ChunkPos(int x, int z) {
|
||||
this.x = x;
|
||||
this.z = z;
|
||||
}
|
||||
|
||||
public final int x(){
|
||||
public final int x() {
|
||||
return x;
|
||||
}
|
||||
|
||||
public final int z(){
|
||||
public final int z() {
|
||||
return z;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,6 +35,7 @@ public class ProtocolWrapper {
|
||||
private static final Reflection.Field<SectionPos> multiBlockChangeChunk = Reflection.getField(TechHider.multiBlockChangePacket, SectionPos.class, 0);
|
||||
private static final Reflection.Field<short[]> multiBlockChangePos = Reflection.getField(TechHider.multiBlockChangePacket, short[].class, 0);
|
||||
private static final Reflection.Field<BlockState[]> multiBlockChangeBlocks = Reflection.getField(TechHider.multiBlockChangePacket, BlockState[].class, 0);
|
||||
|
||||
public BiFunction<Player, Object, Object> multiBlockChangeGenerator(TechHider techHider) {
|
||||
return (p, packet) -> {
|
||||
TechHider.LocationEvaluator locationEvaluator = techHider.getLocationEvaluator();
|
||||
@@ -42,7 +43,7 @@ public class ProtocolWrapper {
|
||||
int chunkX = TechHider.blockPositionX.get(chunkCoords);
|
||||
int chunkY = TechHider.blockPositionY.get(chunkCoords);
|
||||
int chunkZ = TechHider.blockPositionZ.get(chunkCoords);
|
||||
if(locationEvaluator.skipChunkSection(p, chunkX, chunkY, chunkZ))
|
||||
if (locationEvaluator.skipChunkSection(p, chunkX, chunkY, chunkZ))
|
||||
return packet;
|
||||
|
||||
packet = TechHider.multiBlockChangeCloner.apply(packet);
|
||||
@@ -50,10 +51,10 @@ public class ProtocolWrapper {
|
||||
final BlockState[] oldBlocks = multiBlockChangeBlocks.get(packet);
|
||||
ArrayList<Short> poss = new ArrayList<>(oldPos.length);
|
||||
ArrayList<BlockState> blocks = new ArrayList<>(oldPos.length);
|
||||
for(int i = 0; i < oldPos.length; i++) {
|
||||
for (int i = 0; i < oldPos.length; i++) {
|
||||
short pos = oldPos[i];
|
||||
BlockState block = oldBlocks[i];
|
||||
switch(locationEvaluator.check(p, 16*chunkX + (pos >> 8 & 0xF), 16*chunkY + (pos & 0xF), 16*chunkZ + (pos >> 4 & 0xF))) {
|
||||
switch (locationEvaluator.check(p, 16 * chunkX + (pos >> 8 & 0xF), 16 * chunkY + (pos & 0xF), 16 * chunkZ + (pos >> 4 & 0xF))) {
|
||||
case SKIP:
|
||||
poss.add(pos);
|
||||
blocks.add(block);
|
||||
@@ -67,11 +68,11 @@ public class ProtocolWrapper {
|
||||
}
|
||||
}
|
||||
|
||||
if(blocks.isEmpty())
|
||||
if (blocks.isEmpty())
|
||||
return null;
|
||||
|
||||
short[] newPos = new short[poss.size()];
|
||||
for(int i = 0; i < newPos.length; i++)
|
||||
for (int i = 0; i < newPos.length; i++)
|
||||
newPos[i] = poss.get(i);
|
||||
|
||||
multiBlockChangePos.set(packet, newPos);
|
||||
@@ -82,6 +83,7 @@ public class ProtocolWrapper {
|
||||
|
||||
private static final Reflection.Field<BlockEntityType> tileEntityType = Reflection.getField(TechHider.tileEntityDataPacket, BlockEntityType.class, 0);
|
||||
private static final BlockEntityType<?> signType = Reflection.getField(BlockEntityType.class, BlockEntityType.class, 0, SignBlockEntity.class).get(null);
|
||||
|
||||
public boolean unfilteredTileEntityDataAction(Object packet) {
|
||||
return tileEntityType.get(packet) != signType;
|
||||
}
|
||||
|
||||
@@ -101,12 +101,13 @@ public class TechHider {
|
||||
private static final Function<Object, Object> blockChangeCloner = ProtocolUtils.shallowCloneGenerator(blockChangePacket);
|
||||
private static final Reflection.Field<?> blockChangePosition = Reflection.getField(blockChangePacket, blockPosition, 0);
|
||||
private static final Reflection.Field<?> blockChangeBlockData = Reflection.getField(blockChangePacket, iBlockData, 0);
|
||||
|
||||
private Object blockChangeHider(Player p, Object packet) {
|
||||
switch (locationEvaluator.checkBlockPos(p, blockChangePosition.get(packet))) {
|
||||
case SKIP:
|
||||
return packet;
|
||||
case CHECK:
|
||||
if(!iBlockDataHidden((BlockState) blockChangeBlockData.get(packet)))
|
||||
if (!iBlockDataHidden((BlockState) blockChangeBlockData.get(packet)))
|
||||
return packet;
|
||||
case HIDE:
|
||||
packet = blockChangeCloner.apply(packet);
|
||||
@@ -122,6 +123,7 @@ public class TechHider {
|
||||
|
||||
private static final Class<?> blockActionPacket = ClientboundBlockEventPacket.class;
|
||||
private static final Reflection.Field<?> blockActionPosition = Reflection.getField(blockActionPacket, blockPosition, 0);
|
||||
|
||||
private Object blockActionHider(Player p, Object packet) {
|
||||
if (locationEvaluator.checkBlockPos(p, blockActionPosition.get(packet)) == State.SKIP)
|
||||
return packet;
|
||||
@@ -130,12 +132,13 @@ public class TechHider {
|
||||
|
||||
public static final Class<?> tileEntityDataPacket = ClientboundBlockEntityDataPacket.class;
|
||||
private static final Reflection.Field<?> tileEntityDataPosition = Reflection.getField(tileEntityDataPacket, blockPosition, 0);
|
||||
|
||||
private Object tileEntityDataHider(Player p, Object packet) {
|
||||
switch (locationEvaluator.checkBlockPos(p, tileEntityDataPosition.get(packet))) {
|
||||
case SKIP:
|
||||
return packet;
|
||||
case CHECK:
|
||||
if(ProtocolWrapper.impl.unfilteredTileEntityDataAction(packet))
|
||||
if (ProtocolWrapper.impl.unfilteredTileEntityDataAction(packet))
|
||||
return packet;
|
||||
default:
|
||||
return null;
|
||||
@@ -155,9 +158,11 @@ public class TechHider {
|
||||
}
|
||||
|
||||
boolean skipChunk(Player player, int x, int z);
|
||||
|
||||
default boolean skipChunkSection(Player player, int x, int y, int z) {
|
||||
return skipChunk(player, x, z);
|
||||
}
|
||||
|
||||
default State check(Player player, int x, int y, int z) {
|
||||
return skipChunkSection(player, ProtocolUtils.posToChunk(x), ProtocolUtils.posToChunk(y), ProtocolUtils.posToChunk(z)) ? State.SKIP : State.CHECK;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user