Compare commits

..
393 Commits
Author SHA1 Message Date
Kyllian WarmerdamandKyllian Warmerdam f6424ddb56 Cancel own-player equipment packets in 1.9->1.8 (#733)
Needed since https://github.com/ViaVersion/ViaBackwards/commit/53105e644d005c37aaad7a31d1e9a78016026050 emulates SET_EQUIPMENT packets for the client player.

Co-authored-by: Kyllian Warmerdam <kyllian@Mac.localdomain>
2026-10-18 03:58:18 +02:00
Rocco 00bd23a639 Map shulker bullets to wither skulls in 1.9->1.8 (#731)
The previous mapping didn't really work, nothing would spawn.

I chose wither skull for a few reasons:
* They're also a hurting projectile
* They're fairly easy to hit
* Wind Charges are mapped to shulker bullets by ViaBackwards, and having them be wither skulls is quite convenient as they share the same motion properties (namely 0.95 air drag). I tried setting the invulnerable/aura entity data on the skull, though while that looks closer to both shulker bullets and wind charges, the air drag is much lower so movement gets desynced.
2026-10-11 18:27:50 +02:00
Alessandro 7a6d73bd20 Only write the 1.7 length prefix on Velocity (#732) 2026-10-11 18:03:06 +02:00
Maykol Tejeda 118fab1ba2 Don't drop length prefix for 1.7 encoding (#729)
Restore the VarInt packet length prefix after ViaRewind replaces
Velocity's compression encoder with ForwardMessageToByteEncoder.

Without the length prefix, 1.7.x clients receive unframed packets and
fail during login with "Bad packet id" errors.

Verified by reproducing issue #616 and confirming that adding the packet length framing allows a 1.7.10 client to proceed.
Fixes https://github.com/ViaVersion/ViaRewind/issues/616
2026-10-06 11:22:01 +02:00
dependabot[bot] 79ab8df038 Update Gradle wrapper (#730)
Bumps the all-dependencies group with 1 update in the / directory: [gradle-wrapper](https://github.com/gradle/gradle).


Updates `gradle-wrapper` from 9.7.1 to 9.8.0
- [Release notes](https://github.com/gradle/gradle/releases)
- [Commits](https://github.com/gradle/gradle/compare/v9.7.1...v9.8.0)

---
updated-dependencies:
- dependency-name: gradle-wrapper
  dependency-version: 9.8.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: all-dependencies
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-10-06 11:07:38 +02:00
dependabot[bot] 824908a72f [ci skip] Update GH actions (#727)
Bumps the all-dependencies group with 1 update: [actions/setup-java](https://github.com/actions/setup-java).


Updates `actions/setup-java` from 6.0.0 to 6.0.1
- [Release notes](https://github.com/actions/setup-java/releases)
- [Commits](https://github.com/actions/setup-java/compare/dd06d9cba3e5552c54d9f8ea23572deb30010f7c...de7274f081f381c8f8158605e0321c36c376e2e6)

---
updated-dependencies:
- dependency-name: actions/setup-java
  dependency-version: 6.0.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: all-dependencies
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-10-05 21:55:00 +02:00
Florian Reuth 27136c2e3a Start 4.2.1 cycle; Update BaseProject
Signed-off-by: Florian Reuth <git@florianreuth.de>
2026-09-28 17:46:26 +02:00
Florian Reuth d8e4746053 ViaRewind 4.2.0
Signed-off-by: Florian Reuth <git@florianreuth.de>
2026-09-18 17:06:16 +02:00
BeanesandFlorian Reuth 82a3ee84e0 Replace 1.9.4 mappings with 1.9 mappings, fixes invalid sound (#689)
Signed-off-by: Florian Reuth <git@florianreuth.de>
Co-authored-by: Florian Reuth <git@florianreuth.de>
2026-09-16 18:28:43 +02:00
Beanes 9df4d11f8c Implement 1.9->1.8 command block translation (#692)
* Implement 1.9->1.8 command block translation

* Inline methods
2026-09-16 17:30:23 +02:00
Term4 c92916a265 Send the delayed potion spawn's velocity as its own packet in 1.9->1.8 (#722) 2026-09-16 17:27:33 +02:00
Term4 dc04defeb6 Pass view-relative teleport flags through in 1.9->1.8 (#719)
1.8 handles the rotation-relative position flags (0x08/0x10) natively,
and resolving them against the tracked rotation snaps the camera to a
stale look on every teleport. Keep the rotation bits and their deltas on
the wire and only resolve the position bits.

Since the client applies kept deltas to its own live look, its teleport
confirm echoes a rotation the tracker cannot predict - match those
confirms on position only and adopt the echoed rotation.
2026-09-16 17:27:04 +02:00
Beanes c7edeba340 Fix using an item in air packet not matching the 1.8 packet (#718) 2026-09-16 17:26:34 +02:00
dependabot[bot] d232bd020f [ci skip] Update GH actions (#720)
Bumps the all-dependencies group with 1 update: [actions/setup-java](https://github.com/actions/setup-java).


Updates `actions/setup-java` from 5.7.0 to 6.0.0
- [Release notes](https://github.com/actions/setup-java/releases)
- [Commits](https://github.com/actions/setup-java/compare/b6effb05e454b25005698d916606bdc6ffcbf961...dd06d9cba3e5552c54d9f8ea23572deb30010f7c)

---
updated-dependencies:
- dependency-name: actions/setup-java
  dependency-version: 6.0.0
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: all-dependencies
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-09-02 15:29:08 +02:00
dependabot[bot] 2525d42666 [ci skip] Update deps (#721)
Bumps the all-dependencies group with 1 update: [gradle-wrapper](https://github.com/gradle/gradle).


Updates `gradle-wrapper` from 9.7.0 to 9.7.1
- [Release notes](https://github.com/gradle/gradle/releases)
- [Commits](https://github.com/gradle/gradle/compare/v9.7.0...v9.7.1)

---
updated-dependencies:
- dependency-name: gradle-wrapper
  dependency-version: 9.7.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: all-dependencies
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-09-02 15:28:43 +02:00
Florian Reuth 4d51a62410 Fix class token replacing
Signed-off-by: Florian Reuth <git@florianreuth.de>
2026-08-19 19:56:12 +02:00
Florian Reuth b177e048dd Update BaseProject
Signed-off-by: Florian Reuth <git@florianreuth.de>
2026-08-19 19:32:39 +02:00
Florian Reuth 7577279fcb Update GH files
Signed-off-by: Florian Reuth <git@florianreuth.de>
2026-08-19 19:29:40 +02:00
dependabot[bot] e3211f99ef [ci skip] Bump gradle-wrapper from 9.6.1 to 9.7.0 (#717)
Bumps [gradle-wrapper](https://github.com/gradle/gradle) from 9.6.1 to 9.7.0.
- [Release notes](https://github.com/gradle/gradle/releases)
- [Commits](https://github.com/gradle/gradle/compare/v9.6.1...v9.7.0)

---
updated-dependencies:
- dependency-name: gradle-wrapper
  dependency-version: 9.7.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-17 15:06:58 +02:00
Florian Reuth d562f9745a Update Via* API usage
Signed-off-by: Florian Reuth <git@florianreuth.de>
2026-08-13 17:48:09 +02:00
dependabot[bot] 7339df9fdb [ci skip] Bump gradle/actions/setup-gradle from 6.2.0 to 6.3.0 (#713)
Bumps [gradle/actions/setup-gradle](https://github.com/gradle/actions) from 6.2.0 to 6.3.0.
- [Release notes](https://github.com/gradle/actions/releases)
- [Commits](https://github.com/gradle/actions/compare/3f131e8634966bd73d06cc69884922b02e6faf92...9c971963bec38e04b3d30dcc455b5382be2fdbfb)

---
updated-dependencies:
- dependency-name: gradle/actions/setup-gradle
  dependency-version: 6.3.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-13 17:17:59 +02:00
dependabot[bot] d98d5bed9b [ci skip] Bump actions/setup-java from 5.6.0 to 5.7.0 (#715)
Bumps [actions/setup-java](https://github.com/actions/setup-java) from 5.6.0 to 5.7.0.
- [Release notes](https://github.com/actions/setup-java/releases)
- [Commits](https://github.com/actions/setup-java/compare/03ad4de0992f5dab5e18fcb136590ce7c4a0ac95...b6effb05e454b25005698d916606bdc6ffcbf961)

---
updated-dependencies:
- dependency-name: actions/setup-java
  dependency-version: 5.7.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-13 17:17:44 +02:00
dependabot[bot] 786529efbe [ci skip] Bump actions/setup-java from 5.5.0 to 5.6.0 (#712)
Bumps [actions/setup-java](https://github.com/actions/setup-java) from 5.5.0 to 5.6.0.
- [Release notes](https://github.com/actions/setup-java/releases)
- [Commits](https://github.com/actions/setup-java/compare/0f481fcb613427c0f801b606911222b5b6f3083a...03ad4de0992f5dab5e18fcb136590ce7c4a0ac95)

---
updated-dependencies:
- dependency-name: actions/setup-java
  dependency-version: 5.6.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-07-28 18:41:34 +02:00
dependabot[bot] 71546a7699 [ci skip] Bump actions/checkout from 7.0.0 to 7.0.1 (#711)
Bumps [actions/checkout](https://github.com/actions/checkout) from 7.0.0 to 7.0.1.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0...3d3c42e5aac5ba805825da76410c181273ba90b1)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-version: 7.0.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-07-28 18:41:24 +02:00
Term4andFlorian Reuth 9e7c853a5d Fix splash potions turning into drinkable potions in 1.9->1.8 (#703)
Co-authored-by: Florian Reuth <git@florianreuth.de>
2026-07-25 21:51:08 +02:00
315a1a0fab Handle single player inventory slot updates in 1.9->1.8 (#699)
Co-authored-by: Beanes <sikyserver@gmail.com>
Co-authored-by: Florian Reuth <git@florianreuth.de>
2026-07-25 21:27:09 +02:00
BeanesandFlorian Reuth 7a2898e44a Send server titles back to the client after cooldown visualization in 1.9->1.8 (#693)
Fixes https://github.com/ViaVersion/ViaRewind/issues/160

Co-authored-by: Florian Reuth <git@florianreuth.de>
2026-07-25 21:06:50 +02:00
Beanes 5783fa98e9 Queue teleport confirmation acks to match client behaviour in 1.9->1.8 (#704)
Fixes https://github.com/ViaVersion/ViaRewind/issues/469
2026-07-25 20:12:44 +02:00
Term4 77d9d9143e Fix double->int*32 conversion rounding in 1.9->1.8 (#707) 2026-07-25 20:11:19 +02:00
Term4 ede1920686 Fix use animation cancelling upon status updates in 1.9->1.8 (#708)
Fixes https://github.com/ViaVersion/ViaRewind/issues/520
2026-07-25 19:00:29 +02:00
dependabot[bot] 189249478f [ci skip] Bump actions/setup-java from 5.4.0 to 5.5.0 (#710)
Bumps [actions/setup-java](https://github.com/actions/setup-java) from 5.4.0 to 5.5.0.
- [Release notes](https://github.com/actions/setup-java/releases)
- [Commits](https://github.com/actions/setup-java/compare/1bcf9fb12cf4aa7d266a90ae39939e61372fe520...0f481fcb613427c0f801b606911222b5b6f3083a)

---
updated-dependencies:
- dependency-name: actions/setup-java
  dependency-version: 5.5.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-07-25 18:49:53 +02:00
dependabot[bot] 6c19760af6 Bump actions/setup-java from 5.3.0 to 5.4.0 (#705)
Bumps [actions/setup-java](https://github.com/actions/setup-java) from 5.3.0 to 5.4.0.
- [Release notes](https://github.com/actions/setup-java/releases)
- [Commits](https://github.com/actions/setup-java/compare/ad2b38190b15e4d6bdf0c97fb4fca8412226d287...1bcf9fb12cf4aa7d266a90ae39939e61372fe520)

---
updated-dependencies:
- dependency-name: actions/setup-java
  dependency-version: 5.4.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-07-12 20:22:51 +02:00
dependabot[bot] 69f8213445 Bump gradle-wrapper from 9.6.0 to 9.6.1 (#706)
Bumps [gradle-wrapper](https://github.com/gradle/gradle) from 9.6.0 to 9.6.1.
- [Release notes](https://github.com/gradle/gradle/releases)
- [Commits](https://github.com/gradle/gradle/compare/v9.6.0...v9.6.1)

---
updated-dependencies:
- dependency-name: gradle-wrapper
  dependency-version: 9.6.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-07-12 20:22:43 +02:00
Florian Reuth f95871bdc5 Start 4.1.4 cycle
Signed-off-by: Florian Reuth <git@florianreuth.de>
2026-07-12 20:18:36 +02:00
Florian Reuth 7d6c75ad31 ViaRewind 4.1.3
Signed-off-by: Florian Reuth <git@florianreuth.de>
2026-07-12 20:13:54 +02:00
Nassim Jahnke 0bb7be88ff Update mapping files 2026-07-12 11:05:47 +02:00
Nassim Jahnke 4b7264c944 Update VV usage 2026-07-09 15:22:35 +02:00
Beanes db6afa5b1b Fix potential 1.7 teleport confirmation desync (#695) 2026-07-02 16:21:32 +02:00
Beanes 02f55edb0c Fix edge cases with chat newline rewriter; make it more like vanilla (#696) 2026-07-02 16:14:48 +02:00
dependabot[bot] 5ef900a61e [ci skip] Bump actions/checkout from 6.0.3 to 7.0.0 (#701)
Bumps [actions/checkout](https://github.com/actions/checkout) from 6.0.3 to 7.0.0.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/df4cb1c069e1874edd31b4311f1884172cec0e10...9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-version: 7.0.0
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-07-02 15:32:45 +02:00
dependabot[bot] 4fe7e35f6b [ci skip] Bump gradle-wrapper from 9.5.1 to 9.6.0 (#700)
Bumps [gradle-wrapper](https://github.com/gradle/gradle) from 9.5.1 to 9.6.0.
- [Release notes](https://github.com/gradle/gradle/releases)
- [Commits](https://github.com/gradle/gradle/compare/v9.5.1...v9.6.0)

---
updated-dependencies:
- dependency-name: gradle-wrapper
  dependency-version: 9.6.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-07-02 15:32:30 +02:00
dependabot[bot] 1af08ced41 [ci skip] Bump actions/setup-java from 5.2.0 to 5.3.0 (#702)
Bumps [actions/setup-java](https://github.com/actions/setup-java) from 5.2.0 to 5.3.0.
- [Release notes](https://github.com/actions/setup-java/releases)
- [Commits](https://github.com/actions/setup-java/compare/be666c2fcd27ec809703dec50e508c2fdc7f6654...ad2b38190b15e4d6bdf0c97fb4fca8412226d287)

---
updated-dependencies:
- dependency-name: actions/setup-java
  dependency-version: 5.3.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-07-02 15:32:20 +02:00
Nassim Jahnke fd1d3ed221 Update VV use 2026-07-01 21:05:36 +02:00
dependabot[bot] 1d6ef8833f [ci skip] Bump gradle/actions from 6.1.0 to 6.2.0 (#698)
Bumps [gradle/actions](https://github.com/gradle/actions) from 6.1.0 to 6.2.0.
- [Release notes](https://github.com/gradle/actions/releases)
- [Commits](https://github.com/gradle/actions/compare/50e97c2cd7a37755bbfafc9c5b7cafaece252f6e...3f131e8634966bd73d06cc69884922b02e6faf92)

---
updated-dependencies:
- dependency-name: gradle/actions
  dependency-version: 6.2.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-06-24 05:15:50 +02:00
Beanes f2e2f18511 Fix custom sound handling in 1.9->1.8 (#691) 2026-06-20 00:16:36 +02:00
Florian Reuth 2adf7757f0 Start 4.1.3 cycle
Signed-off-by: Florian Reuth <git@florianreuth.de>
2026-06-20 00:13:53 +02:00
Florian Reuth 4dd3de2ce9 ViaRewind 4.1.2
Signed-off-by: Florian Reuth <git@florianreuth.de>
2026-06-19 21:52:24 +02:00
Florian Reuth ddbdbdb1cc Cleanup code to reproduce the original tag
Signed-off-by: Florian Reuth <git@florianreuth.de>
2026-06-19 21:45:16 +02:00
Beanes 28b4998912 Use gray color for elytra & brown color for shield in 1.9->1.8 (#688) 2026-06-19 21:38:32 +02:00
Beanes f9b0fd5c5a Custom payload fixes (#687)
* Fix remaining bytes issue of 1.7.10 custom payload

* Properly rewrite 1.7 books to 1.8 books

* Small code cleanup
2026-06-19 21:35:54 +02:00
Florian Reuth a676368588 26.2 2026-06-19 21:32:14 +02:00
Beanes 966231ad1c Null check storages in global tasks (#690)
Fixes https://github.com/ViaVersion/ViaRewind/issues/564
Fixes https://github.com/ViaVersion/ViaRewind/issues/680
2026-06-19 21:21:00 +02:00
dependabot[bot] d73c2198ea [ci skip] Bump actions/checkout from 6.0.2 to 6.0.3 (#686)
Bumps [actions/checkout](https://github.com/actions/checkout) from 6.0.2 to 6.0.3.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/de0fac2e4500dabe0009e67214ff5f5447ce83dd...df4cb1c069e1874edd31b4311f1884172cec0e10)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-version: 6.0.3
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-06-18 21:57:00 +02:00
Florian Reuth 6f319932be Start 4.1.2 cycle 2026-06-09 20:50:39 +02:00
Beanes f172de2742 Rewrite to direct chunk buffer handling in 1.8->1.7 (#670)
* Use netty directly for chunks in 1.8->1.7, additionally support native compression by velocity for 1.7 chunk compression

* Refactor the velocity code a bit
2026-06-09 20:49:09 +02:00
dependabot[bot] ca25da9445 [ci skip] Bump gradle-wrapper from 9.5.0 to 9.5.1 (#683)
Bumps [gradle-wrapper](https://github.com/gradle/gradle) from 9.5.0 to 9.5.1.
- [Release notes](https://github.com/gradle/gradle/releases)
- [Commits](https://github.com/gradle/gradle/compare/v9.5.0...v9.5.1)

---
updated-dependencies:
- dependency-name: gradle-wrapper
  dependency-version: 9.5.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-06-07 01:41:05 +02:00
dependabot[bot] ea548dfd91 [ci skip] Bump gradle-wrapper from 9.4.1 to 9.5.0 (#681)
Bumps [gradle-wrapper](https://github.com/gradle/gradle) from 9.4.1 to 9.5.0.
- [Release notes](https://github.com/gradle/gradle/releases)
- [Commits](https://github.com/gradle/gradle/compare/v9.4.1...v9.5.0)

---
updated-dependencies:
- dependency-name: gradle-wrapper
  dependency-version: 9.5.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-05-05 20:48:44 +02:00
Florian Reuth d0561f2e19 ViaRewind 4.1.1 2026-05-05 20:42:51 +02:00
Beanes 2c8189a447 Fix edge case when server sends a useless packet (#679) 2026-04-28 23:06:11 +02:00
Beanes 48c9e45bcf Also rewrite extra entity ids for other interaction modes (#678) 2026-04-26 16:56:26 +02:00
Gabik21 ecb4f4bf00 Fix nametag visibility duplicate names edge case (#675) 2026-04-24 21:34:24 +02:00
Kichura 6ea9377622 [ci skip] Fix version comments, Unsubscribe from proprietary caching tier. (#677) 2026-04-24 21:34:05 +02:00
Beanes b789fdebb7 Fix set score packet crashing (#674) 2026-04-22 15:16:00 +02:00
Beanes e7b0606e18 Rewrite "no face" in digging packet to a valid 1.8 value (#673) 2026-04-22 13:43:35 +02:00
NotAlexNoyle bf490c3805 Fix brewing stand titles for 1.8 clients on 1.9+ servers (#672) 2026-04-20 22:10:04 +02:00
Florian Reuth 7ca7078141 Start 4.1.1 cycle
Signed-off-by: Florian Reuth <git@florianreuth.de>
2026-04-20 22:09:12 +02:00
Florian Reuth 170af55f91 ViaRewind 4.1.0
Signed-off-by: Florian Reuth <git@florianreuth.de>
2026-04-20 21:15:13 +02:00
dependabot[bot] 00d82f9f2f [ci skip] Bump actions/upload-artifact from 7.0.0 to 7.0.1 (#671)
Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 7.0.0 to 7.0.1.
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](https://github.com/actions/upload-artifact/compare/bbbca2ddaa5d8feaa63e36b76fdaad77386f024f...043fb46d1a93c77aae656e7c1c64a875d1fc6a0a)

---
updated-dependencies:
- dependency-name: actions/upload-artifact
  dependency-version: 7.0.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-20 21:13:24 +02:00
Beanes 79ef613c15 Implement invisible name tag tracking in 1.8->1.7 (#666)
Fixes https://github.com/ViaVersion/ViaRewind/issues/518
Fixes https://github.com/ViaVersion/ViaRewind/issues/364
2026-04-19 21:58:18 +02:00
Beanes e2fcbafc70 Improve hologram emulation in 1.8->1.7 (#667)
* Fix metadata flags not saving cross packets syncing

* Fix marker zombie no gravity offsets

* Improve interaction by rewriting "extra" entity ids of holograms to normal hologram id
2026-04-19 17:40:18 +02:00
dependabot[bot] 9ae46145e5 [ci skip] Bump gradle/actions from 5.0.2 to 6.1.0 (#669)
Bumps [gradle/actions](https://github.com/gradle/actions) from 5.0.2 to 6.1.0.
- [Release notes](https://github.com/gradle/actions/releases)
- [Commits](https://github.com/gradle/actions/compare/0723195856401067f7a2779048b490ace7a47d7c...50e97c2cd7a37755bbfafc9c5b7cafaece252f6e)

---
updated-dependencies:
- dependency-name: gradle/actions
  dependency-version: 6.1.0
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-19 17:27:54 +02:00
dependabot[bot] 76f90b68b8 Bump de.florianreuth.baseproject from 2.0.1 to 2.0.2 (#665)
Bumps de.florianreuth.baseproject from 2.0.1 to 2.0.2.

---
updated-dependencies:
- dependency-name: de.florianreuth.baseproject
  dependency-version: 2.0.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-09 17:59:11 +02:00
Florian Reuth 32a2ee6bfa 26.1.2
Signed-off-by: Florian Reuth <git@florianreuth.de>
2026-04-09 17:54:37 +02:00
Florian Reuth 04878b7e34 26.1.1
Signed-off-by: Florian Reuth <git@florianreuth.de>
2026-04-02 20:50:46 +02:00
Florian Reuth adccdc4b41 26.1
Signed-off-by: Florian Reuth <git@florianreuth.de>
2026-03-27 17:39:20 +01:00
dependabot[bot] 0accea66f2 Bump gradle-wrapper from 9.4.0 to 9.4.1 (#662)
Bumps [gradle-wrapper](https://github.com/gradle/gradle) from 9.4.0 to 9.4.1.
- [Release notes](https://github.com/gradle/gradle/releases)
- [Commits](https://github.com/gradle/gradle/compare/v9.4.0...v9.4.1)

---
updated-dependencies:
- dependency-name: gradle-wrapper
  dependency-version: 9.4.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-26 16:11:29 +01:00
dependabot[bot] 65257be3ee Bump actions/upload-artifact from 6.0.0 to 7.0.0 (#658)
Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 6.0.0 to 7.0.0.
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](https://github.com/actions/upload-artifact/compare/b7c566a772e6b6bfb58ed0dc250532a479d7789f...bbbca2ddaa5d8feaa63e36b76fdaad77386f024f)

---
updated-dependencies:
- dependency-name: actions/upload-artifact
  dependency-version: 7.0.0
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-11 21:58:54 +01:00
dependabot[bot] 880e879dce Bump gradle/actions from 5.0.1 to 5.0.2 (#659)
Bumps [gradle/actions](https://github.com/gradle/actions) from 5.0.1 to 5.0.2.
- [Release notes](https://github.com/gradle/actions/releases)
- [Commits](https://github.com/gradle/actions/compare/f29f5a9d7b09a7c6b29859002d29d24e1674c884...0723195856401067f7a2779048b490ace7a47d7c)

---
updated-dependencies:
- dependency-name: gradle/actions
  dependency-version: 5.0.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-11 21:58:46 +01:00
dependabot[bot] 0ccc6a0923 Bump gradle-wrapper from 9.3.1 to 9.4.0 (#660)
Bumps gradle-wrapper from 9.3.1 to 9.4.0.

---
updated-dependencies:
- dependency-name: gradle-wrapper
  dependency-version: 9.4.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-11 21:58:40 +01:00
dependabot[bot] 7bff361e14 Bump de.florianreuth.baseproject from 2.0.0 to 2.0.1 (#657)
Bumps de.florianreuth.baseproject from 2.0.0 to 2.0.1.

---
updated-dependencies:
- dependency-name: de.florianreuth.baseproject
  dependency-version: 2.0.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-03 20:34:07 +01:00
Florian Reuth c2c28473cc Start 4.1.0 cycle
Signed-off-by: Florian Reuth <git@florianreuth.de>
2026-03-01 18:10:12 +01:00
Florian Reuth 048d502998 ViaRewind 4.0.15
Signed-off-by: Florian Reuth <git@florianreuth.de>
2026-03-01 18:05:34 +01:00
Beanes e0c1f53115 Manually split newlines in chat messages in 1.8->1.7 (#655) 2026-02-16 17:55:48 +01:00
dependabot[bot] e5313a466b Bump gradle/actions from 5.0.0 to 5.0.1 (#654)
Bumps [gradle/actions](https://github.com/gradle/actions) from 5.0.0 to 5.0.1.
- [Release notes](https://github.com/gradle/actions/releases)
- [Commits](https://github.com/gradle/actions/compare/4d9f0ba0025fe599b4ebab900eb7f3a1d93ef4c2...f29f5a9d7b09a7c6b29859002d29d24e1674c884)

---
updated-dependencies:
- dependency-name: gradle/actions
  dependency-version: 5.0.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-02-12 15:20:14 +01:00
dependabot[bot] e30633e367 Bump gradle-wrapper from 9.3.0 to 9.3.1 (#653)
Bumps gradle-wrapper from 9.3.0 to 9.3.1.

---
updated-dependencies:
- dependency-name: gradle-wrapper
  dependency-version: 9.3.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-02-07 16:04:17 +01:00
Florian Reuth a443dd5d11 Update my name
Signed-off-by: Florian Reuth <git@florianreuth.de>
2026-02-07 16:00:19 +01:00
dependabot[bot] 3820426bce Bump actions/setup-java from 5.1.0 to 5.2.0 (#651)
Bumps [actions/setup-java](https://github.com/actions/setup-java) from 5.1.0 to 5.2.0.
- [Release notes](https://github.com/actions/setup-java/releases)
- [Commits](https://github.com/actions/setup-java/compare/f2beeb24e141e01a676f977032f5a29d81c9e27e...be666c2fcd27ec809703dec50e508c2fdc7f6654)

---
updated-dependencies:
- dependency-name: actions/setup-java
  dependency-version: 5.2.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-02-03 16:32:51 +01:00
Beanes 031ae32f27 Only set hologram state if name tag is visible (#652) 2026-02-03 16:32:38 +01:00
FlorianMichael e83616139e Update supported Velocity versions
Signed-off-by: FlorianMichael <git@florianmichael.de>
2026-01-31 20:16:07 +01:00
dependabot[bot] 7325b733d6 Bump actions/checkout from 6.0.1 to 6.0.2 (#650)
Bumps [actions/checkout](https://github.com/actions/checkout) from 6.0.1 to 6.0.2.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/8e8c483db84b4bee98b60c0593521ed34d9990e8...de0fac2e4500dabe0009e67214ff5f5447ce83dd)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-version: 6.0.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-01-27 10:57:27 +01:00
Alessandro e64501eae8 Fix red sandstone stairs rotation in 1.8->1.7 (#649) 2026-01-25 17:09:32 +01:00
FlorianMichael 2d99607c35 Start 4.0.15 cycle
Signed-off-by: FlorianMichael <git@florianmichael.de>
2026-01-18 16:31:36 +01:00
FlorianMichael 4d159189c0 ViaRewind 4.0.14
Signed-off-by: FlorianMichael <git@florianmichael.de>
2026-01-18 16:19:42 +01:00
FlorianMichael 2076294856 Gradle 9.3.0
Signed-off-by: FlorianMichael <git@florianmichael.de>
2026-01-18 13:36:11 +01:00
FlorianMichael 49f7bd22be Add default impl class 2026-01-17 14:19:49 +01:00
FlorianMichael 298605874d Remove special sign component type 2026-01-10 00:39:23 +01:00
BeanesandFlorianMichael 35b94f1878 Use velocity native compression if available (#647)
* Optimize 1.7 compression by using velocity-native compressor

* Rewrite 1.7 chunk serializing to reduce allocations

* Don't include velocity native as shaded dependency, add fallback and only use velocity compression if available

* Change chunk compression back to default java as chunks are serialized on heap byte arrays so native compression has no use

* Move velocity only code in custom decoder/encoder overrides

* Remove debug

* Move compression into non static context

---------

Co-authored-by: FlorianMichael <git@florianmichael.de>
2026-01-06 03:25:48 +01:00
FlorianMichael 37955059c4 Don't require config impl class in ViaRewindPlatform#init 2026-01-04 13:01:44 +01:00
FlorianMichael af4306bc81 Start 4.0.14 cycle 2025-12-29 15:08:09 +01:00
FlorianMichael 98ca00f625 ViaRewind 4.0.13 2025-12-29 15:04:19 +01:00
dependabot[bot] 598804432b Bump actions/upload-artifact from 5.0.0 to 6.0.0 (#648)
Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 5.0.0 to 6.0.0.
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](https://github.com/actions/upload-artifact/compare/330a01c490aca151604b8cf639adc76d48f6c5d4...b7c566a772e6b6bfb58ed0dc250532a479d7789f)

---
updated-dependencies:
- dependency-name: actions/upload-artifact
  dependency-version: 6.0.0
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-12-29 14:30:50 +01:00
FlorianMichael 92bae0a5c4 Update VV API usage 2025-12-29 14:23:20 +01:00
FlorianMichael d50b6a2f89 Prepare for next year (2026) 2025-12-29 00:12:28 +01:00
Kichura 54cc085717 Change schedule's interval to monthly. (#633) 2025-12-20 14:30:53 +01:00
dependabot[bot] bd0d4c31b2 Bump actions/checkout from 6.0.0 to 6.0.1 (#644)
Bumps [actions/checkout](https://github.com/actions/checkout) from 6.0.0 to 6.0.1.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/1af3b93b6815bc44a9784bd300feb67ff0d1eeb3...8e8c483db84b4bee98b60c0593521ed34d9990e8)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-version: 6.0.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-12-15 21:41:52 +01:00
dependabot[bot] 705c88f4b3 Bump actions/setup-java from 5.0.0 to 5.1.0 (#645)
Bumps [actions/setup-java](https://github.com/actions/setup-java) from 5.0.0 to 5.1.0.
- [Release notes](https://github.com/actions/setup-java/releases)
- [Commits](https://github.com/actions/setup-java/compare/dded0888837ed1f317902acf8a20df0ad188d165...f2beeb24e141e01a676f977032f5a29d81c9e27e)

---
updated-dependencies:
- dependency-name: actions/setup-java
  dependency-version: 5.1.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-12-15 21:41:45 +01:00
FlorianMichael 7306a795b9 [ci skip] Include the newest ViaProxy version from 3.0.0 to 4.0.0 2025-12-13 20:00:44 +01:00
FlorianMichael dfdfad4bfc Add ViaRewindPlatform#init with config instance 2025-12-13 19:59:51 +01:00
FlorianMichael c87654848d Start 4.0.13 cycle 2025-12-12 16:08:44 +01:00
FlorianMichael 08a7077d10 ViaRewind 4.0.12 2025-12-12 16:04:46 +01:00
dependabot[bot] 73afaaf493 Bump io.papermc.hangar-publish-plugin from 0.1.3 to 0.1.4 (#636)
Bumps io.papermc.hangar-publish-plugin from 0.1.3 to 0.1.4.

---
updated-dependencies:
- dependency-name: io.papermc.hangar-publish-plugin
  dependency-version: 0.1.4
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-12-12 14:29:12 +01:00
dependabot[bot] f0f8038b18 Bump de.florianmichael.baseproject.BaseProject from 1.2.5 to 1.2.6 (#631)
Bumps de.florianmichael.baseproject.BaseProject from 1.2.5 to 1.2.6.

---
updated-dependencies:
- dependency-name: de.florianmichael.baseproject.BaseProject
  dependency-version: 1.2.6
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-11-29 23:11:31 +01:00
Kichura 540c0d0d47 Mitigate security vulnerabilities in CI. (#632) 2025-11-29 23:10:32 +01:00
dependabot[bot] d00b0c8afe Bump de.florianmichael.baseproject.BaseProject from 1.2.4 to 1.2.5 (#628)
Bumps de.florianmichael.baseproject.BaseProject from 1.2.4 to 1.2.5.

---
updated-dependencies:
- dependency-name: de.florianmichael.baseproject.BaseProject
  dependency-version: 1.2.5
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-11-24 21:59:31 +01:00
dependabot[bot] b34385c09e Bump actions/checkout from 5 to 6 (#630)
Bumps [actions/checkout](https://github.com/actions/checkout) from 5 to 6.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/v5...v6)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-version: '6'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-11-24 21:59:24 +01:00
FlorianMichael ff47845df1 Gradle 9.2.0 2025-11-03 16:18:55 +01:00
FlorianMichael fc37b9c0ba Only send start fall flying if player has elytra on chestplate in 1.9->1.8
Closes https://github.com/ViaVersion/ViaRewind/pull/625
2025-10-29 15:28:17 +01:00
FlorianMichael e3baafa2a2 4.0.11 Release 2025-10-12 19:05:30 +02:00
Nassim Jahnke 11914da37e Use VV contained sound mappings in 1.9->1.8 2025-10-12 13:58:31 +02:00
FlorianMichael 30fa58af81 Fix boat y offset in 1.9->1.8 2025-10-09 21:40:47 +02:00
dependabot[bot] 52b6aed005 Bump de.florianmichael.baseproject.BaseProject from 1.2.2 to 1.2.3 (#620)
Bumps de.florianmichael.baseproject.BaseProject from 1.2.2 to 1.2.3.

---
updated-dependencies:
- dependency-name: de.florianmichael.baseproject.BaseProject
  dependency-version: 1.2.3
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-10-07 17:51:03 +02:00
dependabot[bot] 9d74706e84 Bump gradle/actions from 4 to 5 (#621)
Bumps [gradle/actions](https://github.com/gradle/actions) from 4 to 5.
- [Release notes](https://github.com/gradle/actions/releases)
- [Commits](https://github.com/gradle/actions/compare/v4...v5)

---
updated-dependencies:
- dependency-name: gradle/actions
  dependency-version: '5'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-10-07 17:50:55 +02:00
FlorianMichael 7d5ad45ffc Update VV api usage 2025-10-07 17:50:24 +02:00
FlorianMichael bd3593e15a 4.0.10 Release 2025-10-03 13:54:15 +02:00
FlorianMichael 835fb5de08 Update VV api usage 2025-09-30 19:57:11 +02:00
FlorianMichael 8b2769f19b Don't include subprojects as dependencies in the root project 2025-09-25 21:03:21 +02:00
FlorianMichael 4da08b5a35 Auto: Gradle 9.1.0 2025-09-22 21:46:11 +02:00
dependabot[bot] 7da8e62a39 Bump actions/setup-java from 4 to 5 (#619)
Bumps [actions/setup-java](https://github.com/actions/setup-java) from 4 to 5.
- [Release notes](https://github.com/actions/setup-java/releases)
- [Commits](https://github.com/actions/setup-java/compare/v4...v5)

---
updated-dependencies:
- dependency-name: actions/setup-java
  dependency-version: '5'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-08-30 18:26:38 +02:00
FlorianMichael 31c62f96b9 [ci skip] Fix SECURITY.md formatting 2025-08-12 06:05:37 +02:00
FlorianMichael 0f866d8b50 Fix sign update component read types in 1.7<->1.9
Closes https://github.com/ViaVersion/ViaRewind/issues/613
2025-08-12 06:02:30 +02:00
dependabot[bot] 32d265116a [ci skip] Bump actions/checkout from 4 to 5 (#617)
Bumps [actions/checkout](https://github.com/actions/checkout) from 4 to 5.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/v4...v5)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-version: '5'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-08-12 05:50:50 +02:00
dependabot[bot] b7d1197be3 [ci skip] Bump de.florianmichael.baseproject.BaseProject from 1.1.1 to 1.2.1 (#614)
Bumps de.florianmichael.baseproject.BaseProject from 1.1.1 to 1.2.1.

---
updated-dependencies:
- dependency-name: de.florianmichael.baseproject.BaseProject
  dependency-version: 1.2.1
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-08-08 02:08:39 +02:00
FlorianMichael d4363b67b6 Gradle 9.0.0 2025-08-03 01:35:34 +02:00
FlorianMichael dcdce8ad52 4.0.9 Release 2025-07-27 14:51:16 +02:00
Ambassator af44f88d6e Remove the wither outline when using the bossbar on 1.9->1.8 (#604)
Adds metadata to the spawn packet to make the wither tiny so the player doesn't see a wither outline when the bossbar is on low health
2025-07-27 14:27:06 +02:00
Beanes 1d1d77abfd Add support for armor stands with no gravity as zombie in 1.8->1.7 (#609) 2025-07-27 14:24:06 +02:00
BeanesandFlorianMichael ae800f16be Basic chat item handling in 1.8->1.7 (#606)
This is still missing most packets and should one day be moved into a proper component rewriter, but this works for now.


Co-authored-by: FlorianMichael <florian.michael07@gmail.com>
2025-07-27 14:17:55 +02:00
BeanesandFlorianMichael f31d731f34 Cleanup player info logic 1.8->1.7 (#608)
* Cleanup player info logic

* Don't update ping if it's the same

* Cleanup

---------

Co-authored-by: FlorianMichael <florian.michael07@gmail.com>
2025-07-26 20:10:15 +02:00
Beanes 2ddd0d8b66 [ci skip] Clarify respawn metadata resending (#612) 2025-07-26 13:43:57 +02:00
BeanesandFlorianMichael f97884158b Implement play state compression and handle compression being set twice (#607)
* Implement play state compression and handle compression being set twice

* Fix 0 threshold; Code cleanup

---------

Co-authored-by: FlorianMichael <florian.michael07@gmail.com>
2025-07-25 20:57:49 +02:00
FlorianMichael 1e2fcb9c58 [ci skip] Reformat all classes 2025-07-25 11:26:09 +02:00
FlorianMichael 5110326a90 Aggressively validate sign update component 2025-07-25 11:20:40 +02:00
FlorianMichael 6887556b2c [ci skip] Add SECURITY.md 2025-07-25 08:37:43 +02:00
LabyStudio 66cf650d36 Limit legacy string trimming (#605) 2025-07-25 08:36:05 +02:00
FlorianMichael 1426631c97 [ci skip] Update ViaProxy 2025-07-24 20:15:40 +02:00
EthanKeating b6a32823cc Fix hologram height offsets in 1.8->1.7 (#601) 2025-07-23 18:27:28 +02:00
EthanKeatingandFlorianMichael aff88a6ca3 Fix respawn screen appearing twice in 1.8->1.7 (#597)
* Fixed double respawn screen displaying

* Only remove, don't re-add

---------

Co-authored-by: FlorianMichael <florian.michael07@gmail.com>
2025-07-22 16:32:49 +02:00
FlorianMichaelandNassim Jahnke 0edfd844b9 [ci skip] Split up publishing steps
Co-authored-by: Nassim Jahnke <nassim@njahnke.dev>
2025-07-22 16:26:41 +02:00
FlorianMichael 57a64740aa [ci skip] Mark 1.21.8 release 2025-07-17 21:27:26 +02:00
EthanKeating f7903050bf Update ping value in player list entry instead of sending a new one in 1.8->1.7 (#599) 2025-07-14 00:18:29 +02:00
EthanKeatingandEnZaXD 3a7ac0765b Also pass sneaking through hologram emulation; fix attachments 1.8->1.7 (#598)
* Fixed holograms flying up + Hologram sneaking

* Code cleanup

---------

Co-authored-by: EnZaXD <florian.michael07@gmail.com>
2025-07-13 21:13:47 +02:00
FlorianMichael 48f500a470 Copy over always show nametag 1:1 2025-07-13 21:00:22 +02:00
EthanKeating c3e19b769b Don't drop alwaysShowNametag entity data in hologram emulation 1.8->1.7 (#600) 2025-07-13 20:49:05 +02:00
dependabot[bot] 561829d952 Bump net.raphimc.class-token-replacer from 1.1.6 to 1.1.7 (#594)
Bumps net.raphimc.class-token-replacer from 1.1.6 to 1.1.7.

---
updated-dependencies:
- dependency-name: net.raphimc.class-token-replacer
  dependency-version: 1.1.7
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-06-30 21:04:07 +02:00
FlorianMichael 6767379526 Mark 1.21.7 release 2025-06-30 21:02:49 +02:00
mariaum a10ce1f35f Remap yaw values correctly when teleporting entities in 1.9->1.8 (#585) 2025-06-27 02:40:40 +02:00
FlorianMichael 49f0c673e6 Bump version to 4.0.9-SNAPSHOT 2025-06-27 02:39:00 +02:00
dependabot[bot] fd2c81a6fd [ci skip] Bump de.florianmichael.baseproject.BaseProject from 1.0.7 to 1.1.1 (#588)
Bumps de.florianmichael.baseproject.BaseProject from 1.0.7 to 1.1.1.

---
updated-dependencies:
- dependency-name: de.florianmichael.baseproject.BaseProject
  dependency-version: 1.1.1
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-06-27 02:10:49 +02:00
FlorianMichael 901463e095 4.0.8 Release 2025-06-20 20:11:01 +02:00
FlorianMichael 227d37b2b9 Update VV api usage 2025-06-16 18:27:46 +02:00
FlorianMichael be5bb6e07c Write flags as byte in PLAYER_INPUT 1.8->1.7 2025-06-10 20:16:14 +02:00
Nassim Jahnke 064dbee920 Update profile properties type 2025-05-26 17:32:13 +02:00
FlorianMichael 783006baa5 Auto: Gradle 8.14.1 2025-05-22 17:51:04 +02:00
Adrian ba93a40d22 Change end rod block state mapping to white stained glass in 1.9->1.8 (#584) 2025-05-22 00:18:48 +02:00
dependabot[bot] 422f81dd2e Bump org.gradle.toolchains.foojay-resolver-convention (#583)
Bumps org.gradle.toolchains.foojay-resolver-convention from 0.10.0 to 1.0.0.

---
updated-dependencies:
- dependency-name: org.gradle.toolchains.foojay-resolver-convention
  dependency-version: 1.0.0
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-22 00:12:32 +02:00
FlorianMichael aa47e3c0a5 Update BaseProject 2025-05-19 00:12:39 +02:00
FlorianMichael 094298771e Update ClassTokenReplacer 2025-05-17 17:57:07 +02:00
FlorianMichael 66133d1ccc Update VV api usage 2025-05-17 15:37:37 +02:00
FlorianMichael 11011d59aa Rewrite build files 2025-05-15 15:28:44 +02:00
FlorianMichael 691cbf1b2a Small cleanup 2025-05-15 11:18:26 +02:00
EthanKeating 8d8675a891 Fix hologram movement by wrapping them to an interpolated entity in 1.8->1.7 (#580)
* Hologram movement fix for 1.7 clients

* fix: addressed feedback from PR review
2025-05-15 08:26:12 +02:00
Beanes 4fa2f10f3a Use correct entity id data type in 1.8->1.7 entity data sending (#579) 2025-05-08 20:24:50 +02:00
FlorianMichael c2e516dcd2 Auto: Gradle 8.14 2025-04-26 16:25:07 +02:00
BeanesandFlorianMichael 153eedd5eb Optimize memory usage for 1.7 chunk rewriting (#577)
* Optimize memory usage

* Bump version; cleanup code

---------

Co-authored-by: FlorianMichael <florian.michael07@gmail.com>
2025-04-22 23:52:39 +02:00
FlorianMichael 2d404608ee [ci skip] Reformat GH issue templates 2025-04-20 14:41:56 +02:00
FlorianMichael bbc1d77939 4.0.7 Release 2025-03-31 01:08:03 +02:00
dependabot[bot] fa36428391 Bump io.papermc.hangar-publish-plugin from 0.1.2 to 0.1.3 (#568)
Bumps io.papermc.hangar-publish-plugin from 0.1.2 to 0.1.3.

---
updated-dependencies:
- dependency-name: io.papermc.hangar-publish-plugin
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-29 14:47:08 +01:00
FlorianMichael b6dee43620 Update VV api usage 2025-03-29 14:46:44 +01:00
FlorianMichael 371c25f9d0 Update MCStructs to 3.0.0 2025-03-29 14:46:14 +01:00
FlorianMichael a41bbc2d67 4.0.6 Release 2025-03-28 19:07:24 +01:00
Nassim Jahnke de84a8fffc Replace deprecated class use 2025-03-26 13:47:29 +01:00
Nassim Jahnke 22ff1416c2 Fix serverbound container_close container types
Fixes #566
2025-03-13 13:58:14 +01:00
FlorianMichael 00b74ef2dd Update container id types 2025-03-12 18:31:20 +01:00
FlorianMichael 8d5b348318 Fix data field getting in ADD_ENTITY handler in 1.9->1.8 2025-03-09 01:06:11 +01:00
FlorianMichael 51f001ac3e Don't use -1 as indicator in EntityTracker1_9#getVehicle 2025-02-26 20:21:50 +01:00
FlorianMichael e27caba231 Cleanup code here and there 2025-02-25 21:40:03 +01:00
FlorianMichael 07aab015ea Auto: Gradle 8.13, .editorconfig 2025-02-25 18:44:28 +01:00
FlorianMichael 6bcf8d8895 Update ViaProxy, exclude run folder in .gitignore 2025-02-12 16:28:41 +01:00
FlorianMichael 43c42f44f6 Move handler names to the platform
As needs platform handling it should be directly exposed to the wrapper rather than being in the storage
2025-02-12 16:25:37 +01:00
FlorianMichael 295d87d49f Add functions to allow changing the handler names in TrackingCompressionHandlerProvider 2025-01-28 19:01:45 +01:00
FlorianMichael ab97e248da Auto: Gradle 8.12.1 2025-01-24 15:44:23 +01:00
FlorianMichael 276b9ba386 Update VV API usage 2025-01-10 22:44:59 +01:00
FlorianMichael 351ff79187 4.0.5 Release 2025-01-01 21:29:53 +01:00
FlorianMichael 87ed2160c9 Auto: 2025 2025-01-01 01:07:59 +01:00
FlorianMichael 668ed3c455 Auto: Gradle 8.12 2024-12-22 02:12:08 +01:00
FlorianMichael 3a0c742878 Auto: Migrate to setup-gradle action 2024-12-17 00:29:36 +01:00
FlorianMichael bc7b33f28a Handle unknown entity types correctly 2024-12-16 01:27:26 +01:00
FlorianMichael 657dcaa682 Do not persist credentials 2024-12-15 18:05:25 +01:00
FlorianMichael 3676906fbf Remove wiki.vg references 2024-12-13 22:50:24 +01:00
FlorianMichael dc9dbe9900 Bump version to 4.0.5-SNAPSHOT 2024-12-13 22:50:06 +01:00
FlorianMichael d8924485ac 4.0.4 Release 2024-12-06 16:34:00 +01:00
LeeGod b02a257383 Fix data loose in enchantment table item rewriting in 1.8->1.7 (#554) 2024-12-03 21:24:29 +01:00
FlorianMichael a4b666724f Use correct array type for reading passengers in 1.9->1.8
Closes https://github.com/ViaVersion/ViaRewind/issues/552
2024-11-27 21:51:25 +01:00
github-actions[bot]andgradle-update-robot e92b15c19f Update Gradle Wrapper from 8.11 to 8.11.1 (#551)
Signed-off-by: gradle-update-robot <gradle-update-robot@regolo.cc>
Co-authored-by: gradle-update-robot <gradle-update-robot@regolo.cc>
2024-11-24 02:04:41 +01:00
3fd2da9bf8 Update Gradle Wrapper from 8.10.2 to 8.11 (#549)
* Update Gradle Wrapper from 8.10.2 to 8.11

Signed-off-by: gradle-update-robot <gradle-update-robot@regolo.cc>

* Update Gradle API usage

---------

Signed-off-by: gradle-update-robot <gradle-update-robot@regolo.cc>
Co-authored-by: gradle-update-robot <gradle-update-robot@regolo.cc>
Co-authored-by: FlorianMichael <florian.michael07@gmail.com>
2024-11-14 23:28:48 +01:00
FlorianMichael ff4fbe2029 Bump version to 4.0.4-SNAPSHOT 2024-11-07 19:25:17 +01:00
Remigio c3d32874a7 Correct wrong name in plugin.yml (#548) 2024-11-07 19:24:04 +01:00
FlorianMichael 7b9888c758 [ci skip] Add gradle task to quickly test/debug code changes 2024-10-31 21:27:50 +01:00
FlorianMichael e0c05df633 [ci skip] Update version ranges in gradle.properties 2024-10-23 15:49:10 +02:00
FlorianMichael 3af661b256 4.0.3 Release 2024-10-14 17:26:28 +02:00
FlorianMichael 74ebb09ebc Update required ViaFabric version, don't require fabric-loader 2024-10-10 15:44:20 +02:00
FlorianMichael 36396c10b0 Define as Sponge plugin for ViaSponge 2024-10-03 18:59:02 +02:00
github-actions[bot]andgradle-update-robot bc9b84464b Update Gradle Wrapper from 8.10.1 to 8.10.2 (#544)
Signed-off-by: gradle-update-robot <gradle-update-robot@regolo.cc>
Co-authored-by: gradle-update-robot <gradle-update-robot@regolo.cc>
2024-09-29 04:21:22 +02:00
FlorianMichaelandBT (calcastor/mame) 0ee7c1cf16 Update correct entity data list in 1.8->1.7
Co-authored-by: "BT (calcastor/mame)" <43831917+calcastor@users.noreply.github.com>
2024-09-26 15:08:18 +02:00
dependabot[bot] 6d35536862 Bump gradle-update/update-gradle-wrapper-action from 1 to 2 (#542)
Bumps [gradle-update/update-gradle-wrapper-action](https://github.com/gradle-update/update-gradle-wrapper-action) from 1 to 2.
- [Release notes](https://github.com/gradle-update/update-gradle-wrapper-action/releases)
- [Changelog](https://github.com/gradle-update/update-gradle-wrapper-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/gradle-update/update-gradle-wrapper-action/compare/v1...v2)

---
updated-dependencies:
- dependency-name: gradle-update/update-gradle-wrapper-action
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-25 17:11:17 +02:00
FlorianMichael 8945193a8a Improve spectating client entity id tracking 2024-09-20 14:36:17 +02:00
FlorianMichael 546f4b14fa Add setting for player combat packet handling 2024-09-18 00:10:37 +02:00
FlorianMichael e8028cf446 Show player combat death message above hotbar in 1.9->1.8 2024-09-17 23:45:36 +02:00
FlorianMichael 6a85860132 Use RewriterBase API class for packet rewriter classes 2024-09-17 23:31:10 +02:00
FlorianMichael 4b11b8e1bb Fix client world get on level chunk packet in 1.8->1.7 2024-09-17 23:18:06 +02:00
FlorianMichael 724a6b7a4b Check if client entity id is set 2024-09-17 23:16:06 +02:00
FlorianMichael c785df5fc0 Refactor dimension switch handling 2024-09-15 22:20:36 +02:00
github-actions[bot]andgradle-update-robot de92c06dfd Update Gradle Wrapper from 8.10 to 8.10.1. (#541)
Signed-off-by: gradle-update-robot <gradle-update-robot@regolo.cc>
Co-authored-by: gradle-update-robot <gradle-update-robot@regolo.cc>
2024-09-15 09:55:02 +02:00
FlorianMichael 31f427a1b6 Cleanup LOGIN packet handlers 2024-08-25 21:44:17 +02:00
github-actions[bot]andgradle-update-robot fffcae9c0e Update Gradle Wrapper from 8.9 to 8.10. (#540)
Signed-off-by: gradle-update-robot <gradle-update-robot@regolo.cc>
Co-authored-by: gradle-update-robot <gradle-update-robot@regolo.cc>
2024-08-18 03:17:39 +02:00
FlorianMichael 594dbbcbe9 Only print broken components if suppression disabled 2024-08-13 04:54:38 +02:00
Clairton Santos 8c4efbbb13 Fix race condition when destroy entities on 1.7 (#539) 2024-08-11 02:46:18 +02:00
FlorianMichael 5b1dcf63d2 Add gradle wrapper update workflow 2024-08-07 00:03:39 +02:00
FlorianMichael beead5773c Update IDEA copyright configuration files 2024-08-05 19:51:47 +02:00
FlorianMichael 60a5c4ae2f Setup dependabot, cleanup build files 2024-08-05 19:48:46 +02:00
FlorianMichael d707e20b05 Bump version to 4.0.3-SNAPSHOT 2024-08-05 19:46:22 +02:00
FlorianMichael 14bad1d36f 4.0.2 Release 2024-07-28 16:36:21 +02:00
FlorianMichael 7a9bf5f465 Code cleanup 2024-07-25 18:23:45 +02:00
FlorianMichael f290af7b81 Deep copy items 2024-07-25 17:52:13 +02:00
FlorianMichael 064d0008f5 Keep entity data after respawn in 1.8->1.7 2024-07-25 17:28:04 +02:00
FlorianMichael fbe30d9da5 Cleanup build files
Delete not needed gradle.properties and moves the universal submodule to the root project
2024-07-21 19:43:38 +02:00
FlorianMichael 31490069ea Gradle 8.9 2024-07-14 20:31:37 +02:00
FlorianMichael 1b8d5eacc0 Print death message in chat 2024-07-12 01:53:45 +02:00
FlorianMichael abdb79598b Emulate PLAYER_COMBAT packet in 1.9->1.8 2024-07-12 01:27:33 +02:00
FlorianMichael 1b5b59317c Rename VREntityRewriter#removeEntities, move PLAYER_COMBAT to player packets 2024-07-12 00:59:58 +02:00
FlorianMichael 6e4ac65983 Update VB API usage 2024-07-06 21:20:23 +02:00
FlorianMichael 64cce82140 Properly skip entity data packets 2024-07-04 22:03:28 +02:00
FlorianMichael cb79316d6a Update potion mappings documentation 2024-07-04 00:03:47 +02:00
FlorianMichael 7d34c3838a Fix sign rewriting in 1.8->1.7 2024-07-04 00:03:35 +02:00
FlorianMichael c60152532d Only continue item rewriting if tag is present in 1.8->1.7 2024-06-29 22:59:22 +02:00
FlorianMichael 1894bac11b Fix nullable tag issues in 1.9->1.8 item rewriter 2024-06-29 22:57:59 +02:00
FlorianMichael a80ca442e5 Bump gradle wrapper validation to v3 2024-06-29 15:59:58 +02:00
FlorianMichael c69ce24d32 Only allow VB 5.0.0+ in fabric.mod.json 2024-06-29 15:26:54 +02:00
FlorianMichael e937a886ec Bump version to 4.0.2-SNAPSHOT 2024-06-27 18:21:39 +02:00
FlorianMichael 3e261824ef 4.0.1 Release 2024-06-27 18:13:39 +02:00
FlorianMichael 43c3bb11dc Skip metadata of entities which aren't spawned (yet) 2024-06-27 15:52:00 +02:00
FlorianMichael f57ac05bd4 Add setting for levitation emulation, cleanup code 2024-06-27 02:17:59 +02:00
FlorianMichael a3c623c202 Slightly improve wording in config.yml 2024-06-22 00:56:42 +02:00
FlorianMichael 481315f1e6 Cleanup code 2024-06-22 00:55:50 +02:00
FlorianMichael 21e50421e5 Rename Gradle convention plugin 2024-06-21 11:28:07 +02:00
FlorianMichael 233d52281b Add getter/setter for CooldownStorage#visualizationFactory
Allows servers to override the existing visualization factory with their own ones
2024-06-21 11:25:25 +02:00
FlorianMichael 6807a02de7 Bump version to 4.0.1-SNAPSHOT 2024-06-21 11:23:57 +02:00
FlorianMichael b34cc42a65 4.0.0 Release 2024-06-16 18:10:25 +02:00
FlorianMichael 7b1f0a8737 Rename build-logic submodule 2024-06-15 21:14:47 +02:00
FlorianMichael a171e4013b Only accept correct byte type in custom payload 1.8->1.7 2024-06-11 15:38:34 +02:00
FlorianMichael 3e3561c18f Update VV API usage 2024-06-11 15:36:03 +02:00
FlorianMichael 0097a97ab0 Add note for J8 builds 2024-06-06 05:20:24 +02:00
FlorianMichael 6e583a0c8e Remove missing bungee/sponge references 2024-06-06 05:11:00 +02:00
FlorianMichael 780b981c68 Fixup hologram handling 1.8->1.7
Closes https://github.com/ViaVersion/ViaRewind/issues/509
2024-06-06 05:07:47 +02:00
FlorianMichael 5df933f0e2 Fix 1.7->1.8 player action rewriting 2024-06-03 03:02:45 +02:00
FlorianMichael 750a98cb06 Fixup position reading 2024-06-02 17:50:56 +02:00
FlorianMichael 1ebfa0a715 Update Gradle Wrapper 2024-06-01 17:41:58 +02:00
Nassim Jahnke dc82de8ba2 Move Sponge and Bungee modules to separate plugins 2024-05-30 22:45:53 +02:00
Nassim Jahnke 9ecdaa30bf Use unsigned byte for facing direction in player action 2024-05-30 11:33:49 +02:00
FlorianMichael ee69005318 Delete temporary fix for shulker box window titles
Properly fixed by https://github.com/ViaVersion/ViaBackwards/pull/761
2024-05-28 18:11:08 +02:00
FlorianMichael 740a6d9b96 Finish up v5 migration
Also:
- Reduces the amount of anonymous classes
- Removes usages of PacketWrapper#create with raw ids
2024-05-22 23:36:51 +02:00
Nassim Jahnke b1d680468b Update VV API usage 2024-05-22 12:11:11 +02:00
FlorianMichael 64c18af7b6 Update Via API usage 2024-05-18 21:33:21 +02:00
FlorianMichael 6728a8a809 Port to upstream changes (hopefully) 2024-05-15 00:08:22 +02:00
FlorianMichael 0cb70b0a04 Rename protocol packages and classes 2024-05-11 15:18:21 +02:00
FlorianMichael 2f7f108cd8 Bump version to 4.0.0-SNAPSHOT 2024-05-11 15:12:41 +02:00
FlorianMichael c595c654aa 3.1.2 Release 2024-05-10 13:19:10 +02:00
FlorianMichael c0d1cabb12 Fix bow animation not working in 1.9->1.8
Closes https://github.com/ViaVersion/ViaRewind/issues/516
2024-05-10 00:29:41 +02:00
FlorianMichael 51e81c7bb1 Fix mappings and update project description
Closes https://github.com/ViaVersion/ViaRewind/issues/514
2024-05-10 00:08:00 +02:00
FlorianMichael 6bdaa54ce8 Use 1.9.0 sounds for name<->id conversion
1.9.1 added a new sound so mapping files were previously wrong
2024-05-09 01:03:39 +02:00
FlorianMichael 65ac2f37f2 Don't throw metadata away in 1.8->1.7
Closes https://github.com/ViaVersion/ViaRewind/issues/512
2024-05-09 00:25:13 +02:00
FlorianMichael b08bb90cef Fix packet send usages 2024-05-08 21:31:47 +02:00
FlorianMichael 89e76d369b Fix destroy entities handling in 1.7->1.8
Split into multiple packets since 1.8 can handle a larger list of entities than 1.7 can, causing NegativeArraySizeException's to appear on some servers.
2024-05-07 00:09:24 +02:00
FlorianMichael ed8cc47c7a Bump version to 3.1.2-SNAPSHOT 2024-05-06 23:51:55 +02:00
FlorianMichael d988fdc849 3.1.1 Release 2024-05-05 16:45:42 +02:00
FlorianMichael a0ff53fb9d Don't handle entity properties for holograms 2024-04-30 19:08:19 +02:00
FlorianMichael 1d1dd7dc66 Catch exceptions in custom payload handling
Closes https://github.com/ViaVersion/ViaRewind/issues/192
2024-04-29 02:25:21 +02:00
FlorianMichael cb4ef9ffa8 Fix mob spawner entity data translation in 1.8->1.9
Closes https://github.com/ViaVersion/ViaRewind/issues/126
2024-04-29 02:05:15 +02:00
FlorianMichael 459f403541 Map END_GATEWAY to END_PORTAL in 1.8->1.9
Closes https://github.com/ViaVersion/ViaRewind/issues/150
2024-04-29 01:54:46 +02:00
FlorianMichael 465962b939 Clear enchantments on screen close 2024-04-29 01:42:51 +02:00
FlorianMichael 2fad493eac Rewrite enchantment window properties in 1.8->1.9
Closes https://github.com/ViaVersion/ViaRewind/issues/485
2024-04-29 01:38:29 +02:00
FlorianMichael fb8ea8c4f8 Merge remote-tracking branch 'origin/master' 2024-04-29 00:33:00 +02:00
FlorianMichael 9713e5a8a4 Update mapping files 2024-04-29 00:32:30 +02:00
Nassim Jahnke 7cee59f548 Set paperweight-mappings-namespace manifest attribute 2024-04-28 12:34:56 +02:00
FlorianMichael c7e638fc70 Fix 1.8->1.9 window items translation 2024-04-27 13:58:42 +02:00
FlorianMichael a4b445cf1f Use correct method to remove vehicle in 1.8->1.9
Closes https://github.com/ViaVersion/ViaRewind/issues/505
2024-04-27 13:10:02 +02:00
FlorianMichael 6859f6125c Bump version to 3.1.1-SNAPSHOT 2024-04-27 12:58:07 +02:00
FlorianMichael d85e043325 3.1.0 Release 2024-04-26 15:32:46 +02:00
FlorianMichael 967adaa607 Update item mappings
Adds support for https://github.com/ViaVersion/ViaBackwards/pull/728 as well as missing blockstate mappings from before the rewrite.
2024-04-26 00:27:44 +02:00
FlorianMichael e233b0fa09 Fix and clean hologram emulation 2024-04-24 18:10:29 +02:00
FlorianMichael 2e52a396d3 Migrate 1.7->1.8 as well 2024-04-24 16:57:00 +02:00
FlorianMichael 93731be764 Add new config options for /offhand, also some cleanup 2024-04-23 23:49:43 +02:00
FlorianMichael 8a5d826fd3 Tidy up a few things and fixed tons of bugs 2024-04-23 22:29:37 +02:00
FlorianMichael d5fa0ff8e8 Migrate 1.8->1.9 and removed tons of outdated code 2024-04-23 20:35:27 +02:00
FlorianMichael 823b00930e Merge remote-tracking branch 'refs/remotes/origin/dev' into refactor/viabackwards
# Conflicts:
#	common/src/main/java/com/viaversion/viarewind/protocol/protocol1_7_6_10to1_8/packets/BlockItemPackets1_8.java
#	common/src/main/java/com/viaversion/viarewind/protocol/protocol1_7_6_10to1_8/rewriter/ReplacementItemRewriter1_7_6_10.java
#	common/src/main/java/com/viaversion/viarewind/protocol/protocol1_8to1_9/metadata/MetadataRewriter.java
#	common/src/main/java/com/viaversion/viarewind/protocol/protocol1_8to1_9/packets/InventoryPackets.java
#	common/src/main/java/com/viaversion/viarewind/protocol/protocol1_8to1_9/rewriter/ReplacementItemRewriter1_8.java
2024-04-22 11:46:53 +02:00
Nassim Jahnke da449f2a9e Add UserConnection param to item rewriter methods 2024-04-21 22:48:30 +02:00
FlorianMichael 8835ee4ed2 Update metadata rewriter 2024-04-09 16:00:48 +02:00
FlorianMichael 3ef9dbec1f Merge branch 'refs/heads/dev' into refactor/viabackwards
# Conflicts:
#	common/src/main/java/com/viaversion/viarewind/protocol/protocol1_8to1_9/metadata/MetadataRewriter.java
2024-04-09 15:59:31 +02:00
FlorianMichael b2a78d6dd2 Merge remote-tracking branch 'refs/remotes/origin/master' into dev 2024-04-09 15:57:56 +02:00
FlorianMichael 1aaba348d2 Update build script 2024-04-09 15:56:46 +02:00
FlorianMichael 4d5c4e6223 Removed non-existent meta type 2024-04-09 15:53:42 +02:00
FlorianMichael d08739839e Fix universal module name 2024-04-09 15:51:35 +02:00
FlorianMichael e891696387 Start with porting protocol code 2024-04-09 15:47:45 +02:00
vadage 08cb78f065 Support config loading from input stream (#502)
* Support config loading from input stream

* Fix formatting issue to be consistent with spaces
2024-04-05 20:38:35 +02:00
FlorianMichael 819a4d8bb3 More work 2024-03-29 18:13:05 +01:00
FlorianMichael aa5696e586 Overall improvements to README.md 2024-03-29 13:00:02 +01:00
FlorianMichael 3c9232949a Rename classes to match VB 2024-03-29 12:47:38 +01:00
FlorianMichael a43ad2b737 Prepare entity rewriter migration 2024-03-29 12:41:17 +01:00
FlorianMichael 7e5e8fd2c1 Fix enchantments in 1.7->1.8 2024-03-28 18:08:24 +01:00
FlorianMichael 7fc2530693 Compile from repository server 2024-03-28 11:46:11 +01:00
FlorianMichael e104df51b0 Drop format reset 2024-03-28 10:44:32 +01:00
FlorianMichael 6d237cc337 Deprecate and move classes 2024-03-27 20:34:23 +01:00
FlorianMichael a982ac8c38 Move particle class 2024-03-27 20:26:28 +01:00
FlorianMichael 8494976e4f Port 1.8 -> 1.9 item rewriter as well 2024-03-27 20:02:50 +01:00
FlorianMichael 7b2ad249da Use EnchantmentRewriter base (probably) 2024-03-27 18:22:31 +01:00
FlorianMichael 5f73bee3c5 Start with using ViaBackwards API 2024-03-27 18:04:04 +01:00
FlorianMichael 709f918272 Generate item mappings 2024-03-27 13:55:39 +01:00
FlorianMichael dca9854486 Removed support status from README 2024-03-27 13:54:44 +01:00
FlorianMichael d93dce88d8 So it begins... 2024-03-27 11:12:37 +01:00
FlorianMichael 5ae0f29f42 Fixed version range 2024-03-25 17:35:55 +01:00
FlorianMichael eae4a3ac09 Renamed universal artifact to viarewind, fixed platform name in Via dumps 2024-03-25 17:34:07 +01:00
FlorianMichael 5e1ae7ac0f Back to VV dev 2024-03-24 13:06:13 +01:00
FlorianMichael 2422588db5 Remove viafabricplus from dependency list 2024-03-24 13:01:43 +01:00
FlorianMichael 0a1707f1d0 Fix up again 2024-03-23 13:18:47 +01:00
FlorianMichael c6d6128c5e Update publishing plugin usage 2024-03-23 13:11:40 +01:00
FlorianMichael 8f2072d2af [ci skip] Removed unused import 2024-03-23 12:32:59 +01:00
FlorianMichael 42fbcfb26a Gradle 8.7 2024-03-23 12:31:27 +01:00
FlorianMichael a9568d388f Update Hangar publish plugin 2024-03-23 12:29:42 +01:00
FlorianMichael 36ea0fecc6 Fixed compile error 2024-03-09 14:11:41 +01:00
FlorianMichael 6a26bbdf84 Back to VV master 2024-03-09 14:09:30 +01:00
FlorianMichael 45deefdea3 Update ViaNBT API usage 2024-03-09 14:04:37 +01:00
FlorianMichael 476c5f2077 Updated Via API usage 2024-03-09 13:51:19 +01:00
FlorianMichael aaddfb186b Fixed API usage 2024-03-05 21:02:35 +01:00
FlorianMichael 5407bf9922 Bump version to 3.0.7-24w09a-SNAPSHOT 2024-03-05 20:13:44 +01:00
FlorianMichael 8aea3e43aa Bump version to 3.0.7-SNAPSHOT 2024-03-05 20:11:38 +01:00
FlorianMichael 38e59d7cb5 3.0.6 2024-03-05 19:55:56 +01:00
FlorianMichael 66851feaff [ci skip] Create FUNDING.yml 2024-03-05 13:46:58 +01:00
FlorianMichael 2474f2f347 Merge remote-tracking branch 'origin/master' 2024-03-04 22:18:51 +01:00
FlorianMichael 3322b77afb Merge dev changes into master 2024-03-04 22:18:39 +01:00
FlorianMichael fc7b10e4aa Merge remote-tracking branch 'origin/dev' 2024-03-04 22:15:27 +01:00
FlorianMichael 000c414418 Change dev branch version to 3.0.6-24w07a-SNAPSHOT 2024-03-04 22:13:44 +01:00
FlorianMichael 26b9a83f5a Fixed api usages 2024-02-29 15:25:04 +01:00
FlorianMichael 37a671dfa1 Simplified entity rewriter 2024-02-29 15:21:01 +01:00
FlorianMichael 6a1c89676c Fixed painting rotations in 1.7 -> 1.8 2024-02-29 14:51:56 +01:00
FlorianMichael f0706eca23 Cleaned up token replacement 2024-02-29 14:22:15 +01:00
FlorianMichael 0610ed53ab Finished ReplacementEntityTracker rewrite for now (?) 2024-02-29 14:10:11 +01:00
FlorianMichael dbe26e0ecc Move some classes 2024-02-29 14:04:17 +01:00
FlorianMichael 62606d604e Random code cleanup 2024-02-29 14:01:44 +01:00
FlorianMichael 7254e1ce42 [ci skip] Removed debug code 2024-02-29 13:53:32 +01:00
FlorianMichael b3b6bb325f Proper include of project description 2024-02-29 13:33:21 +01:00
FlorianMichael a0eb8aee24 Mark VR as library for ModMenu 2024-02-29 12:25:16 +01:00
FlorianMichael 630e0224e6 Use equals in legacy custom payload channel comparisons 2024-02-29 12:23:12 +01:00
EnZaXD 224cc121d7 Merge pull request #488 from Kichura/master
paste.gg -> mclo.gs
2024-02-18 23:12:57 +01:00
Kichura a6d9b601d1 paste.gg -> mclo.gs. 2024-02-18 23:10:28 +01:00
FlorianMichael 97044dbe2c Back to VV master 2024-02-18 22:43:35 +01:00
FlorianMichael bb5610c072 Added ViaRewindPlatform#getDataFolder to match VV/VB style 2024-02-18 22:27:08 +01:00
FlorianMichael 57997b25cf Sync fabric.mod.json description with project description 2024-02-18 22:18:33 +01:00
FlorianMichael fc85a00d8c Updated mcVersions in gradle.properties 2024-02-14 20:41:47 +01:00
FlorianMichael f6ceeba636 Updated Via API usage 2024-02-14 20:39:57 +01:00
FlorianMichael 66c810c284 Merge remote-tracking branch 'origin/master' into dev 2024-01-26 15:28:48 +01:00
EnZaXD 3422d90882 Merge pull request #481 from Kichura/master
Update JDK to 17, Cache to v4
2024-01-20 21:24:04 +01:00
Kichura 1f4ab995c5 Update JDK to 17, Cache to v4. 2024-01-20 21:13:17 +01:00
EnZaXD 6a726a289d Merge pull request #479 from ItsClairton/master
fix: Add missing creeper metadata
2024-01-19 14:04:00 +01:00
Clairton (Aiko - W11) 4abe3fb7e8 Add missing creeper metadata, index 18 2024-01-18 00:17:13 -03:00
EnZaXD db93bbbc3e Merge pull request #476 from Kichura/master
Update Velocity to 3.3
2024-01-14 17:25:20 +01:00
Kichura dd220ccf7f Update Velocity to 3.3. 2024-01-14 13:09:37 +01:00
FlorianMichael 0a20ead08b Compile against dev branch of VV again ™️ 2024-01-13 06:37:57 +01:00
FlorianMichael 1eb0d1672e Merge branch 'master' into dev 2024-01-13 06:36:29 +01:00
FlorianMichael f0969b5515 Fixed Via API usage 2024-01-13 06:35:20 +01:00
FlorianMichael 05dea07d99 Delete a lot unused code 2024-01-02 18:53:03 +01:00
FlorianMichael 4d3e5264bc Read names 2024-01-02 18:49:13 +01:00
FlorianMichael fba5a1c7d1 Compile against master branch of VV 2024-01-02 18:21:14 +01:00
EnZaXD 171d33525f Merge pull request #473 from ViaVersion/master
Update dev branch for master changes
2024-01-02 18:20:45 +01:00
FlorianMichael 8d35b00fd7 2024 2024-01-01 00:47:57 +01:00
FlorianMichael 572551b670 Fixed 1.8 -> 1.9 explosion packet translation being broken.
Closes https://github.com/ViaVersion/ViaRewind/issues/471
2023-12-28 00:27:33 +01:00
FlorianMichael 531e564d0b Use correct version for serializing the json component 2023-12-27 20:09:35 +01:00
FlorianMichael 81840dc643 Updated Via API usage 2023-12-27 20:03:00 +01:00
FlorianMichael a9f0b72adc Merge remote-tracking branch 'origin/master' 2023-12-27 17:55:23 +01:00
FlorianMichael e1b9c76063 Updated copyright profile 2023-12-27 17:54:52 +01:00
Kichura 2da271ffe7 [ci skip] Update checkout and setup-java to v4. (#470) 2023-12-27 17:26:33 +01:00
Kichura f27b4f0df6 Add description for ViaRewind. (#468)
This properly describes on what viarewind is for when viewing it in Mod Menu.
2023-12-23 11:51:37 +01:00
SplotyCode cf64b7ffcc Fix 1.9->1.8 use item (#466) 2023-12-21 10:19:12 +01:00
FlorianMichael 6829af6cb7 Bump version to 3.0.6-SNAPSHOT 2023-12-13 23:21:04 +01:00
229 changed files with 13200 additions and 12729 deletions

No files matched your search

+14 -2
View File
@@ -1,4 +1,16 @@
root = true
[*]
charset = utf-8
indent_size = 4
indent_style = space
insert_final_newline = true
tab_width = 4
[*.java]
indent_style = tab
ij_java_class_count_to_use_import_on_demand = 999999
ij_java_names_count_to_use_import_on_demand = 999999
ij_java_imports_layout = *, |, $*
ij_java_generate_final_locals = true
ij_java_generate_final_parameters = true
[{*.json,*.yml}]
indent_size = 2
+2
View File
@@ -0,0 +1,2 @@
github: florianreuth
custom: [ 'https://florianreuth.de/donate', 'https://creeper123123321.github.io/#donate' ]
+7 -7
View File
@@ -1,6 +1,6 @@
name: Bug report
description: Report a bug or console error
labels: [Unconfirmed]
labels: [ Unconfirmed ]
body:
- type: markdown
@@ -23,11 +23,11 @@ body:
attributes:
label: Console Error
description: |
If you encounter warnings/errors in your console, **paste them with https://paste.gg/ and put the paste link here**.
If you encounter warnings/errors in your console, **paste them with https://mclo.gs/ and put the paste link here**.
If the error is small/less than 10 lines, you may put it directly into this field.
value: |
```
Put the paste.gg link or text here.
Put the mclo.gs link or text here.
```
placeholder: Please do not remove the grave accents; simply replace the line of text in the middle.
validations:
@@ -71,9 +71,9 @@ body:
attributes:
label: Additional Server Info
description: |
Do you use a proxy (eg. BungeeCord)? What software do you use and what plugins?
Do you use a proxy (eg. Velocity)? What software do you use and what plugins?
placeholder: |
Example: "I also use BungeeCord with the following plugins: x, y, z"
Example: "I also use Velocity with the following plugins: x, y, z"
validations:
required: false
@@ -82,7 +82,7 @@ body:
label: Checklist
description: Make sure you have followed each of the steps outlined here.
options:
- label: Via plugins are only running on **EITHER** the backend servers (e.g. Paper) **OR** the proxy (e.g. BungeeCord), **not on both**.
- label: Via plugins are only running on **EITHER** the backend servers (e.g. Paper) **OR** the proxy (e.g. Velocity), **not on both**.
required: true
- label: I have included a ViaVersion dump.
required: true
@@ -91,4 +91,4 @@ body:
- label: I have tried the latest build(s) from https://ci.viaversion.com/ and the issue still persists.
required: true
- label: I have looked at https://www.spigotmc.org/resources/viarewind-legacy-support.52924/ and it does not offer a fix for my problem
required: true
required: true
+18 -18
View File
@@ -5,34 +5,34 @@ labels: [ Feature Request ]
body:
- type: textarea
attributes:
label: Problem Description
description: |
Describe the issue you are facing or why you need the feature to be added.
placeholder: |
I am always frustrated with...
label: Problem Description
description: |
Describe the issue you are facing or why you need the feature to be added.
placeholder: |
I am always frustrated with...
validations:
required: true
required: true
- type: textarea
attributes:
label: Solution Description
description: |
Describe the solution you would like to see.
label: Solution Description
description: |
Describe the solution you would like to see.
validations:
required: true
required: true
- type: textarea
attributes:
label: Alternatives
description: |
Describe alternatives you have considered.
label: Alternatives
description: |
Describe alternatives you have considered.
validations:
required: false
required: false
- type: textarea
attributes:
label: Additional Info
description: |
Does the feature apply to any specific version or environment?
label: Additional Info
description: |
Does the feature apply to any specific version or environment?
validations:
required: false
required: false
+22
View File
@@ -0,0 +1,22 @@
version: 2
updates:
- package-ecosystem: "gradle"
cooldown:
default-days: 7
directory: "/"
schedule:
interval: "monthly"
groups:
all-dependencies:
patterns:
- "*"
- package-ecosystem: "github-actions"
cooldown:
default-days: 7
directory: "/"
schedule:
interval: "monthly"
groups:
all-dependencies:
patterns:
- "*"
+23 -19
View File
@@ -1,28 +1,32 @@
name: ViaRewind CI
name: Build
on: [pull_request, push, workflow_dispatch]
permissions:
contents: read
jobs:
build:
runs-on: ubuntu-22.04
runs-on: ubuntu-26.04
timeout-minutes: 30
steps:
- name: Checkout Repository
uses: actions/checkout@v3
- name: Validate Gradle Wrapper
uses: gradle/wrapper-validation-action@v1
- name: Set up JDK 8
uses: actions/setup-java@v3
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- name: Set up Gradle
uses: gradle/actions/setup-gradle@9c971963bec38e04b3d30dcc455b5382be2fdbfb # v6.3.0
with:
cache-disabled: true
cache-provider: basic
- name: Set up Java
uses: actions/setup-java@de7274f081f381c8f8158605e0321c36c376e2e6 # v6.0.1
with:
distribution: 'temurin'
java-version: 8
java-version: 25
check-latest: true
- name: Cache Dependencies
uses: actions/cache@v3
with:
path: |
~/.gradle/caches
~/.gradle/wrapper
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
restore-keys: |
${{ runner.os }}-gradle-
- name: Build with Gradle
run: ./gradlew build
run: ./gradlew build --stacktrace
- name: Upload Artifacts to GitHub
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: Artifacts
path: build/libs/
if-no-files-found: error
+26 -9
View File
@@ -4,24 +4,41 @@ on:
branches:
- master
- dev
workflow_dispatch:
permissions:
contents: read
jobs:
publish:
if: github.repository_owner == 'ViaVersion'
runs-on: ubuntu-22.04
runs-on: ubuntu-26.04
timeout-minutes: 30
steps:
- name: Checkout Repository
uses: actions/checkout@v3
- name: Validate Gradle Wrapper
uses: gradle/wrapper-validation-action@v1
- name: Set up JDK 8
uses: actions/setup-java@v3
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- name: Set up Gradle
uses: gradle/actions/setup-gradle@9c971963bec38e04b3d30dcc455b5382be2fdbfb # v6.3.0
with:
cache-disabled: true
cache-provider: basic
- name: Set up Java
uses: actions/setup-java@de7274f081f381c8f8158605e0321c36c376e2e6 # v6.0.1
with:
distribution: 'temurin'
java-version: 8
java-version: 25
check-latest: true
- name: Publish
- name: Build with Gradle
run: ./gradlew build --stacktrace
- name: Publish to Hangar
env:
HANGAR_TOKEN: ${{ secrets.HANGAR_TOKEN }}
run: ./gradlew publishAllPublicationsToHangar --stacktrace
continue-on-error: true
- name: Publish to Modrinth
env:
MODRINTH_TOKEN: ${{ secrets.MODRINTH_TOKEN }}
run: ./gradlew build modrinth publishAllPublicationsToHangar
run: ./gradlew modrinth --stacktrace
continue-on-error: true
+20 -97
View File
@@ -1,113 +1,36 @@
### Java files ###
*.class
# Gradle
# Package Files
#*.jar
*.war
*.ear
.gradle/
build/
out/
classes/
.kotlin/
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
hs_err_pid*
# Eclipse
*.launch
# Idea
### Intellij ###
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm
# Ignore project files
.idea/
!.idea/copyright/*
!.idea/scopes/*
*.iml
# Ignore IDEA directory
.idea/*
# Include the project's dictionary
!.idea/dictionaries/
!.idea/dictionaries/*
# File-based project format:
*.ipr
*.iws
### Plugin-specific files: ###
# IntelliJ
/out/
# VSCode
# mpeltonen/sbt-idea plugin
.idea_modules/
# JIRA plugin
atlassian-ide-plugin.xml
# Crashlytics plugin (for Android Studio and IntelliJ)
com_crashlytics_export_strings.xml
crashlytics.properties
crashlytics-build.properties
### Eclipse ###
*.pydevproject
.metadata
.gradle
bin/
tmp/
*.tmp
*.bak
*.swp
*~.nib
local.properties
.settings/
.loadpath
# Eclipse Core
.vscode/
bin/
.classpath
.project
# External tool builders
.externalToolBuilders/
# macOS
# Locally stored "Eclipse launch configurations"
*.launch
DS_Store
# CDT-specific
.cproject
# Misc
# JDT-specific (Eclipse Java Development Tools)
.classpath
# PDT-specific
.buildpath
# sbteclipse plugin
.target
# TeXlipse plugin
.texlipse
### Maven ###
target/
pom.xml.tag
pom.xml.releaseBackup
pom.xml.versionsBackup
pom.xml.next
release.properties
dependency-reduced-pom.xml
buildNumber.properties
### NetBeans ###
nbproject/private/
build/
nbbuild/
dist/
nbdist/
nbactions.xml
nb-configuration.xml
.nb-gradle/
### Git ###
# Don't exclude the .gitignore itself
!/.gitignore
run/
@@ -1,5 +1,5 @@
<component name="CopyrightManager">
<settings>
<settings default="viarewind-gpl">
<module2copyright>
<element module="ViaRewind" copyright="viarewind-gpl" />
</module2copyright>
+1 -1
View File
@@ -1,6 +1,6 @@
<component name="CopyrightManager">
<copyright>
<option name="notice" value="This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind&#10;Copyright (C) &amp;#36;originalComment.match(&quot;Copyright \(C\) (\d+)&quot;, 1, &quot;-&quot;)&amp;#36;today.year ViaVersion and contributors&#10;&#10;This program is free software: you can redistribute it and/or modify&#10;it under the terms of the GNU General Public License as published by&#10;the Free Software Foundation, either version 3 of the License, or&#10;(at your option) any later version.&#10;&#10;This program is distributed in the hope that it will be useful,&#10;but WITHOUT ANY WARRANTY; without even the implied warranty of&#10;MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the&#10;GNU General Public License for more details.&#10;&#10;You should have received a copy of the GNU General Public License&#10;along with this program. If not, see &lt;http://www.gnu.org/licenses/&gt;." />
<option name="notice" value="This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind&#10;Copyright (C) 2018-&amp;#36;today.year ViaVersion and contributors&#10;&#10;This program is free software: you can redistribute it and/or modify&#10;it under the terms of the GNU General Public License as published by&#10;the Free Software Foundation, either version 3 of the License, or&#10;(at your option) any later version.&#10;&#10;This program is distributed in the hope that it will be useful,&#10;but WITHOUT ANY WARRANTY; without even the implied warranty of&#10;MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the&#10;GNU General Public License for more details.&#10;&#10;You should have received a copy of the GNU General Public License&#10;along with this program. If not, see &lt;http://www.gnu.org/licenses/&gt;." />
<option name="myName" value="viarewind-gpl" />
</copyright>
</component>
+28 -7
View File
@@ -1,22 +1,32 @@
# ViaRewind
[![Latest Release](https://img.shields.io/github/v/release/ViaVersion/ViaRewind)](https://github.com/ViaVersion/ViaRewind/releases)
[![Build Status](https://github.com/ViaVersion/ViaRewind/actions/workflows/build.yml/badge.svg?branch=master)](https://github.com/ViaVersion/ViaRewind/actions)
[![Discord](https://img.shields.io/badge/chat-on%20discord-blue.svg)](https://viaversion.com/discord)
**ViaVersion addon to allow 1.8.x and 1.7.x clients on newer server versions.** <br>
Runs on 1.9-latest servers or 1.8 clients and lower.
**You can override the included version in [ViaFabric](https://modrinth.com/mod/viafabric) or [ViaProxy](https://github.com/ViaVersion/ViaProxy):**
**You can override the included version in [ViaFabric](https://modrinth.com/mod/viafabric)
or [ViaProxy](https://github.com/ViaVersion/ViaProxy):**
- in **ViaFabric**, put ViaRewind into the `mods` folder
- in **ViaProxy**, put ViaRewind into the `jars` folder
**Depending on the platform and version, this also requires [ViaVersion](https://modrinth.com/mod/viaversion) and [ViaBackwards](https://modrinth.com/mod/viabackwards).**
Note: when using ViaFabric <= 1.16.5 or J8 ViaProxy builds, you
need [J8 ViaRewind](https://ci.viaversion.com/view/ViaRewind/job/ViaRewind-Java8/) builds.
Support Status
-
While ViaRewind will keep getting updates to function with changes to ViaVersion or ViaBackwards, it will likely not receive many bug fixes or additional features anymore.
**Requires [ViaVersion](https://hangar.papermc.io/ViaVersion/ViaVersion)
and [ViaBackwards](https://hangar.papermc.io/ViaVersion/ViaBackwards) to be installed..**
Releases / Dev Builds
Releases/Dev Builds
-
You can find releases in the following places:
- **Hangar (for our plugins)**: https://hangar.papermc.io/ViaVersion/ViaRewind
- **Modrinth (for our mods)**: https://modrinth.com/mod/viarewind
- **GitHub**: https://github.com/ViaVersion/ViaRewind/releases
Dev builds for **all** of our projects are on our Jenkins server:
- **Jenkins**: https://ci.viaversion.com/view/ViaRewind/
@@ -27,4 +37,15 @@ Other Links
**Issue tracker:** https://github.com/ViaVersion/ViaRewind/issues
**List of contributors:** https://github.com/ViaVersion/ViaRewind/graphs/contributors
**List of contributors:** https://github.com/ViaVersion/ViaRewind/graphs/contributors
Building
-
After cloning this repository, build the project with Gradle by running `./gradlew build` and take the created jar out
of the `build/libs` directory.
You need JDK 17 or newer to build ViaRewind.
License
-
This project is licensed under the [GNU General Public License Version 3](LICENSE).
+15
View File
@@ -0,0 +1,15 @@
# Security Policy
## Reporting a Vulnerability
If you discover a **security vulnerability**, please **do not** open a public issue. Instead, use one of the following
**confidential contact methods**:
* **Email:** [security@viaversion.com](mailto:security@viaversion.com)
* **Discord:** Join our [Discord server](https://discord.gg/viaversion) and visit
the [#exploit-report](https://discord.com/channels/316206679014244363/1388847764137316485) channel for further
instructions.
If your issue is **not security-related** (e.g., bug reports, feature requests, or usage questions), please use
the [GitHub Issues page](https://github.com/ViaVersion/ViaRewind/issues) or contact us via
the [Discord server](https://discord.gg/viaversion).
+8
View File
@@ -0,0 +1,8 @@
plugins {
`kotlin-dsl`
}
dependencies {
implementation(libs.foojay.resolver.convention.plugin)
implementation(libs.classtokenreplacer.plugin)
}
+10
View File
@@ -0,0 +1,10 @@
dependencyResolutionManagement {
repositories {
gradlePluginPortal()
}
versionCatalogs {
create("libs") {
from(files("../gradle/libs.versions.toml"))
}
}
}
@@ -0,0 +1,39 @@
plugins {
`java-library`
}
group = property("project_group") as String
version = property("project_version") as String
description = property("project_description") as String
if (project == rootProject) {
(findProperty("project_name") as String?)?.let { base.archivesName = it }
}
// The Kotlin plugin picks up the Java toolchain, so no Kotlin specific configuration is needed
val jvmVersion = (property("jvm_version") as String).toInt()
java {
toolchain.languageVersion = JavaLanguageVersion.of(jvmVersion)
sourceCompatibility = JavaVersion.toVersion(jvmVersion)
targetCompatibility = JavaVersion.toVersion(jvmVersion)
}
tasks.withType<JavaCompile>().configureEach {
options.encoding = "UTF-8"
options.compilerArgs.addAll(listOf("-nowarn", "-Xlint:-unchecked", "-Xlint:-deprecation"))
}
tasks.withType<Javadoc>().configureEach {
options.encoding = "UTF-8"
(options as StandardJavadocDocletOptions).apply {
addBooleanOption("Xdoclint:none", true)
quiet()
}
}
tasks.jar {
val projectName = project.name
from("LICENSE") {
rename { "LICENSE_$projectName" }
}
}
@@ -0,0 +1,60 @@
plugins {
`java-library`
`maven-publish`
signing
}
val projectName = property("project_name") as String
val ownerId = property("publish_owner_id") as String
val ownerName = property("publish_owner_name") as String
val ownerMail = property("publish_owner_mail") as String
val githubAccount = findProperty("publish_github_account") as String? ?: ownerId
val licenseName = findProperty("publish_license") as String? ?: "Apache-2.0"
val githubRepository = "github.com/$githubAccount/$projectName"
java {
withSourcesJar()
withJavadocJar()
}
publishing {
publications {
create<MavenPublication>("maven") {
groupId = project.group.toString()
artifactId = project.name
version = project.version.toString()
from(components["java"])
pom {
name = projectName
// Lazy so that a description set in the build script body is picked up
description = provider { project.description }
url = "https://$githubRepository"
licenses {
license {
name = licenseName
url = "https://$githubRepository/blob/main/LICENSE"
}
}
developers {
developer {
id = ownerId
name = ownerName
email = ownerMail
}
}
scm {
connection = "scm:git:git://$githubRepository.git"
developerConnection = "scm:git:ssh://$githubRepository.git"
url = "https://$githubRepository"
}
}
}
}
}
signing {
isRequired = false
sign(publishing.publications)
}
@@ -0,0 +1,14 @@
plugins {
id("org.gradle.toolchains.foojay-resolver-convention")
}
enableFeaturePreview("TYPESAFE_PROJECT_ACCESSORS")
dependencyResolutionManagement {
// Repositories live in the settings only, a project or plugin declaring its own fails the build
repositoriesMode = RepositoriesMode.FAIL_ON_PROJECT_REPOS
repositories {
mavenCentral()
maven("https://maven.florianreuth.de/releases")
}
}
@@ -0,0 +1,16 @@
plugins {
java
}
val embeddedDependencies = configurations.create("embeddedDependencies") {
isCanBeResolved = true
isCanBeConsumed = true
}
tasks.jar {
dependsOn(embeddedDependencies)
from({ embeddedDependencies.map { zipTree(it) } }) {
exclude("META-INF/*.RSA", "META-INF/*.SF", "META-INF/*.DSA")
}
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
}
@@ -0,0 +1,59 @@
package de.florianreuth.baseproject
import org.gradle.api.Project
import org.gradle.api.provider.ListProperty
import org.gradle.api.provider.ValueSource
import org.gradle.api.provider.ValueSourceParameters
import org.gradle.process.ExecOperations
import java.io.ByteArrayOutputStream
import javax.inject.Inject
/**
* Short hash of the latest commit, or "unknown" if Git is unavailable.
*/
fun Project.latestCommitHash(): String = runGitCommand(listOf("rev-parse", "--short", "HEAD"))
/**
* Message of the latest commit, or "unknown" if Git is unavailable.
*/
fun Project.latestCommitMessage(): String = runGitCommand(listOf("log", "-1", "--pretty=%B"))
/**
* Name of the current branch, or "unknown" if Git is unavailable.
*/
fun Project.branchName(): String = runGitCommand(listOf("rev-parse", "--abbrev-ref", "HEAD"))
/**
* Runs a Git command through a configuration-cache compatible [ValueSource].
*
* @param args the arguments passed to `git`
* @return the trimmed output, or "unknown" if the command fails or prints nothing
*/
fun Project.runGitCommand(args: List<String>): String {
return providers.of(GitCommand::class.java) { parameters.args.set(args) }.getOrNull() ?: "unknown"
}
abstract class GitCommand : ValueSource<String, GitCommand.GitCommandParameters> {
@get:Inject
abstract val execOperations: ExecOperations
interface GitCommandParameters : ValueSourceParameters {
val args: ListProperty<String>
}
override fun obtain(): String? {
try {
val output = ByteArrayOutputStream()
execOperations.exec {
commandLine = listOf("git") + parameters.args.get()
standardOutput = output
isIgnoreExitValue = true
}
return output.toString(Charsets.UTF_8).trim().takeIf { it.isNotBlank() }
} catch (_: Exception) {
return null
}
}
}
@@ -0,0 +1,78 @@
/*
* This file is part of BaseProject - https://github.com/florianreuth/BaseProject
* Copyright (C) 2024-2026 Florian Reuth <git@florianreuth.de>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package de.florianreuth.baseproject
import org.gradle.api.Project
import org.gradle.api.initialization.Settings
/**
* Includes `<rootProject.name>-<name>` for every name, located in the `<name>` folder.
*
* @param names the subproject folder names
*/
fun Settings.setupViaSubprojects(vararg names: String) {
names.forEach { name ->
include("${rootProject.name}-$name")
project(":${rootProject.name}-$name").projectDir = settingsDir.resolve(name)
}
}
/**
* Version, channel and changelog of a Modrinth / Hangar upload of a ViaVersion project.
*
* @property isRelease whether the project version has no pre-release suffix
* @property isMainBranch whether the current Git branch is the main branch
* @property version the project version, suffixed with the GitHub run number for non-releases
* @property changelog a link to the GitHub releases for releases, otherwise [commitChangelog]
* @property commitChangelog a link to and the message of the latest commit
*/
class ViaRelease(
val isRelease: Boolean,
val isMainBranch: Boolean,
val version: String,
val changelog: String,
val commitChangelog: String
) {
val modrinthVersionType: String
get() = if (isRelease) "release" else if (isMainBranch) "beta" else "alpha"
val hangarChannel: String
get() = if (isRelease) "Release" else if (isMainBranch) "Snapshot" else "Alpha"
}
/**
* Collects the release information from the project version and Git; the repository is `ViaVersion/<project_name>`.
*
* @param mainBranch the name of the branch releases are published from
* @return the release information of the current build
*/
fun Project.viaRelease(mainBranch: String): ViaRelease {
val baseVersion = version.toString()
val isRelease = !baseVersion.contains('-')
val repository = "https://github.com/ViaVersion/${property("project_name")}"
val commitHash = latestCommitHash()
val commitChangelog = "[$commitHash]($repository/commit/$commitHash) ${latestCommitMessage()}"
return ViaRelease(
isRelease = isRelease,
isMainBranch = branchName() == mainBranch,
version = if (isRelease) baseVersion else baseVersion + "+" + System.getenv("GITHUB_RUN_NUMBER"),
changelog = if (isRelease) "See [GitHub]($repository) for release notes." else commitChangelog,
commitChangelog = commitChangelog
)
}
@@ -0,0 +1,20 @@
import de.florianreuth.baseproject.latestCommitHash
import net.raphimc.classtokenreplacer.extension.ClassTokenReplacerExtension
plugins {
java
id("net.raphimc.class-token-replacer")
}
val implVersion = "git-${property("project_name")}-${project.version}:${latestCommitHash()}"
sourceSets.configureEach {
extensions.getByType<ClassTokenReplacerExtension>().apply {
property("\${version}", project.version)
property("\${impl_version}", implVersion)
}
}
// With replaceInPlace the plugin only finalizes classes with the replacement, so the jar could pack unreplaced classes
tasks.jar {
dependsOn("replaceTokens")
}
@@ -0,0 +1,19 @@
plugins {
`maven-publish`
}
publishing {
repositories {
maven {
name = "Via"
url = uri("https://repo.viaversion.com/")
credentials {
username = findProperty("ViaUsername") as String?
password = findProperty("ViaPassword") as String?
}
authentication {
create<BasicAuthentication>("basic")
}
}
}
}
@@ -0,0 +1,20 @@
plugins {
java
id("base.java")
id("via.maven_publish")
}
val libs = project.the<VersionCatalogsExtension>().named("libs")
dependencies {
compileOnly(libs.findLibrary("viaversion").get())
compileOnly(libs.findLibrary("viabackwards").get())
}
tasks.processResources {
val projectVersion = project.version
val projectDescription = project.description
filesMatching(listOf("plugin.yml", "fabric.mod.json", "META-INF/sponge_plugins.json")) {
expand(mapOf("version" to projectVersion, "description" to projectDescription))
}
}
@@ -0,0 +1,8 @@
plugins {
id("publishing.viaversion")
}
// base.maven_publish reads these when applied, so it is applied only after they are set
extra["publish_github_account"] = "ViaVersion"
extra["publish_license"] = "GPL-3.0"
apply(plugin = "base.maven_publish")
@@ -0,0 +1,47 @@
// Task to quickly test/debug code changes using https://github.com/ViaVersion/ViaProxy
// For further instructions see the ViaProxy repository README
plugins {
java
}
val viaProxy = configurations.create("viaProxy")
dependencies {
addProvider<MinimalExternalModuleDependency, ExternalModuleDependency>(
viaProxy.name,
project.the<VersionCatalogsExtension>().named("libs").findLibrary("viaproxy").get()
) {
isTransitive = false
}
}
val prepareViaProxyFiles by tasks.registering(Copy::class) {
dependsOn(project.tasks.jar)
from(project.tasks.jar.get().archiveFile.get().asFile)
into(layout.projectDirectory.dir("run/jars"))
val projectName = project.name
rename { "${projectName}.jar" }
}
val cleanupViaProxyFiles by tasks.registering(Delete::class) {
delete(
layout.projectDirectory.file("run/jars/${project.name}.jar"),
layout.projectDirectory.dir("run/logs")
)
}
tasks.register<JavaExec>("runViaProxy") {
dependsOn(prepareViaProxyFiles)
finalizedBy(cleanupViaProxyFiles)
mainClass.set("net.raphimc.viaproxy.ViaProxy")
classpath = viaProxy
workingDir = layout.projectDirectory.dir("run").asFile
jvmArgs = listOf("-DskipUpdateCheck")
if (System.getProperty("viaproxy.gui.autoStart") != null) {
jvmArgs("-Dviaproxy.gui.autoStart")
}
}
+96
View File
@@ -0,0 +1,96 @@
import de.florianreuth.baseproject.viaRelease
plugins {
`java-library`
alias(libs.plugins.hangar.publish)
alias(libs.plugins.minotaur)
id("base.java")
id("via.maven_publish")
id("configuration.embedded_dependencies")
}
dependencies {
embeddedDependencies(projects.viarewindCommon)
embeddedDependencies(projects.viarewindBukkit)
embeddedDependencies(projects.viarewindFabric)
embeddedDependencies(projects.viarewindSponge)
embeddedDependencies(projects.viarewindVelocity)
}
tasks {
jar {
manifest {
attributes("paperweight-mappings-namespace" to "mojang")
}
}
}
val release = viaRelease("master")
if (!release.isRelease || release.isMainBranch) { // Only publish releases from the main branch
modrinth {
val mcVersions: List<String> = (property("minecraft_versions") as String)
.split(",")
.map { it.trim() }
token.set(System.getenv("MODRINTH_TOKEN"))
projectId.set("viarewind")
versionType.set(release.modrinthVersionType)
versionNumber.set(release.version)
versionName.set(release.version)
changelog.set(release.changelog)
uploadFile.set(tasks.jar.flatMap { it.archiveFile })
gameVersions.set(mcVersions)
loaders.add("fabric")
loaders.add("paper")
loaders.add("folia")
loaders.add("velocity")
autoAddDependsOn.set(false)
detectLoaders.set(false)
dependencies {
required.project("viaversion")
required.project("viabackwards")
optional.project("viafabric")
}
}
tasks.modrinth {
notCompatibleWithConfigurationCache("")
}
hangarPublish {
publications.register("plugin") {
version.set(release.version)
id.set("ViaRewind")
channel.set(release.hangarChannel)
changelog.set(release.changelog)
apiKey.set(System.getenv("HANGAR_TOKEN"))
platforms {
paper {
jar.set(tasks.jar.flatMap { it.archiveFile })
platformVersions.set(listOf(property("minecraft_version_range") as String))
dependencies {
hangar("ViaVersion") {
required = true
}
hangar("ViaBackwards") {
required = true
}
}
}
velocity {
jar.set(tasks.jar.flatMap { it.archiveFile })
platformVersions.set(listOf(property("velocity_version") as String))
dependencies {
hangar("ViaVersion") {
required = true
}
hangar("ViaBackwards") {
required = true
}
}
}
}
}
}
tasks.named("publishPluginPublicationToHangar") {
notCompatibleWithConfigurationCache("")
}
}
-7
View File
@@ -1,7 +0,0 @@
plugins {
id "groovy-gradle-plugin"
}
repositories {
gradlePluginPortal()
}
@@ -1,91 +0,0 @@
plugins {
id "java-library"
id "maven-publish"
}
repositories {
mavenLocal()
maven {
url = uri("https://repo.viaversion.com")
}
maven {
url = uri("https://repo.maven.apache.org/maven2/")
}
maven {
url = uri("https://hub.spigotmc.org/nexus/content/repositories/snapshots/")
}
maven {
url = uri("https://oss.sonatype.org/content/repositories/snapshots")
}
maven {
url = uri("https://maven.fabricmc.net/")
}
maven {
url = uri("https://repo.spongepowered.org/repository/maven-public/")
}
maven {
url = uri("https://nexus.velocitypowered.com/repository/maven-public/")
}
}
dependencies {
compileOnly "com.viaversion:viaversion:${project.viaversion_version}"
compileOnly "io.netty:netty-all:${project.netty_version}"
compileOnly "com.google.guava:guava:${project.guava_version}"
}
archivesBaseName = project.maven_name
group = project.maven_group
version = project.maven_version
java.sourceCompatibility = JavaVersion.VERSION_1_8
tasks {
// Variable replacements
processResources {
inputs.property "version", project.version
for (final def file in ["plugin.yml", "bungee.yml", "META-INF/sponge_plugins.json", "fabric.mod.json"]) {
filesMatching(file) {
expand "version": version
}
}
}
}
publishing {
repositories {
maven {
name = "Via"
url = "https://repo.viaversion.com/"
credentials(PasswordCredentials)
authentication {
basic(BasicAuthentication)
}
}
}
publications {
main(MavenPublication) {
artifactId = project.maven_name
groupId = project.maven_group
version = project.maven_version
from(components.java)
}
}
}
tasks.withType(JavaCompile) {
options.encoding = 'UTF-8'
}
tasks.withType(Javadoc) {
options.encoding = 'UTF-8'
}
-9
View File
@@ -1,9 +0,0 @@
plugins {
id "com.viaversion.java-conventions"
}
dependencies {
api project(":viarewind-common")
compileOnly(annotationProcessor("org.spigotmc:spigot-api:1.12.2-R0.1-SNAPSHOT"))
}
+8
View File
@@ -0,0 +1,8 @@
plugins {
id("via.addon_subproject")
}
dependencies {
compileOnly(projects.viarewindCommon)
compileOnly(libs.spigot.api)
}
-1
View File
@@ -1 +0,0 @@
maven_name=viarewind-bukkit
@@ -1,6 +1,6 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2016-2023 ViaVersion and contributors
* Copyright (C) 2018-2026 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -15,18 +15,25 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind;
import com.viaversion.viarewind.api.ViaRewindPlatform;
import com.viaversion.viarewind.protocol.v1_9to1_8.provider.InventoryProvider;
import com.viaversion.viarewind.provider.BukkitInventoryProvider;
import com.viaversion.viaversion.api.Via;
import org.bukkit.plugin.java.JavaPlugin;
import java.io.File;
import com.viaversion.viaversion.api.platform.providers.ViaProviders;
import org.bukkit.plugin.java.JavaPlugin;
public class BukkitPlugin extends JavaPlugin implements ViaRewindPlatform {
public BukkitPlugin() {
Via.getManager().addEnableListener(() -> this.init(new File(getDataFolder(), "config.yml")));
}
public BukkitPlugin() {
Via.getManager().addEnableListener(() -> this.init(new File(getDataFolder(), "config.yml")));
}
@Override
public void onEnable() {
final ViaProviders providers = Via.getManager().getProviders();
providers.use(InventoryProvider.class, new BukkitInventoryProvider());
}
}
@@ -0,0 +1,36 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2018-2026 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.provider;
import com.viaversion.viarewind.protocol.v1_9to1_8.provider.InventoryProvider;
import com.viaversion.viaversion.api.connection.UserConnection;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
public final class BukkitInventoryProvider extends InventoryProvider {
@Override
public boolean hasElytra(final UserConnection connection) {
final Player player = Bukkit.getPlayer(connection.getProtocolInfo().getUuid());
final ItemStack chestplate = player.getInventory().getChestplate();
return chestplate != null && chestplate.getType() == Material.ELYTRA;
}
}
+5 -7
View File
@@ -1,12 +1,10 @@
name: ViaRewind
version: ${version}
main: com.viaversion.viarewind.BukkitPlugin
authors: [ EnZaXD, Gerrygames, creeper123123321 ]
version: ${version}
description: ${description}
website: https://viaversion.com/rewind
api-version: 1.13
folia-supported: true
authors: [Gerrygames, FlorianMichael/EnZaXD, creeper123321123]
website: https://viaversion.com/rewind
load: STARTUP
depend: [ViaVersion]
softdepend: [ViaBackwards]
depend: [ ViaVersion, ViaBackwards ]
-9
View File
@@ -1,9 +0,0 @@
plugins {
id "com.viaversion.java-conventions"
}
dependencies {
api project(":viarewind-common")
compileOnly(annotationProcessor("net.md-5:bungeecord-api:1.19-R0.1-SNAPSHOT"))
}
-1
View File
@@ -1 +0,0 @@
maven_name=viarewind-bungee
-7
View File
@@ -1,7 +0,0 @@
name: ViaRewind
main: com.viaversion.viarewind.BungeePlugin
authors: [Gerrygames, FlorianMichael/EnZaXD, creeper123321123]
version: ${version}
depends: [ViaVersion]
softdepends: [ViaBackwards]
website: https://viaversion.com/rewind
-28
View File
@@ -1,28 +0,0 @@
plugins {
id "com.viaversion.java-conventions"
}
plugins {
id "net.raphimc.class-token-replacer" version "1.0.0"
}
dependencies {
}
sourceSets {
main {
classTokenReplacer {
property("\${version}", rootProject.maven_version)
property("\${impl_version}", "git-${project.name}-${rootProject.maven_version}:${project.latestCommitHash()}")
}
}
}
String latestCommitHash() {
def stdout = new ByteArrayOutputStream()
exec {
commandLine 'git', 'rev-parse', '--short', 'HEAD'
standardOutput = stdout
}
return stdout.toString().trim()
}
+11
View File
@@ -0,0 +1,11 @@
plugins {
id("via.addon_subproject")
id("extra.fill_build_constants")
id("via.run_viaproxy")
}
dependencies {
compileOnly(libs.netty.all)
compileOnly(libs.guava)
compileOnly(libs.velocity.native)
}
-1
View File
@@ -1 +0,0 @@
maven_name=viarewind-common
@@ -1,6 +1,6 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2016-2023 ViaVersion and contributors
* Copyright (C) 2018-2026 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -15,7 +15,6 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind;
import com.google.common.base.Preconditions;
@@ -24,21 +23,21 @@ import com.viaversion.viarewind.api.ViaRewindPlatform;
public class ViaRewind {
private static ViaRewindPlatform platform;
private static ViaRewindConfig config;
private static ViaRewindPlatform platform;
private static ViaRewindConfig config;
public static void init(ViaRewindPlatform platform, ViaRewindConfig config) {
Preconditions.checkArgument(ViaRewind.platform == null, "ViaRewind is already initialized");
public static void init(ViaRewindPlatform platform, ViaRewindConfig config) {
Preconditions.checkArgument(ViaRewind.platform == null, "ViaRewind is already initialized");
ViaRewind.platform = platform;
ViaRewind.config = config;
}
ViaRewind.platform = platform;
ViaRewind.config = config;
}
public static ViaRewindPlatform getPlatform() {
return ViaRewind.platform;
}
public static ViaRewindPlatform getPlatform() {
return ViaRewind.platform;
}
public static ViaRewindConfig getConfig() {
return ViaRewind.config;
}
public static ViaRewindConfig getConfig() {
return ViaRewind.config;
}
}
@@ -1,6 +1,6 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2016-2023 ViaVersion and contributors
* Copyright (C) 2018-2026 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -15,67 +15,129 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind;
import com.viaversion.viaversion.util.Config;
import java.io.File;
import java.io.InputStream;
import java.net.URL;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.logging.Logger;
public class ViaRewindConfig extends Config implements com.viaversion.viarewind.api.ViaRewindConfig {
public ViaRewindConfig(File configFile) {
super(configFile);
reload();
private CooldownIndicator cooldownIndicator;
private boolean replaceAdventureMode;
private boolean replaceParticles;
private int maxBookPages;
private int maxBookPageSize;
private boolean emulateWorldBorder;
private boolean alwaysShowOriginalMobName;
private String worldBorderParticle;
private boolean enableOffhand;
private String offhandCommand;
private boolean emulateLevitationEffect;
private boolean handlePlayerCombatPacket;
public ViaRewindConfig(File configFile, Logger logger) {
super(configFile, logger);
}
@Override
public void reload() {
super.reload();
loadFields();
}
private void loadFields() {
cooldownIndicator = CooldownIndicator.valueOf(getString("cooldown-indicator", "TITLE").toUpperCase());
replaceAdventureMode = getBoolean("replace-adventure", false);
replaceParticles = getBoolean("replace-particles", false);
maxBookPages = getInt("max-book-pages", 100);
maxBookPageSize = getInt("max-book-page-length", 5000);
emulateWorldBorder = getBoolean("emulate-world-border", true);
alwaysShowOriginalMobName = getBoolean("always-show-original-mob-name", true);
worldBorderParticle = getString("world-border-particle", "fireworksSpark");
enableOffhand = getBoolean("enable-offhand", true);
offhandCommand = getString("offhand-command", "/offhand");
emulateLevitationEffect = getBoolean("emulate-levitation-effect", true);
handlePlayerCombatPacket = getBoolean("handle-player-combat-packet", true);
}
@Override
public CooldownIndicator getCooldownIndicator() {
return CooldownIndicator.valueOf(getString("cooldown-indicator", "TITLE").toUpperCase());
return cooldownIndicator;
}
@Override
public boolean isReplaceAdventureMode() {
return getBoolean("replace-adventure", false);
return replaceAdventureMode;
}
@Override
public boolean isReplaceParticles() {
return getBoolean("replace-particles", false);
return replaceParticles;
}
@Override
public int getMaxBookPages() {
return getInt("max-book-pages", 100);
return maxBookPages;
}
@Override
public int getMaxBookPageSize() {
return getInt("max-book-page-length", 5000);
return maxBookPageSize;
}
@Override
public boolean isEmulateWorldBorder() {
return getBoolean("emulate-world-border", true);
}
@Override
public boolean isEmulateWorldBorder() {
return emulateWorldBorder;
}
@Override
public String getWorldBorderParticle() {
return getString("world-border-particle", "fireworksSpark");
}
@Override
public boolean alwaysShowOriginalMobName() {
return alwaysShowOriginalMobName;
}
@Override
@Override
public String getWorldBorderParticle() {
return worldBorderParticle;
}
@Override
public boolean isEnableOffhand() {
return enableOffhand;
}
@Override
public String getOffhandCommand() {
return offhandCommand;
}
@Override
public boolean emulateLevitationEffect() {
return emulateLevitationEffect;
}
@Override
public boolean handlePlayerCombatPacket() {
return handlePlayerCombatPacket;
}
@Override
public URL getDefaultConfigURL() {
return getClass().getClassLoader().getResource("assets/viarewind/config.yml");
}
@Override
protected void handleConfig(Map<String, Object> map) {
public InputStream getDefaultConfigInputStream() {
return getClass().getClassLoader().getResourceAsStream("assets/viarewind/config.yml");
}
@Override
protected void handleConfig(Map<String, Object> map) {
}
@Override
@@ -1,6 +1,6 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2016-2023 ViaVersion and contributors
* Copyright (C) 2018-2026 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -15,19 +15,29 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind;
import com.viaversion.viarewind.api.ViaRewindPlatform;
import com.viaversion.viaversion.api.Via;
import net.md_5.bungee.api.plugin.Plugin;
import java.io.File;
import java.util.logging.Logger;
public class BungeePlugin extends Plugin implements ViaRewindPlatform {
public class ViaRewindPlatformImpl implements ViaRewindPlatform {
@Override
public void onLoad() {
Via.getManager().addEnableListener(() -> this.init(new File(getDataFolder(), "config.yml")));
}
private final Logger logger;
public ViaRewindPlatformImpl() {
logger = Via.getPlatform().createLogger("ViaRewind");
init(new File(getDataFolder(), "viarewind.yml"));
}
@Override
public Logger getLogger() {
return logger;
}
@Override
public File getDataFolder() {
return Via.getPlatform().getDataFolder();
}
}
@@ -1,6 +1,6 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2016-2023 ViaVersion and contributors
* Copyright (C) 2018-2026 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -15,7 +15,6 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.api;
import com.viaversion.viaversion.api.configuration.Config;
@@ -25,62 +24,97 @@ import com.viaversion.viaversion.api.configuration.Config;
*/
public interface ViaRewindConfig extends Config {
enum CooldownIndicator {
TITLE, ACTION_BAR, BOSS_BAR, DISABLED
}
/**
* Specifies how 1.8.x clients should see the cooldown indicator
* You can choose between TITLE, ACTION_BAR, BOSS_BAR and DISABLED
* ONLY DISABLE IF YOU HAVE 1.9 COOLDOWN DISABLED ON YOUR SERVER
* 1.8 PLAYERS MAY ASK WHY PVP IS NOT WORKING OTHERWISE
*
* @return the cooldown indicator
*/
CooldownIndicator getCooldownIndicator();
/**
* Specifies how 1.8.x clients should see the cooldown indicator
* You can choose between TITLE, ACTION_BAR, BOSS_BAR and DISABLED
* ONLY DISABLE IF YOU HAVE 1.9 COOLDOWN DISABLED ON YOUR SERVER
* 1.8 PLAYERS MAY ASK WHY PVP IS NOT WORKING OTHERWISE
*
* @return the cooldown indicator
*/
CooldownIndicator getCooldownIndicator();
/**
* Replaces Adventure mode with Survival mode for 1.7.x clients
* Enable this option if your server is using the 'CanDestroy'
* or 'CanPlaceOn' flags on items
*
* @return true if enabled
*/
boolean isReplaceAdventureMode();
/**
* Replaces Adventure mode with Survival mode for 1.7.x clients
* Enable this option if your server is using the 'CanDestroy'
* or 'CanPlaceOn' flags on items
*
* @return true if enabled
*/
boolean isReplaceAdventureMode();
/**
* Whether 1.9 particles should be replaced by similar ones in
* 1.8 and lower
*
* @return true if enabled
*/
boolean isReplaceParticles();
/**
* Whether 1.9 particles should be replaced by similar ones in
* 1.8 and lower
*
* @return true if enabled
*/
boolean isReplaceParticles();
/**
* Max amount of pages for written books before a client gets kicked
*
* @return the max amount of pages
*/
int getMaxBookPages();
/**
* Max amount of pages for written books before a client gets kicked
*
* @return the max amount of pages
*/
int getMaxBookPages();
/**
* Max amount of characters in the json (!) string of a book page before a client gets kicked
*
* @return the max amount of characters
*/
int getMaxBookPageSize();
/**
* Max amount of characters in the json (!) string of a book page before a client gets kicked
*
* @return the max amount of characters
*/
int getMaxBookPageSize();
/**
* Whether to emulate the 1.8+ world border for 1.7.x clients
*
* @return true if enabled
*/
boolean isEmulateWorldBorder();
/**
* Whether to emulate the 1.8+ world border for 1.7.x clients
*
* @return true if enabled
*/
boolean isEmulateWorldBorder();
/**
* Always shows the original mob's name instead of only when hovering over them with the cursor.
*
* @return true if enabled
*/
boolean alwaysShowOriginalMobName();
/**
* The particle to show the world border for the 1.8+ world border for 1.7.x clients
*
* @return the particle name (see <a href="https://wiki.vg/index.php?title=Protocol&oldid=7368#Particle_2">Particle registry for Packet</a>)
*/
String getWorldBorderParticle();
/**
* The particle to show the world border for the 1.8+ world border for 1.7.x clients
*
* @return the particle name
*/
String getWorldBorderParticle();
/**
* If enabled, 1.8 players on 1.9+ servers can use /offhand to switch items between their main hand and offhand.
*
* @return true if enabled
*/
boolean isEnableOffhand();
/**
* Allows to define the offhand command
*
* @return the offhand command
*/
String getOffhandCommand();
/**
* If enabled, 1.8 players on 1.9+ servers will also experience the levitation effect by sending velocity packets.
*
* @return true if enabled
*/
boolean emulateLevitationEffect();
/**
* If enabled, 1.8 players will handle the player combat packet added in 1.9 by showing the custom death message above the hotbar.
*
* @return true if enabled
*/
boolean handlePlayerCombatPacket();
enum CooldownIndicator {
TITLE, ACTION_BAR, BOSS_BAR, DISABLED
}
}
@@ -1,6 +1,6 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2016-2023 ViaVersion and contributors
* Copyright (C) 2018-2026 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -15,18 +15,16 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.api;
import com.viaversion.viarewind.ViaRewind;
import com.viaversion.viarewind.ViaRewindConfig;
import com.viaversion.viarewind.protocol.protocol1_7_2_5to1_7_6_10.Protocol1_7_2_5To1_7_6_10;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.Protocol1_7_6_10To1_8;
import com.viaversion.viarewind.protocol.protocol1_8to1_9.Protocol1_8To1_9;
import com.viaversion.viarewind.protocol.v1_7_6_10to1_7_2_5.Protocol1_7_6_10To1_7_2_5;
import com.viaversion.viarewind.protocol.v1_8to1_7_6_10.Protocol1_8To1_7_6_10;
import com.viaversion.viarewind.protocol.v1_9to1_8.Protocol1_9To1_8;
import com.viaversion.viaversion.api.Via;
import com.viaversion.viaversion.api.protocol.ProtocolManager;
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
import java.io.File;
import java.util.logging.Logger;
@@ -35,32 +33,71 @@ import java.util.logging.Logger;
*/
public interface ViaRewindPlatform {
String VERSION = "${version}";
String IMPL_VERSION = "${impl_version}";
String VERSION = "${version}";
String IMPL_VERSION = "${impl_version}";
/**
* Initialize ViaRewind
*/
default void init(final File configFile) {
ViaRewindConfig config = new ViaRewindConfig(configFile);
config.reload();
Via.getManager().getConfigurationProvider().register(config);
default void init(final File configFile) {
init(new ViaRewindConfig(configFile, getLogger()));
}
ViaRewind.init(this, config);
/**
* Initialize ViaRewind
*/
default void init(final com.viaversion.viarewind.api.ViaRewindConfig config) {
config.reload();
Via.getManager().getConfigurationProvider().register(config);
Via.getManager().getSubPlatforms().add(IMPL_VERSION);
ViaRewind.init(this, config);
final ProtocolManager protocolManager = Via.getManager().getProtocolManager();
Via.getManager().getSubPlatforms().add(IMPL_VERSION);
protocolManager.registerProtocol(new Protocol1_7_2_5To1_7_6_10(), ProtocolVersion.v1_7_1, ProtocolVersion.v1_7_6);
protocolManager.registerProtocol(new Protocol1_7_6_10To1_8(), ProtocolVersion.v1_7_6, ProtocolVersion.v1_8);
protocolManager.registerProtocol(new Protocol1_8To1_9(), ProtocolVersion.v1_8, ProtocolVersion.v1_9);
}
getLogger().info("Registering protocols...");
final ProtocolManager protocolManager = Via.getManager().getProtocolManager();
protocolManager.registerProtocol(new Protocol1_7_6_10To1_7_2_5(), ProtocolVersion.v1_7_2, ProtocolVersion.v1_7_6);
protocolManager.registerProtocol(new Protocol1_8To1_7_6_10(), ProtocolVersion.v1_7_6, ProtocolVersion.v1_8);
protocolManager.registerProtocol(new Protocol1_9To1_8(), ProtocolVersion.v1_8, ProtocolVersion.v1_9);
}
/**
* Get the platform logger
*
* @return the logger
*/
Logger getLogger();
/**
* Returns ViaRewind's data folder.
*
* @return data folder
*/
File getDataFolder();
/**
* Returns the platform's compression handler name. Only used in the 1.8 -> 1.7 protocol.
*
* @return the compression handler name
*/
default String compressHandlerName() {
return "compress";
}
/**
* Returns the platform's decompression handler name. Only used in the 1.8 -> 1.7 protocol.
*
* @return the decompression handler name
*/
default String decompressHandlerName() {
return "decompress";
}
/**
* Returns whether the platform's compression handler also writes the packet length. Only used in the 1.8 -> 1.7 protocol.
*
* @return true if the compression handler writes the packet length
*/
default boolean compressHandlerWritesLength() {
return false;
}
/**
* Get the platform logger
*
* @return the logger
*/
Logger getLogger();
}
@@ -0,0 +1,157 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2018-2026 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.api.compression;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufAllocator;
import java.util.zip.DataFormatException;
import java.util.zip.Deflater;
import java.util.zip.Inflater;
/**
* A ThreadLocal-based compression provider that either uses Velocity's native compression
* or falls back to Java's built-in compression (Deflater/Inflater).
*/
public final class ThreadLocalCompressionProvider {
private static final boolean VELOCITY_NATIVES_AVAILABLE;
static {
boolean velocityAvailable = false;
try {
Class.forName("com.velocitypowered.natives.compression.VelocityCompressor");
velocityAvailable = true;
} catch (final ClassNotFoundException ignored) {
}
VELOCITY_NATIVES_AVAILABLE = velocityAvailable;
}
// ThreadLocal for Java's Deflater (used when Velocity natives are not available)
private static final ThreadLocal<Deflater> JAVA_DEFLATER = ThreadLocal.withInitial(Deflater::new);
// ThreadLocal for Java's Inflater (used when Velocity natives are not available)
private static final ThreadLocal<Inflater> JAVA_INFLATER = ThreadLocal.withInitial(Inflater::new);
private ThreadLocalCompressionProvider() {
}
/**
* Compresses data from the source buffer into the destination buffer.
*
* @param source the source buffer containing uncompressed data
* @param destination the destination buffer to write compressed data to
* @throws DataFormatException if compression fails
*/
public static void deflate(final ByteBuf source, final ByteBuf destination) throws DataFormatException {
if (VELOCITY_NATIVES_AVAILABLE) {
deflateVelocity(source, destination);
} else {
deflateJava(source, destination);
}
}
/**
* Decompresses data from the source buffer into the destination buffer.
*
* @param source the source buffer containing compressed data
* @param destination the destination buffer to write decompressed data to
* @param expectedSize the expected size of the decompressed data
* @throws DataFormatException if decompression fails
*/
public static void inflate(final ByteBuf source, final ByteBuf destination, final int expectedSize) throws DataFormatException {
if (VELOCITY_NATIVES_AVAILABLE) {
inflateVelocity(source, destination, expectedSize);
} else {
inflateJava(source, destination, expectedSize);
}
}
// Java native implementation
private static void deflateJava(final ByteBuf source, final ByteBuf destination) throws DataFormatException {
ByteBuf temp = source;
if (!source.hasArray()) {
temp = ByteBufAllocator.DEFAULT.heapBuffer().writeBytes(source);
} else {
source.retain();
}
ByteBuf output = ByteBufAllocator.DEFAULT.heapBuffer();
try {
final Deflater deflater = JAVA_DEFLATER.get();
deflater.setInput(temp.array(), temp.arrayOffset() + temp.readerIndex(), temp.readableBytes());
deflater.finish();
while (!deflater.finished()) {
output.ensureWritable(4096);
output.writerIndex(output.writerIndex() + deflater.deflate(output.array(), output.arrayOffset() + output.writerIndex(), output.writableBytes()));
}
destination.writeBytes(output);
} finally {
output.release();
temp.release();
JAVA_DEFLATER.get().reset();
}
}
private static void inflateJava(final ByteBuf source, final ByteBuf destination, final int expectedSize) throws DataFormatException {
ByteBuf temp = source;
if (!source.hasArray()) {
temp = ByteBufAllocator.DEFAULT.heapBuffer().writeBytes(source);
} else {
source.retain();
}
ByteBuf output = ByteBufAllocator.DEFAULT.heapBuffer(expectedSize, expectedSize);
try {
final Inflater inflater = JAVA_INFLATER.get();
inflater.setInput(temp.array(), temp.arrayOffset() + temp.readerIndex(), temp.readableBytes());
output.writerIndex(output.writerIndex() + inflater.inflate(output.array(), output.arrayOffset(), expectedSize));
destination.writeBytes(output);
} finally {
output.release();
temp.release();
JAVA_INFLATER.get().reset();
}
}
// Velocity native implementation
private static void deflateVelocity(final ByteBuf source, final ByteBuf destination) throws DataFormatException {
VelocityHolder.deflate(source, destination);
}
private static void inflateVelocity(final ByteBuf source, final ByteBuf destination, final int expectedSize) throws DataFormatException {
VelocityHolder.inflate(source, destination, expectedSize);
}
private static final class VelocityHolder {
private static final ThreadLocal<com.velocitypowered.natives.compression.VelocityCompressor> COMPRESSOR =
ThreadLocal.withInitial(() -> com.velocitypowered.natives.util.Natives.compress.get().create(-1));
static void deflate(final ByteBuf source, final ByteBuf destination) throws DataFormatException {
COMPRESSOR.get().deflate(source, destination);
}
static void inflate(final ByteBuf source, final ByteBuf destination, final int expectedSize) throws DataFormatException {
COMPRESSOR.get().inflate(source, destination, expectedSize);
}
}
}
@@ -0,0 +1,49 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2018-2026 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.api.data;
import com.viaversion.nbt.tag.CompoundTag;
import com.viaversion.viabackwards.api.data.BackwardsMappingData;
import com.viaversion.viarewind.ViaRewind;
import com.viaversion.viaversion.api.data.FullMappings;
import com.viaversion.viaversion.api.data.LegacyFullStringMappingsBase;
import com.viaversion.viaversion.api.data.MappingDataLoader;
import com.viaversion.viaversion.api.data.Mappings;
import java.util.logging.Logger;
public class RewindMappingData extends BackwardsMappingData {
public RewindMappingData(String unmappedVersion, String mappedVersion) {
super(unmappedVersion, mappedVersion);
}
@Override
protected Logger getLogger() {
return ViaRewind.getPlatform().getLogger();
}
@Override
protected CompoundTag readMappingsFile(String name) {
return RewindMappingDataLoader.INSTANCE.loadNBTFromDir(name);
}
@Override
protected FullMappings createFullMappings(MappingDataLoader.IdentifiersPair identifiersPair, Mappings mappings) {
return new LegacyFullStringMappingsBase(identifiersPair, mappings);
}
}
@@ -0,0 +1,43 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2018-2026 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.api.data;
import com.viaversion.viabackwards.api.data.BackwardsMappingDataLoader;
import com.viaversion.viarewind.ViaRewind;
import java.io.File;
import java.util.logging.Logger;
public class RewindMappingDataLoader extends BackwardsMappingDataLoader {
public static final RewindMappingDataLoader INSTANCE = new RewindMappingDataLoader();
public RewindMappingDataLoader() {
super(RewindMappingDataLoader.class, "assets/viarewind/data/");
}
@Override
public Logger getLogger() {
return ViaRewind.getPlatform().getLogger();
}
@Override
public File getDataFolder() {
return ViaRewind.getPlatform().getDataFolder();
}
}
@@ -1,102 +0,0 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2016-2023 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.api.minecraft;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.minecraft.metadata.Metadata;
import com.viaversion.viaversion.api.protocol.Protocol;
import java.util.List;
/**
* Represents a model that is replacing an entity on the client side (e.g. armor stand)
*/
public abstract class EntityModel<T extends Protocol<?, ?, ?, ?>> {
protected final UserConnection user;
protected final T protocol;
public EntityModel(final UserConnection user, final T protocol) {
this.user = user;
this.protocol = protocol;
}
/**
* @return The entity id of the entity this model is replacing
*/
public abstract int getEntityId();
/**
* Updates the position of the entity this model is replacing
*
* @param x The new x position
* @param y The new y position
* @param z The new z position
*/
public abstract void updateReplacementPosition(final double x, final double y, final double z);
/**
* Handles the original movement packet of the entity this model is replacing
*
* @param x The x position
* @param y The y position
* @param z The z position
*/
public abstract void handleOriginalMovementPacket(final double x, final double y, final double z);
/**
* Sets the yaw and pitch of the entity this model is replacing
*
* @param yaw The new yaw
* @param pitch The new pitch
*/
public abstract void setYawPitch(final float yaw, final float pitch);
/**
* Sets the head yaw of the entity this model is replacing
*
* @param yaw The new head yaw
*/
public abstract void setHeadYaw(final float yaw);
/**
* Spawns the entity this model is replacing
*/
public abstract void sendSpawnPacket();
/**
* Destroys the entity this model is replacing
*/
public abstract void deleteEntity();
/**
* Updates the metadata of the entity this model is replacing
*
* @param metadataList The new metadata
*/
public abstract void updateMetadata(final List<Metadata> metadataList);
public UserConnection getUser() {
return user;
}
public T getProtocol() {
return protocol;
}
}
@@ -1,78 +0,0 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2016-2023 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.api.minecraft;
import com.viaversion.viaversion.api.minecraft.chunks.ChunkSection;
import com.viaversion.viaversion.api.minecraft.chunks.NibbleArray;
public class ExtendedBlockStorage {
private final byte[] blockLSBArray = new byte[4096];
private final NibbleArray blockMetadataArray = new NibbleArray(this.blockLSBArray.length);
private final NibbleArray blockLightArray = new NibbleArray(this.blockLSBArray.length);
private NibbleArray blockMSBArray;
private NibbleArray skyLightArray;
public ExtendedBlockStorage(final boolean skylight) {
if (skylight) {
this.skyLightArray = new NibbleArray(this.blockLSBArray.length);
}
}
public void setBlockId(final int x, final int y, final int z, final int value) {
this.blockLSBArray[ChunkSection.index(x, y, z)] = (byte) (value & 255);
if (value > 255) {
this.getOrCreateBlockMSBArray().set(x, y, z, (value & 0xF00) >> 8);
} else if (this.blockMSBArray != null) {
this.blockMSBArray.set(x, y, z, 0);
}
}
public void setBlockMetadata(final int x, final int y, final int z, final int value) {
this.blockMetadataArray.set(x, y, z, value);
}
public boolean hasBlockMSBArray() {
return this.blockMSBArray != null;
}
public byte[] getBlockLSBArray() {
return this.blockLSBArray;
}
public NibbleArray getOrCreateBlockMSBArray() {
if (this.blockMSBArray == null) {
return this.blockMSBArray = new NibbleArray(this.blockLSBArray.length);
}
return this.blockMSBArray;
}
public NibbleArray getBlockMetadataArray() {
return this.blockMetadataArray;
}
public NibbleArray getBlockLightArray() {
return this.blockLightArray;
}
public NibbleArray getSkyLightArray() {
return this.skyLightArray;
}
}
@@ -0,0 +1,55 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2018-2026 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.api.minecraft.entitydata;
import com.viaversion.viarewind.api.type.RewindTypes;
import com.viaversion.viaversion.api.minecraft.entitydata.EntityDataType;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.Types;
public enum EntityDataTypes1_7_6_10 implements EntityDataType {
BYTE(0, Types.BYTE),
SHORT(1, Types.SHORT),
INT(2, Types.INT),
FLOAT(3, Types.FLOAT),
STRING(4, Types.STRING),
ITEM(5, RewindTypes.COMPRESSED_NBT_ITEM),
POSITION(6, Types.VECTOR);
private final int typeID;
private final Type<?> type;
EntityDataTypes1_7_6_10(int typeID, Type<?> type) {
this.typeID = typeID;
this.type = type;
}
public static EntityDataTypes1_7_6_10 byId(int id) {
return values()[id];
}
@Override
public int typeId() {
return this.typeID;
}
@Override
public Type<?> type() {
return this.type;
}
}
@@ -1,6 +1,6 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2016-2023 ViaVersion and contributors
* Copyright (C) 2018-2026 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -15,23 +15,22 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.utils.math;
package com.viaversion.viarewind.api.minecraft.math;
public class AABB {
Vector3d min;
Vector3d max;
Vector3d min;
Vector3d max;
public AABB(Vector3d min, Vector3d max) {
this.min = min;
this.max = max;
}
public AABB(Vector3d min, Vector3d max) {
this.min = min;
this.max = max;
}
public Vector3d getMin() {
return this.min;
}
public Vector3d getMin() {
return this.min;
}
public Vector3d getMax() {
return this.max;
}
public Vector3d getMax() {
return this.max;
}
}
@@ -1,6 +1,6 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2016-2023 ViaVersion and contributors
* Copyright (C) 2018-2026 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -15,23 +15,22 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.utils.math;
package com.viaversion.viarewind.api.minecraft.math;
public class Ray3d {
Vector3d start;
Vector3d dir;
Vector3d start;
Vector3d dir;
public Ray3d(Vector3d start, Vector3d dir) {
this.start = start;
this.dir = dir;
}
public Ray3d(Vector3d start, Vector3d dir) {
this.start = start;
this.dir = dir;
}
public Vector3d getStart() {
return this.start;
}
public Vector3d getStart() {
return this.start;
}
public Vector3d getDir() {
return this.dir;
}
public Vector3d getDir() {
return this.dir;
}
}
@@ -0,0 +1,58 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2018-2026 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.api.minecraft.math;
public class RayTracing {
public static Vector3d trace(Ray3d ray, AABB aabb, double distance) {
Vector3d invDir = new Vector3d(1f / ray.dir.x, 1f / ray.dir.y, 1f / ray.dir.z);
boolean signDirX = invDir.x < 0;
boolean signDirY = invDir.y < 0;
boolean signDirZ = invDir.z < 0;
Vector3d bbox = signDirX ? aabb.max : aabb.min;
double tmin = (bbox.x - ray.start.x) * invDir.x;
bbox = signDirX ? aabb.min : aabb.max;
double tmax = (bbox.x - ray.start.x) * invDir.x;
bbox = signDirY ? aabb.max : aabb.min;
double tymin = (bbox.y - ray.start.y) * invDir.y;
bbox = signDirY ? aabb.min : aabb.max;
double tymax = (bbox.y - ray.start.y) * invDir.y;
if (tmin > tymax || tymin > tmax) return null;
if (tymin > tmin) tmin = tymin;
if (tymax < tmax) tmax = tymax;
bbox = signDirZ ? aabb.max : aabb.min;
double tzmin = (bbox.z - ray.start.z) * invDir.z;
bbox = signDirZ ? aabb.min : aabb.max;
double tzmax = (bbox.z - ray.start.z) * invDir.z;
if (tmin > tzmax || tzmin > tmax) return null;
if (tzmin > tmin) tmin = tzmin;
if (tzmax < tmax) tmax = tzmax;
return tmin <= distance && tmax > 0 ? ray.start.clone().add(ray.dir.clone().normalize().multiply(tmin)) : null;
}
}
@@ -0,0 +1,99 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2018-2026 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.api.minecraft.math;
import com.viaversion.viarewind.protocol.v1_9to1_8.storage.EntityTracker1_9;
import com.viaversion.viaversion.api.minecraft.Vector;
@Deprecated // ?????????
public class RelativeMoveUtil {
public static Vector[] calculateRelativeMoves(EntityTracker1_9 tracker, int entityId, int relX, int relY, int relZ) {
int x;
int y;
int z;
Vector offset = tracker.getEntityOffset(entityId);
if (offset != null) {
relX += offset.blockX();
relY += offset.blockY();
relZ += offset.blockZ();
}
if (relX > Short.MAX_VALUE) {
x = relX - Short.MAX_VALUE;
relX = Short.MAX_VALUE;
} else if (relX < Short.MIN_VALUE) {
x = relX - Short.MIN_VALUE;
relX = Short.MIN_VALUE;
} else {
x = 0;
}
if (relY > Short.MAX_VALUE) {
y = relY - Short.MAX_VALUE;
relY = Short.MAX_VALUE;
} else if (relY < Short.MIN_VALUE) {
y = relY - Short.MIN_VALUE;
relY = Short.MIN_VALUE;
} else {
y = 0;
}
if (relZ > Short.MAX_VALUE) {
z = relZ - Short.MAX_VALUE;
relZ = Short.MAX_VALUE;
} else if (relZ < Short.MIN_VALUE) {
z = relZ - Short.MIN_VALUE;
relZ = Short.MIN_VALUE;
} else {
z = 0;
}
int sentRelX, sentRelY, sentRelZ;
Vector[] moves;
if (relX > Byte.MAX_VALUE * 128 || relX < Byte.MIN_VALUE * 128 || relY > Byte.MAX_VALUE * 128 || relY < Byte.MIN_VALUE * 128 || relZ > Byte.MAX_VALUE * 128 || relZ < Byte.MIN_VALUE * 128) {
byte relX1 = (byte) (relX / 256);
byte relX2 = (byte) (Math.round((relX - relX1 * 128) / 128f));
byte relY1 = (byte) (relY / 256);
byte relY2 = (byte) (Math.round((relY - relY1 * 128) / 128f));
byte relZ1 = (byte) (relZ / 256);
byte relZ2 = (byte) (Math.round((relZ - relZ1 * 128) / 128f));
sentRelX = relX1 + relX2;
sentRelY = relY1 + relY2;
sentRelZ = relZ1 + relZ2;
moves = new Vector[]{new Vector(relX1, relY1, relZ1), new Vector(relX2, relY2, relZ2)};
} else {
sentRelX = Math.round(relX / 128f);
sentRelY = Math.round(relY / 128f);
sentRelZ = Math.round(relZ / 128f);
moves = new Vector[]{new Vector(sentRelX, sentRelY, sentRelZ)};
}
x = x + relX - sentRelX * 128;
y = y + relY - sentRelY * 128;
z = z + relZ - sentRelZ * 128;
tracker.setEntityOffset(entityId, new Vector(x, y, z));
return moves;
}
}
@@ -0,0 +1,128 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2018-2026 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.api.minecraft.math;
import java.util.Objects;
public class Vector3d {
double x, y, z;
public Vector3d(double x, double y, double z) {
this.x = x;
this.y = y;
this.z = z;
}
public Vector3d() {
}
public void set(Vector3d vec) {
this.x = vec.x;
this.y = vec.y;
this.z = vec.z;
}
public Vector3d set(double x, double y, double z) {
this.x = x;
this.y = y;
this.z = z;
return this;
}
public Vector3d multiply(double a) {
this.x *= a;
this.y *= a;
this.z *= a;
return this;
}
public Vector3d add(Vector3d vec) {
this.x += vec.x;
this.y += vec.y;
this.z += vec.z;
return this;
}
public Vector3d substract(Vector3d vec) {
this.x -= vec.x;
this.y -= vec.y;
this.z -= vec.z;
return this;
}
public double length() {
return Math.sqrt(lengthSquared());
}
public double lengthSquared() {
return this.x * this.x + this.y * this.y + this.z * this.z;
}
public Vector3d normalize() {
double length = length();
multiply(1.0 / length);
return this;
}
@Override
public Vector3d clone() {
return new Vector3d(this.x, this.y, this.z);
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Vector3d vector3d = (Vector3d) o;
return Double.compare(vector3d.x, x) == 0 && Double.compare(vector3d.y, y) == 0 && Double.compare(vector3d.z, z) == 0;
}
@Override
public int hashCode() {
return Objects.hash(x, y, z);
}
@Override
public String toString() {
return "Vector3d{" + "x=" + x + ", y=" + y + ", z=" + z + '}';
}
public double getX() {
return this.x;
}
public void setX(double x) {
this.x = x;
}
public double getY() {
return this.y;
}
public void setY(double y) {
this.y = y;
}
public double getZ() {
return this.z;
}
public void setZ(double z) {
this.z = z;
}
}
@@ -1,6 +1,6 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2016-2023 ViaVersion and contributors
* Copyright (C) 2018-2026 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -15,8 +15,7 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.api.netty;
package com.viaversion.viarewind.api.minecraft.netty;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerAdapter;
@@ -1,6 +1,6 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2016-2023 ViaVersion and contributors
* Copyright (C) 2018-2026 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -15,17 +15,26 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.api.minecraft.netty;
package com.viaversion.viarewind.api.netty;
import com.viaversion.viaversion.api.type.Types;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToByteEncoder;
public class ForwardMessageToByteEncoder extends MessageToByteEncoder<ByteBuf> {
@Override
protected void encode(ChannelHandlerContext ctx, ByteBuf msg, ByteBuf out) {
out.writeBytes(msg);
}
private final boolean writeLength;
public ForwardMessageToByteEncoder(final boolean writeLength) {
this.writeLength = writeLength;
}
@Override
protected void encode(ChannelHandlerContext ctx, ByteBuf msg, ByteBuf out) {
if (writeLength) {
Types.VAR_INT.writePrimitive(out, msg.readableBytes());
}
out.writeBytes(msg);
}
}
@@ -1,86 +0,0 @@
package com.viaversion.viarewind.api.rewriter;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.model.MetaIndex1_7_6_10To1_8;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.types.metadata.MetaType1_7_6_10;
import com.viaversion.viaversion.api.connection.StoredObject;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.data.entity.ClientEntityIdChangeListener;
import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_10;
import com.viaversion.viaversion.api.minecraft.metadata.Metadata;
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
import com.viaversion.viaversion.util.Pair;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class ReplacementEntityTracker extends StoredObject implements ClientEntityIdChangeListener {
private final Map<EntityTypes1_10.EntityType, Pair<EntityTypes1_10.EntityType, String>> ENTITY_REPLACEMENTS = new HashMap<>();
private final Map<Integer, EntityTypes1_10.EntityType> entityMap = new HashMap<>();
private final Map<Integer, EntityTypes1_10.EntityType> entityReplacementMap = new HashMap<>();
private int playerId = -1;
private final ProtocolVersion version;
public ReplacementEntityTracker(UserConnection user, final ProtocolVersion version) {
super(user);
this.version = version;
}
public void registerEntity(final EntityTypes1_10.EntityType oldType, final EntityTypes1_10.EntityType newType, final String name) {
ENTITY_REPLACEMENTS.put(oldType, new Pair<>(newType, this.version.getName() + " " + name));
}
public void addEntity(final int entityId, final EntityTypes1_10.EntityType type) {
entityMap.put(entityId, type);
}
public int replaceEntity(final int entityId, final EntityTypes1_10.EntityType type) {
entityReplacementMap.put(entityId, type);
return ENTITY_REPLACEMENTS.get(type).key().getId();
}
public void removeEntity(final int entityId) {
entityMap.remove(entityId);
entityReplacementMap.remove(entityId);
}
public void clear() {
entityMap.clear();
entityReplacementMap.clear();
}
public boolean isReplaced(final EntityTypes1_10.EntityType type) {
return ENTITY_REPLACEMENTS.containsKey(type);
}
public void updateMetadata(final int entityId, final List<Metadata> metadata) throws Exception {
final String name = ENTITY_REPLACEMENTS.get(entityMap.get(entityId)).value();
metadata.add(new Metadata(MetaIndex1_7_6_10To1_8.ENTITY_LIVING_NAME_TAG_VISIBILITY.getNewIndex(), MetaType1_7_6_10.Byte, (byte) 1)); // TODO: Make this definable for 1.8 -> 1.9 ?
metadata.add(new Metadata(MetaIndex1_7_6_10To1_8.ENTITY_LIVING_NAME_TAG.getNewIndex(), MetaType1_7_6_10.String, name));
}
@Override
public void setClientEntityId(int entityId) {
removeEntity(this.playerId);
addEntity(entityId, EntityTypes1_10.EntityType.ENTITY_HUMAN);
this.playerId = entityId;
}
public Map<Integer, EntityTypes1_10.EntityType> getEntityMap() {
return entityMap;
}
public Map<Integer, EntityTypes1_10.EntityType> getEntityReplacementMap() {
return entityReplacementMap;
}
public int getPlayerId() {
return playerId;
}
}
@@ -0,0 +1,42 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2018-2026 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.api.rewriter;
import com.viaversion.viabackwards.api.BackwardsProtocol;
import com.viaversion.viabackwards.api.rewriters.LegacyBlockItemRewriter;
import com.viaversion.viarewind.api.data.RewindMappingDataLoader;
import com.viaversion.viaversion.api.protocol.packet.ClientboundPacketType;
import com.viaversion.viaversion.api.protocol.packet.ServerboundPacketType;
import com.viaversion.viaversion.libs.gson.JsonObject;
public class VRBlockItemRewriter<C extends ClientboundPacketType, S extends ServerboundPacketType, T extends BackwardsProtocol<C, ?, ?, S>> extends LegacyBlockItemRewriter<C, S, T> {
protected VRBlockItemRewriter(T protocol, String name) {
super(protocol, name);
}
@Override
protected JsonObject readMappingsFile(String name) {
return RewindMappingDataLoader.INSTANCE.loadFromDataDir(name);
}
@Override
public String nbtTagName() {
return "VR|" + protocol.getClass().getSimpleName();
}
}
@@ -0,0 +1,66 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2018-2026 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.api.rewriter;
import com.viaversion.viabackwards.api.BackwardsProtocol;
import com.viaversion.viabackwards.api.rewriters.LegacyEntityRewriter;
import com.viaversion.viarewind.ViaRewind;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.minecraft.ClientWorld;
import com.viaversion.viaversion.api.minecraft.entitydata.EntityDataType;
import com.viaversion.viaversion.api.minecraft.entitydata.types.EntityDataTypes1_8;
import com.viaversion.viaversion.api.protocol.packet.ClientboundPacketType;
import com.viaversion.viaversion.api.protocol.remapper.PacketHandler;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.data.entity.EntityTrackerBase;
public abstract class VREntityRewriter<C extends ClientboundPacketType, T extends BackwardsProtocol<C, ?, ?, ?>> extends LegacyEntityRewriter<C, T> {
public VREntityRewriter(T protocol) {
super(protocol, EntityDataTypes1_8.STRING, EntityDataTypes1_8.BYTE);
}
public VREntityRewriter(T protocol, EntityDataType displayType, EntityDataType displayVisibilityType) {
super(protocol, displayType, displayVisibilityType);
}
protected void removeEntities(final UserConnection connection, final int[] entities) {
final EntityTrackerBase tracker = tracker(connection);
for (int entityId : entities) {
tracker.removeEntity(entityId);
}
}
protected PacketHandler getDimensionHandler() {
return wrapper -> {
final int dimension = wrapper.get(Types.BYTE, 0);
final ClientWorld clientWorld = wrapper.user().getClientWorld(protocol.getClass());
clientWorld.setEnvironment(dimension);
};
}
@Override
protected Object getDisplayVisibilityDataValue() {
return (byte) 1;
}
@Override
protected boolean alwaysShowOriginalMobName() {
return ViaRewind.getConfig().alwaysShowOriginalMobName();
}
}
@@ -1,106 +0,0 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2016-2023 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.api.rewriter.item;
import com.viaversion.viaversion.api.minecraft.item.Item;
import com.viaversion.viaversion.libs.opennbt.tag.builtin.CompoundTag;
import com.viaversion.viaversion.libs.opennbt.tag.builtin.StringTag;
import com.viaversion.viaversion.util.ChatColorUtil;
public class Replacement {
private final int id;
private final int data;
private final String name;
private String resetName;
private String bracketName;
public Replacement(final int id) {
this(id, -1);
}
public Replacement(final int id, final int data) {
this(id, data, null);
}
public Replacement(final int id, final String name) {
this(id, -1, name);
}
public Replacement(final int id, final int data, final String name) {
this.id = id;
this.data = data;
this.name = name;
}
public void buildNames(final String protocolVersion) {
if (this.name != null) {
this.resetName = ChatColorUtil.translateAlternateColorCodes("&r" + protocolVersion + " " + this.name);
this.bracketName = ChatColorUtil.translateAlternateColorCodes(" &r&7(" + protocolVersion + " " + this.name + "&r&7)");
}
}
public int getId() {
return id;
}
public int getData() {
return data;
}
public String getName() {
return name;
}
/**
* @param item The item to replace
* @return The replacement for the item or the item if not found
*/
public Item replace(final Item item) {
item.setIdentifier(id); // Set the new id
if (data != -1) {
item.setData((short) data); // Set the new data
}
if (name != null) { // Set the new name
CompoundTag rootTag = item.tag() == null ? new CompoundTag() : item.tag(); // Get root tag or create new one if not exists
if (!rootTag.contains("display")) rootTag.put("display", new CompoundTag()); // Create display tag if not exists
final CompoundTag display = rootTag.get("display");
if (display.contains("Name")) {
final StringTag name = display.get("Name");
if (!name.getValue().equals(resetName) && !name.getValue().endsWith(bracketName)) {
name.setValue(name.getValue() + bracketName); // Append the new name tag
}
} else {
display.put("Name", new StringTag(resetName)); // Set the new name tag
}
item.setTag(rootTag);
}
return item;
}
/**
* @param data The data of the item/block
* @return The replacement data for the item/block
*/
public int replaceData(int data) {
return this.data == -1 ? data : this.data;
}
}
@@ -1,115 +0,0 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2016-2023 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.api.rewriter.item;
import com.viaversion.viarewind.api.minecraft.IdDataCombine;
import com.viaversion.viaversion.api.minecraft.item.Item;
import com.viaversion.viaversion.api.protocol.AbstractProtocol;
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
import com.viaversion.viaversion.api.rewriter.ItemRewriter;
import com.viaversion.viaversion.libs.fastutil.ints.Int2ObjectMap;
import com.viaversion.viaversion.libs.fastutil.ints.Int2ObjectOpenHashMap;
public abstract class ReplacementItemRewriter<T extends AbstractProtocol<?, ?, ?, ?>> implements ItemRewriter<T> {
private final Int2ObjectMap<Replacement> ITEM_REPLACEMENTS = new Int2ObjectOpenHashMap<>();
private final Int2ObjectMap<Replacement> BLOCK_REPLACEMENTS = new Int2ObjectOpenHashMap<>();
private final T protocol;
private final ProtocolVersion protocolVersion;
public ReplacementItemRewriter(final T protocol, final ProtocolVersion protocolVersion) {
this.protocol = protocol;
this.protocolVersion = protocolVersion;
}
public void registerItem(int id, Replacement replacement) {
registerItem(id, -1, replacement);
}
public void registerBlock(int id, Replacement replacement) {
registerBlock(id, -1, replacement);
}
public void registerItemBlock(int id, Replacement replacement) {
registerItemBlock(id, -1, replacement);
}
public void registerItem(int id, int data, Replacement replacement) {
ITEM_REPLACEMENTS.put(generateTrackingId(id, data), replacement);
replacement.buildNames(protocolVersion.getName());
}
public void registerBlock(int id, int data, Replacement replacement) {
BLOCK_REPLACEMENTS.put(generateTrackingId(id, data), replacement);
replacement.buildNames(protocolVersion.getName());
}
public void registerItemBlock(int id, int data, Replacement replacement) {
registerItem(id, data, replacement);
registerBlock(id, data, replacement);
}
/**
* @param item The item to replace
* @return The replacement for the item or the item if not found
*/
public Item replace(Item item) {
Replacement replacement = ITEM_REPLACEMENTS.get(generateTrackingId(item.identifier(), item.data()));
if (replacement == null) replacement = ITEM_REPLACEMENTS.get(generateTrackingId(item.identifier(), -1));
return replacement == null ? item : replacement.replace(item);
}
/**
* @param id The id of the item/block
* @param data The data of the item/block
* @return The replacement for the item/block or null if not found
*/
public Replacement replace(int id, int data) {
Replacement replacement = BLOCK_REPLACEMENTS.get(generateTrackingId(id, data));
if (replacement == null) replacement = BLOCK_REPLACEMENTS.get(generateTrackingId(id, -1));
return replacement;
}
/**
* @param combined The combined id and data
* @return The generated tracking id for the item/block
*/
public int replace(int combined) {
final int data = IdDataCombine.dataFromCombined(combined);
final Replacement replace = replace(IdDataCombine.idFromCombined(combined), data);
return replace != null ? IdDataCombine.toCombined(replace.getId(), replace.replaceData(data)) : combined;
}
/**
* @param id The id of the item/block
* @param data The data of the item/block
* @return The generated tracking id for the item/block
*/
private int generateTrackingId(int id, int data) {
return (id << 16) | (data & 0xFFFF);
}
@Override
public T protocol() {
return this.protocol;
}
}
@@ -1,6 +1,6 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2016-2023 ViaVersion and contributors
* Copyright (C) 2018-2026 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -15,31 +15,30 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.types.primitive;
package com.viaversion.viarewind.api.type;
import com.viaversion.viaversion.api.type.Type;
import io.netty.buffer.ByteBuf;
public class ByteIntArrayType extends Type<int[]> {
public class IntArrayType extends Type<int[]> {
public ByteIntArrayType() {
super(int[].class);
}
public IntArrayType() {
super(int[].class);
}
@Override
public int[] read(ByteBuf byteBuf) throws Exception {
byte size = byteBuf.readByte();
int[] array = new int[size];
for (byte i = 0; i < size; i++) {
array[i] = byteBuf.readInt();
}
return array;
}
@Override
public int[] read(ByteBuf byteBuf) {
byte size = byteBuf.readByte();
int[] array = new int[size];
for (byte i = 0; i < size; i++) {
array[i] = byteBuf.readInt();
}
return array;
}
@Override
public void write(ByteBuf byteBuf, int[] array) throws Exception {
byteBuf.writeByte(array.length);
for (int i : array) byteBuf.writeInt(i);
}
@Override
public void write(ByteBuf byteBuf, int[] array) {
byteBuf.writeByte(array.length);
for (int i : array) byteBuf.writeInt(i);
}
}
@@ -0,0 +1,52 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2018-2026 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.api.type;
import com.viaversion.viaversion.api.minecraft.BlockPosition;
import com.viaversion.viaversion.api.type.Type;
import io.netty.buffer.ByteBuf;
import java.util.function.IntFunction;
public class PositionVarYType<T extends Number> extends Type<BlockPosition> {
private final Type<T> yType;
private final IntFunction<T> toY;
public PositionVarYType(final Type<T> yType, final IntFunction<T> toY) {
super(BlockPosition.class);
this.yType = yType;
this.toY = toY;
}
@Override
public BlockPosition read(ByteBuf buffer) {
final int x = buffer.readInt();
final int y = yType.read(buffer).intValue();
final int z = buffer.readInt();
return new BlockPosition(x, y, z);
}
@Override
public void write(ByteBuf buffer, BlockPosition value) {
buffer.writeInt(value.x());
yType.write(buffer, this.toY.apply(value.y()));
buffer.writeInt(value.z());
}
}
@@ -0,0 +1,52 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2018-2026 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.api.type;
import com.viaversion.nbt.tag.CompoundTag;
import com.viaversion.viarewind.api.type.entitydata.EntityDataListType;
import com.viaversion.viarewind.api.type.entitydata.EntityDataType;
import com.viaversion.viarewind.api.type.item.ItemArrayType;
import com.viaversion.viarewind.api.type.item.ItemType;
import com.viaversion.viarewind.api.type.item.NBTType;
import com.viaversion.viaversion.api.minecraft.BlockPosition;
import com.viaversion.viaversion.api.minecraft.entitydata.EntityData;
import com.viaversion.viaversion.api.minecraft.item.Item;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.Types;
import java.util.List;
/**
* Safe to use before protocol loading
*/
public class RewindTypes {
public static final Type<int[]> INT_ARRAY = new IntArrayType(); // Integer array with byte as length indicator
public static final Type<BlockPosition> SHORT_POSITION = new PositionVarYType<>(Types.SHORT, value -> (short) value);
public static final Type<BlockPosition> INT_POSITION = new PositionVarYType<>(Types.INT, value -> value);
public static final Type<BlockPosition> BYTE_POSITION = new PositionVarYType<>(Types.BYTE, value -> (byte) value);
public static final Type<BlockPosition> U_BYTE_POSITION = new PositionVarYType<>(Types.UNSIGNED_BYTE, value -> (short) value);
public static final Type<CompoundTag> COMPRESSED_NBT = new NBTType();
public static final Type<Item> COMPRESSED_NBT_ITEM = new ItemType();
public static final Type<Item[]> COMPRESSED_NBT_ITEM_ARRAY = new ItemArrayType();
public static final Type<EntityData> ENTITY_DATA1_7 = new EntityDataType();
public static final Type<List<EntityData>> ENTITY_DATA_LIST1_7 = new EntityDataListType(ENTITY_DATA1_7);
}
@@ -0,0 +1,118 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2018-2026 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.api.type.chunk;
import com.viaversion.viarewind.api.compression.ThreadLocalCompressionProvider;
import com.viaversion.viaversion.api.minecraft.chunks.Chunk;
import com.viaversion.viaversion.api.type.Type;
import io.netty.buffer.ByteBuf;
import java.util.zip.DataFormatException;
public class BulkChunkType1_7_6 extends Type<Chunk[]> {
public static final BulkChunkType1_7_6 TYPE = new BulkChunkType1_7_6();
public BulkChunkType1_7_6() {
super(Chunk[].class);
}
@Override
public Chunk[] read(ByteBuf byteBuf) {
throw new UnsupportedOperationException(); // Not needed, see https://github.com/ViaVersion/ViaLegacy/blob/main/src/main/java/net/raphimc/vialegacy/protocols/release/protocol1_8to1_7_6_10/types/ChunkBulk1_7_6Type.java
}
@Override
public void write(ByteBuf buffer, Chunk[] chunks) {
final int chunkCount = chunks.length;
final int[] addBitMasks = new int[chunkCount];
int totalSize = 0;
boolean anySkyLight = false;
for (Chunk chunk : chunks) {
if (ChunkType1_7_6.hasSkyLight(chunk)) {
anySkyLight = true;
break;
}
}
for (int i = 0; i < chunkCount; i++) {
Chunk chunk = chunks[i];
addBitMasks[i] = ChunkType1_7_6.getAddBitMask(chunk);
boolean biomes = chunk.isFullChunk() && chunk.getBiomeData() != null;
totalSize += ChunkType1_7_6.calcSize(
chunk.getBitmask(),
addBitMasks[i],
anySkyLight,
biomes
);
}
final ByteBuf uncompressed = buffer.alloc().buffer(totalSize);
try {
for (int i = 0; i < chunkCount; i++) {
Chunk chunk = chunks[i];
boolean biomes = chunk.isFullChunk() && chunk.getBiomeData() != null;
ChunkType1_7_6.serialize(
chunk,
uncompressed,
addBitMasks[i],
anySkyLight,
biomes
);
}
buffer.writeShort(chunkCount);
// Reserve 4 bytes for the compressed size
final int sizeIndex = buffer.writerIndex();
buffer.writeInt(0); // Placeholder for compressed size
buffer.writeBoolean(anySkyLight);
// Write compressed data directly to output buffer
final int compressedStart = buffer.writerIndex();
try {
ThreadLocalCompressionProvider.deflate(uncompressed, buffer);
} catch (DataFormatException e) {
throw new RuntimeException("Failed to compress bulk chunk data", e);
}
final int compressedSize = buffer.writerIndex() - compressedStart;
// Go back and write the compressed size
final int endIndex = buffer.writerIndex();
buffer.writerIndex(sizeIndex);
buffer.writeInt(compressedSize);
buffer.writerIndex(endIndex);
} finally {
uncompressed.release();
}
for (int i = 0; i < chunkCount; i++) {
Chunk chunk = chunks[i];
buffer.writeInt(chunk.getX());
buffer.writeInt(chunk.getZ());
buffer.writeShort(chunk.getBitmask());
buffer.writeShort(addBitMasks[i]);
}
}
}
@@ -0,0 +1,207 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2018-2026 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.api.type.chunk;
import com.viaversion.viarewind.api.compression.ThreadLocalCompressionProvider;
import com.viaversion.viaversion.api.minecraft.chunks.Chunk;
import com.viaversion.viaversion.api.minecraft.chunks.ChunkSection;
import com.viaversion.viaversion.api.minecraft.chunks.DataPalette;
import com.viaversion.viaversion.api.minecraft.chunks.PaletteType;
import com.viaversion.viaversion.api.type.Type;
import io.netty.buffer.ByteBuf;
import java.util.zip.DataFormatException;
import static com.viaversion.viaversion.api.minecraft.chunks.ChunkSection.SIZE;
import static com.viaversion.viaversion.api.minecraft.chunks.ChunkSectionLight.LIGHT_LENGTH;
public class ChunkType1_7_6 extends Type<Chunk> {
public static final ChunkType1_7_6 TYPE = new ChunkType1_7_6();
public ChunkType1_7_6() {
super(Chunk.class);
}
@Override
public Chunk read(ByteBuf byteBuf) {
throw new UnsupportedOperationException(); // Not needed, see https://github.com/ViaVersion/ViaLegacy/blob/main/src/main/java/net/raphimc/vialegacy/protocols/release/protocol1_8to1_7_6_10/types/Chunk1_7_6Type.java
}
@Override
public void write(ByteBuf buffer, Chunk chunk) {
final int bitmask = chunk.getBitmask();
final int addBitmask = getAddBitMask(chunk);
final boolean hasSkyLight = hasSkyLight(chunk);
final boolean biomes = chunk.isFullChunk() && chunk.getBiomeData() != null;
final int size = calcSize(bitmask, addBitmask, hasSkyLight, biomes);
final ByteBuf uncompressed = buffer.alloc().buffer(size);
try {
serialize(chunk, uncompressed, addBitmask, hasSkyLight, biomes);
buffer.writeInt(chunk.getX());
buffer.writeInt(chunk.getZ());
buffer.writeBoolean(chunk.isFullChunk());
buffer.writeShort(bitmask);
buffer.writeShort(addBitmask);
// Reserve 4 bytes for the compressed size
final int sizeIndex = buffer.writerIndex();
buffer.writeInt(0); // Placeholder for compressed size
// Write compressed data directly to output buffer
final int compressedStart = buffer.writerIndex();
try {
ThreadLocalCompressionProvider.deflate(uncompressed, buffer);
} catch (DataFormatException e) {
throw new RuntimeException("Failed to compress chunk data", e);
}
final int compressedSize = buffer.writerIndex() - compressedStart;
// Go back and write the compressed size
final int endIndex = buffer.writerIndex();
buffer.writerIndex(sizeIndex);
buffer.writeInt(compressedSize);
buffer.writerIndex(endIndex);
} finally {
uncompressed.release();
}
}
public static void serialize(Chunk chunk, ByteBuf output, int addBitmask, boolean writeSkyLight, boolean biomes) {
final ChunkSection[] sections = chunk.getSections();
final int bitmask = chunk.getBitmask();
for (int i = 0; i < 16; i++) {
if ((bitmask & (1 << i)) != 0) {
final ChunkSection section = sections[i];
final DataPalette palette = section.palette(PaletteType.BLOCKS);
for (int j = 0; j < SIZE; j++) {
final int block = palette.idAt(j);
output.writeByte((block >> 4) & 0xFF);
}
}
}
for (int i = 0; i < 16; i++) {
if ((bitmask & (1 << i)) != 0) {
final ChunkSection section = sections[i];
final DataPalette palette = section.palette(PaletteType.BLOCKS);
for (int j = 0; j < ChunkSection.SIZE; j += 2) {
final int meta1 = palette.idAt(j) & 0xF;
final int meta2 = palette.idAt(j + 1) & 0xF;
output.writeByte(meta1 | (meta2 << 4));
}
}
}
for (int i = 0; i < 16; i++) {
if ((bitmask & (1 << i)) != 0) {
final byte[] blockLight = sections[i].getLight().getBlockLight();
output.writeBytes(blockLight);
}
}
if (writeSkyLight) {
for (int i = 0; i < 16; i++) {
if ((bitmask & (1 << i)) != 0) {
if (sections[i].getLight().hasSkyLight()) {
final byte[] skyLight = sections[i].getLight().getSkyLight();
output.writeBytes(skyLight);
} else {
// Write empty skylight data
output.writeZero(LIGHT_LENGTH);
}
}
}
}
if (addBitmask != 0) {
for (int i = 0; i < 16; i++) {
if ((bitmask & (1 << i)) != 0 && (addBitmask & (1 << i)) != 0) {
final ChunkSection section = sections[i];
final DataPalette palette = section.palette(PaletteType.BLOCKS);
for (int j = 0; j < SIZE; j += 2) {
final int add1 = (palette.idAt(j) >> 12) & 0xF;
final int add2 = (palette.idAt(j + 1) >> 12) & 0xF;
output.writeByte(add1 | (add2 << 4));
}
}
}
}
if (biomes && chunk.getBiomeData() != null) {
final int[] biomeData = chunk.getBiomeData();
for (int biome : biomeData) {
output.writeByte(biome);
}
}
}
public static int calcSize(int bitmask, int addBitmask, boolean hasSkyLight, boolean biomes) {
int size = 0;
int sections = Integer.bitCount(bitmask);
size += sections * SIZE;
size += sections * (SIZE / 2);
size += sections * LIGHT_LENGTH;
if (hasSkyLight) {
size += sections * LIGHT_LENGTH;
}
if (addBitmask != 0) {
size += Integer.bitCount(addBitmask) * (SIZE / 2);
}
if (biomes) {
size += 256;
}
return size;
}
public static int getAddBitMask(Chunk chunk) {
int addBitMask = 0;
for (int i = 0; i < 16; i++) {
if ((chunk.getBitmask() & (1 << i)) != 0) {
final ChunkSection section = chunk.getSections()[i];
final DataPalette palette = section.palette(PaletteType.BLOCKS);
for (int j = 0; j < SIZE; j++) {
final int id = palette.idAt(j);
if ((id >> 12) != 0) {
addBitMask |= (1 << i);
break;
}
}
}
}
return addBitMask;
}
public static boolean hasSkyLight(Chunk chunk) {
for (ChunkSection section : chunk.getSections()) {
if (section != null && section.getLight().hasSkyLight()) {
return true;
}
}
return false;
}
}
@@ -0,0 +1,61 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2018-2026 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.api.type.entitydata;
import com.viaversion.viarewind.api.minecraft.entitydata.EntityDataTypes1_7_6_10;
import com.viaversion.viaversion.api.minecraft.entitydata.EntityData;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.types.entitydata.EntityDataListTypeTemplate;
import io.netty.buffer.ByteBuf;
import java.util.ArrayList;
import java.util.List;
public class EntityDataListType extends EntityDataListTypeTemplate {
private final Type<EntityData> type;
public EntityDataListType(Type<EntityData> type) {
this.type = type;
}
@Override
public List<EntityData> read(ByteBuf buffer) {
ArrayList<EntityData> entityData = new ArrayList<>();
EntityData data;
do {
data = type.read(buffer);
if (data != null) {
entityData.add(data);
}
} while (data != null);
return entityData;
}
@Override
public void write(ByteBuf buffer, List<EntityData> entityData) {
for (EntityData meta : entityData) {
type.write(buffer, meta);
}
if (entityData.isEmpty()) {
type.write(buffer, new EntityData(0, EntityDataTypes1_7_6_10.BYTE, (byte) 0));
}
buffer.writeByte(127);
}
}
@@ -0,0 +1,45 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2018-2026 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.api.type.entitydata;
import com.viaversion.viarewind.api.minecraft.entitydata.EntityDataTypes1_7_6_10;
import com.viaversion.viaversion.api.minecraft.entitydata.EntityData;
import com.viaversion.viaversion.api.type.types.entitydata.EntityDataTypeTemplate;
import io.netty.buffer.ByteBuf;
public class EntityDataType extends EntityDataTypeTemplate {
@Override
public EntityData read(ByteBuf buffer) {
byte item = buffer.readByte();
if (item == 127) {
return null;
} else {
int typeID = (item & 224) >> 5;
EntityDataTypes1_7_6_10 type = EntityDataTypes1_7_6_10.byId(typeID);
int id = item & 31;
return new EntityData(id, type, type.type().read(buffer));
}
}
@Override
public void write(ByteBuf buffer, EntityData meta) {
int item = (meta.dataType().typeId() << 5 | meta.id() & 31) & 255;
buffer.writeByte(item);
meta.dataType().type().write(buffer, meta.getValue());
}
}
@@ -1,6 +1,6 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2016-2023 ViaVersion and contributors
* Copyright (C) 2018-2026 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -15,38 +15,36 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.api.type.item;
package com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.types.item;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.types.Types1_7_6_10;
import com.viaversion.viarewind.api.type.RewindTypes;
import com.viaversion.viaversion.api.minecraft.item.Item;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.Types;
import io.netty.buffer.ByteBuf;
public class ItemArrayType extends Type<Item[]> {
private final boolean compressed;
public ItemArrayType(boolean compressed) {
super(Item[].class);
this.compressed = compressed;
}
public ItemArrayType() {
super(Item[].class);
}
@Override
public Item[] read(ByteBuf buffer) throws Exception {
int amount = Type.SHORT.readPrimitive(buffer);
Item[] items = new Item[amount];
@Override
public Item[] read(ByteBuf buffer) {
int amount = Types.SHORT.readPrimitive(buffer);
Item[] items = new Item[amount];
for (int i = 0; i < amount; ++i) {
items[i] = (compressed ? Types1_7_6_10.COMPRESSED_NBT_ITEM : Types1_7_6_10.ITEM).read(buffer);
}
return items;
}
for (int i = 0; i < amount; ++i) {
items[i] = RewindTypes.COMPRESSED_NBT_ITEM.read(buffer);
}
return items;
}
@Override
public void write(ByteBuf buffer, Item[] items) throws Exception {
Type.SHORT.writePrimitive(buffer, (short) items.length);
for (Item item : items) {
(compressed ? Types1_7_6_10.COMPRESSED_NBT_ITEM : Types1_7_6_10.ITEM).write(buffer, item);
}
}
@Override
public void write(ByteBuf buffer, Item[] items) {
Types.SHORT.writePrimitive(buffer, (short) items.length);
for (Item item : items) {
RewindTypes.COMPRESSED_NBT_ITEM.write(buffer, item);
}
}
}
@@ -0,0 +1,57 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2018-2026 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.api.type.item;
import com.viaversion.viarewind.api.type.RewindTypes;
import com.viaversion.viaversion.api.minecraft.item.DataItem;
import com.viaversion.viaversion.api.minecraft.item.Item;
import com.viaversion.viaversion.api.type.Type;
import io.netty.buffer.ByteBuf;
public class ItemType extends Type<Item> {
public ItemType() {
super(Item.class);
}
@Override
public Item read(ByteBuf buffer) {
short id = buffer.readShort();
if (id < 0) {
return null;
}
Item item = new DataItem();
item.setIdentifier(id);
item.setAmount(buffer.readByte());
item.setData(buffer.readShort());
item.setTag(RewindTypes.COMPRESSED_NBT.read(buffer));
return item;
}
@Override
public void write(ByteBuf buffer, Item item) {
if (item == null) {
buffer.writeShort(-1);
} else {
buffer.writeShort(item.identifier());
buffer.writeByte(item.amount());
buffer.writeShort(item.data());
RewindTypes.COMPRESSED_NBT.write(buffer, item.tag());
}
}
}
@@ -0,0 +1,72 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2018-2026 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.api.type.item;
import com.viaversion.nbt.io.NBTIO;
import com.viaversion.nbt.tag.CompoundTag;
import com.viaversion.viaversion.api.type.Type;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufInputStream;
import io.netty.buffer.ByteBufOutputStream;
import java.io.IOException;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;
public class NBTType extends Type<CompoundTag> {
public NBTType() {
super(CompoundTag.class);
}
@Override
public CompoundTag read(ByteBuf buffer) {
short length = buffer.readShort();
if (length <= 0) {
return null;
}
ByteBuf compressed = buffer.readSlice(length);
try (GZIPInputStream gzipStream = new GZIPInputStream(new ByteBufInputStream(compressed))) {
return NBTIO.reader(CompoundTag.class).named().read(gzipStream);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
@Override
public void write(ByteBuf buffer, CompoundTag nbt) {
if (nbt == null) {
buffer.writeShort(-1);
return;
}
ByteBuf compressedBuf = buffer.alloc().buffer();
try {
try (GZIPOutputStream gzipStream = new GZIPOutputStream(new ByteBufOutputStream(compressedBuf))) {
NBTIO.writer().named().write(gzipStream, nbt);
} catch (IOException e) {
throw new RuntimeException(e);
}
buffer.writeShort(compressedBuf.readableBytes());
buffer.writeBytes(compressedBuf);
} finally {
compressedBuf.release();
}
}
}
@@ -1,99 +0,0 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2016-2023 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.protocol.protocol1_7_2_5to1_7_6_10;
import com.viaversion.viaversion.api.protocol.packet.ClientboundPacketType;
public enum ClientboundPackets1_7_2_5 implements ClientboundPacketType {
KEEP_ALIVE, // 0x00
JOIN_GAME, // 0x01
CHAT_MESSAGE, // 0x02
TIME_UPDATE, // 0x03
ENTITY_EQUIPMENT, // 0x04
SPAWN_POSITION, // 0x05
UPDATE_HEALTH, // 0x06
RESPAWN, // 0x07
PLAYER_POSITION, // 0x08
HELD_ITEM_CHANGE, // 0x09
USE_BED, // 0x0A
ENTITY_ANIMATION, // 0x0B
SPAWN_PLAYER, // 0x0C
COLLECT_ITEM, // 0x0D
SPAWN_ENTITY, // 0x0E
SPAWN_MOB, // 0x0F
SPAWN_PAINTING, // 0x10
SPAWN_EXPERIENCE_ORB, // 0x11
ENTITY_VELOCITY, // 0x12
DESTROY_ENTITIES, // 0x13
ENTITY_MOVEMENT, // 0x14
ENTITY_POSITION, // 0x15
ENTITY_ROTATION, // 0x16
ENTITY_POSITION_AND_ROTATION, // 0x17
ENTITY_TELEPORT, // 0x18
ENTITY_HEAD_LOOK, // 0x19
ENTITY_STATUS, // 0x1A
ATTACH_ENTITY, // 0x1B
ENTITY_METADATA, // 0x1C
ENTITY_EFFECT, // 0x1D
REMOVE_ENTITY_EFFECT, // 0x1E
SET_EXPERIENCE, // 0x1F
ENTITY_PROPERTIES, // 0x20
CHUNK_DATA, // 0x21
MULTI_BLOCK_CHANGE, // 0x22
BLOCK_CHANGE, // 0x23
BLOCK_ACTION, // 0x24
BLOCK_BREAK_ANIMATION, // 0x25
MAP_BULK_CHUNK, // 0x26
EXPLOSION, // 0x27
EFFECT, // 0x28
NAMED_SOUND, // 0x29
SPAWN_PARTICLE, // 0x2A
GAME_EVENT, // 0x2B
SPAWN_GLOBAL_ENTITY, // 0x2C
OPEN_WINDOW, // 0x2D
CLOSE_WINDOW, // 0x2E
SET_SLOT, // 0x2F
WINDOW_ITEMS, // 0x30
WINDOW_PROPERTY, // 0x31
WINDOW_CONFIRMATION, // 0x32
UPDATE_SIGN, // 0x33
MAP_DATA, // 0x34
BLOCK_ENTITY_DATA, // 0x35
OPEN_SIGN_EDITOR, // 0x36
STATISTICS, // 0x37
PLAYER_INFO, // 0x38
PLAYER_ABILITIES, // 0x39
TAB_COMPLETE, // 0x3A
SCOREBOARD_OBJECTIVE, // 0x3B
UPDATE_SCORE, // 0x3C
DISPLAY_SCOREBOARD, // 0x3D
TEAMS, // 0x3E
PLUGIN_MESSAGE, // 0x3F
DISCONNECT; // 0x40
@Override
public int getId() {
return ordinal();
}
@Override
public String getName() {
return name();
}
}
@@ -1,114 +0,0 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2016-2023 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.protocol.protocol1_7_2_5to1_7_6_10;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.types.Types1_7_6_10;
import com.viaversion.viaversion.api.protocol.AbstractProtocol;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.protocol.packet.State;
import com.viaversion.viaversion.api.protocol.remapper.PacketHandlers;
import com.viaversion.viaversion.api.protocol.remapper.ValueTransformer;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.protocols.base.ClientboundLoginPackets;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
public class Protocol1_7_2_5To1_7_6_10 extends AbstractProtocol<ClientboundPackets1_7_2_5, ClientboundPackets1_7_2_5, ServerboundPackets1_7_2_5, ServerboundPackets1_7_2_5> {
public final static ValueTransformer<String, String> REMOVE_DASHES = new ValueTransformer<String, String>(Type.STRING) {
@Override
public String transform(PacketWrapper packetWrapper, String s) {
return s.replace("-", "");
}
};
public Protocol1_7_2_5To1_7_6_10() {
super(ClientboundPackets1_7_2_5.class, ClientboundPackets1_7_2_5.class, ServerboundPackets1_7_2_5.class, ServerboundPackets1_7_2_5.class);
}
@Override
protected void registerPackets() {
this.registerClientbound(State.LOGIN, ClientboundLoginPackets.GAME_PROFILE.getId(), ClientboundLoginPackets.GAME_PROFILE.getId(), new PacketHandlers() {
@Override
public void register() {
map(Type.STRING, REMOVE_DASHES); // uuid
map(Type.STRING); // name
}
});
this.registerClientbound(ClientboundPackets1_7_2_5.SPAWN_PLAYER, new PacketHandlers() {
@Override
public void register() {
map(Type.VAR_INT); // entity id
map(Type.STRING, REMOVE_DASHES); // uuid
map(Type.STRING); // name
handler(packetWrapper -> { // delete data introduced in 1.7.6
final int size = packetWrapper.read(Type.VAR_INT); // data count
for (int i = 0; i < size; i++) {
packetWrapper.read(Type.STRING); // data name
packetWrapper.read(Type.STRING); // data value
packetWrapper.read(Type.STRING); // data signature
}
});
map(Type.INT); // x
map(Type.INT); // y
map(Type.INT); // z
map(Type.BYTE); // yaw
map(Type.BYTE); // pitch
map(Type.SHORT); // item in hand
map(Types1_7_6_10.METADATA_LIST); // metadata
}
});
this.registerClientbound(ClientboundPackets1_7_2_5.TEAMS, new PacketHandlers() {
@Override
public void register() {
map(Type.STRING); // team name
map(Type.BYTE); // mode
handler(packetWrapper -> {
byte mode = packetWrapper.get(Type.BYTE, 0);
if (mode == 0 || mode == 2) { // team is created or information is updated
packetWrapper.passthrough(Type.STRING); // team display name
packetWrapper.passthrough(Type.STRING); // team prefix
packetWrapper.passthrough(Type.STRING); // team suffix
packetWrapper.passthrough(Type.BYTE); // friendly fire
}
if (mode == 0 || mode == 3 || mode == 4) { // team is created, player is added or player is removed
List<String> entryList = new ArrayList<>();
final int size = packetWrapper.read(Type.SHORT);
for (int i = 0; i < size; i++) {
entryList.add(packetWrapper.read(Type.STRING));
}
entryList = entryList.stream()
.map(it -> it.length() > 16 ? it.substring(0, 16) : it) // trim to 16 characters
.distinct() // remove duplicates
.collect(Collectors.toList());
packetWrapper.write(Type.SHORT, (short) entryList.size());
for (String entry : entryList) {
packetWrapper.write(Type.STRING, entry);
}
}
});
}
});
}
}
@@ -1,58 +0,0 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2016-2023 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.protocol.protocol1_7_2_5to1_7_6_10;
import com.viaversion.viaversion.api.protocol.packet.ServerboundPacketType;
public enum ServerboundPackets1_7_2_5 implements ServerboundPacketType {
KEEP_ALIVE, // 0x00
CHAT_MESSAGE, // 0x01
INTERACT_ENTITY, // 0x02
PLAYER_MOVEMENT, // 0x03
PLAYER_POSITION, // 0x04
PLAYER_ROTATION, // 0x05
PLAYER_POSITION_AND_ROTATION, // 0x06
PLAYER_DIGGING, // 0x07
PLAYER_BLOCK_PLACEMENT, // 0x08
HELD_ITEM_CHANGE, // 0x09
ANIMATION, // 0x0A
ENTITY_ACTION, // 0x0B
STEER_VEHICLE, // 0x0C
CLOSE_WINDOW, // 0x0D
CLICK_WINDOW, // 0x0E
WINDOW_CONFIRMATION, // 0x0F
CREATIVE_INVENTORY_ACTION, // 0x10
CLICK_WINDOW_BUTTON, // 0x11
UPDATE_SIGN, // 0x12
PLAYER_ABILITIES, // 0x13
TAB_COMPLETE, // 0x14
CLIENT_SETTINGS, // 0x15
CLIENT_STATUS, // 0x16
PLUGIN_MESSAGE; // 0x17
@Override
public int getId() {
return ordinal();
}
@Override
public String getName() {
return name();
}
}
@@ -1,163 +0,0 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2016-2023 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8;
import com.viaversion.viarewind.ViaRewind;
import com.viaversion.viarewind.api.rewriter.item.ReplacementItemRewriter;
import com.viaversion.viarewind.protocol.protocol1_7_2_5to1_7_6_10.ClientboundPackets1_7_2_5;
import com.viaversion.viarewind.protocol.protocol1_7_2_5to1_7_6_10.ServerboundPackets1_7_2_5;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.rewriter.MetadataRewriter;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.packets.*;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.provider.CompressionHandlerProvider;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.provider.compression.TrackingCompressionHandlerProvider;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.rewriter.ReplacementItemRewriter1_7_6_10;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.storage.*;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.task.WorldBorderUpdateTask;
import com.viaversion.viaversion.api.Via;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.minecraft.ClientWorld;
import com.viaversion.viaversion.api.platform.providers.ViaProviders;
import com.viaversion.viaversion.api.protocol.AbstractProtocol;
import com.viaversion.viaversion.api.protocol.packet.Direction;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.protocol.packet.State;
import com.viaversion.viaversion.api.protocol.remapper.PacketHandlers;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.protocols.base.ClientboundLoginPackets;
import com.viaversion.viaversion.protocols.base.ServerboundLoginPackets;
import com.viaversion.viaversion.protocols.protocol1_8.ClientboundPackets1_8;
import com.viaversion.viaversion.protocols.protocol1_8.ServerboundPackets1_8;
import java.util.concurrent.TimeUnit;
public class Protocol1_7_6_10To1_8 extends AbstractProtocol<ClientboundPackets1_8, ClientboundPackets1_7_2_5, ServerboundPackets1_8, ServerboundPackets1_7_2_5> {
private final ReplacementItemRewriter<Protocol1_7_6_10To1_8> itemRewriter = new ReplacementItemRewriter1_7_6_10(this);
private final MetadataRewriter metadataRewriter = new MetadataRewriter(this);
public Protocol1_7_6_10To1_8() {
super(ClientboundPackets1_8.class, ClientboundPackets1_7_2_5.class, ServerboundPackets1_8.class, ServerboundPackets1_7_2_5.class);
}
@Override
protected void registerPackets() {
itemRewriter.register();
EntityPackets.register(this);
InventoryPackets.register(this);
PlayerPackets.register(this);
ScoreboardPackets.register(this);
SpawnPackets.register(this);
WorldPackets.register(this);
this.registerClientbound(State.LOGIN, ClientboundLoginPackets.HELLO.getId(), ClientboundLoginPackets.HELLO.getId(), new PacketHandlers() {
@Override
public void register() {
map(Type.STRING); // server hash
map(Type.BYTE_ARRAY_PRIMITIVE, Type.SHORT_BYTE_ARRAY); // public key
map(Type.BYTE_ARRAY_PRIMITIVE, Type.SHORT_BYTE_ARRAY); // verification token
}
});
this.registerClientbound(State.LOGIN, ClientboundLoginPackets.LOGIN_COMPRESSION.getId(), ClientboundLoginPackets.LOGIN_COMPRESSION.getId(), new PacketHandlers() {
@Override
public void register() {
handler(wrapper -> {
final int threshold = wrapper.read(Type.VAR_INT);
Via.getManager().getProviders().get(CompressionHandlerProvider.class).onHandleLoginCompressionPacket(wrapper.user(), threshold);
wrapper.cancel();
});
}
});
this.cancelClientbound(ClientboundPackets1_8.SET_COMPRESSION); // unused
this.registerClientbound(ClientboundPackets1_8.KEEP_ALIVE, new PacketHandlers() {
@Override
public void register() {
map(Type.VAR_INT, Type.INT); // id
}
});
this.registerServerbound(State.LOGIN, ServerboundLoginPackets.ENCRYPTION_KEY.getId(), ServerboundLoginPackets.ENCRYPTION_KEY.getId(), new PacketHandlers() {
@Override
public void register() {
map(Type.SHORT_BYTE_ARRAY, Type.BYTE_ARRAY_PRIMITIVE); // shared secret
map(Type.SHORT_BYTE_ARRAY, Type.BYTE_ARRAY_PRIMITIVE); // verification token
}
});
this.registerServerbound(ServerboundPackets1_7_2_5.KEEP_ALIVE, new PacketHandlers() {
@Override
public void register() {
map(Type.INT, Type.VAR_INT); // id
}
});
}
@Override
public void transform(Direction direction, State state, PacketWrapper packetWrapper) throws Exception {
Via.getManager().getProviders().get(CompressionHandlerProvider.class).onTransformPacket(packetWrapper.user());
// if (direction == Direction.CLIENTBOUND) {
// System.out.println("Pre: " + direction + " " + state + " " + packetWrapper.getId() + " " + ClientboundPackets1_8.values()[packetWrapper.getId()].getName() + ": " + packetWrapper);
// } else {
// System.out.println("Pre: " + direction + " " + state + " " + packetWrapper.getId() + " " + ServerboundPackets1_7_2_5.values()[packetWrapper.getId()].getName() + ": " + packetWrapper);
// }
super.transform(direction, state, packetWrapper);
// if (direction == Direction.CLIENTBOUND) {
// System.out.println("Post: " + direction + " " + state + " " + packetWrapper.getId() + " " + ClientboundPackets1_7_2_5.values()[packetWrapper.getId()].getName() + ": " + packetWrapper);
// } else {
// System.out.println("Post: " + direction + " " + state + " " + packetWrapper.getId() + " " + ServerboundPackets1_8.values()[packetWrapper.getId()].getName() + ": " + packetWrapper);
// }
}
@Override
public void init(UserConnection userConnection) {
userConnection.put(new InventoryTracker(userConnection));
userConnection.put(new EntityTracker1_7_6_10(userConnection, metadataRewriter));
userConnection.put(new PlayerSessionStorage(userConnection));
userConnection.put(new GameProfileStorage(userConnection));
userConnection.put(new Scoreboard(userConnection));
userConnection.put(new CompressionStatusTracker(userConnection));
userConnection.put(new WorldBorderEmulator(userConnection));
if (!userConnection.has(ClientWorld.class)) {
userConnection.put(new ClientWorld());
}
}
@Override
public void register(ViaProviders providers) {
providers.register(CompressionHandlerProvider.class, new TrackingCompressionHandlerProvider());
if (ViaRewind.getConfig().isEmulateWorldBorder()) {
Via.getManager().getScheduler().scheduleRepeating(new WorldBorderUpdateTask(), 0L, 50L, TimeUnit.MILLISECONDS);
}
}
@Override
public ReplacementItemRewriter<Protocol1_7_6_10To1_8> getItemRewriter() {
return itemRewriter;
}
public MetadataRewriter getMetadataRewriter() {
return metadataRewriter;
}
}
@@ -1,9 +0,0 @@
package com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.model;
public class FurnaceData {
public short fuelLeft = 0;
public short maxFuel = 0;
public short progress = 0;
public short maxProgress = 200;
}
@@ -1,184 +0,0 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2016-2023 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.model;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.types.metadata.MetaType1_7_6_10;
import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_10;
import com.viaversion.viaversion.api.minecraft.metadata.types.MetaType1_8;
import com.viaversion.viaversion.util.Pair;
import java.util.HashMap;
import java.util.Optional;
public enum MetaIndex1_7_6_10To1_8 {
ENTITY_FLAGS(EntityTypes1_10.EntityType.ENTITY, 0, MetaType1_7_6_10.Byte, MetaType1_8.Byte),
ENTITY_AIR(EntityTypes1_10.EntityType.ENTITY, 1, MetaType1_7_6_10.Short, MetaType1_8.Short),
ENTITY_NAME_TAG(EntityTypes1_10.EntityType.ENTITY, -1, MetaType1_7_6_10.NonExistent, 2, MetaType1_8.String),
ENTITY_NAME_TAG_VISIBILITY(EntityTypes1_10.EntityType.ENTITY, -1, MetaType1_7_6_10.NonExistent, 3, MetaType1_8.Byte),
ENTITY_SILENT(EntityTypes1_10.EntityType.ENTITY, -1, MetaType1_7_6_10.NonExistent, 4, MetaType1_8.Byte),
ENTITY_LIVING_HEALTH(EntityTypes1_10.EntityType.ENTITY_LIVING, 6, MetaType1_7_6_10.Float, MetaType1_8.Float),
ENTITY_LIVING_POTION_EFFECT_COLOR(EntityTypes1_10.EntityType.ENTITY_LIVING, 7, MetaType1_7_6_10.Int, MetaType1_8.Int),
ENTITY_LIVING_IS_POTION_EFFECT_AMBIENT(EntityTypes1_10.EntityType.ENTITY_LIVING, 8, MetaType1_7_6_10.Byte, MetaType1_8.Byte),
ENTITY_LIVING_ARROWS(EntityTypes1_10.EntityType.ENTITY_LIVING, 9, MetaType1_7_6_10.Byte, MetaType1_8.Byte),
ENTITY_LIVING_NAME_TAG(EntityTypes1_10.EntityType.ENTITY_LIVING, 10, MetaType1_7_6_10.String, 2, MetaType1_8.String),
ENTITY_LIVING_NAME_TAG_VISIBILITY(EntityTypes1_10.EntityType.ENTITY_LIVING, 11, MetaType1_7_6_10.Byte, 3, MetaType1_8.Byte),
ENTITY_LIVING_AI(EntityTypes1_10.EntityType.ENTITY_LIVING, -1, MetaType1_7_6_10.NonExistent, 15, MetaType1_8.Byte),
ENTITY_AGEABLE_AGE(EntityTypes1_10.EntityType.ENTITY_AGEABLE, 12, MetaType1_7_6_10.Int, MetaType1_8.Byte),
ARMOR_STAND_FLAGS(EntityTypes1_10.EntityType.ARMOR_STAND, -1, MetaType1_7_6_10.NonExistent, 10, MetaType1_8.Byte),
ARMOR_STAND_HEAD_POSITION(EntityTypes1_10.EntityType.ARMOR_STAND, -1, MetaType1_7_6_10.NonExistent, 11, MetaType1_8.Rotation),
ARMOR_STAND_BODY_POSITION(EntityTypes1_10.EntityType.ARMOR_STAND, -1, MetaType1_7_6_10.NonExistent, 12, MetaType1_8.Rotation),
ARMOR_STAND_LEFT_ARM_POSITION(EntityTypes1_10.EntityType.ARMOR_STAND, -1, MetaType1_7_6_10.NonExistent, 13, MetaType1_8.Rotation),
ARMOR_STAND_RIGHT_ARM_POSITION(EntityTypes1_10.EntityType.ARMOR_STAND, -1, MetaType1_7_6_10.NonExistent, 14, MetaType1_8.Rotation),
ARMOR_STAND_LEFT_LEG_POSITION(EntityTypes1_10.EntityType.ARMOR_STAND, -1, MetaType1_7_6_10.NonExistent, 15, MetaType1_8.Rotation),
ARMOR_STAND_RIGHT_LEG_POSITION(EntityTypes1_10.EntityType.ARMOR_STAND, -1, MetaType1_7_6_10.NonExistent, 16, MetaType1_8.Rotation),
HUMAN_SKIN_FLAGS(EntityTypes1_10.EntityType.ENTITY_HUMAN, 16, MetaType1_7_6_10.Byte, 10, MetaType1_8.Byte),
HUMAN_UNUSED(EntityTypes1_10.EntityType.ENTITY_HUMAN, -1, MetaType1_7_6_10.NonExistent, 16, MetaType1_8.Byte),
HUMAN_ABSORPTION_HEATS(EntityTypes1_10.EntityType.ENTITY_HUMAN, 17, MetaType1_7_6_10.Float, MetaType1_8.Float),
HUMAN_SCORE(EntityTypes1_10.EntityType.ENTITY_HUMAN, 18, MetaType1_7_6_10.Int, MetaType1_8.Int),
HORSE_FLAGS(EntityTypes1_10.EntityType.HORSE, 16, MetaType1_7_6_10.Int, MetaType1_8.Int),
HORSE_TYPE(EntityTypes1_10.EntityType.HORSE, 19, MetaType1_7_6_10.Byte, MetaType1_8.Byte),
HORSE_COLOR(EntityTypes1_10.EntityType.HORSE, 20, MetaType1_7_6_10.Int, MetaType1_8.Int),
HORSE_OWNER(EntityTypes1_10.EntityType.HORSE, 21, MetaType1_7_6_10.String, MetaType1_8.String),
HORSE_ARMOR(EntityTypes1_10.EntityType.HORSE, 22, MetaType1_7_6_10.Int, MetaType1_8.Int),
BAT_HANGING(EntityTypes1_10.EntityType.BAT, 16, MetaType1_7_6_10.Byte, MetaType1_8.Byte),
TAMEABLE_FLAGS(EntityTypes1_10.EntityType.ENTITY_TAMEABLE_ANIMAL, 16, MetaType1_7_6_10.Byte, MetaType1_8.Byte),
TAMEABLE_OWNER(EntityTypes1_10.EntityType.ENTITY_TAMEABLE_ANIMAL, 17, MetaType1_7_6_10.String, MetaType1_8.String),
OCELOT_TYPE(EntityTypes1_10.EntityType.OCELOT, 18, MetaType1_7_6_10.Byte, MetaType1_8.Byte),
WOLF_FLAGS(EntityTypes1_10.EntityType.WOLF, 16, MetaType1_7_6_10.Byte, MetaType1_8.Byte),
WOLF_HEALTH(EntityTypes1_10.EntityType.WOLF, 18, MetaType1_7_6_10.Float, MetaType1_8.Float),
WOLF_BEGGING(EntityTypes1_10.EntityType.WOLF, 19, MetaType1_7_6_10.Byte, MetaType1_8.Byte),
WOLF_COLLAR_COLOR(EntityTypes1_10.EntityType.WOLF, 20, MetaType1_7_6_10.Byte, MetaType1_8.Byte),
PIG_SADDLE(EntityTypes1_10.EntityType.PIG, 16, MetaType1_7_6_10.Byte, MetaType1_8.Byte),
SHEEP_COLOR_OR_SHEARED(EntityTypes1_10.EntityType.SHEEP, 16, MetaType1_7_6_10.Byte, MetaType1_8.Byte),
VILLAGER_TYPE(EntityTypes1_10.EntityType.VILLAGER, 16, MetaType1_7_6_10.Int, MetaType1_8.Int),
ENDERMAN_CARRIED_BLOCK(EntityTypes1_10.EntityType.ENDERMAN, 16, MetaType1_7_6_10.NonExistent, MetaType1_8.Short),
ENDERMAN_CARRIED_BLOCK_DATA(EntityTypes1_10.EntityType.ENDERMAN, 17, MetaType1_7_6_10.NonExistent, MetaType1_8.Byte),
ENDERMAN_IS_SCREAMING(EntityTypes1_10.EntityType.ENDERMAN, 18, MetaType1_7_6_10.Byte, MetaType1_8.Byte),
ZOMBIE_CHILD(EntityTypes1_10.EntityType.ZOMBIE, 12, MetaType1_7_6_10.Byte, MetaType1_8.Byte),
ZOMBIE_VILLAGER(EntityTypes1_10.EntityType.ZOMBIE, 13, MetaType1_7_6_10.Byte, MetaType1_8.Byte),
ZOMBIE_CONVERTING(EntityTypes1_10.EntityType.ZOMBIE, 14, MetaType1_7_6_10.Byte, MetaType1_8.Byte),
BLAZE_ON_FIRE(EntityTypes1_10.EntityType.BLAZE, 16, MetaType1_7_6_10.Byte, MetaType1_8.Byte),
SPIDER_CLIMBING(EntityTypes1_10.EntityType.SPIDER, 16, MetaType1_7_6_10.Byte, MetaType1_8.Byte),
CREEPER_STATE(EntityTypes1_10.EntityType.CREEPER, 16, MetaType1_7_6_10.Byte, MetaType1_8.Byte),
CREEPER_POWERED(EntityTypes1_10.EntityType.CREEPER, 17, MetaType1_7_6_10.Byte, MetaType1_8.Byte),
GHAST_STATE(EntityTypes1_10.EntityType.GHAST, 16, MetaType1_7_6_10.Byte, MetaType1_8.Byte),
GHAST_IS_POWERED(EntityTypes1_10.EntityType.GHAST, 17, MetaType1_7_6_10.NonExistent, MetaType1_8.Byte),
SLIME_SIZE(EntityTypes1_10.EntityType.SLIME, 16, MetaType1_7_6_10.Byte, MetaType1_8.Byte),
SKELETON_TYPE(EntityTypes1_10.EntityType.SKELETON, 13, MetaType1_7_6_10.Byte, MetaType1_8.Byte),
WITCH_AGGRESSIVE(EntityTypes1_10.EntityType.WITCH, 21, MetaType1_7_6_10.Byte, MetaType1_8.Byte),
IRON_GOLEM_IS_PLAYER_CREATED(EntityTypes1_10.EntityType.IRON_GOLEM, 16, MetaType1_7_6_10.Byte, MetaType1_8.Byte),
WITHER_WATCHED_TARGET_1(EntityTypes1_10.EntityType.WITHER, 17, MetaType1_7_6_10.Int, MetaType1_8.Int),
WITHER_WATCHED_TARGET_2(EntityTypes1_10.EntityType.WITHER, 18, MetaType1_7_6_10.Int, MetaType1_8.Int),
WITHER_WATCHED_TARGET_3(EntityTypes1_10.EntityType.WITHER, 19, MetaType1_7_6_10.Int, MetaType1_8.Int),
WITHER_INVULNERABLE_TIME(EntityTypes1_10.EntityType.WITHER, 20, MetaType1_7_6_10.Int, MetaType1_8.Int),
GUARDIAN_FLAGS(EntityTypes1_10.EntityType.GUARDIAN, 16, MetaType1_7_6_10.NonExistent, MetaType1_8.Byte),
GUARDIAN_TARGET(EntityTypes1_10.EntityType.GUARDIAN, 17, MetaType1_7_6_10.NonExistent, MetaType1_8.Int),
BOAT_TIME_SINCE_HIT(EntityTypes1_10.EntityType.BOAT, 17, MetaType1_7_6_10.Int, MetaType1_8.Int),
BOAT_FORWARD_DIRECTION(EntityTypes1_10.EntityType.BOAT, 18, MetaType1_7_6_10.Int, MetaType1_8.Int),
BOAT_DAMAGE_TAKEN(EntityTypes1_10.EntityType.BOAT, 19, MetaType1_7_6_10.Float, MetaType1_8.Float),
MINECART_SHAKING_POWER(EntityTypes1_10.EntityType.MINECART_ABSTRACT, 17, MetaType1_7_6_10.Int, MetaType1_8.Int),
MINECART_SHAKING_DIRECTION(EntityTypes1_10.EntityType.MINECART_ABSTRACT, 18, MetaType1_7_6_10.Int, MetaType1_8.Int),
MINECART_DAMAGE_TAKEN(EntityTypes1_10.EntityType.MINECART_ABSTRACT, 19, MetaType1_7_6_10.Float, MetaType1_8.Float),
MINECART_BLOCK_INSIDE(EntityTypes1_10.EntityType.MINECART_ABSTRACT, 20, MetaType1_7_6_10.Int, MetaType1_8.Int),
MINECART_BLOCK_Y(EntityTypes1_10.EntityType.MINECART_ABSTRACT, 21, MetaType1_7_6_10.Int, MetaType1_8.Int),
MINECART_SHOW_BLOCK(EntityTypes1_10.EntityType.MINECART_ABSTRACT, 22, MetaType1_7_6_10.Byte, MetaType1_8.Byte),
FURNACE_MINECART_IS_POWERED(EntityTypes1_10.EntityType.MINECART_FURNACE, 16, MetaType1_7_6_10.Byte, MetaType1_8.Byte),
ITEM_ITEM(EntityTypes1_10.EntityType.DROPPED_ITEM, 10, MetaType1_7_6_10.Slot, MetaType1_8.Slot),
ARROW_IS_CRITICAL(EntityTypes1_10.EntityType.ARROW, 16, MetaType1_7_6_10.Byte, MetaType1_8.Byte),
FIREWORK_INFO(EntityTypes1_10.EntityType.FIREWORK, 8, MetaType1_7_6_10.Slot, MetaType1_8.Slot),
ITEM_FRAME_ITEM(EntityTypes1_10.EntityType.ITEM_FRAME, 2, MetaType1_7_6_10.Slot, 8, MetaType1_8.Slot),
ITEM_FRAME_ROTATION(EntityTypes1_10.EntityType.ITEM_FRAME, 3, MetaType1_7_6_10.Byte, 9, MetaType1_8.Byte),
ENDER_CRYSTAL_HEALTH(EntityTypes1_10.EntityType.ENDER_CRYSTAL, 8, MetaType1_7_6_10.Int, 9, MetaType1_8.Int),
;
private final static HashMap<Pair<EntityTypes1_10.EntityType, Integer>, MetaIndex1_7_6_10To1_8> metadataRewrites = new HashMap<>();
static {
for (MetaIndex1_7_6_10To1_8 index : MetaIndex1_7_6_10To1_8.values()) {
metadataRewrites.put(new Pair<>(index.getClazz(), index.getNewIndex()), index);
}
}
private final EntityTypes1_10.EntityType clazz;
private final int newIndex;
private final MetaType1_8 newType;
private final MetaType1_7_6_10 oldType;
private final int index;
MetaIndex1_7_6_10To1_8(EntityTypes1_10.EntityType type, int index, MetaType1_7_6_10 oldType, MetaType1_8 newType) {
this.clazz = type;
this.index = index;
this.newIndex = index;
this.oldType = oldType;
this.newType = newType;
}
MetaIndex1_7_6_10To1_8(EntityTypes1_10.EntityType type, int index, MetaType1_7_6_10 oldType, int newIndex, MetaType1_8 newType) {
this.clazz = type;
this.index = index;
this.oldType = oldType;
this.newIndex = newIndex;
this.newType = newType;
}
private static Optional<MetaIndex1_7_6_10To1_8> getIndex(EntityTypes1_10.EntityType type, int index) {
Pair<EntityTypes1_10.EntityType, Integer> pair = new Pair<>(type, index);
if (metadataRewrites.containsKey(pair)) {
return Optional.of(metadataRewrites.get(pair));
}
return Optional.empty();
}
public EntityTypes1_10.EntityType getClazz() {
return clazz;
}
public int getNewIndex() {
return newIndex;
}
public MetaType1_8 getNewType() {
return newType;
}
public MetaType1_7_6_10 getOldType() {
return oldType;
}
public int getIndex() {
return index;
}
public static MetaIndex1_7_6_10To1_8 searchIndex(EntityTypes1_10.EntityType type, int index) {
EntityTypes1_10.EntityType currentType = type;
do {
Optional<MetaIndex1_7_6_10To1_8> optMeta = getIndex(currentType, index);
if (optMeta.isPresent()) {
return optMeta.get();
}
currentType = currentType.getParent();
} while (currentType != null);
return null;
}
}
@@ -1,97 +0,0 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2016-2023 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.model;
import java.util.HashMap;
public enum ParticleIndex1_7_6_10 {
EXPLOSION_NORMAL("explode"),
EXPLOSION_LARGE("largeexplode"),
EXPLOSION_HUGE("hugeexplosion"),
FIREWORKS_SPARK("fireworksSpark"),
WATER_BUBBLE("bubble"),
WATER_SPLASH("splash"),
WATER_WAKE("wake"),
SUSPENDED("suspended"),
SUSPENDED_DEPTH("depthsuspend"),
CRIT("crit"),
CRIT_MAGIC("magicCrit"),
SMOKE_NORMAL("smoke"),
SMOKE_LARGE("largesmoke"),
SPELL("spell"),
SPELL_INSTANT("instantSpell"),
SPELL_MOB("mobSpell"),
SPELL_MOB_AMBIENT("mobSpellAmbient"),
SPELL_WITCH("witchMagic"),
DRIP_WATER("dripWater"),
DRIP_LAVA("dripLava"),
VILLAGER_ANGRY("angryVillager"),
VILLAGER_HAPPY("happyVillager"),
TOWN_AURA("townaura"),
NOTE("note"),
PORTAL("portal"),
ENCHANTMENT_TABLE("enchantmenttable"),
FLAME("flame"),
LAVA("lava"),
FOOTSTEP("footstep"),
CLOUD("cloud"),
REDSTONE("reddust"),
SNOWBALL("snowballpoof"),
SNOW_SHOVEL("snowshovel"),
SLIME("slime"),
HEART("heart"),
BARRIER("barrier"),
ICON_CRACK("iconcrack", 2),
BLOCK_CRACK("blockcrack", 1),
BLOCK_DUST("blockdust", 1),
WATER_DROP("droplet"),
ITEM_TAKE("take"),
MOB_APPEARANCE("mobappearance");
public final String name;
public final int extra;
private final static HashMap<String, ParticleIndex1_7_6_10> particleMap = new HashMap<>();
ParticleIndex1_7_6_10(String name) {
this(name, 0);
}
ParticleIndex1_7_6_10(String name, int extra) {
this.name = name;
this.extra = extra;
}
public static ParticleIndex1_7_6_10 find(String part) {
return particleMap.get(part);
}
public static ParticleIndex1_7_6_10 find(int id) {
if (id < 0) return null;
ParticleIndex1_7_6_10[] values = ParticleIndex1_7_6_10.values();
return id >= values.length ? null : values[id];
}
static {
ParticleIndex1_7_6_10[] particles = values();
for (ParticleIndex1_7_6_10 particle : particles) {
particleMap.put(particle.name, particle);
}
}
}
@@ -1,318 +0,0 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2016-2023 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.model;
import com.viaversion.viarewind.protocol.protocol1_7_2_5to1_7_6_10.ClientboundPackets1_7_2_5;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.Protocol1_7_6_10To1_8;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.rewriter.MetadataRewriter;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.types.Types1_7_6_10;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.types.metadata.MetaType1_7_6_10;
import com.viaversion.viarewind.utils.PacketUtil;
import com.viaversion.viarewind.utils.math.AABB;
import com.viaversion.viarewind.utils.math.Vector3d;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_10;
import com.viaversion.viaversion.api.minecraft.metadata.Metadata;
import com.viaversion.viaversion.api.minecraft.metadata.types.MetaType1_8;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.type.Type;
import java.util.ArrayList;
import java.util.List;
public class VirtualHologramEntity {
private final List<Metadata> metadataTracker = new ArrayList<>();
private double locX, locY, locZ;
private final UserConnection user;
private final MetadataRewriter metadataRewriter;
private final int entityId;
private int[] entityIds = null;
private State currentState = null;
private boolean invisible = false;
private String name = null;
private float yaw, pitch;
private float headYaw;
private boolean small = false;
private boolean marker = false;
public VirtualHologramEntity(final UserConnection user, final MetadataRewriter metadataRewriter, final int entityId) {
this.user = user;
this.metadataRewriter = metadataRewriter;
this.entityId = entityId;
}
public void updateReplacementPosition(double x, double y, double z) {
if (x == this.locX && y == this.locY && z == this.locZ) {
return;
}
this.locX = x;
this.locY = y;
this.locZ = z;
updateLocation(false);
}
public void handleOriginalMovementPacket(double x, double y, double z) {
if (x == 0.0 && y == 0.0 && z == 0.0) {
return;
}
this.locX += x;
this.locY += y;
this.locZ += z;
updateLocation(false);
}
public void setYawPitch(float yaw, float pitch) {
if (this.yaw == yaw || this.headYaw == yaw || this.pitch == pitch) {
return;
}
this.yaw = yaw;
this.headYaw = yaw;
this.pitch = pitch;
updateLocation(false);
}
public void setHeadYaw(float yaw) {
if (this.headYaw == yaw) {
return;
}
this.headYaw = yaw;
updateLocation(false);
}
public void updateMetadata(final List<Metadata> metadataList) {
for (Metadata metadata : metadataList) {
metadataTracker.removeIf(m -> m.id() == metadata.id());
metadataTracker.add(metadata);
}
updateState();
}
public void updateState() {
byte flags = 0;
byte armorStandFlags = 0;
for (Metadata metadata : metadataTracker) {
if (metadata.id() == 0 && metadata.metaType() == MetaType1_8.Byte) {
flags = ((Number) metadata.getValue()).byteValue();
} else if (metadata.id() == 2 && metadata.metaType() == MetaType1_8.String) {
name = metadata.getValue().toString();
if (name != null && name.isEmpty()) name = null;
} else if (metadata.id() == 10 && metadata.metaType() == MetaType1_8.Byte) {
armorStandFlags = ((Number) metadata.getValue()).byteValue();
}
}
invisible = (flags & 0x20) != 0;
small = (armorStandFlags & 0x01) != 0;
marker = (armorStandFlags & 0x10) != 0;
State prevState = currentState;
if (invisible && name != null) {
currentState = State.HOLOGRAM;
} else {
currentState = State.ZOMBIE;
}
if (currentState != prevState) {
deleteEntity();
sendSpawnPacket();
} else {
updateMetadata();
updateLocation(false);
}
}
public void updateLocation(boolean remount) {
if (entityIds == null) return;
if (currentState == State.ZOMBIE) {
teleportEntity(entityId, locX, locY, locZ, yaw, pitch);
final PacketWrapper entityHeadLook = PacketWrapper.create(ClientboundPackets1_7_2_5.ENTITY_HEAD_LOOK, user);
entityHeadLook.write(Type.INT, entityId);
entityHeadLook.write(Type.BYTE, (byte) ((headYaw / 360f) * 256));
PacketUtil.sendPacket(entityHeadLook, Protocol1_7_6_10To1_8.class, true, true);
} else if (currentState == State.HOLOGRAM) {
if (remount) {
PacketWrapper detach = PacketWrapper.create(ClientboundPackets1_7_2_5.ATTACH_ENTITY, null, user);
detach.write(Type.INT, entityIds[1]);
detach.write(Type.INT, -1);
detach.write(Type.BOOLEAN, false);
PacketUtil.sendPacket(detach, Protocol1_7_6_10To1_8.class, true, true);
}
// Don't ask me where this offset is coming from
teleportEntity(entityIds[0], locX, (locY + (marker ? 54.85 : small ? 56 : 57) - 0.16), locZ, 0, 0); // Skull
if (remount) {
teleportEntity(entityIds[1], locX, locY + 56.75, locZ, 0, 0); // Horse
PacketWrapper attach = PacketWrapper.create(ClientboundPackets1_7_2_5.ATTACH_ENTITY, null, user);
attach.write(Type.INT, entityIds[1]);
attach.write(Type.INT, entityIds[0]);
attach.write(Type.BOOLEAN, false);
PacketUtil.sendPacket(attach, Protocol1_7_6_10To1_8.class, true, true);
}
}
}
protected void teleportEntity(final int entityId, final double x, final double y, final double z, final float yaw, final float pitch) {
final PacketWrapper entityTeleport = PacketWrapper.create(ClientboundPackets1_7_2_5.ENTITY_TELEPORT, user);
entityTeleport.write(Type.INT, entityId); // entity id
entityTeleport.write(Type.INT, (int) (x * 32.0)); // x
entityTeleport.write(Type.INT, (int) (y * 32.0)); // y
entityTeleport.write(Type.INT, (int) (z * 32.0)); // z
entityTeleport.write(Type.BYTE, (byte) ((yaw / 360f) * 256)); // yaw
entityTeleport.write(Type.BYTE, (byte) ((pitch / 360f) * 256)); // pitch
PacketUtil.sendPacket(entityTeleport, Protocol1_7_6_10To1_8.class, true, true);
}
protected void spawnEntity(final int entityId, final int type, final double locX, final double locY, final double locZ) {
final PacketWrapper spawnMob = PacketWrapper.create(ClientboundPackets1_7_2_5.SPAWN_MOB, null, user);
spawnMob.write(Type.VAR_INT, entityId); // entity id
spawnMob.write(Type.UNSIGNED_BYTE, (short) type); // type
spawnMob.write(Type.INT, (int) (locX * 32.0)); // x
spawnMob.write(Type.INT, (int) (locY * 32.0)); // y
spawnMob.write(Type.INT, (int) (locZ * 32.0)); // z
spawnMob.write(Type.BYTE, (byte) 0); // yaw
spawnMob.write(Type.BYTE, (byte) 0); // pitch
spawnMob.write(Type.BYTE, (byte) 0); // head pitch
spawnMob.write(Type.SHORT, (short) 0); // velocity x
spawnMob.write(Type.SHORT, (short) 0); // velocity y
spawnMob.write(Type.SHORT, (short) 0); // velocity z
spawnMob.write(Types1_7_6_10.METADATA_LIST, new ArrayList<>()); // metadata
PacketUtil.sendPacket(spawnMob, Protocol1_7_6_10To1_8.class, true, true);
}
public void updateMetadata() {
if (entityIds == null) return;
PacketWrapper metadataPacket = PacketWrapper.create(ClientboundPackets1_7_2_5.ENTITY_METADATA, null, user);
if (currentState == State.ZOMBIE) {
writeZombieMeta(metadataPacket);
} else if (currentState == State.HOLOGRAM) {
writeHologramMeta(metadataPacket);
} else {
return;
}
PacketUtil.sendPacket(metadataPacket, Protocol1_7_6_10To1_8.class, true, true);
}
private void writeZombieMeta(PacketWrapper metadataPacket) {
metadataPacket.write(Type.INT, entityIds[0]);
List<Metadata> metadataList = new ArrayList<>();
for (Metadata metadata : metadataTracker) {
if (metadata.id() < 0 || metadata.id() > 9) continue;
metadataList.add(new Metadata(metadata.id(), metadata.metaType(), metadata.getValue()));
}
if (small) metadataList.add(new Metadata(12, MetaType1_8.Byte, (byte) 1));
metadataRewriter.transform(EntityTypes1_10.EntityType.ZOMBIE, metadataList);
metadataPacket.write(Types1_7_6_10.METADATA_LIST, metadataList);
}
private void writeHologramMeta(PacketWrapper metadataPacket) {
metadataPacket.write(Type.INT, entityIds[1]);
List<Metadata> metadataList = new ArrayList<>();
metadataList.add(new Metadata(MetaIndex1_7_6_10To1_8.ENTITY_AGEABLE_AGE.getIndex(), MetaType1_7_6_10.Int, -1700000));
metadataList.add(new Metadata(MetaIndex1_7_6_10To1_8.ENTITY_LIVING_NAME_TAG.getIndex(), MetaType1_7_6_10.String, name));
metadataList.add(new Metadata(MetaIndex1_7_6_10To1_8.ENTITY_LIVING_NAME_TAG_VISIBILITY.getIndex(), MetaType1_7_6_10.Byte, (byte) 1));
metadataPacket.write(Types1_7_6_10.METADATA_LIST, metadataList);
}
public void sendSpawnPacket() {
if (entityIds != null) deleteEntity();
if (currentState == State.ZOMBIE) {
spawnEntity(entityId, 54, locX, locY, locZ);
entityIds = new int[]{entityId};
} else if (currentState == State.HOLOGRAM) {
int[] entityIds = {entityId, additionalEntityId()};
PacketWrapper spawnSkull = PacketWrapper.create(ClientboundPackets1_7_2_5.SPAWN_ENTITY, null, user);
spawnSkull.write(Type.VAR_INT, entityIds[0]);
spawnSkull.write(Type.BYTE, (byte) 66);
spawnSkull.write(Type.INT, (int) (locX * 32.0));
spawnSkull.write(Type.INT, (int) (locY * 32.0));
spawnSkull.write(Type.INT, (int) (locZ * 32.0));
spawnSkull.write(Type.BYTE, (byte) 0);
spawnSkull.write(Type.BYTE, (byte) 0);
spawnSkull.write(Type.INT, 0);
PacketUtil.sendPacket(spawnSkull, Protocol1_7_6_10To1_8.class, true, true);
spawnEntity(entityIds[1], 100, locX, locY, locZ); // Horse
this.entityIds = entityIds;
}
updateMetadata();
updateLocation(true);
}
public AABB getBoundingBox() {
final double width = this.small ? 0.25 : 0.5;
final double height = this.small ? 0.9875 : 1.975;
final Vector3d min = new Vector3d(this.locX - width / 2, this.locY, this.locZ - width / 2);
final Vector3d max = new Vector3d(this.locX + width / 2, this.locY + height, this.locZ + width / 2);
return new AABB(min, max);
}
private int additionalEntityId() {
return Integer.MAX_VALUE - 16000 - entityId;
}
public void deleteEntity() {
if (entityIds == null) return;
PacketWrapper despawn = PacketWrapper.create(ClientboundPackets1_7_2_5.DESTROY_ENTITIES, null, user);
despawn.write(Type.BYTE, (byte) entityIds.length);
for (int id : entityIds) {
despawn.write(Type.INT, id);
}
entityIds = null;
PacketUtil.sendPacket(despawn, Protocol1_7_6_10To1_8.class, true, true);
}
private enum State {
HOLOGRAM, ZOMBIE
}
public int getEntityId() {
return entityId;
}
}
@@ -1,358 +0,0 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2016-2023 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.packets;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.Protocol1_7_6_10To1_8;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.model.VirtualHologramEntity;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.storage.EntityTracker1_7_6_10;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.storage.GameProfileStorage;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.storage.PlayerSessionStorage;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.types.Types1_7_6_10;
import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_10;
import com.viaversion.viaversion.api.minecraft.item.Item;
import com.viaversion.viaversion.api.minecraft.metadata.Metadata;
import com.viaversion.viaversion.api.protocol.remapper.PacketHandlers;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.types.version.Types1_8;
import com.viaversion.viaversion.protocols.protocol1_8.ClientboundPackets1_8;
import java.util.List;
import java.util.UUID;
public class EntityPackets {
public static void register(Protocol1_7_6_10To1_8 protocol) {
protocol.registerClientbound(ClientboundPackets1_8.ENTITY_EQUIPMENT, new PacketHandlers() {
@Override
public void register() {
map(Type.VAR_INT, Type.INT); // entity id
map(Type.SHORT); // slot
map(Type.ITEM1_8, Types1_7_6_10.COMPRESSED_NBT_ITEM); // item
// remap item
handler(wrapper -> {
final Item item = wrapper.get(Types1_7_6_10.COMPRESSED_NBT_ITEM, 0);
protocol.getItemRewriter().handleItemToClient(item);
wrapper.set(Types1_7_6_10.COMPRESSED_NBT_ITEM, 0, item);
});
handler(wrapper -> {
final short slot = wrapper.get(Type.SHORT, 0);
final UUID uuid = wrapper.user().get(EntityTracker1_7_6_10.class).getPlayerUUID(wrapper.get(Type.INT, 0));
if (uuid == null) return;
final Item item = wrapper.get(Types1_7_6_10.COMPRESSED_NBT_ITEM, 0);
wrapper.user().get(PlayerSessionStorage.class).setPlayerEquipment(uuid, item, slot);
final GameProfileStorage storage = wrapper.user().get(GameProfileStorage.class);
GameProfileStorage.GameProfile profile = storage.get(uuid);
if (profile != null && profile.gamemode == 3) { // spectator mode didn't exist in 1.7.10
wrapper.cancel();
}
});
}
});
protocol.registerClientbound(ClientboundPackets1_8.USE_BED, new PacketHandlers() {
@Override
public void register() {
map(Type.VAR_INT, Type.INT); // entity id
map(Type.POSITION1_8, Types1_7_6_10.U_BYTE_POSITION); // position
}
});
protocol.registerClientbound(ClientboundPackets1_8.COLLECT_ITEM, new PacketHandlers() {
@Override
public void register() {
map(Type.VAR_INT, Type.INT); // collected entity id
map(Type.VAR_INT, Type.INT); // collector entity id
handler(wrapper -> wrapper.user().get(EntityTracker1_7_6_10.class).removeEntity(wrapper.get(Type.INT, 0)));
}
});
protocol.registerClientbound(ClientboundPackets1_8.ENTITY_VELOCITY, new PacketHandlers() {
@Override
public void register() {
map(Type.VAR_INT, Type.INT); // entity id
map(Type.SHORT); // velocity x
map(Type.SHORT); // velocity y
map(Type.SHORT); // velocity z
}
});
protocol.registerClientbound(ClientboundPackets1_8.DESTROY_ENTITIES, new PacketHandlers() {
@Override
public void register() {
map(Type.VAR_INT_ARRAY_PRIMITIVE, Types1_7_6_10.BYTE_INT_ARRAY); // entity ids
handler(wrapper -> {
final EntityTracker1_7_6_10 tracker = wrapper.user().get(EntityTracker1_7_6_10.class);
for (int entityId : wrapper.get(Types1_7_6_10.BYTE_INT_ARRAY, 0)) {
tracker.removeEntity(entityId);
}
});
}
});
protocol.registerClientbound(ClientboundPackets1_8.ENTITY_MOVEMENT, new PacketHandlers() {
@Override
public void register() {
map(Type.VAR_INT, Type.INT); // entity id
}
});
protocol.registerClientbound(ClientboundPackets1_8.ENTITY_POSITION, new PacketHandlers() {
@Override
public void register() {
map(Type.VAR_INT, Type.INT); // entity id
map(Type.BYTE); // x
map(Type.BYTE); // y
map(Type.BYTE); // z
read(Type.BOOLEAN); // on ground
handler(wrapper -> {
final EntityTracker1_7_6_10 tracker = wrapper.user().get(EntityTracker1_7_6_10.class);
final VirtualHologramEntity hologram = tracker.getVirtualHologramMap().get(wrapper.get(Type.INT, 0));
if (hologram != null) {
wrapper.cancel();
final int x = wrapper.get(Type.BYTE, 0);
final int y = wrapper.get(Type.BYTE, 1);
final int z = wrapper.get(Type.BYTE, 2);
hologram.handleOriginalMovementPacket(x / 32.0, y / 32.0, z / 32.0);
}
});
}
});
protocol.registerClientbound(ClientboundPackets1_8.ENTITY_ROTATION, new PacketHandlers() {
@Override
public void register() {
map(Type.VAR_INT, Type.INT); // entity id
map(Type.BYTE); // yaw
map(Type.BYTE); // pitch
read(Type.BOOLEAN); // on ground
handler(wrapper -> {
final EntityTracker1_7_6_10 tracker = wrapper.user().get(EntityTracker1_7_6_10.class);
final VirtualHologramEntity hologram = tracker.getVirtualHologramMap().get(wrapper.get(Type.INT, 0));
if (hologram != null) {
wrapper.cancel();
final int yaw = wrapper.get(Type.BYTE, 0);
final int pitch = wrapper.get(Type.BYTE, 1);
hologram.setYawPitch(yaw * 360f / 256, pitch * 360f / 256);
}
});
}
});
protocol.registerClientbound(ClientboundPackets1_8.ENTITY_POSITION_AND_ROTATION, new PacketHandlers() {
@Override
public void register() {
map(Type.VAR_INT, Type.INT); // entity id
map(Type.BYTE); // x
map(Type.BYTE); // y
map(Type.BYTE); // z
map(Type.BYTE); // yaw
map(Type.BYTE); // pitch
read(Type.BOOLEAN); // on ground
handler(wrapper -> {
final EntityTracker1_7_6_10 tracker = wrapper.user().get(EntityTracker1_7_6_10.class);
final VirtualHologramEntity hologram = tracker.getVirtualHologramMap().get(wrapper.get(Type.INT, 0));
if (hologram != null) {
wrapper.cancel();
final int x = wrapper.get(Type.BYTE, 0);
final int y = wrapper.get(Type.BYTE, 1);
final int z = wrapper.get(Type.BYTE, 2);
final int yaw = wrapper.get(Type.BYTE, 3);
final int pitch = wrapper.get(Type.BYTE, 4);
hologram.handleOriginalMovementPacket(x / 32.0, y / 32.0, z / 32.0);
hologram.setYawPitch(yaw * 360f / 256, pitch * 360f / 256);
}
});
}
});
protocol.registerClientbound(ClientboundPackets1_8.ENTITY_TELEPORT, new PacketHandlers() {
@Override
public void register() {
map(Type.VAR_INT, Type.INT); // entity id
map(Type.INT); // x
map(Type.INT); // y
map(Type.INT); // z
map(Type.BYTE); // yaw
map(Type.BYTE); // pitch
read(Type.BOOLEAN); // on ground
handler(wrapper -> {
final EntityTracker1_7_6_10 tracker = wrapper.user().get(EntityTracker1_7_6_10.class);
final int entityId = wrapper.get(Type.INT, 0);
final EntityTypes1_10.EntityType type = tracker.getEntityMap().get(entityId);
if (type == EntityTypes1_10.EntityType.MINECART_ABSTRACT) { // TODO | Realign all entities?
int y = wrapper.get(Type.INT, 2);
y += 12;
wrapper.set(Type.INT, 2, y);
}
final VirtualHologramEntity hologram = tracker.getVirtualHologramMap().get(entityId);
if (hologram != null) {
wrapper.cancel();
final int x = wrapper.get(Type.INT, 1);
final int y = wrapper.get(Type.INT, 2);
final int z = wrapper.get(Type.INT, 3);
final int yaw = wrapper.get(Type.BYTE, 0);
final int pitch = wrapper.get(Type.BYTE, 1);
hologram.updateReplacementPosition(x / 32.0, y / 32.0, z / 32.0);
hologram.setYawPitch(yaw * 360f / 256, pitch * 360f / 256);
}
});
}
});
protocol.registerClientbound(ClientboundPackets1_8.ENTITY_HEAD_LOOK, new PacketHandlers() {
@Override
public void register() {
map(Type.VAR_INT, Type.INT); // entity id
map(Type.BYTE); // head yaw
handler(wrapper -> {
final EntityTracker1_7_6_10 tracker = wrapper.user().get(EntityTracker1_7_6_10.class);
final VirtualHologramEntity hologram = tracker.getVirtualHologramMap().get(wrapper.get(Type.INT, 0));
if (hologram != null) {
wrapper.cancel();
final int yaw = wrapper.get(Type.BYTE, 0);
hologram.setHeadYaw(yaw * 360f / 256);
}
});
}
});
protocol.registerClientbound(ClientboundPackets1_8.ATTACH_ENTITY, new PacketHandlers() {
@Override
public void register() {
map(Type.INT); // riding entity id
map(Type.INT); // vehicle entity id
map(Type.BOOLEAN); // leash state
handler(packetWrapper -> {
final boolean leash = packetWrapper.get(Type.BOOLEAN, 0);
if (!leash) {
final EntityTracker1_7_6_10 tracker = packetWrapper.user().get(EntityTracker1_7_6_10.class);
final int passenger = packetWrapper.get(Type.INT, 0);
final int vehicle = packetWrapper.get(Type.INT, 1);
tracker.setPassenger(vehicle, passenger);
}
});
}
});
protocol.registerClientbound(ClientboundPackets1_8.ENTITY_METADATA, new PacketHandlers() {
@Override
public void register() {
map(Type.VAR_INT, Type.INT); // entity id
map(Types1_8.METADATA_LIST, Types1_7_6_10.METADATA_LIST); // metadata
handler(wrapper -> {
final int entityId = wrapper.get(Type.INT, 0);
final List<Metadata> metadataList = wrapper.get(Types1_7_6_10.METADATA_LIST, 0);
final EntityTracker1_7_6_10 tracker = wrapper.user().get(EntityTracker1_7_6_10.class);
if (tracker.getEntityReplacementMap().containsKey(entityId)) {
tracker.updateMetadata(entityId, metadataList);
wrapper.cancel();
return;
}
if (tracker.getEntityMap().containsKey(entityId)) {
protocol.getMetadataRewriter().transform(tracker.getEntityMap().get(entityId), metadataList);
if (metadataList.isEmpty()) {
wrapper.cancel();
}
} else {
wrapper.cancel();
}
});
}
});
protocol.registerClientbound(ClientboundPackets1_8.ENTITY_EFFECT, new PacketHandlers() {
@Override
public void register() {
map(Type.VAR_INT, Type.INT); // entity id
map(Type.BYTE); // effect id
map(Type.BYTE); // amplifier
map(Type.VAR_INT, Type.SHORT); // duration
read(Type.BYTE); // hide particles
}
});
protocol.registerClientbound(ClientboundPackets1_8.REMOVE_ENTITY_EFFECT, new PacketHandlers() {
@Override
public void register() {
map(Type.VAR_INT, Type.INT); // entity id
map(Type.BYTE); // effect id
}
});
protocol.registerClientbound(ClientboundPackets1_8.ENTITY_PROPERTIES, new PacketHandlers() {
@Override
public void register() {
map(Type.VAR_INT, Type.INT); // entity id
handler(wrapper -> {
final int entityId = wrapper.get(Type.INT, 0);
if (wrapper.user().get(EntityTracker1_7_6_10.class).getEntityReplacementMap().containsKey(entityId)) {
wrapper.cancel();
return;
}
final int amount = wrapper.passthrough(Type.INT);
for (int i = 0; i < amount; i++) {
wrapper.passthrough(Type.STRING); // id
wrapper.passthrough(Type.DOUBLE); // value
int modifierLength = wrapper.read(Type.VAR_INT);
wrapper.write(Type.SHORT, (short) modifierLength);
for (int j = 0; j < modifierLength; j++) {
wrapper.passthrough(Type.UUID); // modifier uuid
wrapper.passthrough(Type.DOUBLE); // modifier amount
wrapper.passthrough(Type.BYTE); // modifier operation
}
}
});
}
});
protocol.cancelClientbound(ClientboundPackets1_8.UPDATE_ENTITY_NBT);
}
}
@@ -1,269 +0,0 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2016-2023 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.packets;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.Protocol1_7_6_10To1_8;
import com.viaversion.viarewind.protocol.protocol1_7_2_5to1_7_6_10.ServerboundPackets1_7_2_5;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.model.FurnaceData;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.storage.GameProfileStorage;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.storage.InventoryTracker;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.storage.PlayerSessionStorage;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.types.Types1_7_6_10;
import com.viaversion.viarewind.utils.ChatUtil;
import com.viaversion.viaversion.api.minecraft.item.Item;
import com.viaversion.viaversion.api.protocol.remapper.PacketHandlers;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.libs.gson.JsonElement;
import com.viaversion.viaversion.protocols.protocol1_8.ClientboundPackets1_8;
import java.util.UUID;
public class InventoryPackets {
public static void register(Protocol1_7_6_10To1_8 protocol) {
protocol.registerClientbound(ClientboundPackets1_8.OPEN_WINDOW, wrapper -> {
final InventoryTracker windowTracker = wrapper.user().get(InventoryTracker.class);
final short windowId = wrapper.passthrough(Type.UNSIGNED_BYTE); // window id
final short windowTypeId = InventoryTracker.getInventoryType(wrapper.read(Type.STRING)); // window type
windowTracker.getWindowTypeMap().put(windowId, windowTypeId);
wrapper.write(Type.UNSIGNED_BYTE, windowTypeId); // window type id
final JsonElement titleComponent = wrapper.read(Type.COMPONENT); // Title
String title = ChatUtil.jsonToLegacy(titleComponent);
title = ChatUtil.removeUnusedColor(title, '8');
if (title.length() > 32) {
title = title.substring(0, 32);
}
wrapper.write(Type.STRING, title); // window title
wrapper.passthrough(Type.UNSIGNED_BYTE); // slots count
wrapper.write(Type.BOOLEAN, true); // use provided window title
if (windowTypeId == 11) { // Horse
wrapper.passthrough(Type.INT); // entity id
}
});
protocol.registerClientbound(ClientboundPackets1_8.CLOSE_WINDOW, wrapper -> {
final short windowId = wrapper.passthrough(Type.UNSIGNED_BYTE); // window id
wrapper.user().get(InventoryTracker.class).remove(windowId);
});
protocol.registerClientbound(ClientboundPackets1_8.SET_SLOT, new PacketHandlers() {
@Override
public void register() {
map(Type.UNSIGNED_BYTE); // window id
map(Type.SHORT); // slot
handler(wrapper -> {
final short windowType = wrapper.user().get(InventoryTracker.class).get(wrapper.get(Type.UNSIGNED_BYTE, 0));
final short slot = wrapper.get(Type.SHORT, 0);
if (windowType == 4) { // Enchantment Table
if (slot == 1) {
wrapper.cancel();
} else if (slot >= 2) {
wrapper.set(Type.SHORT, 0, (short) (slot - 1));
}
}
});
map(Type.ITEM1_8, Types1_7_6_10.COMPRESSED_NBT_ITEM); // item
// remap item
handler(wrapper -> {
final Item item = wrapper.get(Types1_7_6_10.COMPRESSED_NBT_ITEM, 0);
protocol.getItemRewriter().handleItemToClient(item);
wrapper.set(Types1_7_6_10.COMPRESSED_NBT_ITEM, 0, item);
});
handler(wrapper -> {
final short windowId = wrapper.get(Type.UNSIGNED_BYTE, 0);
if (windowId != 0) return;
final short slot = wrapper.get(Type.SHORT, 0);
if (slot < 5 || slot > 8) return;
final PlayerSessionStorage playerSession = wrapper.user().get(PlayerSessionStorage.class);
final Item item = wrapper.get(Types1_7_6_10.COMPRESSED_NBT_ITEM, 0);
playerSession.setPlayerEquipment(wrapper.user().getProtocolInfo().getUuid(), item, 8 - slot);
if (playerSession.isSpectator()) { // Spectator mode didn't exist in 1.7.10
wrapper.cancel();
}
});
}
});
protocol.registerClientbound(ClientboundPackets1_8.WINDOW_ITEMS, new PacketHandlers() {
@Override
public void register() {
map(Type.UNSIGNED_BYTE); // window id
// remap enchantment table items
handler(wrapper -> {
final short windowType = wrapper.user().get(InventoryTracker.class).get(wrapper.get(Type.UNSIGNED_BYTE, 0));
Item[] items = wrapper.read(Type.ITEM1_8_SHORT_ARRAY);
if (windowType == 4) { // Enchantment Table
Item[] old = items;
items = new Item[old.length - 1];
items[0] = old[0];
System.arraycopy(old, 2, items, 1, old.length - 3);
}
for (int i = 0; i < items.length; i++) {
items[i] = protocol.getItemRewriter().handleItemToClient(items[i]);
}
wrapper.write(Types1_7_6_10.COMPRESSED_NBT_ITEM_ARRAY, items); // items
});
handler(wrapper -> {
final short windowId = wrapper.get(Type.UNSIGNED_BYTE, 0);
if (windowId != 0) return;
final UUID userId = wrapper.user().getProtocolInfo().getUuid();
final PlayerSessionStorage playerSession = wrapper.user().get(PlayerSessionStorage.class);
final Item[] items = wrapper.get(Types1_7_6_10.COMPRESSED_NBT_ITEM_ARRAY, 0);
for (int i = 5; i < 9; i++) {
playerSession.setPlayerEquipment(userId, items[i], 8 - i);
if (playerSession.isSpectator()) {
items[i] = null;
}
}
if (playerSession.isSpectator()) {
final GameProfileStorage.GameProfile profile = wrapper.user().get(GameProfileStorage.class).get(userId);
if (profile != null) {
items[5] = profile.getSkull();
}
}
});
}
});
protocol.registerClientbound(ClientboundPackets1_8.WINDOW_PROPERTY, new PacketHandlers() {
@Override
public void register() {
map(Type.UNSIGNED_BYTE); // window id
map(Type.SHORT); // progress bar id
map(Type.SHORT); // progress bar value
handler(wrapper -> {
final InventoryTracker windowTracker = wrapper.user().get(InventoryTracker.class);
final short windowId = wrapper.get(Type.UNSIGNED_BYTE, 0);
final short windowType = windowTracker.get(windowId);
final short progressBarId = wrapper.get(Type.SHORT, 0);
short progress = wrapper.get(Type.SHORT, 1);
if (windowType == 2) { // Furnace
final FurnaceData furnace = windowTracker.getFurnaceData().computeIfAbsent(windowId, x -> new FurnaceData());
if (progressBarId == 0 || progressBarId == 1) {
if (progressBarId == 0) {
furnace.fuelLeft = progress;
} else {
furnace.maxFuel = progress;
}
if (furnace.maxFuel == 0) {
wrapper.cancel();
return;
}
progress = (short) (200 * furnace.fuelLeft / furnace.maxFuel);
wrapper.set(Type.SHORT, 0, (short) 1);
wrapper.set(Type.SHORT, 1, progress);
} else if (progressBarId == 2 || progressBarId == 3) {
if (progressBarId == 2) {
furnace.progress = progress;
} else {
furnace.maxProgress = progress;
}
if (furnace.maxProgress == 0) {
wrapper.cancel();
return;
}
progress = (short) (200 * furnace.progress / furnace.maxProgress);
wrapper.set(Type.SHORT, 0, (short) 0);
wrapper.set(Type.SHORT, 1, progress);
}
} else if (windowType == 4 && progressBarId > 2) { // Enchanting Table
wrapper.cancel();
} else if (windowType == 8) { // Anvil
windowTracker.levelCost = progress;
windowTracker.anvilId = windowId;
}
});
}
});
protocol.registerServerbound(ServerboundPackets1_7_2_5.CLOSE_WINDOW, wrapper -> {
final short windowId = wrapper.passthrough(Type.UNSIGNED_BYTE);
wrapper.user().get(InventoryTracker.class).remove(windowId);
});
protocol.registerServerbound(ServerboundPackets1_7_2_5.CLICK_WINDOW, new PacketHandlers() {
@Override
public void register() {
map(Type.BYTE, Type.UNSIGNED_BYTE); // window id
map(Type.SHORT); // slot
handler(wrapper -> {
final short windowId = wrapper.get(Type.UNSIGNED_BYTE, 0); //Window Id
final short slot = wrapper.get(Type.SHORT, 0);
final short windowType = wrapper.user().get(InventoryTracker.class).get(windowId);
if (windowType == 4) { // Enchantment Table
if (slot > 0) {
wrapper.set(Type.SHORT, 0, (short) (slot + 1));
}
}
});
map(Type.BYTE); // button
map(Type.SHORT); // action number
map(Type.BYTE); // mode
map(Types1_7_6_10.COMPRESSED_NBT_ITEM, Type.ITEM1_8); // clicked item
// remap item
handler(wrapper -> {
final Item item = wrapper.get(Type.ITEM1_8, 0);
protocol.getItemRewriter().handleItemToServer(item);
wrapper.set(Type.ITEM1_8, 0, item);
});
}
});
protocol.registerServerbound(ServerboundPackets1_7_2_5.CREATIVE_INVENTORY_ACTION, new PacketHandlers() {
@Override
public void register() {
map(Type.SHORT); // slot
map(Types1_7_6_10.COMPRESSED_NBT_ITEM, Type.ITEM1_8); // item
// remap item
handler(wrapper -> {
final Item item = wrapper.get(Type.ITEM1_8, 0);
protocol.getItemRewriter().handleItemToServer(item);
wrapper.set(Type.ITEM1_8, 0, item);
});
}
});
}
}
@@ -1,917 +0,0 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2016-2023 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.packets;
import com.viaversion.viarewind.ViaRewind;
import com.viaversion.viarewind.protocol.protocol1_7_2_5to1_7_6_10.ClientboundPackets1_7_2_5;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.Protocol1_7_6_10To1_8;
import com.viaversion.viarewind.protocol.protocol1_7_2_5to1_7_6_10.ServerboundPackets1_7_2_5;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.provider.TitleRenderProvider;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.storage.*;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.types.Types1_7_6_10;
import com.viaversion.viarewind.utils.ChatUtil;
import com.viaversion.viarewind.utils.PacketUtil;
import com.viaversion.viarewind.utils.math.AABB;
import com.viaversion.viarewind.utils.math.Ray3d;
import com.viaversion.viarewind.utils.math.RayTracing;
import com.viaversion.viarewind.utils.math.Vector3d;
import com.viaversion.viaversion.api.Via;
import com.viaversion.viaversion.api.minecraft.Environment;
import com.viaversion.viaversion.api.minecraft.Position;
import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_10;
import com.viaversion.viaversion.api.minecraft.item.Item;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.protocol.remapper.PacketHandlers;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.libs.gson.JsonElement;
import com.viaversion.viaversion.libs.gson.JsonParser;
import com.viaversion.viaversion.libs.opennbt.tag.builtin.CompoundTag;
import com.viaversion.viaversion.libs.opennbt.tag.builtin.ListTag;
import com.viaversion.viaversion.libs.opennbt.tag.builtin.StringTag;
import com.viaversion.viaversion.protocols.protocol1_8.ClientboundPackets1_8;
import com.viaversion.viaversion.api.minecraft.ClientWorld;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufAllocator;
import io.netty.buffer.Unpooled;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.UUID;
public class PlayerPackets {
public static void register(Protocol1_7_6_10To1_8 protocol) {
protocol.registerClientbound(ClientboundPackets1_8.JOIN_GAME, new PacketHandlers() {
@Override
public void register() {
map(Type.INT); // entity id
map(Type.UNSIGNED_BYTE);// game mode
map(Type.BYTE); // dimension
map(Type.UNSIGNED_BYTE); // difficulty
map(Type.UNSIGNED_BYTE); // max players
map(Type.STRING); // level type
read(Type.BOOLEAN); // reduced debug info
handler(wrapper -> {
if (ViaRewind.getConfig().isReplaceAdventureMode()) {
if (wrapper.get(Type.UNSIGNED_BYTE, 0) == 2) { // adventure
wrapper.set(Type.UNSIGNED_BYTE, 0, (short) 0); // survival
}
}
final EntityTracker1_7_6_10 tracker = wrapper.user().get(EntityTracker1_7_6_10.class);
tracker.setClientEntityId(wrapper.get(Type.INT, 0));
tracker.addPlayer(wrapper.get(Type.INT, 0), wrapper.user().getProtocolInfo().getUuid());
wrapper.user().get(PlayerSessionStorage.class).gameMode = wrapper.get(Type.UNSIGNED_BYTE, 0);
wrapper.user().get(ClientWorld.class).setEnvironment(wrapper.get(Type.BYTE, 0));
// Reset on Velocity server change
wrapper.user().put(new Scoreboard(wrapper.user()));
});
}
});
protocol.registerClientbound(ClientboundPackets1_8.CHAT_MESSAGE, new PacketHandlers() {
@Override
public void register() {
map(Type.COMPONENT); // chat message
handler(wrapper -> {
final int position = wrapper.read(Type.BYTE);
if (position == 2) { // above hotbar
wrapper.cancel();
}
});
}
});
protocol.registerClientbound(ClientboundPackets1_8.SPAWN_POSITION, new PacketHandlers() {
@Override
public void register() {
map(Type.POSITION1_8, Types1_7_6_10.INT_POSITION); // spawn position
}
});
protocol.registerClientbound(ClientboundPackets1_8.UPDATE_HEALTH, new PacketHandlers() {
@Override
public void register() {
map(Type.FLOAT); // health
map(Type.VAR_INT, Type.SHORT); // food
map(Type.FLOAT); // food saturation
}
});
protocol.registerClientbound(ClientboundPackets1_8.RESPAWN, new PacketHandlers() {
@Override
public void register() {
map(Type.INT); // dimension
map(Type.UNSIGNED_BYTE); // difficulty
map(Type.UNSIGNED_BYTE); // game mode
map(Type.STRING); // level type
handler(wrapper -> {
if (ViaRewind.getConfig().isReplaceAdventureMode()) {
if (wrapper.get(Type.UNSIGNED_BYTE, 1) == 2) {
wrapper.set(Type.UNSIGNED_BYTE, 1, (short) 0);
}
}
wrapper.user().get(PlayerSessionStorage.class).gameMode = wrapper.get(Type.UNSIGNED_BYTE, 1);
final ClientWorld world = wrapper.user().get(ClientWorld.class);
final Environment dimension = Environment.getEnvironmentById(wrapper.get(Type.INT, 0));
final EntityTracker1_7_6_10 tracker = wrapper.user().get(EntityTracker1_7_6_10.class);
if (world.getEnvironment() != dimension) {
world.setEnvironment(dimension.id());
// Reset on dimension change
tracker.clear();
tracker.getEntityMap().put(tracker.getPlayerId(), EntityTypes1_10.EntityType.ENTITY_HUMAN);
}
});
}
});
protocol.registerClientbound(ClientboundPackets1_8.PLAYER_POSITION, new PacketHandlers() {
@Override
public void register() {
map(Type.DOUBLE); // x
map(Type.DOUBLE); // y
map(Type.DOUBLE); // z
map(Type.FLOAT); // yaw
map(Type.FLOAT); // pitch
handler(wrapper -> {
final double x = wrapper.get(Type.DOUBLE, 0);
double y = wrapper.get(Type.DOUBLE, 1);
final double z = wrapper.get(Type.DOUBLE, 2);
final float yaw = wrapper.get(Type.FLOAT, 0);
final float pitch = wrapper.get(Type.FLOAT, 1);
final PlayerSessionStorage playerSession = wrapper.user().get(PlayerSessionStorage.class);
final int flags = wrapper.read(Type.BYTE);
// x, y, and z
if ((flags & 0x01) == 0x01) wrapper.set(Type.DOUBLE, 0, x + playerSession.getPosX());
if ((flags & 0x02) == 0x02) y += playerSession.getPosY();
playerSession.receivedPosY = y;
wrapper.set(Type.DOUBLE, 1, y + 1.62F);
if ((flags & 0x04) == 0x04) wrapper.set(Type.DOUBLE, 2, z + playerSession.getPosZ());
// yaw and pitch
if ((flags & 0x08) == 0x08) wrapper.set(Type.FLOAT, 0, yaw + playerSession.yaw);
if ((flags & 0x10) == 0x10) wrapper.set(Type.FLOAT, 1, pitch + playerSession.pitch);
wrapper.write(Type.BOOLEAN, playerSession.onGround);
final EntityTracker1_7_6_10 tracker = wrapper.user().get(EntityTracker1_7_6_10.class);
if (tracker.spectatingPlayerId != tracker.getPlayerId()) {
wrapper.cancel();
}
});
}
});
protocol.registerClientbound(ClientboundPackets1_8.SET_EXPERIENCE, new PacketHandlers() {
@Override
public void register() {
map(Type.FLOAT); // experience bar
map(Type.VAR_INT, Type.SHORT); // level
map(Type.VAR_INT, Type.SHORT); // total experience
}
});
protocol.registerClientbound(ClientboundPackets1_8.GAME_EVENT, new PacketHandlers() {
@Override
public void register() {
map(Type.UNSIGNED_BYTE); // reason
map(Type.FLOAT); // value
handler(wrapper -> {
if (wrapper.get(Type.UNSIGNED_BYTE, 0) != 3) return; // Change game mode
int gameMode = wrapper.get(Type.FLOAT, 0).intValue();
final PlayerSessionStorage playerSession = wrapper.user().get(PlayerSessionStorage.class);
if (gameMode == 3 || playerSession.gameMode == 3) {
UUID myId = wrapper.user().getProtocolInfo().getUuid();
Item[] equipment = new Item[4];
if (gameMode == 3) {
GameProfileStorage.GameProfile profile = wrapper.user().get(GameProfileStorage.class).get(myId);
equipment[3] = profile == null ? null : profile.getSkull();
} else {
for (int i = 0; i < equipment.length; i++) {
equipment[i] = playerSession.getPlayerEquipment(myId, i);
}
}
for (int i = 0; i < equipment.length; i++) {
PacketWrapper setSlot = PacketWrapper.create(ClientboundPackets1_7_2_5.SET_SLOT, wrapper.user());
setSlot.write(Type.BYTE, (byte) 0);
setSlot.write(Type.SHORT, (short) (8 - i));
setSlot.write(Types1_7_6_10.COMPRESSED_NBT_ITEM, equipment[i]);
PacketUtil.sendPacket(setSlot, Protocol1_7_6_10To1_8.class);
}
}
if (gameMode == 2 && ViaRewind.getConfig().isReplaceAdventureMode()) {
gameMode = 0;
wrapper.set(Type.FLOAT, 0, 0.0f);
}
wrapper.user().get(PlayerSessionStorage.class).gameMode = gameMode;
});
}
});
protocol.registerClientbound(ClientboundPackets1_8.OPEN_SIGN_EDITOR, new PacketHandlers() {
@Override
public void register() {
map(Type.POSITION1_8, Types1_7_6_10.INT_POSITION); // position
}
});
protocol.registerClientbound(ClientboundPackets1_8.PLAYER_INFO, new PacketHandlers() {
@Override
public void register() {
handler(packetWrapper -> {
packetWrapper.cancel();
int action = packetWrapper.read(Type.VAR_INT);
int count = packetWrapper.read(Type.VAR_INT);
GameProfileStorage gameProfileStorage = packetWrapper.user().get(GameProfileStorage.class);
for (int i = 0; i < count; i++) {
UUID uuid = packetWrapper.read(Type.UUID);
if (action == 0) {
String name = packetWrapper.read(Type.STRING);
GameProfileStorage.GameProfile gameProfile = gameProfileStorage.get(uuid);
if (gameProfile == null) gameProfile = gameProfileStorage.put(uuid, name);
int propertyCount = packetWrapper.read(Type.VAR_INT);
while (propertyCount-- > 0) {
String propertyName = packetWrapper.read(Type.STRING);
String propertyValue = packetWrapper.read(Type.STRING);
String propertySignature = packetWrapper.read(Type.OPTIONAL_STRING);
gameProfile.properties.add(new GameProfileStorage.Property(propertyName, propertyValue, propertySignature));
}
int gamemode = packetWrapper.read(Type.VAR_INT);
int ping = packetWrapper.read(Type.VAR_INT);
gameProfile.ping = ping;
gameProfile.gamemode = gamemode;
JsonElement displayName = packetWrapper.read(Type.OPTIONAL_COMPONENT);
if (displayName != null) {
gameProfile.setDisplayName(ChatUtil.jsonToLegacy(displayName));
}
PacketWrapper packet = PacketWrapper.create(ClientboundPackets1_7_2_5.PLAYER_INFO, null, packetWrapper.user());
packet.write(Type.STRING, gameProfile.getDisplayName());
packet.write(Type.BOOLEAN, true);
packet.write(Type.SHORT, (short) ping);
PacketUtil.sendPacket(packet, Protocol1_7_6_10To1_8.class);
} else if (action == 1) {
int gamemode = packetWrapper.read(Type.VAR_INT);
GameProfileStorage.GameProfile gameProfile = gameProfileStorage.get(uuid);
if (gameProfile == null || gameProfile.gamemode == gamemode) continue;
if (gamemode == 3 || gameProfile.gamemode == 3) {
EntityTracker1_7_6_10 tracker = packetWrapper.user().get(EntityTracker1_7_6_10.class);
int entityId = tracker.getPlayerEntityId(uuid);
boolean isOwnPlayer = entityId == tracker.getPlayerId();
if (entityId != -1) {
// Weirdly, PlayerEntity has only 4 slots instead of 5
Item[] equipment = new Item[isOwnPlayer ? 4 : 5];
if (gamemode == 3) {
equipment[isOwnPlayer ? 3 : 4] = gameProfile.getSkull();
} else {
for (int j = 0; j < equipment.length; j++) {
equipment[j] = packetWrapper.user().get(PlayerSessionStorage.class).getPlayerEquipment(uuid, j);
}
}
for (short slot = 0; slot < equipment.length; slot++) {
PacketWrapper equipmentPacket = PacketWrapper.create(ClientboundPackets1_7_2_5.ENTITY_EQUIPMENT, packetWrapper.user());
equipmentPacket.write(Type.INT, entityId);
equipmentPacket.write(Type.SHORT, slot);
equipmentPacket.write(Types1_7_6_10.COMPRESSED_NBT_ITEM, equipment[slot]);
PacketUtil.sendPacket(equipmentPacket, Protocol1_7_6_10To1_8.class);
}
}
}
gameProfile.gamemode = gamemode;
} else if (action == 2) {
int ping = packetWrapper.read(Type.VAR_INT);
GameProfileStorage.GameProfile gameProfile = gameProfileStorage.get(uuid);
if (gameProfile == null) continue;
PacketWrapper packet = PacketWrapper.create(ClientboundPackets1_7_2_5.PLAYER_INFO, null, packetWrapper.user());
packet.write(Type.STRING, gameProfile.getDisplayName());
packet.write(Type.BOOLEAN, false);
packet.write(Type.SHORT, (short) gameProfile.ping);
PacketUtil.sendPacket(packet, Protocol1_7_6_10To1_8.class);
gameProfile.ping = ping;
packet = PacketWrapper.create(ClientboundPackets1_7_2_5.PLAYER_INFO, null, packetWrapper.user());
packet.write(Type.STRING, gameProfile.getDisplayName());
packet.write(Type.BOOLEAN, true);
packet.write(Type.SHORT, (short) ping);
PacketUtil.sendPacket(packet, Protocol1_7_6_10To1_8.class);
} else if (action == 3) {
JsonElement displayNameComponent = packetWrapper.read(Type.OPTIONAL_COMPONENT);
String displayName = displayNameComponent != null ? ChatUtil.jsonToLegacy(displayNameComponent) : null;
GameProfileStorage.GameProfile gameProfile = gameProfileStorage.get(uuid);
if (gameProfile == null || gameProfile.displayName == null && displayName == null) continue;
PacketWrapper packet = PacketWrapper.create(ClientboundPackets1_7_2_5.PLAYER_INFO, null, packetWrapper.user());
packet.write(Type.STRING, gameProfile.getDisplayName());
packet.write(Type.BOOLEAN, false);
packet.write(Type.SHORT, (short) gameProfile.ping);
PacketUtil.sendPacket(packet, Protocol1_7_6_10To1_8.class);
if (gameProfile.displayName == null && displayName != null || gameProfile.displayName != null && displayName == null || !gameProfile.displayName.equals(displayName)) {
gameProfile.setDisplayName(displayName);
}
packet = PacketWrapper.create(ClientboundPackets1_7_2_5.PLAYER_INFO, null, packetWrapper.user());
packet.write(Type.STRING, gameProfile.getDisplayName());
packet.write(Type.BOOLEAN, true);
packet.write(Type.SHORT, (short) gameProfile.ping);
PacketUtil.sendPacket(packet, Protocol1_7_6_10To1_8.class);
} else if (action == 4) {
GameProfileStorage.GameProfile gameProfile = gameProfileStorage.remove(uuid);
if (gameProfile == null) continue;
PacketWrapper packet = PacketWrapper.create(ClientboundPackets1_7_2_5.PLAYER_INFO, null, packetWrapper.user());
packet.write(Type.STRING, gameProfile.getDisplayName());
packet.write(Type.BOOLEAN, false);
packet.write(Type.SHORT, (short) gameProfile.ping);
PacketUtil.sendPacket(packet, Protocol1_7_6_10To1_8.class);
}
}
});
}
});
protocol.registerClientbound(ClientboundPackets1_8.PLAYER_ABILITIES, new PacketHandlers() {
@Override
public void register() {
map(Type.BYTE);
map(Type.FLOAT);
map(Type.FLOAT);
handler(packetWrapper -> {
byte flags = packetWrapper.get(Type.BYTE, 0);
float flySpeed = packetWrapper.get(Type.FLOAT, 0);
float walkSpeed = packetWrapper.get(Type.FLOAT, 1);
PlayerSessionStorage abilities = packetWrapper.user().get(PlayerSessionStorage.class);
abilities.invincible = (flags & 8) == 8;
abilities.allowFly = (flags & 4) == 4;
abilities.flying = (flags & 2) == 2;
abilities.creative = (flags & 1) == 1;
abilities.flySpeed = flySpeed;
abilities.walkSpeed = walkSpeed;
if (abilities.sprinting && abilities.flying) {
packetWrapper.set(Type.FLOAT, 0, abilities.flySpeed * 2.0f);
}
});
}
});
protocol.registerClientbound(ClientboundPackets1_8.PLUGIN_MESSAGE, new PacketHandlers() {
@Override
public void register() {
map(Type.STRING);
handler(packetWrapper -> {
String channel = packetWrapper.get(Type.STRING, 0);
if (channel.equalsIgnoreCase("MC|TrList")) {
packetWrapper.passthrough(Type.INT); //Window Id
int size;
if (packetWrapper.isReadable(Type.BYTE, 0)) {
size = packetWrapper.passthrough(Type.BYTE);
} else {
size = packetWrapper.passthrough(Type.UNSIGNED_BYTE);
}
for (int i = 0; i < size; i++) {
Item item = protocol.getItemRewriter().handleItemToClient(packetWrapper.read(Type.ITEM1_8));
packetWrapper.write(Types1_7_6_10.COMPRESSED_NBT_ITEM, item); //Buy Item 1
item = protocol.getItemRewriter().handleItemToClient(packetWrapper.read(Type.ITEM1_8));
packetWrapper.write(Types1_7_6_10.COMPRESSED_NBT_ITEM, item); //Buy Item 3
boolean has3Items = packetWrapper.passthrough(Type.BOOLEAN);
if (has3Items) {
item = protocol.getItemRewriter().handleItemToClient(packetWrapper.read(Type.ITEM1_8));
packetWrapper.write(Types1_7_6_10.COMPRESSED_NBT_ITEM, item); //Buy Item 2
}
packetWrapper.passthrough(Type.BOOLEAN); //Unavailable
packetWrapper.read(Type.INT); //Uses
packetWrapper.read(Type.INT); //Max Uses
}
} else if (channel.equalsIgnoreCase("MC|Brand")) {
packetWrapper.write(Type.REMAINING_BYTES, packetWrapper.read(Type.STRING).getBytes(StandardCharsets.UTF_8));
}
packetWrapper.cancel();
packetWrapper.setPacketType(null);
ByteBuf newPacketBuf = Unpooled.buffer();
packetWrapper.writeToBuffer(newPacketBuf);
PacketWrapper newWrapper = PacketWrapper.create(ClientboundPackets1_7_2_5.PLUGIN_MESSAGE, newPacketBuf, packetWrapper.user());
newWrapper.passthrough(Type.STRING);
if (newPacketBuf.readableBytes() <= Short.MAX_VALUE) {
newWrapper.write(Type.SHORT, (short) newPacketBuf.readableBytes());
newWrapper.send(Protocol1_7_6_10To1_8.class);
}
});
}
});
//Camera
protocol.registerClientbound(ClientboundPackets1_8.CAMERA, null, new PacketHandlers() {
@Override
public void register() {
handler(packetWrapper -> {
packetWrapper.cancel();
EntityTracker1_7_6_10 tracker = packetWrapper.user().get(EntityTracker1_7_6_10.class);
int entityId = packetWrapper.read(Type.VAR_INT);
int spectating = tracker.spectatingPlayerId;
if (spectating != entityId) {
tracker.setSpectating(entityId);
}
});
}
});
//Title
protocol.registerClientbound(ClientboundPackets1_8.TITLE, null, new PacketHandlers() {
@Override
public void register() {
handler(packetWrapper -> {
packetWrapper.cancel();
TitleRenderProvider titleRenderProvider = Via.getManager().getProviders().get(TitleRenderProvider.class);
if (titleRenderProvider == null) return;
int action = packetWrapper.read(Type.VAR_INT);
UUID uuid = packetWrapper.user().getProtocolInfo().getUuid();
switch (action) {
case 0:
titleRenderProvider.setTitle(uuid, packetWrapper.read(Type.STRING));
break;
case 1:
titleRenderProvider.setSubTitle(uuid, packetWrapper.read(Type.STRING));
break;
case 2:
titleRenderProvider.setTimings(uuid, packetWrapper.read(Type.INT), packetWrapper.read(Type.INT), packetWrapper.read(Type.INT));
break;
case 3:
titleRenderProvider.clear(uuid);
break;
case 4:
titleRenderProvider.reset(uuid);
break;
}
});
}
});
//Player List Header And Footer
protocol.cancelClientbound(ClientboundPackets1_8.TAB_LIST);
//Resource Pack Send
protocol.registerClientbound(ClientboundPackets1_8.RESOURCE_PACK, ClientboundPackets1_7_2_5.PLUGIN_MESSAGE, new PacketHandlers() {
@Override
public void register() {
create(Type.STRING, "MC|RPack");
handler(packetWrapper -> {
ByteBuf buf = ByteBufAllocator.DEFAULT.buffer();
try {
// Url
Type.STRING.write(buf, packetWrapper.read(Type.STRING));
packetWrapper.write(Type.SHORT_BYTE_ARRAY, Type.REMAINING_BYTES.read(buf));
} finally {
buf.release();
}
});
read(Type.STRING); // Hash
}
});
/* INCOMING */
protocol.registerServerbound(ServerboundPackets1_7_2_5.CHAT_MESSAGE, new PacketHandlers() {
@Override
public void register() {
map(Type.STRING);
handler(packetWrapper -> {
String msg = packetWrapper.get(Type.STRING, 0);
int gamemode = packetWrapper.user().get(PlayerSessionStorage.class).gameMode;
if (gamemode == 3 && msg.toLowerCase().startsWith("/stp ")) {
String username = msg.split(" ")[1];
GameProfileStorage storage = packetWrapper.user().get(GameProfileStorage.class);
GameProfileStorage.GameProfile profile = storage.get(username, true);
if (profile != null && profile.uuid != null) {
packetWrapper.cancel();
PacketWrapper teleportPacket = PacketWrapper.create(0x18, null, packetWrapper.user());
teleportPacket.write(Type.UUID, profile.uuid);
PacketUtil.sendToServer(teleportPacket, Protocol1_7_6_10To1_8.class, true, true);
}
}
});
}
});
protocol.registerServerbound(ServerboundPackets1_7_2_5.INTERACT_ENTITY, new PacketHandlers() {
@Override
public void register() {
map(Type.INT, Type.VAR_INT);
map(Type.BYTE, Type.VAR_INT);
handler(wrapper -> {
int mode = wrapper.get(Type.VAR_INT, 1);
if (mode != 0) {
return;
}
final int entityId = wrapper.get(Type.VAR_INT, 0);
final EntityTracker1_7_6_10 tracker = wrapper.user().get(EntityTracker1_7_6_10.class);
final PlayerSessionStorage position = wrapper.user().get(PlayerSessionStorage.class);
if (tracker.getVirtualHologramMap().containsKey(entityId)) {
final AABB boundingBox = tracker.getVirtualHologramMap().get(entityId).getBoundingBox();
Vector3d pos = new Vector3d(position.getPosX(), position.getPosY() + 1.8, position.getPosZ());
double yaw = Math.toRadians(position.yaw);
double pitch = Math.toRadians(position.pitch);
Vector3d dir = new Vector3d(-Math.cos(pitch) * Math.sin(yaw), -Math.sin(pitch), Math.cos(pitch) * Math.cos(yaw));
Ray3d ray = new Ray3d(pos, dir);
Vector3d intersection = RayTracing.trace(ray, boundingBox, 5.0);
if (intersection == null) {
return;
}
intersection.substract(boundingBox.getMin());
mode = 2;
wrapper.set(Type.VAR_INT, 1, mode);
wrapper.write(Type.FLOAT, (float) intersection.getX());
wrapper.write(Type.FLOAT, (float) intersection.getY());
wrapper.write(Type.FLOAT, (float) intersection.getZ());
}
});
}
});
protocol.registerServerbound(ServerboundPackets1_7_2_5.PLAYER_MOVEMENT, new PacketHandlers() {
@Override
public void register() {
map(Type.BOOLEAN);
handler(packetWrapper -> {
PlayerSessionStorage playerSession = packetWrapper.user().get(PlayerSessionStorage.class);
playerSession.onGround = packetWrapper.get(Type.BOOLEAN, 0);
});
}
});
protocol.registerServerbound(ServerboundPackets1_7_2_5.PLAYER_POSITION, new PacketHandlers() {
@Override
public void register() {
map(Type.DOUBLE); //X
map(Type.DOUBLE); //Y
read(Type.DOUBLE);
map(Type.DOUBLE); //Z
map(Type.BOOLEAN); //OnGround
handler(packetWrapper -> {
double x = packetWrapper.get(Type.DOUBLE, 0);
double feetY = packetWrapper.get(Type.DOUBLE, 1);
double z = packetWrapper.get(Type.DOUBLE, 2);
PlayerSessionStorage playerSession = packetWrapper.user().get(PlayerSessionStorage.class);
playerSession.onGround = packetWrapper.get(Type.BOOLEAN, 0);
playerSession.setPos(x, feetY, z);
});
}
});
protocol.registerServerbound(ServerboundPackets1_7_2_5.PLAYER_ROTATION, new PacketHandlers() {
@Override
public void register() {
map(Type.FLOAT);
map(Type.FLOAT);
map(Type.BOOLEAN);
handler(packetWrapper -> {
PlayerSessionStorage playerSession = packetWrapper.user().get(PlayerSessionStorage.class);
playerSession.yaw = packetWrapper.get(Type.FLOAT, 0);
playerSession.pitch = packetWrapper.get(Type.FLOAT, 1);
playerSession.onGround = packetWrapper.get(Type.BOOLEAN, 0);
});
}
});
protocol.registerServerbound(ServerboundPackets1_7_2_5.PLAYER_POSITION_AND_ROTATION, new PacketHandlers() {
@Override
public void register() {
map(Type.DOUBLE); //X
map(Type.DOUBLE); //Y
read(Type.DOUBLE);
map(Type.DOUBLE); //Z
map(Type.FLOAT); //Yaw
map(Type.FLOAT); //Pitch
map(Type.BOOLEAN); //OnGround
handler(packetWrapper -> {
double x = packetWrapper.get(Type.DOUBLE, 0);
double feetY = packetWrapper.get(Type.DOUBLE, 1);
double z = packetWrapper.get(Type.DOUBLE, 2);
float yaw = packetWrapper.get(Type.FLOAT, 0);
float pitch = packetWrapper.get(Type.FLOAT, 1);
PlayerSessionStorage playerSession = packetWrapper.user().get(PlayerSessionStorage.class);
playerSession.onGround = packetWrapper.get(Type.BOOLEAN, 0);
playerSession.setPos(x, feetY, z);
playerSession.yaw = yaw;
playerSession.pitch = pitch;
});
}
});
protocol.registerServerbound(ServerboundPackets1_7_2_5.PLAYER_DIGGING, new PacketHandlers() {
@Override
public void register() {
map(Type.VAR_INT); //Status
handler(packetWrapper -> {
int x = packetWrapper.read(Type.INT);
int y = packetWrapper.read(Type.UNSIGNED_BYTE);
int z = packetWrapper.read(Type.INT);
packetWrapper.write(Type.POSITION1_8, new Position(x, y, z));
});
}
});
protocol.registerServerbound(ServerboundPackets1_7_2_5.PLAYER_BLOCK_PLACEMENT, new PacketHandlers() {
@Override
public void register() {
handler(packetWrapper -> {
int x = packetWrapper.read(Type.INT);
int y = packetWrapper.read(Type.UNSIGNED_BYTE);
int z = packetWrapper.read(Type.INT);
packetWrapper.write(Type.POSITION1_8, new Position(x, y, z));
packetWrapper.passthrough(Type.BYTE); //Direction
Item item = packetWrapper.read(Types1_7_6_10.COMPRESSED_NBT_ITEM);
item = protocol.getItemRewriter().handleItemToServer(item);
packetWrapper.write(Type.ITEM1_8, item);
for (int i = 0; i < 3; i++) {
packetWrapper.passthrough(Type.BYTE);
}
});
}
});
protocol.registerServerbound(ServerboundPackets1_7_2_5.ANIMATION, new PacketHandlers() {
@Override
public void register() {
handler(packetWrapper -> {
int entityId = packetWrapper.read(Type.INT);
int animation = packetWrapper.read(Type.BYTE); //Animation
if (animation == 1) return;
packetWrapper.cancel();
//1.7 vanilla client is not sending this packet with animation!=1
switch (animation) {
case 104:
animation = 0;
break;
case 105:
animation = 1;
break;
case 3:
animation = 2;
break;
default:
return;
}
PacketWrapper entityAction = PacketWrapper.create(0x0B, null, packetWrapper.user());
entityAction.write(Type.VAR_INT, entityId);
entityAction.write(Type.VAR_INT, animation);
entityAction.write(Type.VAR_INT, 0);
PacketUtil.sendPacket(entityAction, Protocol1_7_6_10To1_8.class, true, true);
});
}
});
protocol.registerServerbound(ServerboundPackets1_7_2_5.ENTITY_ACTION, new PacketHandlers() {
@Override
public void register() {
map(Type.INT, Type.VAR_INT); //Entity Id
handler(packetWrapper -> packetWrapper.write(Type.VAR_INT, packetWrapper.read(Type.BYTE) - 1)); //Action Id
map(Type.INT, Type.VAR_INT); //Action Parameter
handler(packetWrapper -> {
int action = packetWrapper.get(Type.VAR_INT, 1);
if (action == 3 || action == 4) {
PlayerSessionStorage playerSession = packetWrapper.user().get(PlayerSessionStorage.class);
playerSession.sprinting = action == 3;
PacketWrapper abilitiesPacket = PacketWrapper.create(0x39, null, packetWrapper.user());
abilitiesPacket.write(Type.BYTE, playerSession.combineAbilities());
abilitiesPacket.write(Type.FLOAT, playerSession.sprinting ? playerSession.flySpeed * 2.0f : playerSession.flySpeed);
abilitiesPacket.write(Type.FLOAT, playerSession.walkSpeed);
PacketUtil.sendPacket(abilitiesPacket, Protocol1_7_6_10To1_8.class);
}
});
}
});
protocol.registerServerbound(ServerboundPackets1_7_2_5.STEER_VEHICLE, new PacketHandlers() {
@Override
public void register() {
map(Type.FLOAT); //Sideways
map(Type.FLOAT); //Forwards
handler(packetWrapper -> {
boolean jump = packetWrapper.read(Type.BOOLEAN);
boolean unmount = packetWrapper.read(Type.BOOLEAN);
short flags = 0;
if (jump) flags += 0x01;
if (unmount) flags += 0x02;
packetWrapper.write(Type.UNSIGNED_BYTE, flags);
if (unmount) {
EntityTracker1_7_6_10 tracker = packetWrapper.user().get(EntityTracker1_7_6_10.class);
if (tracker.spectatingPlayerId != tracker.getPlayerId()) {
PacketWrapper sneakPacket = PacketWrapper.create(0x0B, null, packetWrapper.user());
sneakPacket.write(Type.VAR_INT, tracker.getPlayerId());
sneakPacket.write(Type.VAR_INT, 0); //Start sneaking
sneakPacket.write(Type.VAR_INT, 0); //Action Parameter
PacketWrapper unsneakPacket = PacketWrapper.create(0x0B, null, packetWrapper.user());
unsneakPacket.write(Type.VAR_INT, tracker.getPlayerId());
unsneakPacket.write(Type.VAR_INT, 1); //Stop sneaking
unsneakPacket.write(Type.VAR_INT, 0); //Action Parameter
PacketUtil.sendToServer(sneakPacket, Protocol1_7_6_10To1_8.class);
}
}
});
}
});
protocol.registerServerbound(ServerboundPackets1_7_2_5.UPDATE_SIGN, new PacketHandlers() {
@Override
public void register() {
handler(packetWrapper -> {
int x = packetWrapper.read(Type.INT);
int y = packetWrapper.read(Type.SHORT);
int z = packetWrapper.read(Type.INT);
packetWrapper.write(Type.POSITION1_8, new Position(x, y, z));
for (int i = 0; i < 4; i++) {
String line = packetWrapper.read(Type.STRING);
line = ChatUtil.legacyToJson(line);
packetWrapper.write(Type.COMPONENT, JsonParser.parseString(line));
}
});
}
});
protocol.registerServerbound(ServerboundPackets1_7_2_5.PLAYER_ABILITIES, new PacketHandlers() {
@Override
public void register() {
map(Type.BYTE);
map(Type.FLOAT);
map(Type.FLOAT);
handler(packetWrapper -> {
PlayerSessionStorage playerSession = packetWrapper.user().get(PlayerSessionStorage.class);
if (playerSession.allowFly) {
byte flags = packetWrapper.get(Type.BYTE, 0);
playerSession.flying = (flags & 2) == 2;
}
packetWrapper.set(Type.FLOAT, 0, playerSession.flySpeed);
});
}
});
protocol.registerServerbound(ServerboundPackets1_7_2_5.TAB_COMPLETE, new PacketHandlers() {
@Override
public void register() {
map(Type.STRING);
create(Type.OPTIONAL_POSITION1_8, null);
handler(packetWrapper -> {
String msg = packetWrapper.get(Type.STRING, 0);
if (msg.toLowerCase().startsWith("/stp ")) {
packetWrapper.cancel();
String[] args = msg.split(" ");
if (args.length <= 2) {
String prefix = args.length == 1 ? "" : args[1];
GameProfileStorage storage = packetWrapper.user().get(GameProfileStorage.class);
List<GameProfileStorage.GameProfile> profiles = storage.getAllWithPrefix(prefix, true);
PacketWrapper tabComplete = PacketWrapper.create(0x3A, null, packetWrapper.user());
tabComplete.write(Type.VAR_INT, profiles.size());
for (GameProfileStorage.GameProfile profile : profiles) {
tabComplete.write(Type.STRING, profile.name);
}
PacketUtil.sendPacket(tabComplete, Protocol1_7_6_10To1_8.class);
}
}
});
}
});
//Client Settings
protocol.registerServerbound(ServerboundPackets1_7_2_5.CLIENT_SETTINGS, new PacketHandlers() {
@Override
public void register() {
map(Type.STRING);
map(Type.BYTE);
map(Type.BYTE);
map(Type.BOOLEAN);
read(Type.BYTE);
handler(packetWrapper -> {
boolean cape = packetWrapper.read(Type.BOOLEAN);
packetWrapper.write(Type.UNSIGNED_BYTE, (short) (cape ? 127 : 126));
});
}
});
protocol.registerServerbound(ServerboundPackets1_7_2_5.PLUGIN_MESSAGE, new PacketHandlers() {
@Override
public void register() {
map(Type.STRING);
read(Type.SHORT); // Length
handler(packetWrapper -> {
String channel = packetWrapper.get(Type.STRING, 0);
switch (channel) {
case "MC|TrSel": {
packetWrapper.passthrough(Type.INT);
packetWrapper.read(Type.REMAINING_BYTES); // unused data ???
break;
}
case "MC|ItemName": {
byte[] data = packetWrapper.read(Type.REMAINING_BYTES);
String name = new String(data, StandardCharsets.UTF_8);
packetWrapper.write(Type.STRING, name);
InventoryTracker windowTracker = packetWrapper.user().get(InventoryTracker.class);
PacketWrapper updateCost = PacketWrapper.create(0x31, null, packetWrapper.user());
updateCost.write(Type.UNSIGNED_BYTE, windowTracker.anvilId);
updateCost.write(Type.SHORT, (short) 0);
updateCost.write(Type.SHORT, windowTracker.levelCost);
PacketUtil.sendPacket(updateCost, Protocol1_7_6_10To1_8.class, true, true);
break;
}
case "MC|BEdit":
case "MC|BSign": {
Item book = packetWrapper.read(Types1_7_6_10.COMPRESSED_NBT_ITEM);
CompoundTag tag = book.tag();
if (tag != null && tag.contains("pages")) {
ListTag pages = tag.get("pages");
for (int i = 0; i < pages.size(); i++) {
StringTag page = pages.get(i);
String value = page.getValue();
value = ChatUtil.legacyToJson(value);
page.setValue(value);
}
}
packetWrapper.write(Type.ITEM1_8, book);
break;
}
case "MC|Brand": {
packetWrapper.write(Type.STRING, new String(packetWrapper.read(Type.REMAINING_BYTES), StandardCharsets.UTF_8));
break;
}
}
});
}
});
}
}
@@ -1,262 +0,0 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2016-2023 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.packets;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.Protocol1_7_6_10To1_8;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.storage.Scoreboard;
import com.viaversion.viarewind.utils.PacketUtil;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.protocol.remapper.PacketHandlers;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.protocols.protocol1_8.ClientboundPackets1_8;
import com.viaversion.viaversion.util.ChatColorUtil;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
public class ScoreboardPackets {
public static void register(Protocol1_7_6_10To1_8 protocol) {
/* OUTGOING */
//Scoreboard Objective
protocol.registerClientbound(ClientboundPackets1_8.SCOREBOARD_OBJECTIVE, new PacketHandlers() {
@Override
public void register() {
handler(packetWrapper -> {
String name = packetWrapper.passthrough(Type.STRING);
if (name.length() > 16) {
packetWrapper.set(Type.STRING, 0, name = name.substring(0, 16));
}
byte mode = packetWrapper.read(Type.BYTE);
Scoreboard scoreboard = packetWrapper.user().get(Scoreboard.class);
if (mode == 0) {
if (scoreboard.objectiveExists(name)) {
packetWrapper.cancel();
return;
}
scoreboard.addObjective(name);
} else if (mode == 1) {
if (!scoreboard.objectiveExists(name)) {
packetWrapper.cancel();
return;
}
if (scoreboard.getColorIndependentSidebar() != null) {
String username = packetWrapper.user().getProtocolInfo().getUsername();
Optional<Byte> color = scoreboard.getPlayerTeamColor(username);
if (color.isPresent()) {
String sidebar = scoreboard.getColorDependentSidebar().get(color.get());
if (name.equals(sidebar)) {
PacketWrapper sidebarPacket = PacketWrapper.create(0x3D, null, packetWrapper.user());
sidebarPacket.write(Type.BYTE, (byte) 1);
sidebarPacket.write(Type.STRING, scoreboard.getColorIndependentSidebar());
PacketUtil.sendPacket(sidebarPacket, Protocol1_7_6_10To1_8.class);
}
}
}
scoreboard.removeObjective(name);
} else if (mode == 2) {
if (!scoreboard.objectiveExists(name)) {
packetWrapper.cancel();
return;
}
}
if (mode == 0 || mode == 2) {
String displayName = packetWrapper.passthrough(Type.STRING);
if (displayName.length() > 32) {
packetWrapper.set(Type.STRING, 1, displayName.substring(0, 32));
}
packetWrapper.read(Type.STRING);
} else {
packetWrapper.write(Type.STRING, "");
}
packetWrapper.write(Type.BYTE, mode);
});
}
});
//Update Score
protocol.registerClientbound(ClientboundPackets1_8.UPDATE_SCORE, new PacketHandlers() {
@Override
public void register() {
map(Type.STRING); // Name
map(Type.VAR_INT, Type.BYTE); // Mode
handler(packetWrapper -> {
Scoreboard scoreboard = packetWrapper.user().get(Scoreboard.class);
String name = packetWrapper.get(Type.STRING, 0);
byte mode = packetWrapper.get(Type.BYTE, 0);
if (mode == 1) {
name = scoreboard.removeTeamForScore(name);
} else {
name = scoreboard.sendTeamForScore(name);
}
if (name.length() > 16) {
name = ChatColorUtil.stripColor(name);
if (name.length() > 16) {
name = name.substring(0, 16);
}
}
packetWrapper.set(Type.STRING, 0, name);
String objective = packetWrapper.read(Type.STRING);
if (objective.length() > 16) {
objective = objective.substring(0, 16);
}
if (mode != 1) {
int score = packetWrapper.read(Type.VAR_INT);
packetWrapper.write(Type.STRING, objective);
packetWrapper.write(Type.INT, score);
}
});
}
});
protocol.registerClientbound(ClientboundPackets1_8.DISPLAY_SCOREBOARD, new PacketHandlers() {
@Override
public void register() {
map(Type.BYTE); // Position
map(Type.STRING); // Score name
handler(packetWrapper -> {
byte position = packetWrapper.get(Type.BYTE, 0);
String name = packetWrapper.get(Type.STRING, 0);
Scoreboard scoreboard = packetWrapper.user().get(Scoreboard.class);
if (position > 2) { // team specific sidebar
byte receiverTeamColor = (byte) (position - 3);
scoreboard.getColorDependentSidebar().put(receiverTeamColor, name);
String username = packetWrapper.user().getProtocolInfo().getUsername();
Optional<Byte> color = scoreboard.getPlayerTeamColor(username);
if (color.isPresent() && color.get() == receiverTeamColor) {
position = 1;
} else {
position = -1;
}
} else if (position == 1) { // team independent sidebar
scoreboard.setColorIndependentSidebar(name);
String username = packetWrapper.user().getProtocolInfo().getUsername();
Optional<Byte> color = scoreboard.getPlayerTeamColor(username);
if (color.isPresent() && scoreboard.getColorDependentSidebar().containsKey(color.get())) {
position = -1;
}
}
if (position == -1) {
packetWrapper.cancel();
return;
}
packetWrapper.set(Type.BYTE, 0, position);
});
}
});
protocol.registerClientbound(ClientboundPackets1_8.TEAMS, new PacketHandlers() {
@Override
public void register() {
map(Type.STRING);
handler(packetWrapper -> {
String team = packetWrapper.get(Type.STRING, 0);
if (team == null) {
packetWrapper.cancel();
return;
}
byte mode = packetWrapper.passthrough(Type.BYTE);
Scoreboard scoreboard = packetWrapper.user().get(Scoreboard.class);
if (mode != 0 && !scoreboard.teamExists(team)) {
packetWrapper.cancel();
return;
} else if (mode == 0 && scoreboard.teamExists(team)) {
scoreboard.removeTeam(team);
PacketWrapper remove = PacketWrapper.create(0x3E, null, packetWrapper.user());
remove.write(Type.STRING, team);
remove.write(Type.BYTE, (byte) 1);
PacketUtil.sendPacket(remove, Protocol1_7_6_10To1_8.class, true, true);
}
if (mode == 0) {
scoreboard.addTeam(team);
} else if (mode == 1) {
scoreboard.removeTeam(team);
}
if (mode == 0 || mode == 2) {
packetWrapper.passthrough(Type.STRING); // Display name
packetWrapper.passthrough(Type.STRING); // prefix
packetWrapper.passthrough(Type.STRING); // suffix
packetWrapper.passthrough(Type.BYTE); // friendly fire
packetWrapper.read(Type.STRING); // name tag visibility
byte color = packetWrapper.read(Type.BYTE);
if (mode == 2 && scoreboard.getTeamColor(team).get() != color) {
String username = packetWrapper.user().getProtocolInfo().getUsername();
String sidebar = scoreboard.getColorDependentSidebar().get(color);
PacketWrapper sidebarPacket = packetWrapper.create(0x3D);
sidebarPacket.write(Type.BYTE, (byte) 1);
sidebarPacket.write(Type.STRING, sidebar == null ? "" : sidebar);
PacketUtil.sendPacket(sidebarPacket, Protocol1_7_6_10To1_8.class);
}
scoreboard.setTeamColor(team, color);
}
if (mode == 0 || mode == 3 || mode == 4) {
byte color = scoreboard.getTeamColor(team).get();
String[] entries = packetWrapper.read(Type.STRING_ARRAY);
List<String> entryList = new ArrayList<>();
for (int i = 0; i < entries.length; i++) {
String entry = entries[i];
String username = packetWrapper.user().getProtocolInfo().getUsername();
if (mode == 4) {
if (!scoreboard.isPlayerInTeam(entry, team)) continue;
scoreboard.removePlayerFromTeam(entry, team);
if (entry.equals(username)) {
PacketWrapper sidebarPacket = packetWrapper.create(0x3D);
sidebarPacket.write(Type.BYTE, (byte) 1);
sidebarPacket.write(Type.STRING, scoreboard.getColorIndependentSidebar() == null ? "" : scoreboard.getColorIndependentSidebar());
PacketUtil.sendPacket(sidebarPacket, Protocol1_7_6_10To1_8.class);
}
} else {
scoreboard.addPlayerToTeam(entry, team);
if (entry.equals(username) && scoreboard.getColorDependentSidebar().containsKey(color)) {
PacketWrapper displayObjective = packetWrapper.create(0x3D);
displayObjective.write(Type.BYTE, (byte) 1);
displayObjective.write(Type.STRING, scoreboard.getColorDependentSidebar().get(color));
PacketUtil.sendPacket(displayObjective, Protocol1_7_6_10To1_8.class);
}
}
entryList.add(entry);
}
packetWrapper.write(Type.SHORT, (short) entryList.size());
for (String entry : entryList) {
packetWrapper.write(Type.STRING, entry);
}
}
});
}
});
}
}
@@ -1,301 +0,0 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2016-2023 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.packets;
import com.viaversion.viarewind.protocol.protocol1_7_2_5to1_7_6_10.ClientboundPackets1_7_2_5;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.Protocol1_7_6_10To1_8;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.model.VirtualHologramEntity;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.storage.GameProfileStorage;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.storage.EntityTracker1_7_6_10;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.types.Types1_7_6_10;
import com.viaversion.viarewind.api.rewriter.item.Replacement;
import com.viaversion.viaversion.api.minecraft.Position;
import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_10;
import com.viaversion.viaversion.api.minecraft.metadata.Metadata;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.protocol.remapper.PacketHandlers;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.types.version.Types1_8;
import com.viaversion.viaversion.protocols.protocol1_8.ClientboundPackets1_8;
import java.util.List;
import java.util.UUID;
public class SpawnPackets {
public static void register(Protocol1_7_6_10To1_8 protocol) {
protocol.registerClientbound(ClientboundPackets1_8.SPAWN_PLAYER, new PacketHandlers() {
@Override
public void register() {
map(Type.VAR_INT); // entity id
handler(wrapper -> {
final UUID uuid = wrapper.read(Type.UUID);
wrapper.write(Type.STRING, uuid.toString()); // map to string
final GameProfileStorage gameProfileStorage = wrapper.user().get(GameProfileStorage.class);
GameProfileStorage.GameProfile gameProfile = gameProfileStorage.get(uuid);
if (gameProfile == null) {
wrapper.write(Type.STRING, ""); // name
wrapper.write(Type.VAR_INT, 0); // properties count
} else {
wrapper.write(Type.STRING, gameProfile.name.length() > 16 ? gameProfile.name.substring(0, 16) : gameProfile.name); // name
wrapper.write(Type.VAR_INT, gameProfile.properties.size()); // properties count
for (GameProfileStorage.Property property : gameProfile.properties) {
wrapper.write(Type.STRING, property.name); // property name
wrapper.write(Type.STRING, property.value); // property value
wrapper.write(Type.STRING, property.signature == null ? "" : property.signature); // property signature
}
}
final int entityId = wrapper.get(Type.VAR_INT, 0);
final EntityTracker1_7_6_10 tracker = wrapper.user().get(EntityTracker1_7_6_10.class);
if (gameProfile != null && gameProfile.gamemode == 3) { // Spectator mode
for (short i = 0; i < 5; i++) {
final PacketWrapper entityEquipment = PacketWrapper.create(ClientboundPackets1_7_2_5.ENTITY_EQUIPMENT, wrapper.user());
entityEquipment.write(Type.INT, entityId);
entityEquipment.write(Type.SHORT, i);
entityEquipment.write(Types1_7_6_10.COMPRESSED_NBT_ITEM, i == 4 ? gameProfile.getSkull() : null);
entityEquipment.scheduleSend(Protocol1_7_6_10To1_8.class, true);
}
}
tracker.addPlayer(entityId, uuid);
});
map(Type.INT); // x
map(Type.INT); // y
map(Type.INT); // z
map(Type.BYTE); // yaw
map(Type.BYTE); // pitch
map(Type.SHORT); // item in hand id
map(Types1_8.METADATA_LIST, Types1_7_6_10.METADATA_LIST); // metadata
handler(wrapper -> {
final List<Metadata> metadata = wrapper.get(Types1_7_6_10.METADATA_LIST, 0);
protocol.getMetadataRewriter().transform(EntityTypes1_10.EntityType.PLAYER, metadata);
wrapper.set(Types1_7_6_10.METADATA_LIST, 0, metadata);
});
handler(wrapper -> {
final EntityTracker1_7_6_10 tracker = wrapper.user().get(EntityTracker1_7_6_10.class);
tracker.addEntity(wrapper.get(Type.VAR_INT, 0), EntityTypes1_10.EntityType.PLAYER);
});
}
});
protocol.registerClientbound(ClientboundPackets1_8.SPAWN_ENTITY, new PacketHandlers() {
@Override
public void register() {
map(Type.VAR_INT); // entity id
map(Type.BYTE); // type id
map(Type.INT); // x
map(Type.INT); // y
map(Type.INT); // z
map(Type.BYTE); // pitch
map(Type.BYTE); // yaw
map(Type.INT); // data
handler(wrapper -> {
final EntityTracker1_7_6_10 tracker = wrapper.user().get(EntityTracker1_7_6_10.class);
final EntityTypes1_10.EntityType type = EntityTypes1_10.getTypeFromId(wrapper.get(Type.BYTE, 0), true);
final int entityId = wrapper.get(Type.VAR_INT, 0);
int x = wrapper.get(Type.INT, 0);
int y = wrapper.get(Type.INT, 1);
int z = wrapper.get(Type.INT, 2);
byte pitch = wrapper.get(Type.BYTE, 1);
byte yaw = wrapper.get(Type.BYTE, 2);
int data = wrapper.get(Type.INT, 3);
if (type == EntityTypes1_10.ObjectType.ITEM_FRAME.getType()) {
switch (yaw) {
case -128:
z += 32;
yaw = 0;
break;
case -64:
x -= 32;
yaw = -64;
break;
case 0:
z -= 32;
yaw = -128;
break;
case 64:
x += 32;
yaw = 64;
break;
}
} else if (type == EntityTypes1_10.ObjectType.ARMOR_STAND.getType()) {
wrapper.cancel();
final VirtualHologramEntity hologram = new VirtualHologramEntity(wrapper.user(), protocol.getMetadataRewriter(), entityId);
hologram.updateReplacementPosition(x / 32.0, y / 32.0, z / 32.0);
hologram.setYawPitch(yaw * 360f / 256, pitch * 360f / 256);
hologram.setHeadYaw(yaw * 360f / 256);
tracker.trackHologram(entityId, hologram);
}
// TODO | Realign all entities
wrapper.set(Type.INT, 0, x);
wrapper.set(Type.INT, 1, y);
wrapper.set(Type.INT, 2, z);
wrapper.set(Type.BYTE, 2, yaw);
tracker.addEntity(entityId, type);
if (type != null && type.isOrHasParent(EntityTypes1_10.EntityType.FALLING_BLOCK)) {
int blockId = data & 0xFFF;
int blockData = data >> 12 & 0xF;
final Replacement replace = protocol.getItemRewriter().replace(blockId, blockData);
if (replace != null) {
blockId = replace.getId();
blockData = replace.replaceData(blockData);
}
wrapper.set(Type.INT, 3, data = (blockId | blockData << 16));
}
if (data > 0) {
wrapper.passthrough(Type.SHORT); // velocity x
wrapper.passthrough(Type.SHORT); // velocity y
wrapper.passthrough(Type.SHORT); // velocity z
}
});
}
});
protocol.registerClientbound(ClientboundPackets1_8.SPAWN_MOB, new PacketHandlers() {
@Override
public void register() {
map(Type.VAR_INT); // entity id
map(Type.UNSIGNED_BYTE); // type id
map(Type.INT); // x
map(Type.INT); // y
map(Type.INT); // z
map(Type.BYTE); // yaw
map(Type.BYTE); // pitch
map(Type.BYTE); // head yaw
map(Type.SHORT); // velocity x
map(Type.SHORT); // velocity y
map(Type.SHORT); // velocity z
map(Types1_8.METADATA_LIST, Types1_7_6_10.METADATA_LIST); // metadata
handler(wrapper -> {
final EntityTracker1_7_6_10 tracker = wrapper.user().get(EntityTracker1_7_6_10.class);
final short typeId = wrapper.get(Type.UNSIGNED_BYTE, 0);
if (typeId == 255 || typeId == -1) {
wrapper.cancel();
}
final EntityTypes1_10.EntityType type = EntityTypes1_10.getTypeFromId(typeId, false);
final int entityId = wrapper.get(Type.VAR_INT, 0);
final int x = wrapper.get(Type.INT, 0);
final int y = wrapper.get(Type.INT, 1);
final int z = wrapper.get(Type.INT, 2);
final byte pitch = wrapper.get(Type.BYTE, 1);
final byte yaw = wrapper.get(Type.BYTE, 0);
final byte headYaw = wrapper.get(Type.BYTE, 2);
final List<Metadata> metadataList = wrapper.get(Types1_7_6_10.METADATA_LIST, 0);
if (type == EntityTypes1_10.EntityType.ARMOR_STAND) {
final VirtualHologramEntity hologram = new VirtualHologramEntity(wrapper.user(), protocol.getMetadataRewriter(), entityId);
hologram.updateReplacementPosition(x / 32.0, y / 32.0, z / 32.0);
hologram.setYawPitch(yaw * 360f / 256, pitch * 360f / 256);
hologram.setHeadYaw(headYaw * 360f / 256);
tracker.trackHologram(entityId, hologram);
tracker.updateMetadata(entityId, metadataList); // Track and remap hologram <-> zombie metadata
wrapper.cancel();
} else {
protocol.getMetadataRewriter().transform(type, metadataList);
tracker.addEntity(entityId, type);
if (tracker.isReplaced(type)) {
final int newTypeId = tracker.replaceEntity(entityId, type);
wrapper.set(Type.UNSIGNED_BYTE, 0, (short) newTypeId);
tracker.updateMetadata(entityId, metadataList);
}
}
});
}
});
protocol.registerClientbound(ClientboundPackets1_8.SPAWN_PAINTING, new PacketHandlers() {
@Override
public void register() {
map(Type.VAR_INT); // entity id
map(Type.STRING); // title
handler(wrapper -> {
final Position position = wrapper.read(Type.POSITION1_8);
wrapper.write(Type.INT, position.x());
wrapper.write(Type.INT, position.y());
wrapper.write(Type.INT, position.z());
});
map(Type.UNSIGNED_BYTE, Type.INT); // rotation
handler(wrapper -> {
final EntityTracker1_7_6_10 tracker = wrapper.user().get(EntityTracker1_7_6_10.class);
tracker.addEntity(wrapper.get(Type.VAR_INT, 0), EntityTypes1_10.EntityType.PAINTING);
});
}
});
protocol.registerClientbound(ClientboundPackets1_8.SPAWN_EXPERIENCE_ORB, new PacketHandlers() {
@Override
public void register() {
map(Type.VAR_INT); // entity id
map(Type.INT); // x
map(Type.INT); // y
map(Type.INT); // z
map(Type.SHORT); // count
handler(wrapper -> {
final EntityTracker1_7_6_10 tracker = wrapper.user().get(EntityTracker1_7_6_10.class);
tracker.addEntity(wrapper.get(Type.VAR_INT, 0), EntityTypes1_10.EntityType.EXPERIENCE_ORB);
});
}
});
protocol.registerClientbound(ClientboundPackets1_8.SPAWN_GLOBAL_ENTITY, new PacketHandlers() {
@Override
public void register() {
map(Type.VAR_INT); // entity id
map(Type.BYTE); // type id
map(Type.INT); // x
map(Type.INT); // y
map(Type.INT); // z
handler(wrapper -> {
final EntityTracker1_7_6_10 tracker = wrapper.user().get(EntityTracker1_7_6_10.class);
tracker.addEntity(wrapper.get(Type.VAR_INT, 0), EntityTypes1_10.EntityType.LIGHTNING);
});
}
});
}
}
@@ -1,304 +0,0 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2016-2023 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.packets;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.Protocol1_7_6_10To1_8;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.storage.WorldBorderEmulator;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.types.chunk.ChunkType1_7_6;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.types.chunk.BulkChunkType1_7_6;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.model.ParticleIndex1_7_6_10;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.types.Types1_7_6_10;
import com.viaversion.viarewind.utils.ChatUtil;
import com.viaversion.viaversion.api.minecraft.BlockChangeRecord;
import com.viaversion.viaversion.api.minecraft.chunks.Chunk;
import com.viaversion.viaversion.api.minecraft.chunks.ChunkSection;
import com.viaversion.viaversion.api.minecraft.chunks.DataPalette;
import com.viaversion.viaversion.api.minecraft.chunks.PaletteType;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.protocol.remapper.PacketHandlers;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.types.FixedByteArrayType;
import com.viaversion.viaversion.api.type.types.chunk.BulkChunkType1_8;
import com.viaversion.viaversion.api.type.types.chunk.ChunkType1_8;
import com.viaversion.viaversion.protocols.protocol1_8.ClientboundPackets1_8;
import com.viaversion.viaversion.api.minecraft.ClientWorld;
import com.viaversion.viaversion.util.ChatColorUtil;
public class WorldPackets {
private static void rewriteBlockIds(final Protocol1_7_6_10To1_8 protocol, final Chunk chunk) {
for (ChunkSection section : chunk.getSections()) {
if (section == null) continue;
final DataPalette palette = section.palette(PaletteType.BLOCKS);
for (int i = 0; i < palette.size(); i++) {
palette.setIdByIndex(i, protocol.getItemRewriter().replace(palette.idByIndex(i)));
}
}
}
public static void register(Protocol1_7_6_10To1_8 protocol) {
protocol.registerClientbound(ClientboundPackets1_8.CHUNK_DATA, wrapper -> {
final ClientWorld world = wrapper.user().get(ClientWorld.class);
final Chunk chunk = wrapper.read(ChunkType1_8.forEnvironment(world.getEnvironment()));
rewriteBlockIds(protocol, chunk);
wrapper.write(ChunkType1_7_6.TYPE, chunk);
});
protocol.registerClientbound(ClientboundPackets1_8.MULTI_BLOCK_CHANGE, new PacketHandlers() {
@Override
public void register() {
map(Type.INT); // chunk x
map(Type.INT); // chunk z
handler(wrapper -> {
final BlockChangeRecord[] records = wrapper.read(Type.BLOCK_CHANGE_RECORD_ARRAY);
wrapper.write(Type.SHORT, (short) records.length); // record count
wrapper.write(Type.INT, records.length * 4); // data array length (position + block id)
for (BlockChangeRecord record : records) {
wrapper.write(Type.SHORT, (short) (record.getSectionX() << 12 | record.getSectionZ() << 8 | record.getY())); // position
wrapper.write(Type.SHORT, (short) protocol.getItemRewriter().replace(record.getBlockId())); // block id
}
});
}
});
protocol.registerClientbound(ClientboundPackets1_8.BLOCK_CHANGE, new PacketHandlers() {
@Override
protected void register() {
map(Type.POSITION1_8, Types1_7_6_10.U_BYTE_POSITION); // position
handler(wrapper -> {
int data = wrapper.read(Type.VAR_INT); // block data
data = protocol.getItemRewriter().replace(data);
wrapper.write(Type.VAR_INT, data >> 4); // block id
wrapper.write(Type.UNSIGNED_BYTE, (short) (data & 0xF)); // block data
});
}
});
protocol.registerClientbound(ClientboundPackets1_8.BLOCK_ACTION, new PacketHandlers() {
@Override
public void register() {
map(Type.POSITION1_8, Types1_7_6_10.SHORT_POSITION); // position
map(Type.UNSIGNED_BYTE); // type
map(Type.UNSIGNED_BYTE); // data
map(Type.VAR_INT); // block id
}
});
protocol.registerClientbound(ClientboundPackets1_8.BLOCK_BREAK_ANIMATION, new PacketHandlers() {
@Override
public void register() {
map(Type.VAR_INT); // entity id
map(Type.POSITION1_8, Types1_7_6_10.INT_POSITION); // position
map(Type.BYTE); // progress
}
});
protocol.registerClientbound(ClientboundPackets1_8.MAP_BULK_CHUNK, wrapper -> {
final Chunk[] chunks = wrapper.read(BulkChunkType1_8.TYPE);
for (Chunk chunk : chunks) {
rewriteBlockIds(protocol, chunk);
}
wrapper.write(BulkChunkType1_7_6.TYPE, chunks);
});
protocol.registerClientbound(ClientboundPackets1_8.EFFECT, new PacketHandlers() {
@Override
public void register() {
map(Type.INT); // effect id
map(Type.POSITION1_8, Types1_7_6_10.BYTE_POSITION); // position
map(Type.INT); // data
map(Type.BOOLEAN); // disable relative volume
}
});
protocol.registerClientbound(ClientboundPackets1_8.SPAWN_PARTICLE, new PacketHandlers() {
@Override
public void register() {
handler(wrapper -> {
final int particleId = wrapper.read(Type.INT); // particle id
ParticleIndex1_7_6_10 particle = ParticleIndex1_7_6_10.find(particleId);
if (particle == null) particle = ParticleIndex1_7_6_10.CRIT;
wrapper.write(Type.STRING, particle.name); // particle name
});
read(Type.BOOLEAN); // long distance
map(Type.FLOAT); // x
map(Type.FLOAT); // y
map(Type.FLOAT); // z
map(Type.FLOAT); // offset x
map(Type.FLOAT); // offset y
map(Type.FLOAT); // offset z
map(Type.FLOAT); // particle data
map(Type.INT); // particle count
handler(wrapper -> {
String name = wrapper.get(Type.STRING, 0);
ParticleIndex1_7_6_10 particle = ParticleIndex1_7_6_10.find(name);
if (particle == ParticleIndex1_7_6_10.ICON_CRACK || particle == ParticleIndex1_7_6_10.BLOCK_CRACK || particle == ParticleIndex1_7_6_10.BLOCK_DUST) {
int id = wrapper.read(Type.VAR_INT);
int data = particle == ParticleIndex1_7_6_10.ICON_CRACK ? wrapper.read(Type.VAR_INT) : id / 4096;
id %= 4096;
if (id >= 256 && id <= 422 || id >= 2256 && id <= 2267) { //item
particle = ParticleIndex1_7_6_10.ICON_CRACK;
} else if (id >= 0 && id <= 164 || id >= 170 && id <= 175) {
if (particle == ParticleIndex1_7_6_10.ICON_CRACK) particle = ParticleIndex1_7_6_10.BLOCK_CRACK;
} else {
wrapper.cancel();
return;
}
name = particle.name + "_" + id + "_" + data;
}
wrapper.set(Type.STRING, 0, name);
});
}
});
protocol.registerClientbound(ClientboundPackets1_8.UPDATE_SIGN, new PacketHandlers() {
@Override
public void register() {
map(Type.POSITION1_8, Types1_7_6_10.SHORT_POSITION); // position
handler(wrapper -> {
for (int i = 0; i < 4; i++) {
String line = wrapper.read(Type.STRING);
line = ChatUtil.jsonToLegacy(line);
line = ChatUtil.removeUnusedColor(line, '0');
if (line.length() > 15) {
line = ChatColorUtil.stripColor(line);
if (line.length() > 15) line = line.substring(0, 15);
}
wrapper.write(Type.STRING, line);
}
});
}
});
protocol.registerClientbound(ClientboundPackets1_8.MAP_DATA, new PacketHandlers() {
@Override
public void register() {
handler(wrapper -> {
wrapper.cancel();
final int id = wrapper.read(Type.VAR_INT);
final byte scale = wrapper.read(Type.BYTE);
final int iconCount = wrapper.read(Type.VAR_INT);
byte[] icons = new byte[iconCount * 4];
for (int i = 0; i < iconCount; i++) {
final int directionAndType = wrapper.read(Type.BYTE);
icons[i * 4] = (byte) (directionAndType >> 4 & 0xF);
icons[i * 4 + 1] = wrapper.read(Type.BYTE); // x
icons[i * 4 + 2] = wrapper.read(Type.BYTE); // z
icons[i * 4 + 3] = (byte) (directionAndType & 0xF);
}
final short columns = wrapper.read(Type.UNSIGNED_BYTE);
if (columns > 0) {
final short rows = wrapper.read(Type.UNSIGNED_BYTE);
final short x = wrapper.read(Type.UNSIGNED_BYTE);
final short z = wrapper.read(Type.UNSIGNED_BYTE);
final byte[] data = wrapper.read(Type.BYTE_ARRAY_PRIMITIVE);
for (int column = 0; column < columns; column++) {
byte[] columnData = new byte[rows + 3];
columnData[0] = 0;
columnData[1] = (byte) (x + column);
columnData[2] = (byte) z;
for (int i = 0; i < rows; i++) {
columnData[i + 3] = data[column + i * columns];
}
final PacketWrapper mapData = PacketWrapper.create(ClientboundPackets1_8.MAP_DATA, wrapper.user());
mapData.write(Type.VAR_INT, id); // map id
mapData.write(Type.SHORT, (short) columnData.length); // data length
mapData.write(new FixedByteArrayType(columnData.length), columnData); // data
mapData.send(Protocol1_7_6_10To1_8.class, true);
}
}
if (iconCount > 0) {
final byte[] iconData = new byte[iconCount * 3 + 1];
iconData[0] = 1;
for (int i = 0; i < iconCount; i++) {
iconData[i * 3 + 1] = (byte) (icons[i * 4] << 4 | icons[i * 4 + 3] & 0xF);
iconData[i * 3 + 2] = icons[i * 4 + 1];
iconData[i * 3 + 3] = icons[i * 4 + 2];
}
final PacketWrapper mapData = PacketWrapper.create(ClientboundPackets1_8.MAP_DATA, wrapper.user());
mapData.write(Type.VAR_INT, id); // map id
mapData.write(Type.SHORT, (short) iconData.length); // data length
mapData.write(new FixedByteArrayType(iconData.length), iconData); // data
mapData.send(Protocol1_7_6_10To1_8.class, true);
}
// Update scale
final PacketWrapper mapData = PacketWrapper.create(ClientboundPackets1_8.MAP_DATA, wrapper.user());
mapData.write(Type.VAR_INT, id); // map id
mapData.write(Type.SHORT, (short) 2); // data length
mapData.write(new FixedByteArrayType(2), new byte[]{ 2, scale }); // data
mapData.send(Protocol1_7_6_10To1_8.class, true);
});
}
});
protocol.registerClientbound(ClientboundPackets1_8.BLOCK_ENTITY_DATA, new PacketHandlers() {
@Override
public void register() {
map(Type.POSITION1_8, Types1_7_6_10.SHORT_POSITION); // position
map(Type.UNSIGNED_BYTE); // action
map(Type.NAMED_COMPOUND_TAG, Types1_7_6_10.COMPRESSED_NBT); // nbt
}
});
protocol.cancelClientbound(ClientboundPackets1_8.SERVER_DIFFICULTY);
protocol.cancelClientbound(ClientboundPackets1_8.COMBAT_EVENT);
protocol.registerClientbound(ClientboundPackets1_8.WORLD_BORDER, null, wrapper -> {
final WorldBorderEmulator emulator = wrapper.user().get(WorldBorderEmulator.class);
wrapper.cancel();
final int action = wrapper.read(Type.VAR_INT);
if (action == 0) { // set size
emulator.setSize(wrapper.read(Type.DOUBLE)); // radius
} else if (action == 1) { // lerp size
emulator.lerpSize(wrapper.read(Type.DOUBLE), wrapper.read(Type.DOUBLE), wrapper.read(Type.VAR_LONG)); // old radius, new radius, speed
} else if (action == 2) { // set center
emulator.setCenter(wrapper.read(Type.DOUBLE), wrapper.read(Type.DOUBLE)); // x, z
} else if (action == 3) { // initialize
emulator.init(
wrapper.read(Type.DOUBLE), wrapper.read(Type.DOUBLE), // x, z
wrapper.read(Type.DOUBLE), wrapper.read(Type.DOUBLE), // old radius, new radius
wrapper.read(Type.VAR_LONG) // speed
);
}
});
}
}
@@ -1,99 +0,0 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2016-2023 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.provider;
import com.viaversion.viaversion.api.platform.providers.Provider;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.atomic.AtomicInteger;
public abstract class TitleRenderProvider implements Provider {
protected Map<UUID, Integer> fadeIn = new HashMap<>();
protected Map<UUID, Integer> stay = new HashMap<>();
protected Map<UUID, Integer> fadeOut = new HashMap<>();
protected Map<UUID, String> titles = new HashMap<>();
protected Map<UUID, String> subTitles = new HashMap<>();
protected Map<UUID, AtomicInteger> times = new HashMap<>();
public void setTimings(UUID uuid, int fadeIn, int stay, int fadeOut) {
setFadeIn(uuid, fadeIn);
setStay(uuid, stay);
setFadeOut(uuid, fadeOut);
AtomicInteger time = getTime(uuid);
if (time.get() > 0) time.set(getFadeIn(uuid) + getStay(uuid) + getFadeOut(uuid));
}
public void reset(UUID uuid) {
this.titles.remove(uuid);
this.subTitles.remove(uuid);
getTime(uuid).set(0);
fadeIn.remove(uuid);
stay.remove(uuid);
fadeOut.remove(uuid);
}
public void setTitle(UUID uuid, String title) {
this.titles.put(uuid, title);
getTime(uuid).set(getFadeIn(uuid) + getStay(uuid) + getFadeOut(uuid));
}
public void setSubTitle(UUID uuid, String subTitle) {
this.subTitles.put(uuid, subTitle);
}
public void clear(UUID uuid) {
this.titles.remove(uuid);
this.subTitles.remove(uuid);
getTime(uuid).set(0);
}
public AtomicInteger getTime(UUID uuid) {
return times.computeIfAbsent(uuid, key -> new AtomicInteger(0));
}
public int getFadeIn(UUID uuid) {
return fadeIn.getOrDefault(uuid, 10);
}
public int getStay(UUID uuid) {
return stay.getOrDefault(uuid, 70);
}
public int getFadeOut(UUID uuid) {
return fadeOut.getOrDefault(uuid, 20);
}
public void setFadeIn(UUID uuid, int fadeIn) {
if (fadeIn >= 0) this.fadeIn.put(uuid, fadeIn);
else this.fadeIn.remove(uuid);
}
public void setStay(UUID uuid, int stay) {
if (stay >= 0) this.stay.put(uuid, stay);
else this.stay.remove(uuid);
}
public void setFadeOut(UUID uuid, int fadeOut) {
if (fadeOut >= 0) this.fadeOut.put(uuid, fadeOut);
else this.fadeOut.remove(uuid);
}
}
@@ -1,56 +0,0 @@
package com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.provider.compression;
import com.viaversion.viaversion.api.type.Type;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufAllocator;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.DecoderException;
import io.netty.handler.codec.MessageToMessageDecoder;
import java.util.List;
import java.util.zip.Inflater;
// https://github.com/Gerrygames/ClientViaVersion/blob/master/src/main/java/de/gerrygames/the5zig/clientviaversion/netty/CompressionDecoder.java
public class CompressionDecoder extends MessageToMessageDecoder<ByteBuf> {
private final Inflater inflater = new Inflater();
private final int threshold;
public CompressionDecoder(final int threshold) {
this.threshold = threshold;
}
@Override
protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
if (!in.isReadable()) return;
int outLength = Type.VAR_INT.readPrimitive(in);
if (outLength == 0) {
out.add(in.readBytes(in.readableBytes()));
return;
}
if (outLength < this.threshold) {
throw new DecoderException("Badly compressed packet - size of " + outLength + " is below server threshold of " + this.threshold);
} else if (outLength > 2097152) {
throw new DecoderException("Badly compressed packet - size of " + outLength + " is larger than protocol maximum of " + 2097152);
}
ByteBuf temp = in;
if (!in.hasArray()) {
temp = ByteBufAllocator.DEFAULT.heapBuffer().writeBytes(in);
} else {
in.retain();
}
ByteBuf output = ByteBufAllocator.DEFAULT.heapBuffer(outLength, outLength);
try {
this.inflater.setInput(temp.array(), temp.arrayOffset() + temp.readerIndex(), temp.readableBytes());
output.writerIndex(output.writerIndex() + this.inflater.inflate(output.array(), output.arrayOffset(), outLength));
out.add(output.retain());
} finally {
output.release();
temp.release();
this.inflater.reset();
}
}
}
@@ -1,54 +0,0 @@
package com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.provider.compression;
import com.viaversion.viaversion.api.type.Type;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufAllocator;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToByteEncoder;
import java.util.zip.Deflater;
// https://github.com/Gerrygames/ClientViaVersion/blob/master/src/main/java/de/gerrygames/the5zig/clientviaversion/netty/CompressionEncoder.java
public class CompressionEncoder extends MessageToByteEncoder<ByteBuf> {
private final Deflater deflater = new Deflater();
private final int threshold;
public CompressionEncoder(final int threshold) {
this.threshold = threshold;
}
@Override
protected void encode(ChannelHandlerContext ctx, ByteBuf in, ByteBuf out) throws Exception {
int frameLength = in.readableBytes();
if (frameLength < this.threshold) {
out.writeByte(0); // VarInt
out.writeBytes(in);
return;
}
Type.VAR_INT.writePrimitive(out, frameLength);
ByteBuf temp = in;
if (!in.hasArray()) {
temp = ByteBufAllocator.DEFAULT.heapBuffer().writeBytes(in);
} else {
in.retain();
}
ByteBuf output = ByteBufAllocator.DEFAULT.heapBuffer();
try {
this.deflater.setInput(temp.array(), temp.arrayOffset() + temp.readerIndex(), temp.readableBytes());
deflater.finish();
while (!deflater.finished()) {
output.ensureWritable(4096);
output.writerIndex(output.writerIndex() + this.deflater.deflate(output.array(), output.arrayOffset() + output.writerIndex(), output.writableBytes()));
}
out.writeBytes(output);
} finally {
output.release();
temp.release();
this.deflater.reset();
}
}
}
@@ -1,61 +0,0 @@
package com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.provider.compression;
import com.viaversion.viarewind.api.netty.EmptyChannelHandler;
import com.viaversion.viarewind.api.netty.ForwardMessageToByteEncoder;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.provider.CompressionHandlerProvider;
import com.viaversion.viaversion.api.Via;
import com.viaversion.viaversion.api.connection.UserConnection;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelPipeline;
public class TrackingCompressionHandlerProvider extends CompressionHandlerProvider {
public final static String COMPRESS_HANDLER_NAME = "compress";
public final static String DECOMPRESS_HANDLER_NAME = "decompress";
@Override
public void onHandleLoginCompressionPacket(UserConnection user, int threshold) {
final ChannelPipeline pipeline = user.getChannel().pipeline();
if (user.isClientSide()) {
pipeline.addBefore(Via.getManager().getInjector().getEncoderName(), COMPRESS_HANDLER_NAME, getEncoder(threshold));
pipeline.addBefore(Via.getManager().getInjector().getDecoderName(), DECOMPRESS_HANDLER_NAME, getDecoder(threshold));
} else {
setCompressionEnabled(user, true); // We need to remove compression for 1.7 clients
}
}
@Override
public void onTransformPacket(UserConnection user) {
if (isCompressionEnabled(user)) {
final ChannelPipeline pipeline = user.getChannel().pipeline();
String compressor = null;
String decompressor = null;
if (pipeline.get(COMPRESS_HANDLER_NAME) != null) { // ViaVersion
compressor = COMPRESS_HANDLER_NAME;
decompressor = DECOMPRESS_HANDLER_NAME;
} else if (pipeline.get("compression-encoder") != null) { // Velocity
compressor = "compression-encoder";
decompressor = "compression-decoder";
}
if (compressor != null) { // We can neutralize the effect of compressor to the client
pipeline.replace(decompressor, decompressor, new EmptyChannelHandler());
pipeline.replace(compressor, compressor, new ForwardMessageToByteEncoder());
} else {
throw new IllegalStateException("Couldn't remove compression for 1.7!");
}
setCompressionEnabled(user, false);
}
}
@Override
public ChannelHandler getEncoder(int threshold) {
return new CompressionEncoder(threshold);
}
@Override
public ChannelHandler getDecoder(int threshold) {
return new CompressionDecoder(threshold);
}
}
@@ -1,115 +0,0 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2016-2023 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.rewriter;
import com.viaversion.viarewind.ViaRewind;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.Protocol1_7_6_10To1_8;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.model.MetaIndex1_7_6_10To1_8;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.types.metadata.MetaType1_7_6_10;
import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_10;
import com.viaversion.viaversion.api.minecraft.item.Item;
import com.viaversion.viaversion.api.minecraft.metadata.Metadata;
import com.viaversion.viaversion.api.minecraft.metadata.types.MetaType1_8;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
@SuppressWarnings({"deprecation"})
public class MetadataRewriter {
private final Protocol1_7_6_10To1_8 protocol;
public MetadataRewriter(Protocol1_7_6_10To1_8 protocol) {
this.protocol = protocol;
}
public void transform(EntityTypes1_10.EntityType type, List<Metadata> list) {
for (Metadata entry : new ArrayList<>(list)) {
final MetaIndex1_7_6_10To1_8 metaIndex = MetaIndex1_7_6_10To1_8.searchIndex(type, entry.id());
try {
if (metaIndex == null) {
ViaRewind.getPlatform().getLogger().warning("Could not find 1.8 metadata for " + type + " with index " + entry.id());
list.remove(entry);
continue;
}
if (metaIndex.getOldType() == MetaType1_7_6_10.NonExistent) {
list.remove(entry);
continue;
}
final Object value = entry.getValue();
entry.setTypeAndValue(metaIndex.getNewType(), value);
entry.setMetaTypeUnsafe(metaIndex.getOldType());
entry.setId(metaIndex.getIndex());
switch (metaIndex.getOldType()) {
case Int:
if (metaIndex.getNewType() == MetaType1_8.Byte) {
entry.setValue(((Byte) value).intValue());
if (metaIndex == MetaIndex1_7_6_10To1_8.ENTITY_AGEABLE_AGE) {
if ((Integer) entry.getValue() < 0) {
entry.setValue(-25000);
}
}
}
if (metaIndex.getNewType() == MetaType1_8.Short) {
entry.setValue(((Short) value).intValue());
}
if (metaIndex.getNewType() == MetaType1_8.Int) {
entry.setValue(value);
}
break;
case Byte:
if (metaIndex.getNewType() == MetaType1_8.Int) {
entry.setValue(((Integer) value).byteValue());
}
if (metaIndex.getNewType() == MetaType1_8.Byte) {
if (metaIndex == MetaIndex1_7_6_10To1_8.ITEM_FRAME_ROTATION) {
entry.setValue(Integer.valueOf((Byte) value % 4).byteValue());
} else {
entry.setValue(value);
}
}
if (metaIndex == MetaIndex1_7_6_10To1_8.HUMAN_SKIN_FLAGS) {
byte flags = (byte) value;
boolean cape = (flags & 0x01) != 0;
flags = (byte) (cape ? 0x00 : 0x02);
entry.setValue(flags);
}
break;
case Slot:
entry.setValue(protocol.getItemRewriter().handleItemToClient((Item) value));
break;
case Float:
case String:
case Short:
case Position:
break;
default:
ViaRewind.getPlatform().getLogger().warning("Could not transform metadata for " + type + " with index " + entry.id() + " and type " + metaIndex.getOldType());
list.remove(entry);
break;
}
} catch (Exception e) {
ViaRewind.getPlatform().getLogger().log(Level.WARNING, "Unable to transform metadata", e);
list.remove(entry);
}
}
}
}
@@ -1,230 +0,0 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2016-2023 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.rewriter;
import com.viaversion.viarewind.api.rewriter.item.ReplacementItemRewriter;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.Protocol1_7_6_10To1_8;
import com.viaversion.viarewind.api.rewriter.item.Replacement;
import com.viaversion.viarewind.utils.ChatUtil;
import com.viaversion.viarewind.utils.Enchantments;
import com.viaversion.viaversion.api.minecraft.item.Item;
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
import com.viaversion.viaversion.libs.opennbt.tag.builtin.*;
import java.util.ArrayList;
import java.util.List;
public class ReplacementItemRewriter1_7_6_10 extends ReplacementItemRewriter<Protocol1_7_6_10To1_8> {
private final static String VIA_REWIND_TAG_KEY = "ViaRewind1_7_6_10to1_8";
public ReplacementItemRewriter1_7_6_10(Protocol1_7_6_10To1_8 protocol) {
super(protocol, ProtocolVersion.v1_8);
}
@Override
public void register() {
registerBlock(176, new Replacement(63));
registerBlock(177, new Replacement(68));
registerBlock(193, new Replacement(64));
registerBlock(194, new Replacement(64));
registerBlock(195, new Replacement(64));
registerBlock(196, new Replacement(64));
registerBlock(197, new Replacement(64));
registerBlock(77, 5, new Replacement(69, 6));
registerBlock(77, 13, new Replacement(69, 14));
registerBlock(77, 0, new Replacement(69, 0));
registerBlock(77, 8, new Replacement(69, 8));
registerBlock(143, 5, new Replacement(69, 6));
registerBlock(143, 13, new Replacement(69, 14));
registerBlock(143, 0, new Replacement(69, 0));
registerBlock(143, 8, new Replacement(69, 8));
registerBlock(178, new Replacement(151));
registerBlock(182, 0, new Replacement(44, 1));
registerBlock(182, 8, new Replacement(44, 9));
registerItem(425, new Replacement(323, "Banner"));
registerItem(409, new Replacement(406, "Prismarine Shard"));
registerItem(410, new Replacement(406, "Prismarine Crystal"));
registerItem(416, new Replacement(280, "Armor Stand"));
registerItem(423, new Replacement(363, "Raw Mutton"));
registerItem(424, new Replacement(364, "Cooked Mutton"));
registerItem(411, new Replacement(365, "Raw Rabbit"));
registerItem(412, new Replacement(366, "Cooked Rabbit"));
registerItem(413, new Replacement(282, "Rabbit Stew"));
registerItem(414, new Replacement(375, "Rabbit's Foot"));
registerItem(415, new Replacement(334, "Rabbit Hide"));
registerItem(373, 8203, new Replacement(373, 0, "Potion of Leaping"));
registerItem(373, 8235, new Replacement(373, 0, "Potion of Leaping"));
registerItem(373, 8267, new Replacement(373, 0, "Potion of Leaping"));
registerItem(373, 16395, new Replacement(373, 0, "Splash Potion of Leaping"));
registerItem(373, 16427, new Replacement(373, 0, "Splash Potion of Leaping"));
registerItem(373, 16459, new Replacement(373, 0, "Splash Potion of Leaping"));
registerItem(383, 30, new Replacement(383, "Spawn ArmorStand"));
registerItem(383, 67, new Replacement(383, "Spawn Endermite"));
registerItem(383, 68, new Replacement(383, "Spawn Guardian"));
registerItem(383, 101, new Replacement(383, "Spawn Rabbit"));
registerItem(19, 1, new Replacement(19, 0, "Wet Sponge"));
registerItem(182, new Replacement(44, 1, "Red Sandstone Slab"));
registerItemBlock(166, new Replacement(20, "Barrier"));
registerItemBlock(167, new Replacement(96, "Iron Trapdoor"));
registerItemBlock(1, 1, new Replacement(1, 0, "Granite"));
registerItemBlock(1, 2, new Replacement(1, 0, "Polished Granite"));
registerItemBlock(1, 3, new Replacement(1, 0, "Diorite"));
registerItemBlock(1, 4, new Replacement(1, 0, "Polished Diorite"));
registerItemBlock(1, 5, new Replacement(1, 0, "Andesite"));
registerItemBlock(1, 6, new Replacement(1, 0, "Polished Andesite"));
registerItemBlock(168, 0, new Replacement(1, 0, "Prismarine"));
registerItemBlock(168, 1, new Replacement(98, 0, "Prismarine Bricks"));
registerItemBlock(168, 2, new Replacement(98, 1, "Dark Prismarine"));
registerItemBlock(169, new Replacement(89, "Sea Lantern"));
registerItemBlock(165, new Replacement(95, 5, "Slime Block"));
registerItemBlock(179, 0, new Replacement(24, "Red Sandstone"));
registerItemBlock(179, 1, new Replacement(24, "Chiseled Red Sandstone"));
registerItemBlock(179, 2, new Replacement(24, "Smooth Sandstone"));
registerItemBlock(181, new Replacement(43, 1, "Double Red Sandstone Slab"));
registerItemBlock(180, new Replacement(128, "Red Sandstone Stairs"));
registerItemBlock(188, new Replacement(85, "Spruce Fence"));
registerItemBlock(189, new Replacement(85, "Birch Fence"));
registerItemBlock(190, new Replacement(85, "Jungle Fence"));
registerItemBlock(191, new Replacement(85, "Dark Oak Fence"));
registerItemBlock(192, new Replacement(85, "Acacia Fence"));
registerItemBlock(183, new Replacement(107, "Spruce Fence Gate"));
registerItemBlock(184, new Replacement(107, "Birch Fence Gate"));
registerItemBlock(185, new Replacement(107, "Jungle Fence Gate"));
registerItemBlock(186, new Replacement(107, "Dark Oak Fence Gate"));
registerItemBlock(187, new Replacement(107, "Acacia Fence Gate"));
registerItemBlock(427, new Replacement(324, "Spruce Door"));
registerItemBlock(428, new Replacement(324, "Birch Door"));
registerItemBlock(429, new Replacement(324, "Jungle Door"));
registerItemBlock(430, new Replacement(324, "Dark Oak Door"));
registerItemBlock(431, new Replacement(324, "Acacia Door"));
registerItemBlock(157, new Replacement(28, "Activator Rail"));
}
@Override
public Item handleItemToClient(Item item) {
if (item == null) return null;
CompoundTag tag = item.tag();
if (tag == null) {
item.setTag(tag = new CompoundTag());
}
CompoundTag viaRewindTag = new CompoundTag();
tag.put(VIA_REWIND_TAG_KEY, viaRewindTag);
viaRewindTag.put("id", new ShortTag((short) item.identifier()));
viaRewindTag.put("data", new ShortTag(item.data()));
CompoundTag display = tag.get("display");
if (display != null && display.contains("Name")) {
viaRewindTag.put("displayName", new StringTag((String) display.get("Name").getValue()));
}
if (display != null && display.contains("Lore")) {
viaRewindTag.put("lore", new ListTag(((ListTag) display.get("Lore")).getValue()));
}
if (tag.contains("ench") || tag.contains("StoredEnchantments")) {
ListTag enchTag = tag.contains("ench") ? tag.get("ench") : tag.get("StoredEnchantments");
List<Tag> lore = new ArrayList<>();
for (Tag ench : new ArrayList<>(enchTag.getValue())) {
short id = ((NumberTag) ((CompoundTag) ench).get("id")).asShort();
short lvl = ((NumberTag) ((CompoundTag) ench).get("lvl")).asShort();
String s;
if (id == 8) {
s = "§r§7Depth Strider ";
} else {
continue;
}
enchTag.remove(ench);
s += Enchantments.ENCHANTMENTS.getOrDefault(lvl, "enchantment.level." + lvl);
lore.add(new StringTag(s));
}
if (!lore.isEmpty()) {
if (display == null) {
tag.put("display", display = new CompoundTag());
viaRewindTag.put("noDisplay", new ByteTag());
}
ListTag loreTag = display.get("Lore");
if (loreTag == null) display.put("Lore", loreTag = new ListTag(StringTag.class));
lore.addAll(loreTag.getValue());
loreTag.setValue(lore);
}
}
if (item.identifier() == 387 && tag.contains("pages")) {
ListTag pages = tag.get("pages");
ListTag oldPages = new ListTag(StringTag.class);
viaRewindTag.put("pages", oldPages);
for (int i = 0; i < pages.size(); i++) {
StringTag page = pages.get(i);
String value = page.getValue();
oldPages.add(new StringTag(value));
value = ChatUtil.jsonToLegacy(value);
page.setValue(value);
}
}
replace(item);
if (viaRewindTag.size() == 2 && (short) viaRewindTag.get("id").getValue() == item.identifier() && (short) viaRewindTag.get("data").getValue() == item.data()) {
item.tag().remove(VIA_REWIND_TAG_KEY);
if (item.tag().isEmpty()) item.setTag(null);
}
return item;
}
@Override
public Item handleItemToServer(Item item) {
if (item == null) return null;
CompoundTag tag = item.tag();
if (tag == null || !item.tag().contains(VIA_REWIND_TAG_KEY)) return item;
CompoundTag viaVersionTag = tag.remove(VIA_REWIND_TAG_KEY);
item.setIdentifier((short) viaVersionTag.get("id").getValue());
item.setData((Short) viaVersionTag.get("data").getValue());
if (viaVersionTag.contains("noDisplay")) tag.remove("display");
if (viaVersionTag.contains("displayName")) {
CompoundTag display = tag.get("display");
if (display == null) tag.put("display", display = new CompoundTag());
StringTag name = display.get("Name");
if (name == null) display.put("Name", new StringTag((String) viaVersionTag.get("displayName").getValue()));
else name.setValue((String) viaVersionTag.get("displayName").getValue());
} else if (tag.contains("display")) {
((CompoundTag) tag.get("display")).remove("Name");
}
if (item.identifier() == 387) {
ListTag oldPages = viaVersionTag.get("pages");
tag.remove("pages");
tag.put("pages", oldPages);
}
return item;
}
}
@@ -1,174 +0,0 @@
package com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.storage;
import com.viaversion.viarewind.ViaRewind;
import com.viaversion.viarewind.api.rewriter.ReplacementEntityTracker;
import com.viaversion.viarewind.protocol.protocol1_7_2_5to1_7_6_10.ServerboundPackets1_7_2_5;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.Protocol1_7_6_10To1_8;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.model.VirtualHologramEntity;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.rewriter.MetadataRewriter;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_10;
import com.viaversion.viaversion.api.minecraft.metadata.Metadata;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.protocols.protocol1_8.ClientboundPackets1_8;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.logging.Level;
public class EntityTracker1_7_6_10 extends ReplacementEntityTracker {
protected final MetadataRewriter metadataRewriter;
private final Map<Integer, Integer> vehicleMap = new ConcurrentHashMap<>();
private final Map<Integer, VirtualHologramEntity> virtualHologramMap = new HashMap<>();
private final Map<Integer, UUID> playersByEntityId = new HashMap<>();
private final Map<UUID, Integer> playersByUniqueId = new HashMap<>();
public int spectatingPlayerId = -1;
public EntityTracker1_7_6_10(UserConnection user, final MetadataRewriter metadataRewriter) {
super(user, ProtocolVersion.v1_8);
this.metadataRewriter = metadataRewriter;
registerEntity(EntityTypes1_10.EntityType.GUARDIAN, EntityTypes1_10.EntityType.SQUID, "Guardian");
registerEntity(EntityTypes1_10.EntityType.ENDERMITE, EntityTypes1_10.EntityType.SQUID, "Endermite");
registerEntity(EntityTypes1_10.EntityType.RABBIT, EntityTypes1_10.EntityType.CHICKEN, "Rabbit");
}
public void trackHologram(final int entityId, final VirtualHologramEntity hologram) {
addEntity(entityId, EntityTypes1_10.EntityType.ARMOR_STAND);
getEntityReplacementMap().put(entityId, EntityTypes1_10.EntityType.ARMOR_STAND);
virtualHologramMap.put(entityId, hologram);
}
@Override
public void updateMetadata(int entityId, List<Metadata> metadata) throws Exception {
if (virtualHologramMap.containsKey(entityId)) {
virtualHologramMap.get(entityId).updateMetadata(metadata);
return;
}
super.updateMetadata(entityId, metadata);
}
@Override
public void removeEntity(int entityId) {
super.removeEntity(entityId);
if (playersByEntityId.containsKey(entityId)) {
final UUID playerId = playersByEntityId.remove(entityId);
playersByUniqueId.remove(playerId);
getUser().get(PlayerSessionStorage.class).getPlayerEquipment().remove(playerId);
}
}
@Override
public void clear() {
super.clear();
vehicleMap.clear();
}
@Override
public void setClientEntityId(int entityId) {
if (this.spectatingPlayerId == this.getPlayerId()) {
this.spectatingPlayerId = entityId;
}
super.setClientEntityId(entityId);
}
public void addPlayer(final Integer entityId, final UUID uuid) {
playersByUniqueId.put(uuid, entityId);
playersByEntityId.put(entityId, uuid);
}
public UUID getPlayerUUID(final int entityId) {
return playersByEntityId.get(entityId);
}
public int getPlayerEntityId(final UUID uuid) {
return playersByUniqueId.getOrDefault(uuid, -1);
}
public int getVehicle(final int passengerId) {
for (Map.Entry<Integer, Integer> vehicle : vehicleMap.entrySet()) {
if (vehicle.getValue() == passengerId) {
return vehicle.getValue();
}
}
return -1;
}
public int getPassenger(int vehicleId) {
return vehicleMap.getOrDefault(vehicleId, -1);
}
protected void startSneaking() {
try {
final PacketWrapper entityAction = PacketWrapper.create(ServerboundPackets1_7_2_5.ENTITY_ACTION, getUser());
entityAction.write(Type.VAR_INT, this.getPlayerId()); // entity id
entityAction.write(Type.VAR_INT, 0); // action id, start sneaking
entityAction.write(Type.VAR_INT, 0); // jump boost
entityAction.sendToServer(Protocol1_7_6_10To1_8.class, true);
} catch (Exception e) {
ViaRewind.getPlatform().getLogger().log(Level.SEVERE, "Failed to send sneak packet", e);
}
}
public void setPassenger(int vehicleId, int passengerId) {
if (vehicleId == this.spectatingPlayerId && this.spectatingPlayerId != this.getPlayerId()) {
startSneaking();
setSpectating(this.getPlayerId());
}
if (vehicleId == -1) {
vehicleMap.remove(getVehicle(passengerId));
} else if (passengerId == -1) {
vehicleMap.remove(vehicleId);
} else {
vehicleMap.put(vehicleId, passengerId);
}
}
protected void attachEntity(final int target) {
try {
final PacketWrapper attachEntity = PacketWrapper.create(ClientboundPackets1_8.ATTACH_ENTITY, getUser());
attachEntity.write(Type.INT, this.getPlayerId()); // vehicle id
attachEntity.write(Type.INT, target); // passenger id
attachEntity.write(Type.BOOLEAN, false); // leash
attachEntity.scheduleSend(Protocol1_7_6_10To1_8.class, true);
} catch (Exception e) {
ViaRewind.getPlatform().getLogger().log(Level.SEVERE, "Failed to send attach packet", e);
}
}
public void setSpectating(int spectating) {
if (spectating != this.getPlayerId() && getPassenger(spectating) != -1) {
startSneaking();
setSpectating(this.getPlayerId());
return;
}
if (this.spectatingPlayerId != spectating && this.spectatingPlayerId != this.getPlayerId()) {
attachEntity(-1);
}
this.spectatingPlayerId = spectating;
if (spectating != this.getPlayerId()) {
attachEntity(this.spectatingPlayerId);
}
}
public Map<Integer, VirtualHologramEntity> getVirtualHologramMap() {
return virtualHologramMap;
}
}
@@ -1,146 +0,0 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2016-2023 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.storage;
import com.viaversion.viarewind.utils.ChatUtil;
import com.viaversion.viaversion.api.connection.StoredObject;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.minecraft.item.DataItem;
import com.viaversion.viaversion.api.minecraft.item.Item;
import com.viaversion.viaversion.libs.opennbt.tag.builtin.CompoundTag;
import com.viaversion.viaversion.libs.opennbt.tag.builtin.ListTag;
import com.viaversion.viaversion.libs.opennbt.tag.builtin.StringTag;
import com.viaversion.viaversion.util.ChatColorUtil;
import java.util.*;
public class GameProfileStorage extends StoredObject {
private final Map<UUID, GameProfile> properties = new HashMap<>();
public GameProfileStorage(UserConnection user) {
super(user);
}
public GameProfile put(UUID uuid, String name) {
GameProfile gameProfile = new GameProfile(uuid, name);
properties.put(uuid, gameProfile);
return gameProfile;
}
public GameProfile get(UUID uuid) {
return properties.get(uuid);
}
public GameProfile get(String name, boolean ignoreCase) {
if (ignoreCase) name = name.toLowerCase();
for (GameProfile profile : properties.values()) {
if (profile.name == null) continue;
String n = ignoreCase ? profile.name.toLowerCase() : profile.name;
if (n.equals(name)) {
return profile;
}
}
return null;
}
public List<GameProfile> getAllWithPrefix(String prefix, boolean ignoreCase) {
if (ignoreCase) prefix = prefix.toLowerCase();
ArrayList<GameProfile> profiles = new ArrayList<>();
for (GameProfile profile : properties.values()) {
if (profile.name == null) continue;
String n = ignoreCase ? profile.name.toLowerCase() : profile.name;
if (n.startsWith(prefix)) profiles.add(profile);
}
return profiles;
}
public GameProfile remove(UUID uuid) {
return properties.remove(uuid);
}
public static class GameProfile {
public final String name;
public final UUID uuid;
public String displayName;
public int ping;
public List<Property> properties = new ArrayList<>();
public int gamemode = 0;
public GameProfile(UUID uuid, String name) {
this.name = name;
this.uuid = uuid;
}
public Item getSkull() {
CompoundTag tag = new CompoundTag();
CompoundTag ownerTag = new CompoundTag();
tag.put("SkullOwner", ownerTag);
ownerTag.put("Id", new StringTag(uuid.toString()));
CompoundTag properties = new CompoundTag();
ownerTag.put("Properties", properties);
ListTag textures = new ListTag(CompoundTag.class);
properties.put("textures", textures);
for (Property property : this.properties) {
if (property.name.equals("textures")) {
CompoundTag textureTag = new CompoundTag();
textureTag.put("Value", new StringTag(property.value));
if (property.signature != null) {
textureTag.put("Signature", new StringTag(property.signature));
}
textures.add(textureTag);
}
}
return new DataItem(397, (byte) 1, (short) 3, tag);
}
public String getDisplayName() {
String displayName = this.displayName == null ? name : this.displayName;
if (displayName.length() > 16) displayName = ChatUtil.removeUnusedColor(displayName, 'f');
if (displayName.length() > 16) displayName = ChatColorUtil.stripColor(displayName);
if (displayName.length() > 16) displayName = displayName.substring(0, 16);
return displayName;
}
public void setDisplayName(String displayName) {
this.displayName = displayName;
}
}
public static class Property {
public final String name;
public final String value;
public final String signature;
public Property(String name, String value, String signature) {
this.name = name;
this.value = value;
this.signature = signature;
}
}
}
@@ -1,79 +0,0 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2016-2023 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.storage;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.model.FurnaceData;
import com.viaversion.viaversion.api.connection.StoredObject;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.minecraft.item.Item;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
public class InventoryTracker extends StoredObject {
public final static Map<String, Integer> WINDOW_TYPE_REGISTRY = new HashMap<>();
static {
WINDOW_TYPE_REGISTRY.put("minecraft:container", 0);
WINDOW_TYPE_REGISTRY.put("minecraft:chest", 0);
WINDOW_TYPE_REGISTRY.put("minecraft:crafting_table", 1);
WINDOW_TYPE_REGISTRY.put("minecraft:furnace", 2);
WINDOW_TYPE_REGISTRY.put("minecraft:dispenser", 3);
WINDOW_TYPE_REGISTRY.put("minecraft:enchanting_table", 4);
WINDOW_TYPE_REGISTRY.put("minecraft:brewing_stand", 5);
WINDOW_TYPE_REGISTRY.put("minecraft:villager", 6);
WINDOW_TYPE_REGISTRY.put("minecraft:beacon", 7);
WINDOW_TYPE_REGISTRY.put("minecraft:anvil", 8);
WINDOW_TYPE_REGISTRY.put("minecraft:hopper", 9);
WINDOW_TYPE_REGISTRY.put("minecraft:dropper", 10);
WINDOW_TYPE_REGISTRY.put("EntityHorse", 11);
}
private final HashMap<Short, Short> windowTypeMap = new HashMap<>();
private final HashMap<Short, FurnaceData> furnaceData = new HashMap<>();
public short levelCost = 0;
public short anvilId = -1;
public InventoryTracker(UserConnection user) {
super(user);
}
public short get(short windowId) {
return windowTypeMap.getOrDefault(windowId, (short) -1);
}
public void remove(short windowId) {
windowTypeMap.remove(windowId);
furnaceData.remove(windowId);
}
public static short getInventoryType(String name) {
return WINDOW_TYPE_REGISTRY.getOrDefault(name, -1).shortValue();
}
public HashMap<Short, Short> getWindowTypeMap() {
return windowTypeMap;
}
public HashMap<Short, FurnaceData> getFurnaceData() {
return furnaceData;
}
}
@@ -1,87 +0,0 @@
package com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.storage;
import com.viaversion.viaversion.api.connection.StoredObject;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.minecraft.item.Item;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
public class PlayerSessionStorage extends StoredObject {
// Player info
public int gameMode;
// Player abilities
public boolean sprinting, allowFly, flying, invincible, creative;
public float flySpeed, walkSpeed;
// Player position, rotation and data
private double posX, posY, posZ;
public double receivedPosY;
public float yaw, pitch;
public boolean onGround;
// Player inventory
private final Map<UUID, Item[]> playerEquipment = new HashMap<>();
public PlayerSessionStorage(UserConnection user) {
super(user);
}
public byte combineAbilities() {
byte flags = 0;
if (invincible) flags |= 8;
if (allowFly) flags |= 4;
if (flying) flags |= 2;
if (creative) flags |= 1;
return flags;
}
public double getPosX() {
return posX;
}
public double getPosY() {
return posY;
}
public double getPosZ() {
return posZ;
}
public void setPos(double x, double y, double z) {
posX = x;
posY = y;
posZ = z;
}
public Item getPlayerEquipment(final UUID uuid, final int slot) {
final Item[] items = playerEquipment.get(uuid);
if (items == null || slot < 0 || slot >= items.length) {
return null;
}
return items[slot];
}
public void setPlayerEquipment(final UUID uuid, final Item equipment, final int slot) {
final Item[] items = playerEquipment.computeIfAbsent(uuid, it -> new Item[5]);
if (slot < 0 || slot >= items.length) {
return;
}
items[slot] = equipment;
}
public boolean isSpectator() {
return gameMode == 3;
}
public Map<UUID, Item[]> getPlayerEquipment() {
return playerEquipment;
}
}
@@ -1,187 +0,0 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2016-2023 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.storage;
import com.viaversion.viarewind.protocol.protocol1_7_2_5to1_7_6_10.ClientboundPackets1_7_2_5;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.Protocol1_7_6_10To1_8;
import com.viaversion.viarewind.utils.PacketUtil;
import com.viaversion.viaversion.api.connection.StoredObject;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.type.Type;
import java.util.*;
public class Scoreboard extends StoredObject {
private final HashMap<String, List<String>> teams = new HashMap<>();
private final HashSet<String> objectives = new HashSet<>();
private final HashMap<String, ScoreTeam> scoreTeams = new HashMap<>();
private final HashMap<String, Byte> teamColors = new HashMap<>();
private final HashSet<String> scoreTeamNames = new HashSet<>();
private String colorIndependentSidebar;
private final HashMap<Byte, String> colorDependentSidebar = new HashMap<>();
public Scoreboard(UserConnection user) {
super(user);
}
public void addPlayerToTeam(String player, String team) {
teams.computeIfAbsent(team, key -> new ArrayList<>()).add(player);
}
public void setTeamColor(String team, Byte color) {
teamColors.put(team, color);
}
public Optional<Byte> getTeamColor(String team) {
return Optional.ofNullable(teamColors.get(team));
}
public void addTeam(String team) {
teams.computeIfAbsent(team, key -> new ArrayList<>());
}
public void removeTeam(String team) {
teams.remove(team);
scoreTeams.remove(team);
teamColors.remove(team);
}
public boolean teamExists(String team) {
return teams.containsKey(team);
}
public void removePlayerFromTeam(String player, String team) {
List<String> teamPlayers = teams.get(team);
if (teamPlayers != null) teamPlayers.remove(player);
}
public boolean isPlayerInTeam(String player, String team) {
List<String> teamPlayers = teams.get(team);
return teamPlayers != null && teamPlayers.contains(player);
}
public boolean isPlayerInTeam(String player) {
for (List<String> teamPlayers : teams.values()) {
if (teamPlayers.contains(player)) return true;
}
return false;
}
public Optional<Byte> getPlayerTeamColor(String player) {
Optional<String> team = getTeam(player);
return team.isPresent() ? getTeamColor(team.get()) : Optional.empty();
}
public Optional<String> getTeam(String player) {
for (Map.Entry<String, List<String>> entry : teams.entrySet())
if (entry.getValue().contains(player))
return Optional.of(entry.getKey());
return Optional.empty();
}
public void addObjective(String name) {
objectives.add(name);
}
public void removeObjective(String name) {
objectives.remove(name);
colorDependentSidebar.values().remove(name);
if (name.equals(colorIndependentSidebar)) {
colorIndependentSidebar = null;
}
}
public boolean objectiveExists(String name) {
return objectives.contains(name);
}
public String sendTeamForScore(String score) {
if (score.length() <= 16) return score;
if (scoreTeams.containsKey(score)) return scoreTeams.get(score).name;
int l = 16;
int i = Math.min(16, score.length() - 16);
String name = score.substring(i, i + l);
while (scoreTeamNames.contains(name) || teams.containsKey(name)) {
i--;
while (score.length() - l - i > 16) {
l--;
if (l < 1) return score;
i = Math.min(16, score.length() - l);
}
name = score.substring(i, i + l);
}
String prefix = score.substring(0, i);
String suffix = i + l >= score.length() ? "" : score.substring(i + l);
ScoreTeam scoreTeam = new ScoreTeam(name, prefix, suffix);
scoreTeams.put(score, scoreTeam);
scoreTeamNames.add(name);
PacketWrapper teamPacket = PacketWrapper.create(ClientboundPackets1_7_2_5.TEAMS, getUser());
teamPacket.write(Type.STRING, name);
teamPacket.write(Type.BYTE, (byte) 0);
teamPacket.write(Type.STRING, "ViaRewind");
teamPacket.write(Type.STRING, prefix);
teamPacket.write(Type.STRING, suffix);
teamPacket.write(Type.BYTE, (byte) 0);
teamPacket.write(Type.SHORT, (short) 1);
teamPacket.write(Type.STRING, name);
PacketUtil.sendPacket(teamPacket, Protocol1_7_6_10To1_8.class, true, true);
return name;
}
public String removeTeamForScore(String score) {
ScoreTeam scoreTeam = scoreTeams.remove(score);
if (scoreTeam == null) return score;
scoreTeamNames.remove(scoreTeam.name);
PacketWrapper teamPacket = PacketWrapper.create(ClientboundPackets1_7_2_5.TEAMS, getUser());
teamPacket.write(Type.STRING, scoreTeam.name);
teamPacket.write(Type.BYTE, (byte) 1);
PacketUtil.sendPacket(teamPacket, Protocol1_7_6_10To1_8.class, true, true);
return scoreTeam.name;
}
public String getColorIndependentSidebar() {
return this.colorIndependentSidebar;
}
public HashMap<Byte, String> getColorDependentSidebar() {
return this.colorDependentSidebar;
}
public void setColorIndependentSidebar(String colorIndependentSidebar) {
this.colorIndependentSidebar = colorIndependentSidebar;
}
private static class ScoreTeam {
private final String prefix;
private final String suffix;
private final String name;
public ScoreTeam(String name, String prefix, String suffix) {
this.prefix = prefix;
this.suffix = suffix;
this.name = name;
}
}
}
@@ -1,108 +0,0 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2016-2023 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.storage;
import com.viaversion.viaversion.api.connection.StoredObject;
import com.viaversion.viaversion.api.connection.UserConnection;
public class WorldBorderEmulator extends StoredObject {
private double x, z;
private double oldDiameter, newDiameter;
private long lerpTime;
private long lerpStartTime;
private boolean init = false;
public WorldBorderEmulator(UserConnection user) {
super(user);
}
public void init(double x, double z, double oldDiameter, double newDiameter, long lerpTime) {
this.x = x;
this.z = z;
this.oldDiameter = oldDiameter;
this.newDiameter = newDiameter;
this.lerpTime = lerpTime;
init = true;
}
public void setCenter(double x, double z) {
this.x = x;
this.z = z;
}
public void lerpSize(double oldDiameter, double newDiameter, long lerpTime) {
this.oldDiameter = oldDiameter;
this.newDiameter = newDiameter;
this.lerpTime = lerpTime;
this.lerpStartTime = System.currentTimeMillis();
}
public void setSize(double size) {
this.oldDiameter = size;
this.newDiameter = size;
this.lerpTime = 0;
}
public double getSize() {
if (lerpTime == 0) {
return newDiameter;
}
double percent = ((double) (System.currentTimeMillis() - lerpStartTime) / (double) (lerpTime));
// Clamp value
if (percent > 1.0D) percent = 1.0d;
else if (percent < 0.0D) percent = 0.0d;
return oldDiameter + (newDiameter - oldDiameter) * percent;
}
public double getX() {
return x;
}
public double getZ() {
return z;
}
public boolean isInit() {
return init;
}
public enum Side {
NORTH(0, -1),
EAST(1, 0),
SOUTH(0, 1),
WEST(-1, 0);
public final int modX;
public final int modZ;
Side(int modX, int modZ) {
this.modX = modX;
this.modZ = modZ;
}
}
}
@@ -1,78 +0,0 @@
package com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.task;
import com.viaversion.viarewind.ViaRewind;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.Protocol1_7_6_10To1_8;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.storage.PlayerSessionStorage;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.storage.WorldBorderEmulator;
import com.viaversion.viaversion.api.Via;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.protocols.protocol1_8.ClientboundPackets1_8;
import java.util.logging.Level;
public class WorldBorderUpdateTask implements Runnable {
public final static int VIEW_DISTANCE = 16;
@Override
public void run() {
for (UserConnection connection : Via.getManager().getConnectionManager().getConnections()) {
final WorldBorderEmulator worldBorderEmulatorTracker = connection.get(WorldBorderEmulator.class);
if (!worldBorderEmulatorTracker.isInit()) continue;
final PlayerSessionStorage playerSession = connection.get(PlayerSessionStorage.class);
double radius = worldBorderEmulatorTracker.getSize() / 2.0;
for (WorldBorderEmulator.Side side : WorldBorderEmulator.Side.values()) {
double d;
double pos;
double center;
if (side.modX != 0) {
pos = playerSession.getPosZ();
center = worldBorderEmulatorTracker.getZ();
d = Math.abs(worldBorderEmulatorTracker.getX() + radius * side.modX - playerSession.getPosX());
} else {
center = worldBorderEmulatorTracker.getX();
pos = playerSession.getPosX();
d = Math.abs(worldBorderEmulatorTracker.getZ() + radius * side.modZ - playerSession.getPosZ());
}
if (d >= VIEW_DISTANCE) continue;
double r = Math.sqrt(VIEW_DISTANCE * VIEW_DISTANCE - d * d);
double minH = Math.ceil(pos - r);
double maxH = Math.floor(pos + r);
double minV = Math.ceil(playerSession.getPosY() - r);
double maxV = Math.floor(playerSession.getPosY() + r);
if (minH < center - radius) minH = Math.ceil(center - radius);
if (maxH > center + radius) maxH = Math.floor(center + radius);
if (minV < 0.0) minV = 0.0;
double centerH = (minH + maxH) / 2.0;
double centerV = (minV + maxV) / 2.0;
double particleOffset = 2.5;
final PacketWrapper spawnParticle = PacketWrapper.create(ClientboundPackets1_8.SPAWN_PARTICLE, connection);
spawnParticle.write(Type.STRING, ViaRewind.getConfig().getWorldBorderParticle()); // particle name
spawnParticle.write(Type.FLOAT, (float) (side.modX != 0 ? worldBorderEmulatorTracker.getX() + (radius * side.modX) : centerH)); // x
spawnParticle.write(Type.FLOAT, (float) centerV); // y
spawnParticle.write(Type.FLOAT, (float) (side.modX == 0 ? worldBorderEmulatorTracker.getZ() + (radius * side.modZ) : centerH)); // z
spawnParticle.write(Type.FLOAT, (float) (side.modX != 0 ? 0f : (maxH - minH) / particleOffset)); // offset x
spawnParticle.write(Type.FLOAT, (float) ((maxV - minV) / particleOffset)); // offset y
spawnParticle.write(Type.FLOAT, (float) (side.modX == 0 ? 0f : (maxH - minH) / particleOffset)); // offset z
spawnParticle.write(Type.FLOAT, 0F); // particle data
spawnParticle.write(Type.INT, (int) Math.floor((maxH - minH) * (maxV - minV) * 0.5));
try {
spawnParticle.send(Protocol1_7_6_10To1_8.class, true);
} catch (Exception e) {
ViaRewind.getPlatform().getLogger().log(Level.SEVERE, "Failed to send world border particle", e);
}
}
}
}
}
Loaded 100 of 229 files, more files were not shown because too many files have changed in this diff. Show more