├── .editorconfig
├── .gitattributes
├── .github
├── ISSUE_TEMPLATE
│ ├── behavior-bug.yml
│ ├── config.yml
│ ├── feature-request.yml
│ ├── performance-problems.yml
│ └── server-crash-or-stacktrace.yml
└── workflows
│ └── build.yml
├── .gitignore
├── PATCHES-LICENSE
├── PROJECT_DESCRIPTION.md
├── README.md
├── REGION_LOGIC.md
├── build-data
├── dev-imports.txt
└── reobf-mappings-patch.tiny
├── build.gradle.kts
├── gradle.properties
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── install.bat
├── jar.bat
├── paperrecorder.png
├── patch.bat
├── patches
└── server
│ ├── 0001-Build-changes.patch
│ ├── 0002-ServerSideRecorder.patch
│ ├── 0003-ServerSideRecorder.patch
│ ├── 0004-ServerSideRecorder.patch
│ ├── 0005-ServerSideRecorder.patch
│ ├── 0006-ServerSideRecorder.patch
│ ├── 0007-ServerSideRecorder.patch
│ ├── 0008-ServerSideRecorder.patch
│ ├── 0009-ServerSideRecorder.patch
│ ├── 0010-ServerSideRecorder.patch
│ ├── 0011-ServerSideRecorder.patch
│ ├── 0012-ServerSideRecorder.patch
│ ├── 0013-ServerSideRecorder.patch
│ ├── 0014-ServerSideRecorder.patch
│ ├── 0015-ServerSideRecorder.patch
│ ├── 0016-ServerSideRecorder.patch
│ ├── 0017-ServerSideRecorder.patch
│ ├── 0018-ServerSideRecorder.patch
│ ├── 0019-ServerSideRecorder.patch
│ ├── 0020-ServerSideVoiceChat.patch
│ ├── 0021-ServerSideVoiceChat.patch
│ ├── 0022-ServerSideVoiceChat.patch
│ ├── 0023-Improved-Performance-For-Simple-Voice-Chat.patch
│ ├── 0024-Improved-Performance-For-Simple-Voice-Chat.patch
│ ├── 0025-Support-Region-Voice-Recording.patch
│ ├── 0026-Support-Region-Voice-Recording.patch
│ ├── 0027-Support-Region-Voice-Recording.patch
│ ├── 0028-Support-Region-Voice-Recording.patch
│ ├── 0029-Support-Region-Voice-Recording.patch
│ ├── 0030-Support-Region-Voice-Recording.patch
│ ├── 0031-Support-Region-Voice-Recording.patch
│ ├── 0032-Support-Region-Voice-Recording.patch
│ ├── 0033-Support-Region-Voice-Recording.patch
│ └── 0034-Support-Region-Voice-Recording.patch
├── rb.bat
├── regiontodo.txt
└── settings.gradle.kts
/.editorconfig:
--------------------------------------------------------------------------------
1 | [*.java]
2 | charset=utf-8
3 | end_of_line=lf
4 | insert_final_newline=true
5 | indent_style=space
6 | indent_size=4
7 |
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | * text=auto
2 |
3 | *.sh text eol=lf
4 | gradlew text eol=lf
5 | *.bat text eol=crlf
6 |
7 | *.jar binary
8 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/behavior-bug.yml:
--------------------------------------------------------------------------------
1 | name: Behavior Bug
2 | description: Report behavior related issues, where Folia does not work like vanilla. Paper and Bukkit plugins are not guaranteed to work on Folia. Do not submit bug reports for plugin issues here.
3 | labels: [ "status: needs triage", "type: bug" ]
4 | body:
5 | - type: textarea
6 | attributes:
7 | label: Expected behavior
8 | description: What you expected to see.
9 | validations:
10 | required: true
11 |
12 | - type: textarea
13 | attributes:
14 | label: Observed/Actual behavior
15 | description: What you actually saw.
16 | validations:
17 | required: true
18 |
19 | - type: textarea
20 | attributes:
21 | label: Steps/models to reproduce
22 | description: This may include a build schematic, a video, or detailed instructions to help reconstruct the issue.
23 | validations:
24 | required: true
25 |
26 | - type: textarea
27 | attributes:
28 | label: Plugin and Datapack List
29 | description: |
30 | All plugins and datapacks running on your server.
31 | To list plugins, run `/plugins`. For datapacks, run `/datapack list`.
32 | validations:
33 | required: true
34 |
35 | - type: textarea
36 | attributes:
37 | label: Folia version
38 | description: |
39 | Run `/version` on your server and **paste** the full, unmodified output here.
40 | "latest" is *not* a version; we require the output of `/version` so we can adequately track down the issue.
41 | Additionally, do NOT provide a screenshot, you MUST paste the entire output.
42 |
43 | Example
44 |
45 | ```
46 | > version
47 | [10:00:11 INFO]: Checking version, please wait...
48 | [10:00:12 INFO]: This server is running Folia version git-Folia-"5b74945" (MC: 1.19.4) (Implementing API version 1.19.4-R0.1-SNAPSHOT) (Git: 5b74945)
49 | You are running the latest version
50 | Previous version: git-Paper-481 (MC: 1.19.4)
51 | ```
52 |
53 |
54 | validations:
55 | required: true
56 |
57 | - type: textarea
58 | attributes:
59 | label: Other
60 | description: |
61 | Please include other helpful information below.
62 | The more information we receive, the quicker and more effective we can be at finding the solution to the issue.
63 | validations:
64 | required: false
65 |
66 | - type: markdown
67 | attributes:
68 | value: |
69 | Before submitting this issue, please ensure the following:
70 |
71 | 1. You are running the latest version of Folia from [our downloads page](https://papermc.io/downloads).
72 | 2. You searched for and ensured there isn't already an open issue regarding this.
73 | 3. Your version of Minecraft is supported by Folia.
74 |
75 | If you think you have a bug but are not sure, feel free to ask the `#folia-help` channel of our
76 | [Discord](https://discord.gg/papermc).
77 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/config.yml:
--------------------------------------------------------------------------------
1 | blank_issues_enabled: false
2 | contact_links:
3 | - name: PaperMC Discord
4 | url: https://discord.gg/papermc
5 | about: If you are having minor issues, come ask us on our Discord server!
6 | - name: Exploit Report
7 | url: https://discord.gg/papermc
8 | about: |
9 | Due to GitHub not currently allowing private issues, exploit reports are currently handled via our Discord.
10 | To report an exploit, see the #paper-exploit-report channel.
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/feature-request.yml:
--------------------------------------------------------------------------------
1 | name: Feature Request
2 | description: Suggest an idea for Folia
3 | labels: [ "status: needs triage", "type: feature" ]
4 | body:
5 | - type: markdown
6 | attributes:
7 | value: |
8 | Thank you for filling out a feature request for Folia! Please be as detailed as possible so that we may consider and review the request easier.
9 | We ask that you search all the issues to avoid a duplicate feature request. If one exists, please reply if you have anything to add.
10 | Before requesting a new feature, please make sure you are using the latest version and that the feature you are requesting is not already in Folia.
11 |
12 | - type: textarea
13 | attributes:
14 | label: Is your feature request related to a problem?
15 | description: Please give some context for this request. Why do you want it added?
16 | validations:
17 | required: true
18 |
19 | - type: textarea
20 | attributes:
21 | label: Describe the solution you'd like.
22 | description: A clear and concise description of what you want.
23 | validations:
24 | required: true
25 |
26 | - type: textarea
27 | attributes:
28 | label: Describe alternatives you've considered.
29 | description: List any alternatives you might have tried to get the feature you want.
30 | validations:
31 | required: true
32 |
33 | - type: textarea
34 | attributes:
35 | label: Other
36 | description: Add any other context or screenshots about the feature request below.
37 | validations:
38 | required: false
39 |
40 | - type: markdown
41 | attributes:
42 | value: |
43 | Before submitting this feature request, please search our issue tracker to ensure your feature has not
44 | already been requested.
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/performance-problems.yml:
--------------------------------------------------------------------------------
1 | name: Performance Problem
2 | description: Report performance related problems or other areas of concern
3 | labels: [ "status: needs triage", "type: performance" ]
4 | body:
5 | - type: markdown
6 | attributes:
7 | value: |
8 | Before creating an issue regarding server performance, please consider reaching out for support in the
9 | `#folia-help` channel of [our Discord](https://discord.gg/papermc)!
10 |
11 | - type: input
12 | attributes:
13 | label: Profile link
14 | description: We ask that all profiles are a link, not a screenshot. Screenshots inhibit our ability to figure out the real cause of the issue.
15 | placeholder: "Example: https://spark.lucko.me/abcdefg12h"
16 | validations:
17 | required: true
18 |
19 | - type: textarea
20 | attributes:
21 | label: Description of issue
22 | description: If applicable, please describe your issue.
23 | validations:
24 | required: false
25 |
26 | - type: textarea
27 | attributes:
28 | label: Plugin and Datapack List
29 | description: |
30 | All plugins and datapacks running on your server.
31 | To list plugins, run `/plugins`. For datapacks, run `/datapack list`.
32 | validations:
33 | required: true
34 |
35 | - type: textarea
36 | attributes:
37 | label: Server config files
38 | description: We need bukkit.yml, spigot.yml, paper-global.yml, paper-world-defaults.yml and server.properties. If you use per-world Paper configs, make sure to include them. You can paste it below or use a paste site like https://paste.gg.
39 | value: |
40 | ```
41 | Paste configs or paste.gg link here!
42 | ```
43 | placeholder: Please don't remove the backticks; it makes your issue a lot harder to read!
44 | validations:
45 | required: true
46 |
47 | - type: textarea
48 | attributes:
49 | label: Folia version
50 | description: |
51 | Run `/version` on your server and **paste** the full, unmodified output here.
52 | "latest" is *not* a version; we require the output of `/version` so we can adequately track down the issue.
53 | Additionally, do NOT provide a screenshot, you MUST paste the entire output.
54 |
55 | Example
56 |
57 | ```
58 | > version
59 | [10:00:11 INFO]: Checking version, please wait...
60 | [10:00:12 INFO]: This server is running Folia version git-Folia-"5b74945" (MC: 1.19.4) (Implementing API version 1.19.4-R0.1-SNAPSHOT) (Git: 5b74945)
61 | You are running the latest version
62 | Previous version: git-Paper-481 (MC: 1.19.4)
63 | ```
64 |
65 |
66 | validations:
67 | required: true
68 |
69 | - type: textarea
70 | attributes:
71 | label: Other
72 | description: |
73 | Please include other helpful links below.
74 | The more information we receive, the quicker and more effective we can be at finding the solution to the issue.
75 | validations:
76 | required: false
77 | - type: markdown
78 | attributes:
79 | value: |
80 | Before submitting this issue, please ensure the following:
81 |
82 | 1. You are running the latest version of Folia from [our downloads page](https://papermc.io/downloads).
83 | 2. You searched for and ensured there isn't already an open issue regarding this.
84 | 3. Your version of Minecraft is supported by Folia.
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/server-crash-or-stacktrace.yml:
--------------------------------------------------------------------------------
1 | name: Server crash or Stacktrace
2 | description: Report server crashes or scary stacktraces
3 | labels: [ "status: needs triage" ]
4 | body:
5 | - type: textarea
6 | attributes:
7 | label: Stack trace
8 | description: |
9 | We need all of the stack trace! Do not cut off parts of it. Please do not use attachments.
10 | If you prefer, you can use a paste site like https://paste.gg.
11 | value: |
12 | ```
13 | paste your stack trace or a paste.gg link here!
14 | ```
15 | placeholder: Please don't remove the backticks; it makes your issue a lot harder to read!
16 | validations:
17 | required: true
18 |
19 | - type: textarea
20 | attributes:
21 | label: Plugin and Datapack List
22 | description: |
23 | All plugins and datapacks running on your server.
24 | To list plugins, run `/plugins`. For datapacks, run `/datapack list`.
25 | validations:
26 | required: true
27 |
28 | - type: textarea
29 | attributes:
30 | label: Actions to reproduce (if known)
31 | description: This may include a build schematic, a video, or detailed instructions to help reconstruct the issue. Anything helps!
32 | validations:
33 | required: false
34 |
35 | - type: textarea
36 | attributes:
37 | label: Folia version
38 | description: |
39 | Run `/version` on your server and **paste** the full, unmodified output here.
40 | "latest" is *not* a version; we require the output of `/version` so we can adequately track down the issue.
41 | Additionally, do NOT provide a screenshot, you MUST paste the entire output.
42 |
43 | Example
44 |
45 | ```
46 | > version
47 | [10:00:11 INFO]: Checking version, please wait...
48 | [10:00:12 INFO]: This server is running Folia version git-Folia-"5b74945" (MC: 1.19.4) (Implementing API version 1.19.4-R0.1-SNAPSHOT) (Git: 5b74945)
49 | You are running the latest version
50 | Previous version: git-Paper-481 (MC: 1.19.4)
51 | ```
52 |
53 |
54 | validations:
55 | required: true
56 |
57 | - type: textarea
58 | attributes:
59 | label: Other
60 | description: |
61 | Please include other helpful information below, if any.
62 | The more information we receive, the quicker and more effective we can be at finding the solution to the issue.
63 | validations:
64 | required: false
65 |
66 | - type: markdown
67 | attributes:
68 | value: |
69 | Before submitting this issue, please ensure the following:
70 |
71 | 1. You are running the latest version of Folia from [our downloads page](https://papermc.io/downloads).
72 | 2. Your version of Minecraft is supported by Folia.
73 |
74 | If your server crash log contains `DO NOT REPORT THIS TO FOLIA`, please ask in our
75 | [Discord](https://discord.gg/papermc) before opening this issue. These messages are informing you of server
76 | lag and providing debug information.
--------------------------------------------------------------------------------
/.github/workflows/build.yml:
--------------------------------------------------------------------------------
1 | name: Patch and Build
2 |
3 | on:
4 | push:
5 | branches: [ "**"]
6 | pull_request:
7 |
8 | jobs:
9 | build:
10 | # Only run on PRs if the source branch is on someone else's repo
11 | if: ${{ github.event_name != 'pull_request' || github.repository != github.event.pull_request.head.repo.full_name }}
12 | runs-on: ubuntu-latest
13 | steps:
14 | - name: Checking Environment
15 | run: |
16 | echo "Compile_Date=$(date +%Y%m%d%H%M)" >> $GITHUB_ENV
17 | - name: Checkout Git Repository
18 | uses: actions/checkout@v3
19 | - name: Validate Gradle wrapper
20 | uses: gradle/wrapper-validation-action@v1
21 | - name: Setup Gradle
22 | uses: gradle/gradle-build-action@v2
23 | - name: Set up JDK
24 | uses: actions/setup-java@v3
25 | with:
26 | distribution: 'temurin'
27 | java-version: '17'
28 | - name: Configure Git User Details
29 | run: git config --global user.email "actions@github.com" && git config --global user.name "Github Actions"
30 | - name: Apply Patches
31 | run: ./gradlew applyPatches
32 | - name: Build Bundler & Paperclip
33 | run: ./gradlew createReobfBundlerJar
34 | - name: capture build artifacts
35 | uses: actions/upload-artifact@v2
36 | with:
37 | name: Artifacts
38 | path: build/libs/
39 | - name: Create Release Tag
40 | uses: rickstaa/action-create-tag@v1
41 | with:
42 | tag: "v1_20_1-${{ env.Compile_Date }}"
43 | message: "1.20.1 Build ${{ env.Compile_Date }}"
44 | - name: Upload Build to Release
45 | uses: svenstaro/upload-release-action@v2
46 | with:
47 | repo_token: ${{ secrets.GITHUB_TOKEN }}
48 | file: build/libs/*
49 | file_glob: true
50 | tag: "v1_20_1-${{ env.Compile_Date }}"
51 | release_name: "1.20.1_PaperRecord-${{ env.Compile_Date }}"
52 | overwrite: true
53 | prerelease: false
54 | body: |
55 | PaperRecord Build
56 | Version: 1.20.1
57 | Build Time: ${{ env.Compile_Date }}
58 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .gradle/
2 | build/
3 |
4 | # Eclipse stuff
5 | .classpath
6 | .project
7 | .settings/
8 |
9 | # VSCode stuff
10 | .vscode/
11 |
12 | # netbeans
13 | nbproject/
14 | nbactions.xml
15 |
16 | # we use maven!
17 | build.xml
18 |
19 | # maven
20 | target/
21 | dependency-reduced-pom.xml
22 |
23 | # vim
24 | .*.sw[a-p]
25 |
26 | # various other potential build files
27 | build/
28 | bin/
29 | dist/
30 | manifest.mf
31 |
32 | # Mac filesystem dust
33 | .DS_Store/
34 | .DS_Store
35 |
36 | # intellij
37 | *.iml
38 | *.ipr
39 | *.iws
40 | .idea/
41 | out/
42 |
43 | # Linux temp files
44 | *~
45 |
46 | # other stuff
47 | run/
48 |
49 | Folia-Server
50 | Folia-API
51 | PaperRecord-Server
52 | PaperRecord-API
53 |
54 | !gradle/wrapper/gradle-wrapper.jar
55 |
--------------------------------------------------------------------------------
/PATCHES-LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2022
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in
13 | all copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 | THE SOFTWARE.
22 |
--------------------------------------------------------------------------------
/PROJECT_DESCRIPTION.md:
--------------------------------------------------------------------------------
1 | # Project overview
2 |
3 | This page has been moved to [the PaperMC documentation](https://docs.papermc.io/folia/reference/overview) site.
4 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |

3 |
4 |
PaperRecorder
5 |
6 |
7 |
8 | ## Overview
9 | PaperRecorder for 1.20.1 is a Fork of paper allowing players to record players and replay it using the replay mod.
10 | Original Mod for ServerSideReplayRecorder https://github.com/thecolonel63/server-side-replay-recorder
11 |
12 | ## Commands
13 | **/replay players (add|remove|list)** - Add/list/remove players to/from the blacklist/whitelist
14 | **/replay status** - Show the active recording list as well as if recording is enabled
15 | **/replay status (enable|disable)** - Toggle recording across entire mod
16 | **/replay region (start|stop|status)** - Enable recording of a pre-defined large area independent of players
17 | **/replay file (player|region)** - Delete / Upload replay files without manually accessing the replay folder
18 | **/replay marker (player|region)** - Add a marker to the specified replay file
19 |
20 | ## Config
21 | Config is in **/config/ServerSideReplayRecorder.yml**
22 |
23 | # Compatibility
24 | This Paper Fork is compatible with [Simple Voice Chat](https://modrinth.com/plugin/simple-voice-chat).
25 | To use please download the [Simple Voice Chat](https://modrinth.com/plugin/simple-voice-chat) plugin for Bukkit and install in the plugins folder
26 | and PaperRecorder will take care of the rest. To hear the voices in the [Replay Mod](https://modrinth.com/mod/replaymod) please download
27 | [Replay Voice Chat](https://modrinth.com/mod/replay-voice-chat)
28 |
29 | ## License
30 | The PATCHES-LICENSE file describes the license for api & server patches,
31 | found in `./patches` and its subdirectories except when noted otherwise.
32 |
33 | The fork is based off of PaperMC's fork example found [here](https://github.com/PaperMC/paperweight-examples).
34 | As such, it contains modifications to it in this project, please see the repository for license information
35 | of modified files.
36 |
--------------------------------------------------------------------------------
/REGION_LOGIC.md:
--------------------------------------------------------------------------------
1 | # Region Logic
2 |
3 | This page has been moved to [the PaperMC documentation](https://docs.papermc.io/folia/reference/region-logic) site.
4 |
--------------------------------------------------------------------------------
/build-data/dev-imports.txt:
--------------------------------------------------------------------------------
1 | # You can use this file to import files from minecraft libraries into the project
2 | # format:
3 | #
4 | # both fully qualified and a file based syntax are accepted for :
5 | # authlib com/mojang/authlib/yggdrasil/YggdrasilGameProfileRepository.java
6 | # datafixerupper com.mojang.datafixers.DataFixerBuilder
7 | # datafixerupper com/mojang/datafixers/util/Either.java
8 | # To import classes from the vanilla Minecraft jar use `minecraft` as the artifactId:
9 | # minecraft net.minecraft.world.level.entity.LevelEntityGetterAdapter
10 | # minecraft net/minecraft/world/level/entity/LevelEntityGetter.java
11 |
--------------------------------------------------------------------------------
/build-data/reobf-mappings-patch.tiny:
--------------------------------------------------------------------------------
1 | # We would like for paperweight to generate 100% perfect reobf mappings (and deobf mappings for that matter).
2 | # But unfortunately it's not quite there yet - and it may be some time before that happens. Generating perfect mappings
3 | # from Spigot's mappings is extremely difficult due to Spigot's bad tooling and bad mappings. To add insult to injury
4 | # we remap Spigot's _source code_ which is a lot more complex and error-prone than bytecode remapping. So with all that
5 | # said, this file exists to help fill in the gap.
6 | #
7 | # We will continue to improve paperweight and will work on fixing these issues so they don't come up in the first place,
8 | # but these mappings exist to prevent these issues from holding everything else in Paper up while we work through all
9 | # of these issues. Due to the complex nature of mappings generation and the debugging difficulty involved it may take
10 | # a significant amount of time for us to track down every possible issue, so this file will likely be around and in
11 | # use - at least in some capacity - for a long time.
12 | #
13 | # If you are adding mappings patches which are correcting for issues in paperweight's reobf mappings generation,
14 | # unrelated to any changes in your patches, we ask that you PR the mapping to Paper so more users can benefit rather
15 | # than keep the fix for your own fork. If the mappings patch is there to correct reobf for changes made in your patches,
16 | # then obviously it doesn't make any sense to PR them upstream.
17 |
18 | tiny 2 0 mojang+yarn spigot
19 |
--------------------------------------------------------------------------------
/build.gradle.kts:
--------------------------------------------------------------------------------
1 | import io.papermc.paperweight.tasks.RebuildGitPatches
2 |
3 | plugins {
4 | java
5 | `maven-publish`
6 | id("com.github.johnrengelman.shadow") version "8.1.1" apply false
7 | id("io.papermc.paperweight.patcher") version "1.5.5"
8 | }
9 |
10 | val paperMavenPublicUrl = "https://repo.papermc.io/repository/maven-public/"
11 | val voicechatMavenPublicUrl = "https://maven.maxhenkel.de/repository/public"
12 | val modrinthMavenPublicUrl = "https://api.modrinth.com/maven"
13 | repositories {
14 | mavenCentral()
15 | maven(paperMavenPublicUrl) {
16 | content { onlyForConfigurations(configurations.paperclip.name) }
17 | }
18 |
19 | }
20 |
21 | dependencies {
22 | remapper("net.fabricmc:tiny-remapper:0.8.6:fat")
23 | decompiler("net.minecraftforge:forgeflower:2.0.627.2")
24 | paperclip("io.papermc:paperclip:3.0.3")
25 | }
26 |
27 | allprojects {
28 | apply(plugin = "java")
29 | apply(plugin = "maven-publish")
30 |
31 | java {
32 | toolchain {
33 | languageVersion.set(JavaLanguageVersion.of(17))
34 | }
35 | }
36 | }
37 |
38 | subprojects {
39 | tasks.withType {
40 | options.encoding = Charsets.UTF_8.name()
41 | options.release.set(17)
42 | }
43 | tasks.withType {
44 | options.encoding = Charsets.UTF_8.name()
45 | }
46 | tasks.withType {
47 | filteringCharset = Charsets.UTF_8.name()
48 | }
49 |
50 | repositories {
51 | mavenCentral()
52 | maven(paperMavenPublicUrl)
53 | maven(voicechatMavenPublicUrl)
54 | maven(modrinthMavenPublicUrl)
55 | }
56 | }
57 |
58 | paperweight {
59 | serverProject.set(project(":paperrecord-server"))
60 |
61 | remapRepo.set(paperMavenPublicUrl)
62 | decompileRepo.set(paperMavenPublicUrl)
63 |
64 | usePaperUpstream(providers.gradleProperty("paperRef")) {
65 | withPaperPatcher {
66 | apiPatchDir.set(layout.projectDirectory.dir("patches/api"))
67 | apiOutputDir.set(layout.projectDirectory.dir("PaperRecord-API"))
68 |
69 | serverPatchDir.set(layout.projectDirectory.dir("patches/server"))
70 | serverOutputDir.set(layout.projectDirectory.dir("PaperRecord-Server"))
71 | }
72 | }
73 | }
74 |
75 | tasks.generateDevelopmentBundle {
76 | apiCoordinates.set("dev.paperrecord:paperrecord-api")
77 | mojangApiCoordinates.set("io.papermc.paper:paper-mojangapi")
78 | libraryRepositories.addAll(
79 | "https://repo.maven.apache.org/maven2/",
80 | paperMavenPublicUrl,
81 | )
82 | }
83 |
84 | allprojects {
85 | publishing {
86 | repositories {
87 | maven("https://repo.papermc.io/repository/maven-snapshots/") {
88 | name = "paperSnapshots"
89 | credentials(PasswordCredentials::class)
90 | }
91 | }
92 | }
93 | }
94 |
95 | publishing {
96 | if (project.hasProperty("publishDevBundle")) {
97 | publications.create("devBundle") {
98 | artifact(tasks.generateDevelopmentBundle) {
99 | artifactId = "dev-bundle"
100 | }
101 | }
102 | }
103 | }
104 |
105 | tasks.withType {
106 | filterPatches.set(false)
107 | }
108 |
109 | tasks.register("printMinecraftVersion") {
110 | doLast {
111 | println(providers.gradleProperty("mcVersion").get().trim())
112 | }
113 | }
114 |
115 | tasks.register("printPaperVersion") {
116 | doLast {
117 | println(project.version)
118 | }
119 | }
120 |
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | group=dev.paperrecord
2 |
3 | version=1.20.1-R0.1-SNAPSHOT
4 | mcVersion=1.20.1
5 | paperRef=e8bec64217064476784a5c65a5060cfc0145fa98
6 |
7 | org.gradle.caching=true
8 | org.gradle.parallel=true
9 | org.gradle.vfs.watch=false
10 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Moyettes/PaperRecorder/b72f6a1f0ca38ba4315950b6cd27736658391a48/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionBase=GRADLE_USER_HOME
2 | distributionPath=wrapper/dists
3 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.0.2-bin.zip
4 | networkTimeout=10000
5 | zipStoreBase=GRADLE_USER_HOME
6 | zipStorePath=wrapper/dists
7 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | #
4 | # Copyright © 2015-2021 the original authors.
5 | #
6 | # Licensed under the Apache License, Version 2.0 (the "License");
7 | # you may not use this file except in compliance with the License.
8 | # You may obtain a copy of the License at
9 | #
10 | # https://www.apache.org/licenses/LICENSE-2.0
11 | #
12 | # Unless required by applicable law or agreed to in writing, software
13 | # distributed under the License is distributed on an "AS IS" BASIS,
14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | # See the License for the specific language governing permissions and
16 | # limitations under the License.
17 | #
18 |
19 | ##############################################################################
20 | #
21 | # Gradle start up script for POSIX generated by Gradle.
22 | #
23 | # Important for running:
24 | #
25 | # (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
26 | # noncompliant, but you have some other compliant shell such as ksh or
27 | # bash, then to run this script, type that shell name before the whole
28 | # command line, like:
29 | #
30 | # ksh Gradle
31 | #
32 | # Busybox and similar reduced shells will NOT work, because this script
33 | # requires all of these POSIX shell features:
34 | # * functions;
35 | # * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
36 | # «${var#prefix}», «${var%suffix}», and «$( cmd )»;
37 | # * compound commands having a testable exit status, especially «case»;
38 | # * various built-in commands including «command», «set», and «ulimit».
39 | #
40 | # Important for patching:
41 | #
42 | # (2) This script targets any POSIX shell, so it avoids extensions provided
43 | # by Bash, Ksh, etc; in particular arrays are avoided.
44 | #
45 | # The "traditional" practice of packing multiple parameters into a
46 | # space-separated string is a well documented source of bugs and security
47 | # problems, so this is (mostly) avoided, by progressively accumulating
48 | # options in "$@", and eventually passing that to Java.
49 | #
50 | # Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
51 | # and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
52 | # see the in-line comments for details.
53 | #
54 | # There are tweaks for specific operating systems such as AIX, CygWin,
55 | # Darwin, MinGW, and NonStop.
56 | #
57 | # (3) This script is generated from the Groovy template
58 | # https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
59 | # within the Gradle project.
60 | #
61 | # You can find Gradle at https://github.com/gradle/gradle/.
62 | #
63 | ##############################################################################
64 |
65 | # Attempt to set APP_HOME
66 |
67 | # Resolve links: $0 may be a link
68 | app_path=$0
69 |
70 | # Need this for daisy-chained symlinks.
71 | while
72 | APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
73 | [ -h "$app_path" ]
74 | do
75 | ls=$( ls -ld "$app_path" )
76 | link=${ls#*' -> '}
77 | case $link in #(
78 | /*) app_path=$link ;; #(
79 | *) app_path=$APP_HOME$link ;;
80 | esac
81 | done
82 |
83 | # This is normally unused
84 | # shellcheck disable=SC2034
85 | APP_BASE_NAME=${0##*/}
86 | APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
87 |
88 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
89 | DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
90 |
91 | # Use the maximum available, or set MAX_FD != -1 to use that value.
92 | MAX_FD=maximum
93 |
94 | warn () {
95 | echo "$*"
96 | } >&2
97 |
98 | die () {
99 | echo
100 | echo "$*"
101 | echo
102 | exit 1
103 | } >&2
104 |
105 | # OS specific support (must be 'true' or 'false').
106 | cygwin=false
107 | msys=false
108 | darwin=false
109 | nonstop=false
110 | case "$( uname )" in #(
111 | CYGWIN* ) cygwin=true ;; #(
112 | Darwin* ) darwin=true ;; #(
113 | MSYS* | MINGW* ) msys=true ;; #(
114 | NONSTOP* ) nonstop=true ;;
115 | esac
116 |
117 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
118 |
119 |
120 | # Determine the Java command to use to start the JVM.
121 | if [ -n "$JAVA_HOME" ] ; then
122 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
123 | # IBM's JDK on AIX uses strange locations for the executables
124 | JAVACMD=$JAVA_HOME/jre/sh/java
125 | else
126 | JAVACMD=$JAVA_HOME/bin/java
127 | fi
128 | if [ ! -x "$JAVACMD" ] ; then
129 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
130 |
131 | Please set the JAVA_HOME variable in your environment to match the
132 | location of your Java installation."
133 | fi
134 | else
135 | JAVACMD=java
136 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
137 |
138 | Please set the JAVA_HOME variable in your environment to match the
139 | location of your Java installation."
140 | fi
141 |
142 | # Increase the maximum file descriptors if we can.
143 | if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
144 | case $MAX_FD in #(
145 | max*)
146 | # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
147 | # shellcheck disable=SC3045
148 | MAX_FD=$( ulimit -H -n ) ||
149 | warn "Could not query maximum file descriptor limit"
150 | esac
151 | case $MAX_FD in #(
152 | '' | soft) :;; #(
153 | *)
154 | # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
155 | # shellcheck disable=SC3045
156 | ulimit -n "$MAX_FD" ||
157 | warn "Could not set maximum file descriptor limit to $MAX_FD"
158 | esac
159 | fi
160 |
161 | # Collect all arguments for the java command, stacking in reverse order:
162 | # * args from the command line
163 | # * the main class name
164 | # * -classpath
165 | # * -D...appname settings
166 | # * --module-path (only if needed)
167 | # * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
168 |
169 | # For Cygwin or MSYS, switch paths to Windows format before running java
170 | if "$cygwin" || "$msys" ; then
171 | APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
172 | CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
173 |
174 | JAVACMD=$( cygpath --unix "$JAVACMD" )
175 |
176 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
177 | for arg do
178 | if
179 | case $arg in #(
180 | -*) false ;; # don't mess with options #(
181 | /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
182 | [ -e "$t" ] ;; #(
183 | *) false ;;
184 | esac
185 | then
186 | arg=$( cygpath --path --ignore --mixed "$arg" )
187 | fi
188 | # Roll the args list around exactly as many times as the number of
189 | # args, so each arg winds up back in the position where it started, but
190 | # possibly modified.
191 | #
192 | # NB: a `for` loop captures its iteration list before it begins, so
193 | # changing the positional parameters here affects neither the number of
194 | # iterations, nor the values presented in `arg`.
195 | shift # remove old arg
196 | set -- "$@" "$arg" # push replacement arg
197 | done
198 | fi
199 |
200 | # Collect all arguments for the java command;
201 | # * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
202 | # shell script including quotes and variable substitutions, so put them in
203 | # double quotes to make sure that they get re-expanded; and
204 | # * put everything else in single quotes, so that it's not re-expanded.
205 |
206 | set -- \
207 | "-Dorg.gradle.appname=$APP_BASE_NAME" \
208 | -classpath "$CLASSPATH" \
209 | org.gradle.wrapper.GradleWrapperMain \
210 | "$@"
211 |
212 | # Stop when "xargs" is not available.
213 | if ! command -v xargs >/dev/null 2>&1
214 | then
215 | die "xargs is not available"
216 | fi
217 |
218 | # Use "xargs" to parse quoted args.
219 | #
220 | # With -n1 it outputs one arg per line, with the quotes and backslashes removed.
221 | #
222 | # In Bash we could simply go:
223 | #
224 | # readarray ARGS < <( xargs -n1 <<<"$var" ) &&
225 | # set -- "${ARGS[@]}" "$@"
226 | #
227 | # but POSIX shell has neither arrays nor command substitution, so instead we
228 | # post-process each arg (as a line of input to sed) to backslash-escape any
229 | # character that might be a shell metacharacter, then use eval to reverse
230 | # that process (while maintaining the separation between arguments), and wrap
231 | # the whole thing up as a single "set" statement.
232 | #
233 | # This will of course break if any of these variables contains a newline or
234 | # an unmatched quote.
235 | #
236 |
237 | eval "set -- $(
238 | printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
239 | xargs -n1 |
240 | sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
241 | tr '\n' ' '
242 | )" '"$@"'
243 |
244 | exec "$JAVACMD" "$@"
245 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @rem
2 | @rem Copyright 2015 the original author or authors.
3 | @rem
4 | @rem Licensed under the Apache License, Version 2.0 (the "License");
5 | @rem you may not use this file except in compliance with the License.
6 | @rem You may obtain a copy of the License at
7 | @rem
8 | @rem https://www.apache.org/licenses/LICENSE-2.0
9 | @rem
10 | @rem Unless required by applicable law or agreed to in writing, software
11 | @rem distributed under the License is distributed on an "AS IS" BASIS,
12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | @rem See the License for the specific language governing permissions and
14 | @rem limitations under the License.
15 | @rem
16 |
17 | @if "%DEBUG%"=="" @echo off
18 | @rem ##########################################################################
19 | @rem
20 | @rem Gradle startup script for Windows
21 | @rem
22 | @rem ##########################################################################
23 |
24 | @rem Set local scope for the variables with windows NT shell
25 | if "%OS%"=="Windows_NT" setlocal
26 |
27 | set DIRNAME=%~dp0
28 | if "%DIRNAME%"=="" set DIRNAME=.
29 | @rem This is normally unused
30 | set APP_BASE_NAME=%~n0
31 | set APP_HOME=%DIRNAME%
32 |
33 | @rem Resolve any "." and ".." in APP_HOME to make it shorter.
34 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
35 |
36 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
37 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
38 |
39 | @rem Find java.exe
40 | if defined JAVA_HOME goto findJavaFromJavaHome
41 |
42 | set JAVA_EXE=java.exe
43 | %JAVA_EXE% -version >NUL 2>&1
44 | if %ERRORLEVEL% equ 0 goto execute
45 |
46 | echo.
47 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
48 | echo.
49 | echo Please set the JAVA_HOME variable in your environment to match the
50 | echo location of your Java installation.
51 |
52 | goto fail
53 |
54 | :findJavaFromJavaHome
55 | set JAVA_HOME=%JAVA_HOME:"=%
56 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
57 |
58 | if exist "%JAVA_EXE%" goto execute
59 |
60 | echo.
61 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
62 | echo.
63 | echo Please set the JAVA_HOME variable in your environment to match the
64 | echo location of your Java installation.
65 |
66 | goto fail
67 |
68 | :execute
69 | @rem Setup the command line
70 |
71 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
72 |
73 |
74 | @rem Execute Gradle
75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
76 |
77 | :end
78 | @rem End local scope for the variables with windows NT shell
79 | if %ERRORLEVEL% equ 0 goto mainEnd
80 |
81 | :fail
82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
83 | rem the _cmd.exe /c_ return code!
84 | set EXIT_CODE=%ERRORLEVEL%
85 | if %EXIT_CODE% equ 0 set EXIT_CODE=1
86 | if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
87 | exit /b %EXIT_CODE%
88 |
89 | :mainEnd
90 | if "%OS%"=="Windows_NT" endlocal
91 |
92 | :omega
93 |
--------------------------------------------------------------------------------
/install.bat:
--------------------------------------------------------------------------------
1 | ./gradlew publishToMavenLocal
--------------------------------------------------------------------------------
/jar.bat:
--------------------------------------------------------------------------------
1 | ./gradlew createMojmapPaperclipJar
--------------------------------------------------------------------------------
/paperrecorder.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Moyettes/PaperRecorder/b72f6a1f0ca38ba4315950b6cd27736658391a48/paperrecorder.png
--------------------------------------------------------------------------------
/patch.bat:
--------------------------------------------------------------------------------
1 | ./gradlew applypatches
--------------------------------------------------------------------------------
/patches/server/0005-ServerSideRecorder.patch:
--------------------------------------------------------------------------------
1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
2 | From: Bryan1029384756 <23323626+Bryan1029384756@users.noreply.github.com>
3 | Date: Sat, 17 Jun 2023 23:00:30 -0500
4 | Subject: [PATCH] ServerSideRecorder
5 |
6 |
7 | diff --git a/src/main/java/net/minecraft/serversidereplayrecorder/ServerSideReplayRecorderServer.java b/src/main/java/net/minecraft/serversidereplayrecorder/ServerSideReplayRecorderServer.java
8 | index be30a4f207069228d62990614bfcea30415a7e62..198841e836943e20e65d75a432884b709c9e405f 100644
9 | --- a/src/main/java/net/minecraft/serversidereplayrecorder/ServerSideReplayRecorderServer.java
10 | +++ b/src/main/java/net/minecraft/serversidereplayrecorder/ServerSideReplayRecorderServer.java
11 | @@ -8,6 +8,7 @@ import org.slf4j.Logger;
12 | import org.slf4j.LoggerFactory;
13 |
14 | import java.io.*;
15 | +import java.nio.file.Path;
16 | import java.util.ResourceBundle;
17 | import java.util.concurrent.ExecutorService;
18 | import java.util.concurrent.Executors;
19 | @@ -15,57 +16,68 @@ import java.util.concurrent.Executors;
20 | public class ServerSideReplayRecorderServer {
21 |
22 | static {
23 | - YAMLFactoryBuilder builder = YAMLFactory.builder();
24 | - builder.disable(YAMLGenerator.Feature.WRITE_DOC_START_MARKER);
25 | - builder.enable(YAMLGenerator.Feature.INDENT_ARRAYS_WITH_INDICATOR);
26 | - yaml = new ObjectMapper(builder.build()).configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
27 | - placeholders = ResourceBundle.getBundle("placeholders");
28 | - upload_sites = ResourceBundle.getBundle("upload_sites");
29 | +// YAMLFactoryBuilder builder = YAMLFactory.builder();
30 | +// builder.disable(YAMLGenerator.Feature.WRITE_DOC_START_MARKER);
31 | +// builder.enable(YAMLGenerator.Feature.INDENT_ARRAYS_WITH_INDICATOR);
32 | +// yaml = new ObjectMapper(builder.build()).configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
33 | +// placeholders = ResourceBundle.getBundle("placeholders");
34 | +// upload_sites = ResourceBundle.getBundle("upload_sites");
35 | }
36 |
37 | public static final ExecutorService recorderExecutor = Executors.newSingleThreadExecutor(new DefaultThreadFactory("Replay",true));
38 |
39 | - private static final ObjectMapper yaml;
40 | -
41 | - public static final ResourceBundle placeholders;
42 | - public static final ResourceBundle upload_sites;
43 | +// private static final ObjectMapper yaml;
44 | +//
45 | +// public static final ResourceBundle placeholders;
46 | +// public static final ResourceBundle upload_sites;
47 |
48 | public static final Logger LOGGER = LoggerFactory.getLogger(ServerSideReplayRecorderServer.class.getName());
49 |
50 | public static MinecraftServer server;
51 |
52 | - public static final String configPath = FabricLoader.getInstance().getConfigDir() + "/ServerSideReplayRecorder.yml";
53 | + public static final String configPath = getConfigDirectory() + "/ServerSideReplayRecorder.yml";
54 | public static MainConfig config = new MainConfig();
55 |
56 | - public static void loadConfig() {
57 | - try {
58 | -
59 | - yaml.findAndRegisterModules();
60 | - config = yaml.readValue(new FileReader(configPath), MainConfig.class);
61 | -
62 | - }catch (FileNotFoundException e){
63 | - System.out.println("Config file not found, creating with default values...");
64 | - saveConfig();
65 | - }catch (Throwable t){
66 | - throw new RuntimeException(t);
67 | - }
68 | +// public static void loadConfig() {
69 | +// try {
70 | +// yaml.findAndRegisterModules();
71 | +// config = yaml.readValue(new FileReader(configPath), MainConfig.class);
72 | +//
73 | +// }catch (FileNotFoundException e){
74 | +// System.out.println("Config file not found, creating with default values...");
75 | +// saveConfig();
76 | +// }catch (Throwable t){
77 | +// throw new RuntimeException(t);
78 | +// }
79 | +// }
80 | +//
81 | +// public static void saveConfig() {
82 | +// try {
83 | +// yaml.findAndRegisterModules();
84 | +// //noinspection ResultOfMethodCallIgnored
85 | +//
86 | +// new File(getConfigDirectory()).mkdirs();
87 | +// BufferedWriter writer = new BufferedWriter(new FileWriter(configPath));
88 | +// writer.write("#Config for Server Side Replay Recorder\n");
89 | +// writer.write("##WARNING any comments in this file might get deleted\n");
90 | +// writer.write("\n");
91 | +// yaml.writeValue(writer, config);
92 | +// writer.close();
93 | +// } catch (IOException ioException) {
94 | +// ioException.printStackTrace();
95 | +// }
96 | +// }
97 | +
98 | + public static String getConfigDirectory(){
99 | + System.out.println(System.getProperty("user.dir") + "/config");
100 | + return System.getProperty("user.dir") + "/config";
101 | }
102 |
103 | - public static void saveConfig() {
104 | - try {
105 | - yaml.findAndRegisterModules();
106 | - //noinspection ResultOfMethodCallIgnored
107 | - new File(FabricLoader.getInstance().getConfigDir().toString()).mkdirs();
108 | - BufferedWriter writer = new BufferedWriter(new FileWriter(configPath));
109 | - writer.write("#Config for Server Side Replay Recorder\n");
110 | - writer.write("##WARNING any comments in this file might get deleted\n");
111 | - writer.write("\n");
112 | - yaml.writeValue(writer, config);
113 | - writer.close();
114 | - } catch (IOException ioException) {
115 | - ioException.printStackTrace();
116 | - }
117 | + public static String getDirectory(){
118 | + System.out.println(System.getProperty("user.dir"));
119 | + return System.getProperty("user.dir");
120 | }
121 | +
122 | public static void registerServer(MinecraftServer mcServer) {
123 | server = mcServer;
124 | //fixStoppedReplays();
125 | @@ -73,7 +85,7 @@ public class ServerSideReplayRecorderServer {
126 |
127 | public void onInitialize() {
128 | LOGGER.info(ServerSideReplayRecorderServer.class.getSimpleName() + " loaded");
129 | - loadConfig();
130 | + //loadConfig();
131 | }
132 |
133 | }
134 | diff --git a/src/main/java/net/minecraft/serversidereplayrecorder/recorder/PlayerRecorder.java b/src/main/java/net/minecraft/serversidereplayrecorder/recorder/PlayerRecorder.java
135 | index a417433aa83be221fd26f5ef8a3197ca48fb408a..0b89881480c14f44b5943c547606ff2bbc6b9bab 100644
136 | --- a/src/main/java/net/minecraft/serversidereplayrecorder/recorder/PlayerRecorder.java
137 | +++ b/src/main/java/net/minecraft/serversidereplayrecorder/recorder/PlayerRecorder.java
138 | @@ -12,6 +12,7 @@ import net.minecraft.serversidereplayrecorder.ServerSideReplayRecorderServer;
139 | import net.minecraft.serversidereplayrecorder.util.WrappedPacket;
140 | import net.minecraft.serversidereplayrecorder.util.interfaces.LightUpdatePacketAccessor;
141 | import net.minecraft.world.entity.player.Player;
142 | +import net.minecraft.world.level.storage.LevelStorageSource;
143 |
144 | import java.io.File;
145 | import java.io.IOException;
146 | @@ -39,6 +40,8 @@ public class PlayerRecorder extends ReplayRecorder {
147 | return this.playerName;
148 | }
149 |
150 | +
151 | +
152 | @Override
153 | protected String getSaveFolder() {
154 | String name;
155 | @@ -51,7 +54,7 @@ public class PlayerRecorder extends ReplayRecorder {
156 | if (new File(ServerSideReplayRecorderServer.config.getReplay_folder_name()).isAbsolute())
157 | return Paths.get(ServerSideReplayRecorderServer.config.getReplay_folder_name(), PLAYER_FOLDER, name).toString();
158 | else
159 | - return Paths.get(FabricLoader.getInstance().getGameDir().toString(), ServerSideReplayRecorderServer.config.getReplay_folder_name(), PLAYER_FOLDER, name).toString();
160 | + return Paths.get(ServerSideReplayRecorderServer.getDirectory(), ServerSideReplayRecorderServer.config.getReplay_folder_name(), PLAYER_FOLDER, name).toString();
161 | }
162 |
163 |
164 | diff --git a/src/main/java/net/minecraft/serversidereplayrecorder/recorder/RegionRecorder.java b/src/main/java/net/minecraft/serversidereplayrecorder/recorder/RegionRecorder.java
165 | index 04b34176da3ab7fc62ca33212e2de41776bf8ea1..ffdbd36015553ca8d15d55803c945f8949f234f0 100644
166 | --- a/src/main/java/net/minecraft/serversidereplayrecorder/recorder/RegionRecorder.java
167 | +++ b/src/main/java/net/minecraft/serversidereplayrecorder/recorder/RegionRecorder.java
168 | @@ -23,7 +23,9 @@ import net.minecraft.world.flag.FeatureFlags;
169 | import net.minecraft.world.item.ItemStack;
170 | import net.minecraft.world.level.ChunkPos;
171 | import net.minecraft.world.level.GameRules;
172 | +import net.minecraft.world.level.GameType;
173 | import net.minecraft.world.level.border.WorldBorder;
174 | +import net.minecraft.world.level.chunk.ChunkAccess;
175 | import net.minecraft.world.level.chunk.ChunkStatus;
176 | import net.minecraft.world.level.chunk.ImposterProtoChunk;
177 | import net.minecraft.world.level.chunk.LevelChunk;
178 | @@ -97,26 +99,26 @@ public class RegionRecorder extends ReplayRecorder {
179 | onPacket(new ClientboundLoginPacket(
180 | 0,
181 | worldProperties.isHardcore(),
182 | - GameMode.SPECTATOR,
183 | - GameMode.SPECTATOR,
184 | + GameType.SPECTATOR,
185 | + GameType.SPECTATOR,
186 | ms.levelKeys(),
187 | - ms.registryAccess().toImmutable(),
188 | - world.getDimensionKey(),
189 | - world.getRegistryKey(),
190 | + ms.registryAccess().freeze(),
191 | + world.dimensionTypeId(),
192 | + world.dimension(),
193 | world.getSeed(),
194 | ms.getMaxPlayers(),
195 | region.radius,
196 | region.radius,
197 | false,
198 | false,
199 | - world.isDebugWorld(),
200 | + world.isDebug(),
201 | world.isFlat(),
202 | Optional.empty(),
203 | 0
204 | ));
205 | onPacket(new ClientboundUpdateEnabledFeaturesPacket(FeatureFlags.REGISTRY.toNames(world.enabledFeatures())));
206 | onPacket(
207 | - new ClientboundCustomPayloadPacket(ClientboundCustomPayloadPacket.BRAND, new FriendlyByteBuf(Unpooled.buffer()).writeString(ms.getServerModName()))
208 | + new ClientboundCustomPayloadPacket(ClientboundCustomPayloadPacket.BRAND, new FriendlyByteBuf(Unpooled.buffer()).writeUtf(ms.getServerModName()))
209 | );
210 | onPacket(new ClientboundChangeDifficultyPacket(worldProperties.getDifficulty(), worldProperties.isDifficultyLocked()));
211 | onPacket(new ClientboundPlayerAbilitiesPacket(new Abilities()));
212 | @@ -130,12 +132,12 @@ public class RegionRecorder extends ReplayRecorder {
213 | //save world ( dimension ) information
214 | WorldBorder worldBorder = world.getWorldBorder();
215 | onPacket(new ClientboundInitializeBorderPacket(worldBorder));
216 | - onPacket(new ClientboundSetTimePacket(world.getTime(), world.getTimeOfDay(), world.getGameRules().getBoolean(GameRules.RULE_DAYLIGHT)));
217 | - onPacket(new ClientboundSetDefaultSpawnPositionPacket(world.getSpawnPos(), world.getSpawnAngle()));
218 | + onPacket(new ClientboundSetTimePacket(world.getGameTime(), world.getDayTime(), world.getGameRules().getBoolean(GameRules.RULE_DAYLIGHT)));
219 | + onPacket(new ClientboundSetDefaultSpawnPositionPacket(world.getSharedSpawnPos(), world.getSharedSpawnAngle()));
220 | if (world.isRaining()) {
221 | onPacket(new ClientboundGameEventPacket(ClientboundGameEventPacket.START_RAINING, ClientboundGameEventPacket.DEMO_PARAM_INTRO));
222 | - onPacket(new ClientboundGameEventPacket(ClientboundGameEventPacket.RAIN_LEVEL_CHANGE, world.getRainGradient(1.0F)));
223 | - onPacket(new ClientboundGameEventPacket(ClientboundGameEventPacket.THUNDER_LEVEL_CHANGE, world.getThunderGradient(1.0F)));
224 | + onPacket(new ClientboundGameEventPacket(ClientboundGameEventPacket.RAIN_LEVEL_CHANGE, world.getRainLevel(1.0F)));
225 | + onPacket(new ClientboundGameEventPacket(ClientboundGameEventPacket.THUNDER_LEVEL_CHANGE, world.getThunderLevel(1.0F)));
226 | }
227 | ms
228 | .getServerResourcePack()
229 | @@ -170,7 +172,7 @@ public class RegionRecorder extends ReplayRecorder {
230 | for (ChunkPos pos : this.region.expandedChunks ){
231 | //get chunk, load if needed, no create
232 | //this call is deferred to the MainServer executor which runs at the end of a tick in the spare time
233 | - Chunk chunk = world.getChunk(pos.x,pos.z, ChunkStatus.EMPTY);
234 | + ChunkAccess chunk = world.getChunk(pos.x,pos.z, ChunkStatus.EMPTY);
235 | LevelChunk worldChunk = null;
236 | if (chunk instanceof LevelChunk)
237 | worldChunk = (LevelChunk) chunk;
238 | @@ -183,17 +185,17 @@ public class RegionRecorder extends ReplayRecorder {
239 | if (pos.equals(this.region.center)) {
240 |
241 | //find the highest non-transparent block as viewpoint
242 | - int surface_y = worldChunk.sampleHeightmap(Heightmap.Type.MOTION_BLOCKING, viewpoint.getX(), viewpoint.getZ());
243 | + int surface_y = worldChunk.getHeight(Heightmap.Types.MOTION_BLOCKING, viewpoint.getX(), viewpoint.getZ());
244 | BlockPos b_pos = new BlockPos(viewpoint.getX(), surface_y, viewpoint.getZ());
245 | while (!worldChunk.getBlockState(b_pos).isOpaque() && surface_y != chunk.getMinBuildHeight()) {
246 | b_pos = new BlockPos(viewpoint.getX(), --surface_y, viewpoint.getZ());
247 | }
248 | //if no blocks are found in the column keep the original viewpoint
249 | - if (surface_y != chunk.getBottomY())
250 | + if (surface_y != chunk.getMinBuildHeight())
251 | this.viewpoint = new Vec3i(viewpoint.getX(), surface_y + 1, viewpoint.getZ());
252 | }
253 | //save chunk
254 | - onPacket(new WrappedPacket(new ClientboundLevelChunkWithLightPacket(worldChunk, world.getLightingProvider(), null, null)));
255 | + onPacket(new WrappedPacket(new ClientboundLevelChunkWithLightPacket(worldChunk, world.getLightEngine(), null, null)));
256 | //--obsolete in new versions
257 | //onPacket(new WrappedPacket(new LightUpdateS2CPacket(pos, world.getLightingProvider(), null, null, true)));
258 | known_chunk_data.add(pos);
259 | @@ -256,7 +258,7 @@ public class RegionRecorder extends ReplayRecorder {
260 | if (new File(ServerSideReplayRecorderServer.config.getReplay_folder_name()).isAbsolute())
261 | return Paths.get(ServerSideReplayRecorderServer.config.getReplay_folder_name(), REGION_FOLDER,name).toString();
262 | else
263 | - return Paths.get(FabricLoader.getInstance().getGameDir().toString(), ServerSideReplayRecorderServer.config.getReplay_folder_name(), REGION_FOLDER,name).toString();
264 | + return Paths.get(ServerSideReplayRecorderServer.getDirectory(), ServerSideReplayRecorderServer.config.getReplay_folder_name(), REGION_FOLDER,name).toString();
265 | }
266 |
267 | @Override
268 | diff --git a/src/main/java/net/minecraft/serversidereplayrecorder/recorder/ReplayRecorder.java b/src/main/java/net/minecraft/serversidereplayrecorder/recorder/ReplayRecorder.java
269 | index 7a28f357e71c4c964de200557182222d2fbd6665..d6f1308bc76895094dc07f71ba00b1ace427d494 100644
270 | --- a/src/main/java/net/minecraft/serversidereplayrecorder/recorder/ReplayRecorder.java
271 | +++ b/src/main/java/net/minecraft/serversidereplayrecorder/recorder/ReplayRecorder.java
272 | @@ -84,7 +84,7 @@ public abstract class ReplayRecorder {
273 | if (new File(ServerSideReplayRecorderServer.config.getReplay_folder_name()).isAbsolute())
274 | tmp_folder = Paths.get(ServerSideReplayRecorderServer.config.getReplay_folder_name(), "recording_" + this.hashCode()).toFile();
275 | else
276 | - tmp_folder = Paths.get(FabricLoader.getInstance().getGameDir().toString(), ServerSideReplayRecorderServer.config.getReplay_folder_name(), "recording_" + this.hashCode()).toFile();
277 | + tmp_folder = Paths.get(ServerSideReplayRecorderServer.getDirectory(), ServerSideReplayRecorderServer.config.getReplay_folder_name(), "recording_" + this.hashCode()).toFile();
278 | tmp_folder.mkdirs();
279 | recording_file= Paths.get(tmp_folder.getAbsolutePath(), "recording.tmcpr").toFile();
280 | fileName = String.format("%s.mcpr", new SimpleDateFormat("yyyy-MM-dd_HH-mm-ss").format(new Date()));
281 |
--------------------------------------------------------------------------------
/patches/server/0006-ServerSideRecorder.patch:
--------------------------------------------------------------------------------
1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
2 | From: Bryan1029384756 <23323626+Bryan1029384756@users.noreply.github.com>
3 | Date: Sat, 17 Jun 2023 23:37:21 -0500
4 | Subject: [PATCH] ServerSideRecorder
5 |
6 |
7 | diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java
8 | index 60f77d4f519cf0864ce8a01fdc7bebd5fe548e01..8a2fae854e07482fd5cd372ab12571618fdbeacb 100644
9 | --- a/src/main/java/net/minecraft/server/level/ChunkMap.java
10 | +++ b/src/main/java/net/minecraft/server/level/ChunkMap.java
11 | @@ -1336,7 +1336,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
12 | }
13 | level.timings.tracker2.stopTiming(); // Paper
14 | }
15 | - ((RegionRecorderEntityTracker)playerchunkmap_entitytracker).updateTrackedStatus(((RegionRecorderWorld)playerchunkmap_entitytracker.entity.level()).getRegionRecorders()); //Seversiderecorder
16 | + ((RegionRecorderEntityTracker)this.entityMap).updateTrackedStatus(((RegionRecorderWorld)this.level).getRegionRecorders()); //Seversiderecorder
17 | }
18 |
19 | public void broadcast(Entity entity, Packet> packet) {
20 | @@ -1464,6 +1464,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
21 | this.recorder = new WeakReference<>(recorder);
22 | //send the spawn packets when the tracker is creaed
23 | //works also for dimension change as a new tracker is created while changing dimension
24 | +
25 | if (recorder != null) {
26 | serverEntity.sendPairingData(null, recorder::onPacket);
27 | }
28 | diff --git a/src/main/java/net/minecraft/server/level/ServerEntity.java b/src/main/java/net/minecraft/server/level/ServerEntity.java
29 | index 6670e657e08e130f7e0368f418379fd1ece00cdf..27edf4a0eb3caed5923fd1187c4da1472f77a959 100644
30 | --- a/src/main/java/net/minecraft/server/level/ServerEntity.java
31 | +++ b/src/main/java/net/minecraft/server/level/ServerEntity.java
32 | @@ -308,11 +308,13 @@ public class ServerEntity {
33 | if (this.entity instanceof LivingEntity) {
34 | Collection collection = ((LivingEntity) this.entity).getAttributes().getSyncableAttributes();
35 |
36 | - // CraftBukkit start - If sending own attributes send scaled health instead of current maximum health
37 | - if (this.entity.getId() == player.getId()) {
38 | - ((ServerPlayer) this.entity).getBukkitEntity().injectScaledMaxHealth(collection, false);
39 | + if(player != null){
40 | + // CraftBukkit start - If sending own attributes send scaled health instead of current maximum health
41 | + if (this.entity.getId() == player.getId()) {
42 | + ((ServerPlayer) this.entity).getBukkitEntity().injectScaledMaxHealth(collection, false);
43 | + }
44 | + // CraftBukkit end
45 | }
46 | - // CraftBukkit end
47 |
48 | if (!collection.isEmpty()) {
49 | sender.accept(new ClientboundUpdateAttributesPacket(this.entity.getId(), collection));
50 | diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java
51 | index b0c7f13cf93108349dabdd378e38ff001fc92e7c..1a79374bb771b20309fb087703bfe278d90ed71d 100644
52 | --- a/src/main/java/net/minecraft/server/players/PlayerList.java
53 | +++ b/src/main/java/net/minecraft/server/players/PlayerList.java
54 | @@ -171,8 +171,8 @@ public abstract class PlayerList {
55 |
56 | public void placeNewPlayer(Connection connection, ServerPlayer player) {
57 | //ServerSideReplayRecorder start
58 | - if (ServerSideReplayRecorderServer.config.isRecording_enabled() && !PlayerRecorder.playerRecorderMap.containsKey(connection)
59 | - && ( ServerSideReplayRecorderServer.config.getRecordable_users().contains(player.getGameProfile().getName())) != ServerSideReplayRecorderServer.config.invert_user_list() ) {
60 | + // if (ServerSideReplayRecorderServer.config.isRecording_enabled() && !PlayerRecorder.playerRecorderMap.containsKey(connection)
61 | + // && ( ServerSideReplayRecorderServer.config.getRecordable_users().contains(player.getGameProfile().getName())) != ServerSideReplayRecorderServer.config.invert_user_list() ) {
62 | try {
63 | ServerSideReplayRecorderServer.LOGGER.info("Started Recording Player %s".formatted(player.getGameProfile().getName()));
64 |
65 | @@ -183,7 +183,7 @@ public abstract class PlayerList {
66 | } catch (IOException e) {
67 | e.printStackTrace();
68 | }
69 | - }
70 | + // }
71 | //ServerSideReplayRecorder end
72 |
73 | player.isRealPlayer = true; // Paper
74 | diff --git a/src/main/java/net/minecraft/serversidereplayrecorder/ServerSideReplayRecorderServer.java b/src/main/java/net/minecraft/serversidereplayrecorder/ServerSideReplayRecorderServer.java
75 | index 198841e836943e20e65d75a432884b709c9e405f..9a5ae6b35154bc7cc634306ae3534beca47cb170 100644
76 | --- a/src/main/java/net/minecraft/serversidereplayrecorder/ServerSideReplayRecorderServer.java
77 | +++ b/src/main/java/net/minecraft/serversidereplayrecorder/ServerSideReplayRecorderServer.java
78 | @@ -69,8 +69,8 @@ public class ServerSideReplayRecorderServer {
79 | // }
80 |
81 | public static String getConfigDirectory(){
82 | - System.out.println(System.getProperty("user.dir") + "/config");
83 | - return System.getProperty("user.dir") + "/config";
84 | + System.out.println(System.getProperty("user.dir") + "\\config");
85 | + return System.getProperty("user.dir") + "\\config";
86 | }
87 |
88 | public static String getDirectory(){
89 | diff --git a/src/main/java/net/minecraft/serversidereplayrecorder/command/ReplayCommand.java b/src/main/java/net/minecraft/serversidereplayrecorder/command/ReplayCommand.java
90 | index f1efdd1fa54243110efc6719c3c75c33fdac3199..50634cba3a60eea3d8474c88e8a34f1c97c8fdf0 100644
91 | --- a/src/main/java/net/minecraft/serversidereplayrecorder/command/ReplayCommand.java
92 | +++ b/src/main/java/net/minecraft/serversidereplayrecorder/command/ReplayCommand.java
93 | @@ -180,7 +180,7 @@ public class ReplayCommand {
94 | });
95 | if (count.get() > 0) {
96 | source.sendSuccess(()->Component.literal("Added players will start recording next time they join the server"), true);
97 | - ServerSideReplayRecorderServer.saveConfig();
98 | + //ServerSideReplayRecorderServer.saveConfig();
99 | }
100 | return 0;
101 | })
102 | @@ -211,7 +211,7 @@ public class ReplayCommand {
103 | });
104 | if (count.get() > 0) {
105 | source.sendSuccess(()->Component.literal("Removed players will stop recording on logout"), true);
106 | - ServerSideReplayRecorderServer.saveConfig();
107 | + // ServerSideReplayRecorderServer.saveConfig();
108 | }
109 | return 0;
110 | })
111 | @@ -278,13 +278,13 @@ public class ReplayCommand {
112 | .then(Commands.literal("enable").executes(context -> {
113 | ServerSideReplayRecorderServer.config.setRecording_enabled(true);
114 | context.getSource().sendSuccess(()->Component.literal("Recording " + ((ServerSideReplayRecorderServer.config.isRecording_enabled()) ? "Enabled" : "Disabled")), true);
115 | - ServerSideReplayRecorderServer.saveConfig();
116 | + // ServerSideReplayRecorderServer.saveConfig();
117 | return 0;
118 | }))
119 | .then(Commands.literal("disable").executes(context -> {
120 | ServerSideReplayRecorderServer.config.setRecording_enabled(false);
121 | context.getSource().sendSuccess(()->Component.literal("Recording " + ((ServerSideReplayRecorderServer.config.isRecording_enabled()) ? "Enabled" : "Disabled")), true);
122 | - ServerSideReplayRecorderServer.saveConfig();
123 | + // ServerSideReplayRecorderServer.saveConfig();
124 | return 0;
125 | }))
126 | ).then(
127 |
--------------------------------------------------------------------------------
/patches/server/0007-ServerSideRecorder.patch:
--------------------------------------------------------------------------------
1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
2 | From: Bryan1029384756 <23323626+Bryan1029384756@users.noreply.github.com>
3 | Date: Sat, 17 Jun 2023 23:46:08 -0500
4 | Subject: [PATCH] ServerSideRecorder
5 |
6 |
7 | diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java
8 | index 1a79374bb771b20309fb087703bfe278d90ed71d..f13581964ac8399a1d1acf651a9856d0e6502766 100644
9 | --- a/src/main/java/net/minecraft/server/players/PlayerList.java
10 | +++ b/src/main/java/net/minecraft/server/players/PlayerList.java
11 | @@ -1192,7 +1192,7 @@ public abstract class PlayerList {
12 | //Serversiderecorder start
13 |
14 | if (player != null) {
15 | - ReplayRecorder recorder = ((RecorderHolder)(((ServerPlayer) player).connection)).getRecorder();
16 | + ReplayRecorder recorder = ((RecorderHolder)(((ServerPlayer) player).connection.connection)).getRecorder();
17 | if (recorder != null) {
18 | recorder.onPacket(packet);
19 | }
20 |
--------------------------------------------------------------------------------
/patches/server/0008-ServerSideRecorder.patch:
--------------------------------------------------------------------------------
1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
2 | From: Bryan1029384756 <23323626+Bryan1029384756@users.noreply.github.com>
3 | Date: Sun, 18 Jun 2023 05:32:29 -0500
4 | Subject: [PATCH] ServerSideRecorder
5 |
6 |
7 | diff --git a/src/main/java/net/minecraft/network/Connection.java b/src/main/java/net/minecraft/network/Connection.java
8 | index b25eef60573cb217ac2a288ab7dd9e502e39e247..f56d50a9936ee72ebb74175520d5a08e55bbded6 100644
9 | --- a/src/main/java/net/minecraft/network/Connection.java
10 | +++ b/src/main/java/net/minecraft/network/Connection.java
11 | @@ -435,10 +435,12 @@ public class Connection extends SimpleChannelInboundHandler> implement
12 | this.flushQueue();
13 | // Paper end
14 |
15 | + //Serversiderecorder start
16 | ReplayRecorder recorder = this.recorder.get();
17 | if (recorder != null){
18 | recorder.onPacket(packet);
19 | }
20 | + //Serversiderecorder end
21 | }
22 |
23 | private void sendPacket(Packet> packet, @Nullable PacketSendListener callbacks) {
24 | @@ -836,10 +838,7 @@ public class Connection extends SimpleChannelInboundHandler> implement
25 | }
26 |
27 | public void handleDisconnection() {
28 | - ReplayRecorder recorder = this.recorder.get();
29 | - if (recorder != null){
30 | - recorder.handleDisconnect();
31 | - }
32 | +
33 |
34 | if (this.channel != null && !this.channel.isOpen()) {
35 | if (this.disconnectionHandled) {
36 | diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java
37 | index 37610964e6057709b4d0fb82e36d3943d50b45b1..a6fded634d1545611337ee39b6dcde655b0b6b82 100644
38 | --- a/src/main/java/net/minecraft/server/MinecraftServer.java
39 | +++ b/src/main/java/net/minecraft/server/MinecraftServer.java
40 | @@ -1114,6 +1114,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop
3 | Date: Sun, 18 Jun 2023 19:01:55 -0500
4 | Subject: [PATCH] ServerSideRecorder
5 |
6 |
7 | diff --git a/build.gradle.kts b/build.gradle.kts
8 | index 1e6743e1ac5cfc7f5fbd5a40ead0ca519dac74c9..bc657aeac475dfc5a55e5d91939d5e8318b0c12f 100644
9 | --- a/build.gradle.kts
10 | +++ b/build.gradle.kts
11 | @@ -35,7 +35,8 @@ dependencies {
12 | implementation("org.spongepowered:configurate-yaml:4.1.2") // Paper - config files
13 | implementation("commons-lang:commons-lang:2.6")
14 | implementation("net.fabricmc:mapping-io:0.3.0") // Paper - needed to read mappings for stacktrace deobfuscation
15 | - implementation("com.fasterxml.jackson.core:jackson-annotations:2.15.2")
16 | + implementation("com.fasterxml.jackson.core:jackson-annotations:2.15.2") //ServersideRecording
17 | + implementation("com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:2.15.2") //ServersideRecording
18 | runtimeOnly("org.xerial:sqlite-jdbc:3.42.0.0")
19 | runtimeOnly("com.mysql:mysql-connector-j:8.0.33")
20 | runtimeOnly("com.lmax:disruptor:3.4.4") // Paper
21 | diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java
22 | index a6fded634d1545611337ee39b6dcde655b0b6b82..c301cc293a93c45c3955932ff6bb445bcd32842a 100644
23 | --- a/src/main/java/net/minecraft/server/MinecraftServer.java
24 | +++ b/src/main/java/net/minecraft/server/MinecraftServer.java
25 | @@ -1114,6 +1114,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop this.isOp(p.getGameProfile())).forEach( p -> p.displayClientMessage(Component.literal("Started Recording Player %s".formatted(player.getGameProfile().getName())), false));
57 | + //player.connection
58 | PlayerRecorder recorder = new PlayerRecorder(connection);
59 | PlayerRecorder.playerRecorderMap.put(connection, recorder);
60 | +// PlayerRecorder recorder = new PlayerRecorder(connection);
61 | +// PlayerRecorder.playerRecorderMap.put(connection, recorder);
62 | recorder.onPacket(new ClientboundGameProfilePacket(player.getGameProfile()));
63 | } catch (IOException e) {
64 | e.printStackTrace();
65 | diff --git a/src/main/java/net/minecraft/serversidereplayrecorder/ServerSideReplayRecorderServer.java b/src/main/java/net/minecraft/serversidereplayrecorder/ServerSideReplayRecorderServer.java
66 | index 9a5ae6b35154bc7cc634306ae3534beca47cb170..723aca57bbe71764774ff8991de6e3c6b134c323 100644
67 | --- a/src/main/java/net/minecraft/serversidereplayrecorder/ServerSideReplayRecorderServer.java
68 | +++ b/src/main/java/net/minecraft/serversidereplayrecorder/ServerSideReplayRecorderServer.java
69 | @@ -1,6 +1,10 @@
70 | package net.minecraft.serversidereplayrecorder;
71 |
72 | -import com.mojang.authlib.minecraft.client.ObjectMapper;
73 | +import com.fasterxml.jackson.databind.DeserializationFeature;
74 | +import com.fasterxml.jackson.dataformat.yaml.YAMLFactory;
75 | +import com.fasterxml.jackson.dataformat.yaml.YAMLFactoryBuilder;
76 | +import com.fasterxml.jackson.dataformat.yaml.YAMLGenerator;
77 | +import com.fasterxml.jackson.databind.ObjectMapper;
78 | import io.netty.util.concurrent.DefaultThreadFactory;
79 | import net.minecraft.server.MinecraftServer;
80 | import net.minecraft.serversidereplayrecorder.config.MainConfig;
81 | @@ -8,7 +12,6 @@ import org.slf4j.Logger;
82 | import org.slf4j.LoggerFactory;
83 |
84 | import java.io.*;
85 | -import java.nio.file.Path;
86 | import java.util.ResourceBundle;
87 | import java.util.concurrent.ExecutorService;
88 | import java.util.concurrent.Executors;
89 | @@ -16,20 +19,20 @@ import java.util.concurrent.Executors;
90 | public class ServerSideReplayRecorderServer {
91 |
92 | static {
93 | -// YAMLFactoryBuilder builder = YAMLFactory.builder();
94 | -// builder.disable(YAMLGenerator.Feature.WRITE_DOC_START_MARKER);
95 | -// builder.enable(YAMLGenerator.Feature.INDENT_ARRAYS_WITH_INDICATOR);
96 | -// yaml = new ObjectMapper(builder.build()).configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
97 | -// placeholders = ResourceBundle.getBundle("placeholders");
98 | -// upload_sites = ResourceBundle.getBundle("upload_sites");
99 | + YAMLFactoryBuilder builder = YAMLFactory.builder();
100 | + builder.disable(YAMLGenerator.Feature.WRITE_DOC_START_MARKER);
101 | + builder.enable(YAMLGenerator.Feature.INDENT_ARRAYS_WITH_INDICATOR);
102 | + yaml = new ObjectMapper(builder.build()).configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
103 | + placeholders = ResourceBundle.getBundle("placeholders");
104 | + upload_sites = ResourceBundle.getBundle("upload_sites");
105 | }
106 |
107 | public static final ExecutorService recorderExecutor = Executors.newSingleThreadExecutor(new DefaultThreadFactory("Replay",true));
108 |
109 | -// private static final ObjectMapper yaml;
110 | -//
111 | -// public static final ResourceBundle placeholders;
112 | -// public static final ResourceBundle upload_sites;
113 | + private static final ObjectMapper yaml;
114 | +
115 | + public static final ResourceBundle placeholders;
116 | + public static final ResourceBundle upload_sites;
117 |
118 | public static final Logger LOGGER = LoggerFactory.getLogger(ServerSideReplayRecorderServer.class.getName());
119 |
120 | @@ -38,35 +41,35 @@ public class ServerSideReplayRecorderServer {
121 | public static final String configPath = getConfigDirectory() + "/ServerSideReplayRecorder.yml";
122 | public static MainConfig config = new MainConfig();
123 |
124 | -// public static void loadConfig() {
125 | -// try {
126 | -// yaml.findAndRegisterModules();
127 | -// config = yaml.readValue(new FileReader(configPath), MainConfig.class);
128 | -//
129 | -// }catch (FileNotFoundException e){
130 | -// System.out.println("Config file not found, creating with default values...");
131 | -// saveConfig();
132 | -// }catch (Throwable t){
133 | -// throw new RuntimeException(t);
134 | -// }
135 | -// }
136 | -//
137 | -// public static void saveConfig() {
138 | -// try {
139 | -// yaml.findAndRegisterModules();
140 | -// //noinspection ResultOfMethodCallIgnored
141 | -//
142 | -// new File(getConfigDirectory()).mkdirs();
143 | -// BufferedWriter writer = new BufferedWriter(new FileWriter(configPath));
144 | -// writer.write("#Config for Server Side Replay Recorder\n");
145 | -// writer.write("##WARNING any comments in this file might get deleted\n");
146 | -// writer.write("\n");
147 | -// yaml.writeValue(writer, config);
148 | -// writer.close();
149 | -// } catch (IOException ioException) {
150 | -// ioException.printStackTrace();
151 | -// }
152 | -// }
153 | + public static void loadConfig() {
154 | + try {
155 | + yaml.findAndRegisterModules();
156 | + config = yaml.readValue(new FileReader(configPath), MainConfig.class);
157 | +
158 | + }catch (FileNotFoundException e){
159 | + System.out.println("Config file not found, creating with default values...");
160 | + saveConfig();
161 | + }catch (Throwable t){
162 | + throw new RuntimeException(t);
163 | + }
164 | + }
165 | +
166 | + public static void saveConfig() {
167 | + try {
168 | + yaml.findAndRegisterModules();
169 | + //noinspection ResultOfMethodCallIgnored
170 | +
171 | + new File(getConfigDirectory()).mkdirs();
172 | + BufferedWriter writer = new BufferedWriter(new FileWriter(configPath));
173 | + writer.write("#Config for Server Side Replay Recorder\n");
174 | + writer.write("##WARNING any comments in this file might get deleted\n");
175 | + writer.write("\n");
176 | + yaml.writeValue(writer, config);
177 | + writer.close();
178 | + } catch (IOException ioException) {
179 | + ioException.printStackTrace();
180 | + }
181 | + }
182 |
183 | public static String getConfigDirectory(){
184 | System.out.println(System.getProperty("user.dir") + "\\config");
185 | @@ -83,9 +86,9 @@ public class ServerSideReplayRecorderServer {
186 | //fixStoppedReplays();
187 | }
188 |
189 | - public void onInitialize() {
190 | + public static void onInitialize() {
191 | LOGGER.info(ServerSideReplayRecorderServer.class.getSimpleName() + " loaded");
192 | - //loadConfig();
193 | + loadConfig();
194 | }
195 |
196 | }
197 |
--------------------------------------------------------------------------------
/patches/server/0011-ServerSideRecorder.patch:
--------------------------------------------------------------------------------
1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
2 | From: Bryan1029384756 <23323626+Bryan1029384756@users.noreply.github.com>
3 | Date: Sun, 18 Jun 2023 20:13:13 -0500
4 | Subject: [PATCH] ServerSideRecorder
5 |
6 |
7 | diff --git a/src/main/java/net/minecraft/serversidereplayrecorder/recorder/ReplayRecorder.java b/src/main/java/net/minecraft/serversidereplayrecorder/recorder/ReplayRecorder.java
8 | index 324e2b9fe2e4141cac1ec0a1d2ef8fe9710f94e6..4c1e74dc5acb0519a15f7274f3e7983737292f09 100644
9 | --- a/src/main/java/net/minecraft/serversidereplayrecorder/recorder/ReplayRecorder.java
10 | +++ b/src/main/java/net/minecraft/serversidereplayrecorder/recorder/ReplayRecorder.java
11 | @@ -305,12 +305,14 @@ public abstract class ReplayRecorder {
12 |
13 | public void onServerTick(){
14 | if (Thread.currentThread() == ms.getRunningThread()){
15 | +
16 | if (!this.open.get())
17 | return;
18 | int old_timestamp = this.server_timestamp.get();
19 | int new_timestamp = (ms.getTickCount() - server_start.get()) * 50;
20 | this.server_timestamp.set(new_timestamp);
21 | if (ServerSideReplayRecorderServer.config.use_server_timestamps()){
22 | + if (ServerSideReplayRecorderServer.config.isDebug()) MinecraftServer.LOGGER.info("ReplayRecorder.onServerTick: use_server_timestamps");
23 | Queue> tick_packets = this.packetQueue.getAndSet(new ConcurrentLinkedQueue<>());
24 | this.fileWriterExecutor.execute(()->{
25 | double delta = (new_timestamp - old_timestamp)/(double)tick_packets.size();
26 | @@ -352,12 +354,13 @@ public abstract class ReplayRecorder {
27 | private final AtomicBoolean metadataQueued = new AtomicBoolean(false);
28 |
29 | private void _save(Packet> packet, int timestamp) {
30 | -
31 | + if (ServerSideReplayRecorderServer.config.isDebug()) MinecraftServer.LOGGER.info("ReplayRecorder._save: ");
32 | if(this.current_file_size.get() > ServerSideReplayRecorderServer.config.getMax_file_size()){
33 | if (tooBigFileSize.compareAndSet(false,true)) {
34 | ServerSideReplayRecorderServer.LOGGER.warn("Max File Size Reached, stopping recording %s:%s".formatted(this.getClass().getSimpleName(), this.getRecordingName()));
35 | this.handleDisconnect(true);
36 | }
37 | + if (ServerSideReplayRecorderServer.config.isDebug()) MinecraftServer.LOGGER.info("ReplayRecorder._save: big return");
38 | return;
39 | }
40 |
41 | @@ -388,13 +391,15 @@ public abstract class ReplayRecorder {
42 | }
43 |
44 | if (packetId == null) {
45 | + if (ServerSideReplayRecorderServer.config.isDebug()) MinecraftServer.LOGGER.info("ReplayRecorder._save: packetId null");
46 | //The packet ID is something we do not have an ID for.
47 | throw new IOException("Unknown packet ID for class " + packet.getClass());
48 | } else {
49 | + if (ServerSideReplayRecorderServer.config.isDebug()) MinecraftServer.LOGGER.info("ReplayRecorder._save: packetId:" + packetId);
50 | //Write the packet ID.
51 | buffer.write(packetId);
52 | }
53 | -
54 | + if (ServerSideReplayRecorderServer.config.isDebug()) MinecraftServer.LOGGER.info("ReplayRecorder._save: Write packet");
55 | //Write the packet.
56 | buffer.write(buf.array(), 0, buf.readableBytes());
57 | bos.write(buffer.toByteArray());
58 |
--------------------------------------------------------------------------------
/patches/server/0012-ServerSideRecorder.patch:
--------------------------------------------------------------------------------
1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
2 | From: Bryan1029384756 <23323626+Bryan1029384756@users.noreply.github.com>
3 | Date: Sun, 18 Jun 2023 20:53:18 -0500
4 | Subject: [PATCH] ServerSideRecorder
5 |
6 |
7 | diff --git a/src/main/java/net/minecraft/serversidereplayrecorder/recorder/ReplayRecorder.java b/src/main/java/net/minecraft/serversidereplayrecorder/recorder/ReplayRecorder.java
8 | index 4c1e74dc5acb0519a15f7274f3e7983737292f09..0580cd5d9c7512b8e6d04c363ba6d48e28ee8535 100644
9 | --- a/src/main/java/net/minecraft/serversidereplayrecorder/recorder/ReplayRecorder.java
10 | +++ b/src/main/java/net/minecraft/serversidereplayrecorder/recorder/ReplayRecorder.java
11 | @@ -271,6 +271,7 @@ public abstract class ReplayRecorder {
12 | Runnable endTask = () -> {
13 | try {
14 | try {
15 | +
16 | bos.close();
17 | fos.close();
18 | if (debugFile != null) {
19 |
--------------------------------------------------------------------------------
/patches/server/0013-ServerSideRecorder.patch:
--------------------------------------------------------------------------------
1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
2 | From: Bryan1029384756 <23323626+Bryan1029384756@users.noreply.github.com>
3 | Date: Sun, 18 Jun 2023 21:28:20 -0500
4 | Subject: [PATCH] ServerSideRecorder
5 |
6 |
7 | diff --git a/src/main/java/net/minecraft/network/Connection.java b/src/main/java/net/minecraft/network/Connection.java
8 | index 1bd7c0404d4252ee1bc4f2fbd42b4756e22752e2..b972534be2e59a2f0759100537746889fb657c82 100644
9 | --- a/src/main/java/net/minecraft/network/Connection.java
10 | +++ b/src/main/java/net/minecraft/network/Connection.java
11 | @@ -851,12 +851,7 @@ public class Connection extends SimpleChannelInboundHandler> implement
12 | if (this.disconnectionHandled) {
13 | //Connection.LOGGER.warn("handleDisconnection() called twice"); // Paper - Do not log useless message
14 | } else {
15 | - //ServersideRecorder start
16 | - if(this.getRecorder() != null){
17 | - if (ServerSideReplayRecorderServer.config.isDebug()) MinecraftServer.LOGGER.info("Connection.handleDisconnection: disconnected");
18 | - this.getRecorder().handleDisconnect();
19 | - }
20 | - //ServersideRecorder end
21 | +
22 | this.disconnectionHandled = true;
23 | if (this.getDisconnectedReason() != null) {
24 | this.getPacketListener().onDisconnect(this.getDisconnectedReason());
25 | diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
26 | index 2a609e43370e68943c580083f7f7d8c9b0972955..63cf2c1fa0dc5af7d15198fbdb5a7b0b959174e0 100644
27 | --- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
28 | +++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
29 | @@ -135,6 +135,7 @@ import net.minecraft.resources.ResourceLocation;
30 | import net.minecraft.server.MinecraftServer;
31 | import net.minecraft.server.level.ServerLevel;
32 | import net.minecraft.server.level.ServerPlayer;
33 | +import net.minecraft.serversidereplayrecorder.ServerSideReplayRecorderServer;
34 | import net.minecraft.stats.ServerRecipeBook;
35 | import net.minecraft.util.FutureChain;
36 | import net.minecraft.util.Mth;
37 | @@ -484,6 +485,13 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Tic
38 | }
39 |
40 | public void disconnect(net.kyori.adventure.text.Component reason, org.bukkit.event.player.PlayerKickEvent.Cause cause) {
41 | + //ServersideRecorder start
42 | + if(this.connection.getRecorder() != null){
43 | + if (ServerSideReplayRecorderServer.config.isDebug()) MinecraftServer.LOGGER.info("Connection.handleDisconnection: disconnected");
44 | + this.connection.getRecorder().handleDisconnect();
45 | + }
46 | + //ServersideRecorder end
47 | +
48 | // Paper end
49 | // CraftBukkit start - fire PlayerKickEvent
50 | if (this.processedDisconnect) {
51 |
--------------------------------------------------------------------------------
/patches/server/0014-ServerSideRecorder.patch:
--------------------------------------------------------------------------------
1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
2 | From: Bryan1029384756 <23323626+Bryan1029384756@users.noreply.github.com>
3 | Date: Sun, 18 Jun 2023 21:33:07 -0500
4 | Subject: [PATCH] ServerSideRecorder
5 |
6 |
7 | diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
8 | index 63cf2c1fa0dc5af7d15198fbdb5a7b0b959174e0..f3bc5eb88fdd93fbe7fc914c43f20217cd591d98 100644
9 | --- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
10 | +++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
11 | @@ -486,8 +486,9 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Tic
12 |
13 | public void disconnect(net.kyori.adventure.text.Component reason, org.bukkit.event.player.PlayerKickEvent.Cause cause) {
14 | //ServersideRecorder start
15 | + if (ServerSideReplayRecorderServer.config.isDebug()) MinecraftServer.LOGGER.info("ServerGamePacketListenerImpl.disconnect: disconnected");
16 | if(this.connection.getRecorder() != null){
17 | - if (ServerSideReplayRecorderServer.config.isDebug()) MinecraftServer.LOGGER.info("Connection.handleDisconnection: disconnected");
18 | + if (ServerSideReplayRecorderServer.config.isDebug()) MinecraftServer.LOGGER.info("ServerGamePacketListenerImpl.disconnect: getRecorder");
19 | this.connection.getRecorder().handleDisconnect();
20 | }
21 | //ServersideRecorder end
22 |
--------------------------------------------------------------------------------
/patches/server/0015-ServerSideRecorder.patch:
--------------------------------------------------------------------------------
1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
2 | From: Bryan1029384756 <23323626+Bryan1029384756@users.noreply.github.com>
3 | Date: Sun, 18 Jun 2023 21:37:53 -0500
4 | Subject: [PATCH] ServerSideRecorder
5 |
6 |
7 | diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
8 | index f3bc5eb88fdd93fbe7fc914c43f20217cd591d98..63502534ec83643a9778d22d51b4ebc2a93d9e49 100644
9 | --- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
10 | +++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
11 | @@ -485,13 +485,6 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Tic
12 | }
13 |
14 | public void disconnect(net.kyori.adventure.text.Component reason, org.bukkit.event.player.PlayerKickEvent.Cause cause) {
15 | - //ServersideRecorder start
16 | - if (ServerSideReplayRecorderServer.config.isDebug()) MinecraftServer.LOGGER.info("ServerGamePacketListenerImpl.disconnect: disconnected");
17 | - if(this.connection.getRecorder() != null){
18 | - if (ServerSideReplayRecorderServer.config.isDebug()) MinecraftServer.LOGGER.info("ServerGamePacketListenerImpl.disconnect: getRecorder");
19 | - this.connection.getRecorder().handleDisconnect();
20 | - }
21 | - //ServersideRecorder end
22 |
23 | // Paper end
24 | // CraftBukkit start - fire PlayerKickEvent
25 | @@ -2107,6 +2100,15 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Tic
26 |
27 | @Override
28 | public void onDisconnect(Component reason) {
29 | + //ServersideRecorder start
30 | + if (ServerSideReplayRecorderServer.config.isDebug()) MinecraftServer.LOGGER.info("ServerGamePacketListenerImpl.disconnect: disconnected");
31 | + if(this.connection.getRecorder() != null){
32 | + if (ServerSideReplayRecorderServer.config.isDebug()) MinecraftServer.LOGGER.info("ServerGamePacketListenerImpl.disconnect: getRecorder");
33 | + this.connection.getRecorder().handleDisconnect();
34 | + }else{
35 | + if (ServerSideReplayRecorderServer.config.isDebug()) MinecraftServer.LOGGER.info("ServerGamePacketListenerImpl.disconnect: getRecorder null");
36 | + }
37 | + //ServersideRecorder end
38 | // Paper start
39 | this.onDisconnect(reason, null);
40 | }
41 |
--------------------------------------------------------------------------------
/patches/server/0016-ServerSideRecorder.patch:
--------------------------------------------------------------------------------
1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
2 | From: Bryan1029384756 <23323626+Bryan1029384756@users.noreply.github.com>
3 | Date: Sun, 18 Jun 2023 21:54:16 -0500
4 | Subject: [PATCH] ServerSideRecorder
5 |
6 |
7 | diff --git a/src/main/java/net/minecraft/network/Connection.java b/src/main/java/net/minecraft/network/Connection.java
8 | index b972534be2e59a2f0759100537746889fb657c82..6f7cbd65c8e6f539ba5228401549390b191f9c83 100644
9 | --- a/src/main/java/net/minecraft/network/Connection.java
10 | +++ b/src/main/java/net/minecraft/network/Connection.java
11 | @@ -54,7 +54,7 @@ import org.slf4j.Logger;
12 | import org.slf4j.Marker;
13 | import org.slf4j.MarkerFactory;
14 |
15 | -public class Connection extends SimpleChannelInboundHandler> implements RecorderHolder {
16 | +public class Connection extends SimpleChannelInboundHandler> {
17 |
18 | private static final float AVERAGE_PACKETS_SMOOTHING = 0.75F;
19 | private static final Logger LOGGER = LogUtils.getLogger();
20 | @@ -86,23 +86,6 @@ public class Connection extends SimpleChannelInboundHandler> implement
21 |
22 |
23 |
24 | - //Serversiderecorder start
25 | - WeakReference recorder = new WeakReference<>(null);
26 | -
27 | - @Override
28 | - public void setRecorder(ReplayRecorder recorder){
29 | - if (ServerSideReplayRecorderServer.config.isDebug()) MinecraftServer.LOGGER.info("Connection.setRecorder: ");
30 | - this.recorder = new WeakReference<>(recorder);
31 | - }
32 | -
33 | - @Override
34 | - public ReplayRecorder getRecorder() {
35 | - if (ServerSideReplayRecorderServer.config.isDebug()) MinecraftServer.LOGGER.info("Connection.getRecorder: ");
36 | - return this.recorder.get();
37 | - }
38 | - //Serversiderecorder end
39 | -
40 | -
41 |
42 | // Spigot Start
43 | public java.util.UUID spoofedUUID;
44 | @@ -438,17 +421,6 @@ public class Connection extends SimpleChannelInboundHandler> implement
45 | }
46 | this.flushQueue();
47 | // Paper end
48 | -
49 | - //Serversiderecorder start
50 | - if (ServerSideReplayRecorderServer.config.isDebug()) MinecraftServer.LOGGER.info("Connection.send: ");
51 | - ReplayRecorder recorder = this.recorder.get();
52 | - if (recorder != null){
53 | - if (ServerSideReplayRecorderServer.config.isDebug()) MinecraftServer.LOGGER.info("Connection.send: packet");
54 | - recorder.onPacket(packet);
55 | - }else{
56 | - if (ServerSideReplayRecorderServer.config.isDebug()) MinecraftServer.LOGGER.info("Connection.send: recorder null");
57 | - }
58 | - //Serversiderecorder end
59 | }
60 |
61 | private void sendPacket(Packet> packet, @Nullable PacketSendListener callbacks) {
62 | diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
63 | index 63502534ec83643a9778d22d51b4ebc2a93d9e49..d1ff154b6bba9b4233d0b989c26ec3730f3b6961 100644
64 | --- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
65 | +++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
66 | @@ -9,6 +9,8 @@ import it.unimi.dsi.fastutil.ints.Int2ObjectMap.Entry;
67 | import it.unimi.dsi.fastutil.ints.Int2ObjectMaps;
68 | import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
69 | import it.unimi.dsi.fastutil.objects.ObjectIterator;
70 | +
71 | +import java.lang.ref.WeakReference;
72 | import java.net.SocketAddress;
73 | import java.time.Duration;
74 | import java.time.Instant;
75 | @@ -136,6 +138,9 @@ import net.minecraft.server.MinecraftServer;
76 | import net.minecraft.server.level.ServerLevel;
77 | import net.minecraft.server.level.ServerPlayer;
78 | import net.minecraft.serversidereplayrecorder.ServerSideReplayRecorderServer;
79 | +import net.minecraft.serversidereplayrecorder.recorder.PlayerRecorder;
80 | +import net.minecraft.serversidereplayrecorder.recorder.ReplayRecorder;
81 | +import net.minecraft.serversidereplayrecorder.util.interfaces.RecorderHolder;
82 | import net.minecraft.stats.ServerRecipeBook;
83 | import net.minecraft.util.FutureChain;
84 | import net.minecraft.util.Mth;
85 | @@ -248,7 +253,7 @@ import org.bukkit.inventory.InventoryView;
86 | import org.bukkit.inventory.SmithingInventory;
87 | // CraftBukkit end
88 |
89 | -public class ServerGamePacketListenerImpl implements ServerPlayerConnection, TickablePacketListener, ServerGamePacketListener {
90 | +public class ServerGamePacketListenerImpl implements ServerPlayerConnection, TickablePacketListener, ServerGamePacketListener,RecorderHolder {
91 |
92 | static final Logger LOGGER = LogUtils.getLogger();
93 | private static final int LATENCY_CHECK_INTERVAL = 15000;
94 | @@ -322,8 +327,33 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Tic
95 | this.chatMessageChain = new FutureChain(server.chatExecutor); // CraftBukkit - async chat
96 | // CraftBukkit start - add fields and methods
97 | this.cserver = server.server;
98 | +
99 | + //Serversiderecorder start
100 | + ReplayRecorder recorder = PlayerRecorder.playerRecorderMap.get(connection);
101 | + if (recorder != null){
102 | + this.setRecorder(recorder);
103 | + }
104 | + //Serversiderecorder end
105 | + }
106 | +
107 | +
108 | +
109 | + //Serversiderecorder start
110 | + WeakReference recorder = new WeakReference<>(null);
111 | +
112 | + @Override
113 | + public void setRecorder(ReplayRecorder recorder){
114 | + if (ServerSideReplayRecorderServer.config.isDebug()) MinecraftServer.LOGGER.info("Connection.setRecorder: ");
115 | + this.recorder = new WeakReference<>(recorder);
116 | }
117 |
118 | + @Override
119 | + public ReplayRecorder getRecorder() {
120 | + if (ServerSideReplayRecorderServer.config.isDebug()) MinecraftServer.LOGGER.info("Connection.getRecorder: ");
121 | + return this.recorder.get();
122 | + }
123 | + //Serversiderecorder end
124 | +
125 | private final org.bukkit.craftbukkit.CraftServer cserver;
126 | public boolean processedDisconnect;
127 | private int lastTick = MinecraftServer.currentTick;
128 | @@ -2102,9 +2132,10 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Tic
129 | public void onDisconnect(Component reason) {
130 | //ServersideRecorder start
131 | if (ServerSideReplayRecorderServer.config.isDebug()) MinecraftServer.LOGGER.info("ServerGamePacketListenerImpl.disconnect: disconnected");
132 | - if(this.connection.getRecorder() != null){
133 | +
134 | + if(this.getRecorder() != null){
135 | if (ServerSideReplayRecorderServer.config.isDebug()) MinecraftServer.LOGGER.info("ServerGamePacketListenerImpl.disconnect: getRecorder");
136 | - this.connection.getRecorder().handleDisconnect();
137 | + this.getRecorder().handleDisconnect();
138 | }else{
139 | if (ServerSideReplayRecorderServer.config.isDebug()) MinecraftServer.LOGGER.info("ServerGamePacketListenerImpl.disconnect: getRecorder null");
140 | }
141 | @@ -2113,6 +2144,12 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Tic
142 | this.onDisconnect(reason, null);
143 | }
144 | public void onDisconnect(Component reason, @Nullable net.kyori.adventure.text.Component quitMessage) {
145 | + //Serversiderecorder start
146 | + ReplayRecorder recorder = this.getRecorder();
147 | + if (recorder != null){
148 | + recorder.handleDisconnect();
149 | + }
150 | + //Serversiderecorder end
151 | // Paper end
152 | // CraftBukkit start - Rarely it would send a disconnect line twice
153 | if (this.processedDisconnect) {
154 | @@ -2180,6 +2217,17 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Tic
155 | });
156 | throw new ReportedException(crashreport);
157 | }
158 | +
159 | + //Serversiderecorder start
160 | + if (ServerSideReplayRecorderServer.config.isDebug()) MinecraftServer.LOGGER.info("Connection.send: ");
161 | + ReplayRecorder recorder = this.getRecorder();
162 | + if (recorder != null){
163 | + if (ServerSideReplayRecorderServer.config.isDebug()) MinecraftServer.LOGGER.info("Connection.send: packet");
164 | + recorder.onPacket(packet);
165 | + }else{
166 | + if (ServerSideReplayRecorderServer.config.isDebug()) MinecraftServer.LOGGER.info("Connection.send: recorder null");
167 | + }
168 | + //Serversiderecorder end
169 | }
170 |
171 | @Override
172 | diff --git a/src/main/java/net/minecraft/server/network/ServerHandshakePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerHandshakePacketListenerImpl.java
173 | index 592eed28a8a700b02040689bf215ed7320bc518e..16489f145ff2b8d1697bd1ac709951774912e641 100644
174 | --- a/src/main/java/net/minecraft/server/network/ServerHandshakePacketListenerImpl.java
175 | +++ b/src/main/java/net/minecraft/server/network/ServerHandshakePacketListenerImpl.java
176 | @@ -38,13 +38,6 @@ public class ServerHandshakePacketListenerImpl implements ServerHandshakePacketL
177 |
178 |
179 | public ServerHandshakePacketListenerImpl(MinecraftServer server, Connection connection) {
180 | - //Serversiderecorder start
181 | - ReplayRecorder recorder = PlayerRecorder.playerRecorderMap.get(connection);
182 | - if (recorder != null){
183 | - connection.setRecorder(recorder);
184 | - }
185 | - //Serversiderecorder end
186 | -
187 | this.server = server;
188 | this.connection = connection;
189 | }
190 | @@ -183,12 +176,7 @@ public class ServerHandshakePacketListenerImpl implements ServerHandshakePacketL
191 |
192 | @Override
193 | public void onDisconnect(Component reason) {
194 | - //Serversiderecorder start
195 | - ReplayRecorder recorder = this.connection.getRecorder();
196 | - if (recorder != null){
197 | - recorder.handleDisconnect();
198 | - }
199 | - //Serversiderecorder end
200 | +
201 | }
202 |
203 | @Override
204 |
--------------------------------------------------------------------------------
/patches/server/0017-ServerSideRecorder.patch:
--------------------------------------------------------------------------------
1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
2 | From: Bryan1029384756 <23323626+Bryan1029384756@users.noreply.github.com>
3 | Date: Sun, 18 Jun 2023 22:03:16 -0500
4 | Subject: [PATCH] ServerSideRecorder
5 |
6 |
7 | diff --git a/src/main/java/net/minecraft/network/Connection.java b/src/main/java/net/minecraft/network/Connection.java
8 | index 6f7cbd65c8e6f539ba5228401549390b191f9c83..9a2777e39c0182bb6cfa302fac407783b3925f17 100644
9 | --- a/src/main/java/net/minecraft/network/Connection.java
10 | +++ b/src/main/java/net/minecraft/network/Connection.java
11 | @@ -44,9 +44,6 @@ import net.minecraft.network.protocol.game.ClientboundDisconnectPacket;
12 | import net.minecraft.network.protocol.login.ClientboundLoginDisconnectPacket;
13 | import net.minecraft.server.MinecraftServer;
14 | import net.minecraft.server.RunningOnDifferentThreadException;
15 | -import net.minecraft.serversidereplayrecorder.ServerSideReplayRecorderServer;
16 | -import net.minecraft.serversidereplayrecorder.recorder.ReplayRecorder;
17 | -import net.minecraft.serversidereplayrecorder.util.interfaces.RecorderHolder;
18 | import net.minecraft.util.LazyLoadedValue;
19 | import net.minecraft.util.Mth;
20 | import org.apache.commons.lang3.Validate;
21 | diff --git a/src/main/java/net/minecraft/server/network/ServerHandshakePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerHandshakePacketListenerImpl.java
22 | index 16489f145ff2b8d1697bd1ac709951774912e641..6b5a0ad2fd19361bc44f683d56656e8e7b9e7bc5 100644
23 | --- a/src/main/java/net/minecraft/server/network/ServerHandshakePacketListenerImpl.java
24 | +++ b/src/main/java/net/minecraft/server/network/ServerHandshakePacketListenerImpl.java
25 | @@ -4,15 +4,11 @@ import net.minecraft.SharedConstants;
26 | import net.minecraft.network.Connection;
27 | import net.minecraft.network.ConnectionProtocol;
28 | import net.minecraft.network.chat.Component;
29 | -import net.minecraft.network.chat.MutableComponent;
30 | import net.minecraft.network.protocol.handshake.ClientIntentionPacket;
31 | import net.minecraft.network.protocol.handshake.ServerHandshakePacketListener;
32 | import net.minecraft.network.protocol.login.ClientboundLoginDisconnectPacket;
33 | import net.minecraft.network.protocol.status.ServerStatus;
34 | import net.minecraft.server.MinecraftServer;
35 | -import net.minecraft.serversidereplayrecorder.recorder.PlayerRecorder;
36 | -import net.minecraft.serversidereplayrecorder.recorder.ReplayRecorder;
37 | -import net.minecraft.serversidereplayrecorder.util.interfaces.RecorderHolder;
38 |
39 | // CraftBukkit start
40 | import java.lang.ref.WeakReference;
41 | diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java
42 | index 99b9015aa628ea2434f2a9b697565f6f3524cf4c..1aa50493969f2fb841274ba24a30409812daf07d 100644
43 | --- a/src/main/java/net/minecraft/server/players/PlayerList.java
44 | +++ b/src/main/java/net/minecraft/server/players/PlayerList.java
45 | @@ -1198,7 +1198,7 @@ public abstract class PlayerList {
46 |
47 | if (player != null) {
48 | if (ServerSideReplayRecorderServer.config.isDebug()) MinecraftServer.LOGGER.info("PlayerList.broadcast: player");
49 | - ReplayRecorder recorder = ((RecorderHolder)(((ServerPlayer) player).connection.connection)).getRecorder();
50 | + ReplayRecorder recorder = ((RecorderHolder)(((ServerPlayer) player).connection)).getRecorder();
51 | if (recorder != null) {
52 | if (ServerSideReplayRecorderServer.config.isDebug()) MinecraftServer.LOGGER.info("PlayerList.broadcast: recorder");
53 | recorder.onPacket(packet);
54 | diff --git a/src/main/java/net/minecraft/serversidereplayrecorder/ServerSideReplayRecorderServer.java b/src/main/java/net/minecraft/serversidereplayrecorder/ServerSideReplayRecorderServer.java
55 | index a0cf4c044850fcfc7dcc33182716893466184b29..ae3826202dd3d14bd833caa50bc4ae47c286bff2 100644
56 | --- a/src/main/java/net/minecraft/serversidereplayrecorder/ServerSideReplayRecorderServer.java
57 | +++ b/src/main/java/net/minecraft/serversidereplayrecorder/ServerSideReplayRecorderServer.java
58 | @@ -73,12 +73,10 @@ public class ServerSideReplayRecorderServer {
59 | }
60 |
61 | public static String getConfigDirectory(){
62 | - System.out.println(System.getProperty("user.dir") + "\\config");
63 | return System.getProperty("user.dir") + "\\config";
64 | }
65 |
66 | public static String getDirectory(){
67 | - System.out.println(System.getProperty("user.dir"));
68 | return System.getProperty("user.dir");
69 | }
70 |
71 |
--------------------------------------------------------------------------------
/patches/server/0018-ServerSideRecorder.patch:
--------------------------------------------------------------------------------
1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
2 | From: Bryan1029384756 <23323626+Bryan1029384756@users.noreply.github.com>
3 | Date: Mon, 19 Jun 2023 18:29:18 -0500
4 | Subject: [PATCH] ServerSideRecorder
5 |
6 |
7 | diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java
8 | index 1aa50493969f2fb841274ba24a30409812daf07d..8c54cf82a5bfccfb28cf73797dff5c595caf6404 100644
9 | --- a/src/main/java/net/minecraft/server/players/PlayerList.java
10 | +++ b/src/main/java/net/minecraft/server/players/PlayerList.java
11 | @@ -171,9 +171,9 @@ public abstract class PlayerList {
12 |
13 | public void placeNewPlayer(Connection connection, ServerPlayer player) {
14 | //ServerSideReplayRecorder start
15 | -// if (ServerSideReplayRecorderServer.config.isRecording_enabled() && !PlayerRecorder.playerRecorderMap.containsKey(connection)
16 | -// && ( ServerSideReplayRecorderServer.config.getRecordable_users().contains(player.getGameProfile().getName())) != ServerSideReplayRecorderServer.config.invert_user_list() ) {
17 | - if (!PlayerRecorder.playerRecorderMap.containsKey(connection)) {
18 | + if (ServerSideReplayRecorderServer.config.isRecording_enabled() && !PlayerRecorder.playerRecorderMap.containsKey(connection)
19 | + && ( ServerSideReplayRecorderServer.config.getRecordable_users().contains(player.getGameProfile().getName())) != ServerSideReplayRecorderServer.config.invert_user_list() ) {
20 | + // if (!PlayerRecorder.playerRecorderMap.containsKey(connection)) {
21 | if (ServerSideReplayRecorderServer.config.isDebug()) MinecraftServer.LOGGER.info("PlayerList.placeNewPlayer: ");
22 | try {
23 | ServerSideReplayRecorderServer.LOGGER.info("Started Recording Player %s".formatted(player.getGameProfile().getName()));
24 | diff --git a/src/main/java/net/minecraft/serversidereplayrecorder/ServerSideReplayRecorderServer.java b/src/main/java/net/minecraft/serversidereplayrecorder/ServerSideReplayRecorderServer.java
25 | index ae3826202dd3d14bd833caa50bc4ae47c286bff2..1d6673b4e81a4f322cfde4b22779a999c134cf56 100644
26 | --- a/src/main/java/net/minecraft/serversidereplayrecorder/ServerSideReplayRecorderServer.java
27 | +++ b/src/main/java/net/minecraft/serversidereplayrecorder/ServerSideReplayRecorderServer.java
28 | @@ -23,16 +23,14 @@ public class ServerSideReplayRecorderServer {
29 | builder.disable(YAMLGenerator.Feature.WRITE_DOC_START_MARKER);
30 | builder.enable(YAMLGenerator.Feature.INDENT_ARRAYS_WITH_INDICATOR);
31 | yaml = new ObjectMapper(builder.build()).configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
32 | - // placeholders = ResourceBundle.getBundle("placeholders");
33 | - //upload_sites = ResourceBundle.getBundle("upload_sites");
34 | + upload_sites = ResourceBundle.getBundle("upload_sites");
35 | }
36 |
37 | public static final ExecutorService recorderExecutor = Executors.newSingleThreadExecutor(new DefaultThreadFactory("Replay",true));
38 |
39 | private static final ObjectMapper yaml;
40 |
41 | - //public static final ResourceBundle placeholders;
42 | - //public static final ResourceBundle upload_sites;
43 | + public static final ResourceBundle upload_sites;
44 |
45 | public static final Logger LOGGER = LoggerFactory.getLogger(ServerSideReplayRecorderServer.class.getName());
46 |
47 | diff --git a/src/main/java/net/minecraft/serversidereplayrecorder/config/MainConfig.java b/src/main/java/net/minecraft/serversidereplayrecorder/config/MainConfig.java
48 | index ebd564edbbf60f603e0cf642af99c2f8f5bf1601..8e2d0ec530e408e572d1f0af38f6206e1fa94af7 100644
49 | --- a/src/main/java/net/minecraft/serversidereplayrecorder/config/MainConfig.java
50 | +++ b/src/main/java/net/minecraft/serversidereplayrecorder/config/MainConfig.java
51 | @@ -17,7 +17,7 @@ public class MainConfig {
52 | private String server_name = "My Server";
53 | private Set recordable_users = new HashSet<>();
54 | private boolean invert_user_list = false;
55 | - private boolean recording_enabled = false;
56 | + private boolean recording_enabled = true;
57 | private boolean use_server_timestamps = true;
58 | private boolean assume_unloaded_chunks_dont_change = true;
59 | private boolean render_distance_fog_fix = false;
60 | diff --git a/src/main/java/net/minecraft/serversidereplayrecorder/recorder/ReplayRecorder.java b/src/main/java/net/minecraft/serversidereplayrecorder/recorder/ReplayRecorder.java
61 | index 0580cd5d9c7512b8e6d04c363ba6d48e28ee8535..f0627468012f1725ff4493e559ad8636e122460e 100644
62 | --- a/src/main/java/net/minecraft/serversidereplayrecorder/recorder/ReplayRecorder.java
63 | +++ b/src/main/java/net/minecraft/serversidereplayrecorder/recorder/ReplayRecorder.java
64 | @@ -125,7 +125,6 @@ public abstract class ReplayRecorder {
65 | object.addProperty("fileFormat", "MCPR");
66 | object.addProperty("fileFormatVersion", 14); //Unlikely to change any time soon, last time this was updates was several major versions ago.
67 | object.addProperty("protocol", SharedConstants.getProtocolVersion());
68 | - // object.addProperty("generator", "thecolonel63's Server Side Replay Recorder " + placeholders.getString("version") + "-" + placeholders.getString("build"));
69 | object.addProperty("selfId", -1);
70 | object.add("players", new JsonArray());
71 | FileWriter fw = new FileWriter(Paths.get(tmp_folder.getAbsolutePath(), "metaData.json").toFile(), false);
72 | diff --git a/src/main/java/net/minecraft/serversidereplayrecorder/util/FileHandlingUtility.java b/src/main/java/net/minecraft/serversidereplayrecorder/util/FileHandlingUtility.java
73 | index 13ffb6123158c09605a0030afa35d2ca541eb5ad..19e7c8fa2c1390f534972884ddd9877fbf73f2b0 100644
74 | --- a/src/main/java/net/minecraft/serversidereplayrecorder/util/FileHandlingUtility.java
75 | +++ b/src/main/java/net/minecraft/serversidereplayrecorder/util/FileHandlingUtility.java
76 | @@ -1,5 +1,7 @@
77 | package net.minecraft.serversidereplayrecorder.util;
78 |
79 | +import net.minecraft.ChatFormatting;
80 | +import net.minecraft.network.chat.ClickEvent;
81 | import net.minecraft.network.chat.Component;
82 | import net.minecraft.serversidereplayrecorder.ServerSideReplayRecorderServer;
83 | import org.jetbrains.annotations.NotNull;
84 | @@ -149,18 +151,18 @@ public class FileHandlingUtility {
85 |
86 | Component response_text = Component.literal(response);
87 |
88 | -// if (ServerSideReplayRecorderServer.upload_sites.containsKey(url.getHost())){
89 | -// String regex = ServerSideReplayRecorderServer.upload_sites.getString(url.getHost());
90 | -// Pattern pattern = Pattern.compile(regex);
91 | -// Matcher matcher = pattern.matcher(response);
92 | -// if (matcher.find()){
93 | -// String download_url = matcher.group(1);
94 | -// response_text = Component.literal("%s download link: ".formatted(file.getName())).formatted(Formatting.YELLOW)
95 | -// .append(Component.literal(download_url)
96 | -// .formatted(Formatting.UNDERLINE,Formatting.BLUE)
97 | -// .styled(style -> style.withClickEvent(new ClickEvent(ClickEvent.Action.OPEN_URL, download_url))));
98 | -// }
99 | -// }
100 | + if (ServerSideReplayRecorderServer.upload_sites.containsKey(url.getHost())){
101 | + String regex = ServerSideReplayRecorderServer.upload_sites.getString(url.getHost());
102 | + Pattern pattern = Pattern.compile(regex);
103 | + Matcher matcher = pattern.matcher(response);
104 | + if (matcher.find()){
105 | + String download_url = matcher.group(1);
106 | + response_text = Component.literal("%s download link: ".formatted(file.getName())).withStyle(ChatFormatting.YELLOW)
107 | + .append(Component.literal(download_url)
108 | + .withStyle(ChatFormatting.UNDERLINE,ChatFormatting.BLUE)
109 | + .withStyle(style -> style.withClickEvent(new ClickEvent(ClickEvent.Action.OPEN_URL, download_url))));
110 | + }
111 | + }
112 |
113 | return response_text;
114 | }
115 | diff --git a/src/main/resources/upload_sites.properties b/src/main/resources/upload_sites.properties
116 | new file mode 100644
117 | index 0000000000000000000000000000000000000000..49bc43c610f43604db01e254929d3c27c7152d70
118 | --- /dev/null
119 | +++ b/src/main/resources/upload_sites.properties
120 | @@ -0,0 +1,2 @@
121 | +file.io: \\{"success":true,"status":200,.*"link":"(http[^"]+)".*\\}
122 | +tmpfiles.org: \\{"status":"success",.*"data":\\{.*"url":"(http[^"]+)".*\\}.*\\}
123 | \ No newline at end of file
124 |
--------------------------------------------------------------------------------
/patches/server/0019-ServerSideRecorder.patch:
--------------------------------------------------------------------------------
1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
2 | From: Bryan1029384756 <23323626+Bryan1029384756@users.noreply.github.com>
3 | Date: Mon, 19 Jun 2023 18:37:49 -0500
4 | Subject: [PATCH] ServerSideRecorder
5 |
6 |
7 | diff --git a/src/main/java/net/minecraft/serversidereplayrecorder/command/ReplayCommand.java b/src/main/java/net/minecraft/serversidereplayrecorder/command/ReplayCommand.java
8 | index 50634cba3a60eea3d8474c88e8a34f1c97c8fdf0..d598a7901459fef7334025ca83758b8df0d0c99d 100644
9 | --- a/src/main/java/net/minecraft/serversidereplayrecorder/command/ReplayCommand.java
10 | +++ b/src/main/java/net/minecraft/serversidereplayrecorder/command/ReplayCommand.java
11 | @@ -180,7 +180,7 @@ public class ReplayCommand {
12 | });
13 | if (count.get() > 0) {
14 | source.sendSuccess(()->Component.literal("Added players will start recording next time they join the server"), true);
15 | - //ServerSideReplayRecorderServer.saveConfig();
16 | + ServerSideReplayRecorderServer.saveConfig();
17 | }
18 | return 0;
19 | })
20 |
--------------------------------------------------------------------------------
/patches/server/0021-ServerSideVoiceChat.patch:
--------------------------------------------------------------------------------
1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
2 | From: Bryan1029384756 <23323626+Bryan1029384756@users.noreply.github.com>
3 | Date: Sun, 25 Jun 2023 18:23:30 -0500
4 | Subject: [PATCH] ServerSideVoiceChat
5 |
6 |
7 | diff --git a/src/main/java/net/minecraft/serversidereplayrecorder/voice/ServerSideVoiceChat.java b/src/main/java/net/minecraft/serversidereplayrecorder/voice/ServerSideVoiceChat.java
8 | index b5ddb3a6b717d283f2f7cc3b475b03aa0b527ea6..093d1a39efe81c137674d6c650a31bf243ecdbf7 100644
9 | --- a/src/main/java/net/minecraft/serversidereplayrecorder/voice/ServerSideVoiceChat.java
10 | +++ b/src/main/java/net/minecraft/serversidereplayrecorder/voice/ServerSideVoiceChat.java
11 | @@ -2,11 +2,12 @@ package net.minecraft.serversidereplayrecorder.voice;
12 |
13 | import de.maxhenkel.voicechat.api.VoicechatApi;
14 | import de.maxhenkel.voicechat.api.VoicechatPlugin;
15 | -import de.maxhenkel.voicechat.api.events.EventRegistration;
16 | -import de.maxhenkel.voicechat.api.events.MicrophonePacketEvent;
17 | +import de.maxhenkel.voicechat.api.VoicechatServerApi;
18 | +import de.maxhenkel.voicechat.api.events.*;
19 | import de.maxhenkel.voicechat.api.opus.OpusDecoder;
20 | import net.minecraft.server.level.ServerPlayer;
21 | import net.minecraft.serversidereplayrecorder.ServerSideReplayRecorderServer;
22 | +import net.minecraft.serversidereplayrecorder.voice.recording.VoicechatRecorder;
23 | import org.bukkit.Bukkit;
24 | import javax.sound.sampled.*;
25 | import java.io.*;
26 | @@ -18,7 +19,8 @@ import java.util.*;
27 | public class ServerSideVoiceChat implements VoicechatPlugin {
28 |
29 | private OpusDecoder decoder;
30 | -
31 | + public static double distance;
32 | + public static VoicechatApi SERVERAPI;
33 | @Override
34 | public String getPluginId() {
35 | return "PaperRecord";
36 | @@ -27,15 +29,22 @@ public class ServerSideVoiceChat implements VoicechatPlugin {
37 | @Override
38 | public void initialize(VoicechatApi api) {
39 | System.out.println("Started recording voice chat using PaperRecord");
40 | + this.distance = api.getVoiceChatDistance();
41 | + this.SERVERAPI = api;
42 | }
43 |
44 | @Override
45 | public void registerEvents(EventRegistration registration) {
46 | - registration.registerEvent(MicrophonePacketEvent.class, this::onSound);
47 | + registration.registerEvent(EntitySoundPacketEvent.class, VoicechatRecorder::onEntitySound);
48 | + registration.registerEvent(LocationalSoundPacketEvent.class, VoicechatRecorder::onLocationalSound);
49 | + registration.registerEvent(StaticSoundPacketEvent.class, VoicechatRecorder::onStaticSound);
50 | + //registration.registerEvent(ClientSoundEvent.class, VoicechatRecorder::onSound);
51 | + // registration.registerEvent(MicrophonePacketEvent.class, this::onSound);
52 | }
53 |
54 |
55 |
56 | +
57 | public Map> playerPacketMap = new HashMap<>();
58 | private Map lastPacketTimeMap = new HashMap<>();
59 | private static final int FRAME_SIZE_MS = 20; // Frame size in milliseconds
60 | diff --git a/src/main/java/net/minecraft/serversidereplayrecorder/voice/Utils.java b/src/main/java/net/minecraft/serversidereplayrecorder/voice/Utils.java
61 | new file mode 100644
62 | index 0000000000000000000000000000000000000000..36132fcf9b14c52b9e81929172fea8277b28fbc8
63 | --- /dev/null
64 | +++ b/src/main/java/net/minecraft/serversidereplayrecorder/voice/Utils.java
65 | @@ -0,0 +1,34 @@
66 | +package net.minecraft.serversidereplayrecorder.voice;
67 | +
68 | +public class Utils {
69 | +
70 | + public static short[] bytesToShorts(byte[] bytes) {
71 | + if (bytes.length % 2 != 0) {
72 | + throw new IllegalArgumentException("Input bytes need to be divisible by 2");
73 | + }
74 | + short[] data = new short[bytes.length / 2];
75 | + for (int i = 0; i < bytes.length; i += 2) {
76 | + data[i / 2] = bytesToShort(bytes[i], bytes[i + 1]);
77 | + }
78 | + return data;
79 | + }
80 | +
81 | + public static byte[] shortsToBytes(short[] shorts) {
82 | + byte[] data = new byte[shorts.length * 2];
83 | + for (int i = 0; i < shorts.length; i++) {
84 | + byte[] split = shortToBytes(shorts[i]);
85 | + data[i * 2] = split[0];
86 | + data[i * 2 + 1] = split[1];
87 | + }
88 | + return data;
89 | + }
90 | +
91 | + public static short bytesToShort(byte b1, byte b2) {
92 | + return (short) (((b2 & 0xFF) << 8) | (b1 & 0xFF));
93 | + }
94 | +
95 | + public static byte[] shortToBytes(short s) {
96 | + return new byte[]{(byte) (s & 0xFF), (byte) ((s >> 8) & 0xFF)};
97 | + }
98 | +
99 | +}
100 | diff --git a/src/main/java/net/minecraft/serversidereplayrecorder/voice/net/AbstractSoundPacket.java b/src/main/java/net/minecraft/serversidereplayrecorder/voice/net/AbstractSoundPacket.java
101 | new file mode 100644
102 | index 0000000000000000000000000000000000000000..9546f9d8e0fcc92d049a2e716398556f1b24a141
103 | --- /dev/null
104 | +++ b/src/main/java/net/minecraft/serversidereplayrecorder/voice/net/AbstractSoundPacket.java
105 | @@ -0,0 +1,51 @@
106 | +package net.minecraft.serversidereplayrecorder.voice.net;
107 | +
108 | +import net.minecraft.network.FriendlyByteBuf;
109 | +import net.minecraft.serversidereplayrecorder.voice.Utils;
110 | +
111 | +import java.util.UUID;
112 | +
113 | +public abstract class AbstractSoundPacket> implements Packet {
114 | +
115 | + public static final short CURRENT_VERSION = 1;
116 | +
117 | + protected short version;
118 | + protected UUID id;
119 | + protected short[] rawAudio;
120 | +
121 | + public AbstractSoundPacket(UUID id, short[] rawAudio) {
122 | + version = CURRENT_VERSION;
123 | + this.id = id;
124 | + this.rawAudio = rawAudio;
125 | + }
126 | +
127 | + public AbstractSoundPacket() {
128 | +
129 | + }
130 | +
131 | + public UUID getId() {
132 | + return id;
133 | + }
134 | +
135 | + public short[] getRawAudio() {
136 | + return rawAudio;
137 | + }
138 | +
139 | + @Override
140 | + public T fromBytes(FriendlyByteBuf buf) throws VersionCompatibilityException {
141 | + version = buf.readShort();
142 | + if (version != CURRENT_VERSION && version != 0) {
143 | + throw new VersionCompatibilityException("Incompatible version");
144 | + }
145 | + id = buf.readUUID();
146 | + rawAudio = Utils.bytesToShorts(buf.readByteArray());
147 | + return (T) this;
148 | + }
149 | +
150 | + @Override
151 | + public void toBytes(FriendlyByteBuf buf) {
152 | + buf.writeShort(version);
153 | + buf.writeUUID(id);
154 | + buf.writeByteArray(Utils.shortsToBytes(rawAudio));
155 | + }
156 | +}
157 | diff --git a/src/main/java/net/minecraft/serversidereplayrecorder/voice/net/EntitySoundPacket.java b/src/main/java/net/minecraft/serversidereplayrecorder/voice/net/EntitySoundPacket.java
158 | new file mode 100644
159 | index 0000000000000000000000000000000000000000..f767678d31b5c8525eaf501878e112b4cb0c277b
160 | --- /dev/null
161 | +++ b/src/main/java/net/minecraft/serversidereplayrecorder/voice/net/EntitySoundPacket.java
162 | @@ -0,0 +1,64 @@
163 | +package net.minecraft.serversidereplayrecorder.voice.net;
164 | +
165 | +
166 | +import net.minecraft.network.FriendlyByteBuf;
167 | +import net.minecraft.resources.ResourceLocation;
168 | +import net.minecraft.serversidereplayrecorder.voice.ServerSideVoiceChat;
169 | +
170 | +import java.util.UUID;
171 | +
172 | +public class EntitySoundPacket extends AbstractSoundPacket {
173 | +
174 | + public static ResourceLocation ID = new ResourceLocation("PaperRecord", "entity_sound");
175 | +
176 | + private boolean whispering;
177 | + private float distance;
178 | +
179 | + public EntitySoundPacket(UUID id, short[] rawAudio, boolean whispering, float distance) {
180 | + super(id, rawAudio);
181 | + this.whispering = whispering;
182 | + this.distance = distance;
183 | + }
184 | +
185 | + public EntitySoundPacket() {
186 | +
187 | + }
188 | +
189 | + @Override
190 | + public ResourceLocation getIdentifier() {
191 | + return ID;
192 | + }
193 | +
194 | + public boolean isWhispering() {
195 | + return whispering;
196 | + }
197 | +
198 | + public float getDistance() {
199 | + return distance;
200 | + }
201 | +
202 | + @Override
203 | + public EntitySoundPacket fromBytes(FriendlyByteBuf buf) throws VersionCompatibilityException {
204 | + super.fromBytes(buf);
205 | + whispering = buf.readBoolean();
206 | + if (version >= 1) {
207 | + distance = buf.readFloat();
208 | + } else {
209 | + distance = (float) ServerSideVoiceChat.distance;
210 | + }
211 | + return this;
212 | + }
213 | +
214 | + @Override
215 | + public void toBytes(FriendlyByteBuf buf) {
216 | + super.toBytes(buf);
217 | + buf.writeBoolean(whispering);
218 | + buf.writeFloat(distance);
219 | + }
220 | +
221 | +// @Override
222 | +// public void onPacket() {
223 | +// AudioPlaybackManager.INSTANCE.onEntitySound(this);
224 | +// }
225 | +
226 | +}
227 | diff --git a/src/main/java/net/minecraft/serversidereplayrecorder/voice/net/LocationalSoundPacket.java b/src/main/java/net/minecraft/serversidereplayrecorder/voice/net/LocationalSoundPacket.java
228 | new file mode 100644
229 | index 0000000000000000000000000000000000000000..a035e09d1f5f1fa6e8e294bd52a25ad0e66683ca
230 | --- /dev/null
231 | +++ b/src/main/java/net/minecraft/serversidereplayrecorder/voice/net/LocationalSoundPacket.java
232 | @@ -0,0 +1,66 @@
233 | +package net.minecraft.serversidereplayrecorder.voice.net;
234 | +
235 | +import de.maxhenkel.voicechat.api.Position;
236 | +import net.minecraft.network.FriendlyByteBuf;
237 | +import net.minecraft.resources.ResourceLocation;
238 | +import net.minecraft.serversidereplayrecorder.voice.ServerSideVoiceChat;
239 | +
240 | +import java.util.UUID;
241 | +
242 | +public class LocationalSoundPacket extends AbstractSoundPacket {
243 | +
244 | + public static ResourceLocation ID = new ResourceLocation("PaperRecord", "locational_sound");
245 | +
246 | + private Position location;
247 | + private float distance;
248 | +
249 | + public LocationalSoundPacket(UUID id, short[] rawAudio, Position location, float distance) {
250 | + super(id, rawAudio);
251 | + this.location = location;
252 | + this.distance = distance;
253 | + }
254 | +
255 | + public LocationalSoundPacket() {
256 | +
257 | + }
258 | +
259 | + public Position getLocation() {
260 | + return location;
261 | + }
262 | +
263 | + public float getDistance() {
264 | + return distance;
265 | + }
266 | +
267 | + @Override
268 | + public ResourceLocation getIdentifier() {
269 | + return ID;
270 | + }
271 | +
272 | + @Override
273 | + public LocationalSoundPacket fromBytes(FriendlyByteBuf buf) throws VersionCompatibilityException {
274 | + super.fromBytes(buf);
275 | + location = ServerSideVoiceChat.SERVERAPI.createPosition(buf.readDouble(), buf.readDouble(), buf.readDouble());
276 | + if (version >= 1) {
277 | + distance = buf.readFloat();
278 | + } else {
279 | + distance = (float) ServerSideVoiceChat.distance;
280 | + }
281 | + return this;
282 | + }
283 | +
284 | + @Override
285 | + public void toBytes(FriendlyByteBuf buf) {
286 | + super.toBytes(buf);
287 | + buf.writeDouble(location.getX());
288 | + buf.writeDouble(location.getY());
289 | + buf.writeDouble(location.getZ());
290 | + buf.writeFloat(distance);
291 | + }
292 | +
293 | +// @Override
294 | +// public void onPacket() {
295 | +// AudioPlaybackManager.INSTANCE.onLocationalSound(this);
296 | +// }
297 | +
298 | +}
299 | diff --git a/src/main/java/net/minecraft/serversidereplayrecorder/voice/net/Packet.java b/src/main/java/net/minecraft/serversidereplayrecorder/voice/net/Packet.java
300 | new file mode 100644
301 | index 0000000000000000000000000000000000000000..0913d06dcdc14c618aea3b8d19b36be16e70ae7e
302 | --- /dev/null
303 | +++ b/src/main/java/net/minecraft/serversidereplayrecorder/voice/net/Packet.java
304 | @@ -0,0 +1,15 @@
305 | +package net.minecraft.serversidereplayrecorder.voice.net;
306 | +
307 | +import net.minecraft.network.FriendlyByteBuf;
308 | +import net.minecraft.resources.ResourceLocation;
309 | +
310 | +public interface Packet> {
311 | +
312 | + ResourceLocation getIdentifier();
313 | +
314 | + T fromBytes(FriendlyByteBuf buf) throws VersionCompatibilityException;
315 | +
316 | + void toBytes(FriendlyByteBuf buf);
317 | +
318 | +
319 | +}
320 | diff --git a/src/main/java/net/minecraft/serversidereplayrecorder/voice/net/StaticSoundPacket.java b/src/main/java/net/minecraft/serversidereplayrecorder/voice/net/StaticSoundPacket.java
321 | new file mode 100644
322 | index 0000000000000000000000000000000000000000..15934e72e926d4dae343d6fc0b283c078487c741
323 | --- /dev/null
324 | +++ b/src/main/java/net/minecraft/serversidereplayrecorder/voice/net/StaticSoundPacket.java
325 | @@ -0,0 +1,25 @@
326 | +package net.minecraft.serversidereplayrecorder.voice.net;
327 | +
328 | +import net.minecraft.resources.ResourceLocation;
329 | +
330 | +import java.util.UUID;
331 | +
332 | +public class StaticSoundPacket extends AbstractSoundPacket {
333 | +
334 | + public static ResourceLocation ID = new ResourceLocation("PaperRecord", "static_sound");
335 | +
336 | + public StaticSoundPacket(UUID id, short[] rawAudio) {
337 | + super(id, rawAudio);
338 | + }
339 | +
340 | + public StaticSoundPacket() {
341 | +
342 | + }
343 | +
344 | + @Override
345 | + public ResourceLocation getIdentifier() {
346 | + return ID;
347 | + }
348 | +
349 | +
350 | +}
351 | diff --git a/src/main/java/net/minecraft/serversidereplayrecorder/voice/net/VersionCompatibilityException.java b/src/main/java/net/minecraft/serversidereplayrecorder/voice/net/VersionCompatibilityException.java
352 | new file mode 100644
353 | index 0000000000000000000000000000000000000000..bdeee43a3512ed64d07051d89e49f6dfb7a7379e
354 | --- /dev/null
355 | +++ b/src/main/java/net/minecraft/serversidereplayrecorder/voice/net/VersionCompatibilityException.java
356 | @@ -0,0 +1,8 @@
357 | +package net.minecraft.serversidereplayrecorder.voice.net;
358 | +
359 | +public class VersionCompatibilityException extends Exception {
360 | +
361 | + public VersionCompatibilityException(String message) {
362 | + super(message);
363 | + }
364 | +}
365 | diff --git a/src/main/java/net/minecraft/serversidereplayrecorder/voice/recording/VoicechatRecorder.java b/src/main/java/net/minecraft/serversidereplayrecorder/voice/recording/VoicechatRecorder.java
366 | new file mode 100644
367 | index 0000000000000000000000000000000000000000..9f6d7d9e00a8ff4c1a6f5f274ce4479199826496
368 | --- /dev/null
369 | +++ b/src/main/java/net/minecraft/serversidereplayrecorder/voice/recording/VoicechatRecorder.java
370 | @@ -0,0 +1,67 @@
371 | +package net.minecraft.serversidereplayrecorder.voice.recording;
372 | +
373 | +
374 | +import de.maxhenkel.voicechat.api.events.*;
375 | +import de.maxhenkel.voicechat.api.opus.OpusDecoder;
376 | +import de.maxhenkel.voicechat.api.packets.SoundPacket;
377 | +import io.netty.buffer.Unpooled;
378 | +import net.minecraft.network.FriendlyByteBuf;
379 | +import net.minecraft.network.protocol.game.ClientboundCustomPayloadPacket;
380 | +import net.minecraft.server.MinecraftServer;
381 | +import net.minecraft.serversidereplayrecorder.ServerSideReplayRecorderServer;
382 | +import net.minecraft.serversidereplayrecorder.recorder.ReplayRecorder;
383 | +import net.minecraft.serversidereplayrecorder.voice.net.EntitySoundPacket;
384 | +import net.minecraft.serversidereplayrecorder.voice.net.LocationalSoundPacket;
385 | +import net.minecraft.serversidereplayrecorder.voice.net.Packet;
386 | +import net.minecraft.serversidereplayrecorder.voice.net.StaticSoundPacket;
387 | +
388 | +import java.util.UUID;
389 | +
390 | +public class VoicechatRecorder {
391 | +
392 | +// private static final Minecraft MC = Minecraft.getInstance();
393 | +
394 | + public static void onEntitySound(EntitySoundPacketEvent event) {
395 | + short[] rawAudio = getRawAudio(event, event.getPacket());
396 | + send(new EntitySoundPacket(event.getPacket().getEntityUuid(), rawAudio, event.getPacket().isWhispering(), event.getPacket().getDistance()));
397 | + }
398 | +
399 | + public static void onLocationalSound(LocationalSoundPacketEvent event) {
400 | + short[] rawAudio = getRawAudio(event, event.getPacket());
401 | + send(new LocationalSoundPacket(event.getPacket().getSender(), rawAudio, event.getPacket().getPosition(), event.getPacket().getDistance()));
402 | + }
403 | +
404 | + public static void onStaticSound(StaticSoundPacketEvent event) {
405 | + short[] rawAudio = getRawAudio(event, event.getPacket());
406 | + send(new StaticSoundPacket(event.getPacket().getSender(), rawAudio));
407 | + }
408 | +
409 | + public static short[] getRawAudio(SoundPacketEvent> event, SoundPacket packet){
410 | + OpusDecoder decoder = event.getVoicechat().createDecoder();
411 | +
412 | + byte[] opusData = packet.getOpusEncodedData();
413 | + return decoder.decode(opusData);
414 | + }
415 | +
416 | +// public static void onSound(ClientSoundEvent event) {
417 | +// UUID id = ClientManager.getPlayerStateManager().getOwnID();
418 | +// short[] rawAudio = event.getRawAudio();
419 | +//
420 | +// if (ReplayVoicechatPlugin.CLIENT_API.getGroup() != null) {
421 | +// send(new StaticSoundPacket(id, rawAudio));
422 | +// } else {
423 | +// send(new EntitySoundPacket(id, rawAudio, event.isWhispering(), (float) ReplayVoicechatPlugin.CLIENT_API.getVoiceChatDistance()));
424 | +// }
425 | +// }
426 | +
427 | + public static void send(Packet> packet) {
428 | + FriendlyByteBuf buf = new FriendlyByteBuf(Unpooled.buffer());
429 | + packet.toBytes(buf);
430 | + ClientboundCustomPayloadPacket fakeP = new ClientboundCustomPayloadPacket(packet.getIdentifier(), buf);
431 | + for (ReplayRecorder recorder : ReplayRecorder.active_recorders){
432 | + recorder.onPacket(fakeP);
433 | + }
434 | + // ReplayInterface.INSTANCE.sendFakePacket(packet.getIdentifier(), buf);
435 | + }
436 | +
437 | +}
438 |
--------------------------------------------------------------------------------
/patches/server/0022-ServerSideVoiceChat.patch:
--------------------------------------------------------------------------------
1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
2 | From: Bryan1029384756 <23323626+Bryan1029384756@users.noreply.github.com>
3 | Date: Sun, 25 Jun 2023 19:24:20 -0500
4 | Subject: [PATCH] ServerSideVoiceChat
5 |
6 |
7 | diff --git a/src/main/java/net/minecraft/serversidereplayrecorder/recorder/ReplayRecorder.java b/src/main/java/net/minecraft/serversidereplayrecorder/recorder/ReplayRecorder.java
8 | index f0627468012f1725ff4493e559ad8636e122460e..b4450cb0ba56b113d21da107951f4d4c49975c6e 100644
9 | --- a/src/main/java/net/minecraft/serversidereplayrecorder/recorder/ReplayRecorder.java
10 | +++ b/src/main/java/net/minecraft/serversidereplayrecorder/recorder/ReplayRecorder.java
11 | @@ -330,7 +330,7 @@ public abstract class ReplayRecorder {
12 |
13 | protected final AtomicReference>> packetQueue = new AtomicReference<>(new ConcurrentLinkedQueue<>());
14 |
15 | - protected void save(Packet> packet) {
16 | + public void save(Packet> packet) {
17 | if (ServerSideReplayRecorderServer.config.isDebug()) MinecraftServer.LOGGER.info("ReplayRecorder.save: ");
18 | if (ServerSideReplayRecorderServer.config.use_server_timestamps()) {
19 | if (ServerSideReplayRecorderServer.config.isDebug()) MinecraftServer.LOGGER.info("ReplayRecorder.save: use_server_timestamps");
20 | diff --git a/src/main/java/net/minecraft/serversidereplayrecorder/voice/ServerSideVoiceChat.java b/src/main/java/net/minecraft/serversidereplayrecorder/voice/ServerSideVoiceChat.java
21 | index 093d1a39efe81c137674d6c650a31bf243ecdbf7..1cd99d4708062328e338b25958cd3fabd15b25fb 100644
22 | --- a/src/main/java/net/minecraft/serversidereplayrecorder/voice/ServerSideVoiceChat.java
23 | +++ b/src/main/java/net/minecraft/serversidereplayrecorder/voice/ServerSideVoiceChat.java
24 | @@ -2,7 +2,6 @@ package net.minecraft.serversidereplayrecorder.voice;
25 |
26 | import de.maxhenkel.voicechat.api.VoicechatApi;
27 | import de.maxhenkel.voicechat.api.VoicechatPlugin;
28 | -import de.maxhenkel.voicechat.api.VoicechatServerApi;
29 | import de.maxhenkel.voicechat.api.events.*;
30 | import de.maxhenkel.voicechat.api.opus.OpusDecoder;
31 | import net.minecraft.server.level.ServerPlayer;
32 | @@ -18,7 +17,7 @@ import java.util.*;
33 |
34 | public class ServerSideVoiceChat implements VoicechatPlugin {
35 |
36 | - private OpusDecoder decoder;
37 | + public static OpusDecoder decoder;
38 | public static double distance;
39 | public static VoicechatApi SERVERAPI;
40 | @Override
41 | @@ -28,6 +27,9 @@ public class ServerSideVoiceChat implements VoicechatPlugin {
42 |
43 | @Override
44 | public void initialize(VoicechatApi api) {
45 | + if (decoder == null) {
46 | + decoder = api.createDecoder();
47 | + }
48 | System.out.println("Started recording voice chat using PaperRecord");
49 | this.distance = api.getVoiceChatDistance();
50 | this.SERVERAPI = api;
51 | @@ -38,13 +40,10 @@ public class ServerSideVoiceChat implements VoicechatPlugin {
52 | registration.registerEvent(EntitySoundPacketEvent.class, VoicechatRecorder::onEntitySound);
53 | registration.registerEvent(LocationalSoundPacketEvent.class, VoicechatRecorder::onLocationalSound);
54 | registration.registerEvent(StaticSoundPacketEvent.class, VoicechatRecorder::onStaticSound);
55 | - //registration.registerEvent(ClientSoundEvent.class, VoicechatRecorder::onSound);
56 | - // registration.registerEvent(MicrophonePacketEvent.class, this::onSound);
57 | + registration.registerEvent(MicrophonePacketEvent.class, VoicechatRecorder::onSound);
58 | }
59 |
60 |
61 | -
62 | -
63 | public Map> playerPacketMap = new HashMap<>();
64 | private Map lastPacketTimeMap = new HashMap<>();
65 | private static final int FRAME_SIZE_MS = 20; // Frame size in milliseconds
66 | @@ -62,10 +61,6 @@ public class ServerSideVoiceChat implements VoicechatPlugin {
67 | public void onSound(MicrophonePacketEvent event) {
68 | UUID playerUuid = event.getSenderConnection().getPlayer().getUuid();
69 |
70 | - if (decoder == null) {
71 | - decoder = event.getVoicechat().createDecoder();
72 | - }
73 | -
74 | long now = System.currentTimeMillis();
75 | long lastPacketTime = lastPacketTimeMap.get(playerUuid);
76 | if (lastPacketTime != -1) {
77 | diff --git a/src/main/java/net/minecraft/serversidereplayrecorder/voice/net/EntitySoundPacket.java b/src/main/java/net/minecraft/serversidereplayrecorder/voice/net/EntitySoundPacket.java
78 | index f767678d31b5c8525eaf501878e112b4cb0c277b..57bccb828db34436c80d4ec05c71b33735cf5a46 100644
79 | --- a/src/main/java/net/minecraft/serversidereplayrecorder/voice/net/EntitySoundPacket.java
80 | +++ b/src/main/java/net/minecraft/serversidereplayrecorder/voice/net/EntitySoundPacket.java
81 | @@ -9,7 +9,7 @@ import java.util.UUID;
82 |
83 | public class EntitySoundPacket extends AbstractSoundPacket {
84 |
85 | - public static ResourceLocation ID = new ResourceLocation("PaperRecord", "entity_sound");
86 | + public static ResourceLocation ID = new ResourceLocation("replayvoicechat", "entity_sound");
87 |
88 | private boolean whispering;
89 | private float distance;
90 | diff --git a/src/main/java/net/minecraft/serversidereplayrecorder/voice/net/LocationalSoundPacket.java b/src/main/java/net/minecraft/serversidereplayrecorder/voice/net/LocationalSoundPacket.java
91 | index a035e09d1f5f1fa6e8e294bd52a25ad0e66683ca..6df16a76112407c65e7e6dad344a3c91d330bec4 100644
92 | --- a/src/main/java/net/minecraft/serversidereplayrecorder/voice/net/LocationalSoundPacket.java
93 | +++ b/src/main/java/net/minecraft/serversidereplayrecorder/voice/net/LocationalSoundPacket.java
94 | @@ -9,7 +9,7 @@ import java.util.UUID;
95 |
96 | public class LocationalSoundPacket extends AbstractSoundPacket {
97 |
98 | - public static ResourceLocation ID = new ResourceLocation("PaperRecord", "locational_sound");
99 | + public static ResourceLocation ID = new ResourceLocation("replayvoicechat", "locational_sound");
100 |
101 | private Position location;
102 | private float distance;
103 | diff --git a/src/main/java/net/minecraft/serversidereplayrecorder/voice/net/StaticSoundPacket.java b/src/main/java/net/minecraft/serversidereplayrecorder/voice/net/StaticSoundPacket.java
104 | index 15934e72e926d4dae343d6fc0b283c078487c741..6280fe05ce1b60277eecbf35911d7f100a474443 100644
105 | --- a/src/main/java/net/minecraft/serversidereplayrecorder/voice/net/StaticSoundPacket.java
106 | +++ b/src/main/java/net/minecraft/serversidereplayrecorder/voice/net/StaticSoundPacket.java
107 | @@ -6,7 +6,7 @@ import java.util.UUID;
108 |
109 | public class StaticSoundPacket extends AbstractSoundPacket {
110 |
111 | - public static ResourceLocation ID = new ResourceLocation("PaperRecord", "static_sound");
112 | + public static ResourceLocation ID = new ResourceLocation("replayvoicechat", "static_sound");
113 |
114 | public StaticSoundPacket(UUID id, short[] rawAudio) {
115 | super(id, rawAudio);
116 | diff --git a/src/main/java/net/minecraft/serversidereplayrecorder/voice/recording/VoicechatRecorder.java b/src/main/java/net/minecraft/serversidereplayrecorder/voice/recording/VoicechatRecorder.java
117 | index 9f6d7d9e00a8ff4c1a6f5f274ce4479199826496..ca56f29556cfd1d6da95b930c6332b02d159658e 100644
118 | --- a/src/main/java/net/minecraft/serversidereplayrecorder/voice/recording/VoicechatRecorder.java
119 | +++ b/src/main/java/net/minecraft/serversidereplayrecorder/voice/recording/VoicechatRecorder.java
120 | @@ -10,6 +10,7 @@ import net.minecraft.network.protocol.game.ClientboundCustomPayloadPacket;
121 | import net.minecraft.server.MinecraftServer;
122 | import net.minecraft.serversidereplayrecorder.ServerSideReplayRecorderServer;
123 | import net.minecraft.serversidereplayrecorder.recorder.ReplayRecorder;
124 | +import net.minecraft.serversidereplayrecorder.voice.ServerSideVoiceChat;
125 | import net.minecraft.serversidereplayrecorder.voice.net.EntitySoundPacket;
126 | import net.minecraft.serversidereplayrecorder.voice.net.LocationalSoundPacket;
127 | import net.minecraft.serversidereplayrecorder.voice.net.Packet;
128 | @@ -19,49 +20,43 @@ import java.util.UUID;
129 |
130 | public class VoicechatRecorder {
131 |
132 | -// private static final Minecraft MC = Minecraft.getInstance();
133 | -
134 | public static void onEntitySound(EntitySoundPacketEvent event) {
135 | - short[] rawAudio = getRawAudio(event, event.getPacket());
136 | - send(new EntitySoundPacket(event.getPacket().getEntityUuid(), rawAudio, event.getPacket().isWhispering(), event.getPacket().getDistance()));
137 | + EntitySoundPacket ssp = (EntitySoundPacket)event.getPacket();
138 | + send(new EntitySoundPacket(event.getPacket().getEntityUuid(), ssp.getRawAudio(), event.getPacket().isWhispering(), event.getPacket().getDistance()));
139 | }
140 |
141 | public static void onLocationalSound(LocationalSoundPacketEvent event) {
142 | - short[] rawAudio = getRawAudio(event, event.getPacket());
143 | - send(new LocationalSoundPacket(event.getPacket().getSender(), rawAudio, event.getPacket().getPosition(), event.getPacket().getDistance()));
144 | + LocationalSoundPacket ssp = (LocationalSoundPacket)event.getPacket();
145 | + send(new LocationalSoundPacket(event.getPacket().getSender(), ssp.getRawAudio(), event.getPacket().getPosition(), event.getPacket().getDistance()));
146 | }
147 |
148 | public static void onStaticSound(StaticSoundPacketEvent event) {
149 | - short[] rawAudio = getRawAudio(event, event.getPacket());
150 | - send(new StaticSoundPacket(event.getPacket().getSender(), rawAudio));
151 | + StaticSoundPacket ssp = (StaticSoundPacket)event.getPacket();
152 | + send(new StaticSoundPacket(event.getPacket().getSender(), ssp.getRawAudio()));
153 | }
154 |
155 | - public static short[] getRawAudio(SoundPacketEvent> event, SoundPacket packet){
156 | - OpusDecoder decoder = event.getVoicechat().createDecoder();
157 | + public static void onSound(MicrophonePacketEvent event) {
158 | + UUID id = event.getSenderConnection().getPlayer().getUuid();
159 |
160 | - byte[] opusData = packet.getOpusEncodedData();
161 | - return decoder.decode(opusData);
162 | - }
163 | + OpusDecoder decoder = ServerSideVoiceChat.decoder;
164 | + byte[] opusData = event.getPacket().getOpusEncodedData();
165 | +
166 | + short[] rawAudio = decoder.decode(opusData);
167 |
168 | -// public static void onSound(ClientSoundEvent event) {
169 | -// UUID id = ClientManager.getPlayerStateManager().getOwnID();
170 | -// short[] rawAudio = event.getRawAudio();
171 | -//
172 | -// if (ReplayVoicechatPlugin.CLIENT_API.getGroup() != null) {
173 | -// send(new StaticSoundPacket(id, rawAudio));
174 | -// } else {
175 | -// send(new EntitySoundPacket(id, rawAudio, event.isWhispering(), (float) ReplayVoicechatPlugin.CLIENT_API.getVoiceChatDistance()));
176 | -// }
177 | -// }
178 | + if (event.getSenderConnection().getGroup() != null) {
179 | + send(new StaticSoundPacket(id, rawAudio));
180 | + } else {
181 | + send(new EntitySoundPacket(id, rawAudio, event.getPacket().isWhispering(), (float) ServerSideVoiceChat.distance));
182 | + }
183 | + }
184 |
185 | public static void send(Packet> packet) {
186 | FriendlyByteBuf buf = new FriendlyByteBuf(Unpooled.buffer());
187 | packet.toBytes(buf);
188 | ClientboundCustomPayloadPacket fakeP = new ClientboundCustomPayloadPacket(packet.getIdentifier(), buf);
189 | for (ReplayRecorder recorder : ReplayRecorder.active_recorders){
190 | - recorder.onPacket(fakeP);
191 | + recorder.save(fakeP);
192 | }
193 | - // ReplayInterface.INSTANCE.sendFakePacket(packet.getIdentifier(), buf);
194 | }
195 |
196 | }
197 |
--------------------------------------------------------------------------------
/patches/server/0023-Improved-Performance-For-Simple-Voice-Chat.patch:
--------------------------------------------------------------------------------
1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
2 | From: Bryan1029384756 <23323626+Bryan1029384756@users.noreply.github.com>
3 | Date: Mon, 26 Jun 2023 20:34:27 -0500
4 | Subject: [PATCH] Improved Performance For Simple Voice Chat
5 |
6 |
7 | diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java
8 | index c3586d6dc0168c0da3d8b229a47118bfc907d2a0..b5b42e16d514e3941aab646fa171c500b72bf20e 100644
9 | --- a/src/main/java/net/minecraft/server/MinecraftServer.java
10 | +++ b/src/main/java/net/minecraft/server/MinecraftServer.java
11 | @@ -922,11 +922,6 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop> playerPacketMap = new HashMap<>();
69 | - private Map lastPacketTimeMap = new HashMap<>();
70 | - private static final int FRAME_SIZE_MS = 20; // Frame size in milliseconds
71 | - private static final int FRAME_SIZE_SAMPLES = 960; // Number of samples in a frame, for 24000 Hz
72 | - private static final byte[] SILENT_FRAME; // A silent frame
73 | -
74 | - static {
75 | - // Initialize the silent frame.
76 | - short[] silentSamples = new short[FRAME_SIZE_SAMPLES];
77 | - SILENT_FRAME = new byte[silentSamples.length * 2];
78 | - ByteBuffer.wrap(SILENT_FRAME).order(ByteOrder.LITTLE_ENDIAN).asShortBuffer().put(silentSamples);
79 | - }
80 | -
81 | -
82 | - public void onSound(MicrophonePacketEvent event) {
83 | - UUID playerUuid = event.getSenderConnection().getPlayer().getUuid();
84 | -
85 | - long now = System.currentTimeMillis();
86 | - long lastPacketTime = lastPacketTimeMap.get(playerUuid);
87 | - if (lastPacketTime != -1) {
88 | - // If it's not the first packet, add silence to fill in the gap, if needed.
89 | - long gapMs = now - lastPacketTime;
90 | - if(gapMs > 500) { // More than 1 second gap
91 | - while (gapMs > FRAME_SIZE_MS) {
92 | - playerPacketMap.get(playerUuid).add(SILENT_FRAME);
93 | - gapMs -= FRAME_SIZE_MS;
94 | - }
95 | - }
96 | - }
97 | - lastPacketTimeMap.put(playerUuid, now);
98 | -
99 | - byte[] opusData = event.getPacket().getOpusEncodedData();
100 | - try {
101 | - short[] pcmShorts = decoder.decode(opusData);
102 | - System.out.println(Arrays.toString(Arrays.copyOf(pcmShorts, 10))); // print first 10 samples
103 | - byte[] pcmBytes = new byte[pcmShorts.length * 2];
104 | - ByteBuffer.wrap(pcmBytes).order(ByteOrder.LITTLE_ENDIAN).asShortBuffer().put(pcmShorts);
105 | - playerPacketMap.get(playerUuid).add(pcmBytes);
106 | - } catch (Exception e) {
107 | - e.printStackTrace();
108 | - }
109 | - }
110 | -
111 | - public void startSound(ServerPlayer player){
112 | - ServerSideReplayRecorderServer.LOGGER.info("Started Voice Recording Player %s".formatted(player.getGameProfile().getName()));
113 | - UUID playerUuid = player.getUUID();
114 | -
115 | - playerPacketMap.put(playerUuid, new ArrayList<>(Collections.singletonList(SILENT_FRAME)));
116 | -
117 | - // Initialize this player's last packet time as current time
118 | - lastPacketTimeMap.put(playerUuid, System.currentTimeMillis());
119 | - }
120 | -
121 | - public void saveToWav(UUID playerUuid, String filePath) {
122 | - String playerName = Bukkit.getOfflinePlayer(playerUuid).getName();
123 | - ServerSideReplayRecorderServer.LOGGER.info("Stopped Voice Recording Player %s".formatted(playerName));
124 | - String fileName = String.format("%s.wav", new SimpleDateFormat("yyyy-MM-dd_HH-mm-ss").format(new Date()));
125 | -
126 | - AudioFormat audioFormat = new AudioFormat(24000, 16, 2, true, false);
127 | - File outputFile = new File(filePath + playerName + File.separator + fileName); // add the player's UUID to the filename
128 | - outputFile.getParentFile().mkdirs();
129 | -
130 | - byte[] combinedData = combinePackets(playerUuid);
131 | -
132 | - long numSampleFrames = combinedData.length / 4; // 16 bits = 2 bytes per sample, 2 channels = 4 bytes per frame
133 | -
134 | - try {
135 | - AudioInputStream audioInputStream = new AudioInputStream(new ByteArrayInputStream(combinedData), audioFormat, numSampleFrames);
136 | - AudioSystem.write(audioInputStream, AudioFileFormat.Type.WAVE, outputFile);
137 | - } catch (IOException e) {
138 | - e.printStackTrace();
139 | - }
140 | - }
141 | -
142 | - public byte[] combinePackets(UUID playerUuid) {
143 | - long now = System.currentTimeMillis();
144 | - long lastPacketTime = lastPacketTimeMap.get(playerUuid);
145 | - if (lastPacketTime != -1) {
146 | - // If it's not the first packet, add silence to fill in the gap, if needed.
147 | - long gapMs = now - lastPacketTime;
148 | - if(gapMs > 500) { // More than 1 second gap
149 | - while (gapMs > FRAME_SIZE_MS) {
150 | - playerPacketMap.get(playerUuid).add(SILENT_FRAME);
151 | - gapMs -= FRAME_SIZE_MS;
152 | - }
153 | - }
154 | - }
155 | -
156 | - List packetList = playerPacketMap.get(playerUuid);
157 | -
158 | - int totalLength = packetList.stream().mapToInt(packet -> packet.length).sum();
159 | - byte[] combinedData = new byte[totalLength];
160 | - int offset = 0;
161 | -
162 | - for (byte[] packet : packetList) {
163 | - System.arraycopy(packet, 0, combinedData, offset, packet.length);
164 | - offset += packet.length;
165 | - }
166 | -
167 | - return combinedData;
168 | - }
169 | }
170 | diff --git a/src/main/java/net/minecraft/serversidereplayrecorder/voice/recording/VoicechatRecorder.java b/src/main/java/net/minecraft/serversidereplayrecorder/voice/recording/VoicechatRecorder.java
171 | index ca56f29556cfd1d6da95b930c6332b02d159658e..16d4d137726c97a170f951c879c1e0387019318a 100644
172 | --- a/src/main/java/net/minecraft/serversidereplayrecorder/voice/recording/VoicechatRecorder.java
173 | +++ b/src/main/java/net/minecraft/serversidereplayrecorder/voice/recording/VoicechatRecorder.java
174 | @@ -1,62 +1,96 @@
175 | package net.minecraft.serversidereplayrecorder.voice.recording;
176 |
177 |
178 | +import de.maxhenkel.voicechat.api.Position;
179 | +import de.maxhenkel.voicechat.api.ServerLevel;
180 | +import de.maxhenkel.voicechat.api.ServerPlayer;
181 | import de.maxhenkel.voicechat.api.events.*;
182 | import de.maxhenkel.voicechat.api.opus.OpusDecoder;
183 | import de.maxhenkel.voicechat.api.packets.SoundPacket;
184 | import io.netty.buffer.Unpooled;
185 | +import net.minecraft.network.Connection;
186 | import net.minecraft.network.FriendlyByteBuf;
187 | import net.minecraft.network.protocol.game.ClientboundCustomPayloadPacket;
188 | import net.minecraft.server.MinecraftServer;
189 | import net.minecraft.serversidereplayrecorder.ServerSideReplayRecorderServer;
190 | +import net.minecraft.serversidereplayrecorder.recorder.PlayerRecorder;
191 | +import net.minecraft.serversidereplayrecorder.recorder.RegionRecorder;
192 | import net.minecraft.serversidereplayrecorder.recorder.ReplayRecorder;
193 | import net.minecraft.serversidereplayrecorder.voice.ServerSideVoiceChat;
194 | import net.minecraft.serversidereplayrecorder.voice.net.EntitySoundPacket;
195 | import net.minecraft.serversidereplayrecorder.voice.net.LocationalSoundPacket;
196 | import net.minecraft.serversidereplayrecorder.voice.net.Packet;
197 | import net.minecraft.serversidereplayrecorder.voice.net.StaticSoundPacket;
198 | +import net.minecraft.world.phys.Vec3;
199 |
200 | +import java.util.Collection;
201 | import java.util.UUID;
202 |
203 | public class VoicechatRecorder {
204 |
205 | - public static void onEntitySound(EntitySoundPacketEvent event) {
206 | - EntitySoundPacket ssp = (EntitySoundPacket)event.getPacket();
207 | - send(new EntitySoundPacket(event.getPacket().getEntityUuid(), ssp.getRawAudio(), event.getPacket().isWhispering(), event.getPacket().getDistance()));
208 | - }
209 | + public static void onSound(MicrophonePacketEvent event) {
210 | + ServerPlayer player = event.getSenderConnection().getPlayer();
211 | + ServerLevel level = player.getServerLevel();
212 | + Position position = player.getPosition();
213 | + UUID id = player.getUuid();
214 | + Packet> packet = createPacket(event, id);
215 |
216 | - public static void onLocationalSound(LocationalSoundPacketEvent event) {
217 | - LocationalSoundPacket ssp = (LocationalSoundPacket)event.getPacket();
218 | - send(new LocationalSoundPacket(event.getPacket().getSender(), ssp.getRawAudio(), event.getPacket().getPosition(), event.getPacket().getDistance()));
219 | - }
220 | + Collection playersInRange = event.getVoicechat().getPlayersInRange(
221 | + level,
222 | + position,
223 | + ServerSideReplayRecorderServer.server.getPlayerList().getViewDistance() * 16
224 | + );
225 |
226 | - public static void onStaticSound(StaticSoundPacketEvent event) {
227 | - StaticSoundPacket ssp = (StaticSoundPacket)event.getPacket();
228 | - send(new StaticSoundPacket(event.getPacket().getSender(), ssp.getRawAudio()));
229 | + sendNearbyPlayerPacket(playersInRange, packet);
230 | + //sendRegionPacket(position, packet);
231 | }
232 |
233 | - public static void onSound(MicrophonePacketEvent event) {
234 | - UUID id = event.getSenderConnection().getPlayer().getUuid();
235 | -
236 | + private static Packet> createPacket(MicrophonePacketEvent event, UUID id) {
237 | OpusDecoder decoder = ServerSideVoiceChat.decoder;
238 | byte[] opusData = event.getPacket().getOpusEncodedData();
239 | -
240 | short[] rawAudio = decoder.decode(opusData);
241 |
242 | if (event.getSenderConnection().getGroup() != null) {
243 | - send(new StaticSoundPacket(id, rawAudio));
244 | + return new StaticSoundPacket(id, rawAudio);
245 | } else {
246 | - send(new EntitySoundPacket(id, rawAudio, event.getPacket().isWhispering(), (float) ServerSideVoiceChat.distance));
247 | + return new EntitySoundPacket(id, rawAudio, event.getPacket().isWhispering(), (float) ServerSideVoiceChat.distance);
248 | }
249 | }
250 |
251 | - public static void send(Packet> packet) {
252 | + private static void sendNearbyPlayerPacket(Collection playersInRange, Packet> packet) {
253 | + playersInRange.forEach(player -> {
254 | + Connection connection = MinecraftServer.getServer().getPlayerList().getPlayer(player.getUuid()).connection.connection;
255 | + PlayerRecorder recorder = getPlayerRecorder(connection);
256 | + if (recorder != null) {
257 | + sendPlayerPacket(recorder, packet);
258 | + }
259 | + });
260 | + }
261 | +
262 | + public static PlayerRecorder getPlayerRecorder(Connection connection){
263 | + return PlayerRecorder.playerRecorderMap.get(connection);
264 | + }
265 | +
266 | + public static void sendPlayerPacket(PlayerRecorder recorder, Packet> packet) {
267 | + ClientboundCustomPayloadPacket fakePacket = createCustomPacket(packet);
268 | + recorder.onPacket(fakePacket);
269 | + }
270 | +
271 | + public static void sendRegionPacket(Position pos, Packet> packet) {
272 | + Vec3 playerPos = new Vec3(pos.getX(), pos.getY(), pos.getZ());
273 | + ClientboundCustomPayloadPacket fakePacket = createCustomPacket(packet);
274 | +
275 | + for(RegionRecorder recorder : RegionRecorder.regionRecorderMap.values()){
276 | + if(recorder.region.isInBox(playerPos)){
277 | + recorder.onPacket(fakePacket);
278 | + }
279 | + }
280 | + }
281 | +
282 | + private static ClientboundCustomPayloadPacket createCustomPacket(Packet> packet) {
283 | FriendlyByteBuf buf = new FriendlyByteBuf(Unpooled.buffer());
284 | packet.toBytes(buf);
285 | - ClientboundCustomPayloadPacket fakeP = new ClientboundCustomPayloadPacket(packet.getIdentifier(), buf);
286 | - for (ReplayRecorder recorder : ReplayRecorder.active_recorders){
287 | - recorder.save(fakeP);
288 | - }
289 | + return new ClientboundCustomPayloadPacket(packet.getIdentifier(), buf);
290 | }
291 |
292 | }
293 |
--------------------------------------------------------------------------------
/patches/server/0024-Improved-Performance-For-Simple-Voice-Chat.patch:
--------------------------------------------------------------------------------
1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
2 | From: Bryan1029384756 <23323626+Bryan1029384756@users.noreply.github.com>
3 | Date: Mon, 26 Jun 2023 20:35:55 -0500
4 | Subject: [PATCH] Improved Performance For Simple Voice Chat
5 |
6 |
7 | diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java
8 | index e5e474a68e7b5c8f18724f3455a24ae3a8049440..ddc0f9e5ddcd91cfe4f54c62ebb7a9b4d2bc01ab 100644
9 | --- a/src/main/java/net/minecraft/server/players/PlayerList.java
10 | +++ b/src/main/java/net/minecraft/server/players/PlayerList.java
11 | @@ -182,7 +182,6 @@ public abstract class PlayerList {
12 |
13 | this.getPlayers().stream().filter(p -> this.isOp(p.getGameProfile())).forEach( p -> p.displayClientMessage(Component.literal("Started Recording Player %s".formatted(player.getGameProfile().getName())), false));
14 |
15 | - voiceChat.startSound(player);
16 | PlayerRecorder recorder = new PlayerRecorder(connection);
17 | PlayerRecorder.playerRecorderMap.put(connection, recorder);
18 | recorder.onPacket(new ClientboundGameProfilePacket(player.getGameProfile()));
19 |
--------------------------------------------------------------------------------
/patches/server/0025-Support-Region-Voice-Recording.patch:
--------------------------------------------------------------------------------
1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
2 | From: Bryan1029384756 <23323626+Bryan1029384756@users.noreply.github.com>
3 | Date: Fri, 30 Jun 2023 20:41:08 -0500
4 | Subject: [PATCH] Support Region Voice Recording
5 |
6 |
7 | diff --git a/build.gradle.kts b/build.gradle.kts
8 | index f3b7534eef9fb551146b380e2ba62b1d8ea53aac..27b86c89e8ee3a3b503eef0f71fd9c39132d3f89 100644
9 | --- a/build.gradle.kts
10 | +++ b/build.gradle.kts
11 | @@ -37,7 +37,8 @@ dependencies {
12 | implementation("net.fabricmc:mapping-io:0.3.0") // Paper - needed to read mappings for stacktrace deobfuscation
13 | implementation("com.fasterxml.jackson.core:jackson-annotations:2.15.2") //ServersideRecording
14 | implementation("com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:2.15.2") //ServersideRecording
15 | - implementation("de.maxhenkel.voicechat:voicechat-api:2.4.11") //ServersideRecording
16 | + implementation ("de.maxhenkel.voicechat:voicechat-api:2.4.0") //ServersideRecording
17 | + implementation ("maven.modrinth:simple-voice-chat:fabric-1.20.1-2.4.11") //ServersideRecording
18 | runtimeOnly("org.xerial:sqlite-jdbc:3.42.0.0")
19 | runtimeOnly("com.mysql:mysql-connector-j:8.0.33")
20 | runtimeOnly("com.lmax:disruptor:3.4.4") // Paper
21 | diff --git a/src/main/java/net/minecraft/serversidereplayrecorder/config/MainConfig.java b/src/main/java/net/minecraft/serversidereplayrecorder/config/MainConfig.java
22 | index 8e2d0ec530e408e572d1f0af38f6206e1fa94af7..788bd8f92f91a330b70f497c8f2dc93dc1864140 100644
23 | --- a/src/main/java/net/minecraft/serversidereplayrecorder/config/MainConfig.java
24 | +++ b/src/main/java/net/minecraft/serversidereplayrecorder/config/MainConfig.java
25 | @@ -22,6 +22,8 @@ public class MainConfig {
26 | private boolean assume_unloaded_chunks_dont_change = true;
27 | private boolean render_distance_fog_fix = false;
28 | private long max_file_size = 10000000000L;
29 | + private int voice_recording_range = 48;
30 | + private boolean voice_recording_enabled = false;
31 | private URL file_storage_url;
32 | private boolean debug = false;
33 |
34 | @@ -48,6 +50,22 @@ public class MainConfig {
35 | this.debug = debug;
36 | }
37 |
38 | + public int getVoice_recording_range() {
39 | + return voice_recording_range;
40 | + }
41 | +
42 | + public void setVoice_recording_range(int voice_recording_range) {
43 | + this.voice_recording_range = voice_recording_range;
44 | + }
45 | +
46 | + public boolean isVoice_recording_enabled() {
47 | + return voice_recording_enabled;
48 | + }
49 | +
50 | + public void setVoice_recording_enabled(boolean voice_recording_enabled) {
51 | + this.voice_recording_enabled = voice_recording_enabled;
52 | + }
53 | +
54 | public long getMax_file_size() {
55 |
56 | return max_file_size;
57 | @@ -142,3 +160,4 @@ public class MainConfig {
58 | this.render_distance_fog_fix = render_distance_fog_fix;
59 | }
60 | }
61 | +
62 | diff --git a/src/main/java/net/minecraft/serversidereplayrecorder/recorder/RegionRecorder.java b/src/main/java/net/minecraft/serversidereplayrecorder/recorder/RegionRecorder.java
63 | index ffdbd36015553ca8d15d55803c945f8949f234f0..7312a60b1af9c66efa60a42e81256ee700c7623f 100644
64 | --- a/src/main/java/net/minecraft/serversidereplayrecorder/recorder/RegionRecorder.java
65 | +++ b/src/main/java/net/minecraft/serversidereplayrecorder/recorder/RegionRecorder.java
66 | @@ -1,6 +1,7 @@
67 | package net.minecraft.serversidereplayrecorder.recorder;
68 |
69 | import com.mojang.authlib.GameProfile;
70 | +import de.maxhenkel.voicechat.Voicechat;
71 | import io.netty.buffer.Unpooled;
72 | import net.minecraft.core.BlockPos;
73 | import net.minecraft.core.NonNullList;
74 | @@ -11,12 +12,15 @@ import net.minecraft.network.protocol.Packet;
75 | import net.minecraft.network.protocol.game.*;
76 | import net.minecraft.network.protocol.login.ClientboundGameProfilePacket;
77 | import net.minecraft.server.level.ServerLevel;
78 | +import net.minecraft.server.level.ServerPlayer;
79 | import net.minecraft.serversidereplayrecorder.ServerSideReplayRecorderServer;
80 | import net.minecraft.serversidereplayrecorder.util.ChunkBox;
81 | import net.minecraft.serversidereplayrecorder.util.WrappedPacket;
82 | import net.minecraft.serversidereplayrecorder.util.interfaces.LightUpdatePacketAccessor;
83 | import net.minecraft.serversidereplayrecorder.util.interfaces.RegionRecorderStorage;
84 | import net.minecraft.serversidereplayrecorder.util.interfaces.RegionRecorderWorld;
85 | +import net.minecraft.serversidereplayrecorder.voice.Utils;
86 | +import net.minecraft.serversidereplayrecorder.voice.net.SecretPacket;
87 | import net.minecraft.tags.TagNetworkSerialization;
88 | import net.minecraft.world.entity.player.Abilities;
89 | import net.minecraft.world.flag.FeatureFlags;
90 | @@ -214,6 +218,10 @@ public class RegionRecorder extends ReplayRecorder {
91 | //set the replay viewpoint to the center of the watched region
92 | onPacket(new ClientboundPlayerPositionPacket(viewpoint.getX() + 0.5d,viewpoint.getY(),viewpoint.getZ() + 0.5d,0f,0f, Collections.emptySet(),0));
93 | //ready to record changes
94 | + if(ServerSideReplayRecorderServer.config.isVoice_recording_enabled()){
95 | + ServerPlayer player = new ServerPlayer(ms, ms.overworld(), FAKE_GAMEPROFILE);
96 | + onPacket(Utils.createCustomPacket(new SecretPacket(player, UUID.randomUUID() , Voicechat.SERVER.getServer().getPort(), Voicechat.SERVER_CONFIG)));
97 | + }
98 | }
99 |
100 | @Override
101 | diff --git a/src/main/java/net/minecraft/serversidereplayrecorder/voice/ServerSideVoiceChat.java b/src/main/java/net/minecraft/serversidereplayrecorder/voice/ServerSideVoiceChat.java
102 | index 3e84ce236b33963bd1bd6ac26f73885d9a9a9864..2afbfcb15a30988f3acb92af798819fa231b3022 100644
103 | --- a/src/main/java/net/minecraft/serversidereplayrecorder/voice/ServerSideVoiceChat.java
104 | +++ b/src/main/java/net/minecraft/serversidereplayrecorder/voice/ServerSideVoiceChat.java
105 | @@ -4,6 +4,7 @@ import de.maxhenkel.voicechat.api.VoicechatApi;
106 | import de.maxhenkel.voicechat.api.VoicechatPlugin;
107 | import de.maxhenkel.voicechat.api.events.*;
108 | import de.maxhenkel.voicechat.api.opus.OpusDecoder;
109 | +import net.minecraft.serversidereplayrecorder.ServerSideReplayRecorderServer;
110 | import net.minecraft.serversidereplayrecorder.voice.recording.VoicechatRecorder;
111 | public class ServerSideVoiceChat implements VoicechatPlugin {
112 |
113 | @@ -17,6 +18,7 @@ public class ServerSideVoiceChat implements VoicechatPlugin {
114 |
115 | @Override
116 | public void initialize(VoicechatApi api) {
117 | + if(!ServerSideReplayRecorderServer.config.isVoice_recording_enabled()) return;
118 | if (decoder == null) {
119 | decoder = api.createDecoder();
120 | }
121 | @@ -27,6 +29,7 @@ public class ServerSideVoiceChat implements VoicechatPlugin {
122 |
123 | @Override
124 | public void registerEvents(EventRegistration registration) {
125 | + if(!ServerSideReplayRecorderServer.config.isVoice_recording_enabled()) return;
126 | registration.registerEvent(MicrophonePacketEvent.class, VoicechatRecorder::onSound);
127 | }
128 |
129 | diff --git a/src/main/java/net/minecraft/serversidereplayrecorder/voice/Utils.java b/src/main/java/net/minecraft/serversidereplayrecorder/voice/Utils.java
130 | index 36132fcf9b14c52b9e81929172fea8277b28fbc8..99213f8a949ff5f145185c84e87766172b4cacd5 100644
131 | --- a/src/main/java/net/minecraft/serversidereplayrecorder/voice/Utils.java
132 | +++ b/src/main/java/net/minecraft/serversidereplayrecorder/voice/Utils.java
133 | @@ -1,5 +1,10 @@
134 | package net.minecraft.serversidereplayrecorder.voice;
135 |
136 | +import io.netty.buffer.Unpooled;
137 | +import net.minecraft.network.FriendlyByteBuf;
138 | +import net.minecraft.network.protocol.game.ClientboundCustomPayloadPacket;
139 | +import net.minecraft.serversidereplayrecorder.voice.net.Packet;
140 | +
141 | public class Utils {
142 |
143 | public static short[] bytesToShorts(byte[] bytes) {
144 | @@ -31,4 +36,10 @@ public class Utils {
145 | return new byte[]{(byte) (s & 0xFF), (byte) ((s >> 8) & 0xFF)};
146 | }
147 |
148 | + public static ClientboundCustomPayloadPacket createCustomPacket(Packet> packet) {
149 | + FriendlyByteBuf buf = new FriendlyByteBuf(Unpooled.buffer());
150 | + packet.toBytes(buf);
151 | + return new ClientboundCustomPayloadPacket(packet.getIdentifier(), buf);
152 | + }
153 | +
154 | }
155 | diff --git a/src/main/java/net/minecraft/serversidereplayrecorder/voice/net/SecretPacket.java b/src/main/java/net/minecraft/serversidereplayrecorder/voice/net/SecretPacket.java
156 | new file mode 100644
157 | index 0000000000000000000000000000000000000000..c24e8021e76582210caa9a64ce4d5c8cb92b4f92
158 | --- /dev/null
159 | +++ b/src/main/java/net/minecraft/serversidereplayrecorder/voice/net/SecretPacket.java
160 | @@ -0,0 +1,109 @@
161 | +package net.minecraft.serversidereplayrecorder.voice.net;
162 | +
163 | +import net.minecraft.network.FriendlyByteBuf;
164 | +import net.minecraft.resources.ResourceLocation;
165 | +import net.minecraft.server.level.ServerPlayer;
166 | +import de.maxhenkel.voicechat.config.ServerConfig;
167 | +import de.maxhenkel.voicechat.plugins.PluginManager;
168 | +import java.util.UUID;
169 | +
170 | +public class SecretPacket implements Packet {
171 | + public static final ResourceLocation SECRET = new ResourceLocation("voicechat", "secret");
172 | + private UUID secret;
173 | + private int serverPort;
174 | + private UUID playerUUID;
175 | + private ServerConfig.Codec codec;
176 | + private int mtuSize;
177 | + private double voiceChatDistance;
178 | + private int keepAlive;
179 | + private boolean groupsEnabled;
180 | + private String voiceHost;
181 | + private boolean allowRecording;
182 | +
183 | + public SecretPacket() {
184 | + }
185 | +
186 | + public SecretPacket(ServerPlayer player, UUID secret, int port, ServerConfig serverConfig) {
187 | + this.secret = secret;
188 | + this.serverPort = port;
189 | + this.playerUUID = player.getUUID();
190 | + this.codec = (ServerConfig.Codec)serverConfig.voiceChatCodec.get();
191 | + this.mtuSize = (Integer)serverConfig.voiceChatMtuSize.get();
192 | + this.voiceChatDistance = (Double)serverConfig.voiceChatDistance.get();
193 | + this.keepAlive = (Integer)serverConfig.keepAlive.get();
194 | + this.groupsEnabled = (Boolean)serverConfig.groupsEnabled.get();
195 | + this.voiceHost = PluginManager.instance().getVoiceHost((String)serverConfig.voiceHost.get());
196 | + this.allowRecording = (Boolean)serverConfig.allowRecording.get();
197 | + }
198 | +
199 | + public UUID getSecret() {
200 | + return this.secret;
201 | + }
202 | +
203 | + public int getServerPort() {
204 | + return this.serverPort;
205 | + }
206 | +
207 | + public UUID getPlayerUUID() {
208 | + return this.playerUUID;
209 | + }
210 | +
211 | + public ServerConfig.Codec getCodec() {
212 | + return this.codec;
213 | + }
214 | +
215 | + public int getMtuSize() {
216 | + return this.mtuSize;
217 | + }
218 | +
219 | + public double getVoiceChatDistance() {
220 | + return this.voiceChatDistance;
221 | + }
222 | +
223 | + public int getKeepAlive() {
224 | + return this.keepAlive;
225 | + }
226 | +
227 | + public boolean groupsEnabled() {
228 | + return this.groupsEnabled;
229 | + }
230 | +
231 | + public String getVoiceHost() {
232 | + return this.voiceHost;
233 | + }
234 | +
235 | + public ResourceLocation getIdentifier() {
236 | + return SECRET;
237 | + }
238 | +
239 | + public boolean allowRecording() {
240 | + return this.allowRecording;
241 | + }
242 | +
243 | + public SecretPacket fromBytes(FriendlyByteBuf buf) {
244 | + this.secret = buf.readUUID();
245 | + this.serverPort = buf.readInt();
246 | + this.playerUUID = buf.readUUID();
247 | + this.codec = ServerConfig.Codec.values()[buf.readByte()];
248 | + this.mtuSize = buf.readInt();
249 | + this.voiceChatDistance = buf.readDouble();
250 | + this.keepAlive = buf.readInt();
251 | + this.groupsEnabled = buf.readBoolean();
252 | + this.voiceHost = buf.readUtf(32767);
253 | + this.allowRecording = buf.readBoolean();
254 | + return this;
255 | + }
256 | +
257 | + public void toBytes(FriendlyByteBuf buf) {
258 | + buf.writeUUID(this.secret);
259 | + buf.writeInt(this.serverPort);
260 | + buf.writeUUID(this.playerUUID);
261 | + buf.writeByte(this.codec.ordinal());
262 | + buf.writeInt(this.mtuSize);
263 | + buf.writeDouble(this.voiceChatDistance);
264 | + buf.writeInt(this.keepAlive);
265 | + buf.writeBoolean(this.groupsEnabled);
266 | + buf.writeUtf(this.voiceHost);
267 | + buf.writeBoolean(this.allowRecording);
268 | + }
269 | +}
270 | diff --git a/src/main/java/net/minecraft/serversidereplayrecorder/voice/recording/VoicechatRecorder.java b/src/main/java/net/minecraft/serversidereplayrecorder/voice/recording/VoicechatRecorder.java
271 | index 16d4d137726c97a170f951c879c1e0387019318a..7d29883f7c63747caaa6ce5eb92ccdac3f93f23a 100644
272 | --- a/src/main/java/net/minecraft/serversidereplayrecorder/voice/recording/VoicechatRecorder.java
273 | +++ b/src/main/java/net/minecraft/serversidereplayrecorder/voice/recording/VoicechatRecorder.java
274 | @@ -17,6 +17,7 @@ import net.minecraft.serversidereplayrecorder.recorder.PlayerRecorder;
275 | import net.minecraft.serversidereplayrecorder.recorder.RegionRecorder;
276 | import net.minecraft.serversidereplayrecorder.recorder.ReplayRecorder;
277 | import net.minecraft.serversidereplayrecorder.voice.ServerSideVoiceChat;
278 | +import net.minecraft.serversidereplayrecorder.voice.Utils;
279 | import net.minecraft.serversidereplayrecorder.voice.net.EntitySoundPacket;
280 | import net.minecraft.serversidereplayrecorder.voice.net.LocationalSoundPacket;
281 | import net.minecraft.serversidereplayrecorder.voice.net.Packet;
282 | @@ -38,11 +39,11 @@ public class VoicechatRecorder {
283 | Collection playersInRange = event.getVoicechat().getPlayersInRange(
284 | level,
285 | position,
286 | - ServerSideReplayRecorderServer.server.getPlayerList().getViewDistance() * 16
287 | + ServerSideReplayRecorderServer.config.getVoice_recording_range()
288 | );
289 |
290 | sendNearbyPlayerPacket(playersInRange, packet);
291 | - //sendRegionPacket(position, packet);
292 | + sendRegionPacket(position, packet);
293 | }
294 |
295 | private static Packet> createPacket(MicrophonePacketEvent event, UUID id) {
296 | @@ -72,13 +73,13 @@ public class VoicechatRecorder {
297 | }
298 |
299 | public static void sendPlayerPacket(PlayerRecorder recorder, Packet> packet) {
300 | - ClientboundCustomPayloadPacket fakePacket = createCustomPacket(packet);
301 | + ClientboundCustomPayloadPacket fakePacket = Utils.createCustomPacket(packet);
302 | recorder.onPacket(fakePacket);
303 | }
304 |
305 | public static void sendRegionPacket(Position pos, Packet> packet) {
306 | Vec3 playerPos = new Vec3(pos.getX(), pos.getY(), pos.getZ());
307 | - ClientboundCustomPayloadPacket fakePacket = createCustomPacket(packet);
308 | + ClientboundCustomPayloadPacket fakePacket = Utils.createCustomPacket(packet);
309 |
310 | for(RegionRecorder recorder : RegionRecorder.regionRecorderMap.values()){
311 | if(recorder.region.isInBox(playerPos)){
312 | @@ -87,10 +88,6 @@ public class VoicechatRecorder {
313 | }
314 | }
315 |
316 | - private static ClientboundCustomPayloadPacket createCustomPacket(Packet> packet) {
317 | - FriendlyByteBuf buf = new FriendlyByteBuf(Unpooled.buffer());
318 | - packet.toBytes(buf);
319 | - return new ClientboundCustomPayloadPacket(packet.getIdentifier(), buf);
320 | - }
321 | +
322 |
323 | }
324 |
--------------------------------------------------------------------------------
/patches/server/0026-Support-Region-Voice-Recording.patch:
--------------------------------------------------------------------------------
1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
2 | From: Bryan1029384756 <23323626+Bryan1029384756@users.noreply.github.com>
3 | Date: Fri, 30 Jun 2023 20:59:49 -0500
4 | Subject: [PATCH] Support Region Voice Recording
5 |
6 |
7 | diff --git a/build.gradle.kts b/build.gradle.kts
8 | index 27b86c89e8ee3a3b503eef0f71fd9c39132d3f89..eb8e2148a7fef15ef5870ce5ec31393810043128 100644
9 | --- a/build.gradle.kts
10 | +++ b/build.gradle.kts
11 | @@ -38,7 +38,7 @@ dependencies {
12 | implementation("com.fasterxml.jackson.core:jackson-annotations:2.15.2") //ServersideRecording
13 | implementation("com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:2.15.2") //ServersideRecording
14 | implementation ("de.maxhenkel.voicechat:voicechat-api:2.4.0") //ServersideRecording
15 | - implementation ("maven.modrinth:simple-voice-chat:fabric-1.20.1-2.4.11") //ServersideRecording
16 | + implementation ("maven.modrinth:simple-voice-chat:bukkit-2.4.11") //ServersideRecording
17 | runtimeOnly("org.xerial:sqlite-jdbc:3.42.0.0")
18 | runtimeOnly("com.mysql:mysql-connector-j:8.0.33")
19 | runtimeOnly("com.lmax:disruptor:3.4.4") // Paper
20 | diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java
21 | index b5b42e16d514e3941aab646fa171c500b72bf20e..ddd53d0fd3da2b2ba1b9013b459bc398f0354870 100644
22 | --- a/src/main/java/net/minecraft/server/MinecraftServer.java
23 | +++ b/src/main/java/net/minecraft/server/MinecraftServer.java
24 | @@ -304,7 +304,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop S spin(Function serverFactory) {
32 | AtomicReference atomicreference = new AtomicReference();
33 | @@ -632,7 +632,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop
3 | Date: Fri, 30 Jun 2023 21:02:21 -0500
4 | Subject: [PATCH] Support Region Voice Recording
5 |
6 |
7 | diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java
8 | index ddc0f9e5ddcd91cfe4f54c62ebb7a9b4d2bc01ab..e1ba10c920d8deb0c68c2cd87a1e9a8c772ab4a0 100644
9 | --- a/src/main/java/net/minecraft/server/players/PlayerList.java
10 | +++ b/src/main/java/net/minecraft/server/players/PlayerList.java
11 | @@ -148,13 +148,11 @@ public abstract class PlayerList {
12 | private CraftServer cserver;
13 | private final Map playersByName = new java.util.HashMap<>();
14 | public @Nullable String collideRuleTeamName; // Paper - Team name used for collideRule
15 | - public ServerSideVoiceChat voiceChat;
16 |
17 | public PlayerList(MinecraftServer server, LayeredRegistryAccess registryManager, PlayerDataStorage saveHandler, int maxPlayers) {
18 | this.cserver = server.server = new CraftServer((DedicatedServer) server, this);
19 | server.console = new com.destroystokyo.paper.console.TerminalConsoleCommandSender(); // Paper
20 | // CraftBukkit end
21 | - this.voiceChat = server.voiceChat;
22 | this.bans = new UserBanList(PlayerList.USERBANLIST_FILE);
23 | this.ipBans = new IpBanList(PlayerList.IPBANLIST_FILE);
24 | this.ops = new ServerOpList(PlayerList.OPLIST_FILE);
25 |
--------------------------------------------------------------------------------
/patches/server/0028-Support-Region-Voice-Recording.patch:
--------------------------------------------------------------------------------
1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
2 | From: Bryan1029384756 <23323626+Bryan1029384756@users.noreply.github.com>
3 | Date: Fri, 30 Jun 2023 21:13:48 -0500
4 | Subject: [PATCH] Support Region Voice Recording
5 |
6 |
7 | diff --git a/src/main/java/net/minecraft/serversidereplayrecorder/recorder/RegionRecorder.java b/src/main/java/net/minecraft/serversidereplayrecorder/recorder/RegionRecorder.java
8 | index 7312a60b1af9c66efa60a42e81256ee700c7623f..588d1ee83912b401ee7e1ec1fb867b3bce6b11a2 100644
9 | --- a/src/main/java/net/minecraft/serversidereplayrecorder/recorder/RegionRecorder.java
10 | +++ b/src/main/java/net/minecraft/serversidereplayrecorder/recorder/RegionRecorder.java
11 | @@ -1,7 +1,6 @@
12 | package net.minecraft.serversidereplayrecorder.recorder;
13 |
14 | import com.mojang.authlib.GameProfile;
15 | -import de.maxhenkel.voicechat.Voicechat;
16 | import io.netty.buffer.Unpooled;
17 | import net.minecraft.core.BlockPos;
18 | import net.minecraft.core.NonNullList;
19 | @@ -35,6 +34,10 @@ import net.minecraft.world.level.chunk.ImposterProtoChunk;
20 | import net.minecraft.world.level.chunk.LevelChunk;
21 | import net.minecraft.world.level.levelgen.Heightmap;
22 | import net.minecraft.world.level.storage.LevelData;
23 | +import org.bukkit.Bukkit;
24 | +import org.bukkit.plugin.Plugin;
25 | +import org.bukkit.plugin.java.JavaPlugin;
26 | +
27 | import java.io.File;
28 | import java.io.IOException;
29 | import java.nio.file.Paths;
30 | @@ -219,8 +222,12 @@ public class RegionRecorder extends ReplayRecorder {
31 | onPacket(new ClientboundPlayerPositionPacket(viewpoint.getX() + 0.5d,viewpoint.getY(),viewpoint.getZ() + 0.5d,0f,0f, Collections.emptySet(),0));
32 | //ready to record changes
33 | if(ServerSideReplayRecorderServer.config.isVoice_recording_enabled()){
34 | - ServerPlayer player = new ServerPlayer(ms, ms.overworld(), FAKE_GAMEPROFILE);
35 | - onPacket(Utils.createCustomPacket(new SecretPacket(player, UUID.randomUUID() , Voicechat.SERVER.getServer().getPort(), Voicechat.SERVER_CONFIG)));
36 | + if (Bukkit.getServer().getPluginManager().isPluginEnabled("voicechat")) {
37 | + de.maxhenkel.voicechat.Voicechat vc = (de.maxhenkel.voicechat.Voicechat) Bukkit.getServer().getPluginManager().getPlugin("voicechat");
38 | + ServerPlayer player = new ServerPlayer(ms, ms.overworld(), FAKE_GAMEPROFILE);
39 | + onPacket(Utils.createCustomPacket(new SecretPacket(player, UUID.randomUUID() , vc.SERVER.getServer().getPort(), vc.SERVER_CONFIG)));
40 | + }
41 | +
42 | }
43 | }
44 |
45 |
--------------------------------------------------------------------------------
/patches/server/0029-Support-Region-Voice-Recording.patch:
--------------------------------------------------------------------------------
1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
2 | From: Bryan1029384756 <23323626+Bryan1029384756@users.noreply.github.com>
3 | Date: Fri, 30 Jun 2023 21:26:04 -0500
4 | Subject: [PATCH] Support Region Voice Recording
5 |
6 |
7 | diff --git a/build.gradle.kts b/build.gradle.kts
8 | index eb8e2148a7fef15ef5870ce5ec31393810043128..61f0b30f2bcf2c6a32054e16d10179fcd0a52950 100644
9 | --- a/build.gradle.kts
10 | +++ b/build.gradle.kts
11 | @@ -38,7 +38,7 @@ dependencies {
12 | implementation("com.fasterxml.jackson.core:jackson-annotations:2.15.2") //ServersideRecording
13 | implementation("com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:2.15.2") //ServersideRecording
14 | implementation ("de.maxhenkel.voicechat:voicechat-api:2.4.0") //ServersideRecording
15 | - implementation ("maven.modrinth:simple-voice-chat:bukkit-2.4.11") //ServersideRecording
16 | + compileOnly ("maven.modrinth:simple-voice-chat:bukkit-2.4.11") //ServersideRecording
17 | runtimeOnly("org.xerial:sqlite-jdbc:3.42.0.0")
18 | runtimeOnly("com.mysql:mysql-connector-j:8.0.33")
19 | runtimeOnly("com.lmax:disruptor:3.4.4") // Paper
20 |
--------------------------------------------------------------------------------
/patches/server/0030-Support-Region-Voice-Recording.patch:
--------------------------------------------------------------------------------
1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
2 | From: Bryan1029384756 <23323626+Bryan1029384756@users.noreply.github.com>
3 | Date: Fri, 30 Jun 2023 21:35:45 -0500
4 | Subject: [PATCH] Support Region Voice Recording
5 |
6 |
7 | diff --git a/build.gradle.kts b/build.gradle.kts
8 | index 61f0b30f2bcf2c6a32054e16d10179fcd0a52950..27b86c89e8ee3a3b503eef0f71fd9c39132d3f89 100644
9 | --- a/build.gradle.kts
10 | +++ b/build.gradle.kts
11 | @@ -38,7 +38,7 @@ dependencies {
12 | implementation("com.fasterxml.jackson.core:jackson-annotations:2.15.2") //ServersideRecording
13 | implementation("com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:2.15.2") //ServersideRecording
14 | implementation ("de.maxhenkel.voicechat:voicechat-api:2.4.0") //ServersideRecording
15 | - compileOnly ("maven.modrinth:simple-voice-chat:bukkit-2.4.11") //ServersideRecording
16 | + implementation ("maven.modrinth:simple-voice-chat:fabric-1.20.1-2.4.11") //ServersideRecording
17 | runtimeOnly("org.xerial:sqlite-jdbc:3.42.0.0")
18 | runtimeOnly("com.mysql:mysql-connector-j:8.0.33")
19 | runtimeOnly("com.lmax:disruptor:3.4.4") // Paper
20 | diff --git a/src/main/java/net/minecraft/serversidereplayrecorder/recorder/RegionRecorder.java b/src/main/java/net/minecraft/serversidereplayrecorder/recorder/RegionRecorder.java
21 | index 588d1ee83912b401ee7e1ec1fb867b3bce6b11a2..7312a60b1af9c66efa60a42e81256ee700c7623f 100644
22 | --- a/src/main/java/net/minecraft/serversidereplayrecorder/recorder/RegionRecorder.java
23 | +++ b/src/main/java/net/minecraft/serversidereplayrecorder/recorder/RegionRecorder.java
24 | @@ -1,6 +1,7 @@
25 | package net.minecraft.serversidereplayrecorder.recorder;
26 |
27 | import com.mojang.authlib.GameProfile;
28 | +import de.maxhenkel.voicechat.Voicechat;
29 | import io.netty.buffer.Unpooled;
30 | import net.minecraft.core.BlockPos;
31 | import net.minecraft.core.NonNullList;
32 | @@ -34,10 +35,6 @@ import net.minecraft.world.level.chunk.ImposterProtoChunk;
33 | import net.minecraft.world.level.chunk.LevelChunk;
34 | import net.minecraft.world.level.levelgen.Heightmap;
35 | import net.minecraft.world.level.storage.LevelData;
36 | -import org.bukkit.Bukkit;
37 | -import org.bukkit.plugin.Plugin;
38 | -import org.bukkit.plugin.java.JavaPlugin;
39 | -
40 | import java.io.File;
41 | import java.io.IOException;
42 | import java.nio.file.Paths;
43 | @@ -222,12 +219,8 @@ public class RegionRecorder extends ReplayRecorder {
44 | onPacket(new ClientboundPlayerPositionPacket(viewpoint.getX() + 0.5d,viewpoint.getY(),viewpoint.getZ() + 0.5d,0f,0f, Collections.emptySet(),0));
45 | //ready to record changes
46 | if(ServerSideReplayRecorderServer.config.isVoice_recording_enabled()){
47 | - if (Bukkit.getServer().getPluginManager().isPluginEnabled("voicechat")) {
48 | - de.maxhenkel.voicechat.Voicechat vc = (de.maxhenkel.voicechat.Voicechat) Bukkit.getServer().getPluginManager().getPlugin("voicechat");
49 | - ServerPlayer player = new ServerPlayer(ms, ms.overworld(), FAKE_GAMEPROFILE);
50 | - onPacket(Utils.createCustomPacket(new SecretPacket(player, UUID.randomUUID() , vc.SERVER.getServer().getPort(), vc.SERVER_CONFIG)));
51 | - }
52 | -
53 | + ServerPlayer player = new ServerPlayer(ms, ms.overworld(), FAKE_GAMEPROFILE);
54 | + onPacket(Utils.createCustomPacket(new SecretPacket(player, UUID.randomUUID() , Voicechat.SERVER.getServer().getPort(), Voicechat.SERVER_CONFIG)));
55 | }
56 | }
57 |
58 |
--------------------------------------------------------------------------------
/patches/server/0031-Support-Region-Voice-Recording.patch:
--------------------------------------------------------------------------------
1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
2 | From: Bryan1029384756 <23323626+Bryan1029384756@users.noreply.github.com>
3 | Date: Sat, 1 Jul 2023 16:18:28 -0500
4 | Subject: [PATCH] Support Region Voice Recording
5 |
6 |
7 | diff --git a/build.gradle.kts b/build.gradle.kts
8 | index 27b86c89e8ee3a3b503eef0f71fd9c39132d3f89..61f0b30f2bcf2c6a32054e16d10179fcd0a52950 100644
9 | --- a/build.gradle.kts
10 | +++ b/build.gradle.kts
11 | @@ -38,7 +38,7 @@ dependencies {
12 | implementation("com.fasterxml.jackson.core:jackson-annotations:2.15.2") //ServersideRecording
13 | implementation("com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:2.15.2") //ServersideRecording
14 | implementation ("de.maxhenkel.voicechat:voicechat-api:2.4.0") //ServersideRecording
15 | - implementation ("maven.modrinth:simple-voice-chat:fabric-1.20.1-2.4.11") //ServersideRecording
16 | + compileOnly ("maven.modrinth:simple-voice-chat:bukkit-2.4.11") //ServersideRecording
17 | runtimeOnly("org.xerial:sqlite-jdbc:3.42.0.0")
18 | runtimeOnly("com.mysql:mysql-connector-j:8.0.33")
19 | runtimeOnly("com.lmax:disruptor:3.4.4") // Paper
20 | diff --git a/src/main/java/net/minecraft/serversidereplayrecorder/ServerSideReplayRecorderServer.java b/src/main/java/net/minecraft/serversidereplayrecorder/ServerSideReplayRecorderServer.java
21 | index 1d6673b4e81a4f322cfde4b22779a999c134cf56..2a9abdc696f1d6ccda09f988834bac2056b6262c 100644
22 | --- a/src/main/java/net/minecraft/serversidereplayrecorder/ServerSideReplayRecorderServer.java
23 | +++ b/src/main/java/net/minecraft/serversidereplayrecorder/ServerSideReplayRecorderServer.java
24 | @@ -5,6 +5,8 @@ import com.fasterxml.jackson.dataformat.yaml.YAMLFactory;
25 | import com.fasterxml.jackson.dataformat.yaml.YAMLFactoryBuilder;
26 | import com.fasterxml.jackson.dataformat.yaml.YAMLGenerator;
27 | import com.fasterxml.jackson.databind.ObjectMapper;
28 | +import de.maxhenkel.voicechat.config.ServerConfig;
29 | +import de.maxhenkel.voicechat.configbuilder.ConfigBuilder;
30 | import io.netty.util.concurrent.DefaultThreadFactory;
31 | import net.minecraft.server.MinecraftServer;
32 | import net.minecraft.serversidereplayrecorder.config.MainConfig;
33 | @@ -38,11 +40,12 @@ public class ServerSideReplayRecorderServer {
34 |
35 | public static final String configPath = getConfigDirectory() + "/ServerSideReplayRecorder.yml";
36 | public static MainConfig config = new MainConfig();
37 | + public static ServerConfig SERVER_CONFIG;
38 |
39 | public static void loadConfig() {
40 | if (ServerSideReplayRecorderServer.config.isDebug()) MinecraftServer.LOGGER.info("loadConfig: loading...");
41 | try {
42 | - yaml.findAndRegisterModules();
43 | + //yaml.findAndRegisterModules();
44 | config = yaml.readValue(new FileReader(configPath), MainConfig.class);
45 | if (ServerSideReplayRecorderServer.config.isDebug()) MinecraftServer.LOGGER.info("loadConfig: loaded");
46 | }catch (FileNotFoundException e){
47 | diff --git a/src/main/java/net/minecraft/serversidereplayrecorder/recorder/RegionRecorder.java b/src/main/java/net/minecraft/serversidereplayrecorder/recorder/RegionRecorder.java
48 | index 7312a60b1af9c66efa60a42e81256ee700c7623f..c4d2e42f6e365cbada8c27a5a38d051c421a83d9 100644
49 | --- a/src/main/java/net/minecraft/serversidereplayrecorder/recorder/RegionRecorder.java
50 | +++ b/src/main/java/net/minecraft/serversidereplayrecorder/recorder/RegionRecorder.java
51 | @@ -2,6 +2,7 @@ package net.minecraft.serversidereplayrecorder.recorder;
52 |
53 | import com.mojang.authlib.GameProfile;
54 | import de.maxhenkel.voicechat.Voicechat;
55 | +import de.maxhenkel.voicechat.config.ServerConfig;
56 | import io.netty.buffer.Unpooled;
57 | import net.minecraft.core.BlockPos;
58 | import net.minecraft.core.NonNullList;
59 | @@ -220,7 +221,7 @@ public class RegionRecorder extends ReplayRecorder {
60 | //ready to record changes
61 | if(ServerSideReplayRecorderServer.config.isVoice_recording_enabled()){
62 | ServerPlayer player = new ServerPlayer(ms, ms.overworld(), FAKE_GAMEPROFILE);
63 | - onPacket(Utils.createCustomPacket(new SecretPacket(player, UUID.randomUUID() , Voicechat.SERVER.getServer().getPort(), Voicechat.SERVER_CONFIG)));
64 | + onPacket(Utils.createCustomPacket(new SecretPacket(player, UUID.randomUUID() , 30613, ServerSideReplayRecorderServer.SERVER_CONFIG)));
65 | }
66 | }
67 |
68 | diff --git a/src/main/java/net/minecraft/serversidereplayrecorder/voice/config/ServerConfig.java b/src/main/java/net/minecraft/serversidereplayrecorder/voice/config/ServerConfig.java
69 | new file mode 100644
70 | index 0000000000000000000000000000000000000000..84b188896b3e53a1b42f161a1ac75bbf34a6635a
71 | --- /dev/null
72 | +++ b/src/main/java/net/minecraft/serversidereplayrecorder/voice/config/ServerConfig.java
73 | @@ -0,0 +1,52 @@
74 | +package net.minecraft.serversidereplayrecorder.voice.config;
75 | +
76 | +import de.maxhenkel.voicechat.Voicechat;
77 | +import de.maxhenkel.voicechat.configbuilder.ConfigBuilder;
78 | +import de.maxhenkel.voicechat.configbuilder.ConfigEntry;
79 | +public class ServerConfig {
80 | + public final ConfigEntry voiceChatPort;
81 | + public final ConfigEntry voiceChatBindAddress;
82 | + public final ConfigEntry voiceChatDistance;
83 | + public ConfigEntry crouchDistanceMultiplier;
84 | + public ConfigEntry whisperDistanceMultiplier;
85 | + public final ConfigEntry voiceChatCodec;
86 | + public final ConfigEntry voiceChatMtuSize;
87 | + public final ConfigEntry keepAlive;
88 | + public final ConfigEntry groupsEnabled;
89 | + public final ConfigEntry voiceHost;
90 | + public final ConfigEntry allowRecording;
91 | + public final ConfigEntry spectatorInteraction;
92 | + public ConfigEntry spectatorPlayerPossession;
93 | + public ConfigEntry forceVoiceChat;
94 | + public ConfigEntry loginTimeout;
95 | + public ConfigEntry broadcastRange;
96 | +
97 | + public ServerConfig(ConfigBuilder builder) {
98 | + builder.header(new String[]{String.format("Simple Voice Chat server config v%s", Voicechat.INSTANCE.getDescription().getVersion())});
99 | + this.voiceChatPort = builder.integerEntry("port", 24454, -1, 65535, new String[]{"The port of the voice chat server", "Setting this to \"-1\" sets the port to the Minecraft servers port (Not recommended)"});
100 | + this.voiceChatBindAddress = builder.stringEntry("bind_address", "", new String[]{"The IP address to bind the voice chat server on", "Leave empty to use 'server-ip' of server.properties", "To bind to the wildcard address, use '*'"});
101 | + this.voiceChatDistance = builder.doubleEntry("max_voice_distance", 48.0, 1.0, 1000000.0, new String[]{"The distance to where the voice can be heard"});
102 | + this.crouchDistanceMultiplier = builder.doubleEntry("crouch_distance_multiplier", 1.0, 0.01, 1.0, new String[]{"The multiplier the voice distance will be reduced by when sneaking"});
103 | + this.whisperDistanceMultiplier = builder.doubleEntry("whisper_distance_multiplier", 0.5, 0.01, 1.0, new String[]{"The multiplier the voice distance will be reduced by when whispering"});
104 | + this.voiceChatCodec = builder.enumEntry("codec", de.maxhenkel.voicechat.config.ServerConfig.Codec.VOIP, new String[]{"The opus codec"});
105 | + this.voiceChatMtuSize = builder.integerEntry("mtu_size", 1024, 256, 10000, new String[]{"The maximum size in bytes in a voice packet", "Set this to a lower value if your voice packets don't arrive"});
106 | + this.keepAlive = builder.integerEntry("keep_alive", 1000, 1000, Integer.MAX_VALUE, new String[]{"The frequency in which keep alive packets are sent", "Setting this to a higher value may result in timeouts"});
107 | + this.groupsEnabled = builder.booleanEntry("enable_groups", true, new String[]{"If group chats are allowed"});
108 | + this.voiceHost = builder.stringEntry("voice_host", "", new String[]{"The host name that clients should use to connect to the voice chat", "This may also include a port, e.g. 'example.com:24454'", "Don't change this value if you don't know what you are doing"});
109 | + this.allowRecording = builder.booleanEntry("allow_recording", true, new String[]{"If players are allowed to record the voice chat"});
110 | + this.spectatorInteraction = builder.booleanEntry("spectator_interaction", false, new String[]{"If spectators are allowed to talk to other players"});
111 | + this.spectatorPlayerPossession = builder.booleanEntry("spectator_player_possession", false, new String[]{"If spectators can talk to players they are spectating"});
112 | + this.forceVoiceChat = builder.booleanEntry("force_voice_chat", false, new String[]{"If players without the mod should get kicked from the server"});
113 | + this.loginTimeout = builder.integerEntry("login_timeout", 10000, 100, Integer.MAX_VALUE, new String[]{"The amount of milliseconds, the server should wait to check if the player has the mod installed", "Only active when force_voice_chat is set to true"});
114 | + this.broadcastRange = builder.doubleEntry("broadcast_range", -1.0, -1.0, Double.MAX_VALUE, new String[]{"The range where the voice chat should broadcast audio to", "A value <0 means 'max_voice_distance'"});
115 | + }
116 | +
117 | + public static enum Codec {
118 | + VOIP,
119 | + AUDIO,
120 | + RESTRICTED_LOWDELAY;
121 | +
122 | + private Codec() {
123 | + }
124 | + }
125 | +}
126 |
--------------------------------------------------------------------------------
/patches/server/0032-Support-Region-Voice-Recording.patch:
--------------------------------------------------------------------------------
1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
2 | From: Bryan1029384756 <23323626+Bryan1029384756@users.noreply.github.com>
3 | Date: Sat, 1 Jul 2023 16:34:22 -0500
4 | Subject: [PATCH] Support Region Voice Recording
5 |
6 |
7 | diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java
8 | index ddd53d0fd3da2b2ba1b9013b459bc398f0354870..a27c40aaa626f31d03935a4bffde074eb6f8e230 100644
9 | --- a/src/main/java/net/minecraft/server/MinecraftServer.java
10 | +++ b/src/main/java/net/minecraft/server/MinecraftServer.java
11 | @@ -630,6 +630,11 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop voiceChatPort;
67 | - public final ConfigEntry voiceChatBindAddress;
68 | - public final ConfigEntry voiceChatDistance;
69 | - public ConfigEntry crouchDistanceMultiplier;
70 | - public ConfigEntry whisperDistanceMultiplier;
71 | - public final ConfigEntry voiceChatCodec;
72 | - public final ConfigEntry voiceChatMtuSize;
73 | - public final ConfigEntry keepAlive;
74 | - public final ConfigEntry groupsEnabled;
75 | - public final ConfigEntry voiceHost;
76 | - public final ConfigEntry allowRecording;
77 | - public final ConfigEntry spectatorInteraction;
78 | - public ConfigEntry spectatorPlayerPossession;
79 | - public ConfigEntry forceVoiceChat;
80 | - public ConfigEntry loginTimeout;
81 | - public ConfigEntry broadcastRange;
82 | -
83 | - public ServerConfig(ConfigBuilder builder) {
84 | - builder.header(new String[]{String.format("Simple Voice Chat server config v%s", Voicechat.INSTANCE.getDescription().getVersion())});
85 | - this.voiceChatPort = builder.integerEntry("port", 24454, -1, 65535, new String[]{"The port of the voice chat server", "Setting this to \"-1\" sets the port to the Minecraft servers port (Not recommended)"});
86 | - this.voiceChatBindAddress = builder.stringEntry("bind_address", "", new String[]{"The IP address to bind the voice chat server on", "Leave empty to use 'server-ip' of server.properties", "To bind to the wildcard address, use '*'"});
87 | - this.voiceChatDistance = builder.doubleEntry("max_voice_distance", 48.0, 1.0, 1000000.0, new String[]{"The distance to where the voice can be heard"});
88 | - this.crouchDistanceMultiplier = builder.doubleEntry("crouch_distance_multiplier", 1.0, 0.01, 1.0, new String[]{"The multiplier the voice distance will be reduced by when sneaking"});
89 | - this.whisperDistanceMultiplier = builder.doubleEntry("whisper_distance_multiplier", 0.5, 0.01, 1.0, new String[]{"The multiplier the voice distance will be reduced by when whispering"});
90 | - this.voiceChatCodec = builder.enumEntry("codec", de.maxhenkel.voicechat.config.ServerConfig.Codec.VOIP, new String[]{"The opus codec"});
91 | - this.voiceChatMtuSize = builder.integerEntry("mtu_size", 1024, 256, 10000, new String[]{"The maximum size in bytes in a voice packet", "Set this to a lower value if your voice packets don't arrive"});
92 | - this.keepAlive = builder.integerEntry("keep_alive", 1000, 1000, Integer.MAX_VALUE, new String[]{"The frequency in which keep alive packets are sent", "Setting this to a higher value may result in timeouts"});
93 | - this.groupsEnabled = builder.booleanEntry("enable_groups", true, new String[]{"If group chats are allowed"});
94 | - this.voiceHost = builder.stringEntry("voice_host", "", new String[]{"The host name that clients should use to connect to the voice chat", "This may also include a port, e.g. 'example.com:24454'", "Don't change this value if you don't know what you are doing"});
95 | - this.allowRecording = builder.booleanEntry("allow_recording", true, new String[]{"If players are allowed to record the voice chat"});
96 | - this.spectatorInteraction = builder.booleanEntry("spectator_interaction", false, new String[]{"If spectators are allowed to talk to other players"});
97 | - this.spectatorPlayerPossession = builder.booleanEntry("spectator_player_possession", false, new String[]{"If spectators can talk to players they are spectating"});
98 | - this.forceVoiceChat = builder.booleanEntry("force_voice_chat", false, new String[]{"If players without the mod should get kicked from the server"});
99 | - this.loginTimeout = builder.integerEntry("login_timeout", 10000, 100, Integer.MAX_VALUE, new String[]{"The amount of milliseconds, the server should wait to check if the player has the mod installed", "Only active when force_voice_chat is set to true"});
100 | - this.broadcastRange = builder.doubleEntry("broadcast_range", -1.0, -1.0, Double.MAX_VALUE, new String[]{"The range where the voice chat should broadcast audio to", "A value <0 means 'max_voice_distance'"});
101 | - }
102 | -
103 | - public static enum Codec {
104 | - VOIP,
105 | - AUDIO,
106 | - RESTRICTED_LOWDELAY;
107 | -
108 | - private Codec() {
109 | - }
110 | - }
111 | -}
112 |
--------------------------------------------------------------------------------
/patches/server/0033-Support-Region-Voice-Recording.patch:
--------------------------------------------------------------------------------
1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
2 | From: Bryan1029384756 <23323626+Bryan1029384756@users.noreply.github.com>
3 | Date: Sat, 1 Jul 2023 16:39:27 -0500
4 | Subject: [PATCH] Support Region Voice Recording
5 |
6 |
7 | diff --git a/src/main/java/net/minecraft/serversidereplayrecorder/recorder/RegionRecorder.java b/src/main/java/net/minecraft/serversidereplayrecorder/recorder/RegionRecorder.java
8 | index 7312a60b1af9c66efa60a42e81256ee700c7623f..870678d345fc20cf42f06c8c20318d833a8da80c 100644
9 | --- a/src/main/java/net/minecraft/serversidereplayrecorder/recorder/RegionRecorder.java
10 | +++ b/src/main/java/net/minecraft/serversidereplayrecorder/recorder/RegionRecorder.java
11 | @@ -35,6 +35,8 @@ import net.minecraft.world.level.chunk.ImposterProtoChunk;
12 | import net.minecraft.world.level.chunk.LevelChunk;
13 | import net.minecraft.world.level.levelgen.Heightmap;
14 | import net.minecraft.world.level.storage.LevelData;
15 | +import org.bukkit.Bukkit;
16 | +
17 | import java.io.File;
18 | import java.io.IOException;
19 | import java.nio.file.Paths;
20 | @@ -219,8 +221,11 @@ public class RegionRecorder extends ReplayRecorder {
21 | onPacket(new ClientboundPlayerPositionPacket(viewpoint.getX() + 0.5d,viewpoint.getY(),viewpoint.getZ() + 0.5d,0f,0f, Collections.emptySet(),0));
22 | //ready to record changes
23 | if(ServerSideReplayRecorderServer.config.isVoice_recording_enabled()){
24 | - ServerPlayer player = new ServerPlayer(ms, ms.overworld(), FAKE_GAMEPROFILE);
25 | - onPacket(Utils.createCustomPacket(new SecretPacket(player, UUID.randomUUID() , Voicechat.SERVER.getServer().getPort(), Voicechat.SERVER_CONFIG)));
26 | + if (Bukkit.getServer().getPluginManager().isPluginEnabled("Marriage")) {
27 | + Voicechat mp = (Voicechat) Bukkit.getServer().getPluginManager().getPlugin("Marriage");
28 | + ServerPlayer player = new ServerPlayer(ms, ms.overworld(), FAKE_GAMEPROFILE);
29 | + onPacket(Utils.createCustomPacket(new SecretPacket(player, UUID.randomUUID() , Voicechat.SERVER.getServer().getPort(), Voicechat.SERVER_CONFIG)));
30 | + }
31 | }
32 | }
33 |
34 |
--------------------------------------------------------------------------------
/patches/server/0034-Support-Region-Voice-Recording.patch:
--------------------------------------------------------------------------------
1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
2 | From: Bryan1029384756 <23323626+Bryan1029384756@users.noreply.github.com>
3 | Date: Sat, 1 Jul 2023 18:01:36 -0500
4 | Subject: [PATCH] Support Region Voice Recording
5 |
6 |
7 | diff --git a/build.gradle.kts b/build.gradle.kts
8 | index 61f0b30f2bcf2c6a32054e16d10179fcd0a52950..16f59317c713b2e73479eea2685ad41f637d9020 100644
9 | --- a/build.gradle.kts
10 | +++ b/build.gradle.kts
11 | @@ -38,7 +38,7 @@ dependencies {
12 | implementation("com.fasterxml.jackson.core:jackson-annotations:2.15.2") //ServersideRecording
13 | implementation("com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:2.15.2") //ServersideRecording
14 | implementation ("de.maxhenkel.voicechat:voicechat-api:2.4.0") //ServersideRecording
15 | - compileOnly ("maven.modrinth:simple-voice-chat:bukkit-2.4.11") //ServersideRecording
16 | + // compileOnly ("maven.modrinth:simple-voice-chat:bukkit-2.4.11") //ServersideRecording
17 | runtimeOnly("org.xerial:sqlite-jdbc:3.42.0.0")
18 | runtimeOnly("com.mysql:mysql-connector-j:8.0.33")
19 | runtimeOnly("com.lmax:disruptor:3.4.4") // Paper
20 | diff --git a/src/main/java/net/minecraft/serversidereplayrecorder/ServerSideReplayRecorderServer.java b/src/main/java/net/minecraft/serversidereplayrecorder/ServerSideReplayRecorderServer.java
21 | index 2a9abdc696f1d6ccda09f988834bac2056b6262c..f47184e1d8196a3d5ccb127eeb7a6529c3d59ffb 100644
22 | --- a/src/main/java/net/minecraft/serversidereplayrecorder/ServerSideReplayRecorderServer.java
23 | +++ b/src/main/java/net/minecraft/serversidereplayrecorder/ServerSideReplayRecorderServer.java
24 | @@ -5,8 +5,6 @@ import com.fasterxml.jackson.dataformat.yaml.YAMLFactory;
25 | import com.fasterxml.jackson.dataformat.yaml.YAMLFactoryBuilder;
26 | import com.fasterxml.jackson.dataformat.yaml.YAMLGenerator;
27 | import com.fasterxml.jackson.databind.ObjectMapper;
28 | -import de.maxhenkel.voicechat.config.ServerConfig;
29 | -import de.maxhenkel.voicechat.configbuilder.ConfigBuilder;
30 | import io.netty.util.concurrent.DefaultThreadFactory;
31 | import net.minecraft.server.MinecraftServer;
32 | import net.minecraft.serversidereplayrecorder.config.MainConfig;
33 | @@ -40,7 +38,6 @@ public class ServerSideReplayRecorderServer {
34 |
35 | public static final String configPath = getConfigDirectory() + "/ServerSideReplayRecorder.yml";
36 | public static MainConfig config = new MainConfig();
37 | - public static ServerConfig SERVER_CONFIG;
38 |
39 | public static void loadConfig() {
40 | if (ServerSideReplayRecorderServer.config.isDebug()) MinecraftServer.LOGGER.info("loadConfig: loading...");
41 | diff --git a/src/main/java/net/minecraft/serversidereplayrecorder/recorder/RegionRecorder.java b/src/main/java/net/minecraft/serversidereplayrecorder/recorder/RegionRecorder.java
42 | index 870678d345fc20cf42f06c8c20318d833a8da80c..bca4df2409fd87cd7890acbbc889fd6d741f0e32 100644
43 | --- a/src/main/java/net/minecraft/serversidereplayrecorder/recorder/RegionRecorder.java
44 | +++ b/src/main/java/net/minecraft/serversidereplayrecorder/recorder/RegionRecorder.java
45 | @@ -1,7 +1,6 @@
46 | package net.minecraft.serversidereplayrecorder.recorder;
47 |
48 | import com.mojang.authlib.GameProfile;
49 | -import de.maxhenkel.voicechat.Voicechat;
50 | import io.netty.buffer.Unpooled;
51 | import net.minecraft.core.BlockPos;
52 | import net.minecraft.core.NonNullList;
53 | @@ -20,6 +19,7 @@ import net.minecraft.serversidereplayrecorder.util.interfaces.LightUpdatePacketA
54 | import net.minecraft.serversidereplayrecorder.util.interfaces.RegionRecorderStorage;
55 | import net.minecraft.serversidereplayrecorder.util.interfaces.RegionRecorderWorld;
56 | import net.minecraft.serversidereplayrecorder.voice.Utils;
57 | +import net.minecraft.serversidereplayrecorder.voice.config.ServerConfig;
58 | import net.minecraft.serversidereplayrecorder.voice.net.SecretPacket;
59 | import net.minecraft.tags.TagNetworkSerialization;
60 | import net.minecraft.world.entity.player.Abilities;
61 | @@ -36,9 +36,11 @@ import net.minecraft.world.level.chunk.LevelChunk;
62 | import net.minecraft.world.level.levelgen.Heightmap;
63 | import net.minecraft.world.level.storage.LevelData;
64 | import org.bukkit.Bukkit;
65 | +import org.bukkit.plugin.Plugin;
66 |
67 | import java.io.File;
68 | import java.io.IOException;
69 | +import java.lang.reflect.Field;
70 | import java.nio.file.Paths;
71 | import java.util.*;
72 | import java.util.concurrent.CompletableFuture;
73 | @@ -221,11 +223,9 @@ public class RegionRecorder extends ReplayRecorder {
74 | onPacket(new ClientboundPlayerPositionPacket(viewpoint.getX() + 0.5d,viewpoint.getY(),viewpoint.getZ() + 0.5d,0f,0f, Collections.emptySet(),0));
75 | //ready to record changes
76 | if(ServerSideReplayRecorderServer.config.isVoice_recording_enabled()){
77 | - if (Bukkit.getServer().getPluginManager().isPluginEnabled("Marriage")) {
78 | - Voicechat mp = (Voicechat) Bukkit.getServer().getPluginManager().getPlugin("Marriage");
79 | ServerPlayer player = new ServerPlayer(ms, ms.overworld(), FAKE_GAMEPROFILE);
80 | - onPacket(Utils.createCustomPacket(new SecretPacket(player, UUID.randomUUID() , Voicechat.SERVER.getServer().getPort(), Voicechat.SERVER_CONFIG)));
81 | - }
82 | + ServerConfig SERVER_CONFIG = new ServerConfig();
83 | + onPacket(Utils.createCustomPacket(new SecretPacket(player, UUID.randomUUID() , 34534, SERVER_CONFIG)));
84 | }
85 | }
86 |
87 | diff --git a/src/main/java/net/minecraft/serversidereplayrecorder/voice/ServerSideVoiceChat.java b/src/main/java/net/minecraft/serversidereplayrecorder/voice/ServerSideVoiceChat.java
88 | index 2afbfcb15a30988f3acb92af798819fa231b3022..4025e75918582e561e5692b0a47b46de724e2a8d 100644
89 | --- a/src/main/java/net/minecraft/serversidereplayrecorder/voice/ServerSideVoiceChat.java
90 | +++ b/src/main/java/net/minecraft/serversidereplayrecorder/voice/ServerSideVoiceChat.java
91 | @@ -25,6 +25,7 @@ public class ServerSideVoiceChat implements VoicechatPlugin {
92 | System.out.println("Started recording voice chat using PaperRecord");
93 | this.distance = api.getVoiceChatDistance();
94 | this.SERVERAPI = api;
95 | +
96 | }
97 |
98 | @Override
99 | diff --git a/src/main/java/net/minecraft/serversidereplayrecorder/voice/Utils.java b/src/main/java/net/minecraft/serversidereplayrecorder/voice/Utils.java
100 | index 99213f8a949ff5f145185c84e87766172b4cacd5..7db1dffd42264cbb124d6d5d0def7c4bd95ebbbb 100644
101 | --- a/src/main/java/net/minecraft/serversidereplayrecorder/voice/Utils.java
102 | +++ b/src/main/java/net/minecraft/serversidereplayrecorder/voice/Utils.java
103 | @@ -39,6 +39,8 @@ public class Utils {
104 | public static ClientboundCustomPayloadPacket createCustomPacket(Packet> packet) {
105 | FriendlyByteBuf buf = new FriendlyByteBuf(Unpooled.buffer());
106 | packet.toBytes(buf);
107 | + ClientboundCustomPayloadPacket test = new ClientboundCustomPayloadPacket(packet.getIdentifier(), buf);
108 | +
109 | return new ClientboundCustomPayloadPacket(packet.getIdentifier(), buf);
110 | }
111 |
112 | diff --git a/src/main/java/net/minecraft/serversidereplayrecorder/voice/config/ServerConfig.java b/src/main/java/net/minecraft/serversidereplayrecorder/voice/config/ServerConfig.java
113 | new file mode 100644
114 | index 0000000000000000000000000000000000000000..3216a46922c03ef8167e05d999617a379a6aaa79
115 | --- /dev/null
116 | +++ b/src/main/java/net/minecraft/serversidereplayrecorder/voice/config/ServerConfig.java
117 | @@ -0,0 +1,58 @@
118 | +package net.minecraft.serversidereplayrecorder.voice.config;
119 | +
120 | +//
121 | +// Source code recreated from a .class file by IntelliJ IDEA
122 | +// (powered by FernFlower decompiler
123 | +import java.io.*;
124 | +import java.util.Properties;
125 | +
126 | +public class ServerConfig {
127 | + public int voiceChatPort;
128 | + public String voiceChatBindAddress;
129 | + public double voiceChatDistance;
130 | + public double crouchDistanceMultiplier;
131 | + public double whisperDistanceMultiplier;
132 | + public Codec voiceChatCodec;
133 | + public int voiceChatMtuSize;
134 | + public int keepAlive;
135 | + public boolean groupsEnabled;
136 | + public String voiceHost;
137 | + public boolean allowRecording;
138 | + public boolean spectatorInteraction;
139 | + public boolean spectatorPlayerPossession;
140 | + public boolean forceVoiceChat;
141 | + public int loginTimeout;
142 | + public double broadcastRange;
143 | +
144 | +
145 | + public ServerConfig(){
146 | + Properties properties = new Properties();
147 | + String path = System.getProperty("user.dir") + "\\plugins\\voicechat\\voicechat-server.properties";
148 | +
149 | + try (InputStream input = new FileInputStream(path)) {
150 | + properties.load(input);
151 | + voiceChatPort = Integer.parseInt(properties.getProperty("port", "24454"));
152 | + voiceChatBindAddress = properties.getProperty("bind_address", "");
153 | + voiceChatDistance = Double.parseDouble(properties.getProperty("max_voice_distance", "48.0"));
154 | + crouchDistanceMultiplier = Double.parseDouble(properties.getProperty("crouch_distance_multiplier", "1.0"));
155 | + whisperDistanceMultiplier = Double.parseDouble(properties.getProperty("whisper_distance_multiplier", "0.5"));
156 | + voiceChatCodec = Codec.valueOf(properties.getProperty("codec", "VOIP").toUpperCase());
157 | + voiceChatMtuSize = Integer.parseInt(properties.getProperty("mtu_size", "1024"));
158 | + keepAlive = Integer.parseInt(properties.getProperty("keep_alive", "1000"));
159 | + groupsEnabled = Boolean.parseBoolean(properties.getProperty("enable_groups", "true"));
160 | + voiceHost = properties.getProperty("voice_host", "0.0.0.0");
161 | + allowRecording = Boolean.parseBoolean(properties.getProperty("allow_recording", "true"));
162 | + spectatorInteraction = Boolean.parseBoolean(properties.getProperty("spectator_interaction", "false"));
163 | + spectatorPlayerPossession = Boolean.parseBoolean(properties.getProperty("spectator_player_possession", "false"));
164 | + forceVoiceChat = Boolean.parseBoolean(properties.getProperty("force_voice_chat", "false"));
165 | + loginTimeout = Integer.parseInt(properties.getProperty("login_timeout", "10000"));
166 | + broadcastRange = Double.parseDouble(properties.getProperty("broadcast_range", "-1.0"));
167 | + } catch (IOException ex) {
168 | + ex.printStackTrace();
169 | + }
170 | + }
171 | +
172 | + public enum Codec {
173 | + VOIP, AUDIO, RESTRICTED_LOWDELAY;
174 | + }
175 | +}
176 | diff --git a/src/main/java/net/minecraft/serversidereplayrecorder/voice/net/SecretPacket.java b/src/main/java/net/minecraft/serversidereplayrecorder/voice/net/SecretPacket.java
177 | index c24e8021e76582210caa9a64ce4d5c8cb92b4f92..0ec0cb18711413bf6586f6a9e26e77fc08832644 100644
178 | --- a/src/main/java/net/minecraft/serversidereplayrecorder/voice/net/SecretPacket.java
179 | +++ b/src/main/java/net/minecraft/serversidereplayrecorder/voice/net/SecretPacket.java
180 | @@ -1,10 +1,12 @@
181 | package net.minecraft.serversidereplayrecorder.voice.net;
182 |
183 | +import de.maxhenkel.voicechat.api.VoicechatServerApi;
184 | +import de.maxhenkel.voicechat.api.events.VoiceHostEvent;
185 | import net.minecraft.network.FriendlyByteBuf;
186 | import net.minecraft.resources.ResourceLocation;
187 | import net.minecraft.server.level.ServerPlayer;
188 | -import de.maxhenkel.voicechat.config.ServerConfig;
189 | -import de.maxhenkel.voicechat.plugins.PluginManager;
190 | +import net.minecraft.serversidereplayrecorder.voice.config.ServerConfig;
191 | +
192 | import java.util.UUID;
193 |
194 | public class SecretPacket implements Packet {
195 | @@ -27,13 +29,13 @@ public class SecretPacket implements Packet {
196 | this.secret = secret;
197 | this.serverPort = port;
198 | this.playerUUID = player.getUUID();
199 | - this.codec = (ServerConfig.Codec)serverConfig.voiceChatCodec.get();
200 | - this.mtuSize = (Integer)serverConfig.voiceChatMtuSize.get();
201 | - this.voiceChatDistance = (Double)serverConfig.voiceChatDistance.get();
202 | - this.keepAlive = (Integer)serverConfig.keepAlive.get();
203 | - this.groupsEnabled = (Boolean)serverConfig.groupsEnabled.get();
204 | - this.voiceHost = PluginManager.instance().getVoiceHost((String)serverConfig.voiceHost.get());
205 | - this.allowRecording = (Boolean)serverConfig.allowRecording.get();
206 | + this.codec = (ServerConfig.Codec)serverConfig.voiceChatCodec;
207 | + this.mtuSize = (Integer)serverConfig.voiceChatMtuSize;
208 | + this.voiceChatDistance = (Double)serverConfig.voiceChatDistance;
209 | + this.keepAlive = (Integer)serverConfig.keepAlive;
210 | + this.groupsEnabled = (Boolean)serverConfig.groupsEnabled;
211 | + this.voiceHost = "0.0.0.0";
212 | + this.allowRecording = (Boolean)serverConfig.allowRecording;
213 | }
214 |
215 | public UUID getSecret() {
216 |
--------------------------------------------------------------------------------
/rb.bat:
--------------------------------------------------------------------------------
1 | ./gradlew rebuildpatches
--------------------------------------------------------------------------------
/regiontodo.txt:
--------------------------------------------------------------------------------
1 | Get done after test:
2 | - global autosave queue
3 | - game time / day time tick comparison (== is now invalid due to desync of global / region tick)
4 | - scoreboards
5 | - vanish api
6 | - watchdog stuff
7 | - Spectator teleporting / camera
8 | - Conversable...
9 | - sync load info
10 | - net.minecraft.commands.Commands
11 | - are the race conditions in the weather tick (advanceWeatherCycle) ok?
12 | - make scheduler load chunks better? this requires additional work to:
13 | -> reduce scheduler overhead (i.e at 5000 regions, on 16 threads -> overhead is 10%)
14 | -> unsure how to reduce scheduler overhead, may need to rewrite it so that the queues
15 | are per tick thread and thus it increases parallelism
16 | -> reduce chunk system overhead (i.e at 20 workers, ~100 unique concurrent regions, overhead -> 10-30% on both workers AND tick threads (at tick threads ->8)
17 | -> the only way out of the chunk system overhead is to make the scheduling more parallel - it requires scheduling lock and ticket lock
18 | - redstone wire accross regions
19 |
20 | Delayed and hopefully will not forget:
21 | - api for really a lot of shit
22 | - needs: true async events (i.e fire then complete later)
23 | - needs: region determination, craft scheduler per region, craft scheduler
24 | per entity
25 | - needs: world creation/unload (good god)
26 | - needs: more???
27 | - Projectile#getOwner ...
28 |
29 | Ideas:
30 |
31 | Issues:
32 |
33 | To check:
34 |
--------------------------------------------------------------------------------
/settings.gradle.kts:
--------------------------------------------------------------------------------
1 | import java.util.Locale
2 |
3 | pluginManagement {
4 | repositories {
5 | gradlePluginPortal()
6 | maven("https://repo.papermc.io/repository/maven-public/")
7 | }
8 | }
9 |
10 | plugins {
11 | id("org.gradle.toolchains.foojay-resolver-convention") version "0.4.0"
12 | }
13 |
14 | if (!file(".git").exists()) {
15 | val errorText = """
16 |
17 | =====================[ ERROR ]=====================
18 | The PaperRecord project directory is not a properly cloned Git repository.
19 |
20 | In order to build PaperRecord from source you must clone
21 | the PaperRecord repository using Git, not download a code
22 | zip from GitHub.
23 |
24 | See https://github.com/PaperMC/Paper/blob/master/CONTRIBUTING.md
25 | for further information on building and modifying Paper and Forks.
26 | ===================================================
27 | """.trimIndent()
28 | error(errorText)
29 | }
30 |
31 | rootProject.name = "paperrecord"
32 |
33 | for (name in listOf("PaperRecord-API", "PaperRecord-Server")) {
34 | val projName = name.lowercase(Locale.ENGLISH)
35 | include(projName)
36 | findProject(":$projName")!!.projectDir = file(name)
37 | }
38 |
--------------------------------------------------------------------------------