mirror of
https://github.com/GeyserMC/Geyser.git
synced 2024-08-14 23:57:35 +00:00
Merge branch 'master' of https://github.com/GeyserMC/Geyser
This commit is contained in:
commit
e60a17dbcf
856 changed files with 76411 additions and 30500 deletions
12
.github/FUNDING.yml
vendored
12
.github/FUNDING.yml
vendored
|
@ -1,12 +0,0 @@
|
|||
# These are supported funding model platforms
|
||||
|
||||
github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
|
||||
patreon: #GeyserMC # Disabled currently
|
||||
open_collective: # Replace with a single Open Collective username
|
||||
ko_fi: # Replace with a single Ko-fi username
|
||||
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
|
||||
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
|
||||
liberapay: # Replace with a single Liberapay username
|
||||
issuehunt: # Replace with a single IssueHunt username
|
||||
otechie: # Replace with a single Otechie username
|
||||
custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']
|
40
.github/ISSUE_TEMPLATE/bug_report.md
vendored
40
.github/ISSUE_TEMPLATE/bug_report.md
vendored
|
@ -1,40 +0,0 @@
|
|||
---
|
||||
name: Bug report
|
||||
about: Create a report to help us improve
|
||||
title: ''
|
||||
labels: ''
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
<!--- Please follow this format COMPLETELY and make sure the bug you are reporting has not been reported yet. Reports should contain as much information or context as possible to help us find the problem. Simply creating an issue on a vague topic will not help us at all, and if you are unsure if something should belong here, please contact us on [Discord](http://discord.geysermc.org).-->
|
||||
|
||||
<!--- Issues pertaining to connection problem, or anything of that covered on the [Common Issues](https://github.com/GeyserMC/Geyser/wiki/Common-Issues) do not belong here and only clutter this issue tracker. -->
|
||||
|
||||
**Describe the bug**
|
||||
<!--- A clear and concise description of what the bug is. -->
|
||||
|
||||
**To Reproduce**
|
||||
<!--- Steps to reproduce the behavior: -->
|
||||
<!--- 1. Go to '...' -->
|
||||
<!--- 2. Click on '....' -->
|
||||
<!--- 3. Scroll down to '....' -->
|
||||
<!--- 4. See error -->
|
||||
|
||||
**Expected behavior**
|
||||
<!--- A clear and concise description of what you expected to happen. -->
|
||||
|
||||
**Screenshots / Videos**
|
||||
<!--- If applicable, add screenshots to help explain your problem. -->
|
||||
|
||||
**Server Version**
|
||||
<!--- Give us the exact output from `/version`. Saying "latest" does not help us at all. -->
|
||||
|
||||
**Geyser Version**
|
||||
<!--- Give us the exact build number as well as branch if applicable. Saying "latest" does not help us at all. This info can be obtained from `/geyser version`.Please also include if you are running the standalone version, or specify which plugin version you are using. If your issue is a connection problem, please specify if you are using the Floodgate plugin. -->
|
||||
|
||||
**Minecraft: Bedrock Edition Version**
|
||||
<!-- The version of your Minecraft: Bedrock Edition client you tested with. -->
|
||||
|
||||
**Additional Context**
|
||||
<!--- Add any other context about the problem here. Include any plugins on the Minecraft server that may cause problems. Please also include the link to a dump by using `/geyser dump` --->
|
64
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
Normal file
64
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
Normal file
|
@ -0,0 +1,64 @@
|
|||
name: Bug report
|
||||
description: Create a report to help us improve
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Thanks for taking the time to fill out this bug report for Geyser! Fill out the following form to your best ability to help us fix the problem.
|
||||
Only use this if you're absolutely sure that you found a bug and can reproduce it. For anything else, use: [our Discord server](https://discord.gg/geysermc), [the FAQ](https://github.com/GeyserMC/Geyser/wiki/FAQ) or the [Common Issues](https://github.com/GeyserMC/Geyser/wiki/Common-Issues).
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Describe the bug
|
||||
description: A clear and concise description of what the bug is.
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: To Reproduce
|
||||
description: Steps to reproduce this behaviour
|
||||
placeholder: |
|
||||
1. Go to '...'
|
||||
2. Click on '...'
|
||||
3. Scroll down to '...'
|
||||
4. See error
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Expected behaviour
|
||||
description: A clear and concise description of what you expected to happen.
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Screenshots / Videos
|
||||
description: If applicable, add screenshots to help explain your problem.
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Server Version and Plugins
|
||||
description: |
|
||||
If you just run Geyser-Spigot, you can leave this area blank as the next section covers this information.
|
||||
If you're running a multi-server instance or using Geyser Standalone:
|
||||
* Give us the exact output from `/version` on all servers involved. Saying "latest" does not help us at all.
|
||||
* Please list all plugins on all servers involved.
|
||||
If this bug occurs on a server you do not control, please fill this in to the best of your knowledge.
|
||||
- type: input
|
||||
attributes:
|
||||
label: Geyser Dump
|
||||
description: If Geyser starts correctly, please include the link to a dump using `/geyser dump`. If you're using the Standalone GUI, you can find the option under `Commands` => `Dump`. Doing this provides us information about your server that we can use to debug your issue.
|
||||
- type: input
|
||||
attributes:
|
||||
label: Geyser Version
|
||||
description: What version of Geyser are you running?
|
||||
placeholder: "For example: 1.2.0-SNAPSHOT (git-master-2d9baf1)"
|
||||
validations:
|
||||
required: true
|
||||
- type: input
|
||||
attributes:
|
||||
label: "Minecraft: Bedrock Edition Version"
|
||||
description: "What version of Minecraft: Bedrock Edition are you using? Leave empty if the bug happens before you can connect with Minecraft: Bedrock Edition."
|
||||
placeholder: "For example: 1.16.201"
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Additional Context
|
||||
description: Add any other context about the problem here
|
10
.github/ISSUE_TEMPLATE/config.yml
vendored
10
.github/ISSUE_TEMPLATE/config.yml
vendored
|
@ -1,5 +1,11 @@
|
|||
blank_issues_enabled: false
|
||||
contact_links:
|
||||
- name: GeyserMC Discord
|
||||
url: http://discord.geysermc.org/
|
||||
- name: Common Issues
|
||||
url: https://github.com/GeyserMC/Geyser/wiki/Common-Issues
|
||||
about: Check the common issues to see if you are not alone with that issue and see how you can fix them.
|
||||
- name: Frequently Asked Questions
|
||||
url: https://github.com/GeyserMC/Geyser/wiki/FAQ
|
||||
about: Look at the FAQ page for answers to frequently asked questions.
|
||||
- name: Get help on the GeyserMC Discord server
|
||||
url: https://discord.gg/geysermc
|
||||
about: If your issue seems like it could possibly be an easy fix due to configuration, please hop on our Discord.
|
||||
|
|
14
.github/ISSUE_TEMPLATE/feature_request.md
vendored
14
.github/ISSUE_TEMPLATE/feature_request.md
vendored
|
@ -1,14 +0,0 @@
|
|||
---
|
||||
name: Feature request
|
||||
about: Suggest an idea for this project
|
||||
title: ''
|
||||
labels: ''
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
**What feature do you want?**
|
||||
Add a description
|
||||
|
||||
**Alternatives?**
|
||||
List any alternatives you might have tried
|
21
.github/ISSUE_TEMPLATE/feature_request.yml
vendored
Normal file
21
.github/ISSUE_TEMPLATE/feature_request.yml
vendored
Normal file
|
@ -0,0 +1,21 @@
|
|||
name: Feature request
|
||||
description: Suggest an idea for this project
|
||||
labels: "Feature Request"
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Thanks for taking the time to fill out this feature request for Geyser! Please fill out the following form to your best ability to help us understand your feature request and significantly improve the chance of getting added.
|
||||
For anything else than a feature request, use: [our Discord server](https://discord.gg/geysermc), [the FAQ](https://github.com/GeyserMC/Geyser/wiki/FAQ) or [the Common Issues](https://github.com/GeyserMC/Geyser/wiki/Common-Issues).
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: What feature do you want to see added?
|
||||
description: A clear and concise description of your feature request.
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Are there any alternatives?
|
||||
description: List any alternatives you might have tried
|
||||
validations:
|
||||
required: true
|
4
.github/workflows/pullrequest.yml
vendored
4
.github/workflows/pullrequest.yml
vendored
|
@ -15,10 +15,10 @@ jobs:
|
|||
key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-maven-
|
||||
- name: Set up JDK 1.8
|
||||
- name: Set up JDK 16
|
||||
uses: actions/setup-java@v1
|
||||
with:
|
||||
java-version: 1.8
|
||||
java-version: 16
|
||||
- name: submodules-init
|
||||
uses: snickerbockers/submodules-init@v4
|
||||
- name: Build with Maven
|
||||
|
|
8
.gitmodules
vendored
8
.gitmodules
vendored
|
@ -1,6 +1,6 @@
|
|||
[submodule "connector/src/main/resources/mappings"]
|
||||
path = connector/src/main/resources/mappings
|
||||
[submodule "core/src/main/resources/mappings"]
|
||||
path = core/src/main/resources/mappings
|
||||
url = https://github.com/GeyserMC/mappings.git
|
||||
[submodule "connector/src/main/resources/languages"]
|
||||
path = connector/src/main/resources/languages
|
||||
[submodule "core/src/main/resources/languages"]
|
||||
path = core/src/main/resources/languages
|
||||
url = https://github.com/GeyserMC/languages.git
|
||||
|
|
|
@ -1,39 +1,46 @@
|
|||
Thank for for considering a contribution! Generally, Geyser welcomes PRs from everyone. There are some guidelines about what features should go where:
|
||||
Thank you for considering a contribution! Generally, Geyser welcomes PRs from everyone. There are some guidelines about what features should go where:
|
||||
|
||||
|
||||
*Pull requests that may not get accepted:* Niche features that apply to a specific group, for example integration with a specific plugin. For now, please create a separate plugin if possible.
|
||||
*Pull requests that may not get accepted:* Niche features that apply to a specific group, for example, integration with a specific plugin. For now, please create a separate plugin if possible.
|
||||
|
||||
*Pull requests for Floodgate:* Anything that opens up information within the game for developers to use.
|
||||
|
||||
*Pull requests for Geyser:* Anything that fixes compatibility between Java or Bedrock, or improves the quality of play for Bedrock players. The exception is wherever direct server access is required; in this case it may be better for Floodgate.
|
||||
*Pull requests for Geyser:* Anything that fixes compatibility between Java or Bedrock or improves the quality of play for Bedrock players. The exception is wherever direct server access is required; in this case, it may be better for Floodgate.
|
||||
|
||||
|
||||
We have some general style guides that should be applied throughout the code:
|
||||
|
||||
```java
|
||||
public class LongClassName {
|
||||
private static final int AIR_ITEM = 0; // Static item names should be capitalized
|
||||
|
||||
private static final AIR_ITEM = 0; // Static item names should be capitalized
|
||||
public Int2IntMap items = new Int2IntOpenHashMap(); // Use the interface as the class type but initialize with the implementation.
|
||||
|
||||
public Int2IntMap items = new Int2IntOpenHashMap(); // Use the interface as the class type but initialize with the implementation.
|
||||
public int nameWithMultipleWords = 0;
|
||||
|
||||
public int nameWithMultipleWords = 0;
|
||||
/**
|
||||
* Javadoc comment to explain what a function does.
|
||||
*/
|
||||
@RandomAnnotation(stuff = true, moreStuff = "might exist")
|
||||
public void applyStuff() {
|
||||
Variable variable = new Variable();
|
||||
Variable otherVariable = new Variable();
|
||||
|
||||
/**
|
||||
* Javadoc comment to explain what a function does.
|
||||
*/
|
||||
public void applyStuff() {
|
||||
if (condition) {
|
||||
// Do stuff.
|
||||
} else if (anotherCondition) {
|
||||
// Do something else.
|
||||
}
|
||||
|
||||
switch (value) {
|
||||
case 0:
|
||||
break;
|
||||
case 1:
|
||||
break:
|
||||
}
|
||||
if (condition) {
|
||||
// Do stuff.
|
||||
} else if (anotherCondition) {
|
||||
// Do something else.
|
||||
}
|
||||
|
||||
switch (value) {
|
||||
case 0:
|
||||
stuff();
|
||||
break;
|
||||
case 1:
|
||||
differentStuff();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
@ -41,4 +48,4 @@ Make sure to comment your code where possible.
|
|||
|
||||
The nature of our software requires a lot of arrays and maps to be stored - where possible, use Fastutil's specialized maps. For example, if you're storing block state translations, use an `Int2IntMap`.
|
||||
|
||||
We have a rundown of all the tools you need to develop over on our [wiki](https://github.com/GeyserMC/Geyser/wiki/Developer-Guide). If you have any questions, please feel free to reach out to our [Discord](https://discord.geysermc.org)!
|
||||
We have a rundown of all the tools you need to develop over on our [wiki](https://github.com/GeyserMC/Geyser/wiki/Developer-Guide). If you have any questions, please feel free to reach out to our [Discord](https://discord.gg/geysermc)!
|
||||
|
|
34
Jenkinsfile
vendored
34
Jenkinsfile
vendored
|
@ -2,7 +2,7 @@ pipeline {
|
|||
agent any
|
||||
tools {
|
||||
maven 'Maven 3'
|
||||
jdk 'Java 8'
|
||||
jdk 'Java 16'
|
||||
}
|
||||
options {
|
||||
buildDiscarder(logRotator(artifactNumToKeepStr: '20'))
|
||||
|
@ -26,7 +26,27 @@ pipeline {
|
|||
}
|
||||
|
||||
steps {
|
||||
sh 'mvn javadoc:jar source:jar deploy -DskipTests'
|
||||
rtMavenDeployer(
|
||||
id: "maven-deployer",
|
||||
serverId: "opencollab-artifactory",
|
||||
releaseRepo: "maven-releases",
|
||||
snapshotRepo: "maven-snapshots"
|
||||
)
|
||||
rtMavenResolver(
|
||||
id: "maven-resolver",
|
||||
serverId: "opencollab-artifactory",
|
||||
releaseRepo: "maven-deploy-release",
|
||||
snapshotRepo: "maven-deploy-snapshot"
|
||||
)
|
||||
rtMavenRun(
|
||||
pom: 'pom.xml',
|
||||
goals: 'javadoc:jar source:jar install -pl :core -am -DskipTests',
|
||||
deployerId: "maven-deployer",
|
||||
resolverId: "maven-resolver"
|
||||
)
|
||||
rtPublishBuildInfo(
|
||||
serverId: "opencollab-artifactory"
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -66,7 +86,15 @@ pipeline {
|
|||
}
|
||||
deleteDir()
|
||||
withCredentials([string(credentialsId: 'geyser-discord-webhook', variable: 'DISCORD_WEBHOOK')]) {
|
||||
discordSend description: "**Build:** [${currentBuild.id}](${env.BUILD_URL})\n**Status:** [${currentBuild.currentResult}](${env.BUILD_URL})\n${changes}\n\n[**Artifacts on Jenkins**](https://ci.nukkitx.com/job/Geyser)", footer: 'Cloudburst Jenkins', link: env.BUILD_URL, successful: currentBuild.resultIsBetterOrEqualTo('SUCCESS'), title: "${env.JOB_NAME} #${currentBuild.id}", webhookURL: DISCORD_WEBHOOK
|
||||
discordSend description: "**Build:** [${currentBuild.id}](${env.BUILD_URL})\n**Status:** [${currentBuild.currentResult}](${env.BUILD_URL})\n${changes}\n\n[**Artifacts on Jenkins**](https://ci.opencollab.dev/job/GeyserMC/job/Geyser)", footer: 'Open Collaboration Jenkins', link: env.BUILD_URL, successful: currentBuild.resultIsBetterOrEqualTo('SUCCESS'), title: "${env.JOB_NAME} #${currentBuild.id}", webhookURL: DISCORD_WEBHOOK
|
||||
}
|
||||
}
|
||||
success {
|
||||
script {
|
||||
if (env.BRANCH_NAME == 'master') {
|
||||
build propagate: false, wait: false, job: 'GeyserMC/Geyser-Fabric/java-1.18', parameters: [booleanParam(name: 'SKIP_DISCORD', value: true)]
|
||||
build propagate: false, wait: false, job: 'GeyserMC/GeyserConnect/master', parameters: [booleanParam(name: 'SKIP_DISCORD', value: true)]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
2
LICENSE
2
LICENSE
|
@ -1,6 +1,6 @@
|
|||
The MIT License
|
||||
|
||||
Copyright (c) 2019-2020 GeyserMC. http://geysermc.org
|
||||
Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
|
|
39
README.md
39
README.md
|
@ -1,11 +1,10 @@
|
|||
<img src="https://geysermc.org/img/geyser-1760-860.png" alt="Geyser" width="600"/>
|
||||
|
||||
[![forthebadge made-with-java](http://ForTheBadge.com/images/badges/made-with-java.svg)](https://java.com/)
|
||||
[![forthebadge made-with-java](https://forthebadge.com/images/badges/made-with-java.svg)](https://java.com/)
|
||||
|
||||
[![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)
|
||||
[![Build Status](https://ci.nukkitx.com/job/Geyser/job/master/badge/icon)](https://ci.nukkitx.com/job/GeyserMC/job/Geyser/job/master/)
|
||||
[![Discord](https://img.shields.io/discord/613163671870242838.svg?color=%237289da&label=discord)](http://discord.geysermc.org/)
|
||||
[![HitCount](http://hits.dwyl.io/Geyser/GeyserMC.svg)](http://hits.dwyl.io/Geyser/GeyserMC)
|
||||
[![Build Status](https://ci.opencollab.dev/job/Geyser/job/master/badge/icon)](https://ci.opencollab.dev/job/GeyserMC/job/Geyser/job/master/)
|
||||
[![Discord](https://img.shields.io/discord/613163671870242838.svg?color=%237289da&label=discord)](https://discord.gg/geysermc)
|
||||
[![Crowdin](https://badges.crowdin.net/geyser/localized.svg)](https://translate.geysermc.org/)
|
||||
|
||||
Geyser is a bridge between Minecraft: Bedrock Edition and Minecraft: Java Edition, closing the gap from those wanting to play true cross-platform.
|
||||
|
@ -14,41 +13,38 @@ Geyser is an open collaboration project by [CubeCraft Games](https://cubecraft.n
|
|||
|
||||
## What is Geyser?
|
||||
Geyser is a proxy, bridging the gap between Minecraft: Bedrock Edition and Minecraft: Java Edition servers.
|
||||
The ultimate goal of this project is to allow Minecraft: Bedrock Edition users to join Minecraft: Java Edition servers as seamlessly as possible. **Please note, this project is still a work in progress and should not be used on production. Expect bugs!**
|
||||
The ultimate goal of this project is to allow Minecraft: Bedrock Edition users to join Minecraft: Java Edition servers as seamlessly as possible. However, due to the nature of Geyser translating packets over the network of two different games, *do not expect everything to work perfectly!*
|
||||
|
||||
Special thanks to the DragonProxy project for being a trailblazer in protocol translation and for all the team members who have now joined us here!
|
||||
Special thanks to the DragonProxy project for being a trailblazer in protocol translation and for all the team members who have joined us here!
|
||||
|
||||
### Currently supporting Minecraft Bedrock v1.16.100 and Minecraft Java v1.16.4.
|
||||
### Currently supporting Minecraft Bedrock 1.17.30 - 1.17.41 + 1.18.0 - 1.18.2 and Minecraft Java 1.18/1.18.1.
|
||||
|
||||
## Setting Up
|
||||
Take a look [here](https://github.com/GeyserMC/Geyser/wiki#Setup) for how to set up Geyser.
|
||||
Take a look [here](https://github.com/GeyserMC/Geyser/wiki/Setup) for how to set up Geyser.
|
||||
|
||||
[![YouTube Video](https://img.youtube.com/vi/U7dZZ8w7Gi4/0.jpg)](https://www.youtube.com/watch?v=U7dZZ8w7Gi4)
|
||||
|
||||
## Links:
|
||||
- Website: https://geysermc.org
|
||||
- Docs: https://github.com/GeyserMC/Geyser/wiki
|
||||
- Download: http://ci.geysermc.org
|
||||
- Discord: http://discord.geysermc.org/
|
||||
- ~~Donate: https://patreon.com/GeyserMC~~ Currently disabled.
|
||||
- Download: https://ci.geysermc.org
|
||||
- Discord: https://discord.gg/geysermc
|
||||
- Donate: https://opencollective.com/geysermc
|
||||
- Test Server: `test.geysermc.org` port `25565` for Java and `19132` for Bedrock
|
||||
|
||||
## What's Left to be Added/Fixed
|
||||
- The Following Inventories
|
||||
- [ ] Enchantment Table (as a proper GUI)
|
||||
- [ ] Beacon
|
||||
- [ ] Cartography Table
|
||||
- [ ] Stonecutter
|
||||
- [ ] Structure Block
|
||||
- [ ] Horse Inventory
|
||||
- [ ] Loom
|
||||
- [ ] Smithing Table
|
||||
- Near-perfect movement (to the point where anticheat on large servers is unlikely to ban you)
|
||||
- Resource pack conversion/CustomModelData
|
||||
- Some Entity Flags
|
||||
- Structure block UI
|
||||
|
||||
## What can't be fixed
|
||||
There are a few things Geyser is unable to support due to various differences between Minecraft Bedrock and Java. For a list of these limitations, see the [Current Limitations](https://github.com/GeyserMC/Geyser/wiki/Current-Limitations) page.
|
||||
|
||||
## Compiling
|
||||
1. Clone the repo to your computer
|
||||
2. [Install Maven](https://maven.apache.org/install.html)
|
||||
3. Navigate to the Geyser root directory and run `git submodule update --init --recursive`. This downloads all the needed submodules for Geyser and is a crucial step in this process.
|
||||
3. Navigate to the Geyser root directory and run `git submodule update --init --recursive`. This command downloads all the needed submodules for Geyser and is a crucial step in this process.
|
||||
4. Run `mvn clean install` and locate to the `target` folder.
|
||||
|
||||
## Contributing
|
||||
|
@ -56,6 +52,7 @@ Any contributions are appreciated. Please feel free to reach out to us on [Disco
|
|||
you're interested in helping out with Geyser.
|
||||
|
||||
## Libraries Used:
|
||||
- [Adventure Text Library](https://github.com/KyoriPowered/adventure)
|
||||
- [NukkitX Bedrock Protocol Library](https://github.com/NukkitX/Protocol)
|
||||
- [Steveice10's Java Protocol Library](https://github.com/Steveice10/MCProtocolLib)
|
||||
- [TerminalConsoleAppender](https://github.com/Minecrell/TerminalConsoleAppender)
|
||||
|
|
14
ap/pom.xml
Normal file
14
ap/pom.xml
Normal file
|
@ -0,0 +1,14 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>org.geysermc</groupId>
|
||||
<artifactId>geyser-parent</artifactId>
|
||||
<version>2.0.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>ap</artifactId>
|
||||
<version>2.0.0-SNAPSHOT</version>
|
||||
</project>
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
* @author GeyserMC
|
||||
* @link https://github.com/GeyserMC/Geyser
|
||||
*/
|
||||
|
||||
package org.geysermc.processor;
|
||||
|
||||
import javax.annotation.processing.SupportedAnnotationTypes;
|
||||
import javax.annotation.processing.SupportedSourceVersion;
|
||||
import javax.lang.model.SourceVersion;
|
||||
|
||||
@SupportedAnnotationTypes("*")
|
||||
@SupportedSourceVersion(SourceVersion.RELEASE_16)
|
||||
public class BlockEntityProcessor extends ClassProcessor {
|
||||
public BlockEntityProcessor() {
|
||||
super("org.geysermc.geyser.translator.level.block.entity.BlockEntity");
|
||||
}
|
||||
}
|
184
ap/src/main/java/org/geysermc/processor/ClassProcessor.java
Normal file
184
ap/src/main/java/org/geysermc/processor/ClassProcessor.java
Normal file
|
@ -0,0 +1,184 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
* @author GeyserMC
|
||||
* @link https://github.com/GeyserMC/Geyser
|
||||
*/
|
||||
|
||||
package org.geysermc.processor;
|
||||
|
||||
import javax.annotation.processing.AbstractProcessor;
|
||||
import javax.annotation.processing.ProcessingEnvironment;
|
||||
import javax.annotation.processing.RoundEnvironment;
|
||||
import javax.lang.model.element.AnnotationMirror;
|
||||
import javax.lang.model.element.Element;
|
||||
import javax.lang.model.element.ElementKind;
|
||||
import javax.lang.model.element.TypeElement;
|
||||
import javax.tools.Diagnostic;
|
||||
import javax.tools.FileObject;
|
||||
import javax.tools.StandardLocation;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
public class ClassProcessor extends AbstractProcessor {
|
||||
private final String annotationClassName;
|
||||
|
||||
private Path outputPath;
|
||||
|
||||
private final Set<String> locations = new HashSet<>();
|
||||
|
||||
public ClassProcessor(String annotationClassName) {
|
||||
this.annotationClassName = annotationClassName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void init(ProcessingEnvironment processingEnv) {
|
||||
super.init(processingEnv);
|
||||
|
||||
this.processingEnv.getMessager().printMessage(Diagnostic.Kind.NOTE, "Initializing processor " + this.annotationClassName);
|
||||
|
||||
String outputFile = processingEnv.getOptions().get("metadataOutputFile");
|
||||
if (outputFile != null && !outputFile.isEmpty()) {
|
||||
this.outputPath = Paths.get(outputFile);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
|
||||
if (roundEnv.processingOver()) {
|
||||
if (!roundEnv.errorRaised()) {
|
||||
complete();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!contains(annotations, this.annotationClassName)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (Element element : roundEnv.getRootElements()) {
|
||||
if (element.getKind() != ElementKind.CLASS) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!contains(element.getAnnotationMirrors(), this.annotationClassName)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
TypeElement typeElement = (TypeElement) element;
|
||||
this.locations.add(typeElement.getQualifiedName().toString());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean contains(Collection<? extends TypeElement> elements, String className) {
|
||||
if (elements.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (TypeElement element : elements) {
|
||||
if (element.getQualifiedName().contentEquals(className)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean contains(List<? extends AnnotationMirror> elements, String className) {
|
||||
if (elements.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (AnnotationMirror element : elements) {
|
||||
if (element.getAnnotationType().toString().equals(className)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public void complete() {
|
||||
// Read existing annotation list and verify each class still has this annotation
|
||||
try (BufferedReader reader = this.createReader()) {
|
||||
if (reader != null) {
|
||||
reader.lines().forEach(canonicalName -> {
|
||||
if (!locations.contains(canonicalName)) {
|
||||
TypeElement element = this.processingEnv.getElementUtils().getTypeElement(canonicalName);
|
||||
if (element != null && element.getKind() == ElementKind.CLASS && contains(element.getAnnotationMirrors(), this.annotationClassName)) {
|
||||
locations.add(canonicalName);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
if (!locations.isEmpty()) {
|
||||
try (BufferedWriter writer = this.createWriter()) {
|
||||
for (String location : this.locations) {
|
||||
writer.write(location);
|
||||
writer.newLine();
|
||||
}
|
||||
} catch (IOException ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
} else {
|
||||
this.processingEnv.getMessager().printMessage(Diagnostic.Kind.NOTE, "Did not find any classes annotated with " + this.annotationClassName);
|
||||
}
|
||||
this.processingEnv.getMessager().printMessage(Diagnostic.Kind.NOTE, "Completed processing for " + this.annotationClassName);
|
||||
}
|
||||
|
||||
private BufferedReader createReader() throws IOException {
|
||||
if (this.outputPath != null) {
|
||||
this.processingEnv.getMessager().printMessage(Diagnostic.Kind.NOTE, "Reading existing " + this.annotationClassName + " list from " + this.outputPath);
|
||||
return Files.newBufferedReader(this.outputPath);
|
||||
}
|
||||
FileObject obj = this.processingEnv.getFiler().getResource(StandardLocation.CLASS_OUTPUT, "", this.annotationClassName);
|
||||
if (obj != null) {
|
||||
this.processingEnv.getMessager().printMessage(Diagnostic.Kind.NOTE, "Reading existing " + this.annotationClassName + " list from " + obj.toUri());
|
||||
return new BufferedReader(obj.openReader(false));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private BufferedWriter createWriter() throws IOException {
|
||||
if (this.outputPath != null) {
|
||||
this.processingEnv.getMessager().printMessage(Diagnostic.Kind.NOTE, "Writing " + this.annotationClassName + " to " + this.outputPath);
|
||||
return Files.newBufferedWriter(this.outputPath);
|
||||
}
|
||||
|
||||
FileObject obj = this.processingEnv.getFiler().createResource(StandardLocation.CLASS_OUTPUT, "", this.annotationClassName);
|
||||
this.processingEnv.getMessager().printMessage(Diagnostic.Kind.NOTE, "Writing " + this.annotationClassName + " to " + obj.toUri());
|
||||
return new BufferedWriter(obj.openWriter());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
* @author GeyserMC
|
||||
* @link https://github.com/GeyserMC/Geyser
|
||||
*/
|
||||
|
||||
package org.geysermc.processor;
|
||||
|
||||
import javax.annotation.processing.SupportedAnnotationTypes;
|
||||
import javax.annotation.processing.SupportedSourceVersion;
|
||||
import javax.lang.model.SourceVersion;
|
||||
|
||||
@SupportedAnnotationTypes("*")
|
||||
@SupportedSourceVersion(SourceVersion.RELEASE_16)
|
||||
public class CollisionRemapperProcessor extends ClassProcessor {
|
||||
public CollisionRemapperProcessor() {
|
||||
super("org.geysermc.geyser.translator.collision.CollisionRemapper");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
* @author GeyserMC
|
||||
* @link https://github.com/GeyserMC/Geyser
|
||||
*/
|
||||
|
||||
package org.geysermc.processor;
|
||||
|
||||
import javax.annotation.processing.SupportedAnnotationTypes;
|
||||
import javax.annotation.processing.SupportedSourceVersion;
|
||||
import javax.lang.model.SourceVersion;
|
||||
|
||||
@SupportedAnnotationTypes("*")
|
||||
@SupportedSourceVersion(SourceVersion.RELEASE_16)
|
||||
public class ItemRemapperProcessor extends ClassProcessor {
|
||||
public ItemRemapperProcessor() {
|
||||
super("org.geysermc.geyser.translator.inventory.item.ItemRemapper");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
* @author GeyserMC
|
||||
* @link https://github.com/GeyserMC/Geyser
|
||||
*/
|
||||
|
||||
package org.geysermc.processor;
|
||||
|
||||
import javax.annotation.processing.SupportedAnnotationTypes;
|
||||
import javax.annotation.processing.SupportedSourceVersion;
|
||||
import javax.lang.model.SourceVersion;
|
||||
|
||||
@SupportedAnnotationTypes("*")
|
||||
@SupportedSourceVersion(SourceVersion.RELEASE_16)
|
||||
public class PacketTranslatorProcessor extends ClassProcessor {
|
||||
public PacketTranslatorProcessor() {
|
||||
super("org.geysermc.geyser.translator.protocol.Translator");
|
||||
}
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2020 GeyserMC. http://geysermc.org
|
||||
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
|
@ -23,14 +23,16 @@
|
|||
* @link https://github.com/GeyserMC/Geyser
|
||||
*/
|
||||
|
||||
package org.geysermc.connector.entity.living;
|
||||
package org.geysermc.processor;
|
||||
|
||||
import com.nukkitx.math.vector.Vector3f;
|
||||
import org.geysermc.connector.entity.type.EntityType;
|
||||
import javax.annotation.processing.SupportedAnnotationTypes;
|
||||
import javax.annotation.processing.SupportedSourceVersion;
|
||||
import javax.lang.model.SourceVersion;
|
||||
|
||||
public class CreatureEntity extends InsentientEntity {
|
||||
|
||||
public CreatureEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) {
|
||||
super(entityId, geyserId, entityType, position, motion, rotation);
|
||||
@SupportedAnnotationTypes("*")
|
||||
@SupportedSourceVersion(SourceVersion.RELEASE_16)
|
||||
public class SoundHandlerProcessor extends ClassProcessor {
|
||||
public SoundHandlerProcessor() {
|
||||
super("org.geysermc.geyser.translator.sound.SoundTranslator");
|
||||
}
|
||||
}
|
27
api/base/pom.xml
Normal file
27
api/base/pom.xml
Normal file
|
@ -0,0 +1,27 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<groupId>org.geysermc</groupId>
|
||||
<artifactId>api-parent</artifactId>
|
||||
<version>2.0.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>base-api</artifactId>
|
||||
|
||||
<properties>
|
||||
<maven.compiler.source>16</maven.compiler.source>
|
||||
<maven.compiler.target>16</maven.compiler.target>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.checkerframework</groupId>
|
||||
<artifactId>checker-qual</artifactId>
|
||||
<version>3.19.0</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
94
api/base/src/main/java/org/geysermc/api/Geyser.java
Normal file
94
api/base/src/main/java/org/geysermc/api/Geyser.java
Normal file
|
@ -0,0 +1,94 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
* @author GeyserMC
|
||||
* @link https://github.com/GeyserMC/Geyser
|
||||
*/
|
||||
|
||||
package org.geysermc.api;
|
||||
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
|
||||
/**
|
||||
* General API class for Geyser.
|
||||
*/
|
||||
@NonNull
|
||||
public class Geyser {
|
||||
private static GeyserApiBase api;
|
||||
|
||||
/**
|
||||
* Returns the base api.
|
||||
*
|
||||
* @return the base api
|
||||
*/
|
||||
public static GeyserApiBase api() {
|
||||
if (api == null) {
|
||||
throw new RuntimeException("Api has not been registered yet!");
|
||||
}
|
||||
|
||||
return api;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the api of the given type.
|
||||
*
|
||||
* @param apiClass the api class
|
||||
* @param <T> the type
|
||||
* @return the api of the given type
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <T extends GeyserApiBase> T api(@NonNull Class<T> apiClass) {
|
||||
if (apiClass.isInstance(api)) {
|
||||
return (T) api;
|
||||
}
|
||||
|
||||
if (api == null) {
|
||||
throw new RuntimeException("Api has not been registered yet!");
|
||||
} else {
|
||||
throw new RuntimeException("Api was not an instance of " + apiClass + "! Was " + api.getClass().getCanonicalName());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers the given api type. The api cannot be
|
||||
* registered if {@link #registered()} is true as
|
||||
* an api has already been specified.
|
||||
*
|
||||
* @param api the api
|
||||
*/
|
||||
public static void set(@NonNull GeyserApiBase api) {
|
||||
if (Geyser.api != null) {
|
||||
throw new RuntimeException("Cannot redefine already registered api!");
|
||||
}
|
||||
|
||||
Geyser.api = api;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets if the api has been registered and
|
||||
* is ready for usage.
|
||||
*
|
||||
* @return if the api has been registered
|
||||
*/
|
||||
public static boolean registered() {
|
||||
return api != null;
|
||||
}
|
||||
}
|
90
api/base/src/main/java/org/geysermc/api/GeyserApiBase.java
Normal file
90
api/base/src/main/java/org/geysermc/api/GeyserApiBase.java
Normal file
|
@ -0,0 +1,90 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
* @author GeyserMC
|
||||
* @link https://github.com/GeyserMC/Geyser
|
||||
*/
|
||||
|
||||
package org.geysermc.api;
|
||||
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
import org.geysermc.api.session.Connection;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* The base API class.
|
||||
*/
|
||||
public interface GeyserApiBase {
|
||||
/**
|
||||
* Gets the session from the given UUID, if applicable. The player must be logged in to the Java server
|
||||
* for this to return a non-null value.
|
||||
*
|
||||
* @param uuid the UUID of the session
|
||||
* @return the session from the given UUID, if applicable
|
||||
*/
|
||||
@Nullable
|
||||
Connection connectionByUuid(@NonNull UUID uuid);
|
||||
|
||||
/**
|
||||
* Gets the session from the given
|
||||
* XUID, if applicable.
|
||||
*
|
||||
* @param xuid the XUID of the session
|
||||
* @return the session from the given UUID, if applicable
|
||||
*/
|
||||
@Nullable
|
||||
Connection connectionByXuid(@NonNull String xuid);
|
||||
|
||||
/**
|
||||
* Gets the session from the given
|
||||
* name, if applicable.
|
||||
*
|
||||
* @param name the uuid of the session
|
||||
* @return the session from the given name, if applicable
|
||||
*/
|
||||
@Nullable
|
||||
Connection connectionByName(@NonNull String name);
|
||||
|
||||
/**
|
||||
* Gets all the online sessions.
|
||||
*
|
||||
* @return all the online sessions
|
||||
*/
|
||||
@NonNull
|
||||
List<? extends Connection> onlineConnections();
|
||||
|
||||
/**
|
||||
* @return the major API version. Bumped whenever a significant breaking change or feature addition is added.
|
||||
*/
|
||||
default int majorApiVersion() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the minor API version. May be bumped for new API additions.
|
||||
*/
|
||||
default int minorApiVersion() {
|
||||
return 0;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,59 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
* @author GeyserMC
|
||||
* @link https://github.com/GeyserMC/Geyser
|
||||
*/
|
||||
|
||||
package org.geysermc.api.session;
|
||||
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* Represents a player connection.
|
||||
*/
|
||||
@NonNull
|
||||
public interface Connection {
|
||||
/**
|
||||
* Gets the name of the connection.
|
||||
*
|
||||
* @return the name of the connection
|
||||
*/
|
||||
String name();
|
||||
|
||||
/**
|
||||
* Gets the {@link UUID} of the connection.
|
||||
*
|
||||
* @return the UUID of the connection
|
||||
*/
|
||||
UUID uuid();
|
||||
|
||||
/**
|
||||
* Gets the XUID of the connection.
|
||||
*
|
||||
* @return the XUID of the connection
|
||||
*/
|
||||
String xuid();
|
||||
|
||||
|
||||
}
|
33
api/geyser/pom.xml
Normal file
33
api/geyser/pom.xml
Normal file
|
@ -0,0 +1,33 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<groupId>org.geysermc</groupId>
|
||||
<artifactId>api-parent</artifactId>
|
||||
<version>2.0.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>geyser-api</artifactId>
|
||||
|
||||
<properties>
|
||||
<maven.compiler.source>16</maven.compiler.source>
|
||||
<maven.compiler.target>16</maven.compiler.target>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.checkerframework</groupId>
|
||||
<artifactId>checker-qual</artifactId>
|
||||
<version>3.19.0</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.geysermc</groupId>
|
||||
<artifactId>base-api</artifactId>
|
||||
<version>2.0.0-SNAPSHOT</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
|
@ -0,0 +1,81 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
* @author GeyserMC
|
||||
* @link https://github.com/GeyserMC/Geyser
|
||||
*/
|
||||
|
||||
package org.geysermc.geyser.api;
|
||||
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
import org.geysermc.api.GeyserApiBase;
|
||||
import org.geysermc.geyser.api.connection.GeyserConnection;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* Represents the API used in Geyser.
|
||||
*/
|
||||
public interface GeyserApi extends GeyserApiBase {
|
||||
/**
|
||||
* Shuts down the current Geyser instance.
|
||||
*/
|
||||
void shutdown();
|
||||
|
||||
/**
|
||||
* Reloads the current Geyser instance.
|
||||
*/
|
||||
void reload();
|
||||
|
||||
/**
|
||||
* Gets if this Geyser instance is running in an IDE. This only needs to be used in cases where files
|
||||
* expected to be in a jarfile are not present.
|
||||
*
|
||||
* @return true if the version number is not 'DEV'.
|
||||
*/
|
||||
boolean productionEnvironment();
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
@Nullable GeyserConnection connectionByUuid(@NonNull UUID uuid);
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
@Nullable GeyserConnection connectionByXuid(@NonNull String xuid);
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
@Nullable GeyserConnection connectionByName(@NonNull String name);
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@NonNull
|
||||
List<? extends GeyserConnection> onlineConnections();
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2020 GeyserMC. http://geysermc.org
|
||||
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
|
@ -23,15 +23,12 @@
|
|||
* @link https://github.com/GeyserMC/Geyser
|
||||
*/
|
||||
|
||||
package org.geysermc.connector.network.remote;
|
||||
package org.geysermc.geyser.api.connection;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import org.geysermc.api.session.Connection;
|
||||
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public class RemoteServer {
|
||||
|
||||
private String address;
|
||||
private int port;
|
||||
}
|
||||
/**
|
||||
* Represents a player session used in Geyser.
|
||||
*/
|
||||
public interface GeyserConnection extends Connection {
|
||||
}
|
24
api/pom.xml
Normal file
24
api/pom.xml
Normal file
|
@ -0,0 +1,24 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>org.geysermc</groupId>
|
||||
<artifactId>geyser-parent</artifactId>
|
||||
<version>2.0.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>api-parent</artifactId>
|
||||
<packaging>pom</packaging>
|
||||
|
||||
<properties>
|
||||
<maven.compiler.source>16</maven.compiler.source>
|
||||
<maven.compiler.target>16</maven.compiler.target>
|
||||
</properties>
|
||||
|
||||
<modules>
|
||||
<module>base</module>
|
||||
<module>geyser</module>
|
||||
</modules>
|
||||
</project>
|
|
@ -6,21 +6,22 @@
|
|||
<parent>
|
||||
<groupId>org.geysermc</groupId>
|
||||
<artifactId>bootstrap-parent</artifactId>
|
||||
<version>1.2.0-SNAPSHOT</version>
|
||||
<version>2.0.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>bootstrap-bungeecord</artifactId>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.geysermc</groupId>
|
||||
<artifactId>connector</artifactId>
|
||||
<version>1.2.0-SNAPSHOT</version>
|
||||
<artifactId>core</artifactId>
|
||||
<version>2.0.0-SNAPSHOT</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<!-- Used for better working with internals without reflection -->
|
||||
<dependency>
|
||||
<groupId>net.md-5</groupId>
|
||||
<artifactId>bungeecord-api</artifactId>
|
||||
<version>1.15-SNAPSHOT</version>
|
||||
<groupId>com.github.SpigotMC.BungeeCord</groupId>
|
||||
<artifactId>bungeecord-proxy</artifactId>
|
||||
<version>a7c6ede</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
@ -40,7 +41,7 @@
|
|||
<configuration>
|
||||
<archive>
|
||||
<manifestEntries>
|
||||
<Main-Class>org.geysermc.platform.bungeecord.GeyserBungeeMain</Main-Class>
|
||||
<Main-Class>org.geysermc.geyser.platform.bungeecord.GeyserBungeeMain</Main-Class>
|
||||
</manifestEntries>
|
||||
</archive>
|
||||
</configuration>
|
||||
|
@ -48,7 +49,7 @@
|
|||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-shade-plugin</artifactId>
|
||||
<version>3.2.1</version>
|
||||
<version>3.3.0-SNAPSHOT</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>package</phase>
|
||||
|
@ -59,35 +60,21 @@
|
|||
<relocations>
|
||||
<relocation>
|
||||
<pattern>net.md_5.bungee.jni</pattern>
|
||||
<shadedPattern>org.geysermc.platform.bungeecord.shaded.jni</shadedPattern>
|
||||
<shadedPattern>org.geysermc.geyser.platform.bungeecord.shaded.jni</shadedPattern>
|
||||
</relocation>
|
||||
<relocation>
|
||||
<pattern>com.fasterxml.jackson</pattern>
|
||||
<shadedPattern>org.geysermc.platform.bungeecord.shaded.jackson</shadedPattern>
|
||||
<shadedPattern>org.geysermc.geyser.platform.bungeecord.shaded.jackson</shadedPattern>
|
||||
</relocation>
|
||||
<relocation>
|
||||
<pattern>io.netty</pattern>
|
||||
<shadedPattern>org.geysermc.platform.bungeecord.shaded.netty</shadedPattern>
|
||||
<!-- This is not used because relocating breaks natives, but we must include it
|
||||
or else we get ClassDefNotFound -->
|
||||
<pattern>io.netty.channel.kqueue</pattern>
|
||||
<shadedPattern>org.geysermc.geyser.platform.bungeecord.shaded.io.netty.channel.kqueue</shadedPattern>
|
||||
</relocation>
|
||||
<relocation>
|
||||
<pattern>org.reflections</pattern>
|
||||
<shadedPattern>org.geysermc.platform.bungeecord.shaded.reflections</shadedPattern>
|
||||
</relocation>
|
||||
<relocation>
|
||||
<pattern>com.google.common</pattern>
|
||||
<shadedPattern>org.geysermc.platform.bungeecord.shaded.google.common</shadedPattern>
|
||||
</relocation>
|
||||
<relocation>
|
||||
<pattern>com.google.guava</pattern>
|
||||
<shadedPattern>org.geysermc.platform.bungeecord.shaded.google.guava</shadedPattern>
|
||||
</relocation>
|
||||
<relocation>
|
||||
<pattern>org.dom4j</pattern>
|
||||
<shadedPattern>org.geysermc.platform.bungeecord.shaded.dom4j</shadedPattern>
|
||||
</relocation>
|
||||
<relocation>
|
||||
<pattern>net.kyori.adventure</pattern>
|
||||
<shadedPattern>org.geysermc.platform.bungeecord.shaded.adventure</shadedPattern>
|
||||
<pattern>net.kyori</pattern>
|
||||
<shadedPattern>org.geysermc.geyser.platform.bungeecord.shaded.kyori</shadedPattern>
|
||||
</relocation>
|
||||
</relocations>
|
||||
</configuration>
|
||||
|
@ -96,8 +83,17 @@
|
|||
<configuration>
|
||||
<artifactSet>
|
||||
<excludes>
|
||||
<exclude>com.google.code.gson:*</exclude>
|
||||
<exclude>com.google.*:*</exclude>
|
||||
<exclude>org.yaml:*</exclude>
|
||||
<exclude>io.netty:netty-transport-native-epoll:*</exclude>
|
||||
<exclude>io.netty:netty-transport-native-unix-common:*</exclude>
|
||||
<exclude>io.netty:netty-handler:*</exclude>
|
||||
<exclude>io.netty:netty-common:*</exclude>
|
||||
<exclude>io.netty:netty-buffer:*</exclude>
|
||||
<exclude>io.netty:netty-resolver:*</exclude>
|
||||
<exclude>io.netty:netty-transport:*</exclude>
|
||||
<exclude>io.netty:netty-codec:*</exclude>
|
||||
<exclude>io.netty:netty-resolver-dns:*</exclude>
|
||||
</excludes>
|
||||
</artifactSet>
|
||||
</configuration>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2020 GeyserMC. http://geysermc.org
|
||||
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
|
@ -23,14 +23,14 @@
|
|||
* @link https://github.com/GeyserMC/Geyser
|
||||
*/
|
||||
|
||||
package org.geysermc.platform.bungeecord;
|
||||
package org.geysermc.geyser.platform.bungeecord;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import lombok.Getter;
|
||||
import net.md_5.bungee.api.plugin.Plugin;
|
||||
import org.geysermc.connector.FloodgateKeyLoader;
|
||||
import org.geysermc.connector.configuration.GeyserJacksonConfiguration;
|
||||
import org.geysermc.geyser.FloodgateKeyLoader;
|
||||
import org.geysermc.geyser.configuration.GeyserJacksonConfiguration;
|
||||
|
||||
import java.nio.file.Path;
|
||||
|
||||
|
@ -41,10 +41,10 @@ public final class GeyserBungeeConfiguration extends GeyserJacksonConfiguration
|
|||
private Path floodgateKeyPath;
|
||||
|
||||
public void loadFloodgate(GeyserBungeePlugin plugin) {
|
||||
Plugin floodgate = plugin.getProxy().getPluginManager().getPlugin("floodgate-bungee");
|
||||
Plugin floodgate = plugin.getProxy().getPluginManager().getPlugin("floodgate");
|
||||
Path geyserDataFolder = plugin.getDataFolder().toPath();
|
||||
Path floodgateDataFolder = floodgate != null ? floodgate.getDataFolder().toPath() : null;
|
||||
|
||||
floodgateKeyPath = FloodgateKeyLoader.getKeyPath(this, floodgate, floodgateDataFolder, geyserDataFolder, plugin.getGeyserLogger());
|
||||
floodgateKeyPath = FloodgateKeyLoader.getKeyPath(this, floodgateDataFolder, geyserDataFolder, plugin.getGeyserLogger());
|
||||
}
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2020 GeyserMC. http://geysermc.org
|
||||
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
|
@ -23,26 +23,25 @@
|
|||
* @link https://github.com/GeyserMC/Geyser
|
||||
*/
|
||||
|
||||
package org.geysermc.platform.bungeecord;
|
||||
package org.geysermc.geyser.platform.bungeecord;
|
||||
|
||||
import lombok.Getter;
|
||||
import net.md_5.bungee.api.ProxyServer;
|
||||
import net.md_5.bungee.api.plugin.Plugin;
|
||||
import org.geysermc.connector.common.serializer.AsteriskSerializer;
|
||||
import org.geysermc.connector.dump.BootstrapDumpInfo;
|
||||
import org.geysermc.geyser.text.AsteriskSerializer;
|
||||
import org.geysermc.geyser.dump.BootstrapDumpInfo;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
@Getter
|
||||
public class GeyserBungeeDumpInfo extends BootstrapDumpInfo {
|
||||
|
||||
private String platformName;
|
||||
private String platformVersion;
|
||||
private boolean onlineMode;
|
||||
private List<ListenerInfo> listeners;
|
||||
private List<PluginInfo> plugins;
|
||||
private final String platformName;
|
||||
private final String platformVersion;
|
||||
private final boolean onlineMode;
|
||||
private final List<ListenerInfo> listeners;
|
||||
private final List<PluginInfo> plugins;
|
||||
|
||||
GeyserBungeeDumpInfo(ProxyServer proxy) {
|
||||
super();
|
||||
|
@ -63,7 +62,7 @@ public class GeyserBungeeDumpInfo extends BootstrapDumpInfo {
|
|||
}
|
||||
|
||||
for (Plugin plugin : proxy.getPluginManager().getPlugins()) {
|
||||
this.plugins.add(new PluginInfo(true, plugin.getDescription().getName(), plugin.getDescription().getVersion(), plugin.getDescription().getMain(), Arrays.asList(plugin.getDescription().getAuthor())));
|
||||
this.plugins.add(new PluginInfo(true, plugin.getDescription().getName(), plugin.getDescription().getVersion(), plugin.getDescription().getMain(), Collections.singletonList(plugin.getDescription().getAuthor())));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,191 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
* @author GeyserMC
|
||||
* @link https://github.com/GeyserMC/Geyser
|
||||
*/
|
||||
|
||||
package org.geysermc.geyser.platform.bungeecord;
|
||||
|
||||
import io.netty.bootstrap.ServerBootstrap;
|
||||
import io.netty.channel.Channel;
|
||||
import io.netty.channel.ChannelFuture;
|
||||
import io.netty.channel.ChannelInitializer;
|
||||
import io.netty.channel.EventLoopGroup;
|
||||
import io.netty.channel.local.LocalAddress;
|
||||
import io.netty.util.AttributeKey;
|
||||
import net.md_5.bungee.api.ProxyServer;
|
||||
import net.md_5.bungee.api.config.ListenerInfo;
|
||||
import net.md_5.bungee.api.event.ProxyReloadEvent;
|
||||
import net.md_5.bungee.api.plugin.Listener;
|
||||
import net.md_5.bungee.api.plugin.Plugin;
|
||||
import net.md_5.bungee.event.EventHandler;
|
||||
import net.md_5.bungee.netty.PipelineUtils;
|
||||
import org.geysermc.geyser.GeyserImpl;
|
||||
import org.geysermc.geyser.GeyserBootstrap;
|
||||
import org.geysermc.geyser.network.netty.GeyserInjector;
|
||||
import org.geysermc.geyser.network.netty.LocalServerChannelWrapper;
|
||||
import org.geysermc.geyser.network.netty.LocalSession;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Set;
|
||||
|
||||
public class GeyserBungeeInjector extends GeyserInjector implements Listener {
|
||||
private final Plugin plugin;
|
||||
private final ProxyServer proxy;
|
||||
/**
|
||||
* Set as a variable so it is only set after the proxy has finished initializing
|
||||
*/
|
||||
private ChannelInitializer<Channel> channelInitializer = null;
|
||||
private Set<Channel> bungeeChannels = null;
|
||||
private boolean eventRegistered = false;
|
||||
|
||||
public GeyserBungeeInjector(Plugin plugin) {
|
||||
this.plugin = plugin;
|
||||
this.proxy = plugin.getProxy();
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
protected void initializeLocalChannel0(GeyserBootstrap bootstrap) throws Exception {
|
||||
// TODO - allow Geyser to specify its own listener info properties
|
||||
if (proxy.getConfig().getListeners().size() != 1) {
|
||||
throw new UnsupportedOperationException("Geyser does not currently support multiple listeners with injection! " +
|
||||
"Please reach out to us on our Discord at https://discord.gg/GeyserMC so we can hear feedback on your setup.");
|
||||
}
|
||||
ListenerInfo listenerInfo = proxy.getConfig().getListeners().stream().findFirst().orElseThrow(IllegalStateException::new);
|
||||
|
||||
Class<? extends ProxyServer> proxyClass = proxy.getClass();
|
||||
// Using the specified EventLoop is required, or else an error will be thrown
|
||||
EventLoopGroup bossGroup;
|
||||
EventLoopGroup workerGroup;
|
||||
try {
|
||||
EventLoopGroup eventLoops = (EventLoopGroup) proxyClass.getField("eventLoops").get(proxy);
|
||||
// Netty redirects ServerBootstrap#group(EventLoopGroup) to #group(EventLoopGroup, EventLoopGroup) and uses the same event loop for both.
|
||||
bossGroup = eventLoops;
|
||||
workerGroup = eventLoops;
|
||||
bootstrap.getGeyserLogger().debug("BungeeCord event loop style detected.");
|
||||
} catch (NoSuchFieldException e) {
|
||||
// Waterfall uses two separate event loops
|
||||
// https://github.com/PaperMC/Waterfall/blob/fea7ec356dba6c6ac28819ff11be604af6eb484e/BungeeCord-Patches/0022-Use-a-worker-and-a-boss-event-loop-group.patch
|
||||
bossGroup = (EventLoopGroup) proxyClass.getField("bossEventLoopGroup").get(proxy);
|
||||
workerGroup = (EventLoopGroup) proxyClass.getField("workerEventLoopGroup").get(proxy);
|
||||
bootstrap.getGeyserLogger().debug("Waterfall event loop style detected.");
|
||||
}
|
||||
|
||||
// Is currently just AttributeKey.valueOf("ListerInfo") but we might as well copy the value itself.
|
||||
AttributeKey<ListenerInfo> listener = PipelineUtils.LISTENER;
|
||||
listenerInfo = new ListenerInfo(
|
||||
listenerInfo.getSocketAddress(),
|
||||
listenerInfo.getMotd(),
|
||||
listenerInfo.getMaxPlayers(),
|
||||
listenerInfo.getTabListSize(),
|
||||
listenerInfo.getServerPriority(),
|
||||
listenerInfo.isForceDefault(),
|
||||
listenerInfo.getForcedHosts(),
|
||||
listenerInfo.getTabListType(),
|
||||
listenerInfo.isSetLocalAddress(),
|
||||
listenerInfo.isPingPassthrough(),
|
||||
listenerInfo.getQueryPort(),
|
||||
listenerInfo.isQueryEnabled(),
|
||||
bootstrap.getGeyserConfig().getRemote().isUseProxyProtocol() // If Geyser is expecting HAProxy, so should the Bungee end
|
||||
);
|
||||
|
||||
// The field that stores all listeners in BungeeCord
|
||||
// As of https://github.com/ViaVersion/ViaVersion/pull/2698 ViaVersion adds a wrapper to this field to
|
||||
// add its connections
|
||||
Field listenerField = proxyClass.getDeclaredField("listeners");
|
||||
listenerField.setAccessible(true);
|
||||
bungeeChannels = (Set<Channel>) listenerField.get(proxy);
|
||||
|
||||
// This method is what initializes the connection in Java Edition, after Netty is all set.
|
||||
Method initChannel = ChannelInitializer.class.getDeclaredMethod("initChannel", Channel.class);
|
||||
initChannel.setAccessible(true);
|
||||
|
||||
ChannelFuture channelFuture = (new ServerBootstrap()
|
||||
.channel(LocalServerChannelWrapper.class)
|
||||
.childHandler(new ChannelInitializer<>() {
|
||||
@Override
|
||||
protected void initChannel(Channel ch) throws Exception {
|
||||
if (proxy.getConfig().getServers() == null) {
|
||||
// Proxy hasn't finished loading all plugins - it loads the config after all plugins
|
||||
// Probably doesn't need to be translatable?
|
||||
bootstrap.getGeyserLogger().info("Disconnecting player as Bungee has not finished loading");
|
||||
ch.close();
|
||||
return;
|
||||
}
|
||||
|
||||
if (channelInitializer == null) {
|
||||
// Proxy has finished initializing; we can safely grab this variable without fear of plugins modifying it
|
||||
// (Older versions of ViaVersion replace this to inject)
|
||||
channelInitializer = PipelineUtils.SERVER_CHILD;
|
||||
}
|
||||
initChannel.invoke(channelInitializer, ch);
|
||||
}
|
||||
})
|
||||
.childAttr(listener, listenerInfo)
|
||||
.group(bossGroup, workerGroup)
|
||||
.localAddress(LocalAddress.ANY))
|
||||
.bind()
|
||||
.syncUninterruptibly();
|
||||
|
||||
this.localChannel = channelFuture;
|
||||
this.bungeeChannels.add(this.localChannel.channel());
|
||||
this.serverSocketAddress = channelFuture.channel().localAddress();
|
||||
|
||||
if (!this.eventRegistered) {
|
||||
// Register reload listener
|
||||
this.proxy.getPluginManager().registerListener(this.plugin, this);
|
||||
this.eventRegistered = true;
|
||||
}
|
||||
|
||||
// Only affects Waterfall, but there is no sure way to differentiate between a proxy with this patch and a proxy without this patch
|
||||
// Patch causing the issue: https://github.com/PaperMC/Waterfall/blob/7e6af4cef64d5d377a6ffd00a534379e6efa94cf/BungeeCord-Patches/0045-Don-t-use-a-bytebuf-for-packet-decoding.patch
|
||||
// If native compression is enabled, then this line is tripped up if a heap buffer is sent over in such a situation
|
||||
// as a new direct buffer is not created with that patch (HeapByteBufs throw an UnsupportedOperationException here):
|
||||
// https://github.com/SpigotMC/BungeeCord/blob/a283aaf724d4c9a815540cd32f3aafaa72df9e05/native/src/main/java/net/md_5/bungee/jni/zlib/NativeZlib.java#L43
|
||||
// This issue could be mitigated down the line by preventing Bungee from setting compression
|
||||
LocalSession.createDirectByteBufAllocator();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void shutdown() {
|
||||
if (this.localChannel != null && this.bungeeChannels != null) {
|
||||
this.bungeeChannels.remove(this.localChannel.channel());
|
||||
this.bungeeChannels = null;
|
||||
}
|
||||
super.shutdown();
|
||||
}
|
||||
|
||||
/**
|
||||
* The reload process clears the listeners field. Since we need to add to the listeners for maximum compatibility,
|
||||
* we also need to re-add and re-enable our listener if a reload is initiated.
|
||||
*/
|
||||
@EventHandler
|
||||
public void onProxyReload(ProxyReloadEvent event) {
|
||||
this.bungeeChannels = null;
|
||||
if (this.localChannel != null) {
|
||||
shutdown();
|
||||
initializeLocalChannel(GeyserImpl.getInstance().getBootstrap());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2020 GeyserMC. http://geysermc.org
|
||||
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
|
@ -23,11 +23,11 @@
|
|||
* @link https://github.com/GeyserMC/Geyser
|
||||
*/
|
||||
|
||||
package org.geysermc.platform.bungeecord;
|
||||
package org.geysermc.geyser.platform.bungeecord;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import org.geysermc.connector.GeyserLogger;
|
||||
import org.geysermc.geyser.GeyserLogger;
|
||||
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2020 GeyserMC. http://geysermc.org
|
||||
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
|
@ -23,11 +23,11 @@
|
|||
* @link https://github.com/GeyserMC/Geyser
|
||||
*/
|
||||
|
||||
package org.geysermc.platform.bungeecord;
|
||||
package org.geysermc.geyser.platform.bungeecord;
|
||||
|
||||
import org.geysermc.connector.common.main.IGeyserMain;
|
||||
import org.geysermc.geyser.GeyserMain;
|
||||
|
||||
public class GeyserBungeeMain extends IGeyserMain {
|
||||
public class GeyserBungeeMain extends GeyserMain {
|
||||
|
||||
public static void main(String[] args) {
|
||||
new GeyserBungeeMain().displayMessage();
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2020 GeyserMC. http://geysermc.org
|
||||
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
|
@ -23,7 +23,7 @@
|
|||
* @link https://github.com/GeyserMC/Geyser
|
||||
*/
|
||||
|
||||
package org.geysermc.platform.bungeecord;
|
||||
package org.geysermc.geyser.platform.bungeecord;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import net.md_5.bungee.api.ProxyServer;
|
||||
|
@ -34,10 +34,9 @@ import net.md_5.bungee.api.connection.PendingConnection;
|
|||
import net.md_5.bungee.api.event.ProxyPingEvent;
|
||||
import net.md_5.bungee.api.plugin.Listener;
|
||||
import net.md_5.bungee.protocol.ProtocolConstants;
|
||||
import org.geysermc.connector.common.ping.GeyserPingInfo;
|
||||
import org.geysermc.connector.ping.IGeyserPingPassthrough;
|
||||
import org.geysermc.geyser.ping.GeyserPingInfo;
|
||||
import org.geysermc.geyser.ping.IGeyserPingPassthrough;
|
||||
|
||||
import java.net.Inet4Address;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.SocketAddress;
|
||||
import java.util.Arrays;
|
||||
|
@ -47,14 +46,12 @@ import java.util.concurrent.CompletableFuture;
|
|||
@AllArgsConstructor
|
||||
public class GeyserBungeePingPassthrough implements IGeyserPingPassthrough, Listener {
|
||||
|
||||
private static final GeyserPendingConnection PENDING_CONNECTION = new GeyserPendingConnection();
|
||||
|
||||
private final ProxyServer proxyServer;
|
||||
|
||||
@Override
|
||||
public GeyserPingInfo getPingInformation() {
|
||||
public GeyserPingInfo getPingInformation(InetSocketAddress inetSocketAddress) {
|
||||
CompletableFuture<ProxyPingEvent> future = new CompletableFuture<>();
|
||||
proxyServer.getPluginManager().callEvent(new ProxyPingEvent(PENDING_CONNECTION, getPingInfo(), (event, throwable) -> {
|
||||
proxyServer.getPluginManager().callEvent(new ProxyPingEvent(new GeyserPendingConnection(inetSocketAddress), getPingInfo(), (event, throwable) -> {
|
||||
if (throwable != null) future.completeExceptionally(throwable);
|
||||
else future.complete(event);
|
||||
}));
|
||||
|
@ -66,9 +63,8 @@ public class GeyserBungeePingPassthrough implements IGeyserPingPassthrough, List
|
|||
new GeyserPingInfo.Version(response.getVersion().getName(), response.getVersion().getProtocol())
|
||||
);
|
||||
if (event.getResponse().getPlayers().getSample() != null) {
|
||||
Arrays.stream(event.getResponse().getPlayers().getSample()).forEach(proxiedPlayer -> {
|
||||
geyserPingInfo.getPlayerList().add(proxiedPlayer.getName());
|
||||
});
|
||||
Arrays.stream(event.getResponse().getPlayers().getSample()).forEach(proxiedPlayer ->
|
||||
geyserPingInfo.getPlayerList().add(proxiedPlayer.getName()));
|
||||
}
|
||||
return geyserPingInfo;
|
||||
}
|
||||
|
@ -89,7 +85,12 @@ public class GeyserBungeePingPassthrough implements IGeyserPingPassthrough, List
|
|||
private static class GeyserPendingConnection implements PendingConnection {
|
||||
|
||||
private static final UUID FAKE_UUID = UUID.nameUUIDFromBytes("geyser!internal".getBytes());
|
||||
private static final InetSocketAddress FAKE_REMOTE = new InetSocketAddress(Inet4Address.getLoopbackAddress(), 69);
|
||||
|
||||
private final InetSocketAddress remote;
|
||||
|
||||
public GeyserPendingConnection(InetSocketAddress remote) {
|
||||
this.remote = remote;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
|
@ -143,7 +144,7 @@ public class GeyserBungeePingPassthrough implements IGeyserPingPassthrough, List
|
|||
|
||||
@Override
|
||||
public InetSocketAddress getAddress() {
|
||||
return FAKE_REMOTE;
|
||||
return remote;
|
||||
}
|
||||
|
||||
@Override
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2020 GeyserMC. http://geysermc.org
|
||||
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
|
@ -23,27 +23,31 @@
|
|||
* @link https://github.com/GeyserMC/Geyser
|
||||
*/
|
||||
|
||||
package org.geysermc.platform.bungeecord;
|
||||
package org.geysermc.geyser.platform.bungeecord;
|
||||
|
||||
import net.md_5.bungee.api.config.ListenerInfo;
|
||||
import net.md_5.bungee.api.plugin.Plugin;
|
||||
import org.geysermc.common.PlatformType;
|
||||
import org.geysermc.connector.GeyserConnector;
|
||||
import org.geysermc.connector.bootstrap.GeyserBootstrap;
|
||||
import org.geysermc.connector.command.CommandManager;
|
||||
import org.geysermc.connector.configuration.GeyserConfiguration;
|
||||
import org.geysermc.connector.dump.BootstrapDumpInfo;
|
||||
import org.geysermc.connector.ping.GeyserLegacyPingPassthrough;
|
||||
import org.geysermc.connector.ping.IGeyserPingPassthrough;
|
||||
import org.geysermc.connector.utils.FileUtils;
|
||||
import org.geysermc.connector.utils.LanguageUtils;
|
||||
import org.geysermc.platform.bungeecord.command.GeyserBungeeCommandExecutor;
|
||||
import org.geysermc.platform.bungeecord.command.GeyserBungeeCommandManager;
|
||||
import org.geysermc.geyser.GeyserImpl;
|
||||
import org.geysermc.geyser.GeyserBootstrap;
|
||||
import org.geysermc.geyser.command.CommandManager;
|
||||
import org.geysermc.geyser.session.auth.AuthType;
|
||||
import org.geysermc.geyser.configuration.GeyserConfiguration;
|
||||
import org.geysermc.geyser.dump.BootstrapDumpInfo;
|
||||
import org.geysermc.geyser.ping.GeyserLegacyPingPassthrough;
|
||||
import org.geysermc.geyser.ping.IGeyserPingPassthrough;
|
||||
import org.geysermc.geyser.util.FileUtils;
|
||||
import org.geysermc.geyser.text.GeyserLocale;
|
||||
import org.geysermc.geyser.platform.bungeecord.command.GeyserBungeeCommandExecutor;
|
||||
import org.geysermc.geyser.platform.bungeecord.command.GeyserBungeeCommandManager;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.SocketAddress;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.UUID;
|
||||
import java.util.logging.Level;
|
||||
|
||||
|
@ -51,24 +55,29 @@ public class GeyserBungeePlugin extends Plugin implements GeyserBootstrap {
|
|||
|
||||
private GeyserBungeeCommandManager geyserCommandManager;
|
||||
private GeyserBungeeConfiguration geyserConfig;
|
||||
private GeyserBungeeInjector geyserInjector;
|
||||
private GeyserBungeeLogger geyserLogger;
|
||||
private IGeyserPingPassthrough geyserBungeePingPassthrough;
|
||||
|
||||
private GeyserConnector connector;
|
||||
private GeyserImpl geyser;
|
||||
|
||||
@Override
|
||||
public void onEnable() {
|
||||
GeyserLocale.init(this);
|
||||
|
||||
if (!getDataFolder().exists())
|
||||
getDataFolder().mkdir();
|
||||
|
||||
try {
|
||||
if (!getDataFolder().exists())
|
||||
getDataFolder().mkdir();
|
||||
File configFile = FileUtils.fileOrCopiedFromResource(new File(getDataFolder(), "config.yml"), "config.yml", (x) -> x.replaceAll("generateduuid", UUID.randomUUID().toString()));
|
||||
File configFile = FileUtils.fileOrCopiedFromResource(new File(getDataFolder(), "config.yml"),
|
||||
"config.yml", (x) -> x.replaceAll("generateduuid", UUID.randomUUID().toString()), this);
|
||||
this.geyserConfig = FileUtils.loadConfig(configFile, GeyserBungeeConfiguration.class);
|
||||
} catch (IOException ex) {
|
||||
getLogger().log(Level.WARNING, LanguageUtils.getLocaleStringLog("geyser.config.failed"), ex);
|
||||
getLogger().log(Level.SEVERE, GeyserLocale.getLocaleStringLog("geyser.config.failed"), ex);
|
||||
ex.printStackTrace();
|
||||
return;
|
||||
}
|
||||
|
||||
if (getProxy().getConfig().getListeners().size() == 1) {
|
||||
|
@ -94,33 +103,47 @@ public class GeyserBungeePlugin extends Plugin implements GeyserBootstrap {
|
|||
this.geyserLogger = new GeyserBungeeLogger(getLogger(), geyserConfig.isDebugMode());
|
||||
GeyserConfiguration.checkGeyserConfiguration(geyserConfig, geyserLogger);
|
||||
|
||||
if (geyserConfig.getRemote().getAuthType().equals("floodgate") && getProxy().getPluginManager().getPlugin("floodgate-bungee") == null) {
|
||||
geyserLogger.severe(LanguageUtils.getLocaleStringLog("geyser.bootstrap.floodgate.not_installed") + " " + LanguageUtils.getLocaleStringLog("geyser.bootstrap.floodgate.disabling"));
|
||||
// Remove this in like a year
|
||||
if (getProxy().getPluginManager().getPlugin("floodgate-bungee") != null) {
|
||||
geyserLogger.severe(GeyserLocale.getLocaleStringLog("geyser.bootstrap.floodgate.outdated", "https://ci.opencollab.dev/job/GeyserMC/job/Floodgate/job/master/"));
|
||||
return;
|
||||
} else if (geyserConfig.isAutoconfiguredRemote() && getProxy().getPluginManager().getPlugin("floodgate-bungee") != null) {
|
||||
}
|
||||
|
||||
if (geyserConfig.getRemote().getAuthType() == AuthType.FLOODGATE && getProxy().getPluginManager().getPlugin("floodgate") == null) {
|
||||
geyserLogger.severe(GeyserLocale.getLocaleStringLog("geyser.bootstrap.floodgate.not_installed") + " " + GeyserLocale.getLocaleStringLog("geyser.bootstrap.floodgate.disabling"));
|
||||
return;
|
||||
} else if (geyserConfig.isAutoconfiguredRemote() && getProxy().getPluginManager().getPlugin("floodgate") != null) {
|
||||
// Floodgate installed means that the user wants Floodgate authentication
|
||||
geyserLogger.debug("Auto-setting to Floodgate authentication.");
|
||||
geyserConfig.getRemote().setAuthType("floodgate");
|
||||
geyserConfig.getRemote().setAuthType(AuthType.FLOODGATE);
|
||||
}
|
||||
|
||||
geyserConfig.loadFloodgate(this);
|
||||
|
||||
this.connector = GeyserConnector.start(PlatformType.BUNGEECORD, this);
|
||||
this.geyser = GeyserImpl.start(PlatformType.BUNGEECORD, this);
|
||||
|
||||
this.geyserCommandManager = new GeyserBungeeCommandManager(connector);
|
||||
this.geyserInjector = new GeyserBungeeInjector(this);
|
||||
this.geyserInjector.initializeLocalChannel(this);
|
||||
|
||||
this.geyserCommandManager = new GeyserBungeeCommandManager(geyser);
|
||||
|
||||
if (geyserConfig.isLegacyPingPassthrough()) {
|
||||
this.geyserBungeePingPassthrough = GeyserLegacyPingPassthrough.init(connector);
|
||||
this.geyserBungeePingPassthrough = GeyserLegacyPingPassthrough.init(geyser);
|
||||
} else {
|
||||
this.geyserBungeePingPassthrough = new GeyserBungeePingPassthrough(getProxy());
|
||||
}
|
||||
|
||||
this.getProxy().getPluginManager().registerCommand(this, new GeyserBungeeCommandExecutor(connector));
|
||||
this.getProxy().getPluginManager().registerCommand(this, new GeyserBungeeCommandExecutor(geyser));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDisable() {
|
||||
connector.shutdown();
|
||||
if (geyser != null) {
|
||||
geyser.shutdown();
|
||||
}
|
||||
if (geyserInjector != null) {
|
||||
geyserInjector.shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -152,4 +175,15 @@ public class GeyserBungeePlugin extends Plugin implements GeyserBootstrap {
|
|||
public BootstrapDumpInfo getDumpInfo() {
|
||||
return new GeyserBungeeDumpInfo(getProxy());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Path getLogsPath() {
|
||||
return Paths.get(getProxy().getName().equals("BungeeCord") ? "proxy.log.0" : "logs/latest.log");
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public SocketAddress getSocketAddress() {
|
||||
return this.geyserInjector.getServerSocketAddress();
|
||||
}
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2020 GeyserMC. http://geysermc.org
|
||||
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
|
@ -23,12 +23,12 @@
|
|||
* @link https://github.com/GeyserMC/Geyser
|
||||
*/
|
||||
|
||||
package org.geysermc.platform.bungeecord.command;
|
||||
package org.geysermc.geyser.platform.bungeecord.command;
|
||||
|
||||
import net.md_5.bungee.api.chat.TextComponent;
|
||||
import net.md_5.bungee.api.connection.ProxiedPlayer;
|
||||
import org.geysermc.connector.command.CommandSender;
|
||||
import org.geysermc.connector.utils.LanguageUtils;
|
||||
import org.geysermc.geyser.command.CommandSender;
|
||||
import org.geysermc.geyser.text.GeyserLocale;
|
||||
|
||||
public class BungeeCommandSender implements CommandSender {
|
||||
|
||||
|
@ -37,11 +37,11 @@ public class BungeeCommandSender implements CommandSender {
|
|||
public BungeeCommandSender(net.md_5.bungee.api.CommandSender handle) {
|
||||
this.handle = handle;
|
||||
// Ensure even Java players' languages are loaded
|
||||
LanguageUtils.loadGeyserLocale(getLocale());
|
||||
GeyserLocale.loadGeyserLocale(getLocale());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
public String name() {
|
||||
return handle.getName();
|
||||
}
|
||||
|
||||
|
@ -57,11 +57,15 @@ public class BungeeCommandSender implements CommandSender {
|
|||
|
||||
@Override
|
||||
public String getLocale() {
|
||||
if (handle instanceof ProxiedPlayer) {
|
||||
ProxiedPlayer player = (ProxiedPlayer) handle;
|
||||
if (handle instanceof ProxiedPlayer player) {
|
||||
String locale = player.getLocale().getLanguage() + "_" + player.getLocale().getCountry();
|
||||
return LanguageUtils.formatLocale(locale);
|
||||
return GeyserLocale.formatLocale(locale);
|
||||
}
|
||||
return LanguageUtils.getDefaultLocale();
|
||||
return GeyserLocale.getDefaultLocale();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasPermission(String permission) {
|
||||
return handle.hasPermission(permission);
|
||||
}
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2020 GeyserMC. http://geysermc.org
|
||||
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
|
@ -23,56 +23,63 @@
|
|||
* @link https://github.com/GeyserMC/Geyser
|
||||
*/
|
||||
|
||||
package org.geysermc.platform.bungeecord.command;
|
||||
package org.geysermc.geyser.platform.bungeecord.command;
|
||||
|
||||
import net.md_5.bungee.api.ChatColor;
|
||||
import net.md_5.bungee.api.CommandSender;
|
||||
import net.md_5.bungee.api.plugin.Command;
|
||||
import net.md_5.bungee.api.plugin.TabExecutor;
|
||||
import org.geysermc.connector.GeyserConnector;
|
||||
import org.geysermc.connector.command.GeyserCommand;
|
||||
import org.geysermc.connector.utils.LanguageUtils;
|
||||
import org.geysermc.geyser.GeyserImpl;
|
||||
import org.geysermc.geyser.command.CommandExecutor;
|
||||
import org.geysermc.geyser.command.GeyserCommand;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.geyser.text.GeyserLocale;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
|
||||
public class GeyserBungeeCommandExecutor extends Command implements TabExecutor {
|
||||
private final CommandExecutor commandExecutor;
|
||||
|
||||
private final GeyserConnector connector;
|
||||
|
||||
public GeyserBungeeCommandExecutor(GeyserConnector connector) {
|
||||
public GeyserBungeeCommandExecutor(GeyserImpl geyser) {
|
||||
super("geyser");
|
||||
|
||||
this.connector = connector;
|
||||
this.commandExecutor = new CommandExecutor(geyser);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(CommandSender sender, String[] args) {
|
||||
BungeeCommandSender commandSender = new BungeeCommandSender(sender);
|
||||
GeyserSession session = this.commandExecutor.getGeyserSession(commandSender);
|
||||
|
||||
if (args.length > 0) {
|
||||
if (getCommand(args[0]) != null) {
|
||||
if (!sender.hasPermission(getCommand(args[0]).getPermission())) {
|
||||
BungeeCommandSender commandSender = new BungeeCommandSender(sender);
|
||||
String message = LanguageUtils.getPlayerLocaleString("geyser.bootstrap.command.permission_fail", commandSender.getLocale());
|
||||
GeyserCommand command = this.commandExecutor.getCommand(args[0]);
|
||||
if (command != null) {
|
||||
if (!sender.hasPermission(command.getPermission())) {
|
||||
String message = GeyserLocale.getPlayerLocaleString("geyser.bootstrap.command.permission_fail", commandSender.getLocale());
|
||||
|
||||
commandSender.sendMessage(ChatColor.RED + message);
|
||||
return;
|
||||
}
|
||||
getCommand(args[0]).execute(new BungeeCommandSender(sender), args.length > 1 ? Arrays.copyOfRange(args, 1, args.length) : new String[0]);
|
||||
if (command.isBedrockOnly() && session == null) {
|
||||
String message = GeyserLocale.getPlayerLocaleString("geyser.bootstrap.command.bedrock_only", commandSender.getLocale());
|
||||
|
||||
commandSender.sendMessage(ChatColor.RED + message);
|
||||
return;
|
||||
}
|
||||
command.execute(session, commandSender, args.length > 1 ? Arrays.copyOfRange(args, 1, args.length) : new String[0]);
|
||||
}
|
||||
} else {
|
||||
getCommand("help").execute(new BungeeCommandSender(sender), new String[0]);
|
||||
this.commandExecutor.getCommand("help").execute(session, commandSender, new String[0]);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterable<String> onTabComplete(CommandSender sender, String[] args) {
|
||||
if (args.length == 1) {
|
||||
return connector.getCommandManager().getCommandNames();
|
||||
return commandExecutor.tabComplete(new BungeeCommandSender(sender));
|
||||
} else {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
private GeyserCommand getCommand(String label) {
|
||||
return connector.getCommandManager().getCommands().get(label);
|
||||
}
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2020 GeyserMC. http://geysermc.org
|
||||
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
|
@ -23,15 +23,15 @@
|
|||
* @link https://github.com/GeyserMC/Geyser
|
||||
*/
|
||||
|
||||
package org.geysermc.platform.bungeecord.command;
|
||||
package org.geysermc.geyser.platform.bungeecord.command;
|
||||
|
||||
import org.geysermc.connector.GeyserConnector;
|
||||
import org.geysermc.connector.command.CommandManager;
|
||||
import org.geysermc.geyser.GeyserImpl;
|
||||
import org.geysermc.geyser.command.CommandManager;
|
||||
|
||||
public class GeyserBungeeCommandManager extends CommandManager {
|
||||
|
||||
public GeyserBungeeCommandManager(GeyserConnector connector) {
|
||||
super(connector);
|
||||
public GeyserBungeeCommandManager(GeyserImpl geyser) {
|
||||
super(geyser);
|
||||
}
|
||||
|
||||
@Override
|
|
@ -1,4 +1,4 @@
|
|||
main: org.geysermc.platform.bungeecord.GeyserBungeePlugin
|
||||
main: org.geysermc.geyser.platform.bungeecord.GeyserBungeePlugin
|
||||
name: ${outputName}-BungeeCord
|
||||
author: ${project.organization.name}
|
||||
website: ${project.organization.url}
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
<parent>
|
||||
<groupId>org.geysermc</groupId>
|
||||
<artifactId>geyser-parent</artifactId>
|
||||
<version>1.2.0-SNAPSHOT</version>
|
||||
<version>2.0.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>bootstrap-parent</artifactId>
|
||||
<packaging>pom</packaging>
|
||||
|
@ -16,13 +16,9 @@
|
|||
<id>spigot-public</id>
|
||||
<url>https://hub.spigotmc.org/nexus/content/repositories/public/</url>
|
||||
</repository>
|
||||
<repository>
|
||||
<id>bukkit-public</id>
|
||||
<url>https://repo.md-5.net/content/repositories/public/</url>
|
||||
</repository>
|
||||
<repository>
|
||||
<id>sponge-repo</id>
|
||||
<url>https://repo.spongepowered.org/maven</url>
|
||||
<url>https://repo.spongepowered.org/repository/maven-public/</url>
|
||||
</repository>
|
||||
<repository>
|
||||
<id>bungeecord-repo</id>
|
||||
|
@ -33,6 +29,16 @@
|
|||
<url>https://repo.velocitypowered.com/snapshots/</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.geysermc</groupId>
|
||||
<artifactId>ap</artifactId>
|
||||
<version>2.0.0-SNAPSHOT</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<modules>
|
||||
<module>bungeecord</module>
|
||||
<module>spigot</module>
|
||||
|
|
|
@ -6,15 +6,22 @@
|
|||
<parent>
|
||||
<groupId>org.geysermc</groupId>
|
||||
<artifactId>bootstrap-parent</artifactId>
|
||||
<version>1.2.0-SNAPSHOT</version>
|
||||
<version>2.0.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>bootstrap-spigot</artifactId>
|
||||
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>viaversion-repo</id>
|
||||
<url>https://repo.viaversion.com</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.geysermc</groupId>
|
||||
<artifactId>connector</artifactId>
|
||||
<version>1.2.0-SNAPSHOT</version>
|
||||
<artifactId>core</artifactId>
|
||||
<version>2.0.0-SNAPSHOT</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
|
@ -24,11 +31,16 @@
|
|||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>us.myles</groupId>
|
||||
<groupId>com.viaversion</groupId>
|
||||
<artifactId>viaversion</artifactId>
|
||||
<version>3.2.0</version>
|
||||
<version>4.0.0</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.geysermc.geyser.adapters</groupId>
|
||||
<artifactId>spigot-all</artifactId>
|
||||
<version>1.3-SNAPSHOT</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<build>
|
||||
<finalName>${outputName}-Spigot</finalName>
|
||||
|
@ -46,7 +58,7 @@
|
|||
<configuration>
|
||||
<archive>
|
||||
<manifestEntries>
|
||||
<Main-Class>org.geysermc.platform.spigot.GeyserSpigotMain</Main-Class>
|
||||
<Main-Class>org.geysermc.geyser.platform.spigot.GeyserSpigotMain</Main-Class>
|
||||
</manifestEntries>
|
||||
</archive>
|
||||
</configuration>
|
||||
|
@ -54,7 +66,7 @@
|
|||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-shade-plugin</artifactId>
|
||||
<version>3.2.1</version>
|
||||
<version>3.3.0-SNAPSHOT</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>package</phase>
|
||||
|
@ -63,37 +75,21 @@
|
|||
</goals>
|
||||
<configuration>
|
||||
<relocations>
|
||||
<relocation>
|
||||
<pattern>io.netty</pattern>
|
||||
<shadedPattern>org.geysermc.platform.spigot.shaded.netty</shadedPattern>
|
||||
</relocation>
|
||||
<relocation>
|
||||
<pattern>it.unimi.dsi.fastutil</pattern>
|
||||
<shadedPattern>org.geysermc.platform.spigot.shaded.fastutil</shadedPattern>
|
||||
<shadedPattern>org.geysermc.geyser.platform.spigot.shaded.fastutil</shadedPattern>
|
||||
</relocation>
|
||||
<relocation>
|
||||
<pattern>com.fasterxml.jackson</pattern>
|
||||
<shadedPattern>org.geysermc.platform.spigot.shaded.jackson</shadedPattern>
|
||||
<shadedPattern>org.geysermc.geyser.platform.spigot.shaded.jackson</shadedPattern>
|
||||
</relocation>
|
||||
<relocation>
|
||||
<pattern>org.reflections</pattern>
|
||||
<shadedPattern>org.geysermc.platform.spigot.shaded.reflections</shadedPattern>
|
||||
<pattern>net.kyori</pattern>
|
||||
<shadedPattern>org.geysermc.geyser.platform.spigot.shaded.kyori</shadedPattern>
|
||||
</relocation>
|
||||
<relocation>
|
||||
<pattern>com.google.common</pattern>
|
||||
<shadedPattern>org.geysermc.platform.spigot.shaded.google.common</shadedPattern>
|
||||
</relocation>
|
||||
<relocation>
|
||||
<pattern>com.google.guava</pattern>
|
||||
<shadedPattern>org.geysermc.platform.spigot.shaded.google.guava</shadedPattern>
|
||||
</relocation>
|
||||
<relocation>
|
||||
<pattern>org.dom4j</pattern>
|
||||
<shadedPattern>org.geysermc.platform.spigot.shaded.dom4j</shadedPattern>
|
||||
</relocation>
|
||||
<relocation>
|
||||
<pattern>net.kyori.adventure</pattern>
|
||||
<shadedPattern>org.geysermc.platform.spigot.shaded.adventure</shadedPattern>
|
||||
<pattern>org.objectweb.asm</pattern>
|
||||
<shadedPattern>org.geysermc.geyser.platform.spigot.shaded.asm</shadedPattern>
|
||||
</relocation>
|
||||
</relocations>
|
||||
</configuration>
|
||||
|
@ -102,8 +98,22 @@
|
|||
<configuration>
|
||||
<artifactSet>
|
||||
<excludes>
|
||||
<exclude>com.google.code.gson:*</exclude>
|
||||
<exclude>com.google.*:*</exclude>
|
||||
<exclude>org.yaml:*</exclude>
|
||||
<!-- We cannot shade Netty, or else native libraries will not load -->
|
||||
<!-- Needed because older Spigot builds do not provide the haproxy module -->
|
||||
<exclude>io.netty:netty-transport-native-epoll:*</exclude>
|
||||
<exclude>io.netty:netty-transport-native-unix-common:*</exclude>
|
||||
<exclude>io.netty:netty-transport-native-kqueue:*</exclude>
|
||||
<exclude>io.netty:netty-handler:*</exclude>
|
||||
<exclude>io.netty:netty-common:*</exclude>
|
||||
<exclude>io.netty:netty-buffer:*</exclude>
|
||||
<exclude>io.netty:netty-resolver:*</exclude>
|
||||
<exclude>io.netty:netty-transport:*</exclude>
|
||||
<exclude>io.netty:netty-codec:*</exclude>
|
||||
<exclude>io.netty:netty-codec-dns:*</exclude>
|
||||
<exclude>io.netty:netty-resolver-dns:*</exclude>
|
||||
<exclude>io.netty:netty-resolver-dns-native-macos:*</exclude>
|
||||
</excludes>
|
||||
</artifactSet>
|
||||
</configuration>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2020 GeyserMC. http://geysermc.org
|
||||
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
|
@ -23,15 +23,15 @@
|
|||
* @link https://github.com/GeyserMC/Geyser
|
||||
*/
|
||||
|
||||
package org.geysermc.platform.spigot;
|
||||
package org.geysermc.geyser.platform.spigot;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import lombok.Getter;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
import org.geysermc.connector.FloodgateKeyLoader;
|
||||
import org.geysermc.connector.configuration.GeyserJacksonConfiguration;
|
||||
import org.geysermc.geyser.FloodgateKeyLoader;
|
||||
import org.geysermc.geyser.configuration.GeyserJacksonConfiguration;
|
||||
|
||||
import java.nio.file.Path;
|
||||
|
||||
|
@ -42,15 +42,10 @@ public final class GeyserSpigotConfiguration extends GeyserJacksonConfiguration
|
|||
private Path floodgateKeyPath;
|
||||
|
||||
public void loadFloodgate(GeyserSpigotPlugin plugin) {
|
||||
Plugin floodgate = Bukkit.getPluginManager().getPlugin("floodgate-bukkit");
|
||||
Plugin floodgate = Bukkit.getPluginManager().getPlugin("floodgate");
|
||||
Path geyserDataFolder = plugin.getDataFolder().toPath();
|
||||
Path floodgateDataFolder = floodgate != null ? floodgate.getDataFolder().toPath() : null;
|
||||
|
||||
floodgateKeyPath = FloodgateKeyLoader.getKeyPath(this, floodgate, floodgateDataFolder, geyserDataFolder, plugin.getGeyserLogger());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCacheChunks() {
|
||||
return true; // We override this as with Bukkit, we have direct access to the server implementation
|
||||
floodgateKeyPath = FloodgateKeyLoader.getKeyPath(this, floodgateDataFolder, geyserDataFolder, plugin.getGeyserLogger());
|
||||
}
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2020 GeyserMC. http://geysermc.org
|
||||
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
|
@ -23,13 +23,13 @@
|
|||
* @link https://github.com/GeyserMC/Geyser
|
||||
*/
|
||||
|
||||
package org.geysermc.platform.spigot;
|
||||
package org.geysermc.geyser.platform.spigot;
|
||||
|
||||
import lombok.Getter;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
import org.geysermc.connector.common.serializer.AsteriskSerializer;
|
||||
import org.geysermc.connector.dump.BootstrapDumpInfo;
|
||||
import org.geysermc.geyser.text.AsteriskSerializer;
|
||||
import org.geysermc.geyser.dump.BootstrapDumpInfo;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
@ -37,13 +37,13 @@ import java.util.List;
|
|||
@Getter
|
||||
public class GeyserSpigotDumpInfo extends BootstrapDumpInfo {
|
||||
|
||||
private String platformName;
|
||||
private String platformVersion;
|
||||
private String platformAPIVersion;
|
||||
private boolean onlineMode;
|
||||
private String serverIP;
|
||||
private int serverPort;
|
||||
private List<PluginInfo> plugins;
|
||||
private final String platformName;
|
||||
private final String platformVersion;
|
||||
private final String platformAPIVersion;
|
||||
private final boolean onlineMode;
|
||||
private final String serverIP;
|
||||
private final int serverPort;
|
||||
private final List<PluginInfo> plugins;
|
||||
|
||||
GeyserSpigotDumpInfo() {
|
||||
super();
|
|
@ -0,0 +1,169 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
* @author GeyserMC
|
||||
* @link https://github.com/GeyserMC/Geyser
|
||||
*/
|
||||
|
||||
package org.geysermc.geyser.platform.spigot;
|
||||
|
||||
import com.viaversion.viaversion.bukkit.handlers.BukkitChannelInitializer;
|
||||
import io.netty.bootstrap.ServerBootstrap;
|
||||
import io.netty.channel.*;
|
||||
import io.netty.channel.local.LocalAddress;
|
||||
import io.netty.util.concurrent.DefaultThreadFactory;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.geysermc.geyser.GeyserBootstrap;
|
||||
import org.geysermc.geyser.network.netty.GeyserInjector;
|
||||
import org.geysermc.geyser.network.netty.LocalServerChannelWrapper;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.ParameterizedType;
|
||||
import java.util.List;
|
||||
|
||||
public class GeyserSpigotInjector extends GeyserInjector {
|
||||
/**
|
||||
* Used to determine if ViaVersion is setup to a state where Geyser players will fail at joining if injection is enabled
|
||||
*/
|
||||
private final boolean isViaVersion;
|
||||
/**
|
||||
* Used to uninject ourselves on shutdown.
|
||||
*/
|
||||
private List<ChannelFuture> allServerChannels;
|
||||
|
||||
public GeyserSpigotInjector(boolean isViaVersion) {
|
||||
this.isViaVersion = isViaVersion;
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
protected void initializeLocalChannel0(GeyserBootstrap bootstrap) throws Exception {
|
||||
Class<?> serverClazz;
|
||||
try {
|
||||
serverClazz = Class.forName("net.minecraft.server.MinecraftServer");
|
||||
// We're using 1.17+
|
||||
} catch (ClassNotFoundException e) {
|
||||
// We're using pre-1.17
|
||||
String prefix = Bukkit.getServer().getClass().getPackage().getName().replace("org.bukkit.craftbukkit", "net.minecraft.server");
|
||||
serverClazz = Class.forName(prefix + ".MinecraftServer");
|
||||
}
|
||||
Method getServer = serverClazz.getDeclaredMethod("getServer");
|
||||
Object server = getServer.invoke(null);
|
||||
Object connection = null;
|
||||
// Find the class that manages network IO
|
||||
for (Method m : serverClazz.getDeclaredMethods()) {
|
||||
if (m.getReturnType() != null) {
|
||||
// First is Spigot-mapped name, second is Mojang-mapped name which is implemented as future-proofing
|
||||
if (m.getReturnType().getSimpleName().equals("ServerConnection") || m.getReturnType().getSimpleName().equals("ServerConnectionListener")) {
|
||||
if (m.getParameterTypes().length == 0) {
|
||||
connection = m.invoke(server);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (connection == null) {
|
||||
throw new RuntimeException("Unable to find ServerConnection class!");
|
||||
}
|
||||
|
||||
// Find the channel that Minecraft uses to listen to connections
|
||||
ChannelFuture listeningChannel = null;
|
||||
for (Field field : connection.getClass().getDeclaredFields()) {
|
||||
if (field.getType() != List.class) {
|
||||
continue;
|
||||
}
|
||||
field.setAccessible(true);
|
||||
boolean rightList = ((ParameterizedType) field.getGenericType()).getActualTypeArguments()[0] == ChannelFuture.class;
|
||||
if (!rightList) continue;
|
||||
|
||||
allServerChannels = (List<ChannelFuture>) field.get(connection);
|
||||
for (ChannelFuture o : allServerChannels) {
|
||||
listeningChannel = o;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (listeningChannel == null) {
|
||||
throw new RuntimeException("Unable to find listening channel!");
|
||||
}
|
||||
|
||||
// Making this a function prevents childHandler from being treated as a non-final variable
|
||||
ChannelInitializer<Channel> childHandler = getChildHandler(bootstrap, listeningChannel);
|
||||
// This method is what initializes the connection in Java Edition, after Netty is all set.
|
||||
Method initChannel = childHandler.getClass().getDeclaredMethod("initChannel", Channel.class);
|
||||
initChannel.setAccessible(true);
|
||||
|
||||
ChannelFuture channelFuture = (new ServerBootstrap()
|
||||
.channel(LocalServerChannelWrapper.class)
|
||||
.childHandler(new ChannelInitializer<Channel>() {
|
||||
@Override
|
||||
protected void initChannel(Channel ch) throws Exception {
|
||||
initChannel.invoke(childHandler, ch);
|
||||
}
|
||||
})
|
||||
// Set to MAX_PRIORITY as MultithreadEventLoopGroup#newDefaultThreadFactory which DefaultEventLoopGroup implements does by default
|
||||
.group(new DefaultEventLoopGroup(0, new DefaultThreadFactory("Geyser Spigot connection thread", Thread.MAX_PRIORITY)))
|
||||
.localAddress(LocalAddress.ANY))
|
||||
.bind()
|
||||
.syncUninterruptibly();
|
||||
// We don't need to add to the list, but plugins like ProtocolSupport and ProtocolLib that add to the main pipeline
|
||||
// will work when we add to the list.
|
||||
allServerChannels.add(channelFuture);
|
||||
this.localChannel = channelFuture;
|
||||
this.serverSocketAddress = channelFuture.channel().localAddress();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private ChannelInitializer<Channel> getChildHandler(GeyserBootstrap bootstrap, ChannelFuture listeningChannel) {
|
||||
List<String> names = listeningChannel.channel().pipeline().names();
|
||||
ChannelInitializer<Channel> childHandler = null;
|
||||
for (String name : names) {
|
||||
ChannelHandler handler = listeningChannel.channel().pipeline().get(name);
|
||||
try {
|
||||
Field childHandlerField = handler.getClass().getDeclaredField("childHandler");
|
||||
childHandlerField.setAccessible(true);
|
||||
childHandler = (ChannelInitializer<Channel>) childHandlerField.get(handler);
|
||||
// ViaVersion non-Paper-injector workaround so we aren't double-injecting
|
||||
if (isViaVersion && childHandler instanceof BukkitChannelInitializer) {
|
||||
childHandler = ((BukkitChannelInitializer) childHandler).getOriginal();
|
||||
}
|
||||
break;
|
||||
} catch (Exception e) {
|
||||
if (bootstrap.getGeyserConfig().isDebugMode()) {
|
||||
bootstrap.getGeyserLogger().debug("The handler " + name + " isn't a ChannelInitializer. THIS ERROR IS SAFE TO IGNORE!");
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
if (childHandler == null) {
|
||||
throw new RuntimeException();
|
||||
}
|
||||
return childHandler;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void shutdown() {
|
||||
if (this.allServerChannels != null) {
|
||||
this.allServerChannels.remove(this.localChannel);
|
||||
this.allServerChannels = null;
|
||||
}
|
||||
super.shutdown();
|
||||
}
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2020 GeyserMC. http://geysermc.org
|
||||
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
|
@ -23,12 +23,12 @@
|
|||
* @link https://github.com/GeyserMC/Geyser
|
||||
*/
|
||||
|
||||
package org.geysermc.platform.spigot;
|
||||
package org.geysermc.geyser.platform.spigot;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import org.geysermc.connector.GeyserLogger;
|
||||
import org.geysermc.geyser.GeyserLogger;
|
||||
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2020 GeyserMC. http://geysermc.org
|
||||
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
|
@ -23,11 +23,11 @@
|
|||
* @link https://github.com/GeyserMC/Geyser
|
||||
*/
|
||||
|
||||
package org.geysermc.platform.spigot;
|
||||
package org.geysermc.geyser.platform.spigot;
|
||||
|
||||
import org.geysermc.connector.common.main.IGeyserMain;
|
||||
import org.geysermc.geyser.GeyserMain;
|
||||
|
||||
public class GeyserSpigotMain extends IGeyserMain {
|
||||
public class GeyserSpigotMain extends GeyserMain {
|
||||
|
||||
public static void main(String[] args) {
|
||||
new GeyserSpigotMain().displayMessage();
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2020 GeyserMC. http://geysermc.org
|
||||
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
|
@ -23,18 +23,20 @@
|
|||
* @link https://github.com/GeyserMC/Geyser
|
||||
*/
|
||||
|
||||
package org.geysermc.platform.spigot;
|
||||
package org.geysermc.geyser.platform.spigot;
|
||||
|
||||
import com.github.steveice10.mc.protocol.MinecraftConstants;
|
||||
import lombok.AllArgsConstructor;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.server.ServerListPingEvent;
|
||||
import org.bukkit.util.CachedServerIcon;
|
||||
import org.geysermc.connector.common.ping.GeyserPingInfo;
|
||||
import org.geysermc.connector.ping.IGeyserPingPassthrough;
|
||||
import org.geysermc.geyser.ping.GeyserPingInfo;
|
||||
import org.geysermc.geyser.network.MinecraftProtocol;
|
||||
import org.geysermc.geyser.ping.IGeyserPingPassthrough;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
|
||||
|
@ -44,13 +46,13 @@ public class GeyserSpigotPingPassthrough implements IGeyserPingPassthrough {
|
|||
private final GeyserSpigotLogger logger;
|
||||
|
||||
@Override
|
||||
public GeyserPingInfo getPingInformation() {
|
||||
public GeyserPingInfo getPingInformation(InetSocketAddress inetSocketAddress) {
|
||||
try {
|
||||
ServerListPingEvent event = new GeyserPingEvent(InetAddress.getLocalHost(), Bukkit.getMotd(), Bukkit.getOnlinePlayers().size(), Bukkit.getMaxPlayers());
|
||||
ServerListPingEvent event = new GeyserPingEvent(inetSocketAddress.getAddress(), Bukkit.getMotd(), Bukkit.getOnlinePlayers().size(), Bukkit.getMaxPlayers());
|
||||
Bukkit.getPluginManager().callEvent(event);
|
||||
GeyserPingInfo geyserPingInfo = new GeyserPingInfo(event.getMotd(),
|
||||
new GeyserPingInfo.Players(event.getMaxPlayers(), event.getNumPlayers()),
|
||||
new GeyserPingInfo.Version(Bukkit.getVersion(), MinecraftConstants.PROTOCOL_VERSION) // thanks Spigot for not exposing this, just default to latest
|
||||
new GeyserPingInfo.Version(Bukkit.getVersion(), MinecraftProtocol.getJavaProtocolVersion()) // thanks Spigot for not exposing this, just default to latest
|
||||
);
|
||||
Bukkit.getOnlinePlayers().stream().map(Player::getName).forEach(geyserPingInfo.getPlayerList()::add);
|
||||
return geyserPingInfo;
|
||||
|
@ -71,9 +73,10 @@ public class GeyserSpigotPingPassthrough implements IGeyserPingPassthrough {
|
|||
public void setServerIcon(CachedServerIcon icon) throws IllegalArgumentException, UnsupportedOperationException {
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public Iterator<Player> iterator() throws UnsupportedOperationException {
|
||||
return Collections.EMPTY_LIST.iterator();
|
||||
return Collections.emptyIterator();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,365 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
* @author GeyserMC
|
||||
* @link https://github.com/GeyserMC/Geyser
|
||||
*/
|
||||
|
||||
package org.geysermc.geyser.platform.spigot;
|
||||
|
||||
import com.viaversion.viaversion.api.Via;
|
||||
import com.viaversion.viaversion.api.data.MappingData;
|
||||
import com.viaversion.viaversion.api.protocol.ProtocolPathEntry;
|
||||
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
import org.geysermc.common.PlatformType;
|
||||
import org.geysermc.geyser.GeyserImpl;
|
||||
import org.geysermc.geyser.GeyserBootstrap;
|
||||
import org.geysermc.geyser.command.CommandManager;
|
||||
import org.geysermc.geyser.session.auth.AuthType;
|
||||
import org.geysermc.geyser.configuration.GeyserConfiguration;
|
||||
import org.geysermc.geyser.dump.BootstrapDumpInfo;
|
||||
import org.geysermc.geyser.network.MinecraftProtocol;
|
||||
import org.geysermc.geyser.level.WorldManager;
|
||||
import org.geysermc.geyser.ping.GeyserLegacyPingPassthrough;
|
||||
import org.geysermc.geyser.ping.IGeyserPingPassthrough;
|
||||
import org.geysermc.geyser.Constants;
|
||||
import org.geysermc.geyser.util.FileUtils;
|
||||
import org.geysermc.geyser.text.GeyserLocale;
|
||||
import org.geysermc.geyser.adapters.spigot.SpigotAdapters;
|
||||
import org.geysermc.geyser.platform.spigot.command.GeyserSpigotCommandExecutor;
|
||||
import org.geysermc.geyser.platform.spigot.command.GeyserSpigotCommandManager;
|
||||
import org.geysermc.geyser.platform.spigot.command.SpigotCommandSender;
|
||||
import org.geysermc.geyser.platform.spigot.world.GeyserPistonListener;
|
||||
import org.geysermc.geyser.platform.spigot.world.GeyserSpigot1_11CraftingListener;
|
||||
import org.geysermc.geyser.platform.spigot.world.GeyserSpigotBlockPlaceListener;
|
||||
import org.geysermc.geyser.platform.spigot.world.manager.*;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.SocketAddress;
|
||||
import java.nio.file.Path;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import java.util.logging.Level;
|
||||
|
||||
public class GeyserSpigotPlugin extends JavaPlugin implements GeyserBootstrap {
|
||||
private GeyserSpigotCommandManager geyserCommandManager;
|
||||
private GeyserSpigotConfiguration geyserConfig;
|
||||
private GeyserSpigotInjector geyserInjector;
|
||||
private GeyserSpigotLogger geyserLogger;
|
||||
private IGeyserPingPassthrough geyserSpigotPingPassthrough;
|
||||
private GeyserSpigotWorldManager geyserWorldManager;
|
||||
|
||||
private GeyserImpl geyser;
|
||||
|
||||
/**
|
||||
* The Minecraft server version, formatted as <code>1.#.#</code>
|
||||
*/
|
||||
private String minecraftVersion;
|
||||
|
||||
@Override
|
||||
public void onEnable() {
|
||||
GeyserLocale.init(this);
|
||||
|
||||
// This is manually done instead of using Bukkit methods to save the config because otherwise comments get removed
|
||||
try {
|
||||
if (!getDataFolder().exists()) {
|
||||
getDataFolder().mkdir();
|
||||
}
|
||||
File configFile = FileUtils.fileOrCopiedFromResource(new File(getDataFolder(), "config.yml"), "config.yml",
|
||||
(x) -> x.replaceAll("generateduuid", UUID.randomUUID().toString()), this);
|
||||
this.geyserConfig = FileUtils.loadConfig(configFile, GeyserSpigotConfiguration.class);
|
||||
} catch (IOException ex) {
|
||||
getLogger().log(Level.SEVERE, GeyserLocale.getLocaleStringLog("geyser.config.failed"), ex);
|
||||
ex.printStackTrace();
|
||||
Bukkit.getPluginManager().disablePlugin(this);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
// Required for the Cloudburst Network dependency to initialize.
|
||||
Class.forName("io.netty.channel.kqueue.KQueue");
|
||||
} catch (ClassNotFoundException e) {
|
||||
// While we could support these older versions, the downside is not having KQueue working at all
|
||||
// And since there are alternative ways to get Geyser working for these aging platforms, it's not worth it.
|
||||
getLogger().severe("*********************************************");
|
||||
getLogger().severe("");
|
||||
getLogger().severe(GeyserLocale.getLocaleStringLog("geyser.bootstrap.unsupported_server.header"));
|
||||
getLogger().severe(GeyserLocale.getLocaleStringLog("geyser.bootstrap.unsupported_server.message", "1.12.2"));
|
||||
getLogger().severe("");
|
||||
getLogger().severe("*********************************************");
|
||||
|
||||
Bukkit.getPluginManager().disablePlugin(this);
|
||||
return;
|
||||
}
|
||||
|
||||
// By default this should be localhost but may need to be changed in some circumstances
|
||||
if (this.geyserConfig.getRemote().getAddress().equalsIgnoreCase("auto")) {
|
||||
geyserConfig.setAutoconfiguredRemote(true);
|
||||
// Don't use localhost if not listening on all interfaces
|
||||
if (!Bukkit.getIp().equals("0.0.0.0") && !Bukkit.getIp().equals("")) {
|
||||
geyserConfig.getRemote().setAddress(Bukkit.getIp());
|
||||
}
|
||||
geyserConfig.getRemote().setPort(Bukkit.getPort());
|
||||
}
|
||||
|
||||
if (geyserConfig.getBedrock().isCloneRemotePort()) {
|
||||
geyserConfig.getBedrock().setPort(Bukkit.getPort());
|
||||
}
|
||||
|
||||
this.geyserLogger = new GeyserSpigotLogger(getLogger(), geyserConfig.isDebugMode());
|
||||
GeyserConfiguration.checkGeyserConfiguration(geyserConfig, geyserLogger);
|
||||
|
||||
// Remove this in like a year
|
||||
if (Bukkit.getPluginManager().getPlugin("floodgate-bukkit") != null) {
|
||||
geyserLogger.severe(GeyserLocale.getLocaleStringLog("geyser.bootstrap.floodgate.outdated", Constants.FLOODGATE_DOWNLOAD_LOCATION));
|
||||
this.getPluginLoader().disablePlugin(this);
|
||||
return;
|
||||
}
|
||||
|
||||
if (geyserConfig.getRemote().getAuthType() == AuthType.FLOODGATE && Bukkit.getPluginManager().getPlugin("floodgate") == null) {
|
||||
geyserLogger.severe(GeyserLocale.getLocaleStringLog("geyser.bootstrap.floodgate.not_installed") + " " + GeyserLocale.getLocaleStringLog("geyser.bootstrap.floodgate.disabling"));
|
||||
this.getPluginLoader().disablePlugin(this);
|
||||
return;
|
||||
} else if (geyserConfig.isAutoconfiguredRemote() && Bukkit.getPluginManager().getPlugin("floodgate") != null) {
|
||||
// Floodgate installed means that the user wants Floodgate authentication
|
||||
geyserLogger.debug("Auto-setting to Floodgate authentication.");
|
||||
geyserConfig.getRemote().setAuthType(AuthType.FLOODGATE);
|
||||
}
|
||||
|
||||
geyserConfig.loadFloodgate(this);
|
||||
|
||||
// Turn "(MC: 1.16.4)" into 1.16.4.
|
||||
this.minecraftVersion = Bukkit.getServer().getVersion().split("\\(MC: ")[1].split("\\)")[0];
|
||||
|
||||
this.geyser = GeyserImpl.start(PlatformType.SPIGOT, this);
|
||||
|
||||
if (geyserConfig.isLegacyPingPassthrough()) {
|
||||
this.geyserSpigotPingPassthrough = GeyserLegacyPingPassthrough.init(geyser);
|
||||
} else {
|
||||
this.geyserSpigotPingPassthrough = new GeyserSpigotPingPassthrough(geyserLogger);
|
||||
}
|
||||
|
||||
this.geyserCommandManager = new GeyserSpigotCommandManager(geyser);
|
||||
|
||||
boolean isViaVersion = Bukkit.getPluginManager().getPlugin("ViaVersion") != null;
|
||||
if (isViaVersion) {
|
||||
try {
|
||||
// Ensure that we have the latest 4.0.0 changes and not an older ViaVersion version
|
||||
Class.forName("com.viaversion.viaversion.api.ViaManager");
|
||||
} catch (ClassNotFoundException e) {
|
||||
geyserLogger.warning(GeyserLocale.getLocaleStringLog("geyser.bootstrap.viaversion.too_old",
|
||||
"https://ci.viaversion.com/job/ViaVersion/"));
|
||||
isViaVersion = false;
|
||||
if (this.geyserConfig.isDebugMode()) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
// Used to determine if Block.getBlockData() is present.
|
||||
boolean isLegacy = !isCompatible(Bukkit.getServer().getVersion(), "1.13.0");
|
||||
if (isLegacy)
|
||||
geyserLogger.debug("Legacy version of Minecraft (1.12.2 or older) detected; falling back to ViaVersion for block state retrieval.");
|
||||
|
||||
boolean isPre1_12 = !isCompatible(Bukkit.getServer().getVersion(), "1.12.0");
|
||||
// Set if we need to use a different method for getting a player's locale
|
||||
SpigotCommandSender.setUseLegacyLocaleMethod(isPre1_12);
|
||||
|
||||
// We want to do this late in the server startup process to allow plugins such as ViaVersion and ProtocolLib
|
||||
// To do their job injecting, then connect into *that*
|
||||
this.geyserInjector = new GeyserSpigotInjector(isViaVersion);
|
||||
this.geyserInjector.initializeLocalChannel(this);
|
||||
|
||||
if (Boolean.parseBoolean(System.getProperty("Geyser.UseDirectAdapters", "true"))) {
|
||||
try {
|
||||
String name = Bukkit.getServer().getClass().getPackage().getName();
|
||||
String nmsVersion = name.substring(name.lastIndexOf('.') + 1);
|
||||
SpigotAdapters.registerWorldAdapter(nmsVersion);
|
||||
if (isViaVersion && isViaVersionNeeded()) {
|
||||
if (isLegacy) {
|
||||
// Pre-1.13
|
||||
this.geyserWorldManager = new GeyserSpigot1_12NativeWorldManager(this);
|
||||
} else {
|
||||
// Post-1.13
|
||||
this.geyserWorldManager = new GeyserSpigotLegacyNativeWorldManager(this);
|
||||
}
|
||||
} else {
|
||||
// No ViaVersion
|
||||
this.geyserWorldManager = new GeyserSpigotNativeWorldManager(this);
|
||||
}
|
||||
geyserLogger.debug("Using NMS adapter: " + this.geyserWorldManager.getClass() + ", " + nmsVersion);
|
||||
} catch (Exception e) {
|
||||
if (geyserConfig.isDebugMode()) {
|
||||
geyserLogger.debug("Error while attempting to find NMS adapter. Most likely, this can be safely ignored. :)");
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
geyserLogger.debug("Not using NMS adapter as it is disabled via system property.");
|
||||
}
|
||||
if (this.geyserWorldManager == null) {
|
||||
// No NMS adapter
|
||||
if (isLegacy && isViaVersion) {
|
||||
// Use ViaVersion for converting pre-1.13 block states
|
||||
this.geyserWorldManager = new GeyserSpigot1_12WorldManager(this);
|
||||
} else if (isLegacy) {
|
||||
// Not sure how this happens - without ViaVersion, we don't know any block states, so just assume everything is air
|
||||
this.geyserWorldManager = new GeyserSpigotFallbackWorldManager(this);
|
||||
} else {
|
||||
// Post-1.13
|
||||
this.geyserWorldManager = new GeyserSpigotWorldManager(this);
|
||||
}
|
||||
geyserLogger.debug("Using default world manager: " + this.geyserWorldManager.getClass());
|
||||
}
|
||||
GeyserSpigotBlockPlaceListener blockPlaceListener = new GeyserSpigotBlockPlaceListener(geyser, this.geyserWorldManager);
|
||||
Bukkit.getServer().getPluginManager().registerEvents(blockPlaceListener, this);
|
||||
|
||||
Bukkit.getServer().getPluginManager().registerEvents(new GeyserPistonListener(geyser, this.geyserWorldManager), this);
|
||||
|
||||
if (isPre1_12) {
|
||||
// Register events needed to send all recipes to the client
|
||||
Bukkit.getServer().getPluginManager().registerEvents(new GeyserSpigot1_11CraftingListener(geyser), this);
|
||||
}
|
||||
|
||||
this.getCommand("geyser").setExecutor(new GeyserSpigotCommandExecutor(geyser));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDisable() {
|
||||
if (geyser != null) {
|
||||
geyser.shutdown();
|
||||
}
|
||||
if (geyserInjector != null) {
|
||||
geyserInjector.shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public GeyserSpigotConfiguration getGeyserConfig() {
|
||||
return geyserConfig;
|
||||
}
|
||||
|
||||
@Override
|
||||
public GeyserSpigotLogger getGeyserLogger() {
|
||||
return geyserLogger;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandManager getGeyserCommandManager() {
|
||||
return this.geyserCommandManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IGeyserPingPassthrough getGeyserPingPassthrough() {
|
||||
return geyserSpigotPingPassthrough;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WorldManager getWorldManager() {
|
||||
return this.geyserWorldManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Path getConfigFolder() {
|
||||
return getDataFolder().toPath();
|
||||
}
|
||||
|
||||
@Override
|
||||
public BootstrapDumpInfo getDumpInfo() {
|
||||
return new GeyserSpigotDumpInfo();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMinecraftServerVersion() {
|
||||
return this.minecraftVersion;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SocketAddress getSocketAddress() {
|
||||
return this.geyserInjector.getServerSocketAddress();
|
||||
}
|
||||
|
||||
public boolean isCompatible(String version, String whichVersion) {
|
||||
int[] currentVersion = parseVersion(version);
|
||||
int[] otherVersion = parseVersion(whichVersion);
|
||||
int length = Math.max(currentVersion.length, otherVersion.length);
|
||||
for (int index = 0; index < length; index = index + 1) {
|
||||
int self = (index < currentVersion.length) ? currentVersion[index] : 0;
|
||||
int other = (index < otherVersion.length) ? otherVersion[index] : 0;
|
||||
|
||||
if (self != other) {
|
||||
return (self - other) > 0;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private int[] parseVersion(String versionParam) {
|
||||
versionParam = (versionParam == null) ? "" : versionParam;
|
||||
if (versionParam.contains("(MC: ")) {
|
||||
versionParam = versionParam.split("\\(MC: ")[1];
|
||||
versionParam = versionParam.split("\\)")[0];
|
||||
}
|
||||
String[] stringArray = versionParam.split("[_.-]");
|
||||
int[] temp = new int[stringArray.length];
|
||||
for (int index = 0; index <= (stringArray.length - 1); index = index + 1) {
|
||||
String t = stringArray[index].replaceAll("\\D", "");
|
||||
try {
|
||||
temp[index] = Integer.parseInt(t);
|
||||
} catch (NumberFormatException ex) {
|
||||
temp[index] = 0;
|
||||
}
|
||||
}
|
||||
return temp;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the server version before ViaVersion finishes initializing
|
||||
*/
|
||||
public ProtocolVersion getServerProtocolVersion() {
|
||||
return ProtocolVersion.getClosest(this.minecraftVersion);
|
||||
}
|
||||
|
||||
/**
|
||||
* This function should not run unless ViaVersion is installed on the server.
|
||||
*
|
||||
* @return true if there is any block mappings difference between the server and client.
|
||||
*/
|
||||
private boolean isViaVersionNeeded() {
|
||||
ProtocolVersion serverVersion = getServerProtocolVersion();
|
||||
List<ProtocolPathEntry> protocolList = Via.getManager().getProtocolManager().getProtocolPath(MinecraftProtocol.getJavaProtocolVersion(),
|
||||
serverVersion.getVersion());
|
||||
if (protocolList == null) {
|
||||
// No translation needed!
|
||||
return false;
|
||||
}
|
||||
for (int i = protocolList.size() - 1; i >= 0; i--) {
|
||||
MappingData mappingData = protocolList.get(i).getProtocol().getMappingData();
|
||||
if (mappingData != null) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
// All mapping data is null, which means client and server block states are the same
|
||||
return false;
|
||||
}
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2020 GeyserMC. http://geysermc.org
|
||||
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
|
@ -23,42 +23,51 @@
|
|||
* @link https://github.com/GeyserMC/Geyser
|
||||
*/
|
||||
|
||||
package org.geysermc.platform.spigot.command;
|
||||
package org.geysermc.geyser.platform.spigot.command;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.command.TabExecutor;
|
||||
import org.geysermc.connector.GeyserConnector;
|
||||
import org.geysermc.connector.command.GeyserCommand;
|
||||
import org.geysermc.connector.utils.LanguageUtils;
|
||||
import org.geysermc.geyser.GeyserImpl;
|
||||
import org.geysermc.geyser.command.CommandExecutor;
|
||||
import org.geysermc.geyser.command.GeyserCommand;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.geyser.text.GeyserLocale;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
@AllArgsConstructor
|
||||
public class GeyserSpigotCommandExecutor implements TabExecutor {
|
||||
public class GeyserSpigotCommandExecutor extends CommandExecutor implements TabExecutor {
|
||||
|
||||
private final GeyserConnector connector;
|
||||
public GeyserSpigotCommandExecutor(GeyserImpl geyser) {
|
||||
super(geyser);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
|
||||
SpigotCommandSender commandSender = new SpigotCommandSender(sender);
|
||||
GeyserSession session = getGeyserSession(commandSender);
|
||||
|
||||
if (args.length > 0) {
|
||||
if (getCommand(args[0]) != null) {
|
||||
if (!sender.hasPermission(getCommand(args[0]).getPermission())) {
|
||||
SpigotCommandSender commandSender = new SpigotCommandSender(sender);
|
||||
String message = LanguageUtils.getPlayerLocaleString("geyser.bootstrap.command.permission_fail", commandSender.getLocale());;
|
||||
GeyserCommand geyserCommand = getCommand(args[0]);
|
||||
if (geyserCommand != null) {
|
||||
if (!sender.hasPermission(geyserCommand.getPermission())) {
|
||||
String message = GeyserLocale.getPlayerLocaleString("geyser.bootstrap.command.permission_fail", commandSender.getLocale());
|
||||
|
||||
commandSender.sendMessage(ChatColor.RED + message);
|
||||
return true;
|
||||
}
|
||||
getCommand(args[0]).execute(new SpigotCommandSender(sender), args.length > 1 ? Arrays.copyOfRange(args, 1, args.length) : new String[0]);
|
||||
if (geyserCommand.isBedrockOnly() && session == null) {
|
||||
sender.sendMessage(ChatColor.RED + GeyserLocale.getPlayerLocaleString("geyser.bootstrap.command.bedrock_only", commandSender.getLocale()));
|
||||
return true;
|
||||
}
|
||||
geyserCommand.execute(session, commandSender, args.length > 1 ? Arrays.copyOfRange(args, 1, args.length) : new String[0]);
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
getCommand("help").execute(new SpigotCommandSender(sender), new String[0]);
|
||||
getCommand("help").execute(session, commandSender, new String[0]);
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
|
@ -67,12 +76,8 @@ public class GeyserSpigotCommandExecutor implements TabExecutor {
|
|||
@Override
|
||||
public List<String> onTabComplete(CommandSender sender, Command command, String label, String[] args) {
|
||||
if (args.length == 1) {
|
||||
return connector.getCommandManager().getCommandNames();
|
||||
return tabComplete(new SpigotCommandSender(sender));
|
||||
}
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
private GeyserCommand getCommand(String label) {
|
||||
return connector.getCommandManager().getCommands().get(label);
|
||||
return Collections.emptyList();
|
||||
}
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2020 GeyserMC. http://geysermc.org
|
||||
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
|
@ -23,14 +23,13 @@
|
|||
* @link https://github.com/GeyserMC/Geyser
|
||||
*/
|
||||
|
||||
package org.geysermc.platform.spigot.command;
|
||||
package org.geysermc.geyser.platform.spigot.command;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandMap;
|
||||
import org.geysermc.connector.GeyserConnector;
|
||||
import org.geysermc.connector.command.CommandManager;
|
||||
import org.geysermc.platform.spigot.GeyserSpigotPlugin;
|
||||
import org.geysermc.geyser.GeyserImpl;
|
||||
import org.geysermc.geyser.command.CommandManager;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
|
||||
|
@ -48,12 +47,8 @@ public class GeyserSpigotCommandManager extends CommandManager {
|
|||
}
|
||||
}
|
||||
|
||||
private GeyserSpigotPlugin plugin;
|
||||
|
||||
public GeyserSpigotCommandManager(GeyserSpigotPlugin plugin, GeyserConnector connector) {
|
||||
super(connector);
|
||||
|
||||
this.plugin = plugin;
|
||||
public GeyserSpigotCommandManager(GeyserImpl geyser) {
|
||||
super(geyser);
|
||||
}
|
||||
|
||||
@Override
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2020 GeyserMC. http://geysermc.org
|
||||
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
|
@ -23,13 +23,13 @@
|
|||
* @link https://github.com/GeyserMC/Geyser
|
||||
*/
|
||||
|
||||
package org.geysermc.platform.spigot.command;
|
||||
package org.geysermc.geyser.platform.spigot.command;
|
||||
|
||||
import org.bukkit.command.ConsoleCommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.geysermc.connector.GeyserConnector;
|
||||
import org.geysermc.connector.command.CommandSender;
|
||||
import org.geysermc.connector.utils.LanguageUtils;
|
||||
import org.geysermc.geyser.GeyserImpl;
|
||||
import org.geysermc.geyser.command.CommandSender;
|
||||
import org.geysermc.geyser.text.GeyserLocale;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
|
@ -50,11 +50,11 @@ public class SpigotCommandSender implements CommandSender {
|
|||
this.handle = handle;
|
||||
this.locale = getSpigotLocale();
|
||||
// Ensure even Java players' languages are loaded
|
||||
LanguageUtils.loadGeyserLocale(locale);
|
||||
GeyserLocale.loadGeyserLocale(locale);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
public String name() {
|
||||
return handle.getName();
|
||||
}
|
||||
|
||||
|
@ -73,6 +73,11 @@ public class SpigotCommandSender implements CommandSender {
|
|||
return locale;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasPermission(String permission) {
|
||||
return handle.hasPermission(permission);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set if we are on pre-1.12, and therefore {@code player.getLocale()} doesn't exist and we have to get
|
||||
* {@code player.spigot().getLocale()}.
|
||||
|
@ -86,7 +91,7 @@ public class SpigotCommandSender implements CommandSender {
|
|||
//noinspection JavaReflectionMemberAccess - of course it doesn't exist; that's why we're doing it
|
||||
LOCALE_METHOD = Player.Spigot.class.getMethod("getLocale");
|
||||
} catch (NoSuchMethodException e) {
|
||||
GeyserConnector.getInstance().getLogger().debug("Player.Spigot.getLocale() doesn't exist? Not a big deal but if you're seeing this please report it to the developers!");
|
||||
GeyserImpl.getInstance().getLogger().debug("Player.Spigot.getLocale() doesn't exist? Not a big deal but if you're seeing this please report it to the developers!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -97,8 +102,7 @@ public class SpigotCommandSender implements CommandSender {
|
|||
* @return the locale of the Spigot player
|
||||
*/
|
||||
private String getSpigotLocale() {
|
||||
if (handle instanceof Player) {
|
||||
Player player = (Player) handle;
|
||||
if (handle instanceof Player player) {
|
||||
if (USE_LEGACY_METHOD) {
|
||||
try {
|
||||
// sigh
|
||||
|
@ -110,6 +114,6 @@ public class SpigotCommandSender implements CommandSender {
|
|||
return player.getLocale();
|
||||
}
|
||||
}
|
||||
return LanguageUtils.getDefaultLocale();
|
||||
return GeyserLocale.getDefaultLocale();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,139 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
* @author GeyserMC
|
||||
* @link https://github.com/GeyserMC/Geyser
|
||||
*/
|
||||
|
||||
package org.geysermc.geyser.platform.spigot.world;
|
||||
|
||||
import com.github.steveice10.mc.protocol.data.game.level.block.value.PistonValueType;
|
||||
import com.nukkitx.math.vector.Vector3i;
|
||||
import it.unimi.dsi.fastutil.objects.Object2IntMap;
|
||||
import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.block.BlockPistonEvent;
|
||||
import org.bukkit.event.block.BlockPistonExtendEvent;
|
||||
import org.bukkit.event.block.BlockPistonRetractEvent;
|
||||
import org.geysermc.geyser.GeyserImpl;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.geyser.session.cache.PistonCache;
|
||||
import org.geysermc.geyser.level.block.BlockStateValues;
|
||||
import org.geysermc.geyser.translator.level.block.entity.PistonBlockEntity;
|
||||
import org.geysermc.geyser.level.physics.Direction;
|
||||
import org.geysermc.geyser.platform.spigot.world.manager.GeyserSpigotWorldManager;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
public class GeyserPistonListener implements Listener {
|
||||
private final GeyserImpl geyser;
|
||||
private final GeyserSpigotWorldManager worldManager;
|
||||
|
||||
public GeyserPistonListener(GeyserImpl geyser, GeyserSpigotWorldManager worldManager) {
|
||||
this.geyser = geyser;
|
||||
this.worldManager = worldManager;
|
||||
}
|
||||
|
||||
// The handlers' parent class cannot be registered
|
||||
@EventHandler(priority = EventPriority.MONITOR)
|
||||
public void onPistonExtend(BlockPistonExtendEvent event) {
|
||||
onPistonAction(event);
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.MONITOR)
|
||||
public void onPistonRetract(BlockPistonRetractEvent event) {
|
||||
onPistonAction(event);
|
||||
}
|
||||
|
||||
private void onPistonAction(BlockPistonEvent event) {
|
||||
if (event.isCancelled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
World world = event.getBlock().getWorld();
|
||||
boolean isExtend = event instanceof BlockPistonExtendEvent;
|
||||
|
||||
Location location = event.getBlock().getLocation();
|
||||
Vector3i position = getVector(location);
|
||||
PistonValueType type = isExtend ? PistonValueType.PUSHING : PistonValueType.PULLING;
|
||||
boolean sticky = event.isSticky();
|
||||
|
||||
Object2IntMap<Vector3i> attachedBlocks = new Object2IntOpenHashMap<>();
|
||||
boolean blocksFilled = false;
|
||||
|
||||
for (Map.Entry<UUID, GeyserSession> entry : geyser.getSessionManager().getSessions().entrySet()) {
|
||||
Player player = Bukkit.getPlayer(entry.getKey());
|
||||
if (player == null || !player.getWorld().equals(world)) {
|
||||
continue;
|
||||
}
|
||||
GeyserSession session = entry.getValue();
|
||||
|
||||
int dX = Math.abs(location.getBlockX() - player.getLocation().getBlockX()) >> 4;
|
||||
int dZ = Math.abs(location.getBlockZ() - player.getLocation().getBlockZ()) >> 4;
|
||||
if ((dX * dX + dZ * dZ) > session.getRenderDistance() * session.getRenderDistance()) {
|
||||
// Ignore pistons outside the player's render distance
|
||||
continue;
|
||||
}
|
||||
|
||||
// Trying to grab the blocks from the world like other platforms would result in the moving piston block
|
||||
// being returned instead.
|
||||
if (!blocksFilled) {
|
||||
// Blocks currently require a player for 1.12, so let's just leech off one player to get all blocks
|
||||
// and call it a day for the rest of the sessions (mostly to save on execution time)
|
||||
List<Block> blocks = isExtend ? ((BlockPistonExtendEvent) event).getBlocks() : ((BlockPistonRetractEvent) event).getBlocks();
|
||||
for (Block block : blocks) {
|
||||
Location attachedLocation = block.getLocation();
|
||||
int blockId = worldManager.getBlockNetworkId(player, block,
|
||||
attachedLocation.getBlockX(), attachedLocation.getBlockY(), attachedLocation.getBlockZ());
|
||||
// Ignore blocks that will be destroyed
|
||||
if (BlockStateValues.canPistonMoveBlock(blockId, isExtend)) {
|
||||
attachedBlocks.put(getVector(attachedLocation), blockId);
|
||||
}
|
||||
}
|
||||
blocksFilled = true;
|
||||
}
|
||||
|
||||
int pistonBlockId = worldManager.getBlockNetworkId(player, event.getBlock(), location.getBlockX(), location.getBlockY(), location.getBlockZ());
|
||||
// event.getDirection() is unreliable
|
||||
Direction orientation = BlockStateValues.getPistonOrientation(pistonBlockId);
|
||||
|
||||
session.executeInEventLoop(() -> {
|
||||
PistonCache pistonCache = session.getPistonCache();
|
||||
PistonBlockEntity blockEntity = pistonCache.getPistons().computeIfAbsent(position, pos ->
|
||||
new PistonBlockEntity(session, position, orientation, sticky, !isExtend));
|
||||
blockEntity.setAction(type, attachedBlocks);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private Vector3i getVector(Location location) {
|
||||
return Vector3i.from(location.getX(), location.getY(), location.getZ());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,203 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
* @author GeyserMC
|
||||
* @link https://github.com/GeyserMC/Geyser
|
||||
*/
|
||||
|
||||
package org.geysermc.geyser.platform.spigot.world;
|
||||
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.ItemStack;
|
||||
import com.github.steveice10.mc.protocol.data.game.recipe.Ingredient;
|
||||
import com.github.steveice10.mc.protocol.data.game.recipe.RecipeType;
|
||||
import com.github.steveice10.mc.protocol.data.game.recipe.data.ShapedRecipeData;
|
||||
import com.github.steveice10.mc.protocol.data.game.recipe.data.ShapelessRecipeData;
|
||||
import com.nukkitx.protocol.bedrock.data.inventory.CraftingData;
|
||||
import com.nukkitx.protocol.bedrock.data.inventory.ItemData;
|
||||
import com.nukkitx.protocol.bedrock.packet.CraftingDataPacket;
|
||||
import com.viaversion.viaversion.api.Via;
|
||||
import com.viaversion.viaversion.api.data.MappingData;
|
||||
import com.viaversion.viaversion.api.protocol.ProtocolPathEntry;
|
||||
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
|
||||
import com.viaversion.viaversion.protocols.protocol1_13to1_12_2.Protocol1_13To1_12_2;
|
||||
import com.viaversion.viaversion.util.Pair;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.player.PlayerJoinEvent;
|
||||
import org.bukkit.inventory.Recipe;
|
||||
import org.bukkit.inventory.ShapedRecipe;
|
||||
import org.bukkit.inventory.ShapelessRecipe;
|
||||
import org.geysermc.geyser.GeyserImpl;
|
||||
import org.geysermc.geyser.network.MinecraftProtocol;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.geyser.translator.inventory.item.ItemTranslator;
|
||||
import org.geysermc.geyser.util.InventoryUtils;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Used to send all available recipes from the server to the client, as a valid recipe book packet won't be sent by the server.
|
||||
* Requires ViaVersion.
|
||||
*/
|
||||
public class GeyserSpigot1_11CraftingListener implements Listener {
|
||||
|
||||
private final GeyserImpl geyser;
|
||||
/**
|
||||
* Specific mapping data for 1.12 to 1.13. Used to convert the 1.12 item into 1.13.
|
||||
*/
|
||||
private final MappingData mappingData1_12to1_13;
|
||||
/**
|
||||
* The list of all protocols from the client's version to 1.13.
|
||||
*/
|
||||
private final List<ProtocolPathEntry> protocolList;
|
||||
|
||||
public GeyserSpigot1_11CraftingListener(GeyserImpl geyser) {
|
||||
this.geyser = geyser;
|
||||
this.mappingData1_12to1_13 = Via.getManager().getProtocolManager().getProtocol(Protocol1_13To1_12_2.class).getMappingData();
|
||||
this.protocolList = Via.getManager().getProtocolManager().getProtocolPath(MinecraftProtocol.getJavaProtocolVersion(),
|
||||
ProtocolVersion.v1_13.getVersion());
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onPlayerJoin(PlayerJoinEvent event) {
|
||||
GeyserSession session = null;
|
||||
for (GeyserSession otherSession : geyser.getSessionManager().getSessions().values()) {
|
||||
if (otherSession.name().equals(event.getPlayer().getName())) {
|
||||
session = otherSession;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (session == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
sendServerRecipes(session);
|
||||
}
|
||||
|
||||
public void sendServerRecipes(GeyserSession session) {
|
||||
int netId = InventoryUtils.LAST_RECIPE_NET_ID;
|
||||
|
||||
CraftingDataPacket craftingDataPacket = new CraftingDataPacket();
|
||||
craftingDataPacket.setCleanRecipes(true);
|
||||
|
||||
Iterator<Recipe> recipeIterator = Bukkit.getServer().recipeIterator();
|
||||
while (recipeIterator.hasNext()) {
|
||||
Recipe recipe = recipeIterator.next();
|
||||
|
||||
Pair<ItemStack, ItemData> outputs = translateToBedrock(session, recipe.getResult());
|
||||
ItemStack javaOutput = outputs.getKey();
|
||||
ItemData output = outputs.getValue();
|
||||
if (output == null || output.getId() == 0) continue; // If items make air we don't want that
|
||||
|
||||
boolean isNotAllAir = false; // Check for all-air recipes
|
||||
if (recipe instanceof ShapedRecipe shapedRecipe) {
|
||||
int size = shapedRecipe.getShape().length * shapedRecipe.getShape()[0].length();
|
||||
Ingredient[] ingredients = new Ingredient[size];
|
||||
ItemData[] input = new ItemData[size];
|
||||
for (int i = 0; i < input.length; i++) {
|
||||
// Index is converting char to integer, adding i then converting back to char based on ASCII code
|
||||
Pair<ItemStack, ItemData> result = translateToBedrock(session, shapedRecipe.getIngredientMap().get((char) ('a' + i)));
|
||||
ingredients[i] = new Ingredient(new ItemStack[]{result.getKey()});
|
||||
input[i] = result.getValue();
|
||||
isNotAllAir |= input[i].getId() != 0;
|
||||
}
|
||||
|
||||
if (!isNotAllAir) continue;
|
||||
UUID uuid = UUID.randomUUID();
|
||||
// Add recipe to our internal cache
|
||||
ShapedRecipeData data = new ShapedRecipeData(shapedRecipe.getShape()[0].length(), shapedRecipe.getShape().length,
|
||||
"", ingredients, javaOutput);
|
||||
session.getCraftingRecipes().put(netId,
|
||||
new com.github.steveice10.mc.protocol.data.game.recipe.Recipe(RecipeType.CRAFTING_SHAPED, uuid.toString(), data));
|
||||
|
||||
// Add recipe for Bedrock
|
||||
craftingDataPacket.getCraftingData().add(CraftingData.fromShaped(uuid.toString(),
|
||||
shapedRecipe.getShape()[0].length(), shapedRecipe.getShape().length, Arrays.asList(input),
|
||||
Collections.singletonList(output), uuid, "crafting_table", 0, netId++));
|
||||
} else if (recipe instanceof ShapelessRecipe shapelessRecipe) {
|
||||
Ingredient[] ingredients = new Ingredient[shapelessRecipe.getIngredientList().size()];
|
||||
ItemData[] input = new ItemData[shapelessRecipe.getIngredientList().size()];
|
||||
|
||||
for (int i = 0; i < input.length; i++) {
|
||||
Pair<ItemStack, ItemData> result = translateToBedrock(session, shapelessRecipe.getIngredientList().get(i));
|
||||
ingredients[i] = new Ingredient(new ItemStack[]{result.getKey()});
|
||||
input[i] = result.getValue();
|
||||
isNotAllAir |= input[i].getId() != 0;
|
||||
}
|
||||
|
||||
if (!isNotAllAir) continue;
|
||||
UUID uuid = UUID.randomUUID();
|
||||
// Add recipe to our internal cache
|
||||
ShapelessRecipeData data = new ShapelessRecipeData("", ingredients, javaOutput);
|
||||
session.getCraftingRecipes().put(netId,
|
||||
new com.github.steveice10.mc.protocol.data.game.recipe.Recipe(RecipeType.CRAFTING_SHAPELESS, uuid.toString(), data));
|
||||
|
||||
// Add recipe for Bedrock
|
||||
craftingDataPacket.getCraftingData().add(CraftingData.fromShapeless(uuid.toString(),
|
||||
Arrays.asList(input), Collections.singletonList(output), uuid, "crafting_table", 0, netId++));
|
||||
}
|
||||
}
|
||||
|
||||
session.sendUpstreamPacket(craftingDataPacket);
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
private Pair<ItemStack, ItemData> translateToBedrock(GeyserSession session, org.bukkit.inventory.ItemStack itemStack) {
|
||||
if (itemStack != null && itemStack.getData() != null) {
|
||||
if (itemStack.getType().getId() == 0) {
|
||||
return new Pair<>(null, ItemData.AIR);
|
||||
}
|
||||
|
||||
int legacyId = (itemStack.getType().getId() << 4) | (itemStack.getData().getData() & 0xFFFF);
|
||||
|
||||
if (itemStack.getType().getId() == 355 && itemStack.getData().getData() == (byte) 0) { // Handle bed color since the server will always be pre-1.12
|
||||
legacyId = (itemStack.getType().getId() << 4) | ((byte) 14 & 0xFFFF);
|
||||
}
|
||||
|
||||
// old version -> 1.13 -> 1.13.1 -> 1.14 -> 1.15 -> 1.16 and so on
|
||||
int itemId;
|
||||
if (mappingData1_12to1_13.getItemMappings().containsKey(legacyId)) {
|
||||
itemId = mappingData1_12to1_13.getNewItemId(legacyId);
|
||||
} else if (mappingData1_12to1_13.getItemMappings().containsKey((itemStack.getType().getId() << 4) | (0))) {
|
||||
itemId = mappingData1_12to1_13.getNewItemId((itemStack.getType().getId() << 4) | (0));
|
||||
} else {
|
||||
// No ID found, just send back air
|
||||
return new Pair<>(null, ItemData.AIR);
|
||||
}
|
||||
|
||||
for (int i = protocolList.size() - 1; i >= 0; i--) {
|
||||
MappingData mappingData = protocolList.get(i).getProtocol().getMappingData();
|
||||
if (mappingData != null) {
|
||||
itemId = mappingData.getNewItemId(itemId);
|
||||
}
|
||||
}
|
||||
|
||||
ItemStack mcItemStack = new ItemStack(itemId, itemStack.getAmount());
|
||||
ItemData finalData = ItemTranslator.translateToBedrock(session, mcItemStack);
|
||||
return new Pair<>(mcItemStack, finalData);
|
||||
}
|
||||
|
||||
// Empty slot, most likely
|
||||
return new Pair<>(null, ItemData.AIR);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,69 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
* @author GeyserMC
|
||||
* @link https://github.com/GeyserMC/Geyser
|
||||
*/
|
||||
|
||||
package org.geysermc.geyser.platform.spigot.world;
|
||||
|
||||
import com.nukkitx.math.vector.Vector3f;
|
||||
import com.nukkitx.protocol.bedrock.data.SoundEvent;
|
||||
import com.nukkitx.protocol.bedrock.packet.LevelSoundEventPacket;
|
||||
import lombok.AllArgsConstructor;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.block.BlockPlaceEvent;
|
||||
import org.geysermc.geyser.GeyserImpl;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.geyser.level.block.BlockStateValues;
|
||||
import org.geysermc.geyser.registry.BlockRegistries;
|
||||
import org.geysermc.geyser.platform.spigot.world.manager.GeyserSpigotWorldManager;
|
||||
|
||||
@AllArgsConstructor
|
||||
public class GeyserSpigotBlockPlaceListener implements Listener {
|
||||
private final GeyserImpl geyser;
|
||||
private final GeyserSpigotWorldManager worldManager;
|
||||
|
||||
@EventHandler
|
||||
public void place(final BlockPlaceEvent event) {
|
||||
GeyserSession session = geyser.connectionByUuid(event.getPlayer().getUniqueId());
|
||||
if (session == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
LevelSoundEventPacket placeBlockSoundPacket = new LevelSoundEventPacket();
|
||||
placeBlockSoundPacket.setSound(SoundEvent.PLACE);
|
||||
placeBlockSoundPacket.setPosition(Vector3f.from(event.getBlockPlaced().getX(), event.getBlockPlaced().getY(), event.getBlockPlaced().getZ()));
|
||||
placeBlockSoundPacket.setBabySound(false);
|
||||
if (worldManager.isLegacy()) {
|
||||
placeBlockSoundPacket.setExtraData(session.getBlockMappings().getBedrockBlockId(worldManager.getBlockAt(session,
|
||||
event.getBlockPlaced().getX(), event.getBlockPlaced().getY(), event.getBlockPlaced().getZ())));
|
||||
} else {
|
||||
String javaBlockId = event.getBlockPlaced().getBlockData().getAsString();
|
||||
placeBlockSoundPacket.setExtraData(session.getBlockMappings().getBedrockBlockId(BlockRegistries.JAVA_IDENTIFIERS.get().getOrDefault(javaBlockId, BlockStateValues.JAVA_AIR_ID)));
|
||||
}
|
||||
placeBlockSoundPacket.setIdentifier(":");
|
||||
session.sendUpstreamPacket(placeBlockSoundPacket);
|
||||
session.setLastBlockPlacePosition(null);
|
||||
session.setLastBlockPlacedId(null);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,61 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
* @author GeyserMC
|
||||
* @link https://github.com/GeyserMC/Geyser
|
||||
*/
|
||||
|
||||
package org.geysermc.geyser.platform.spigot.world.manager;
|
||||
|
||||
import com.viaversion.viaversion.api.Via;
|
||||
import com.viaversion.viaversion.protocols.protocol1_13to1_12_2.storage.BlockStorage;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.geyser.level.block.BlockStateValues;
|
||||
import org.geysermc.geyser.adapters.spigot.SpigotAdapters;
|
||||
import org.geysermc.geyser.adapters.spigot.SpigotWorldAdapter;
|
||||
|
||||
/**
|
||||
* Used with ViaVersion and pre-1.13.
|
||||
*/
|
||||
public class GeyserSpigot1_12NativeWorldManager extends GeyserSpigot1_12WorldManager {
|
||||
private final SpigotWorldAdapter adapter;
|
||||
|
||||
public GeyserSpigot1_12NativeWorldManager(Plugin plugin) {
|
||||
super(plugin);
|
||||
this.adapter = SpigotAdapters.getWorldAdapter();
|
||||
// Unlike post-1.13, we can't build up a cache of block states, because block entities need some special conversion
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getBlockAt(GeyserSession session, int x, int y, int z) {
|
||||
Player player = Bukkit.getPlayer(session.getPlayerEntity().getUsername());
|
||||
if (player == null) {
|
||||
return BlockStateValues.JAVA_AIR_ID;
|
||||
}
|
||||
// Get block entity storage
|
||||
BlockStorage storage = Via.getManager().getConnectionManager().getConnectedClient(player.getUniqueId()).get(BlockStorage.class);
|
||||
int blockId = adapter.getBlockAt(player.getWorld(), x, y, z);
|
||||
return getLegacyBlock(storage, blockId, x, y, z);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,125 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
* @author GeyserMC
|
||||
* @link https://github.com/GeyserMC/Geyser
|
||||
*/
|
||||
|
||||
package org.geysermc.geyser.platform.spigot.world.manager;
|
||||
|
||||
import com.viaversion.viaversion.api.Via;
|
||||
import com.viaversion.viaversion.api.data.MappingData;
|
||||
import com.viaversion.viaversion.api.minecraft.Position;
|
||||
import com.viaversion.viaversion.api.protocol.ProtocolPathEntry;
|
||||
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
|
||||
import com.viaversion.viaversion.protocols.protocol1_13to1_12_2.Protocol1_13To1_12_2;
|
||||
import com.viaversion.viaversion.protocols.protocol1_13to1_12_2.storage.BlockStorage;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.geyser.level.block.BlockStateValues;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Should be used when ViaVersion is present, no NMS adapter is being used, and we are pre-1.13.
|
||||
*
|
||||
* You need ViaVersion to connect to an older server with the Geyser-Spigot plugin.
|
||||
*/
|
||||
public class GeyserSpigot1_12WorldManager extends GeyserSpigotWorldManager {
|
||||
/**
|
||||
* Specific mapping data for 1.12 to 1.13. Used to convert the 1.12 block into the 1.13 block state.
|
||||
* (Block IDs did not change between server versions until 1.13 and after)
|
||||
*/
|
||||
private final MappingData mappingData1_12to1_13;
|
||||
|
||||
/**
|
||||
* The list of all protocols from the client's version to 1.13.
|
||||
*/
|
||||
private final List<ProtocolPathEntry> protocolList;
|
||||
|
||||
public GeyserSpigot1_12WorldManager(Plugin plugin) {
|
||||
super(plugin);
|
||||
this.mappingData1_12to1_13 = Via.getManager().getProtocolManager().getProtocol(Protocol1_13To1_12_2.class).getMappingData();
|
||||
this.protocolList = Via.getManager().getProtocolManager().getProtocolPath(CLIENT_PROTOCOL_VERSION,
|
||||
ProtocolVersion.v1_13.getVersion());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getBlockAt(GeyserSession session, int x, int y, int z) {
|
||||
Player player = Bukkit.getPlayer(session.getPlayerEntity().getUsername());
|
||||
if (player == null) {
|
||||
return BlockStateValues.JAVA_AIR_ID;
|
||||
}
|
||||
if (!player.getWorld().isChunkLoaded(x >> 4, z >> 4)) {
|
||||
// Prevent nasty async errors if a player is loading in
|
||||
return BlockStateValues.JAVA_AIR_ID;
|
||||
}
|
||||
|
||||
Block block = player.getWorld().getBlockAt(x, y, z);
|
||||
return getBlockNetworkId(player, block, x, y, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("deprecation")
|
||||
public int getBlockNetworkId(Player player, Block block, int x, int y, int z) {
|
||||
// Get block entity storage
|
||||
BlockStorage storage = Via.getManager().getConnectionManager().getConnectedClient(player.getUniqueId()).get(BlockStorage.class);
|
||||
// Black magic that gets the old block state ID
|
||||
int oldBlockId = (block.getType().getId() << 4) | (block.getData() & 0xF);
|
||||
return getLegacyBlock(storage, oldBlockId, x, y, z);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param storage ViaVersion's block entity storage (used to fix block entity state differences)
|
||||
* @param blockId the pre-1.13 block id
|
||||
* @param x X coordinate of block
|
||||
* @param y Y coordinate of block
|
||||
* @param z Z coordinate of block
|
||||
* @return the block state updated to the latest Minecraft version
|
||||
*/
|
||||
public int getLegacyBlock(BlockStorage storage, int blockId, int x, int y, int z) {
|
||||
// Convert block state from old version (1.12.2) -> 1.13 -> 1.13.1 -> 1.14 -> 1.15 -> 1.16 -> 1.16.2
|
||||
blockId = mappingData1_12to1_13.getNewBlockId(blockId);
|
||||
// Translate block entity differences - some information was stored in block tags and not block states
|
||||
if (storage.isWelcome(blockId)) { // No getOrDefault method
|
||||
BlockStorage.ReplacementData data = storage.get(new Position(x, (short) y, z));
|
||||
if (data != null && data.getReplacement() != -1) {
|
||||
blockId = data.getReplacement();
|
||||
}
|
||||
}
|
||||
for (int i = protocolList.size() - 1; i >= 0; i--) {
|
||||
MappingData mappingData = protocolList.get(i).getProtocol().getMappingData();
|
||||
if (mappingData != null) {
|
||||
blockId = mappingData.getNewBlockStateId(blockId);
|
||||
}
|
||||
}
|
||||
return blockId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isLegacy() {
|
||||
return true;
|
||||
}
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2020 GeyserMC. http://geysermc.org
|
||||
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
|
@ -23,27 +23,34 @@
|
|||
* @link https://github.com/GeyserMC/Geyser
|
||||
*/
|
||||
|
||||
package org.geysermc.connector.utils;
|
||||
package org.geysermc.geyser.platform.spigot.world.manager;
|
||||
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Paths;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.geyser.level.block.BlockStateValues;
|
||||
|
||||
public class DockerCheck {
|
||||
/**
|
||||
* Should only be used when we know {@link GeyserSpigotWorldManager#getBlockAt(GeyserSession, int, int, int)}
|
||||
* cannot be accurate. Typically, this is when ViaVersion is not installed but a client still manages to connect.
|
||||
* If this occurs to you somehow, please let us know!!
|
||||
*/
|
||||
public class GeyserSpigotFallbackWorldManager extends GeyserSpigotWorldManager {
|
||||
public GeyserSpigotFallbackWorldManager(Plugin plugin) {
|
||||
super(plugin);
|
||||
}
|
||||
|
||||
// By default, Geyser now sets the IP to the local IP in all cases on plugin versions so we don't notify the user of anything
|
||||
// However we still have this check for the potential future bug
|
||||
public static boolean checkBasic() {
|
||||
try {
|
||||
String OS = System.getProperty("os.name").toLowerCase();
|
||||
if (OS.indexOf("nix") >= 0 || OS.indexOf("nux") >= 0 || OS.indexOf("aix") > 0) {
|
||||
String output = new String(Files.readAllBytes(Paths.get("/proc/1/cgroup")));
|
||||
|
||||
if (output.contains("docker")) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} catch (Exception ignored) { } // Ignore any errors, inc ip failed to fetch, process could not run or access denied
|
||||
@Override
|
||||
public int getBlockAt(GeyserSession session, int x, int y, int z) {
|
||||
return BlockStateValues.JAVA_AIR_ID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasOwnChunkCache() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isLegacy() {
|
||||
return true;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,78 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
* @author GeyserMC
|
||||
* @link https://github.com/GeyserMC/Geyser
|
||||
*/
|
||||
|
||||
package org.geysermc.geyser.platform.spigot.world.manager;
|
||||
|
||||
import com.viaversion.viaversion.api.Via;
|
||||
import com.viaversion.viaversion.api.data.MappingData;
|
||||
import com.viaversion.viaversion.api.protocol.ProtocolPathEntry;
|
||||
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
|
||||
import it.unimi.dsi.fastutil.ints.Int2IntMap;
|
||||
import it.unimi.dsi.fastutil.ints.Int2IntOpenHashMap;
|
||||
import it.unimi.dsi.fastutil.ints.IntList;
|
||||
import org.geysermc.geyser.network.MinecraftProtocol;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.geyser.platform.spigot.GeyserSpigotPlugin;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Used when block IDs need to be translated to the latest version
|
||||
*/
|
||||
public class GeyserSpigotLegacyNativeWorldManager extends GeyserSpigotNativeWorldManager {
|
||||
|
||||
private final Int2IntMap oldToNewBlockId;
|
||||
|
||||
public GeyserSpigotLegacyNativeWorldManager(GeyserSpigotPlugin plugin) {
|
||||
super(plugin);
|
||||
IntList allBlockStates = adapter.getAllBlockStates();
|
||||
oldToNewBlockId = new Int2IntOpenHashMap(allBlockStates.size());
|
||||
ProtocolVersion serverVersion = plugin.getServerProtocolVersion();
|
||||
List<ProtocolPathEntry> protocolList = Via.getManager().getProtocolManager().getProtocolPath(MinecraftProtocol.getJavaProtocolVersion(),
|
||||
serverVersion.getVersion());
|
||||
for (int oldBlockId : allBlockStates) {
|
||||
int newBlockId = oldBlockId;
|
||||
// protocolList should *not* be null; we checked for that before initializing this class
|
||||
for (int i = protocolList.size() - 1; i >= 0; i--) {
|
||||
MappingData mappingData = protocolList.get(i).getProtocol().getMappingData();
|
||||
if (mappingData != null) {
|
||||
newBlockId = mappingData.getNewBlockStateId(newBlockId);
|
||||
}
|
||||
}
|
||||
oldToNewBlockId.put(oldBlockId, newBlockId);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getBlockAt(GeyserSession session, int x, int y, int z) {
|
||||
int nativeBlockId = super.getBlockAt(session, x, y, z);
|
||||
return oldToNewBlockId.getOrDefault(nativeBlockId, nativeBlockId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isLegacy() {
|
||||
return true;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,52 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
* @author GeyserMC
|
||||
* @link https://github.com/GeyserMC/Geyser
|
||||
*/
|
||||
|
||||
package org.geysermc.geyser.platform.spigot.world.manager;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.geyser.level.block.BlockStateValues;
|
||||
import org.geysermc.geyser.adapters.spigot.SpigotAdapters;
|
||||
import org.geysermc.geyser.adapters.spigot.SpigotWorldAdapter;
|
||||
|
||||
public class GeyserSpigotNativeWorldManager extends GeyserSpigotWorldManager {
|
||||
protected final SpigotWorldAdapter adapter;
|
||||
|
||||
public GeyserSpigotNativeWorldManager(Plugin plugin) {
|
||||
super(plugin);
|
||||
adapter = SpigotAdapters.getWorldAdapter();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getBlockAt(GeyserSession session, int x, int y, int z) {
|
||||
Player player = Bukkit.getPlayer(session.getPlayerEntity().getUsername());
|
||||
if (player == null) {
|
||||
return BlockStateValues.JAVA_AIR_ID;
|
||||
}
|
||||
return adapter.getBlockAt(player.getWorld(), x, y, z);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,194 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
* @author GeyserMC
|
||||
* @link https://github.com/GeyserMC/Geyser
|
||||
*/
|
||||
|
||||
package org.geysermc.geyser.platform.spigot.world.manager;
|
||||
|
||||
import com.nukkitx.math.vector.Vector3i;
|
||||
import com.nukkitx.nbt.NbtMap;
|
||||
import com.nukkitx.nbt.NbtMapBuilder;
|
||||
import com.nukkitx.nbt.NbtType;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.block.Lectern;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.meta.BookMeta;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
import org.geysermc.geyser.network.MinecraftProtocol;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.geyser.translator.inventory.LecternInventoryTranslator;
|
||||
import org.geysermc.geyser.level.GeyserWorldManager;
|
||||
import org.geysermc.geyser.level.block.BlockStateValues;
|
||||
import org.geysermc.geyser.registry.BlockRegistries;
|
||||
import org.geysermc.geyser.util.BlockEntityUtils;
|
||||
import org.geysermc.geyser.level.GameRule;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* The base world manager to use when there is no supported NMS revision
|
||||
*/
|
||||
public class GeyserSpigotWorldManager extends GeyserWorldManager {
|
||||
/**
|
||||
* The current client protocol version for ViaVersion usage.
|
||||
*/
|
||||
protected static final int CLIENT_PROTOCOL_VERSION = MinecraftProtocol.getJavaProtocolVersion();
|
||||
|
||||
private final Plugin plugin;
|
||||
|
||||
public GeyserSpigotWorldManager(Plugin plugin) {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getBlockAt(GeyserSession session, int x, int y, int z) {
|
||||
Player bukkitPlayer;
|
||||
if ((bukkitPlayer = Bukkit.getPlayer(session.getPlayerEntity().getUsername())) == null) {
|
||||
return BlockStateValues.JAVA_AIR_ID;
|
||||
}
|
||||
World world = bukkitPlayer.getWorld();
|
||||
if (!world.isChunkLoaded(x >> 4, z >> 4)) {
|
||||
// If the chunk isn't loaded, how could we even be here?
|
||||
return BlockStateValues.JAVA_AIR_ID;
|
||||
}
|
||||
|
||||
return getBlockNetworkId(bukkitPlayer, world.getBlockAt(x, y, z), x, y, z);
|
||||
}
|
||||
|
||||
public int getBlockNetworkId(Player player, Block block, int x, int y, int z) {
|
||||
return BlockRegistries.JAVA_IDENTIFIERS.getOrDefault(block.getBlockData().getAsString(), BlockStateValues.JAVA_AIR_ID);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasOwnChunkCache() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public NbtMap getLecternDataAt(GeyserSession session, int x, int y, int z, boolean isChunkLoad) {
|
||||
// Run as a task to prevent async issues
|
||||
Runnable lecternInfoGet = () -> {
|
||||
Player bukkitPlayer;
|
||||
if ((bukkitPlayer = Bukkit.getPlayer(session.getPlayerEntity().getUsername())) == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
Block block = bukkitPlayer.getWorld().getBlockAt(x, y, z);
|
||||
if (!(block.getState() instanceof Lectern lectern)) {
|
||||
session.getGeyser().getLogger().error("Lectern expected at: " + Vector3i.from(x, y, z).toString() + " but was not! " + block.toString());
|
||||
return;
|
||||
}
|
||||
|
||||
ItemStack itemStack = lectern.getInventory().getItem(0);
|
||||
if (itemStack == null || !(itemStack.getItemMeta() instanceof BookMeta bookMeta)) {
|
||||
if (!isChunkLoad) {
|
||||
// We need to update the lectern since it's not going to be updated otherwise
|
||||
BlockEntityUtils.updateBlockEntity(session, LecternInventoryTranslator.getBaseLecternTag(x, y, z, 0).build(), Vector3i.from(x, y, z));
|
||||
}
|
||||
// We don't care; return
|
||||
return;
|
||||
}
|
||||
|
||||
// On the count: allow the book to show/open even there are no pages. We know there is a book here, after all, and this matches Java behavior
|
||||
boolean hasBookPages = bookMeta.getPageCount() > 0;
|
||||
NbtMapBuilder lecternTag = LecternInventoryTranslator.getBaseLecternTag(x, y, z, hasBookPages ? bookMeta.getPageCount() : 1);
|
||||
lecternTag.putInt("page", lectern.getPage() / 2);
|
||||
NbtMapBuilder bookTag = NbtMap.builder()
|
||||
.putByte("Count", (byte) itemStack.getAmount())
|
||||
.putShort("Damage", (short) 0)
|
||||
.putString("Name", "minecraft:writable_book");
|
||||
List<NbtMap> pages = new ArrayList<>(bookMeta.getPageCount());
|
||||
if (hasBookPages) {
|
||||
for (String page : bookMeta.getPages()) {
|
||||
NbtMapBuilder pageBuilder = NbtMap.builder()
|
||||
.putString("photoname", "")
|
||||
.putString("text", page);
|
||||
pages.add(pageBuilder.build());
|
||||
}
|
||||
} else {
|
||||
// Empty page
|
||||
NbtMapBuilder pageBuilder = NbtMap.builder()
|
||||
.putString("photoname", "")
|
||||
.putString("text", "");
|
||||
pages.add(pageBuilder.build());
|
||||
}
|
||||
|
||||
bookTag.putCompound("tag", NbtMap.builder().putList("pages", NbtType.COMPOUND, pages).build());
|
||||
lecternTag.putCompound("book", bookTag.build());
|
||||
NbtMap blockEntityTag = lecternTag.build();
|
||||
BlockEntityUtils.updateBlockEntity(session, blockEntityTag, Vector3i.from(x, y, z));
|
||||
};
|
||||
|
||||
if (isChunkLoad) {
|
||||
// Delay to ensure the chunk is sent first, and then the lectern data
|
||||
Bukkit.getScheduler().runTaskLater(this.plugin, lecternInfoGet, 5);
|
||||
} else {
|
||||
Bukkit.getScheduler().runTask(this.plugin, lecternInfoGet);
|
||||
}
|
||||
return LecternInventoryTranslator.getBaseLecternTag(x, y, z, 0).build(); // Will be updated later
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldExpectLecternHandled() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public Boolean getGameRuleBool(GeyserSession session, GameRule gameRule) {
|
||||
String value = Bukkit.getPlayer(session.getPlayerEntity().getUsername()).getWorld().getGameRuleValue(gameRule.getJavaID());
|
||||
if (!value.isEmpty()) {
|
||||
return Boolean.parseBoolean(value);
|
||||
}
|
||||
return (Boolean) gameRule.getDefaultValue();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getGameRuleInt(GeyserSession session, GameRule gameRule) {
|
||||
String value = Bukkit.getPlayer(session.getPlayerEntity().getUsername()).getWorld().getGameRuleValue(gameRule.getJavaID());
|
||||
if (!value.isEmpty()) {
|
||||
return Integer.parseInt(value);
|
||||
}
|
||||
return (int) gameRule.getDefaultValue();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasPermission(GeyserSession session, String permission) {
|
||||
return Bukkit.getPlayer(session.getPlayerEntity().getUsername()).hasPermission(permission);
|
||||
}
|
||||
|
||||
/**
|
||||
* This must be set to true if we are pre-1.13, and {@link BlockData#getAsString() does not exist}.
|
||||
*
|
||||
* This should be set to true if we are post-1.13 but before the latest version, and we should convert the old block state id
|
||||
* to the current one.
|
||||
*
|
||||
* @return whether there is a difference between client block state and server block state that requires extra processing
|
||||
*/
|
||||
public boolean isLegacy() {
|
||||
return false;
|
||||
}
|
||||
}
|
|
@ -1,227 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2020 GeyserMC. http://geysermc.org
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
* @author GeyserMC
|
||||
* @link https://github.com/GeyserMC/Geyser
|
||||
*/
|
||||
|
||||
package org.geysermc.platform.spigot;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
import org.geysermc.common.PlatformType;
|
||||
import org.geysermc.connector.GeyserConnector;
|
||||
import org.geysermc.connector.bootstrap.GeyserBootstrap;
|
||||
import org.geysermc.connector.command.CommandManager;
|
||||
import org.geysermc.connector.configuration.GeyserConfiguration;
|
||||
import org.geysermc.connector.dump.BootstrapDumpInfo;
|
||||
import org.geysermc.connector.network.translators.world.WorldManager;
|
||||
import org.geysermc.connector.ping.GeyserLegacyPingPassthrough;
|
||||
import org.geysermc.connector.ping.IGeyserPingPassthrough;
|
||||
import org.geysermc.connector.utils.FileUtils;
|
||||
import org.geysermc.connector.utils.LanguageUtils;
|
||||
import org.geysermc.platform.spigot.command.GeyserSpigotCommandExecutor;
|
||||
import org.geysermc.platform.spigot.command.GeyserSpigotCommandManager;
|
||||
import org.geysermc.platform.spigot.command.SpigotCommandSender;
|
||||
import org.geysermc.platform.spigot.world.GeyserSpigotBlockPlaceListener;
|
||||
import org.geysermc.platform.spigot.world.GeyserSpigotWorldManager;
|
||||
import us.myles.ViaVersion.api.Via;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.UUID;
|
||||
import java.util.logging.Level;
|
||||
|
||||
public class GeyserSpigotPlugin extends JavaPlugin implements GeyserBootstrap {
|
||||
|
||||
private GeyserSpigotCommandManager geyserCommandManager;
|
||||
private GeyserSpigotConfiguration geyserConfig;
|
||||
private GeyserSpigotLogger geyserLogger;
|
||||
private IGeyserPingPassthrough geyserSpigotPingPassthrough;
|
||||
private GeyserSpigotWorldManager geyserWorldManager;
|
||||
|
||||
private GeyserConnector connector;
|
||||
|
||||
@Override
|
||||
public void onEnable() {
|
||||
// This is manually done instead of using Bukkit methods to save the config because otherwise comments get removed
|
||||
try {
|
||||
if (!getDataFolder().exists()) {
|
||||
getDataFolder().mkdir();
|
||||
File bukkitConfig = new File("plugins/Geyser-Bukkit/config.yml");
|
||||
if (bukkitConfig.exists()) { // Copy over old configs
|
||||
getLogger().log(Level.INFO, LanguageUtils.getLocaleStringLog("geyser.bootstrap.config.copy_bukkit_config"));
|
||||
Files.copy(bukkitConfig.toPath(), new File(getDataFolder().toString() + "/config.yml").toPath());
|
||||
getLogger().log(Level.INFO, LanguageUtils.getLocaleStringLog("geyser.bootstrap.config.copied_bukkit_config"));
|
||||
}
|
||||
}
|
||||
File configFile = FileUtils.fileOrCopiedFromResource(new File(getDataFolder(), "config.yml"), "config.yml", (x) -> x.replaceAll("generateduuid", UUID.randomUUID().toString()));
|
||||
this.geyserConfig = FileUtils.loadConfig(configFile, GeyserSpigotConfiguration.class);
|
||||
} catch (IOException ex) {
|
||||
getLogger().log(Level.WARNING, LanguageUtils.getLocaleStringLog("geyser.config.failed"), ex);
|
||||
ex.printStackTrace();
|
||||
}
|
||||
|
||||
// By default this should be localhost but may need to be changed in some circumstances
|
||||
if (this.geyserConfig.getRemote().getAddress().equalsIgnoreCase("auto")) {
|
||||
geyserConfig.setAutoconfiguredRemote(true);
|
||||
// Don't use localhost if not listening on all interfaces
|
||||
if (!Bukkit.getIp().equals("0.0.0.0") && !Bukkit.getIp().equals("")) {
|
||||
geyserConfig.getRemote().setAddress(Bukkit.getIp());
|
||||
}
|
||||
geyserConfig.getRemote().setPort(Bukkit.getPort());
|
||||
}
|
||||
|
||||
if (geyserConfig.getBedrock().isCloneRemotePort()) {
|
||||
geyserConfig.getBedrock().setPort(Bukkit.getPort());
|
||||
}
|
||||
|
||||
this.geyserLogger = new GeyserSpigotLogger(getLogger(), geyserConfig.isDebugMode());
|
||||
GeyserConfiguration.checkGeyserConfiguration(geyserConfig, geyserLogger);
|
||||
|
||||
if (geyserConfig.getRemote().getAuthType().equals("floodgate") && Bukkit.getPluginManager().getPlugin("floodgate-bukkit") == null) {
|
||||
geyserLogger.severe(LanguageUtils.getLocaleStringLog("geyser.bootstrap.floodgate.not_installed") + " " + LanguageUtils.getLocaleStringLog("geyser.bootstrap.floodgate.disabling"));
|
||||
this.getPluginLoader().disablePlugin(this);
|
||||
return;
|
||||
} else if (geyserConfig.isAutoconfiguredRemote() && Bukkit.getPluginManager().getPlugin("floodgate-bukkit") != null) {
|
||||
// Floodgate installed means that the user wants Floodgate authentication
|
||||
geyserLogger.debug("Auto-setting to Floodgate authentication.");
|
||||
geyserConfig.getRemote().setAuthType("floodgate");
|
||||
}
|
||||
|
||||
geyserConfig.loadFloodgate(this);
|
||||
|
||||
this.connector = GeyserConnector.start(PlatformType.SPIGOT, this);
|
||||
|
||||
if (geyserConfig.isLegacyPingPassthrough()) {
|
||||
this.geyserSpigotPingPassthrough = GeyserLegacyPingPassthrough.init(connector);
|
||||
} else {
|
||||
this.geyserSpigotPingPassthrough = new GeyserSpigotPingPassthrough(geyserLogger);
|
||||
}
|
||||
|
||||
this.geyserCommandManager = new GeyserSpigotCommandManager(this, connector);
|
||||
|
||||
boolean isViaVersion = (Bukkit.getPluginManager().getPlugin("ViaVersion") != null);
|
||||
if (isViaVersion) {
|
||||
if (!isCompatible(Via.getAPI().getVersion().replace("-SNAPSHOT", ""), "3.2.0")) {
|
||||
geyserLogger.warning(LanguageUtils.getLocaleStringLog("geyser.bootstrap.viaversion.too_old",
|
||||
"https://ci.viaversion.com/job/ViaVersion/"));
|
||||
isViaVersion = false;
|
||||
}
|
||||
}
|
||||
// Used to determine if Block.getBlockData() is present.
|
||||
boolean isLegacy = !isCompatible(Bukkit.getServer().getVersion(), "1.13.0");
|
||||
if (isLegacy)
|
||||
geyserLogger.debug("Legacy version of Minecraft (1.12.2 or older) detected; falling back to ViaVersion for block state retrieval.");
|
||||
|
||||
boolean use3dBiomes = isCompatible(Bukkit.getServer().getVersion(), "1.16.0");
|
||||
if (!use3dBiomes) {
|
||||
geyserLogger.debug("Legacy version of Minecraft (1.15.2 or older) detected; not using 3D biomes.");
|
||||
}
|
||||
|
||||
// Set if we need to use a different method for getting a player's locale
|
||||
SpigotCommandSender.setUseLegacyLocaleMethod(!isCompatible(Bukkit.getServer().getVersion(), "1.12.0"));
|
||||
|
||||
this.geyserWorldManager = new GeyserSpigotWorldManager(isLegacy, use3dBiomes, isViaVersion);
|
||||
GeyserSpigotBlockPlaceListener blockPlaceListener = new GeyserSpigotBlockPlaceListener(connector, isLegacy, isViaVersion);
|
||||
|
||||
Bukkit.getServer().getPluginManager().registerEvents(blockPlaceListener, this);
|
||||
|
||||
this.getCommand("geyser").setExecutor(new GeyserSpigotCommandExecutor(connector));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDisable() {
|
||||
if (connector != null)
|
||||
connector.shutdown();
|
||||
}
|
||||
|
||||
@Override
|
||||
public GeyserSpigotConfiguration getGeyserConfig() {
|
||||
return geyserConfig;
|
||||
}
|
||||
|
||||
@Override
|
||||
public GeyserSpigotLogger getGeyserLogger() {
|
||||
return geyserLogger;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandManager getGeyserCommandManager() {
|
||||
return this.geyserCommandManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IGeyserPingPassthrough getGeyserPingPassthrough() {
|
||||
return geyserSpigotPingPassthrough;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WorldManager getWorldManager() {
|
||||
return this.geyserWorldManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Path getConfigFolder() {
|
||||
return getDataFolder().toPath();
|
||||
}
|
||||
|
||||
public boolean isCompatible(String version, String whichVersion) {
|
||||
int[] currentVersion = parseVersion(version);
|
||||
int[] otherVersion = parseVersion(whichVersion);
|
||||
int length = Math.max(currentVersion.length, otherVersion.length);
|
||||
for (int index = 0; index < length; index = index + 1) {
|
||||
int self = (index < currentVersion.length) ? currentVersion[index] : 0;
|
||||
int other = (index < otherVersion.length) ? otherVersion[index] : 0;
|
||||
|
||||
if (self != other) {
|
||||
return (self - other) > 0;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private int[] parseVersion(String versionParam) {
|
||||
versionParam = (versionParam == null) ? "" : versionParam;
|
||||
if (versionParam.contains("(MC: ")) {
|
||||
versionParam = versionParam.split("\\(MC: ")[1];
|
||||
versionParam = versionParam.split("\\)")[0];
|
||||
}
|
||||
String[] stringArray = versionParam.split("[_.-]");
|
||||
int[] temp = new int[stringArray.length];
|
||||
for (int index = 0; index <= (stringArray.length - 1); index = index + 1) {
|
||||
String t = stringArray[index].replaceAll("\\D", "");
|
||||
try {
|
||||
temp[index] = Integer.parseInt(t);
|
||||
} catch(NumberFormatException ex) {
|
||||
temp[index] = 0;
|
||||
}
|
||||
}
|
||||
return temp;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BootstrapDumpInfo getDumpInfo() {
|
||||
return new GeyserSpigotDumpInfo();
|
||||
}
|
||||
}
|
|
@ -1,72 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2020 GeyserMC. http://geysermc.org
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
* @author GeyserMC
|
||||
* @link https://github.com/GeyserMC/Geyser
|
||||
*/
|
||||
|
||||
package org.geysermc.platform.spigot.world;
|
||||
|
||||
import com.nukkitx.math.vector.Vector3f;
|
||||
import com.nukkitx.protocol.bedrock.data.SoundEvent;
|
||||
import com.nukkitx.protocol.bedrock.packet.LevelSoundEventPacket;
|
||||
import lombok.AllArgsConstructor;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.block.BlockPlaceEvent;
|
||||
import org.geysermc.connector.GeyserConnector;
|
||||
import org.geysermc.connector.network.session.GeyserSession;
|
||||
import org.geysermc.connector.network.translators.world.block.BlockTranslator;
|
||||
|
||||
@AllArgsConstructor
|
||||
public class GeyserSpigotBlockPlaceListener implements Listener {
|
||||
|
||||
private final GeyserConnector connector;
|
||||
private final boolean isLegacy;
|
||||
private final boolean isViaVersion;
|
||||
|
||||
@EventHandler
|
||||
public void place(final BlockPlaceEvent event) {
|
||||
for (GeyserSession session : connector.getPlayers()) {
|
||||
if (event.getPlayer() == Bukkit.getPlayer(session.getPlayerEntity().getUsername())) {
|
||||
LevelSoundEventPacket placeBlockSoundPacket = new LevelSoundEventPacket();
|
||||
placeBlockSoundPacket.setSound(SoundEvent.PLACE);
|
||||
placeBlockSoundPacket.setPosition(Vector3f.from(event.getBlockPlaced().getX(), event.getBlockPlaced().getY(), event.getBlockPlaced().getZ()));
|
||||
placeBlockSoundPacket.setBabySound(false);
|
||||
String javaBlockId;
|
||||
if (isLegacy) {
|
||||
javaBlockId = BlockTranslator.getJavaIdBlockMap().inverse().get(GeyserSpigotWorldManager.getLegacyBlock(session,
|
||||
event.getBlockPlaced().getX(), event.getBlockPlaced().getY(), event.getBlockPlaced().getZ(), isViaVersion));
|
||||
} else {
|
||||
javaBlockId = event.getBlockPlaced().getBlockData().getAsString();
|
||||
}
|
||||
placeBlockSoundPacket.setExtraData(BlockTranslator.getBedrockBlockId(BlockTranslator.getJavaIdBlockMap().getOrDefault(javaBlockId, 0)));
|
||||
placeBlockSoundPacket.setIdentifier(":");
|
||||
session.sendUpstreamPacket(placeBlockSoundPacket);
|
||||
session.setLastBlockPlacePosition(null);
|
||||
session.setLastBlockPlacedId(null);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -1,257 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2020 GeyserMC. http://geysermc.org
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
* @author GeyserMC
|
||||
* @link https://github.com/GeyserMC/Geyser
|
||||
*/
|
||||
|
||||
package org.geysermc.platform.spigot.world;
|
||||
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.github.steveice10.mc.protocol.MinecraftConstants;
|
||||
import com.github.steveice10.mc.protocol.data.game.chunk.Chunk;
|
||||
import it.unimi.dsi.fastutil.ints.Int2IntMap;
|
||||
import it.unimi.dsi.fastutil.ints.Int2IntOpenHashMap;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.block.Biome;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.geysermc.connector.GeyserConnector;
|
||||
import org.geysermc.connector.network.session.GeyserSession;
|
||||
import org.geysermc.connector.network.translators.world.GeyserWorldManager;
|
||||
import org.geysermc.connector.network.translators.world.block.BlockTranslator;
|
||||
import org.geysermc.connector.utils.FileUtils;
|
||||
import org.geysermc.connector.utils.GameRule;
|
||||
import org.geysermc.connector.utils.LanguageUtils;
|
||||
import us.myles.ViaVersion.api.Pair;
|
||||
import us.myles.ViaVersion.api.Via;
|
||||
import us.myles.ViaVersion.api.data.MappingData;
|
||||
import us.myles.ViaVersion.api.minecraft.Position;
|
||||
import us.myles.ViaVersion.api.protocol.Protocol;
|
||||
import us.myles.ViaVersion.api.protocol.ProtocolRegistry;
|
||||
import us.myles.ViaVersion.api.protocol.ProtocolVersion;
|
||||
import us.myles.ViaVersion.protocols.protocol1_13to1_12_2.Protocol1_13To1_12_2;
|
||||
import us.myles.ViaVersion.protocols.protocol1_13to1_12_2.storage.BlockStorage;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.util.List;
|
||||
|
||||
public class GeyserSpigotWorldManager extends GeyserWorldManager {
|
||||
/**
|
||||
* The current client protocol version for ViaVersion usage.
|
||||
*/
|
||||
private static final int CLIENT_PROTOCOL_VERSION = MinecraftConstants.PROTOCOL_VERSION;
|
||||
|
||||
/**
|
||||
* Whether the server is pre-1.13.
|
||||
*/
|
||||
private final boolean isLegacy;
|
||||
/**
|
||||
* Whether the server is pre-1.16 and therefore does not support 3D biomes on an API level guaranteed.
|
||||
*/
|
||||
private final boolean use3dBiomes;
|
||||
/**
|
||||
* You need ViaVersion to connect to an older server with Geyser.
|
||||
* However, we still check for ViaVersion in case there's some other way that gets Geyser on a pre-1.13 Bukkit server
|
||||
*/
|
||||
private final boolean isViaVersion;
|
||||
/**
|
||||
* Stores a list of {@link Biome} ordinal numbers to Minecraft biome numeric IDs.
|
||||
*
|
||||
* Working with the Biome enum in Spigot poses two problems:
|
||||
* 1: The Biome enum values change in both order and names over the years.
|
||||
* 2: There is no way to get the Minecraft biome ID from the name itself with Spigot.
|
||||
* To solve both of these problems, we store a JSON file of every Biome enum that has existed,
|
||||
* along with its 1.16 biome number.
|
||||
*
|
||||
* The key is the Spigot Biome ordinal; the value is the Minecraft Java biome numerical ID
|
||||
*/
|
||||
private final Int2IntMap biomeToIdMap = new Int2IntOpenHashMap(Biome.values().length);
|
||||
|
||||
public GeyserSpigotWorldManager(boolean isLegacy, boolean use3dBiomes, boolean isViaVersion) {
|
||||
this.isLegacy = isLegacy;
|
||||
this.use3dBiomes = use3dBiomes;
|
||||
this.isViaVersion = isViaVersion;
|
||||
|
||||
// Load the values into the biome-to-ID map
|
||||
InputStream biomeStream = FileUtils.getResource("biomes.json");
|
||||
JsonNode biomes;
|
||||
try {
|
||||
biomes = GeyserConnector.JSON_MAPPER.readTree(biomeStream);
|
||||
} catch (Exception e) {
|
||||
throw new AssertionError(LanguageUtils.getLocaleStringLog("geyser.toolbox.fail.runtime_java"), e);
|
||||
}
|
||||
// Only load in the biomes that are present in this version of Minecraft
|
||||
for (Biome enumBiome : Biome.values()) {
|
||||
JsonNode biome = biomes.get(enumBiome.toString());
|
||||
if (biome != null) {
|
||||
biomeToIdMap.put(enumBiome.ordinal(), biome.intValue());
|
||||
} else {
|
||||
GeyserConnector.getInstance().getLogger().debug("No biome mapping found for " + enumBiome.toString() +
|
||||
", defaulting to 0");
|
||||
biomeToIdMap.put(enumBiome.ordinal(), 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getBlockAt(GeyserSession session, int x, int y, int z) {
|
||||
Player bukkitPlayer;
|
||||
if ((this.isLegacy && !this.isViaVersion)
|
||||
|| session.getPlayerEntity() == null
|
||||
|| (bukkitPlayer = Bukkit.getPlayer(session.getPlayerEntity().getUsername())) == null) {
|
||||
return BlockTranslator.JAVA_AIR_ID;
|
||||
}
|
||||
World world = bukkitPlayer.getWorld();
|
||||
if (isLegacy) {
|
||||
return getLegacyBlock(session, x, y, z, true);
|
||||
}
|
||||
//TODO possibly: detect server version for all versions and use ViaVersion for block state mappings like below
|
||||
return BlockTranslator.getJavaIdBlockMap().getOrDefault(world.getBlockAt(x, y, z).getBlockData().getAsString(), 0);
|
||||
}
|
||||
|
||||
public static int getLegacyBlock(GeyserSession session, int x, int y, int z, boolean isViaVersion) {
|
||||
if (isViaVersion) {
|
||||
Player bukkitPlayer = Bukkit.getPlayer(session.getPlayerEntity().getUsername());
|
||||
// Get block entity storage
|
||||
BlockStorage storage = Via.getManager().getConnection(bukkitPlayer.getUniqueId()).get(BlockStorage.class);
|
||||
return getLegacyBlock(storage, bukkitPlayer.getWorld(), x, y, z);
|
||||
} else {
|
||||
return BlockTranslator.JAVA_AIR_ID;
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
public static int getLegacyBlock(BlockStorage storage, World world, int x, int y, int z) {
|
||||
Block block = world.getBlockAt(x, y, z);
|
||||
// Black magic that gets the old block state ID
|
||||
int blockId = (block.getType().getId() << 4) | (block.getData() & 0xF);
|
||||
// Convert block state from old version (1.12.2) -> 1.13 -> 1.13.1 -> 1.14 -> 1.15 -> 1.16 -> 1.16.2
|
||||
blockId = ProtocolRegistry.getProtocol(Protocol1_13To1_12_2.class).getMappingData().getNewBlockId(blockId);
|
||||
List<Pair<Integer, Protocol>> protocolList = ProtocolRegistry.getProtocolPath(CLIENT_PROTOCOL_VERSION,
|
||||
ProtocolVersion.v1_13.getId());
|
||||
// Translate block entity differences - some information was stored in block tags and not block states
|
||||
if (storage.isWelcome(blockId)) { // No getOrDefault method
|
||||
BlockStorage.ReplacementData data = storage.get(new Position(x, (short) y, z));
|
||||
if (data != null && data.getReplacement() != -1) {
|
||||
blockId = data.getReplacement();
|
||||
}
|
||||
}
|
||||
for (int i = protocolList.size() - 1; i >= 0; i--) {
|
||||
MappingData mappingData = protocolList.get(i).getValue().getMappingData();
|
||||
if (mappingData != null) {
|
||||
blockId = mappingData.getNewBlockStateId(blockId);
|
||||
}
|
||||
}
|
||||
return blockId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void getBlocksInSection(GeyserSession session, int x, int y, int z, Chunk chunk) {
|
||||
Player bukkitPlayer;
|
||||
if ((this.isLegacy && !this.isViaVersion)
|
||||
|| session.getPlayerEntity() == null
|
||||
|| (bukkitPlayer = Bukkit.getPlayer(session.getPlayerEntity().getUsername())) == null) {
|
||||
return;
|
||||
}
|
||||
World world = bukkitPlayer.getWorld();
|
||||
if (this.isLegacy) {
|
||||
// Get block entity storage
|
||||
BlockStorage storage = Via.getManager().getConnection(bukkitPlayer.getUniqueId()).get(BlockStorage.class);
|
||||
for (int blockY = 0; blockY < 16; blockY++) { // Cache-friendly iteration order
|
||||
for (int blockZ = 0; blockZ < 16; blockZ++) {
|
||||
for (int blockX = 0; blockX < 16; blockX++) {
|
||||
chunk.set(blockX, blockY, blockZ, getLegacyBlock(storage, world, (x << 4) + blockX, (y << 4) + blockY, (z << 4) + blockZ));
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
//TODO: see above TODO in getBlockAt
|
||||
for (int blockY = 0; blockY < 16; blockY++) { // Cache-friendly iteration order
|
||||
for (int blockZ = 0; blockZ < 16; blockZ++) {
|
||||
for (int blockX = 0; blockX < 16; blockX++) {
|
||||
Block block = world.getBlockAt((x << 4) + blockX, (y << 4) + blockY, (z << 4) + blockZ);
|
||||
int id = BlockTranslator.getJavaIdBlockMap().getOrDefault(block.getBlockData().getAsString(), BlockTranslator.JAVA_AIR_ID);
|
||||
chunk.set(blockX, blockY, blockZ, id);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasMoreBlockDataThanChunkCache() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("deprecation")
|
||||
public int[] getBiomeDataAt(GeyserSession session, int x, int z) {
|
||||
if (session.getPlayerEntity() == null) {
|
||||
return new int[1024];
|
||||
}
|
||||
int[] biomeData = new int[1024];
|
||||
World world = Bukkit.getPlayer(session.getPlayerEntity().getUsername()).getWorld();
|
||||
int chunkX = x << 4;
|
||||
int chunkZ = z << 4;
|
||||
int chunkXmax = chunkX + 16;
|
||||
int chunkZmax = chunkZ + 16;
|
||||
// 3D biomes didn't exist until 1.15
|
||||
if (use3dBiomes) {
|
||||
for (int localX = chunkX; localX < chunkXmax; localX += 4) {
|
||||
for (int localY = 0; localY < 255; localY += + 4) {
|
||||
for (int localZ = chunkZ; localZ < chunkZmax; localZ += 4) {
|
||||
// Index is based on wiki.vg's index requirements
|
||||
final int i = ((localY >> 2) & 63) << 4 | ((localZ >> 2) & 3) << 2 | ((localX >> 2) & 3);
|
||||
biomeData[i] = biomeToIdMap.getOrDefault(world.getBiome(localX, localY, localZ).ordinal(), 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Looks like the same code, but we're not checking the Y coordinate here
|
||||
for (int localX = chunkX; localX < chunkXmax; localX += 4) {
|
||||
for (int localY = 0; localY < 255; localY += + 4) {
|
||||
for (int localZ = chunkZ; localZ < chunkZmax; localZ += 4) {
|
||||
// Index is based on wiki.vg's index requirements
|
||||
final int i = ((localY >> 2) & 63) << 4 | ((localZ >> 2) & 3) << 2 | ((localX >> 2) & 3);
|
||||
biomeData[i] = biomeToIdMap.getOrDefault(world.getBiome(localX, localZ).ordinal(), 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return biomeData;
|
||||
}
|
||||
|
||||
public Boolean getGameRuleBool(GeyserSession session, GameRule gameRule) {
|
||||
return Boolean.parseBoolean(Bukkit.getPlayer(session.getPlayerEntity().getUsername()).getWorld().getGameRuleValue(gameRule.getJavaID()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getGameRuleInt(GeyserSession session, GameRule gameRule) {
|
||||
return Integer.parseInt(Bukkit.getPlayer(session.getPlayerEntity().getUsername()).getWorld().getGameRuleValue(gameRule.getJavaID()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasPermission(GeyserSession session, String permission) {
|
||||
return Bukkit.getPlayer(session.getPlayerEntity().getUsername()).hasPermission(permission);
|
||||
}
|
||||
}
|
|
@ -1,155 +0,0 @@
|
|||
{
|
||||
"MUTATED_ICE_FLATS" : 140,
|
||||
"MUTATED_TAIGA" : 133,
|
||||
"SAVANNA_PLATEAU_MOUNTAINS" : 164,
|
||||
"DEEP_WARM_OCEAN" : 47,
|
||||
"REDWOOD_TAIGA_HILLS" : 33,
|
||||
"THE_VOID" : 127,
|
||||
"COLD_TAIGA_MOUNTAINS" : 158,
|
||||
"BAMBOO_JUNGLE_HILLS" : 169,
|
||||
"MOUNTAINS" : 3,
|
||||
"MESA_PLATEAU" : 39,
|
||||
"SNOWY_TAIGA_HILLS" : 31,
|
||||
"DEEP_FROZEN_OCEAN" : 50,
|
||||
"EXTREME_HILLS" : 3,
|
||||
"BIRCH_FOREST_MOUNTAINS" : 155,
|
||||
"FOREST" : 4,
|
||||
"BIRCH_FOREST" : 27,
|
||||
"SNOWY_TUNDRA" : 12,
|
||||
"ICE_SPIKES" : 140,
|
||||
"FROZEN_OCEAN" : 10,
|
||||
"WARPED_FOREST" : 172,
|
||||
"WOODED_BADLANDS_PLATEAU" : 38,
|
||||
"BADLANDS_PLATEAU" : 39,
|
||||
"ICE_PLAINS_SPIKES" : 140,
|
||||
"MEGA_TAIGA" : 32,
|
||||
"MUTATED_SAVANNA_ROCK" : 164,
|
||||
"SAVANNA_PLATEAU" : 36,
|
||||
"DARK_FOREST_HILLS" : 157,
|
||||
"END_MIDLANDS" : 41,
|
||||
"SHATTERED_SAVANNA_PLATEAU" : 164,
|
||||
"SAVANNA" : 35,
|
||||
"MUSHROOM_ISLAND_SHORE" : 15,
|
||||
"SWAMP" : 6,
|
||||
"ICE_MOUNTAINS" : 13,
|
||||
"BEACH" : 16,
|
||||
"MUTATED_MESA_CLEAR_ROCK" : 167,
|
||||
"END_HIGHLANDS" : 42,
|
||||
"COLD_BEACH" : 26,
|
||||
"JUNGLE" : 21,
|
||||
"MUTATED_TAIGA_COLD" : 158,
|
||||
"TALL_BIRCH_HILLS" : 156,
|
||||
"DARK_FOREST" : 29,
|
||||
"WOODED_HILLS" : 18,
|
||||
"HELL" : 8,
|
||||
"MUTATED_REDWOOD_TAIGA" : 160,
|
||||
"MESA_PLATEAU_FOREST" : 38,
|
||||
"MUSHROOM_ISLAND" : 14,
|
||||
"BADLANDS" : 37,
|
||||
"END_BARRENS" : 43,
|
||||
"MUTATED_EXTREME_HILLS_WITH_TREES" : 162,
|
||||
"MUTATED_JUNGLE_EDGE" : 151,
|
||||
"MODIFIED_BADLANDS_PLATEAU" : 167,
|
||||
"ROOFED_FOREST_MOUNTAINS" : 157,
|
||||
"SOUL_SAND_VALLEY" : 170,
|
||||
"DESERT" : 2,
|
||||
"MUTATED_PLAINS" : 129,
|
||||
"MUTATED_BIRCH_FOREST" : 155,
|
||||
"WOODED_MOUNTAINS" : 34,
|
||||
"TAIGA_HILLS" : 19,
|
||||
"BAMBOO_JUNGLE" : 168,
|
||||
"SWAMPLAND_MOUNTAINS" : 134,
|
||||
"DESERT_MOUNTAINS" : 130,
|
||||
"REDWOOD_TAIGA" : 32,
|
||||
"MUSHROOM_FIELDS" : 14,
|
||||
"GIANT_TREE_TAIGA_HILLS" : 33,
|
||||
"PLAINS" : 1,
|
||||
"JUNGLE_EDGE" : 23,
|
||||
"SAVANNA_MOUNTAINS" : 163,
|
||||
"DEEP_COLD_OCEAN" : 49,
|
||||
"DESERT_LAKES" : 130,
|
||||
"MOUNTAIN_EDGE" : 20,
|
||||
"SNOWY_MOUNTAINS" : 13,
|
||||
"MESA_PLATEAU_MOUNTAINS" : 167,
|
||||
"JUNGLE_MOUNTAINS" : 149,
|
||||
"SMALLER_EXTREME_HILLS" : 20,
|
||||
"MESA_PLATEAU_FOREST_MOUNTAINS" : 166,
|
||||
"NETHER_WASTES" : 8,
|
||||
"BIRCH_FOREST_HILLS_MOUNTAINS" : 156,
|
||||
"MUTATED_JUNGLE" : 149,
|
||||
"WARM_OCEAN" : 44,
|
||||
"DEEP_OCEAN" : 24,
|
||||
"STONE_BEACH" : 25,
|
||||
"MODIFIED_JUNGLE" : 149,
|
||||
"MUTATED_SAVANNA" : 163,
|
||||
"TAIGA_COLD_HILLS" : 31,
|
||||
"OCEAN" : 0,
|
||||
"SMALL_END_ISLANDS" : 40,
|
||||
"MUSHROOM_FIELD_SHORE" : 15,
|
||||
"GRAVELLY_MOUNTAINS" : 131,
|
||||
"FROZEN_RIVER" : 11,
|
||||
"TAIGA_COLD" : 30,
|
||||
"BASALT_DELTAS" : 173,
|
||||
"EXTREME_HILLS_WITH_TREES" : 34,
|
||||
"MEGA_TAIGA_HILLS" : 33,
|
||||
"MUTATED_FOREST" : 132,
|
||||
"MUTATED_BIRCH_FOREST_HILLS" : 156,
|
||||
"SKY" : 9,
|
||||
"LUKEWARM_OCEAN" : 45,
|
||||
"EXTREME_HILLS_MOUNTAINS" : 131,
|
||||
"COLD_TAIGA_HILLS" : 31,
|
||||
"THE_END" : 9,
|
||||
"SUNFLOWER_PLAINS" : 129,
|
||||
"SAVANNA_ROCK" : 36,
|
||||
"ERODED_BADLANDS" : 165,
|
||||
"STONE_SHORE" : 25,
|
||||
"EXTREME_HILLS_PLUS_MOUNTAINS" : 162,
|
||||
"CRIMSON_FOREST" : 171,
|
||||
"VOID" : 127,
|
||||
"SNOWY_TAIGA" : 30,
|
||||
"SNOWY_TAIGA_MOUNTAINS" : 158,
|
||||
"FLOWER_FOREST" : 132,
|
||||
"COLD_OCEAN" : 46,
|
||||
"BEACHES" : 16,
|
||||
"MESA" : 37,
|
||||
"MUSHROOM_SHORE" : 15,
|
||||
"MESA_CLEAR_ROCK" : 39,
|
||||
"NETHER" : 8,
|
||||
"ICE_PLAINS" : 12,
|
||||
"SHATTERED_SAVANNA" : 163,
|
||||
"ROOFED_FOREST" : 29,
|
||||
"GIANT_SPRUCE_TAIGA_HILLS" : 161,
|
||||
"SNOWY_BEACH" : 26,
|
||||
"MESA_BRYCE" : 165,
|
||||
"JUNGLE_EDGE_MOUNTAINS" : 151,
|
||||
"MUTATED_DESERT" : 130,
|
||||
"MODIFIED_GRAVELLY_MOUNTAINS" : 158,
|
||||
"MEGA_SPRUCE_TAIGA" : 160,
|
||||
"TAIGA_MOUNTAINS" : 133,
|
||||
"SMALL_MOUNTAINS" : 20,
|
||||
"EXTREME_HILLS_PLUS" : 34,
|
||||
"GIANT_SPRUCE_TAIGA" : 160,
|
||||
"FOREST_HILLS" : 18,
|
||||
"DESERT_HILLS" : 17,
|
||||
"MUTATED_REDWOOD_TAIGA_HILLS" : 161,
|
||||
"MEGA_SPRUCE_TAIGA_HILLS" : 161,
|
||||
"RIVER" : 7,
|
||||
"GIANT_TREE_TAIGA" : 32,
|
||||
"SWAMPLAND" : 6,
|
||||
"JUNGLE_HILLS" : 22,
|
||||
"TALL_BIRCH_FOREST" : 155,
|
||||
"DEEP_LUKEWARM_OCEAN" : 48,
|
||||
"MESA_ROCK" : 38,
|
||||
"SWAMP_HILLS" : 134,
|
||||
"MODIFIED_WOODED_BADLANDS_PLATEAU" : 166,
|
||||
"MODIFIED_JUNGLE_EDGE" : 151,
|
||||
"BIRCH_FOREST_HILLS" : 28,
|
||||
"COLD_TAIGA" : 30,
|
||||
"TAIGA" : 5,
|
||||
"MUTATED_MESA_ROCK" : 166,
|
||||
"MUTATED_SWAMPLAND" : 134,
|
||||
"ICE_FLATS" : 12,
|
||||
"MUTATED_ROOFED_FOREST" : 157,
|
||||
"MUTATED_MESA" : 165,
|
||||
"MUTATED_EXTREME_HILLS" : 131
|
||||
}
|
|
@ -1,11 +1,42 @@
|
|||
main: org.geysermc.platform.spigot.GeyserSpigotPlugin
|
||||
main: org.geysermc.geyser.platform.spigot.GeyserSpigotPlugin
|
||||
name: ${outputName}-Spigot
|
||||
author: ${project.organization.name}
|
||||
website: ${project.organization.url}
|
||||
version: ${project.version}
|
||||
softdepend: ["ViaVersion"]
|
||||
softdepend: ["ViaVersion", "floodgate"]
|
||||
api-version: 1.13
|
||||
commands:
|
||||
geyser:
|
||||
description: The main command for Geyser.
|
||||
usage: /geyser help
|
||||
usage: /geyser <subcommand>
|
||||
permissions:
|
||||
geyser.command.help:
|
||||
description: Shows help for all registered commands.
|
||||
default: true
|
||||
geyser.command.offhand:
|
||||
description: Puts an items in your offhand.
|
||||
default: true
|
||||
geyser.command.advancements:
|
||||
description: Shows the advancements of the player on the server.
|
||||
default: true
|
||||
geyser.command.tooltips:
|
||||
description: Toggles showing advanced tooltips on your items.
|
||||
default: true
|
||||
geyser.command.statistics:
|
||||
description: Shows the statistics of the player on the server.
|
||||
default: true
|
||||
geyser.command.settings:
|
||||
description: Modify user settings
|
||||
default: true
|
||||
geyser.command.list:
|
||||
description: List all players connected through Geyser.
|
||||
default: op
|
||||
geyser.command.dump:
|
||||
description: Dumps Geyser debug information for bug reports.
|
||||
default: op
|
||||
geyser.command.reload:
|
||||
description: Reloads the Geyser configurations. Kicks all players when used!
|
||||
default: false
|
||||
geyser.command.version:
|
||||
description: Shows the current Geyser version and checks for updates.
|
||||
default: op
|
||||
|
|
|
@ -6,15 +6,15 @@
|
|||
<parent>
|
||||
<groupId>org.geysermc</groupId>
|
||||
<artifactId>bootstrap-parent</artifactId>
|
||||
<version>1.2.0-SNAPSHOT</version>
|
||||
<version>2.0.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>bootstrap-sponge</artifactId>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.geysermc</groupId>
|
||||
<artifactId>connector</artifactId>
|
||||
<version>1.2.0-SNAPSHOT</version>
|
||||
<artifactId>core</artifactId>
|
||||
<version>2.0.0-SNAPSHOT</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
|
@ -40,7 +40,7 @@
|
|||
<configuration>
|
||||
<archive>
|
||||
<manifestEntries>
|
||||
<Main-Class>org.geysermc.platform.sponge.GeyserSpongeMain</Main-Class>
|
||||
<Main-Class>org.geysermc.geyser.platform.sponge.GeyserSpongeMain</Main-Class>
|
||||
</manifestEntries>
|
||||
</archive>
|
||||
</configuration>
|
||||
|
@ -48,7 +48,7 @@
|
|||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-shade-plugin</artifactId>
|
||||
<version>3.2.1</version>
|
||||
<version>3.3.0-SNAPSHOT</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>package</phase>
|
||||
|
@ -59,35 +59,27 @@
|
|||
<relocations>
|
||||
<relocation>
|
||||
<pattern>com.fasterxml.jackson</pattern>
|
||||
<shadedPattern>org.geysermc.platform.sponge.shaded.jackson</shadedPattern>
|
||||
<shadedPattern>org.geysermc.geyser.platform.sponge.shaded.jackson</shadedPattern>
|
||||
</relocation>
|
||||
<relocation>
|
||||
<pattern>io.netty</pattern>
|
||||
<shadedPattern>org.geysermc.platform.sponge.shaded.netty</shadedPattern>
|
||||
<shadedPattern>org.geysermc.geyser.platform.sponge.shaded.netty</shadedPattern>
|
||||
</relocation>
|
||||
<relocation>
|
||||
<pattern>it.unimi.dsi.fastutil</pattern>
|
||||
<shadedPattern>org.geysermc.platform.sponge.shaded.fastutil</shadedPattern>
|
||||
</relocation>
|
||||
<relocation>
|
||||
<pattern>org.reflections</pattern>
|
||||
<shadedPattern>org.geysermc.platform.sponge.shaded.reflections</shadedPattern>
|
||||
<shadedPattern>org.geysermc.geyser.platform.sponge.shaded.fastutil</shadedPattern>
|
||||
</relocation>
|
||||
<relocation>
|
||||
<pattern>com.google.common</pattern>
|
||||
<shadedPattern>org.geysermc.platform.sponge.shaded.google.common</shadedPattern>
|
||||
<shadedPattern>org.geysermc.geyser.platform.sponge.shaded.google.common</shadedPattern>
|
||||
</relocation>
|
||||
<relocation>
|
||||
<pattern>com.google.guava</pattern>
|
||||
<shadedPattern>org.geysermc.platform.sponge.shaded.google.guava</shadedPattern>
|
||||
<shadedPattern>org.geysermc.geyser.platform.sponge.shaded.google.guava</shadedPattern>
|
||||
</relocation>
|
||||
<relocation>
|
||||
<pattern>org.dom4j</pattern>
|
||||
<shadedPattern>org.geysermc.platform.sponge.shaded.dom4j</shadedPattern>
|
||||
</relocation>
|
||||
<relocation>
|
||||
<pattern>net.kyori.adventure</pattern>
|
||||
<shadedPattern>org.geysermc.platform.sponge.shaded.adventure</shadedPattern>
|
||||
<pattern>net.kyori</pattern>
|
||||
<shadedPattern>org.geysermc.geyser.platform.sponge.shaded.kyori</shadedPattern>
|
||||
</relocation>
|
||||
</relocations>
|
||||
</configuration>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2020 GeyserMC. http://geysermc.org
|
||||
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
|
@ -23,9 +23,9 @@
|
|||
* @link https://github.com/GeyserMC/Geyser
|
||||
*/
|
||||
|
||||
package org.geysermc.platform.sponge;
|
||||
package org.geysermc.geyser.platform.sponge;
|
||||
|
||||
import org.geysermc.connector.configuration.GeyserJacksonConfiguration;
|
||||
import org.geysermc.geyser.configuration.GeyserJacksonConfiguration;
|
||||
|
||||
import java.nio.file.Path;
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2020 GeyserMC. http://geysermc.org
|
||||
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
|
@ -23,10 +23,10 @@
|
|||
* @link https://github.com/GeyserMC/Geyser
|
||||
*/
|
||||
|
||||
package org.geysermc.platform.sponge;
|
||||
package org.geysermc.geyser.platform.sponge;
|
||||
|
||||
import lombok.Getter;
|
||||
import org.geysermc.connector.dump.BootstrapDumpInfo;
|
||||
import org.geysermc.geyser.dump.BootstrapDumpInfo;
|
||||
import org.spongepowered.api.Platform;
|
||||
import org.spongepowered.api.Sponge;
|
||||
import org.spongepowered.api.plugin.PluginContainer;
|
||||
|
@ -36,13 +36,12 @@ import java.util.List;
|
|||
|
||||
@Getter
|
||||
public class GeyserSpongeDumpInfo extends BootstrapDumpInfo {
|
||||
|
||||
private String platformName;
|
||||
private String platformVersion;
|
||||
private boolean onlineMode;
|
||||
private String serverIP;
|
||||
private int serverPort;
|
||||
private List<PluginInfo> plugins;
|
||||
private final String platformName;
|
||||
private final String platformVersion;
|
||||
private final boolean onlineMode;
|
||||
private final String serverIP;
|
||||
private final int serverPort;
|
||||
private final List<PluginInfo> plugins;
|
||||
|
||||
GeyserSpongeDumpInfo() {
|
||||
super();
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2020 GeyserMC. http://geysermc.org
|
||||
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
|
@ -23,12 +23,12 @@
|
|||
* @link https://github.com/GeyserMC/Geyser
|
||||
*/
|
||||
|
||||
package org.geysermc.platform.sponge;
|
||||
package org.geysermc.geyser.platform.sponge;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import org.geysermc.connector.GeyserLogger;
|
||||
import org.geysermc.geyser.GeyserLogger;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
@AllArgsConstructor
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2020 GeyserMC. http://geysermc.org
|
||||
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
|
@ -23,11 +23,11 @@
|
|||
* @link https://github.com/GeyserMC/Geyser
|
||||
*/
|
||||
|
||||
package org.geysermc.platform.sponge;
|
||||
package org.geysermc.geyser.platform.sponge;
|
||||
|
||||
import org.geysermc.connector.common.main.IGeyserMain;
|
||||
import org.geysermc.geyser.GeyserMain;
|
||||
|
||||
public class GeyserSpongeMain extends IGeyserMain {
|
||||
public class GeyserSpongeMain extends GeyserMain {
|
||||
|
||||
public static void main(String[] args) {
|
||||
new GeyserSpongeMain().displayMessage();
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2020 GeyserMC. http://geysermc.org
|
||||
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
|
@ -23,11 +23,11 @@
|
|||
* @link https://github.com/GeyserMC/Geyser
|
||||
*/
|
||||
|
||||
package org.geysermc.platform.sponge;
|
||||
package org.geysermc.geyser.platform.sponge;
|
||||
|
||||
import com.github.steveice10.mc.protocol.MinecraftConstants;
|
||||
import org.geysermc.connector.common.ping.GeyserPingInfo;
|
||||
import org.geysermc.connector.ping.IGeyserPingPassthrough;
|
||||
import org.geysermc.geyser.ping.GeyserPingInfo;
|
||||
import org.geysermc.geyser.network.MinecraftProtocol;
|
||||
import org.geysermc.geyser.ping.IGeyserPingPassthrough;
|
||||
import org.spongepowered.api.MinecraftVersion;
|
||||
import org.spongepowered.api.Sponge;
|
||||
import org.spongepowered.api.event.SpongeEventFactory;
|
||||
|
@ -38,31 +38,29 @@ import org.spongepowered.api.network.status.StatusClient;
|
|||
import org.spongepowered.api.profile.GameProfile;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.net.Inet4Address;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.Optional;
|
||||
|
||||
public class GeyserSpongePingPassthrough implements IGeyserPingPassthrough {
|
||||
|
||||
private static final GeyserStatusClient STATUS_CLIENT = new GeyserStatusClient();
|
||||
private static final Cause CAUSE = Cause.of(EventContext.empty(), Sponge.getServer());
|
||||
|
||||
private static Method SpongeStatusResponse_create;
|
||||
|
||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||
@Override
|
||||
public GeyserPingInfo getPingInformation() {
|
||||
public GeyserPingInfo getPingInformation(InetSocketAddress inetSocketAddress) {
|
||||
// come on Sponge, this is in commons, why not expose it :(
|
||||
ClientPingServerEvent event;
|
||||
try {
|
||||
if(SpongeStatusResponse_create == null) {
|
||||
if (SpongeStatusResponse_create == null) {
|
||||
Class SpongeStatusResponse = Class.forName("org.spongepowered.common.network.status.SpongeStatusResponse");
|
||||
Class MinecraftServer = Class.forName("net.minecraft.server.MinecraftServer");
|
||||
SpongeStatusResponse_create = SpongeStatusResponse.getDeclaredMethod("create", MinecraftServer);
|
||||
}
|
||||
|
||||
Object response = SpongeStatusResponse_create.invoke(null, Sponge.getServer());
|
||||
event = SpongeEventFactory.createClientPingServerEvent(CAUSE, STATUS_CLIENT, (ClientPingServerEvent.Response) response);
|
||||
event = SpongeEventFactory.createClientPingServerEvent(CAUSE, new GeyserStatusClient(inetSocketAddress), (ClientPingServerEvent.Response) response);
|
||||
} catch (ReflectiveOperationException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
@ -75,8 +73,8 @@ public class GeyserSpongePingPassthrough implements IGeyserPingPassthrough {
|
|||
),
|
||||
new GeyserPingInfo.Version(
|
||||
event.getResponse().getVersion().getName(),
|
||||
MinecraftConstants.PROTOCOL_VERSION) // thanks for also not exposing this sponge
|
||||
);
|
||||
MinecraftProtocol.getJavaProtocolVersion()) // thanks for also not exposing this sponge
|
||||
);
|
||||
event.getResponse().getPlayers().get().getProfiles().stream()
|
||||
.map(GameProfile::getName)
|
||||
.map(op -> op.orElseThrow(IllegalStateException::new))
|
||||
|
@ -87,11 +85,15 @@ public class GeyserSpongePingPassthrough implements IGeyserPingPassthrough {
|
|||
@SuppressWarnings("NullableProblems")
|
||||
private static class GeyserStatusClient implements StatusClient {
|
||||
|
||||
private static final InetSocketAddress FAKE_REMOTE = new InetSocketAddress(Inet4Address.getLoopbackAddress(), 69);
|
||||
private final InetSocketAddress remote;
|
||||
|
||||
public GeyserStatusClient(InetSocketAddress remote) {
|
||||
this.remote = remote;
|
||||
}
|
||||
|
||||
@Override
|
||||
public InetSocketAddress getAddress() {
|
||||
return FAKE_REMOTE;
|
||||
return this.remote;
|
||||
}
|
||||
|
||||
@Override
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2020 GeyserMC. http://geysermc.org
|
||||
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
|
@ -23,21 +23,21 @@
|
|||
* @link https://github.com/GeyserMC/Geyser
|
||||
*/
|
||||
|
||||
package org.geysermc.platform.sponge;
|
||||
package org.geysermc.geyser.platform.sponge;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import org.geysermc.common.PlatformType;
|
||||
import org.geysermc.connector.GeyserConnector;
|
||||
import org.geysermc.connector.bootstrap.GeyserBootstrap;
|
||||
import org.geysermc.connector.command.CommandManager;
|
||||
import org.geysermc.connector.configuration.GeyserConfiguration;
|
||||
import org.geysermc.connector.dump.BootstrapDumpInfo;
|
||||
import org.geysermc.connector.ping.GeyserLegacyPingPassthrough;
|
||||
import org.geysermc.connector.ping.IGeyserPingPassthrough;
|
||||
import org.geysermc.connector.utils.FileUtils;
|
||||
import org.geysermc.connector.utils.LanguageUtils;
|
||||
import org.geysermc.platform.sponge.command.GeyserSpongeCommandExecutor;
|
||||
import org.geysermc.platform.sponge.command.GeyserSpongeCommandManager;
|
||||
import org.geysermc.geyser.GeyserImpl;
|
||||
import org.geysermc.geyser.GeyserBootstrap;
|
||||
import org.geysermc.geyser.command.CommandManager;
|
||||
import org.geysermc.geyser.configuration.GeyserConfiguration;
|
||||
import org.geysermc.geyser.dump.BootstrapDumpInfo;
|
||||
import org.geysermc.geyser.ping.GeyserLegacyPingPassthrough;
|
||||
import org.geysermc.geyser.ping.IGeyserPingPassthrough;
|
||||
import org.geysermc.geyser.util.FileUtils;
|
||||
import org.geysermc.geyser.text.GeyserLocale;
|
||||
import org.geysermc.geyser.platform.sponge.command.GeyserSpongeCommandExecutor;
|
||||
import org.geysermc.geyser.platform.sponge.command.GeyserSpongeCommandManager;
|
||||
import org.slf4j.Logger;
|
||||
import org.spongepowered.api.Sponge;
|
||||
import org.spongepowered.api.config.ConfigDir;
|
||||
|
@ -52,7 +52,7 @@ import java.net.InetSocketAddress;
|
|||
import java.nio.file.Path;
|
||||
import java.util.UUID;
|
||||
|
||||
@Plugin(id = "geyser", name = GeyserConnector.NAME + "-Sponge", version = GeyserConnector.VERSION, url = "https://geysermc.org", authors = "GeyserMC")
|
||||
@Plugin(id = "geyser", name = GeyserImpl.NAME + "-Sponge", version = GeyserImpl.VERSION, url = "https://geysermc.org", authors = "GeyserMC")
|
||||
public class GeyserSpongePlugin implements GeyserBootstrap {
|
||||
|
||||
@Inject
|
||||
|
@ -67,25 +67,29 @@ public class GeyserSpongePlugin implements GeyserBootstrap {
|
|||
private GeyserSpongeLogger geyserLogger;
|
||||
private IGeyserPingPassthrough geyserSpongePingPassthrough;
|
||||
|
||||
private GeyserConnector connector;
|
||||
private GeyserImpl geyser;
|
||||
|
||||
@Override
|
||||
public void onEnable() {
|
||||
GeyserLocale.init(this);
|
||||
|
||||
if (!configDir.exists())
|
||||
configDir.mkdirs();
|
||||
|
||||
File configFile = null;
|
||||
File configFile;
|
||||
try {
|
||||
configFile = FileUtils.fileOrCopiedFromResource(new File(configDir, "config.yml"), "config.yml", (file) -> file.replaceAll("generateduuid", UUID.randomUUID().toString()));
|
||||
configFile = FileUtils.fileOrCopiedFromResource(new File(configDir, "config.yml"), "config.yml",
|
||||
(file) -> file.replaceAll("generateduuid", UUID.randomUUID().toString()), this);
|
||||
} catch (IOException ex) {
|
||||
logger.warn(LanguageUtils.getLocaleStringLog("geyser.config.failed"));
|
||||
logger.error(GeyserLocale.getLocaleStringLog("geyser.config.failed"));
|
||||
ex.printStackTrace();
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
this.geyserConfig = FileUtils.loadConfig(configFile, GeyserSpongeConfiguration.class);
|
||||
} catch (IOException ex) {
|
||||
logger.warn(LanguageUtils.getLocaleStringLog("geyser.config.failed"));
|
||||
logger.warn(GeyserLocale.getLocaleStringLog("geyser.config.failed"));
|
||||
ex.printStackTrace();
|
||||
return;
|
||||
}
|
||||
|
@ -101,27 +105,27 @@ public class GeyserSpongePlugin implements GeyserBootstrap {
|
|||
}
|
||||
}
|
||||
|
||||
if (geyserConfig.getBedrock().isCloneRemotePort()){
|
||||
if (geyserConfig.getBedrock().isCloneRemotePort()) {
|
||||
geyserConfig.getBedrock().setPort(geyserConfig.getRemote().getPort());
|
||||
}
|
||||
|
||||
this.geyserLogger = new GeyserSpongeLogger(logger, geyserConfig.isDebugMode());
|
||||
GeyserConfiguration.checkGeyserConfiguration(geyserConfig, geyserLogger);
|
||||
this.connector = GeyserConnector.start(PlatformType.SPONGE, this);
|
||||
this.geyser = GeyserImpl.start(PlatformType.SPONGE, this);
|
||||
|
||||
if (geyserConfig.isLegacyPingPassthrough()) {
|
||||
this.geyserSpongePingPassthrough = GeyserLegacyPingPassthrough.init(connector);
|
||||
this.geyserSpongePingPassthrough = GeyserLegacyPingPassthrough.init(geyser);
|
||||
} else {
|
||||
this.geyserSpongePingPassthrough = new GeyserSpongePingPassthrough();
|
||||
}
|
||||
|
||||
this.geyserCommandManager = new GeyserSpongeCommandManager(Sponge.getCommandManager(), connector);
|
||||
Sponge.getCommandManager().register(this, new GeyserSpongeCommandExecutor(connector), "geyser");
|
||||
this.geyserCommandManager = new GeyserSpongeCommandManager(Sponge.getCommandManager(), geyser);
|
||||
Sponge.getCommandManager().register(this, new GeyserSpongeCommandExecutor(geyser), "geyser");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDisable() {
|
||||
connector.shutdown();
|
||||
geyser.shutdown();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -163,4 +167,9 @@ public class GeyserSpongePlugin implements GeyserBootstrap {
|
|||
public BootstrapDumpInfo getDumpInfo() {
|
||||
return new GeyserSpongeDumpInfo();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMinecraftServerVersion() {
|
||||
return Sponge.getPlatform().getMinecraftVersion().getName();
|
||||
}
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2020 GeyserMC. http://geysermc.org
|
||||
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
|
@ -23,15 +23,16 @@
|
|||
* @link https://github.com/GeyserMC/Geyser
|
||||
*/
|
||||
|
||||
package org.geysermc.platform.sponge.command;
|
||||
package org.geysermc.geyser.platform.sponge.command;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import org.geysermc.connector.GeyserConnector;
|
||||
import org.geysermc.connector.common.ChatColor;
|
||||
import org.geysermc.connector.command.GeyserCommand;
|
||||
import org.geysermc.connector.utils.LanguageUtils;
|
||||
import org.geysermc.geyser.GeyserImpl;
|
||||
import org.geysermc.geyser.command.CommandExecutor;
|
||||
import org.geysermc.geyser.command.CommandSender;
|
||||
import org.geysermc.geyser.command.GeyserCommand;
|
||||
import org.geysermc.geyser.text.ChatColor;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.geyser.text.GeyserLocale;
|
||||
import org.spongepowered.api.command.CommandCallable;
|
||||
import org.spongepowered.api.command.CommandException;
|
||||
import org.spongepowered.api.command.CommandResult;
|
||||
import org.spongepowered.api.command.CommandSource;
|
||||
import org.spongepowered.api.text.Text;
|
||||
|
@ -39,40 +40,49 @@ import org.spongepowered.api.world.Location;
|
|||
import org.spongepowered.api.world.World;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
@AllArgsConstructor
|
||||
public class GeyserSpongeCommandExecutor implements CommandCallable {
|
||||
public class GeyserSpongeCommandExecutor extends CommandExecutor implements CommandCallable {
|
||||
|
||||
private GeyserConnector connector;
|
||||
public GeyserSpongeCommandExecutor(GeyserImpl geyser) {
|
||||
super(geyser);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandResult process(CommandSource source, String arguments) throws CommandException {
|
||||
public CommandResult process(CommandSource source, String arguments) {
|
||||
CommandSender commandSender = new SpongeCommandSender(source);
|
||||
GeyserSession session = getGeyserSession(commandSender);
|
||||
|
||||
String[] args = arguments.split(" ");
|
||||
if (args.length > 0) {
|
||||
if (getCommand(args[0]) != null) {
|
||||
if (!source.hasPermission(getCommand(args[0]).getPermission())) {
|
||||
GeyserCommand command = getCommand(args[0]);
|
||||
if (command != null) {
|
||||
if (!source.hasPermission(command.getPermission())) {
|
||||
// Not ideal to use log here but we dont get a session
|
||||
source.sendMessage(Text.of(ChatColor.RED + LanguageUtils.getLocaleStringLog("geyser.bootstrap.command.permission_fail")));
|
||||
source.sendMessage(Text.of(ChatColor.RED + GeyserLocale.getLocaleStringLog("geyser.bootstrap.command.permission_fail")));
|
||||
return CommandResult.success();
|
||||
}
|
||||
getCommand(args[0]).execute(new SpongeCommandSender(source), args.length > 1 ? Arrays.copyOfRange(args, 1, args.length) : new String[0]);
|
||||
if (command.isBedrockOnly() && session == null) {
|
||||
source.sendMessage(Text.of(ChatColor.RED + GeyserLocale.getLocaleStringLog("geyser.bootstrap.command.bedrock_only")));
|
||||
return CommandResult.success();
|
||||
}
|
||||
getCommand(args[0]).execute(session, commandSender, args.length > 1 ? Arrays.copyOfRange(args, 1, args.length) : new String[0]);
|
||||
}
|
||||
} else {
|
||||
getCommand("help").execute(new SpongeCommandSender(source), new String[0]);
|
||||
getCommand("help").execute(session, commandSender, new String[0]);
|
||||
}
|
||||
return CommandResult.success();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getSuggestions(CommandSource source, String arguments, @Nullable Location<World> targetPosition) throws CommandException {
|
||||
public List<String> getSuggestions(CommandSource source, String arguments, @Nullable Location<World> targetPosition) {
|
||||
if (arguments.split(" ").length == 1) {
|
||||
return connector.getCommandManager().getCommandNames();
|
||||
return tabComplete(new SpongeCommandSender(source));
|
||||
}
|
||||
return new ArrayList<>();
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -94,8 +104,4 @@ public class GeyserSpongeCommandExecutor implements CommandCallable {
|
|||
public Text getUsage(CommandSource source) {
|
||||
return Text.of("/geyser help");
|
||||
}
|
||||
|
||||
private GeyserCommand getCommand(String label) {
|
||||
return connector.getCommandManager().getCommands().get(label);
|
||||
}
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2020 GeyserMC. http://geysermc.org
|
||||
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
|
@ -23,26 +23,27 @@
|
|||
* @link https://github.com/GeyserMC/Geyser
|
||||
*/
|
||||
|
||||
package org.geysermc.platform.sponge.command;
|
||||
package org.geysermc.geyser.platform.sponge.command;
|
||||
|
||||
import org.geysermc.connector.GeyserConnector;
|
||||
import org.geysermc.connector.command.CommandManager;
|
||||
import org.geysermc.geyser.GeyserImpl;
|
||||
import org.geysermc.geyser.command.CommandManager;
|
||||
import org.spongepowered.api.Sponge;
|
||||
import org.spongepowered.api.command.CommandMapping;
|
||||
import org.spongepowered.api.text.Text;
|
||||
|
||||
public class GeyserSpongeCommandManager extends CommandManager {
|
||||
private final org.spongepowered.api.command.CommandManager handle;
|
||||
|
||||
private org.spongepowered.api.command.CommandManager handle;
|
||||
|
||||
public GeyserSpongeCommandManager(org.spongepowered.api.command.CommandManager handle, GeyserConnector connector) {
|
||||
super(connector);
|
||||
public GeyserSpongeCommandManager(org.spongepowered.api.command.CommandManager handle, GeyserImpl geyser) {
|
||||
super(geyser);
|
||||
|
||||
this.handle = handle;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription(String command) {
|
||||
return handle.get(command).map(CommandMapping::getCallable).map(callable -> callable.getShortDescription(Sponge.getServer().getConsole()).orElse(Text.EMPTY)).orElse(Text.EMPTY).toPlain();
|
||||
return handle.get(command).map(CommandMapping::getCallable)
|
||||
.map(callable -> callable.getShortDescription(Sponge.getServer().getConsole()).orElse(Text.EMPTY))
|
||||
.orElse(Text.EMPTY).toPlain();
|
||||
}
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2020 GeyserMC. http://geysermc.org
|
||||
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
|
@ -23,11 +23,11 @@
|
|||
* @link https://github.com/GeyserMC/Geyser
|
||||
*/
|
||||
|
||||
package org.geysermc.platform.sponge.command;
|
||||
package org.geysermc.geyser.platform.sponge.command;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
|
||||
import org.geysermc.connector.command.CommandSender;
|
||||
import org.geysermc.geyser.command.CommandSender;
|
||||
import org.spongepowered.api.command.CommandSource;
|
||||
import org.spongepowered.api.command.source.ConsoleSource;
|
||||
import org.spongepowered.api.text.Text;
|
||||
|
@ -38,7 +38,7 @@ public class SpongeCommandSender implements CommandSender {
|
|||
private CommandSource handle;
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
public String name() {
|
||||
return handle.getName();
|
||||
}
|
||||
|
||||
|
@ -51,4 +51,9 @@ public class SpongeCommandSender implements CommandSender {
|
|||
public boolean isConsole() {
|
||||
return handle instanceof ConsoleSource;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasPermission(String permission) {
|
||||
return handle.hasPermission(permission);
|
||||
}
|
||||
}
|
|
@ -6,15 +6,19 @@
|
|||
<parent>
|
||||
<groupId>org.geysermc</groupId>
|
||||
<artifactId>bootstrap-parent</artifactId>
|
||||
<version>1.2.0-SNAPSHOT</version>
|
||||
<version>2.0.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>bootstrap-standalone</artifactId>
|
||||
|
||||
<properties>
|
||||
<log4j.version>2.16.0</log4j.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.geysermc</groupId>
|
||||
<artifactId>connector</artifactId>
|
||||
<version>1.2.0-SNAPSHOT</version>
|
||||
<artifactId>core</artifactId>
|
||||
<version>2.0.0-SNAPSHOT</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
|
@ -43,32 +47,32 @@
|
|||
<dependency>
|
||||
<groupId>org.jline</groupId>
|
||||
<artifactId>jline-terminal</artifactId>
|
||||
<version>3.9.0</version>
|
||||
<version>3.20.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jline</groupId>
|
||||
<artifactId>jline-terminal-jna</artifactId>
|
||||
<version>3.9.0</version>
|
||||
<version>3.20.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jline</groupId>
|
||||
<artifactId>jline-reader</artifactId>
|
||||
<version>3.9.0</version>
|
||||
<version>3.20.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.logging.log4j</groupId>
|
||||
<artifactId>log4j-api</artifactId>
|
||||
<version>2.13.1</version>
|
||||
<version>${log4j.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.logging.log4j</groupId>
|
||||
<artifactId>log4j-core</artifactId>
|
||||
<version>2.13.2</version>
|
||||
<version>${log4j.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.logging.log4j</groupId>
|
||||
<artifactId>log4j-slf4j18-impl</artifactId>
|
||||
<version>2.13.1</version>
|
||||
<version>${log4j.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<build>
|
||||
|
@ -81,7 +85,7 @@
|
|||
<configuration>
|
||||
<archive>
|
||||
<manifestEntries>
|
||||
<Main-Class>org.geysermc.platform.standalone.GeyserStandaloneBootstrap</Main-Class>
|
||||
<Main-Class>org.geysermc.geyser.platform.standalone.GeyserStandaloneBootstrap</Main-Class>
|
||||
</manifestEntries>
|
||||
</archive>
|
||||
</configuration>
|
||||
|
@ -89,7 +93,7 @@
|
|||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-shade-plugin</artifactId>
|
||||
<version>3.2.1</version>
|
||||
<version>3.3.0-SNAPSHOT</version>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.github.edwgiz</groupId>
|
||||
|
@ -119,7 +123,7 @@
|
|||
</filters>
|
||||
<transformers>
|
||||
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
|
||||
<mainClass>org.geysermc.platform.standalone.GeyserStandaloneBootstrap</mainClass>
|
||||
<mainClass>org.geysermc.geyser.platform.standalone.GeyserStandaloneBootstrap</mainClass>
|
||||
<manifestEntries>
|
||||
<Multi-Release>true</Multi-Release>
|
||||
</manifestEntries>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2020 GeyserMC. http://geysermc.org
|
||||
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
|
@ -23,32 +23,34 @@
|
|||
* @link https://github.com/GeyserMC/Geyser
|
||||
*/
|
||||
|
||||
package org.geysermc.platform.standalone;
|
||||
package org.geysermc.geyser.platform.standalone;
|
||||
|
||||
import com.fasterxml.jackson.databind.BeanDescription;
|
||||
import com.fasterxml.jackson.databind.JavaType;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.databind.introspect.AnnotatedField;
|
||||
import com.fasterxml.jackson.databind.introspect.BeanPropertyDefinition;
|
||||
import io.netty.util.ResourceLeakDetector;
|
||||
import lombok.Getter;
|
||||
import net.minecrell.terminalconsole.TerminalConsoleAppender;
|
||||
import org.apache.logging.log4j.Level;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.core.Appender;
|
||||
import org.apache.logging.log4j.core.Logger;
|
||||
import org.apache.logging.log4j.core.appender.ConsoleAppender;
|
||||
import org.geysermc.common.PlatformType;
|
||||
import org.geysermc.connector.GeyserConnector;
|
||||
import org.geysermc.connector.bootstrap.GeyserBootstrap;
|
||||
import org.geysermc.connector.command.CommandManager;
|
||||
import org.geysermc.connector.configuration.GeyserConfiguration;
|
||||
import org.geysermc.connector.configuration.GeyserJacksonConfiguration;
|
||||
import org.geysermc.connector.dump.BootstrapDumpInfo;
|
||||
import org.geysermc.connector.ping.GeyserLegacyPingPassthrough;
|
||||
import org.geysermc.connector.ping.IGeyserPingPassthrough;
|
||||
import org.geysermc.connector.utils.FileUtils;
|
||||
import org.geysermc.connector.utils.LanguageUtils;
|
||||
import org.geysermc.platform.standalone.command.GeyserCommandManager;
|
||||
import org.geysermc.platform.standalone.gui.GeyserStandaloneGUI;
|
||||
import org.geysermc.geyser.GeyserImpl;
|
||||
import org.geysermc.geyser.GeyserBootstrap;
|
||||
import org.geysermc.geyser.command.CommandManager;
|
||||
import org.geysermc.geyser.configuration.GeyserConfiguration;
|
||||
import org.geysermc.geyser.configuration.GeyserJacksonConfiguration;
|
||||
import org.geysermc.geyser.dump.BootstrapDumpInfo;
|
||||
import org.geysermc.geyser.ping.GeyserLegacyPingPassthrough;
|
||||
import org.geysermc.geyser.ping.IGeyserPingPassthrough;
|
||||
import org.geysermc.geyser.util.FileUtils;
|
||||
import org.geysermc.geyser.text.GeyserLocale;
|
||||
import org.geysermc.geyser.platform.standalone.command.GeyserCommandManager;
|
||||
import org.geysermc.geyser.platform.standalone.gui.GeyserStandaloneGUI;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
@ -72,18 +74,24 @@ public class GeyserStandaloneBootstrap implements GeyserBootstrap {
|
|||
private boolean useGui = System.console() == null && !isHeadless();
|
||||
private String configFilename = "config.yml";
|
||||
|
||||
private GeyserConnector connector;
|
||||
private GeyserImpl geyser;
|
||||
|
||||
private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
|
||||
|
||||
private static final Map<String, String> argsConfigKeys = new HashMap<>();
|
||||
|
||||
public static void main(String[] args) {
|
||||
if (System.getProperty("io.netty.leakDetection.level") == null) {
|
||||
ResourceLeakDetector.setLevel(ResourceLeakDetector.Level.DISABLED); // Can eat performance
|
||||
}
|
||||
|
||||
GeyserStandaloneBootstrap bootstrap = new GeyserStandaloneBootstrap();
|
||||
// Set defaults
|
||||
boolean useGuiOpts = bootstrap.useGui;
|
||||
String configFilenameOpt = bootstrap.configFilename;
|
||||
|
||||
GeyserLocale.init(bootstrap);
|
||||
|
||||
List<BeanPropertyDefinition> availableProperties = getPOJOForClass(GeyserJacksonConfiguration.class);
|
||||
|
||||
for (int i = 0; i < args.length; i++) {
|
||||
|
@ -92,32 +100,26 @@ public class GeyserStandaloneBootstrap implements GeyserBootstrap {
|
|||
// Allows gui and nogui without options, for backwards compatibility
|
||||
String arg = args[i];
|
||||
switch (arg) {
|
||||
case "--gui":
|
||||
case "gui":
|
||||
useGuiOpts = true;
|
||||
break;
|
||||
case "--nogui":
|
||||
case "nogui":
|
||||
useGuiOpts = false;
|
||||
break;
|
||||
case "--config":
|
||||
case "-c":
|
||||
case "--gui", "gui" -> useGuiOpts = true;
|
||||
case "--nogui", "nogui" -> useGuiOpts = false;
|
||||
case "--config", "-c" -> {
|
||||
if (i >= args.length - 1) {
|
||||
System.err.println(MessageFormat.format(LanguageUtils.getLocaleStringLog("geyser.bootstrap.args.config_not_specified"), "-c"));
|
||||
System.err.println(MessageFormat.format(GeyserLocale.getLocaleStringLog("geyser.bootstrap.args.config_not_specified"), "-c"));
|
||||
return;
|
||||
}
|
||||
configFilenameOpt = args[i+1]; i++;
|
||||
System.out.println(MessageFormat.format(LanguageUtils.getLocaleStringLog("geyser.bootstrap.args.config_specified"), configFilenameOpt));
|
||||
break;
|
||||
case "--help":
|
||||
case "-h":
|
||||
System.out.println(MessageFormat.format(LanguageUtils.getLocaleStringLog("geyser.bootstrap.args.usage"), "[java -jar] Geyser.jar [opts]"));
|
||||
System.out.println(" " + LanguageUtils.getLocaleStringLog("geyser.bootstrap.args.options"));
|
||||
System.out.println(" -c, --config [file] " + LanguageUtils.getLocaleStringLog("geyser.bootstrap.args.config"));
|
||||
System.out.println(" -h, --help " + LanguageUtils.getLocaleStringLog("geyser.bootstrap.args.help"));
|
||||
System.out.println(" --gui, --nogui " + LanguageUtils.getLocaleStringLog("geyser.bootstrap.args.gui"));
|
||||
configFilenameOpt = args[i + 1];
|
||||
i++;
|
||||
System.out.println(MessageFormat.format(GeyserLocale.getLocaleStringLog("geyser.bootstrap.args.config_specified"), configFilenameOpt));
|
||||
}
|
||||
case "--help", "-h" -> {
|
||||
System.out.println(MessageFormat.format(GeyserLocale.getLocaleStringLog("geyser.bootstrap.args.usage"), "[java -jar] Geyser.jar [opts]"));
|
||||
System.out.println(" " + GeyserLocale.getLocaleStringLog("geyser.bootstrap.args.options"));
|
||||
System.out.println(" -c, --config [file] " + GeyserLocale.getLocaleStringLog("geyser.bootstrap.args.config"));
|
||||
System.out.println(" -h, --help " + GeyserLocale.getLocaleStringLog("geyser.bootstrap.args.help"));
|
||||
System.out.println(" --gui, --nogui " + GeyserLocale.getLocaleStringLog("geyser.bootstrap.args.gui"));
|
||||
return;
|
||||
default:
|
||||
}
|
||||
default -> {
|
||||
// We have likely added a config option argument
|
||||
if (arg.startsWith("--")) {
|
||||
// Split the argument by an =
|
||||
|
@ -153,9 +155,9 @@ public class GeyserStandaloneBootstrap implements GeyserBootstrap {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
System.err.println(LanguageUtils.getLocaleStringLog("geyser.bootstrap.args.unrecognised", arg));
|
||||
System.err.println(GeyserLocale.getLocaleStringLog("geyser.bootstrap.args.unrecognised", arg));
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
bootstrap.onEnable(useGuiOpts, configFilenameOpt);
|
||||
|
@ -167,11 +169,6 @@ public class GeyserStandaloneBootstrap implements GeyserBootstrap {
|
|||
this.onEnable();
|
||||
}
|
||||
|
||||
public void onEnable(boolean useGui) {
|
||||
this.useGui = useGui;
|
||||
this.onEnable();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEnable() {
|
||||
Logger logger = (Logger) LogManager.getRootLogger();
|
||||
|
@ -193,7 +190,8 @@ public class GeyserStandaloneBootstrap implements GeyserBootstrap {
|
|||
LoopbackUtil.checkLoopback(geyserLogger);
|
||||
|
||||
try {
|
||||
File configFile = FileUtils.fileOrCopiedFromResource(new File(configFilename), "config.yml", (x) -> x.replaceAll("generateduuid", UUID.randomUUID().toString()));
|
||||
File configFile = FileUtils.fileOrCopiedFromResource(new File(configFilename), "config.yml",
|
||||
(x) -> x.replaceAll("generateduuid", UUID.randomUUID().toString()), this);
|
||||
geyserConfig = FileUtils.loadConfig(configFile, GeyserStandaloneConfiguration.class);
|
||||
|
||||
handleArgsConfigOptions();
|
||||
|
@ -203,19 +201,27 @@ public class GeyserStandaloneBootstrap implements GeyserBootstrap {
|
|||
geyserConfig.getRemote().setAddress("127.0.0.1");
|
||||
}
|
||||
} catch (IOException ex) {
|
||||
geyserLogger.severe(LanguageUtils.getLocaleStringLog("geyser.config.failed"), ex);
|
||||
System.exit(0);
|
||||
geyserLogger.severe(GeyserLocale.getLocaleStringLog("geyser.config.failed"), ex);
|
||||
if (gui == null) {
|
||||
System.exit(1);
|
||||
} else {
|
||||
// Leave the process running so the GUI is still visible
|
||||
return;
|
||||
}
|
||||
}
|
||||
GeyserConfiguration.checkGeyserConfiguration(geyserConfig, geyserLogger);
|
||||
|
||||
connector = GeyserConnector.start(PlatformType.STANDALONE, this);
|
||||
geyserCommandManager = new GeyserCommandManager(connector);
|
||||
// Allow libraries like Protocol to have their debug information passthrough
|
||||
logger.get().setLevel(geyserConfig.isDebugMode() ? Level.DEBUG : Level.INFO);
|
||||
|
||||
geyser = GeyserImpl.start(PlatformType.STANDALONE, this);
|
||||
geyserCommandManager = new GeyserCommandManager(geyser);
|
||||
|
||||
if (gui != null) {
|
||||
gui.setupInterface(geyserLogger, geyserCommandManager);
|
||||
}
|
||||
|
||||
geyserPingPassthrough = GeyserLegacyPingPassthrough.init(connector);
|
||||
geyserPingPassthrough = GeyserLegacyPingPassthrough.init(geyser);
|
||||
|
||||
if (!useGui) {
|
||||
geyserLogger.start(); // Throws an error otherwise
|
||||
|
@ -239,7 +245,7 @@ public class GeyserStandaloneBootstrap implements GeyserBootstrap {
|
|||
|
||||
@Override
|
||||
public void onDisable() {
|
||||
connector.shutdown();
|
||||
geyser.shutdown();
|
||||
System.exit(0);
|
||||
}
|
||||
|
||||
|
@ -306,6 +312,7 @@ public class GeyserStandaloneBootstrap implements GeyserBootstrap {
|
|||
* @param parentObject The object to alter
|
||||
* @param value The new value of the property
|
||||
*/
|
||||
@SuppressWarnings("unchecked") // Required for enum usage
|
||||
private static void setConfigOption(BeanPropertyDefinition property, Object parentObject, Object value) {
|
||||
Object parsedValue = value;
|
||||
|
||||
|
@ -314,6 +321,8 @@ public class GeyserStandaloneBootstrap implements GeyserBootstrap {
|
|||
parsedValue = Integer.valueOf((String) parsedValue);
|
||||
} else if (boolean.class.equals(property.getRawPrimaryType())) {
|
||||
parsedValue = Boolean.valueOf((String) parsedValue);
|
||||
} else if (Enum.class.isAssignableFrom(property.getRawPrimaryType())) {
|
||||
parsedValue = Enum.valueOf((Class<? extends Enum>) property.getRawPrimaryType(), ((String) parsedValue).toUpperCase(Locale.ROOT));
|
||||
}
|
||||
|
||||
// Force the value to be set
|
||||
|
@ -339,7 +348,7 @@ public class GeyserStandaloneBootstrap implements GeyserBootstrap {
|
|||
// Loop through the sub property if the first part matches
|
||||
for (BeanPropertyDefinition subProperty : getPOJOForClass(property.getRawPrimaryType())) {
|
||||
if (configKeyParts[1].equals(subProperty.getName())) {
|
||||
geyserLogger.info(LanguageUtils.getLocaleStringLog("geyser.bootstrap.args.set_config_option", configKey.getKey(), configKey.getValue()));
|
||||
geyserLogger.info(GeyserLocale.getLocaleStringLog("geyser.bootstrap.args.set_config_option", configKey.getKey(), configKey.getValue()));
|
||||
|
||||
// Set the sub property value on the config
|
||||
try {
|
||||
|
@ -353,7 +362,7 @@ public class GeyserStandaloneBootstrap implements GeyserBootstrap {
|
|||
}
|
||||
}
|
||||
} else {
|
||||
geyserLogger.info(LanguageUtils.getLocaleStringLog("geyser.bootstrap.args.set_config_option", configKey.getKey(), configKey.getValue()));
|
||||
geyserLogger.info(GeyserLocale.getLocaleStringLog("geyser.bootstrap.args.set_config_option", configKey.getKey(), configKey.getValue()));
|
||||
|
||||
// Set the property value on the config
|
||||
try {
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2020 GeyserMC. http://geysermc.org
|
||||
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
|
@ -23,11 +23,11 @@
|
|||
* @link https://github.com/GeyserMC/Geyser
|
||||
*/
|
||||
|
||||
package org.geysermc.platform.standalone;
|
||||
package org.geysermc.geyser.platform.standalone;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import lombok.Getter;
|
||||
import org.geysermc.connector.configuration.GeyserJacksonConfiguration;
|
||||
import org.geysermc.geyser.configuration.GeyserJacksonConfiguration;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2020 GeyserMC. http://geysermc.org
|
||||
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
|
@ -23,15 +23,14 @@
|
|||
* @link https://github.com/GeyserMC/Geyser
|
||||
*/
|
||||
|
||||
package org.geysermc.platform.standalone;
|
||||
package org.geysermc.geyser.platform.standalone;
|
||||
|
||||
import lombok.Getter;
|
||||
import org.geysermc.connector.dump.BootstrapDumpInfo;
|
||||
import org.geysermc.geyser.dump.BootstrapDumpInfo;
|
||||
|
||||
@Getter
|
||||
public class GeyserStandaloneDumpInfo extends BootstrapDumpInfo {
|
||||
|
||||
private boolean isGui;
|
||||
private final boolean isGui;
|
||||
|
||||
GeyserStandaloneDumpInfo(GeyserStandaloneBootstrap bootstrap) {
|
||||
super();
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2020 GeyserMC. http://geysermc.org
|
||||
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
|
@ -23,73 +23,68 @@
|
|||
* @link https://github.com/GeyserMC/Geyser
|
||||
*/
|
||||
|
||||
package org.geysermc.platform.standalone;
|
||||
package org.geysermc.geyser.platform.standalone;
|
||||
|
||||
import lombok.extern.log4j.Log4j2;
|
||||
import net.minecrell.terminalconsole.SimpleTerminalConsole;
|
||||
import org.apache.logging.log4j.Level;
|
||||
import org.apache.logging.log4j.core.config.Configurator;
|
||||
import org.geysermc.connector.GeyserConnector;
|
||||
import org.geysermc.connector.GeyserLogger;
|
||||
import org.geysermc.connector.command.CommandSender;
|
||||
import org.geysermc.connector.common.ChatColor;
|
||||
import org.geysermc.geyser.GeyserImpl;
|
||||
import org.geysermc.geyser.GeyserLogger;
|
||||
import org.geysermc.geyser.command.CommandSender;
|
||||
import org.geysermc.geyser.text.ChatColor;
|
||||
|
||||
@Log4j2
|
||||
public class GeyserStandaloneLogger extends SimpleTerminalConsole implements GeyserLogger, CommandSender {
|
||||
private boolean colored = true;
|
||||
|
||||
@Override
|
||||
protected boolean isRunning() {
|
||||
return !GeyserConnector.getInstance().isShuttingDown();
|
||||
return !GeyserImpl.getInstance().isShuttingDown();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void runCommand(String line) {
|
||||
GeyserConnector.getInstance().getCommandManager().runCommand(this, line);
|
||||
GeyserImpl.getInstance().getCommandManager().runCommand(this, line);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void shutdown() {
|
||||
GeyserConnector.getInstance().getBootstrap().onDisable();
|
||||
GeyserImpl.getInstance().getBootstrap().onDisable();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void severe(String message) {
|
||||
log.fatal(printConsole(ChatColor.DARK_RED + message, colored));
|
||||
log.fatal(ChatColor.DARK_RED + message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void severe(String message, Throwable error) {
|
||||
log.fatal(printConsole(ChatColor.DARK_RED + message, colored), error);
|
||||
log.fatal(ChatColor.DARK_RED + message, error);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void error(String message) {
|
||||
log.error(printConsole(ChatColor.RED + message, colored));
|
||||
log.error(ChatColor.RED + message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void error(String message, Throwable error) {
|
||||
log.error(printConsole(ChatColor.RED + message, colored), error);
|
||||
log.error(ChatColor.RED + message, error);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void warning(String message) {
|
||||
log.warn(printConsole(ChatColor.YELLOW + message, colored));
|
||||
log.warn(ChatColor.YELLOW + message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void info(String message) {
|
||||
log.info(printConsole(ChatColor.RESET + ChatColor.BOLD + message, colored));
|
||||
log.info(ChatColor.RESET + message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void debug(String message) {
|
||||
log.debug(printConsole(ChatColor.GRAY + message, colored));
|
||||
}
|
||||
|
||||
public static String printConsole(String message, boolean colors) {
|
||||
return colors ? ChatColor.toANSI(message + ChatColor.RESET) : ChatColor.stripColors(message + ChatColor.RESET);
|
||||
log.debug(ChatColor.GRAY + message);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -102,7 +97,7 @@ public class GeyserStandaloneLogger extends SimpleTerminalConsole implements Gey
|
|||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
public String name() {
|
||||
return "CONSOLE";
|
||||
}
|
||||
|
||||
|
@ -115,4 +110,9 @@ public class GeyserStandaloneLogger extends SimpleTerminalConsole implements Gey
|
|||
public boolean isConsole() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasPermission(String permission) {
|
||||
return true;
|
||||
}
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2020 GeyserMC. http://geysermc.org
|
||||
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
|
@ -23,14 +23,13 @@
|
|||
* @link https://github.com/GeyserMC/Geyser
|
||||
*/
|
||||
|
||||
package org.geysermc.platform.standalone;
|
||||
package org.geysermc.geyser.platform.standalone;
|
||||
|
||||
import org.geysermc.connector.common.ChatColor;
|
||||
import org.geysermc.connector.utils.LanguageUtils;
|
||||
import org.geysermc.geyser.text.ChatColor;
|
||||
import org.geysermc.geyser.text.GeyserLocale;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.OpenOption;
|
||||
import java.nio.file.Paths;
|
||||
|
||||
public class LoopbackUtil {
|
||||
|
@ -54,15 +53,15 @@ public class LoopbackUtil {
|
|||
String result = sb.toString();
|
||||
|
||||
if (!result.contains("minecraftuwp")) {
|
||||
Files.write(Paths.get(System.getenv("temp") + "/loopback_minecraft.bat"), loopbackCommand.getBytes(), new OpenOption[0]);
|
||||
process = Runtime.getRuntime().exec(startScript);
|
||||
Files.write(Paths.get(System.getenv("temp") + "/loopback_minecraft.bat"), loopbackCommand.getBytes());
|
||||
Runtime.getRuntime().exec(startScript);
|
||||
|
||||
geyserLogger.info(ChatColor.AQUA + LanguageUtils.getLocaleStringLog("geyser.bootstrap.loopback.added"));
|
||||
geyserLogger.info(ChatColor.AQUA + GeyserLocale.getLocaleStringLog("geyser.bootstrap.loopback.added"));
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
|
||||
geyserLogger.error(LanguageUtils.getLocaleStringLog("geyser.bootstrap.loopback.failed"));
|
||||
geyserLogger.error(GeyserLocale.getLocaleStringLog("geyser.bootstrap.loopback.failed"));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2020 GeyserMC. http://geysermc.org
|
||||
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
|
@ -23,15 +23,15 @@
|
|||
* @link https://github.com/GeyserMC/Geyser
|
||||
*/
|
||||
|
||||
package org.geysermc.platform.standalone.command;
|
||||
package org.geysermc.geyser.platform.standalone.command;
|
||||
|
||||
import org.geysermc.connector.GeyserConnector;
|
||||
import org.geysermc.connector.command.CommandManager;
|
||||
import org.geysermc.geyser.GeyserImpl;
|
||||
import org.geysermc.geyser.command.CommandManager;
|
||||
|
||||
public class GeyserCommandManager extends CommandManager {
|
||||
|
||||
public GeyserCommandManager(GeyserConnector connector) {
|
||||
super(connector);
|
||||
public GeyserCommandManager(GeyserImpl geyser) {
|
||||
super(geyser);
|
||||
}
|
||||
|
||||
@Override
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2020 GeyserMC. http://geysermc.org
|
||||
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
|
@ -23,7 +23,7 @@
|
|||
* @link https://github.com/GeyserMC/Geyser
|
||||
*/
|
||||
|
||||
package org.geysermc.platform.standalone.gui;
|
||||
package org.geysermc.geyser.platform.standalone.gui;
|
||||
|
||||
import lombok.Getter;
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2020 GeyserMC. http://geysermc.org
|
||||
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
|
@ -23,7 +23,7 @@
|
|||
* @link https://github.com/GeyserMC/Geyser
|
||||
*/
|
||||
|
||||
package org.geysermc.platform.standalone.gui;
|
||||
package org.geysermc.geyser.platform.standalone.gui;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.text.*;
|
||||
|
@ -60,8 +60,8 @@ public class ColorPane extends JTextPane {
|
|||
*/
|
||||
public void appendANSI(String s) { // convert ANSI color codes first
|
||||
int aPos = 0; // current char position in addString
|
||||
int aIndex = 0; // index of next Escape sequence
|
||||
int mIndex = 0; // index of "m" terminating Escape sequence
|
||||
int aIndex; // index of next Escape sequence
|
||||
int mIndex; // index of "m" terminating Escape sequence
|
||||
String tmpString = "";
|
||||
boolean stillSearching = true; // true until no more Escape sequences
|
||||
String addString = remaining + s;
|
||||
|
@ -83,7 +83,6 @@ public class ColorPane extends JTextPane {
|
|||
|
||||
|
||||
// while there's text in the input buffer
|
||||
stillSearching = true;
|
||||
while (stillSearching) {
|
||||
mIndex = addString.indexOf("m", aPos); // find the end of the escape sequence
|
||||
if (mIndex < 0) { // the buffer ends halfway through the ansi string!
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2020 GeyserMC. http://geysermc.org
|
||||
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
|
@ -23,14 +23,14 @@
|
|||
* @link https://github.com/GeyserMC/Geyser
|
||||
*/
|
||||
|
||||
package org.geysermc.platform.standalone.gui;
|
||||
package org.geysermc.geyser.platform.standalone.gui;
|
||||
|
||||
import org.geysermc.connector.GeyserConnector;
|
||||
import org.geysermc.connector.command.GeyserCommand;
|
||||
import org.geysermc.connector.network.session.GeyserSession;
|
||||
import org.geysermc.connector.utils.LanguageUtils;
|
||||
import org.geysermc.platform.standalone.GeyserStandaloneLogger;
|
||||
import org.geysermc.platform.standalone.command.GeyserCommandManager;
|
||||
import org.geysermc.geyser.GeyserImpl;
|
||||
import org.geysermc.geyser.command.GeyserCommand;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.geyser.text.GeyserLocale;
|
||||
import org.geysermc.geyser.platform.standalone.GeyserStandaloneLogger;
|
||||
import org.geysermc.geyser.platform.standalone.command.GeyserCommandManager;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.table.DefaultTableModel;
|
||||
|
@ -67,7 +67,7 @@ public class GeyserStandaloneGUI {
|
|||
|
||||
public GeyserStandaloneGUI() {
|
||||
// Create the frame and setup basic settings
|
||||
JFrame frame = new JFrame(LanguageUtils.getLocaleStringLog("geyser.gui.title"));
|
||||
JFrame frame = new JFrame(GeyserLocale.getLocaleStringLog("geyser.gui.title"));
|
||||
frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
|
||||
frame.setSize(800, 400);
|
||||
frame.setMinimumSize(frame.getSize());
|
||||
|
@ -82,8 +82,8 @@ public class GeyserStandaloneGUI {
|
|||
@Override
|
||||
public void windowClosing(WindowEvent we)
|
||||
{
|
||||
String[] buttons = {LanguageUtils.getLocaleStringLog("geyser.gui.exit.confirm"), LanguageUtils.getLocaleStringLog("geyser.gui.exit.deny")};
|
||||
int result = JOptionPane.showOptionDialog(frame, LanguageUtils.getLocaleStringLog("geyser.gui.exit.message"), frame.getTitle(), JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE, null, buttons, buttons[1]);
|
||||
String[] buttons = {GeyserLocale.getLocaleStringLog("geyser.gui.exit.confirm"), GeyserLocale.getLocaleStringLog("geyser.gui.exit.deny")};
|
||||
int result = JOptionPane.showOptionDialog(frame, GeyserLocale.getLocaleStringLog("geyser.gui.exit.message"), frame.getTitle(), JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE, null, buttons, buttons[1]);
|
||||
if (result == JOptionPane.YES_OPTION) {
|
||||
System.exit(0);
|
||||
}
|
||||
|
@ -124,12 +124,12 @@ public class GeyserStandaloneGUI {
|
|||
JMenuBar menuBar = new JMenuBar();
|
||||
|
||||
// Create 'File'
|
||||
JMenu fileMenu = new JMenu(LanguageUtils.getLocaleStringLog("geyser.gui.menu.file"));
|
||||
JMenu fileMenu = new JMenu(GeyserLocale.getLocaleStringLog("geyser.gui.menu.file"));
|
||||
fileMenu.setMnemonic(KeyEvent.VK_F);
|
||||
menuBar.add(fileMenu);
|
||||
|
||||
// 'Open Geyser folder' button
|
||||
JMenuItem openButton = new JMenuItem(LanguageUtils.getLocaleStringLog("geyser.gui.menu.file.open_folder"), KeyEvent.VK_O);
|
||||
JMenuItem openButton = new JMenuItem(GeyserLocale.getLocaleStringLog("geyser.gui.menu.file.open_folder"), KeyEvent.VK_O);
|
||||
openButton.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_O, InputEvent.CTRL_MASK));
|
||||
openButton.addActionListener(e -> {
|
||||
try {
|
||||
|
@ -141,40 +141,40 @@ public class GeyserStandaloneGUI {
|
|||
fileMenu.addSeparator();
|
||||
|
||||
// 'Exit' button
|
||||
JMenuItem exitButton = new JMenuItem(LanguageUtils.getLocaleStringLog("geyser.gui.menu.file.exit"), KeyEvent.VK_X);
|
||||
JMenuItem exitButton = new JMenuItem(GeyserLocale.getLocaleStringLog("geyser.gui.menu.file.exit"), KeyEvent.VK_X);
|
||||
exitButton.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_F4, InputEvent.ALT_MASK));
|
||||
exitButton.addActionListener(e -> System.exit(0));
|
||||
fileMenu.add(exitButton);
|
||||
|
||||
// Create 'Commands'
|
||||
commandsMenu = new JMenu(LanguageUtils.getLocaleStringLog("geyser.gui.menu.commands"));
|
||||
commandsMenu = new JMenu(GeyserLocale.getLocaleStringLog("geyser.gui.menu.commands"));
|
||||
commandsMenu.setMnemonic(KeyEvent.VK_C);
|
||||
menuBar.add(commandsMenu);
|
||||
|
||||
// Create 'View'
|
||||
JMenu viewMenu = new JMenu(LanguageUtils.getLocaleStringLog("geyser.gui.menu.view"));
|
||||
JMenu viewMenu = new JMenu(GeyserLocale.getLocaleStringLog("geyser.gui.menu.view"));
|
||||
viewMenu.setMnemonic(KeyEvent.VK_V);
|
||||
menuBar.add(viewMenu);
|
||||
|
||||
// 'Zoom in' button
|
||||
JMenuItem zoomInButton = new JMenuItem(LanguageUtils.getLocaleStringLog("geyser.gui.menu.view.zoom_in"));
|
||||
JMenuItem zoomInButton = new JMenuItem(GeyserLocale.getLocaleStringLog("geyser.gui.menu.view.zoom_in"));
|
||||
zoomInButton.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_EQUALS, InputEvent.CTRL_DOWN_MASK));
|
||||
zoomInButton.addActionListener(e -> consolePane.setFont(new Font(consolePane.getFont().getName(), consolePane.getFont().getStyle(), consolePane.getFont().getSize() + 1)));
|
||||
viewMenu.add(zoomInButton);
|
||||
|
||||
// 'Zoom in' button
|
||||
JMenuItem zoomOutButton = new JMenuItem(LanguageUtils.getLocaleStringLog("geyser.gui.menu.view.zoom_out"));
|
||||
JMenuItem zoomOutButton = new JMenuItem(GeyserLocale.getLocaleStringLog("geyser.gui.menu.view.zoom_out"));
|
||||
zoomOutButton.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_MINUS, InputEvent.CTRL_DOWN_MASK));
|
||||
zoomOutButton.addActionListener(e -> consolePane.setFont(new Font(consolePane.getFont().getName(), consolePane.getFont().getStyle(), consolePane.getFont().getSize() - 1)));
|
||||
viewMenu.add(zoomOutButton);
|
||||
|
||||
// 'Reset Zoom' button
|
||||
JMenuItem resetZoomButton = new JMenuItem(LanguageUtils.getLocaleStringLog("geyser.gui.menu.view.reset_zoom"));
|
||||
JMenuItem resetZoomButton = new JMenuItem(GeyserLocale.getLocaleStringLog("geyser.gui.menu.view.reset_zoom"));
|
||||
resetZoomButton.addActionListener(e -> consolePane.setFont(new Font(consolePane.getFont().getName(), consolePane.getFont().getStyle(), originalFontSize)));
|
||||
viewMenu.add(resetZoomButton);
|
||||
|
||||
// create 'Options'
|
||||
optionsMenu = new JMenu(LanguageUtils.getLocaleStringLog("geyser.gui.menu.options"));
|
||||
optionsMenu = new JMenu(GeyserLocale.getLocaleStringLog("geyser.gui.menu.options"));
|
||||
viewMenu.setMnemonic(KeyEvent.VK_O);
|
||||
menuBar.add(optionsMenu);
|
||||
|
||||
|
@ -195,11 +195,11 @@ public class GeyserStandaloneGUI {
|
|||
ramValues.add(0);
|
||||
}
|
||||
ramGraph.setValues(ramValues);
|
||||
ramGraph.setXLabel(LanguageUtils.getLocaleStringLog("geyser.gui.graph.loading"));
|
||||
ramGraph.setXLabel(GeyserLocale.getLocaleStringLog("geyser.gui.graph.loading"));
|
||||
rightContentPane.add(ramGraph);
|
||||
|
||||
playerTableModel.addColumn(LanguageUtils.getLocaleStringLog("geyser.gui.table.ip"));
|
||||
playerTableModel.addColumn(LanguageUtils.getLocaleStringLog("geyser.gui.table.username"));
|
||||
playerTableModel.addColumn(GeyserLocale.getLocaleStringLog("geyser.gui.table.ip"));
|
||||
playerTableModel.addColumn(GeyserLocale.getLocaleStringLog("geyser.gui.table.username"));
|
||||
|
||||
JScrollPane playerScrollPane = new JScrollPane(playerTable);
|
||||
rightContentPane.add(playerScrollPane);
|
||||
|
@ -271,17 +271,17 @@ public class GeyserStandaloneGUI {
|
|||
JMenuItem commandButton = hasSubCommands ? new JMenu(command.getValue().getName()) : new JMenuItem(command.getValue().getName());
|
||||
commandButton.getAccessibleContext().setAccessibleDescription(command.getValue().getDescription());
|
||||
if (!hasSubCommands) {
|
||||
commandButton.addActionListener(e -> command.getValue().execute(geyserStandaloneLogger, new String[]{ }));
|
||||
commandButton.addActionListener(e -> command.getValue().execute(null, geyserStandaloneLogger, new String[]{ }));
|
||||
} else {
|
||||
// Add a submenu that's the same name as the menu can't be pressed
|
||||
JMenuItem otherCommandButton = new JMenuItem(command.getValue().getName());
|
||||
otherCommandButton.getAccessibleContext().setAccessibleDescription(command.getValue().getDescription());
|
||||
otherCommandButton.addActionListener(e -> command.getValue().execute(geyserStandaloneLogger, new String[]{ }));
|
||||
otherCommandButton.addActionListener(e -> command.getValue().execute(null, geyserStandaloneLogger, new String[]{ }));
|
||||
commandButton.add(otherCommandButton);
|
||||
// Add a menu option for all possible subcommands
|
||||
for (String subCommandName : command.getValue().getSubCommands()) {
|
||||
JMenuItem item = new JMenuItem(subCommandName);
|
||||
item.addActionListener(e -> command.getValue().execute(geyserStandaloneLogger, new String[]{subCommandName}));
|
||||
item.addActionListener(e -> command.getValue().execute(null, geyserStandaloneLogger, new String[]{subCommandName}));
|
||||
commandButton.add(item);
|
||||
}
|
||||
}
|
||||
|
@ -289,7 +289,7 @@ public class GeyserStandaloneGUI {
|
|||
}
|
||||
|
||||
// 'Debug Mode' toggle
|
||||
JCheckBoxMenuItem debugMode = new JCheckBoxMenuItem(LanguageUtils.getLocaleStringLog("geyser.gui.menu.options.toggle_debug_mode"));
|
||||
JCheckBoxMenuItem debugMode = new JCheckBoxMenuItem(GeyserLocale.getLocaleStringLog("geyser.gui.menu.options.toggle_debug_mode"));
|
||||
debugMode.setSelected(geyserStandaloneLogger.isDebug());
|
||||
debugMode.addActionListener(e -> geyserStandaloneLogger.setDebug(!geyserStandaloneLogger.isDebug()));
|
||||
optionsMenu.add(debugMode);
|
||||
|
@ -302,11 +302,11 @@ public class GeyserStandaloneGUI {
|
|||
ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();
|
||||
|
||||
Runnable periodicTask = () -> {
|
||||
if (GeyserConnector.getInstance() != null) {
|
||||
if (GeyserImpl.getInstance() != null) {
|
||||
// Update player table
|
||||
playerTableModel.getDataVector().removeAllElements();
|
||||
|
||||
for (GeyserSession player : GeyserConnector.getInstance().getPlayers()) {
|
||||
for (GeyserSession player : GeyserImpl.getInstance().getSessionManager().getSessions().values()) {
|
||||
Vector<String> row = new Vector<>();
|
||||
row.add(player.getSocketAddress().getHostName());
|
||||
row.add(player.getPlayerEntity().getUsername());
|
||||
|
@ -323,7 +323,7 @@ public class GeyserStandaloneGUI {
|
|||
final int freePercent = (int)(freeMemory * 100.0 / totalMemory + 0.5);
|
||||
ramValues.add(100 - freePercent);
|
||||
|
||||
ramGraph.setXLabel(LanguageUtils.getLocaleStringLog("geyser.gui.graph.usage", String.format("%,d", (totalMemory - freeMemory) / MEGABYTE), freePercent));
|
||||
ramGraph.setXLabel(GeyserLocale.getLocaleStringLog("geyser.gui.graph.usage", String.format("%,d", (totalMemory - freeMemory) / MEGABYTE), freePercent));
|
||||
|
||||
// Trim the list
|
||||
int k = ramValues.size();
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2020 GeyserMC. http://geysermc.org
|
||||
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
|
@ -23,7 +23,7 @@
|
|||
* @link https://github.com/GeyserMC/Geyser
|
||||
*/
|
||||
|
||||
package org.geysermc.platform.standalone.gui;
|
||||
package org.geysermc.geyser.platform.standalone.gui;
|
||||
|
||||
import lombok.Setter;
|
||||
|
||||
|
@ -46,7 +46,7 @@ public final class GraphPanel extends JPanel {
|
|||
private final static Color pointColor = new Color(100, 100, 100, 255);
|
||||
private final static Color gridColor = new Color(200, 200, 200, 255);
|
||||
private static final Stroke graphStroke = new BasicStroke(2f);
|
||||
private List<Integer> values = new ArrayList<>(10);
|
||||
private final List<Integer> values = new ArrayList<>(10);
|
||||
|
||||
@Setter
|
||||
private String xLabel = "";
|
||||
|
@ -68,11 +68,10 @@ public final class GraphPanel extends JPanel {
|
|||
@Override
|
||||
protected void paintComponent(Graphics graphics) {
|
||||
super.paintComponent(graphics);
|
||||
if (!(graphics instanceof Graphics2D)) {
|
||||
if (!(graphics instanceof final Graphics2D g)) {
|
||||
graphics.drawString("Graphics is not Graphics2D, unable to render", 0, 0);
|
||||
return;
|
||||
}
|
||||
final Graphics2D g = (Graphics2D) graphics;
|
||||
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
|
||||
|
||||
final int length = values.size();
|
||||
|
@ -172,6 +171,7 @@ public final class GraphPanel extends JPanel {
|
|||
for (Point graphPoint : graphPoints) {
|
||||
final int x = graphPoint.x - pointWidth / 2;
|
||||
final int y = graphPoint.y - pointWidth / 2;
|
||||
//noinspection SuspiciousNameCombination
|
||||
g.fillOval(x, y, pointWidth, pointWidth);
|
||||
}
|
||||
}
|
|
@ -8,7 +8,7 @@
|
|||
<PatternLayout pattern="[%d{HH:mm:ss} %style{%highlight{%level}{FATAL=red dark, ERROR=red, WARN=yellow bright, INFO=cyan bright, DEBUG=green, TRACE=white}}] %minecraftFormatting{%msg}%n"/>
|
||||
</Console>
|
||||
<RollingRandomAccessFile name="File" fileName="logs/latest.log" filePattern="logs/%d{yyyy-MM-dd}-%i.log.gz">
|
||||
<PatternLayout pattern="%d{yyy-MM-dd HH:mm:ss.SSS} [%t] %level{length=1} - %msg%n"/>
|
||||
<PatternLayout pattern="[%d{HH:mm:ss.SSS} %t/%level] %minecraftFormatting{%msg}{strip}%n"/>
|
||||
<Policies>
|
||||
<TimeBasedTriggeringPolicy/>
|
||||
<OnStartupTriggeringPolicy/>
|
||||
|
|
|
@ -6,21 +6,21 @@
|
|||
<parent>
|
||||
<groupId>org.geysermc</groupId>
|
||||
<artifactId>bootstrap-parent</artifactId>
|
||||
<version>1.2.0-SNAPSHOT</version>
|
||||
<version>2.0.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>bootstrap-velocity</artifactId>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.geysermc</groupId>
|
||||
<artifactId>connector</artifactId>
|
||||
<version>1.2.0-SNAPSHOT</version>
|
||||
<artifactId>core</artifactId>
|
||||
<version>2.0.0-SNAPSHOT</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.velocitypowered</groupId>
|
||||
<artifactId>velocity-api</artifactId>
|
||||
<version>1.1.0</version>
|
||||
<version>3.0.0</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
@ -40,7 +40,7 @@
|
|||
<configuration>
|
||||
<archive>
|
||||
<manifestEntries>
|
||||
<Main-Class>org.geysermc.platform.velocity.GeyserVelocityMain</Main-Class>
|
||||
<Main-Class>org.geysermc.geyser.platform.velocity.GeyserVelocityMain</Main-Class>
|
||||
</manifestEntries>
|
||||
</archive>
|
||||
</configuration>
|
||||
|
@ -48,7 +48,7 @@
|
|||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-shade-plugin</artifactId>
|
||||
<version>3.2.1</version>
|
||||
<version>3.3.0-SNAPSHOT</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>package</phase>
|
||||
|
@ -59,31 +59,15 @@
|
|||
<relocations>
|
||||
<relocation>
|
||||
<pattern>com.fasterxml.jackson</pattern>
|
||||
<shadedPattern>org.geysermc.platform.velocity.shaded.jackson</shadedPattern>
|
||||
<shadedPattern>org.geysermc.geyser.platform.velocity.shaded.jackson</shadedPattern>
|
||||
</relocation>
|
||||
<relocation>
|
||||
<pattern>it.unimi.dsi.fastutil</pattern>
|
||||
<shadedPattern>org.geysermc.platform.velocity.shaded.fastutil</shadedPattern>
|
||||
<shadedPattern>org.geysermc.geyser.platform.velocity.shaded.fastutil</shadedPattern>
|
||||
</relocation>
|
||||
<relocation>
|
||||
<pattern>org.reflections</pattern>
|
||||
<shadedPattern>org.geysermc.platform.velocity.shaded.reflections</shadedPattern>
|
||||
</relocation>
|
||||
<relocation>
|
||||
<pattern>com.google.common</pattern>
|
||||
<shadedPattern>org.geysermc.platform.velocity.shaded.google.common</shadedPattern>
|
||||
</relocation>
|
||||
<relocation>
|
||||
<pattern>com.google.guava</pattern>
|
||||
<shadedPattern>org.geysermc.platform.velocity.shaded.google.guava</shadedPattern>
|
||||
</relocation>
|
||||
<relocation>
|
||||
<pattern>org.dom4j</pattern>
|
||||
<shadedPattern>org.geysermc.platform.velocity.shaded.dom4j</shadedPattern>
|
||||
</relocation>
|
||||
<relocation>
|
||||
<pattern>net.kyori.adventure</pattern>
|
||||
<shadedPattern>org.geysermc.platform.velocity.shaded.adventure</shadedPattern>
|
||||
<pattern>net.kyori.adventure.text.serializer.gson.legacyimpl</pattern>
|
||||
<shadedPattern>org.geysermc.geyser.platform.velocity.shaded.kyori.legacyimpl</shadedPattern>
|
||||
</relocation>
|
||||
</relocations>
|
||||
</configuration>
|
||||
|
@ -92,10 +76,27 @@
|
|||
<configuration>
|
||||
<artifactSet>
|
||||
<excludes>
|
||||
<exclude>com.google.code.gson:*</exclude>
|
||||
<exclude>io.netty:*</exclude>
|
||||
<exclude>com.google.*:*</exclude>
|
||||
<!-- Needed because Velocity provides every dependency except netty-resolver-dns -->
|
||||
<exclude>io.netty:netty-transport-native-epoll:*</exclude>
|
||||
<exclude>io.netty:netty-transport-native-unix-common:*</exclude>
|
||||
<exclude>io.netty:netty-transport-native-kqueue:*</exclude>
|
||||
<exclude>io.netty:netty-handler:*</exclude>
|
||||
<exclude>io.netty:netty-common:*</exclude>
|
||||
<exclude>io.netty:netty-buffer:*</exclude>
|
||||
<exclude>io.netty:netty-resolver:*</exclude>
|
||||
<exclude>io.netty:netty-transport:*</exclude>
|
||||
<exclude>io.netty:netty-codec:*</exclude>
|
||||
<exclude>io.netty:netty-codec-haproxy:*</exclude>
|
||||
<exclude>org.slf4j:*</exclude>
|
||||
<exclude>org.ow2.asm:*</exclude>
|
||||
<!-- Exclude all Kyori dependencies except the legacy NBT serializer -->
|
||||
<exclude>net.kyori:adventure-api:*</exclude>
|
||||
<exclude>net.kyori:examination-api:*</exclude>
|
||||
<exclude>net.kyori:examination-string:*</exclude>
|
||||
<exclude>net.kyori:adventure-text-serializer-gson:*</exclude>
|
||||
<exclude>net.kyori:adventure-text-serializer-legacy:*</exclude>
|
||||
<exclude>net.kyori:adventure-nbt:*</exclude>
|
||||
</excludes>
|
||||
</artifactSet>
|
||||
</configuration>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2020 GeyserMC. http://geysermc.org
|
||||
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
|
@ -23,19 +23,20 @@
|
|||
* @link https://github.com/GeyserMC/Geyser
|
||||
*/
|
||||
|
||||
package org.geysermc.platform.velocity;
|
||||
package org.geysermc.geyser.platform.velocity;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.velocitypowered.api.plugin.PluginContainer;
|
||||
import com.velocitypowered.api.proxy.ProxyServer;
|
||||
import lombok.Getter;
|
||||
import org.geysermc.connector.FloodgateKeyLoader;
|
||||
import org.geysermc.connector.configuration.GeyserJacksonConfiguration;
|
||||
import org.geysermc.geyser.FloodgateKeyLoader;
|
||||
import org.geysermc.geyser.configuration.GeyserJacksonConfiguration;
|
||||
|
||||
import java.io.File;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.Optional;
|
||||
|
||||
@Getter
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
|
@ -44,7 +45,8 @@ public final class GeyserVelocityConfiguration extends GeyserJacksonConfiguratio
|
|||
private Path floodgateKeyPath;
|
||||
|
||||
public void loadFloodgate(GeyserVelocityPlugin plugin, ProxyServer proxyServer, File dataFolder) {
|
||||
PluginContainer floodgate = proxyServer.getPluginManager().getPlugin("floodgate").orElse(null);
|
||||
floodgateKeyPath = FloodgateKeyLoader.getKeyPath(this, floodgate, Paths.get("plugins/floodgate/"), dataFolder.toPath(), plugin.getGeyserLogger());
|
||||
Optional<PluginContainer> floodgate = proxyServer.getPluginManager().getPlugin("floodgate");
|
||||
Path floodgateDataPath = floodgate.isPresent() ? Paths.get("plugins/floodgate/") : null;
|
||||
floodgateKeyPath = FloodgateKeyLoader.getKeyPath(this, floodgateDataPath, dataFolder.toPath(), plugin.getGeyserLogger());
|
||||
}
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2020 GeyserMC. http://geysermc.org
|
||||
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
|
@ -23,13 +23,13 @@
|
|||
* @link https://github.com/GeyserMC/Geyser
|
||||
*/
|
||||
|
||||
package org.geysermc.platform.velocity;
|
||||
package org.geysermc.geyser.platform.velocity;
|
||||
|
||||
import com.velocitypowered.api.plugin.PluginContainer;
|
||||
import com.velocitypowered.api.proxy.ProxyServer;
|
||||
import lombok.Getter;
|
||||
import org.geysermc.connector.common.serializer.AsteriskSerializer;
|
||||
import org.geysermc.connector.dump.BootstrapDumpInfo;
|
||||
import org.geysermc.geyser.text.AsteriskSerializer;
|
||||
import org.geysermc.geyser.dump.BootstrapDumpInfo;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
@ -37,13 +37,13 @@ import java.util.List;
|
|||
@Getter
|
||||
public class GeyserVelocityDumpInfo extends BootstrapDumpInfo {
|
||||
|
||||
private String platformName;
|
||||
private String platformVersion;
|
||||
private String platformVendor;
|
||||
private boolean onlineMode;
|
||||
private String serverIP;
|
||||
private int serverPort;
|
||||
private List<PluginInfo> plugins;
|
||||
private final String platformName;
|
||||
private final String platformVersion;
|
||||
private final String platformVendor;
|
||||
private final boolean onlineMode;
|
||||
private final String serverIP;
|
||||
private final int serverPort;
|
||||
private final List<PluginInfo> plugins;
|
||||
|
||||
GeyserVelocityDumpInfo(ProxyServer proxy) {
|
||||
super();
|
||||
|
@ -61,7 +61,7 @@ public class GeyserVelocityDumpInfo extends BootstrapDumpInfo {
|
|||
|
||||
for (PluginContainer plugin : proxy.getPluginManager().getPlugins()) {
|
||||
String pluginClass = plugin.getInstance().map((pl) -> pl.getClass().getName()).orElse("unknown");
|
||||
this.plugins.add(new PluginInfo(true, plugin.getDescription().getName().get(), plugin.getDescription().getVersion().get(), pluginClass, plugin.getDescription().getAuthors()));
|
||||
this.plugins.add(new PluginInfo(true, plugin.getDescription().getName().orElse(null), plugin.getDescription().getVersion().orElse(null), pluginClass, plugin.getDescription().getAuthors()));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,82 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
* @author GeyserMC
|
||||
* @link https://github.com/GeyserMC/Geyser
|
||||
*/
|
||||
|
||||
package org.geysermc.geyser.platform.velocity;
|
||||
|
||||
import com.velocitypowered.api.proxy.ProxyServer;
|
||||
import io.netty.bootstrap.ServerBootstrap;
|
||||
import io.netty.channel.*;
|
||||
import io.netty.channel.local.LocalAddress;
|
||||
import org.geysermc.geyser.GeyserBootstrap;
|
||||
import org.geysermc.geyser.network.netty.GeyserInjector;
|
||||
import org.geysermc.geyser.network.netty.LocalServerChannelWrapper;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public class GeyserVelocityInjector extends GeyserInjector {
|
||||
private final ProxyServer proxy;
|
||||
|
||||
public GeyserVelocityInjector(ProxyServer proxy) {
|
||||
this.proxy = proxy;
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
protected void initializeLocalChannel0(GeyserBootstrap bootstrap) throws Exception {
|
||||
Field cm = proxy.getClass().getDeclaredField("cm");
|
||||
cm.setAccessible(true);
|
||||
Object connectionManager = cm.get(proxy);
|
||||
Class<?> connectionManagerClass = connectionManager.getClass();
|
||||
|
||||
Supplier<ChannelInitializer<Channel>> serverChannelInitializerHolder = (Supplier<ChannelInitializer<Channel>>) connectionManagerClass
|
||||
.getMethod("getServerChannelInitializer")
|
||||
.invoke(connectionManager);
|
||||
ChannelInitializer<Channel> channelInitializer = serverChannelInitializerHolder.get();
|
||||
|
||||
// Is set on Velocity's end for listening to Java connections - required on ours or else the initial world load process won't finish sometimes
|
||||
Field serverWriteMarkField = connectionManagerClass.getDeclaredField("SERVER_WRITE_MARK");
|
||||
serverWriteMarkField.setAccessible(true);
|
||||
WriteBufferWaterMark serverWriteMark = (WriteBufferWaterMark) serverWriteMarkField.get(null);
|
||||
|
||||
EventLoopGroup bossGroup = (EventLoopGroup) connectionManagerClass.getMethod("getBossGroup").invoke(connectionManager);
|
||||
|
||||
Field workerGroupField = connectionManagerClass.getDeclaredField("workerGroup");
|
||||
workerGroupField.setAccessible(true);
|
||||
EventLoopGroup workerGroup = (EventLoopGroup) workerGroupField.get(connectionManager);
|
||||
|
||||
ChannelFuture channelFuture = (new ServerBootstrap()
|
||||
.channel(LocalServerChannelWrapper.class)
|
||||
.childHandler(channelInitializer)
|
||||
.group(bossGroup, workerGroup) // Cannot be DefaultEventLoopGroup
|
||||
.childOption(ChannelOption.WRITE_BUFFER_WATER_MARK, serverWriteMark) // Required or else rare network freezes can occur
|
||||
.localAddress(LocalAddress.ANY))
|
||||
.bind()
|
||||
.syncUninterruptibly();
|
||||
|
||||
this.localChannel = channelFuture;
|
||||
this.serverSocketAddress = channelFuture.channel().localAddress();
|
||||
}
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2020 GeyserMC. http://geysermc.org
|
||||
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
|
@ -23,12 +23,12 @@
|
|||
* @link https://github.com/GeyserMC/Geyser
|
||||
*/
|
||||
|
||||
package org.geysermc.platform.velocity;
|
||||
package org.geysermc.geyser.platform.velocity;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import org.geysermc.connector.GeyserLogger;
|
||||
import org.geysermc.geyser.GeyserLogger;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
@AllArgsConstructor
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2020 GeyserMC. http://geysermc.org
|
||||
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
|
@ -23,11 +23,11 @@
|
|||
* @link https://github.com/GeyserMC/Geyser
|
||||
*/
|
||||
|
||||
package org.geysermc.platform.velocity;
|
||||
package org.geysermc.geyser.platform.velocity;
|
||||
|
||||
import org.geysermc.connector.common.main.IGeyserMain;
|
||||
import org.geysermc.geyser.GeyserMain;
|
||||
|
||||
public class GeyserVelocityMain extends IGeyserMain {
|
||||
public class GeyserVelocityMain extends GeyserMain {
|
||||
|
||||
public static void main(String[] args) {
|
||||
new GeyserVelocityMain().displayMessage();
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2020 GeyserMC. http://geysermc.org
|
||||
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
|
@ -23,7 +23,7 @@
|
|||
* @link https://github.com/GeyserMC/Geyser
|
||||
*/
|
||||
|
||||
package org.geysermc.platform.velocity;
|
||||
package org.geysermc.geyser.platform.velocity;
|
||||
|
||||
import com.velocitypowered.api.event.proxy.ProxyPingEvent;
|
||||
import com.velocitypowered.api.network.ProtocolVersion;
|
||||
|
@ -31,11 +31,10 @@ import com.velocitypowered.api.proxy.InboundConnection;
|
|||
import com.velocitypowered.api.proxy.ProxyServer;
|
||||
import com.velocitypowered.api.proxy.server.ServerPing;
|
||||
import lombok.AllArgsConstructor;
|
||||
import net.kyori.text.serializer.legacy.LegacyComponentSerializer;
|
||||
import org.geysermc.connector.common.ping.GeyserPingInfo;
|
||||
import org.geysermc.connector.ping.IGeyserPingPassthrough;
|
||||
import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
|
||||
import org.geysermc.geyser.ping.GeyserPingInfo;
|
||||
import org.geysermc.geyser.ping.IGeyserPingPassthrough;
|
||||
|
||||
import java.net.Inet4Address;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
|
@ -43,22 +42,20 @@ import java.util.concurrent.ExecutionException;
|
|||
@AllArgsConstructor
|
||||
public class GeyserVelocityPingPassthrough implements IGeyserPingPassthrough {
|
||||
|
||||
private static final GeyserInboundConnection FAKE_INBOUND_CONNECTION = new GeyserInboundConnection();
|
||||
|
||||
private final ProxyServer server;
|
||||
|
||||
@Override
|
||||
public GeyserPingInfo getPingInformation() {
|
||||
public GeyserPingInfo getPingInformation(InetSocketAddress inetSocketAddress) {
|
||||
ProxyPingEvent event;
|
||||
try {
|
||||
event = server.getEventManager().fire(new ProxyPingEvent(FAKE_INBOUND_CONNECTION, ServerPing.builder()
|
||||
.description(server.getConfiguration().getMotdComponent()).onlinePlayers(server.getPlayerCount())
|
||||
event = server.getEventManager().fire(new ProxyPingEvent(new GeyserInboundConnection(inetSocketAddress), ServerPing.builder()
|
||||
.description(server.getConfiguration().getMotd()).onlinePlayers(server.getPlayerCount())
|
||||
.maximumPlayers(server.getConfiguration().getShowMaxPlayers()).build())).get();
|
||||
} catch (ExecutionException | InterruptedException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
GeyserPingInfo geyserPingInfo = new GeyserPingInfo(
|
||||
LegacyComponentSerializer.legacy().serialize(event.getPing().getDescription(), '§'),
|
||||
LegacyComponentSerializer.legacy('§').serialize(event.getPing().getDescriptionComponent()),
|
||||
new GeyserPingInfo.Players(
|
||||
event.getPing().getPlayers().orElseThrow(IllegalStateException::new).getMax(),
|
||||
event.getPing().getPlayers().orElseThrow(IllegalStateException::new).getOnline()
|
||||
|
@ -74,11 +71,15 @@ public class GeyserVelocityPingPassthrough implements IGeyserPingPassthrough {
|
|||
|
||||
private static class GeyserInboundConnection implements InboundConnection {
|
||||
|
||||
private static final InetSocketAddress FAKE_REMOTE = new InetSocketAddress(Inet4Address.getLoopbackAddress(), 69);
|
||||
private final InetSocketAddress remote;
|
||||
|
||||
public GeyserInboundConnection(InetSocketAddress remote) {
|
||||
this.remote = remote;
|
||||
}
|
||||
|
||||
@Override
|
||||
public InetSocketAddress getRemoteAddress() {
|
||||
return FAKE_REMOTE;
|
||||
return this.remote;
|
||||
}
|
||||
|
||||
@Override
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2020 GeyserMC. http://geysermc.org
|
||||
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
|
@ -23,37 +23,42 @@
|
|||
* @link https://github.com/GeyserMC/Geyser
|
||||
*/
|
||||
|
||||
package org.geysermc.platform.velocity;
|
||||
package org.geysermc.geyser.platform.velocity;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import com.velocitypowered.api.command.CommandManager;
|
||||
import com.velocitypowered.api.event.Subscribe;
|
||||
import com.velocitypowered.api.event.proxy.ListenerBoundEvent;
|
||||
import com.velocitypowered.api.event.proxy.ProxyInitializeEvent;
|
||||
import com.velocitypowered.api.event.proxy.ProxyShutdownEvent;
|
||||
import com.velocitypowered.api.network.ListenerType;
|
||||
import com.velocitypowered.api.plugin.Plugin;
|
||||
import com.velocitypowered.api.proxy.ProxyServer;
|
||||
import lombok.Getter;
|
||||
import org.geysermc.common.PlatformType;
|
||||
import org.geysermc.connector.GeyserConnector;
|
||||
import org.geysermc.connector.bootstrap.GeyserBootstrap;
|
||||
import org.geysermc.connector.configuration.GeyserConfiguration;
|
||||
import org.geysermc.connector.dump.BootstrapDumpInfo;
|
||||
import org.geysermc.connector.ping.GeyserLegacyPingPassthrough;
|
||||
import org.geysermc.connector.ping.IGeyserPingPassthrough;
|
||||
import org.geysermc.connector.utils.FileUtils;
|
||||
import org.geysermc.connector.utils.LanguageUtils;
|
||||
import org.geysermc.platform.velocity.command.GeyserVelocityCommandExecutor;
|
||||
import org.geysermc.platform.velocity.command.GeyserVelocityCommandManager;
|
||||
import org.geysermc.geyser.GeyserBootstrap;
|
||||
import org.geysermc.geyser.GeyserImpl;
|
||||
import org.geysermc.geyser.configuration.GeyserConfiguration;
|
||||
import org.geysermc.geyser.dump.BootstrapDumpInfo;
|
||||
import org.geysermc.geyser.ping.GeyserLegacyPingPassthrough;
|
||||
import org.geysermc.geyser.ping.IGeyserPingPassthrough;
|
||||
import org.geysermc.geyser.platform.velocity.command.GeyserVelocityCommandExecutor;
|
||||
import org.geysermc.geyser.platform.velocity.command.GeyserVelocityCommandManager;
|
||||
import org.geysermc.geyser.session.auth.AuthType;
|
||||
import org.geysermc.geyser.text.GeyserLocale;
|
||||
import org.geysermc.geyser.util.FileUtils;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.SocketAddress;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.UUID;
|
||||
|
||||
@Plugin(id = "geyser", name = GeyserConnector.NAME + "-Velocity", version = GeyserConnector.VERSION, url = "https://geysermc.org", authors = "GeyserMC")
|
||||
@Plugin(id = "geyser", name = GeyserImpl.NAME + "-Velocity", version = GeyserImpl.VERSION, url = "https://geysermc.org", authors = "GeyserMC")
|
||||
public class GeyserVelocityPlugin implements GeyserBootstrap {
|
||||
|
||||
@Inject
|
||||
|
@ -67,25 +72,30 @@ public class GeyserVelocityPlugin implements GeyserBootstrap {
|
|||
|
||||
private GeyserVelocityCommandManager geyserCommandManager;
|
||||
private GeyserVelocityConfiguration geyserConfig;
|
||||
private GeyserVelocityInjector geyserInjector;
|
||||
private GeyserVelocityLogger geyserLogger;
|
||||
private IGeyserPingPassthrough geyserPingPassthrough;
|
||||
|
||||
private GeyserConnector connector;
|
||||
private GeyserImpl geyser;
|
||||
|
||||
@Getter
|
||||
private final Path configFolder = Paths.get("plugins/" + GeyserConnector.NAME + "-Velocity/");
|
||||
private final Path configFolder = Paths.get("plugins/" + GeyserImpl.NAME + "-Velocity/");
|
||||
|
||||
@Override
|
||||
public void onEnable() {
|
||||
GeyserLocale.init(this);
|
||||
|
||||
try {
|
||||
if (!configFolder.toFile().exists())
|
||||
//noinspection ResultOfMethodCallIgnored
|
||||
configFolder.toFile().mkdirs();
|
||||
File configFile = FileUtils.fileOrCopiedFromResource(configFolder.resolve("config.yml").toFile(), "config.yml", (x) -> x.replaceAll("generateduuid", UUID.randomUUID().toString()));
|
||||
File configFile = FileUtils.fileOrCopiedFromResource(configFolder.resolve("config.yml").toFile(),
|
||||
"config.yml", (x) -> x.replaceAll("generateduuid", UUID.randomUUID().toString()), this);
|
||||
this.geyserConfig = FileUtils.loadConfig(configFile, GeyserVelocityConfiguration.class);
|
||||
} catch (IOException ex) {
|
||||
logger.warn(LanguageUtils.getLocaleStringLog("geyser.config.failed"), ex);
|
||||
logger.error(GeyserLocale.getLocaleStringLog("geyser.config.failed"), ex);
|
||||
ex.printStackTrace();
|
||||
return;
|
||||
}
|
||||
|
||||
InetSocketAddress javaAddr = proxyServer.getBoundAddress();
|
||||
|
@ -107,23 +117,37 @@ public class GeyserVelocityPlugin implements GeyserBootstrap {
|
|||
this.geyserLogger = new GeyserVelocityLogger(logger, geyserConfig.isDebugMode());
|
||||
GeyserConfiguration.checkGeyserConfiguration(geyserConfig, geyserLogger);
|
||||
|
||||
if (geyserConfig.getRemote().getAuthType().equals("floodgate") && !proxyServer.getPluginManager().getPlugin("floodgate").isPresent()) {
|
||||
geyserLogger.severe(LanguageUtils.getLocaleStringLog("geyser.bootstrap.floodgate.not_installed") + " " + LanguageUtils.getLocaleStringLog("geyser.bootstrap.floodgate.disabling"));
|
||||
// Remove this in like a year
|
||||
try {
|
||||
// Should only exist on 1.0
|
||||
Class.forName("org.geysermc.floodgate.FloodgateAPI");
|
||||
geyserLogger.severe(GeyserLocale.getLocaleStringLog("geyser.bootstrap.floodgate.outdated",
|
||||
"https://ci.opencollab.dev/job/GeyserMC/job/Floodgate/job/master/"));
|
||||
return;
|
||||
} catch (ClassNotFoundException ignored) {
|
||||
}
|
||||
|
||||
if (geyserConfig.getRemote().getAuthType() == AuthType.FLOODGATE && proxyServer.getPluginManager().getPlugin("floodgate").isEmpty()) {
|
||||
geyserLogger.severe(GeyserLocale.getLocaleStringLog("geyser.bootstrap.floodgate.not_installed") + " "
|
||||
+ GeyserLocale.getLocaleStringLog("geyser.bootstrap.floodgate.disabling"));
|
||||
return;
|
||||
} else if (geyserConfig.isAutoconfiguredRemote() && proxyServer.getPluginManager().getPlugin("floodgate").isPresent()) {
|
||||
// Floodgate installed means that the user wants Floodgate authentication
|
||||
geyserLogger.debug("Auto-setting to Floodgate authentication.");
|
||||
geyserConfig.getRemote().setAuthType("floodgate");
|
||||
geyserConfig.getRemote().setAuthType(AuthType.FLOODGATE);
|
||||
}
|
||||
|
||||
geyserConfig.loadFloodgate(this, proxyServer, configFolder.toFile());
|
||||
|
||||
this.connector = GeyserConnector.start(PlatformType.VELOCITY, this);
|
||||
this.geyser = GeyserImpl.start(PlatformType.VELOCITY, this);
|
||||
|
||||
this.geyserCommandManager = new GeyserVelocityCommandManager(connector);
|
||||
this.commandManager.register("geyser", new GeyserVelocityCommandExecutor(connector));
|
||||
this.geyserInjector = new GeyserVelocityInjector(proxyServer);
|
||||
// Will be initialized after the proxy has been bound
|
||||
|
||||
this.geyserCommandManager = new GeyserVelocityCommandManager(geyser);
|
||||
this.commandManager.register("geyser", new GeyserVelocityCommandExecutor(geyser));
|
||||
if (geyserConfig.isLegacyPingPassthrough()) {
|
||||
this.geyserPingPassthrough = GeyserLegacyPingPassthrough.init(connector);
|
||||
this.geyserPingPassthrough = GeyserLegacyPingPassthrough.init(geyser);
|
||||
} else {
|
||||
this.geyserPingPassthrough = new GeyserVelocityPingPassthrough(proxyServer);
|
||||
}
|
||||
|
@ -131,7 +155,12 @@ public class GeyserVelocityPlugin implements GeyserBootstrap {
|
|||
|
||||
@Override
|
||||
public void onDisable() {
|
||||
connector.shutdown();
|
||||
if (geyser != null) {
|
||||
geyser.shutdown();
|
||||
}
|
||||
if (geyserInjector != null) {
|
||||
geyserInjector.shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -145,7 +174,7 @@ public class GeyserVelocityPlugin implements GeyserBootstrap {
|
|||
}
|
||||
|
||||
@Override
|
||||
public org.geysermc.connector.command.CommandManager getGeyserCommandManager() {
|
||||
public org.geysermc.geyser.command.CommandManager getGeyserCommandManager() {
|
||||
return this.geyserCommandManager;
|
||||
}
|
||||
|
||||
|
@ -164,8 +193,22 @@ public class GeyserVelocityPlugin implements GeyserBootstrap {
|
|||
onDisable();
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onProxyBound(ListenerBoundEvent event) {
|
||||
if (event.getListenerType() == ListenerType.MINECRAFT && geyserInjector != null) {
|
||||
// After this bound, we know that the channel initializer cannot change without it being ineffective for Velocity, too
|
||||
geyserInjector.initializeLocalChannel(this);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public BootstrapDumpInfo getDumpInfo() {
|
||||
return new GeyserVelocityDumpInfo(proxyServer);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public SocketAddress getSocketAddress() {
|
||||
return this.geyserInjector.getServerSocketAddress();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,78 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
* @author GeyserMC
|
||||
* @link https://github.com/GeyserMC/Geyser
|
||||
*/
|
||||
|
||||
package org.geysermc.geyser.platform.velocity.command;
|
||||
|
||||
import com.velocitypowered.api.command.SimpleCommand;
|
||||
import org.geysermc.geyser.GeyserImpl;
|
||||
import org.geysermc.geyser.command.CommandExecutor;
|
||||
import org.geysermc.geyser.command.CommandSender;
|
||||
import org.geysermc.geyser.command.GeyserCommand;
|
||||
import org.geysermc.geyser.text.ChatColor;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.geyser.text.GeyserLocale;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
public class GeyserVelocityCommandExecutor extends CommandExecutor implements SimpleCommand {
|
||||
|
||||
public GeyserVelocityCommandExecutor(GeyserImpl geyser) {
|
||||
super(geyser);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(Invocation invocation) {
|
||||
CommandSender sender = new VelocityCommandSender(invocation.source());
|
||||
GeyserSession session = getGeyserSession(sender);
|
||||
|
||||
if (invocation.arguments().length > 0) {
|
||||
GeyserCommand command = getCommand(invocation.arguments()[0]);
|
||||
if (command != null) {
|
||||
if (!invocation.source().hasPermission(getCommand(invocation.arguments()[0]).getPermission())) {
|
||||
sender.sendMessage(ChatColor.RED + GeyserLocale.getPlayerLocaleString("geyser.bootstrap.command.permission_fail", sender.getLocale()));
|
||||
return;
|
||||
}
|
||||
if (command.isBedrockOnly() && session == null) {
|
||||
sender.sendMessage(ChatColor.RED + GeyserLocale.getPlayerLocaleString("geyser.bootstrap.command.bedrock_only", sender.getLocale()));
|
||||
return;
|
||||
}
|
||||
command.execute(session, sender, invocation.arguments().length > 1 ? Arrays.copyOfRange(invocation.arguments(), 1, invocation.arguments().length) : new String[0]);
|
||||
}
|
||||
} else {
|
||||
getCommand("help").execute(session, sender, new String[0]);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> suggest(Invocation invocation) {
|
||||
// Velocity seems to do the splitting a bit differently. This results in the same behaviour in bungeecord/spigot.
|
||||
if (invocation.arguments().length == 0 || invocation.arguments().length == 1) {
|
||||
return tabComplete(new VelocityCommandSender(invocation.source()));
|
||||
}
|
||||
return Collections.emptyList();
|
||||
}
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2020 GeyserMC. http://geysermc.org
|
||||
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
|
@ -23,15 +23,15 @@
|
|||
* @link https://github.com/GeyserMC/Geyser
|
||||
*/
|
||||
|
||||
package org.geysermc.platform.velocity.command;
|
||||
package org.geysermc.geyser.platform.velocity.command;
|
||||
|
||||
import org.geysermc.connector.GeyserConnector;
|
||||
import org.geysermc.connector.command.CommandManager;
|
||||
import org.geysermc.geyser.GeyserImpl;
|
||||
import org.geysermc.geyser.command.CommandManager;
|
||||
|
||||
public class GeyserVelocityCommandManager extends CommandManager {
|
||||
|
||||
public GeyserVelocityCommandManager(GeyserConnector connector) {
|
||||
super(connector);
|
||||
public GeyserVelocityCommandManager(GeyserImpl geyser) {
|
||||
super(geyser);
|
||||
}
|
||||
|
||||
@Override
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2020 GeyserMC. http://geysermc.org
|
||||
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
|
@ -23,14 +23,14 @@
|
|||
* @link https://github.com/GeyserMC/Geyser
|
||||
*/
|
||||
|
||||
package org.geysermc.platform.velocity.command;
|
||||
package org.geysermc.geyser.platform.velocity.command;
|
||||
|
||||
import com.velocitypowered.api.command.CommandSource;
|
||||
import com.velocitypowered.api.proxy.ConsoleCommandSource;
|
||||
import com.velocitypowered.api.proxy.Player;
|
||||
import net.kyori.text.TextComponent;
|
||||
import org.geysermc.connector.command.CommandSender;
|
||||
import org.geysermc.connector.utils.LanguageUtils;
|
||||
import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
|
||||
import org.geysermc.geyser.command.CommandSender;
|
||||
import org.geysermc.geyser.text.GeyserLocale;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
|
@ -41,11 +41,11 @@ public class VelocityCommandSender implements CommandSender {
|
|||
public VelocityCommandSender(CommandSource handle) {
|
||||
this.handle = handle;
|
||||
// Ensure even Java players' languages are loaded
|
||||
LanguageUtils.loadGeyserLocale(getLocale());
|
||||
GeyserLocale.loadGeyserLocale(getLocale());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
public String name() {
|
||||
if (handle instanceof Player) {
|
||||
return ((Player) handle).getUsername();
|
||||
} else if (handle instanceof ConsoleCommandSource) {
|
||||
|
@ -56,7 +56,7 @@ public class VelocityCommandSender implements CommandSender {
|
|||
|
||||
@Override
|
||||
public void sendMessage(String message) {
|
||||
handle.sendMessage(TextComponent.of(message));
|
||||
handle.sendMessage(LegacyComponentSerializer.legacy('§').deserialize(message));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -68,8 +68,13 @@ public class VelocityCommandSender implements CommandSender {
|
|||
public String getLocale() {
|
||||
if (handle instanceof Player) {
|
||||
Locale locale = ((Player) handle).getPlayerSettings().getLocale();
|
||||
return LanguageUtils.formatLocale(locale.getLanguage() + "_" + locale.getCountry());
|
||||
return GeyserLocale.formatLocale(locale.getLanguage() + "_" + locale.getCountry());
|
||||
}
|
||||
return LanguageUtils.getDefaultLocale();
|
||||
return GeyserLocale.getDefaultLocale();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasPermission(String permission) {
|
||||
return handle.hasPermission(permission);
|
||||
}
|
||||
}
|
|
@ -1,73 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2020 GeyserMC. http://geysermc.org
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
* @author GeyserMC
|
||||
* @link https://github.com/GeyserMC/Geyser
|
||||
*/
|
||||
|
||||
package org.geysermc.platform.velocity.command;
|
||||
|
||||
import com.velocitypowered.api.command.CommandSource;
|
||||
import com.velocitypowered.api.command.SimpleCommand;
|
||||
import lombok.AllArgsConstructor;
|
||||
import org.geysermc.connector.GeyserConnector;
|
||||
import org.geysermc.connector.command.CommandSender;
|
||||
import org.geysermc.connector.command.GeyserCommand;
|
||||
import org.geysermc.connector.common.ChatColor;
|
||||
import org.geysermc.connector.utils.LanguageUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
@AllArgsConstructor
|
||||
public class GeyserVelocityCommandExecutor implements SimpleCommand {
|
||||
|
||||
private final GeyserConnector connector;
|
||||
|
||||
@Override
|
||||
public void execute(Invocation invocation) {
|
||||
if (invocation.arguments().length > 0) {
|
||||
if (getCommand(invocation.arguments()[0]) != null) {
|
||||
if (!invocation.source().hasPermission(getCommand(invocation.arguments()[0]).getPermission())) {
|
||||
CommandSender sender = new VelocityCommandSender(invocation.source());
|
||||
sender.sendMessage(ChatColor.RED + LanguageUtils.getPlayerLocaleString("geyser.bootstrap.command.permission_fail", sender.getLocale()));
|
||||
return;
|
||||
}
|
||||
getCommand(invocation.arguments()[0]).execute(new VelocityCommandSender(invocation.source()), invocation.arguments().length > 1 ? Arrays.copyOfRange(invocation.arguments(), 1, invocation.arguments().length) : new String[0]);
|
||||
}
|
||||
} else {
|
||||
getCommand("help").execute(new VelocityCommandSender(invocation.source()), new String[0]);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> suggest(Invocation invocation) {
|
||||
if (invocation.arguments().length == 0) {
|
||||
return connector.getCommandManager().getCommandNames();
|
||||
}
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
private GeyserCommand getCommand(String label) {
|
||||
return connector.getCommandManager().getCommands().get(label);
|
||||
}
|
||||
}
|
|
@ -6,22 +6,26 @@
|
|||
<parent>
|
||||
<groupId>org.geysermc</groupId>
|
||||
<artifactId>geyser-parent</artifactId>
|
||||
<version>1.2.0-SNAPSHOT</version>
|
||||
<version>2.0.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>common</artifactId>
|
||||
|
||||
<!-- Floodgate is still targeting Java 8 -->
|
||||
<properties>
|
||||
<maven.compiler.source>8</maven.compiler.source>
|
||||
<maven.compiler.target>8</maven.compiler.target>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.geysermc.cumulus</groupId>
|
||||
<artifactId>cumulus</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.code.gson</groupId>
|
||||
<artifactId>gson</artifactId>
|
||||
<version>2.8.2</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.datatype</groupId>
|
||||
<artifactId>jackson-datatype-jsr310</artifactId>
|
||||
<version>2.9.8</version>
|
||||
<scope>compile</scope>
|
||||
<version>2.8.6</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue