Игрок: хитбокс 1.45 в шифте и прыжок с места 1.5

- RsxPlayerTuning: высота при подкрадывании 1.45 (ванилла 1.65), прыжок с
  места 1.5, в движении ванильные 1.25, высота глаз в шифте 1.37.
- RsxPlayer: прыжок по наличию горизонтального ввода, глаза при подкрадывании.
- Патч в EntityPlayer.updateSize: высота при подкрадывании из нашего класса.
- Импульс прыжка считается обратным счетом по физике ваниллы.

AABB: редактор хитбоксов и их отрисовка

- Протокол: Hitbox (имя, зона, min/max, поворот), пакеты Hitboxes,
  HitboxInstances и HitboxesReload.
- Сервер: HitboxRegistry читает JSON-файл (world/hitboxes.json, можно
  указать --hitboxes), перечитывает его по запросу клиента и шлет наборы
  игрокам. Сломанный файл не стирает рабочие коробки, а объясняет причину.
- Клиент: RsxHitboxDebug рисует коробки через RenderGlobal.drawBoundingBox
  с подписями DebugRenderer, красит зоны (голова красная, тело желтое, ноги
  синие). Команды: /rsx hitboxes on|off|reload|list|show NAME.
- Новый модуль rsx-plugin-api с интерфейсом Hitboxes: плагин может
  зарегистрировать свои коробки. У сервера появился скрипт сборки.

Тесты: протокол 34, сервер 80 (было 74). Форк собирается чисто, 3279 классов.
This commit is contained in:
sasheg dev
2026-10-21 22:31:16 +03:00
parent e7e332f4ca
commit 9980c1561d
18 changed files with 1528 additions and 14 deletions
@@ -149,6 +149,15 @@ public final class Packets {
/** The client learns a blueprint. */
public static final int LEARN_BLUEPRINT = 0x29;
/** The boxes of every model the server knows. */
public static final int HITBOXES = 0x2A;
/** The places where those models stand. */
public static final int HITBOX_INSTANCES = 0x2B;
/** The client asks the server to read its box file again. */
public static final int HITBOXES_RELOAD = 0x2C;
/**
* One slot of the inventory and what is in it now.
*
@@ -1372,6 +1381,156 @@ public final class Packets {
}
}
/** The boxes of one model. */
public static final class HitboxModel {
public final String name;
public final Hitbox[] boxes;
public HitboxModel(String name, Hitbox[] boxes) {
this.name = name;
this.boxes = boxes;
}
}
/**
* The boxes of every model the server knows.
*
* The file with the boxes is the editor: it is read by the server, sent
* to the client and drawn there, so that a change in the file can be
* seen without anything else being touched.
*/
public static final class Hitboxes implements Packet {
public final HitboxModel[] models;
public Hitboxes(HitboxModel[] models) {
this.models = models;
}
public Buf write() {
Buf buf = new Buf(256 + this.models.length * 64);
buf.writeVarInt(this.models.length);
for (int i = 0; i < this.models.length; i++) {
HitboxModel model = this.models[i];
buf.writeString(model.name);
buf.writeVarInt(model.boxes.length);
for (int j = 0; j < model.boxes.length; j++) {
Hitbox box = model.boxes[j];
buf.writeString(box.name);
buf.writeString(box.part);
buf.writeFloat(box.minX);
buf.writeFloat(box.minY);
buf.writeFloat(box.minZ);
buf.writeFloat(box.maxX);
buf.writeFloat(box.maxY);
buf.writeFloat(box.maxZ);
buf.writeFloat(box.yaw);
}
}
return buf;
}
public static Hitboxes read(Buf in) {
int count = in.readVarInt();
if (count < 0 || count > 4096) {
throw new ProtocolException("that many box models is not real");
}
HitboxModel[] models = new HitboxModel[count];
for (int i = 0; i < count; i++) {
String name = in.readString(MAX_TEXT);
int boxes = in.readVarInt();
if (boxes < 0 || boxes > 256) {
throw new ProtocolException("that many boxes is not real");
}
Hitbox[] list = new Hitbox[boxes];
for (int j = 0; j < boxes; j++) {
String boxName = in.readString(MAX_TEXT);
String part = in.readString(MAX_TEXT);
list[j] = new Hitbox(boxName, part,
in.readFloat(), in.readFloat(), in.readFloat(),
in.readFloat(), in.readFloat(), in.readFloat(),
in.readFloat());
}
models[i] = new HitboxModel(name, list);
}
return new Hitboxes(models);
}
}
/** One model standing somewhere in the world. */
public static final class HitboxInstance {
public final String model;
public final float x;
public final float y;
public final float z;
public final float yaw;
public HitboxInstance(String model, float x, float y, float z, float yaw) {
this.model = model;
this.x = x;
this.y = y;
this.z = z;
this.yaw = yaw;
}
}
/** Every place where a model with boxes stands. */
public static final class HitboxInstances implements Packet {
public final HitboxInstance[] instances;
public HitboxInstances(HitboxInstance[] instances) {
this.instances = instances;
}
public Buf write() {
Buf buf = new Buf(32 + this.instances.length * 32);
buf.writeVarInt(this.instances.length);
for (int i = 0; i < this.instances.length; i++) {
HitboxInstance instance = this.instances[i];
buf.writeString(instance.model);
buf.writeFloat(instance.x);
buf.writeFloat(instance.y);
buf.writeFloat(instance.z);
buf.writeFloat(instance.yaw);
}
return buf;
}
public static HitboxInstances read(Buf in) {
int count = in.readVarInt();
if (count < 0 || count > 65536) {
throw new ProtocolException("that many box instances is not real");
}
HitboxInstance[] instances = new HitboxInstance[count];
for (int i = 0; i < count; i++) {
String model = in.readString(MAX_TEXT);
instances[i] = new HitboxInstance(model, in.readFloat(), in.readFloat(),
in.readFloat(), in.readFloat());
}
return new HitboxInstances(instances);
}
}
/**
* The client asks the server to read its box file again.
*
* The file is the editor, so after a change the client wants the new
* numbers without the server having to be restarted.
*/
public static final class HitboxesReload implements Packet {
public Buf write() {
return new Buf(4);
}
public static HitboxesReload read(Buf in) {
return new HitboxesReload();
}
}
/**
* Every packet id this build knows, and what it decodes into.
*
@@ -1412,6 +1571,9 @@ public final class Packets {
map.put(Integer.valueOf(CONTAINER_OPEN), "ContainerOpen");
map.put(Integer.valueOf(CONTAINER_TAKE), "ContainerTake");
map.put(Integer.valueOf(LEARN_BLUEPRINT), "LearnBlueprint");
map.put(Integer.valueOf(HITBOXES), "Hitboxes");
map.put(Integer.valueOf(HITBOX_INSTANCES), "HitboxInstances");
map.put(Integer.valueOf(HITBOXES_RELOAD), "HitboxesReload");
map.put(Integer.valueOf(DISCONNECT), "Disconnect");
return map;
}