Compare commits

..
Author SHA1 Message Date
Florian Reuth 667493a671 Codebase cleanup
Signed-off-by: Florian Reuth <git@florianreuth.de>
2026-04-20 21:11:21 +02:00
38 changed files with 516 additions and 760 deletions

No files matched your search

+4 -7
View File
@@ -10,16 +10,13 @@ jobs:
runs-on: ubuntu-24.04
steps:
- name: Checkout Repository
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # 6.0.2
with:
persist-credentials: false
- name: Set up Gradle
uses: gradle/actions/setup-gradle@50e97c2cd7a37755bbfafc9c5b7cafaece252f6e # v6.1.0
with:
cache-disabled: false
cache-provider: basic
uses: gradle/actions/setup-gradle@50e97c2cd7a37755bbfafc9c5b7cafaece252f6e # 6.1.0
- name: Set up JDK 17
uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0
uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # 5.2.0
with:
distribution: 'temurin'
java-version: 17
@@ -27,7 +24,7 @@ jobs:
- name: Build with Gradle
run: ./gradlew build
- name: Upload Artifacts to GitHub
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # 7.0.0
with:
name: Artifacts
path: build/libs/
+3 -6
View File
@@ -15,16 +15,13 @@ jobs:
runs-on: ubuntu-24.04
steps:
- name: Checkout Repository
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # 6.0.2
with:
persist-credentials: false
- name: Set up Gradle
uses: gradle/actions/setup-gradle@50e97c2cd7a37755bbfafc9c5b7cafaece252f6e # v6.1.0
with:
cache-disabled: false
cache-provider: basic
uses: gradle/actions/setup-gradle@50e97c2cd7a37755bbfafc9c5b7cafaece252f6e # 6.1.0
- name: Set up JDK 17
uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0
uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # 5.2.0
with:
distribution: 'temurin'
java-version: 17
+2 -2
View File
@@ -24,8 +24,8 @@ allprojects {
subprojects {
dependencies {
compileOnly("com.viaversion:viaversion:5.10.0")
compileOnly("com.viaversion:viabackwards:5.10.0")
compileOnly("com.viaversion:viaversion:5.7.2")
compileOnly("com.viaversion:viabackwards:5.7.2")
}
tasks {
@@ -55,8 +55,8 @@ public class ViaRewindConfig extends Config implements com.viaversion.viarewind.
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);
maxBookPages = getInt("end-book-pages", 100);
maxBookPageSize = getInt("end-book-page-length", 5000);
emulateWorldBorder = getBoolean("emulate-world-border", true);
alwaysShowOriginalMobName = getBoolean("always-show-original-mob-name", true);
worldBorderParticle = getString("world-border-particle", "fireworksSpark");
@@ -54,14 +54,14 @@ public interface ViaRewindConfig extends Config {
/**
* Max amount of pages for written books before a client gets kicked
*
* @return the max amount of pages
* @return the end 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
* @return the end amount of characters
*/
int getMaxBookPageSize();
@@ -1,157 +0,0 @@
/*
* 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);
}
}
}
@@ -22,7 +22,7 @@ import com.viaversion.viabackwards.api.data.BackwardsMappingData;
import com.viaversion.viarewind.ViaRewind;
import java.util.logging.Logger;
public class RewindMappingData extends BackwardsMappingData {
public final class RewindMappingData extends BackwardsMappingData {
public RewindMappingData(String unmappedVersion, String mappedVersion) {
super(unmappedVersion, mappedVersion);
@@ -37,4 +37,5 @@ public class RewindMappingData extends BackwardsMappingData {
protected CompoundTag readMappingsFile(String name) {
return RewindMappingDataLoader.INSTANCE.loadNBTFromDir(name);
}
}
@@ -22,7 +22,7 @@ import com.viaversion.viarewind.ViaRewind;
import java.io.File;
import java.util.logging.Logger;
public class RewindMappingDataLoader extends BackwardsMappingDataLoader {
public final class RewindMappingDataLoader extends BackwardsMappingDataLoader {
public static final RewindMappingDataLoader INSTANCE = new RewindMappingDataLoader();
@@ -30,7 +30,6 @@ public class RewindMappingDataLoader extends BackwardsMappingDataLoader {
super(RewindMappingDataLoader.class, "assets/viarewind/data/");
}
@Override
public Logger getLogger() {
return ViaRewind.getPlatform().getLogger();
@@ -40,4 +39,5 @@ public class RewindMappingDataLoader extends BackwardsMappingDataLoader {
public File getDataFolder() {
return ViaRewind.getPlatform().getDataFolder();
}
}
@@ -23,6 +23,7 @@ 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),
@@ -34,12 +35,12 @@ public enum EntityDataTypes1_7_6_10 implements EntityDataType {
private final int typeID;
private final Type<?> type;
EntityDataTypes1_7_6_10(int typeID, Type<?> type) {
EntityDataTypes1_7_6_10(final int typeID, final Type<?> type) {
this.typeID = typeID;
this.type = type;
}
public static EntityDataTypes1_7_6_10 byId(int id) {
public static EntityDataTypes1_7_6_10 byId(final int id) {
return values()[id];
}
@@ -52,4 +53,5 @@ public enum EntityDataTypes1_7_6_10 implements EntityDataType {
public Type<?> type() {
return this.type;
}
}
@@ -17,20 +17,8 @@
*/
package com.viaversion.viarewind.api.minecraft.math;
public class AABB {
Vector3d min;
Vector3d max;
import com.viaversion.viaversion.api.minecraft.Vector3d;
public AABB(Vector3d min, Vector3d max) {
this.min = min;
this.max = max;
}
public record Box(Vector3d start, Vector3d end) {
public Vector3d getMin() {
return this.min;
}
public Vector3d getMax() {
return this.max;
}
}
@@ -17,42 +17,58 @@
*/
package com.viaversion.viarewind.api.minecraft.math;
public class RayTracing {
import com.viaversion.viaversion.api.minecraft.Vector3d;
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);
public final class RayTracing {
boolean signDirX = invDir.x < 0;
boolean signDirY = invDir.y < 0;
boolean signDirZ = invDir.z < 0;
public static Vector3d trace(final Box ray, final Box box, final double distance) {
final Vector3d invDir = new Vector3d(1f / ray.end().x(), 1f / ray.end().y(), 1f / ray.end().z());
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;
final boolean signDirX = invDir.x() < 0;
final boolean signDirY = invDir.y() < 0;
final boolean signDirZ = invDir.z() < 0;
if (tmin > tymax || tymin > tmax) return null;
Vector3d boundingBox = signDirX ? box.end() : box.start();
double tmin = (boundingBox.x() - ray.start().x()) * invDir.x();
boundingBox = signDirX ? box.start() : box.end();
double tmax = (boundingBox.x() - ray.start().x()) * invDir.x();
boundingBox = signDirY ? box.end() : box.start();
final double tymin = (boundingBox.y() - ray.start().y()) * invDir.y();
boundingBox = signDirY ? box.start() : box.end();
final double tymax = (boundingBox.y() - ray.start().y()) * invDir.y();
if (tymin > tmin) tmin = tymin;
if (tmin > tymax || tymin > tmax) {
return null;
}
if (tymax < tmax) tmax = tymax;
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;
boundingBox = signDirZ ? box.end() : box.start();
double tzmin = (boundingBox.z() - ray.start().z()) * invDir.z();
boundingBox = signDirZ ? box.start() : box.end();
double tzmax = (boundingBox.z() - ray.start().z()) * invDir.z();
if (tmin > tzmax || tzmin > tmax) return null;
if (tmin > tzmax || tzmin > tmax) {
return null;
}
if (tzmin > tmin) tmin = tzmin;
if (tzmin > tmin) {
tmin = tzmin;
}
if (tzmax < tmax) {
tmax = tzmax;
}
if (tzmax < tmax) tmax = tzmax;
if (tmin <= distance && tmax > 0) {
// ray.start().clone().add(ray.dir().clone().normalize().multiply(tmin))
}
return tmin <= distance && tmax > 0 ? ray.start.clone().add(ray.dir.clone().normalize().multiply(tmin)) : null;
return null;
}
}
@@ -1,128 +0,0 @@
/*
* 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;
}
}
@@ -17,13 +17,11 @@
*/
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;
import java.util.zip.Deflater;
public class BulkChunkType1_7_6 extends Type<Chunk[]> {
@@ -65,48 +63,41 @@ public class BulkChunkType1_7_6 extends Type<Chunk[]> {
);
}
final ByteBuf uncompressed = buffer.alloc().buffer(totalSize);
final byte[] data = new byte[totalSize];
int offset = 0;
try {
for (int i = 0; i < chunkCount; i++) {
Chunk chunk = chunks[i];
boolean biomes = chunk.isFullChunk() && chunk.getBiomeData() != null;
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();
offset = ChunkType1_7_6.serialize(
chunk,
data,
offset,
addBitMasks[i],
anySkyLight,
biomes
);
}
buffer.writeShort(chunkCount);
final Deflater deflater = new Deflater();
byte[] compressedData;
int compressedSize;
try {
deflater.setInput(data, 0, data.length);
deflater.finish();
compressedData = new byte[data.length];
compressedSize = deflater.deflate(compressedData);
} finally {
deflater.end();
}
buffer.writeInt(compressedSize);
buffer.writeBoolean(anySkyLight);
buffer.writeBytes(compressedData, 0, compressedSize);
for (int i = 0; i < chunkCount; i++) {
Chunk chunk = chunks[i];
buffer.writeInt(chunk.getX());
@@ -17,15 +17,13 @@
*/
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 java.util.zip.Deflater;
import static com.viaversion.viaversion.api.minecraft.chunks.ChunkSection.SIZE;
import static com.viaversion.viaversion.api.minecraft.chunks.ChunkSectionLight.LIGHT_LENGTH;
@@ -51,41 +49,33 @@ public class ChunkType1_7_6 extends Type<Chunk> {
final boolean biomes = chunk.isFullChunk() && chunk.getBiomeData() != null;
final int size = calcSize(bitmask, addBitmask, hasSkyLight, biomes);
final ByteBuf uncompressed = buffer.alloc().buffer(size);
final byte[] data = new byte[size];
serialize(chunk, data, 0, addBitmask, hasSkyLight, biomes);
buffer.writeInt(chunk.getX());
buffer.writeInt(chunk.getZ());
buffer.writeBoolean(chunk.isFullChunk());
buffer.writeShort(bitmask);
buffer.writeShort(addBitmask);
final Deflater deflater = new Deflater();
byte[] compressedData;
int compressedSize;
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);
deflater.setInput(data, 0, data.length);
deflater.finish();
compressedData = new byte[data.length];
compressedSize = deflater.deflate(compressedData);
} finally {
uncompressed.release();
deflater.end();
}
buffer.writeInt(compressedSize);
buffer.writeBytes(compressedData, 0, compressedSize);
}
public static void serialize(Chunk chunk, ByteBuf output, int addBitmask, boolean writeSkyLight, boolean biomes) {
public static int serialize(Chunk chunk, byte[] output, int offset, int addBitmask, boolean writeSkyLight, boolean biomes) {
final ChunkSection[] sections = chunk.getSections();
final int bitmask = chunk.getBitmask();
@@ -95,7 +85,7 @@ public class ChunkType1_7_6 extends Type<Chunk> {
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);
output[offset++] = (byte) ((block >> 4) & 0xFF);
}
}
}
@@ -107,7 +97,7 @@ public class ChunkType1_7_6 extends Type<Chunk> {
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));
output[offset++] = (byte) (meta1 | (meta2 << 4));
}
}
}
@@ -115,7 +105,8 @@ public class ChunkType1_7_6 extends Type<Chunk> {
for (int i = 0; i < 16; i++) {
if ((bitmask & (1 << i)) != 0) {
final byte[] blockLight = sections[i].getLight().getBlockLight();
output.writeBytes(blockLight);
System.arraycopy(blockLight, 0, output, offset, LIGHT_LENGTH);
offset += LIGHT_LENGTH;
}
}
@@ -124,11 +115,9 @@ public class ChunkType1_7_6 extends Type<Chunk> {
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);
System.arraycopy(skyLight, 0, output, offset, LIGHT_LENGTH);
}
offset += LIGHT_LENGTH;
}
}
}
@@ -141,7 +130,7 @@ public class ChunkType1_7_6 extends Type<Chunk> {
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));
output[offset++] = (byte) (add1 | (add2 << 4));
}
}
}
@@ -150,9 +139,11 @@ public class ChunkType1_7_6 extends Type<Chunk> {
if (biomes && chunk.getBiomeData() != null) {
final int[] biomeData = chunk.getBiomeData();
for (int biome : biomeData) {
output.writeByte(biome);
output[offset++] = (byte) biome;
}
}
return offset;
}
public static int calcSize(int bitmask, int addBitmask, boolean hasSkyLight, boolean biomes) {
@@ -130,7 +130,6 @@ public class Protocol1_8To1_7_6_10 extends BackwardsProtocol<ClientboundPackets1
connection.put(new GameProfileStorage(connection));
connection.put(new ScoreboardTracker(connection));
connection.put(new CompressionStatusTracker(connection));
connection.put(new WorldBorderEmulator(connection));
}
@Override
@@ -18,14 +18,14 @@
package com.viaversion.viarewind.protocol.v1_8to1_7_6_10.data;
import com.viaversion.viarewind.api.minecraft.entitydata.EntityDataTypes1_7_6_10;
import com.viaversion.viarewind.api.minecraft.math.AABB;
import com.viaversion.viarewind.api.minecraft.math.Vector3d;
import com.viaversion.viarewind.api.minecraft.math.Box;
import com.viaversion.viarewind.api.type.RewindTypes;
import com.viaversion.viarewind.protocol.v1_7_6_10to1_7_2_5.packet.ClientboundPackets1_7_2_5;
import com.viaversion.viarewind.protocol.v1_8to1_7_6_10.Protocol1_8To1_7_6_10;
import com.viaversion.viarewind.protocol.v1_8to1_7_6_10.rewriter.EntityPacketRewriter1_8;
import com.viaversion.viarewind.protocol.v1_8to1_7_6_10.storage.EntityTracker1_8;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.minecraft.Vector3d;
import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_8;
import com.viaversion.viaversion.api.minecraft.entitydata.EntityData;
import com.viaversion.viaversion.api.minecraft.entitydata.types.EntityDataTypes1_8;
@@ -328,14 +328,14 @@ public class VirtualHologramEntity {
}
}
public AABB getBoundingBox() {
public Box 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);
return new Box(min, max);
}
private int additionalEntityId() {
@@ -20,6 +20,7 @@ package com.viaversion.viarewind.protocol.v1_8to1_7_6_10.provider;
import com.viaversion.viarewind.protocol.v1_8to1_7_6_10.storage.CompressionStatusTracker;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.platform.providers.Provider;
import io.netty.channel.ChannelHandler;
public abstract class CompressionHandlerProvider implements Provider {
@@ -27,6 +28,23 @@ public abstract class CompressionHandlerProvider implements Provider {
public abstract void onTransformPacket(UserConnection user);
/**
* Creates the compression encoder
*
* @param compressor A nullable object that may present a native backend for compression (if available)
* @param threshold The compression threshold
* @return The encoder
*/
public abstract ChannelHandler getEncoder(Object compressor, int threshold);
/**
* Creates the compression decoder
*
* @param compressor A nullable object that may present a native backend for compression (if available)
* @param threshold The compression threshold
* @return The decoder
*/
public abstract ChannelHandler getDecoder(Object compressor, int threshold);
public boolean isRemoveCompression(UserConnection user) {
return user.get(CompressionStatusTracker.class).removeCompression;
@@ -17,15 +17,18 @@
*/
package com.viaversion.viarewind.protocol.v1_8to1_7_6_10.provider.compression;
import com.viaversion.viarewind.api.compression.ThreadLocalCompressionProvider;
import com.viaversion.viaversion.api.type.Types;
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.DataFormatException;
import java.util.zip.Inflater;
public class CompressionDecoder extends MessageToMessageDecoder<ByteBuf> {
private final Inflater inflater = new Inflater();
private int threshold;
@@ -55,12 +58,25 @@ public class CompressionDecoder extends MessageToMessageDecoder<ByteBuf> {
throw new DecoderException("Badly compressed packet - size of " + outLength + " is larger than protocol maximum of " + 2097152);
}
ByteBuf output = ctx.alloc().buffer(outLength);
inflate(ctx, in, outLength, out);
}
protected void inflate(final ChannelHandlerContext ctx, final ByteBuf source, final int outLength, final List<Object> out) throws DataFormatException {
ByteBuf temp = source;
if (!source.hasArray()) {
temp = ByteBufAllocator.DEFAULT.heapBuffer().writeBytes(source);
} else {
source.retain();
}
ByteBuf output = ByteBufAllocator.DEFAULT.heapBuffer(outLength, outLength);
try {
ThreadLocalCompressionProvider.inflate(in, output, outLength);
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();
}
}
@@ -17,13 +17,16 @@
*/
package com.viaversion.viarewind.protocol.v1_8to1_7_6_10.provider.compression;
import com.viaversion.viarewind.api.compression.ThreadLocalCompressionProvider;
import com.viaversion.viaversion.api.type.Types;
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.DataFormatException;
import java.util.zip.Deflater;
public class CompressionEncoder extends MessageToByteEncoder<ByteBuf> {
private final Deflater deflater = new Deflater();
private int threshold;
@@ -45,7 +48,32 @@ public class CompressionEncoder extends MessageToByteEncoder<ByteBuf> {
}
Types.VAR_INT.writePrimitive(out, frameLength);
ThreadLocalCompressionProvider.deflate(in, out);
deflate(in, out);
}
protected void deflate(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 {
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()));
}
destination.writeBytes(output);
} finally {
output.release();
temp.release();
this.deflater.reset();
}
}
}
@@ -21,12 +21,28 @@ import com.viaversion.viarewind.ViaRewind;
import com.viaversion.viarewind.api.minecraft.netty.EmptyChannelHandler;
import com.viaversion.viarewind.api.minecraft.netty.ForwardMessageToByteEncoder;
import com.viaversion.viarewind.protocol.v1_8to1_7_6_10.provider.CompressionHandlerProvider;
import com.viaversion.viarewind.protocol.v1_8to1_7_6_10.provider.compression.velocity.VelocityCompressionDecoder;
import com.viaversion.viarewind.protocol.v1_8to1_7_6_10.provider.compression.velocity.VelocityCompressionEncoder;
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 {
// Use Velocity's compression backend if ViaRewind is loaded on a Velocity server or a custom server software
// is shipping them in the classpath.
private static boolean velocityNatives;
static {
try {
Class.forName("com.velocitypowered.natives.compression.VelocityCompressor");
velocityNatives = true;
} catch (final ClassNotFoundException ignored) {
velocityNatives = false;
}
}
@Override
public void setCompressionThreshold(UserConnection user, int threshold) {
final ChannelPipeline pipeline = user.getChannel().pipeline();
@@ -35,12 +51,17 @@ public class TrackingCompressionHandlerProvider extends CompressionHandlerProvid
return;
}
Object compressor = null;
if (velocityNatives) {
compressor = com.velocitypowered.natives.util.Natives.compress.get().create(-1);
}
final String compressHandlerName = ViaRewind.getPlatform().compressHandlerName();
final CompressionEncoder encoder = (CompressionEncoder) pipeline.get(compressHandlerName);
if (encoder != null) {
encoder.setThreshold(threshold);
} else {
pipeline.addBefore(Via.getManager().getInjector().getEncoderName(), compressHandlerName, new CompressionEncoder(threshold));
pipeline.addBefore(Via.getManager().getInjector().getEncoderName(), compressHandlerName, getEncoder(compressor, threshold));
}
final String decompressHandlerName = ViaRewind.getPlatform().decompressHandlerName();
@@ -48,7 +69,7 @@ public class TrackingCompressionHandlerProvider extends CompressionHandlerProvid
if (decoder != null) {
decoder.setThreshold(threshold);
} else {
pipeline.addBefore(Via.getManager().getInjector().getDecoderName(), decompressHandlerName, new CompressionDecoder(threshold));
pipeline.addBefore(Via.getManager().getInjector().getDecoderName(), decompressHandlerName, getDecoder(compressor, threshold));
}
}
@@ -75,5 +96,22 @@ public class TrackingCompressionHandlerProvider extends CompressionHandlerProvid
}
}
@Override
public ChannelHandler getEncoder(final Object compressor, int threshold) {
if (velocityNatives) {
return new VelocityCompressionEncoder(threshold, (com.velocitypowered.natives.compression.VelocityCompressor) compressor);
} else {
return new CompressionEncoder(threshold);
}
}
@Override
public ChannelHandler getDecoder(final Object compressor, int threshold) {
if (velocityNatives) {
return new VelocityCompressionDecoder(threshold, (com.velocitypowered.natives.compression.VelocityCompressor) compressor);
} else {
return new CompressionDecoder(threshold);
}
}
}
@@ -0,0 +1,47 @@
/*
* 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.protocol.v1_8to1_7_6_10.provider.compression.velocity;
import com.velocitypowered.natives.compression.VelocityCompressor;
import com.viaversion.viarewind.protocol.v1_8to1_7_6_10.provider.compression.CompressionDecoder;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import java.util.List;
import java.util.zip.DataFormatException;
public final class VelocityCompressionDecoder extends CompressionDecoder {
private final VelocityCompressor compressor;
public VelocityCompressionDecoder(final int threshold, final VelocityCompressor compressor) {
super(threshold);
this.compressor = compressor;
}
@Override
protected void inflate(final ChannelHandlerContext ctx, final ByteBuf source, final int outLength, final List<Object> out) throws DataFormatException {
ByteBuf output = ctx.alloc().buffer(outLength);
try {
this.compressor.inflate(source, output, outLength);
out.add(output.retain());
} finally {
output.release();
}
}
}
@@ -15,22 +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.api.minecraft.math;
package com.viaversion.viarewind.protocol.v1_8to1_7_6_10.provider.compression.velocity;
public class Ray3d {
Vector3d start;
Vector3d dir;
import com.velocitypowered.natives.compression.VelocityCompressor;
import com.viaversion.viarewind.protocol.v1_8to1_7_6_10.provider.compression.CompressionEncoder;
import io.netty.buffer.ByteBuf;
import java.util.zip.DataFormatException;
public Ray3d(Vector3d start, Vector3d dir) {
this.start = start;
this.dir = dir;
public final class VelocityCompressionEncoder extends CompressionEncoder {
private final VelocityCompressor compressor;
public VelocityCompressionEncoder(final int threshold, final VelocityCompressor compressor) {
super(threshold);
this.compressor = compressor;
}
public Vector3d getStart() {
return this.start;
@Override
protected void deflate(final ByteBuf source, final ByteBuf destination) throws DataFormatException {
this.compressor.deflate(source, destination);
}
public Vector3d getDir() {
return this.dir;
}
}
@@ -21,10 +21,8 @@ import com.viaversion.nbt.tag.CompoundTag;
import com.viaversion.nbt.tag.ListTag;
import com.viaversion.nbt.tag.StringTag;
import com.viaversion.viarewind.ViaRewind;
import com.viaversion.viarewind.api.minecraft.math.AABB;
import com.viaversion.viarewind.api.minecraft.math.Ray3d;
import com.viaversion.viarewind.api.minecraft.math.Box;
import com.viaversion.viarewind.api.minecraft.math.RayTracing;
import com.viaversion.viarewind.api.minecraft.math.Vector3d;
import com.viaversion.viarewind.api.type.RewindTypes;
import com.viaversion.viarewind.protocol.v1_7_6_10to1_7_2_5.packet.ClientboundPackets1_7_2_5;
import com.viaversion.viarewind.protocol.v1_7_6_10to1_7_2_5.packet.ServerboundPackets1_7_2_5;
@@ -48,7 +46,6 @@ import com.viaversion.viaversion.api.rewriter.RewriterBase;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.libs.gson.JsonElement;
import com.viaversion.viaversion.libs.gson.JsonObject;
import com.viaversion.viaversion.libs.gson.JsonPrimitive;
import com.viaversion.viaversion.protocols.v1_8to1_9.packet.ClientboundPackets1_8;
import com.viaversion.viaversion.protocols.v1_8to1_9.packet.ServerboundPackets1_8;
import com.viaversion.viaversion.util.ComponentUtil;
@@ -147,8 +144,8 @@ public class PlayerPacketRewriter1_8 extends RewriterBase<Protocol1_8To1_7_6_10>
return;
}
// On 1.8 clients when the player respawns it keeps all metadata and sets player back to max HP
// 1.7 clients do not copy the metadata but do set the health to max HP
// On 1.8 clients when the player respawns it keeps all metadata and sets player back to end HP
// 1.7 clients do not copy the metadata but do set the health to end HP
// to match the same client logic we remove the HP metadata as otherwise the client would be set to their old HP before respawning
final List<EntityData> entityDataList = new ArrayList<>(tracker.getEntityData());
entityDataList.removeIf(entityData -> entityData.id() == 6);
@@ -512,13 +509,7 @@ public class PlayerPacketRewriter1_8 extends RewriterBase<Protocol1_8To1_7_6_10>
String username = message.split(" ")[1];
final GameProfileStorage storage = wrapper.user().get(GameProfileStorage.class);
// Multiple players with the same name may exist. This will only represent
// fake players so it's fine to just pick the first one.
List<GameProfileStorage.GameProfile> profiles = storage.get(username, true);
if (profiles.isEmpty()) {
return;
}
final GameProfileStorage.GameProfile profile = profiles.get(0);
final GameProfileStorage.GameProfile profile = storage.get(username, true);
if (profile != null && profile.uuid != null) {
wrapper.cancel();
@@ -536,6 +527,9 @@ public class PlayerPacketRewriter1_8 extends RewriterBase<Protocol1_8To1_7_6_10>
map(Types.BYTE, Types.VAR_INT); // Mode
handler(wrapper -> {
final int mode = wrapper.get(Types.VAR_INT, 1);
if (mode != 0) {
return;
}
final EntityTracker1_8 tracker = wrapper.user().getEntityTracker(Protocol1_8To1_7_6_10.class);
final int entityId = tracker.getHologramIdWithExtra(wrapper.get(Types.VAR_INT, 0));
final PlayerSessionStorage position = wrapper.user().get(PlayerSessionStorage.class);
@@ -545,25 +539,20 @@ public class PlayerPacketRewriter1_8 extends RewriterBase<Protocol1_8To1_7_6_10>
}
wrapper.set(Types.VAR_INT, 0, entityId);
if (mode != 0) {
return;
}
final AABB boundingBox = tracker.getHolograms().get(entityId).getBoundingBox();
final Box boundingBox = tracker.getHolograms().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);
Rotation ray = new Rotation(pos, dir);
Vector3d intersection = RayTracing.trace(ray, boundingBox, 5.0);
if (intersection == null) {
return;
}
intersection.substract(boundingBox.getMin());
intersection.substract(boundingBox.start());
wrapper.set(Types.VAR_INT, 1, 2);
wrapper.write(Types.FLOAT, (float) intersection.getX());
@@ -617,16 +606,6 @@ public class PlayerPacketRewriter1_8 extends RewriterBase<Protocol1_8To1_7_6_10>
protected void register() {
map(Types.VAR_INT); // Status
map(RewindTypes.U_BYTE_POSITION, Types.BLOCK_POSITION1_8); // Position
handler(wrapper -> {
// 1.7 uses 255 as "no face"
// 1.8 changed this to only be in the range EnumFacing range (0-5) and uses DOWN when no face is used
// This properly rewrites invalid values to the 1.8 equivalent
int face = wrapper.read(Types.UNSIGNED_BYTE);
if (face > 5) {
face = 0;
}
wrapper.write(Types.UNSIGNED_BYTE, (short) face);
});
}
});
@@ -789,8 +768,6 @@ public class PlayerPacketRewriter1_8 extends RewriterBase<Protocol1_8To1_7_6_10>
}
});
// 1.7.10 custom payload constructor (String, ByteBuf) uses byteBuf.array(), so it sends the whole backing array capacity, not only the written bytes
// After reading the proper packet data we discard the remaining bytes
protocol.registerServerbound(ServerboundPackets1_7_2_5.CUSTOM_PAYLOAD, new PacketHandlers() {
@Override
public void register() {
@@ -801,27 +778,7 @@ public class PlayerPacketRewriter1_8 extends RewriterBase<Protocol1_8To1_7_6_10>
switch (channel) {
case "MC|TrSel": {
wrapper.passthrough(Types.INT);
wrapper.read(Types.REMAINING_BYTES); // Discard remaining bytes
break;
}
case "MC|AdvCdm": {
final byte commandBlockType = wrapper.passthrough(Types.BYTE);
if (commandBlockType == 0) { // Block
wrapper.passthrough(Types.INT); // X
wrapper.passthrough(Types.INT); // Y
wrapper.passthrough(Types.INT); // Z
} else if (commandBlockType == 1) { // Minecart
wrapper.passthrough(Types.INT); // Entity id
}
wrapper.passthrough(Types.STRING); // Command
wrapper.write(Types.BOOLEAN, true); // Track output, added in 1.8, default to true
wrapper.read(Types.REMAINING_BYTES); // Discard remaining bytes
break;
}
case "MC|Beacon": {
wrapper.passthrough(Types.INT); // Primary effect
wrapper.passthrough(Types.INT); // Secondary effect
wrapper.read(Types.REMAINING_BYTES); // Discard remaining bytes
wrapper.read(Types.REMAINING_BYTES); // unused data ???
break;
}
case "MC|ItemName": {
@@ -838,28 +795,17 @@ public class PlayerPacketRewriter1_8 extends RewriterBase<Protocol1_8To1_7_6_10>
}
case "MC|BEdit":
case "MC|BSign": {
final boolean signBook = channel.equals("MC|BSign");
final Item book = wrapper.read(RewindTypes.COMPRESSED_NBT_ITEM);
wrapper.read(Types.REMAINING_BYTES); // Discard remaining bytes
if (book == null) {
wrapper.write(Types.ITEM1_8, null);
break;
}
final CompoundTag tag = book.tag();
if (signBook && tag != null && tag.contains("pages")) {
final ListTag<StringTag> pages = tag.getListTag("pages", StringTag.class);
if (pages != null) {
for (int i = 0; i < pages.size(); i++) {
final StringTag page = pages.get(i);
String value = page.getValue();
value = new JsonPrimitive(value).toString();
page.setValue(value);
}
CompoundTag tag = book.tag();
if (tag != null && tag.contains("pages")) {
ListTag<StringTag> pages = tag.getListTag("pages", StringTag.class);
for (int i = 0; i < pages.size(); i++) {
StringTag page = pages.get(i);
String value = page.getValue();
value = ComponentUtil.legacyToJsonString(value);
page.setValue(value);
}
}
protocol.getItemRewriter().handleItemToServer(wrapper.user(), book);
wrapper.write(Types.ITEM1_8, book);
break;
}
@@ -24,6 +24,7 @@ import com.viaversion.viarewind.protocol.v1_8to1_7_6_10.Protocol1_8To1_7_6_10;
import com.viaversion.viarewind.protocol.v1_8to1_7_6_10.data.Particles1_8;
import com.viaversion.viarewind.protocol.v1_8to1_7_6_10.storage.WorldBorderEmulator;
import com.viaversion.viarewind.utils.ChatUtil;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.minecraft.BlockChangeRecord;
import com.viaversion.viaversion.api.minecraft.ClientWorld;
import com.viaversion.viaversion.api.minecraft.chunks.Chunk;
@@ -224,12 +225,7 @@ public class WorldPacketRewriter1_8 extends RewriterBase<Protocol1_8To1_7_6_10>
columnData[i + 3] = data[column + i * columns];
}
final PacketWrapper mapData = PacketWrapper.create(ClientboundPackets1_8.MAP_ITEM_DATA, wrapper.user());
mapData.write(Types.VAR_INT, id); // map id
mapData.write(Types.SHORT, (short) columnData.length); // data length
mapData.write(new FixedByteArrayType(columnData.length), columnData); // data
mapData.send(Protocol1_8To1_7_6_10.class);
sendMapItemData(wrapper.user(), id, columnData);
}
}
@@ -242,12 +238,7 @@ public class WorldPacketRewriter1_8 extends RewriterBase<Protocol1_8To1_7_6_10>
iconData[i * 3 + 3] = icons[i * 4 + 2];
}
final PacketWrapper mapData = PacketWrapper.create(ClientboundPackets1_8.MAP_ITEM_DATA, wrapper.user());
mapData.write(Types.VAR_INT, id); // map id
mapData.write(Types.SHORT, (short) iconData.length); // data length
mapData.write(new FixedByteArrayType(iconData.length), iconData); // data
mapData.send(Protocol1_8To1_7_6_10.class);
sendMapItemData(wrapper.user(), id, iconData);
}
// Update scale
@@ -259,35 +250,55 @@ public class WorldPacketRewriter1_8 extends RewriterBase<Protocol1_8To1_7_6_10>
mapData.send(Protocol1_8To1_7_6_10.class);
});
protocol.registerClientbound(ClientboundPackets1_8.BLOCK_ENTITY_DATA, new PacketHandlers() {
@Override
public void register() {
map(Types.BLOCK_POSITION1_8, RewindTypes.SHORT_POSITION); // position
map(Types.UNSIGNED_BYTE); // action
map(Types.NAMED_COMPOUND_TAG, RewindTypes.COMPRESSED_NBT); // nbt
}
protocol.registerClientbound(ClientboundPackets1_8.BLOCK_ENTITY_DATA, wrapper -> {
wrapper.passthroughAndMap(Types.BLOCK_POSITION1_8, RewindTypes.SHORT_POSITION); // Position
wrapper.passthrough(Types.UNSIGNED_BYTE); // Action
wrapper.passthroughAndMap(Types.NAMED_COMPOUND_TAG, RewindTypes.COMPRESSED_NBT); // Tag
});
protocol.cancelClientbound(ClientboundPackets1_8.CHANGE_DIFFICULTY);
protocol.registerClientbound(ClientboundPackets1_8.SET_BORDER, null, wrapper -> {
final WorldBorderEmulator emulator = wrapper.user().get(WorldBorderEmulator.class);
wrapper.cancel();
final int action = wrapper.read(Types.VAR_INT);
if (action == 3) { // initialize
final double x = wrapper.read(Types.DOUBLE);
final double z = wrapper.read(Types.DOUBLE);
final double oldRadius = wrapper.read(Types.DOUBLE);
final double newRadius = wrapper.read(Types.DOUBLE);
final long speed = wrapper.read(Types.VAR_LONG);
wrapper.user().put(new WorldBorderEmulator(wrapper.user(), x, z, oldRadius, newRadius, speed));
}
final WorldBorderEmulator emulator = wrapper.user().get(WorldBorderEmulator.class);
if (emulator == null) {
return;
}
if (action == 0) { // set size
emulator.setSize(wrapper.read(Types.DOUBLE)); // radius
} else if (action == 1) { // lerp size
emulator.lerpSize(wrapper.read(Types.DOUBLE), wrapper.read(Types.DOUBLE), wrapper.read(Types.VAR_LONG)); // old radius, new radius, speed
final double radius = wrapper.read(Types.DOUBLE);
emulator.setSize(radius);
} else if (action == 1) { // delta size
final double oldRadius = wrapper.read(Types.DOUBLE);
final double newRadius = wrapper.read(Types.DOUBLE);
final long speed = wrapper.read(Types.VAR_LONG);
emulator.updateDeltaTime(oldRadius, newRadius, speed);
} else if (action == 2) { // set center
emulator.setCenter(wrapper.read(Types.DOUBLE), wrapper.read(Types.DOUBLE)); // x, z
} else if (action == 3) { // initialize
emulator.init(
wrapper.read(Types.DOUBLE), wrapper.read(Types.DOUBLE), // x, z
wrapper.read(Types.DOUBLE), wrapper.read(Types.DOUBLE), // old radius, new radius
wrapper.read(Types.VAR_LONG) // speed
);
final double x = wrapper.read(Types.DOUBLE);
final double z = wrapper.read(Types.DOUBLE);
emulator.setCenter(x, z);
}
});
}
private void sendMapItemData(final UserConnection connection, final int id, final byte[] columnData) {
final PacketWrapper mapData = PacketWrapper.create(ClientboundPackets1_8.MAP_ITEM_DATA, connection);
mapData.write(Types.VAR_INT, id); // map id
mapData.write(Types.SHORT, (short) columnData.length); // data length
mapData.write(new FixedByteArrayType(columnData.length), columnData); // data
mapData.send(Protocol1_8To1_7_6_10.class);
}
}
@@ -222,16 +222,17 @@ public class EntityTracker1_8 extends EntityTrackerBase {
public void checkNametagVisbility(final String username) {
final GameProfileStorage profileStorage = user().get(GameProfileStorage.class);
final List<GameProfileStorage.GameProfile> profiles = profileStorage.get(username, false);
for (GameProfileStorage.GameProfile profile : profiles) {
final int entityId = getPlayerEntityId(profile.uuid);
if (entityId == -1) {
return;
}
checkNametagVisibility(entityId);
final GameProfileStorage.GameProfile profile = profileStorage.get(username, false);
if (profile == null) {
return;
}
final int entityId = getPlayerEntityId(profile.uuid);
if (entityId == -1) {
return;
}
checkNametagVisibility(entityId);
}
private boolean isPlayerNametagHidden(final int entityId) {
@@ -17,10 +17,6 @@
*/
package com.viaversion.viarewind.protocol.v1_8to1_7_6_10.storage;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.ListMultimap;
import com.google.common.collect.Multimap;
import com.viaversion.nbt.tag.CompoundTag;
import com.viaversion.nbt.tag.ListTag;
import com.viaversion.nbt.tag.StringTag;
@@ -38,7 +34,6 @@ import java.util.UUID;
public class GameProfileStorage extends StoredObject {
private final Map<UUID, GameProfile> properties = new HashMap<>();
private final ListMultimap<String, GameProfile> nameToProfile = ArrayListMultimap.create();
public GameProfileStorage(UserConnection user) {
super(user);
@@ -47,7 +42,6 @@ public class GameProfileStorage extends StoredObject {
public GameProfile put(UUID uuid, String name, String displayName, int ping, int gamemode) {
GameProfile gameProfile = new GameProfile(uuid, name, displayName, ping, gamemode);
properties.put(uuid, gameProfile);
nameToProfile.put(name, gameProfile);
return gameProfile;
}
@@ -55,9 +49,19 @@ public class GameProfileStorage extends StoredObject {
return properties.get(uuid);
}
public List<GameProfile> get(String name, boolean ignoreCase) {
public GameProfile get(String name, boolean ignoreCase) {
if (ignoreCase) name = name.toLowerCase();
return nameToProfile.get(name);
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) {
@@ -77,11 +81,7 @@ public class GameProfileStorage extends StoredObject {
}
public GameProfile remove(UUID uuid) {
GameProfile removedProfile = properties.remove(uuid);
if (removedProfile != null) {
nameToProfile.get(removedProfile.name).remove(removedProfile);
}
return removedProfile;
return properties.remove(uuid);
}
@@ -30,7 +30,8 @@ import java.util.List;
import java.util.Map;
import java.util.Optional;
public class ScoreboardTracker extends StoredObject {
public final class ScoreboardTracker 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<>();
@@ -40,76 +41,74 @@ public class ScoreboardTracker extends StoredObject {
private final HashMap<String, String> teamNameTagVisibilities = new HashMap<>();
private String colorIndependentSidebar;
public ScoreboardTracker(UserConnection user) {
public ScoreboardTracker(final UserConnection user) {
super(user);
}
public void addPlayerToTeam(String player, String team) {
public void addPlayerToTeam(final String player, final String team) {
teams.computeIfAbsent(team, key -> new ArrayList<>()).add(player);
}
public void setTeamColor(String team, Byte color) {
public void setTeamColor(final String team, final Byte color) {
teamColors.put(team, color);
}
public Optional<Byte> getTeamColor(String team) {
public Optional<Byte> getTeamColor(final String team) {
return Optional.ofNullable(teamColors.get(team));
}
public void addTeam(String team) {
public void addTeam(final String team) {
teams.computeIfAbsent(team, key -> new ArrayList<>());
}
public void removeTeam(String team) {
public void removeTeam(final String team) {
teams.remove(team);
scoreTeams.remove(team);
teamColors.remove(team);
teamNameTagVisibilities.remove(team);
}
public boolean teamExists(String team) {
public boolean teamExists(final 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);
final 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);
public boolean isPlayerInTeam(final String player, final String team) {
final 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(final String player) {
final Optional<String> team = getTeam(player);
return team.flatMap(this::getTeamColor);
}
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))
public Optional<String> getTeam(final 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 setTeamNameTagVisibility(String team, String visibility) {
public void setTeamNameTagVisibility(final String team, final String visibility) {
teamNameTagVisibilities.put(team, visibility);
}
public String getTeamNameTagVisibility(String team) {
public String getTeamNameTagVisibility(final String team) {
return teamNameTagVisibilities.getOrDefault(team, "always");
}
public boolean isNametagHidden(String username) {
for (Map.Entry<String, List<String>> entry : teams.entrySet()) {
public boolean isNametagHidden(final String username) {
for (final Map.Entry<String, List<String>> entry : teams.entrySet()) {
if (entry.getValue().contains(username)) {
return "never".equalsIgnoreCase(teamNameTagVisibilities.getOrDefault(entry.getKey(), "always"));
}
@@ -117,15 +116,15 @@ public class ScoreboardTracker extends StoredObject {
return false;
}
public List<String> getTeamMembers(String team) {
public List<String> getTeamMembers(final String team) {
return teams.getOrDefault(team, new ArrayList<>());
}
public void addObjective(String name) {
public void addObjective(final String name) {
objectives.add(name);
}
public void removeObjective(String name) {
public void removeObjective(final String name) {
objectives.remove(name);
colorDependentSidebar.values().remove(name);
if (name.equals(colorIndependentSidebar)) {
@@ -133,58 +132,63 @@ public class ScoreboardTracker extends StoredObject {
}
}
public boolean objectiveExists(String name) {
public boolean objectiveExists(final 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;
// Find the longest window score[i, i+l) that:
// - is not already claimed as a team name
// - keeps prefix (score[0,i)) at most 16 chars i <= 16
// - keeps suffix (score[i+l, end)) at most 16 chars score.length()-l-i <= 16
for (int l = 16; l >= 1; l--) {
final int iMax = Math.min(16, score.length() - l);
final int iMin = Math.max(0, score.length() - l - 16);
for (int i = iMax; i >= iMin; i--) {
final String name = score.substring(i, i + l);
if (scoreTeamNames.contains(name) || teams.containsKey(name)) {
continue;
}
final String prefix = score.substring(0, i);
final String suffix = i + l >= score.length() ? "" : score.substring(i + l);
final ScoreTeam scoreTeam = new ScoreTeam(name, prefix, suffix);
scoreTeams.put(score, scoreTeam);
scoreTeamNames.add(name);
final PacketWrapper teamPacket = PacketWrapper.create(ClientboundPackets1_7_2_5.SET_PLAYER_TEAM, getUser());
teamPacket.write(Types.STRING, name);
teamPacket.write(Types.BYTE, (byte) 0);
teamPacket.write(Types.STRING, "ViaRewind");
teamPacket.write(Types.STRING, prefix);
teamPacket.write(Types.STRING, suffix);
teamPacket.write(Types.BYTE, (byte) 0);
teamPacket.write(Types.SHORT, (short) 1);
teamPacket.write(Types.STRING, name);
teamPacket.send(Protocol1_8To1_7_6_10.class);
return name;
}
public String sendTeamForScore(final String score) {
if (score.length() <= 16) {
return score;
}
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);
}
final String prefix = score.substring(0, i);
final String suffix = i + l >= score.length() ? "" : score.substring(i + l);
final ScoreTeam scoreTeam = new ScoreTeam(name, prefix, suffix);
scoreTeams.put(score, scoreTeam);
scoreTeamNames.add(name);
PacketWrapper teamPacket = PacketWrapper.create(ClientboundPackets1_7_2_5.SET_PLAYER_TEAM, user());
teamPacket.write(Types.STRING, name);
teamPacket.write(Types.BYTE, (byte) 0);
teamPacket.write(Types.STRING, "ViaRewind");
teamPacket.write(Types.STRING, prefix);
teamPacket.write(Types.STRING, suffix);
teamPacket.write(Types.BYTE, (byte) 0);
teamPacket.write(Types.SHORT, (short) 1);
teamPacket.write(Types.STRING, name);
teamPacket.send(Protocol1_8To1_7_6_10.class);
return name;
}
public String removeTeamForScore(String score) {
ScoreTeam scoreTeam = scoreTeams.remove(score);
if (scoreTeam == null) return score;
public String removeTeamForScore(final String score) {
final ScoreTeam scoreTeam = scoreTeams.remove(score);
if (scoreTeam == null) {
return score;
}
scoreTeamNames.remove(scoreTeam.name);
PacketWrapper teamPacket = PacketWrapper.create(ClientboundPackets1_7_2_5.SET_PLAYER_TEAM, getUser());
final PacketWrapper teamPacket = PacketWrapper.create(ClientboundPackets1_7_2_5.SET_PLAYER_TEAM, user());
teamPacket.write(Types.STRING, scoreTeam.name);
teamPacket.write(Types.BYTE, (byte) 1);
teamPacket.send(Protocol1_8To1_7_6_10.class);
@@ -196,7 +200,7 @@ public class ScoreboardTracker extends StoredObject {
return this.colorIndependentSidebar;
}
public void setColorIndependentSidebar(String colorIndependentSidebar) {
public void setColorIndependentSidebar(final String colorIndependentSidebar) {
this.colorIndependentSidebar = colorIndependentSidebar;
}
@@ -204,15 +208,6 @@ public class ScoreboardTracker extends StoredObject {
return this.colorDependentSidebar;
}
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;
}
private record ScoreTeam(String name, String prefix, String suffix) {
}
}
@@ -19,63 +19,54 @@ package com.viaversion.viarewind.protocol.v1_8to1_7_6_10.storage;
import com.viaversion.viaversion.api.connection.StoredObject;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.util.MathUtil;
public final class WorldBorderEmulator extends StoredObject {
public class WorldBorderEmulator extends StoredObject {
private double x, z;
private double oldDiameter, newDiameter;
private long lerpTime;
private long lerpStartTime;
private long deltaTime;
private long deltaStartTime;
private boolean init = false;
public WorldBorderEmulator(UserConnection user) {
public WorldBorderEmulator(UserConnection user, final double x, final double z, final double oldDiameter, final double newDiameter, final long deltaTime) {
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;
this.deltaTime = deltaTime;
}
public void setCenter(double x, double z) {
public void setCenter(final double x, final double z) {
this.x = x;
this.z = z;
}
public void lerpSize(double oldDiameter, double newDiameter, long lerpTime) {
public void updateDeltaTime(final double oldDiameter, final double newDiameter, final long deltaTime) {
this.oldDiameter = oldDiameter;
this.newDiameter = newDiameter;
this.lerpTime = lerpTime;
this.lerpStartTime = System.currentTimeMillis();
this.deltaTime = deltaTime;
this.deltaStartTime = System.currentTimeMillis();
}
public double getSize() {
if (lerpTime == 0) {
if (deltaTime == 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;
final double percent = ((double) (System.currentTimeMillis() - deltaStartTime) / (double) (deltaTime));
return oldDiameter + (newDiameter - oldDiameter) * MathUtil.clamp(percent, 0D, 1D);
}
public void setSize(double size) {
public void setSize(final double size) {
this.oldDiameter = size;
this.newDiameter = size;
this.lerpTime = 0;
this.deltaTime = 0;
}
public double getX() {
@@ -86,10 +77,6 @@ public class WorldBorderEmulator extends StoredObject {
return z;
}
public boolean isInit() {
return init;
}
public enum Side {
NORTH(0, -1),
EAST(1, 0),
@@ -105,3 +92,4 @@ public class WorldBorderEmulator extends StoredObject {
}
}
}
@@ -35,9 +35,6 @@ public class WorldBorderUpdateTask implements Runnable {
public void run() {
for (UserConnection connection : Via.getManager().getConnectionManager().getConnections()) {
final WorldBorderEmulator worldBorderEmulatorTracker = connection.get(WorldBorderEmulator.class);
if (worldBorderEmulatorTracker == null) {
continue;
}
if (!worldBorderEmulatorTracker.isInit()) continue;
final PlayerSessionStorage playerSession = connection.get(PlayerSessionStorage.class);
@@ -19,7 +19,6 @@ package com.viaversion.viarewind.protocol.v1_9to1_8.rewriter;
import com.viaversion.nbt.tag.ByteTag;
import com.viaversion.nbt.tag.CompoundTag;
import com.viaversion.nbt.tag.IntTag;
import com.viaversion.nbt.tag.ListTag;
import com.viaversion.nbt.tag.StringTag;
import com.viaversion.nbt.tag.Tag;
@@ -195,7 +194,6 @@ public class BlockItemPacketRewriter1_9 extends VRBlockItemRewriter<ClientboundP
@Override
public Item handleItemToClient(UserConnection connection, Item item) {
if (item == null) return null;
final int originalId = item.identifier();
super.handleItemToClient(connection, item);
CompoundTag tag = item.tag();
@@ -282,32 +280,6 @@ public class BlockItemPacketRewriter1_9 extends VRBlockItemRewriter<ClientboundP
});
}
// Colors the fake leather armor for an elytra gray
if (originalId == 443) {
if (tag == null) {
item.setTag(tag = new CompoundTag());
}
CompoundTag display = tag.getCompoundTag("display");
if (display == null) {
tag.put("display", display = new CompoundTag());
}
display.put("color", new IntTag(0x737373)); // Gray
tag.put(nbtTagName() + "|noDisplay", new ByteTag(true));
}
// Makes the fake banner for a shield brown if it has no banner patterns
if (originalId == 442) {
final CompoundTag blockEntityTag = tag == null ? null : tag.getCompoundTag("BlockEntityTag");
final ListTag<CompoundTag> patterns = blockEntityTag == null ? null : blockEntityTag.getListTag("Patterns", CompoundTag.class);
if (patterns == null || patterns.isEmpty()) {
item.setData((short) 3); // Brown
if (tag == null) {
item.setTag(tag = new CompoundTag());
}
tag.put(nbtTagName() + "|noData", new ByteTag(true));
}
}
return item;
}
@@ -350,9 +322,6 @@ public class BlockItemPacketRewriter1_9 extends VRBlockItemRewriter<ClientboundP
if (tag == null) {
return item;
}
if (tag.remove(nbtTagName() + "|noData") != null) {
item.setData((short) 0);
}
final Tag noDisplayTag = tag.remove(nbtTagName() + "|noDisplay");
if (noDisplayTag != null) {
tag.remove("display");
@@ -52,11 +52,11 @@ public class WindowTracker extends StoredObject {
openWindow.write(Types.UNSIGNED_BYTE, windowId);
openWindow.write(Types.STRING, "minecraft:brewing_stand");
TextComponent title = new StringComponent()
.append(new TranslationComponent("container.brewing"))
.append(new StringComponent(": ").formatted(TextFormatting.DARK_GRAY))
.append(new StringComponent(amount + " ").formatted(TextFormatting.DARK_RED))
.append(new TranslationComponent("item.blazePowder.name").formatted(TextFormatting.DARK_RED));
TextComponent title = new StringComponent().
append(new TranslationComponent("container.brewing")).
append(new StringComponent(": " + TextFormatting.DARK_GRAY)).
append(new StringComponent(amount + " " + TextFormatting.DARK_RED)).
append(new TranslationComponent("item.blazePowder.name", TextFormatting.DARK_RED));
openWindow.write(Types.COMPONENT, TextComponentSerializer.V1_8.serializeJson(title));
openWindow.write(Types.UNSIGNED_BYTE, (short) 420);
@@ -26,11 +26,7 @@ public class CooldownIndicatorTask implements Runnable {
@Override
public void run() {
for (UserConnection connection : Via.getManager().getConnectionManager().getConnections()) {
final CooldownStorage cooldown = connection.get(CooldownStorage.class);
if (cooldown == null) {
continue;
}
cooldown.tick(connection);
connection.get(CooldownStorage.class).tick(connection);
}
}
}
@@ -36,9 +36,6 @@ public class LevitationUpdateTask implements Runnable {
}
for (UserConnection connection : Via.getManager().getConnectionManager().getConnections()) {
final LevitationStorage levitation = connection.get(LevitationStorage.class);
if (levitation == null) {
continue;
}
if (!levitation.isActive()) {
continue;
}
+3 -3
View File
@@ -7,7 +7,7 @@ org.gradle.configuration-cache=true
project_jvm_version=17
project_group=com.viaversion
project_version=4.1.2
project_version=4.1.0-SNAPSHOT
project_description=ViaVersion addon to allow 1.8.x and 1.7.x clients on newer server versions.
publishing_dev_id=florianreuth
@@ -15,6 +15,6 @@ publishing_dev_name=Florian Reuth
publishing_dev_mail=git@florianreuth.de
# Modrinth/Hangar Publishing
minecraft_versions=26.2, 26.1.2, 26.1.1, 26.1, 1.21.11, 1.21.10, 1.21.9, 1.21.8, 1.21.7, 1.21.6, 1.21.5, 1.21.4, 1.21.3, 1.21.2, 1.21.1, 1.21, 1.20.6, 1.20.5, 1.20.4, 1.20.3, 1.20.2, 1.20.1, 1.20, 1.19.4, 1.19.3, 1.19.2, 1.19.1, 1.19, 1.18.2, 1.18.1, 1.18, 1.17.1, 1.17, 1.16.5, 1.16.4, 1.16.3, 1.16.2, 1.16.1, 1.16, 1.15.2, 1.15.1, 1.15, 1.14.4, 1.14.3, 1.14.2, 1.14.1, 1.14, 1.13.2, 1.13.1, 1.13, 1.12.2, 1.12.1, 1.12, 1.11.2, 1.11.1, 1.11, 1.10.2, 1.10.1, 1.10, 1.9.4, 1.9.3, 1.9.2, 1.9.1, 1.9, 1.8.9, 1.8.8
minecraft_version_range=1.8-26.2
minecraft_versions=26.1.2, 26.1.1, 26.1, 1.21.11, 1.21.10, 1.21.9, 1.21.8, 1.21.7, 1.21.6, 1.21.5, 1.21.4, 1.21.3, 1.21.2, 1.21.1, 1.21, 1.20.6, 1.20.5, 1.20.4, 1.20.3, 1.20.2, 1.20.1, 1.20, 1.19.4, 1.19.3, 1.19.2, 1.19.1, 1.19, 1.18.2, 1.18.1, 1.18, 1.17.1, 1.17, 1.16.5, 1.16.4, 1.16.3, 1.16.2, 1.16.1, 1.16, 1.15.2, 1.15.1, 1.15, 1.14.4, 1.14.3, 1.14.2, 1.14.1, 1.14, 1.13.2, 1.13.1, 1.13, 1.12.2, 1.12.1, 1.12, 1.11.2, 1.11.1, 1.11, 1.10.2, 1.10.1, 1.10, 1.9.4, 1.9.3, 1.9.2, 1.9.1, 1.9, 1.8.9, 1.8.8
minecraft_version_range=1.8-26.1.2
velocity_version=3.4-3.5
Binary file not shown.
+2 -4
View File
@@ -1,10 +1,8 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionSha256Sum=bafc141b619ad6350fd975fc903156dd5c151998cc8b058e8c1044ab5f7b031f
distributionUrl=https\://services.gradle.org/distributions/gradle-9.5.1-bin.zip
distributionSha256Sum=2ab2958f2a1e51120c326cad6f385153bb11ee93b3c216c5fccebfdfbb7ec6cb
distributionUrl=https\://services.gradle.org/distributions/gradle-9.4.1-bin.zip
networkTimeout=10000
retries=0
retryBackOffMs=500
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
Vendored
+1 -1
View File
@@ -57,7 +57,7 @@
# Darwin, MinGW, and NonStop.
#
# (3) This script is generated from the Groovy template
# https://github.com/gradle/gradle/blob/3d91ce3b8caaf77ad09f381f43615b715b53f72c/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
# https://github.com/gradle/gradle/blob/2d6327017519d23b96af35865dc997fcb544fb40/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
# within the Gradle project.
#
# You can find Gradle at https://github.com/gradle/gradle/.
Vendored
+21 -10
View File
@@ -23,8 +23,8 @@
@rem
@rem ##########################################################################
@rem Set local scope for the variables, and ensure extensions are enabled
setlocal EnableExtensions
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0
if "%DIRNAME%"=="" set DIRNAME=.
@@ -51,7 +51,7 @@ echo. 1>&2
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
echo location of your Java installation. 1>&2
"%COMSPEC%" /c exit 1
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
@@ -65,7 +65,7 @@ echo. 1>&2
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
echo location of your Java installation. 1>&2
"%COMSPEC%" /c exit 1
goto fail
:execute
@rem Setup the command line
@@ -73,10 +73,21 @@ echo location of your Java installation. 1>&2
@rem Execute Gradle
@rem endlocal doesn't take effect until after the line is parsed and variables are expanded
@rem which allows us to clear the local environment before executing the java command
endlocal & "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* & call :exitWithErrorLevel
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %*
:exitWithErrorLevel
@rem Use "%COMSPEC%" /c exit to allow operators to work properly in scripts
"%COMSPEC%" /c exit %ERRORLEVEL%
:end
@rem End local scope for the variables with windows NT shell
if %ERRORLEVEL% equ 0 goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
set EXIT_CODE=%ERRORLEVEL%
if %EXIT_CODE% equ 0 set EXIT_CODE=1
if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
exit /b %EXIT_CODE%
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega