chore: add ci
This commit is contained in:
parent
ea50e4f4cc
commit
74cccd2a98
106
.github/workflows/ci.yml
vendored
Normal file
106
.github/workflows/ci.yml
vendored
Normal file
@ -0,0 +1,106 @@
|
||||
name: CI
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
- main
|
||||
pull_request:
|
||||
branches:
|
||||
- master
|
||||
- main
|
||||
workflow_dispatch:
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
env:
|
||||
CARGO_TERM_COLOR: always
|
||||
|
||||
jobs:
|
||||
fmt:
|
||||
name: Formatting
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup Rust toolchain
|
||||
uses: dtolnay/rust-toolchain@stable
|
||||
with:
|
||||
components: rustfmt
|
||||
|
||||
- name: Check formatting
|
||||
run: cargo fmt --all --check
|
||||
|
||||
clippy:
|
||||
name: Clippy
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Clone Pumpkin dependency
|
||||
run: git clone --depth 1 https://github.com/Pumpkin-MC/Pumpkin.git ../Pumpkin
|
||||
|
||||
- name: Setup Rust toolchain
|
||||
uses: dtolnay/rust-toolchain@stable
|
||||
with:
|
||||
components: clippy
|
||||
targets: wasm32-wasip2
|
||||
|
||||
- name: Setup Rust cache
|
||||
uses: Swatinem/rust-cache@v2
|
||||
|
||||
- name: Run Clippy (WASM target)
|
||||
run: cargo clippy --target wasm32-wasip2 -- -D warnings
|
||||
|
||||
- name: Run Clippy (Host target)
|
||||
run: cargo clippy --all-targets -- -D warnings
|
||||
|
||||
build:
|
||||
name: Compile & Build
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Clone Pumpkin dependency
|
||||
run: git clone --depth 1 https://github.com/Pumpkin-MC/Pumpkin.git ../Pumpkin
|
||||
|
||||
- name: Setup Rust toolchain
|
||||
uses: dtolnay/rust-toolchain@stable
|
||||
with:
|
||||
targets: wasm32-wasip2
|
||||
|
||||
- name: Setup Rust cache
|
||||
uses: Swatinem/rust-cache@v2
|
||||
|
||||
- name: Check native compilation
|
||||
run: cargo check --all-targets
|
||||
|
||||
- name: Build WASM plugin (debug)
|
||||
run: cargo build --target wasm32-wasip2
|
||||
|
||||
- name: Build WASM plugin (release)
|
||||
run: cargo build --release --target wasm32-wasip2
|
||||
|
||||
test:
|
||||
name: Test
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Clone Pumpkin dependency
|
||||
run: git clone --depth 1 https://github.com/Pumpkin-MC/Pumpkin.git ../Pumpkin
|
||||
|
||||
- name: Setup Rust toolchain
|
||||
uses: dtolnay/rust-toolchain@stable
|
||||
|
||||
- name: Setup Rust cache
|
||||
uses: Swatinem/rust-cache@v2
|
||||
|
||||
- name: Run unit tests
|
||||
run: cargo test --lib --verbose
|
||||
@ -1,6 +1,6 @@
|
||||
use super::util::write_compound_nbt;
|
||||
use crate::remap::block_state_remap::remap_block_state_for_version;
|
||||
use crate::remap::block_entity_type_id_remap::remap_block_entity_type_id_for_version;
|
||||
use crate::remap::block_state_remap::remap_block_state_for_version;
|
||||
const CURRENT_MC_VERSION: JavaMinecraftVersion = JavaMinecraftVersion::V_26_3;
|
||||
use pumpkin_protocol::codec::bit_set::BitSet;
|
||||
use pumpkin_protocol::codec::var_int::VarInt;
|
||||
@ -230,10 +230,7 @@ pub fn write_chunk_data(
|
||||
.position(|&n| n == name)
|
||||
.unwrap_or(0)
|
||||
});
|
||||
let remapped_id =
|
||||
remap_block_entity_type_id_for_version(
|
||||
id as u32, *version,
|
||||
);
|
||||
let remapped_id = remap_block_entity_type_id_for_version(id as u32, *version);
|
||||
|
||||
write.write_var_int(&VarInt(remapped_id as i32))?;
|
||||
|
||||
|
||||
24
src/lib.rs
24
src/lib.rs
@ -5,12 +5,13 @@ pub mod remap;
|
||||
pub mod tag;
|
||||
|
||||
use pumpkin_plugin_api::{
|
||||
Context, Plugin, PluginMetadata, Server,
|
||||
events::{
|
||||
EventHandler, EventPriority,
|
||||
packet::{PacketReceivedEvent, PacketSentEvent},
|
||||
},
|
||||
events_wit::{PacketReceivedEventData, PacketSentEventData},
|
||||
Context, Plugin, PluginMetadata, Server, register_plugin,
|
||||
register_plugin,
|
||||
};
|
||||
|
||||
use crate::packet::translator::{PacketTranslator, from_wasm_java_version};
|
||||
@ -29,7 +30,8 @@ impl Plugin for MultiVersionPlugin {
|
||||
name: "pumpkin-java-multiversion".into(),
|
||||
version: env!("CARGO_PKG_VERSION").into(),
|
||||
authors: vec!["Pumpkin Developer".into()],
|
||||
description: "Multi-version Java Edition protocol translation plugin for Pumpkin.".into(),
|
||||
description: "Multi-version Java Edition protocol translation plugin for Pumpkin."
|
||||
.into(),
|
||||
dependencies: vec![],
|
||||
permissions: vec![],
|
||||
}
|
||||
@ -39,17 +41,9 @@ impl Plugin for MultiVersionPlugin {
|
||||
tracing::info!("Loading Pumpkin Java Multi-Version Plugin...");
|
||||
|
||||
// Register packet event handlers with High priority to translate before/after game logic
|
||||
context.register_event_handler(
|
||||
PacketReceivedHandler,
|
||||
EventPriority::Highest,
|
||||
true,
|
||||
)?;
|
||||
context.register_event_handler(PacketReceivedHandler, EventPriority::Highest, true)?;
|
||||
|
||||
context.register_event_handler(
|
||||
PacketSentHandler,
|
||||
EventPriority::Lowest,
|
||||
true,
|
||||
)?;
|
||||
context.register_event_handler(PacketSentHandler, EventPriority::Lowest, true)?;
|
||||
|
||||
tracing::info!("Pumpkin Java Multi-Version Plugin enabled! Supporting 1.7.2 - 26.3");
|
||||
Ok(())
|
||||
@ -65,7 +59,11 @@ impl Plugin for MultiVersionPlugin {
|
||||
struct PacketReceivedHandler;
|
||||
|
||||
impl EventHandler<PacketReceivedEvent> for PacketReceivedHandler {
|
||||
fn handle(&self, _server: Server, mut event: PacketReceivedEventData) -> PacketReceivedEventData {
|
||||
fn handle(
|
||||
&self,
|
||||
_server: Server,
|
||||
mut event: PacketReceivedEventData,
|
||||
) -> PacketReceivedEventData {
|
||||
if let Some(java_player) = event.player.as_java() {
|
||||
let version = from_wasm_java_version(java_player.get_version());
|
||||
if let Some((new_id, new_payload)) = PacketTranslator::translate_incoming_packet(
|
||||
|
||||
@ -1,13 +1,10 @@
|
||||
use pumpkin_data::entity::EntityType;
|
||||
use pumpkin_protocol::{
|
||||
ClientPacket, MultiVersionJavaPacket, VarInt,
|
||||
java::client::play::CSpawnEntity,
|
||||
ClientPacket, MultiVersionJavaPacket, VarInt, java::client::play::CSpawnEntity,
|
||||
};
|
||||
use pumpkin_util::{math::position::BlockPos, version::JavaMinecraftVersion};
|
||||
|
||||
use crate::packet::legacy::{
|
||||
CSpawnLivingEntity, CSpawnPainting,
|
||||
};
|
||||
use crate::packet::legacy::{CSpawnLivingEntity, CSpawnPainting};
|
||||
use crate::packet::mappings::{self, PacketId};
|
||||
use crate::remap::{
|
||||
self, block_state_remap::remap_block_state_for_version,
|
||||
@ -77,9 +74,7 @@ pub const fn from_wasm_java_version(
|
||||
}
|
||||
}
|
||||
|
||||
pub static SERVERBOUND_HANDSHAKE: &[&PacketId] = &[
|
||||
&mappings::serverbound::handshake::INTENTION,
|
||||
];
|
||||
pub static SERVERBOUND_HANDSHAKE: &[&PacketId] = &[&mappings::serverbound::handshake::INTENTION];
|
||||
|
||||
pub static SERVERBOUND_STATUS: &[&PacketId] = &[
|
||||
&mappings::serverbound::status::PING_REQUEST,
|
||||
@ -406,7 +401,10 @@ pub struct PacketTranslator;
|
||||
impl PacketTranslator {
|
||||
/// Translates an incoming serverbound packet ID from a specific client version into the 26.3 packet ID.
|
||||
#[must_use]
|
||||
pub fn translate_serverbound_packet_id(packet_id: i32, version: JavaMinecraftVersion) -> Option<i32> {
|
||||
pub fn translate_serverbound_packet_id(
|
||||
packet_id: i32,
|
||||
version: JavaMinecraftVersion,
|
||||
) -> Option<i32> {
|
||||
if version == JavaMinecraftVersion::V_26_3 {
|
||||
return Some(packet_id);
|
||||
}
|
||||
@ -440,7 +438,10 @@ impl PacketTranslator {
|
||||
|
||||
/// Translates an outgoing 26.3 clientbound packet ID into the target client version packet ID.
|
||||
#[must_use]
|
||||
pub fn translate_clientbound_packet_id(packet_id_26_3: i32, version: JavaMinecraftVersion) -> Option<i32> {
|
||||
pub fn translate_clientbound_packet_id(
|
||||
packet_id_26_3: i32,
|
||||
version: JavaMinecraftVersion,
|
||||
) -> Option<i32> {
|
||||
if version == JavaMinecraftVersion::V_26_3 {
|
||||
return Some(packet_id_26_3);
|
||||
}
|
||||
@ -530,7 +531,8 @@ impl PacketTranslator {
|
||||
/// Translates a custom stat ID from 26.3 to the client's version.
|
||||
#[must_use]
|
||||
pub fn translate_custom_stat_id(stat_id: u16, version: JavaMinecraftVersion) -> u16 {
|
||||
remap::custom_stat_id_remap::remap_custom_stat_id_for_version(u32::from(stat_id), version) as u16
|
||||
remap::custom_stat_id_remap::remap_custom_stat_id_for_version(u32::from(stat_id), version)
|
||||
as u16
|
||||
}
|
||||
|
||||
/// Translates a painting variant ID from 26.3 to the client's version.
|
||||
@ -570,7 +572,9 @@ impl PacketTranslator {
|
||||
}
|
||||
|
||||
// 2. ACCEPT_TELEPORTATION (< 26.3 only sent teleport_id: VarInt)
|
||||
if new_id == mappings::serverbound::play::ACCEPT_TELEPORTATION.v26_3 && version < JavaMinecraftVersion::V_26_3 {
|
||||
if new_id == mappings::serverbound::play::ACCEPT_TELEPORTATION.v26_3
|
||||
&& version < JavaMinecraftVersion::V_26_3
|
||||
{
|
||||
let teleport_id = payload.get_var_int().ok()?;
|
||||
let mut out = Vec::new();
|
||||
let _ = out.write_var_int(&teleport_id);
|
||||
@ -583,7 +587,9 @@ impl PacketTranslator {
|
||||
}
|
||||
|
||||
// 3. USE_ITEM (< 1.21 sequence / yaw / pitch missing)
|
||||
if new_id == mappings::serverbound::play::USE_ITEM.v26_3 && version < JavaMinecraftVersion::V_1_21 {
|
||||
if new_id == mappings::serverbound::play::USE_ITEM.v26_3
|
||||
&& version < JavaMinecraftVersion::V_1_21
|
||||
{
|
||||
let hand = payload.get_var_int().ok()?;
|
||||
let sequence = if version >= JavaMinecraftVersion::V_1_19 {
|
||||
payload.get_var_int().unwrap_or(VarInt(0))
|
||||
@ -599,7 +605,9 @@ impl PacketTranslator {
|
||||
}
|
||||
|
||||
// 4. SIGN_UPDATE (< 26.3 is_front_text was bool before lines or missing in < 1.20)
|
||||
if new_id == mappings::serverbound::play::SIGN_UPDATE.v26_3 && version < JavaMinecraftVersion::V_26_3 {
|
||||
if new_id == mappings::serverbound::play::SIGN_UPDATE.v26_3
|
||||
&& version < JavaMinecraftVersion::V_26_3
|
||||
{
|
||||
let pos_val = payload.get_i64_be().ok()?;
|
||||
let is_front = if version >= JavaMinecraftVersion::V_1_20 {
|
||||
payload.get_bool().unwrap_or(true)
|
||||
@ -621,7 +629,9 @@ impl PacketTranslator {
|
||||
}
|
||||
|
||||
// 5. PLAYER_ACTION (< 26.3 status shifted by 1, < 1.19 sequence missing)
|
||||
if new_id == mappings::serverbound::play::PLAYER_ACTION.v26_3 && version < JavaMinecraftVersion::V_26_3 {
|
||||
if new_id == mappings::serverbound::play::PLAYER_ACTION.v26_3
|
||||
&& version < JavaMinecraftVersion::V_26_3
|
||||
{
|
||||
let status = if version >= JavaMinecraftVersion::V_1_9 {
|
||||
payload.get_var_int().ok()?
|
||||
} else {
|
||||
@ -648,7 +658,9 @@ impl PacketTranslator {
|
||||
}
|
||||
|
||||
// 6. PLAYER_COMMAND (< 1.21.6 action 0/1 were sneak)
|
||||
if new_id == mappings::serverbound::play::PLAYER_COMMAND.v26_3 && version < JavaMinecraftVersion::V_1_21_6 {
|
||||
if new_id == mappings::serverbound::play::PLAYER_COMMAND.v26_3
|
||||
&& version < JavaMinecraftVersion::V_1_21_6
|
||||
{
|
||||
let entity_id = if version >= JavaMinecraftVersion::V_1_8 {
|
||||
payload.get_var_int().ok()?
|
||||
} else {
|
||||
@ -692,7 +704,9 @@ impl PacketTranslator {
|
||||
}
|
||||
|
||||
// 8. HELLO / LOGIN_START (< 1.20.2 missing UUID)
|
||||
if new_id == mappings::serverbound::login::HELLO.v26_3 && version < JavaMinecraftVersion::V_1_20_2 {
|
||||
if new_id == mappings::serverbound::login::HELLO.v26_3
|
||||
&& version < JavaMinecraftVersion::V_1_20_2
|
||||
{
|
||||
let name = payload.get_str_borrowed().ok()?;
|
||||
let offline_uuid = uuid::Uuid::new_v3(
|
||||
&uuid::Uuid::nil(),
|
||||
@ -705,7 +719,9 @@ impl PacketTranslator {
|
||||
}
|
||||
|
||||
// 9. CHANGE_DIFFICULTY (< 1.21.6 was u8, now VarInt)
|
||||
if new_id == mappings::serverbound::play::CHANGE_DIFFICULTY.v26_3 && version < JavaMinecraftVersion::V_1_21_6 {
|
||||
if new_id == mappings::serverbound::play::CHANGE_DIFFICULTY.v26_3
|
||||
&& version < JavaMinecraftVersion::V_1_21_6
|
||||
{
|
||||
let diff = payload.get_u8().ok()?;
|
||||
let mut out = Vec::new();
|
||||
let _ = out.write_var_int(&VarInt(i32::from(diff)));
|
||||
@ -713,23 +729,39 @@ impl PacketTranslator {
|
||||
}
|
||||
|
||||
// 10. PLAYER_INPUT (< 1.21.2 was floats + bools, now i8 bitmask)
|
||||
if new_id == mappings::serverbound::play::PLAYER_INPUT.v26_3 && version < JavaMinecraftVersion::V_1_21_2 {
|
||||
if new_id == mappings::serverbound::play::PLAYER_INPUT.v26_3
|
||||
&& version < JavaMinecraftVersion::V_1_21_2
|
||||
{
|
||||
let sideways = payload.get_f32_be().unwrap_or(0.0);
|
||||
let forward = payload.get_f32_be().unwrap_or(0.0);
|
||||
let jumping = payload.get_bool().unwrap_or(false);
|
||||
let sneaking = payload.get_bool().unwrap_or(false);
|
||||
let mut input: i8 = 0;
|
||||
if forward > 0.0 { input |= 1; } else if forward < 0.0 { input |= 2; }
|
||||
if sideways > 0.0 { input |= 4; } else if sideways < 0.0 { input |= 8; }
|
||||
if jumping { input |= 16; }
|
||||
if sneaking { input |= 32; }
|
||||
if forward > 0.0 {
|
||||
input |= 1;
|
||||
} else if forward < 0.0 {
|
||||
input |= 2;
|
||||
}
|
||||
if sideways > 0.0 {
|
||||
input |= 4;
|
||||
} else if sideways < 0.0 {
|
||||
input |= 8;
|
||||
}
|
||||
if jumping {
|
||||
input |= 16;
|
||||
}
|
||||
if sneaking {
|
||||
input |= 32;
|
||||
}
|
||||
let mut out = Vec::new();
|
||||
let _ = out.write_i8(input);
|
||||
return Some(out);
|
||||
}
|
||||
|
||||
// 11. MOVE_VEHICLE (< 1.21.4 missing on_ground bool)
|
||||
if new_id == mappings::serverbound::play::MOVE_VEHICLE.v26_3 && version < JavaMinecraftVersion::V_1_21_4 {
|
||||
if new_id == mappings::serverbound::play::MOVE_VEHICLE.v26_3
|
||||
&& version < JavaMinecraftVersion::V_1_21_4
|
||||
{
|
||||
let x = payload.get_f64_be().ok()?;
|
||||
let y = payload.get_f64_be().ok()?;
|
||||
let z = payload.get_f64_be().ok()?;
|
||||
@ -746,7 +778,9 @@ impl PacketTranslator {
|
||||
}
|
||||
|
||||
// 12. CONTAINER_BUTTON_CLICK (< 1.21.2 button was i8)
|
||||
if new_id == mappings::serverbound::play::CONTAINER_BUTTON_CLICK.v26_3 && version < JavaMinecraftVersion::V_1_21_2 {
|
||||
if new_id == mappings::serverbound::play::CONTAINER_BUTTON_CLICK.v26_3
|
||||
&& version < JavaMinecraftVersion::V_1_21_2
|
||||
{
|
||||
let window_id = payload.get_u8().ok()?;
|
||||
let button_id = payload.get_i8().ok()?;
|
||||
let mut out = Vec::new();
|
||||
@ -774,12 +808,16 @@ impl PacketTranslator {
|
||||
}
|
||||
|
||||
// Check for CSpawnEntity (ADD_ENTITY) in 26.3
|
||||
if packet_id == mappings::clientbound::play::ADD_ENTITY.v26_3 {
|
||||
if let Ok(spawn_entity) = CSpawnEntity::read_packet_data(raw_payload, &JavaMinecraftVersion::V_26_3) {
|
||||
if packet_id == mappings::clientbound::play::ADD_ENTITY.v26_3
|
||||
&& let Ok(spawn_entity) =
|
||||
CSpawnEntity::read_packet_data(raw_payload, &JavaMinecraftVersion::V_26_3)
|
||||
{
|
||||
let entity_type_id = spawn_entity.r#type.0 as u16;
|
||||
|
||||
// 1. Check if entity is a Painting in <= 1.18.2
|
||||
if version <= JavaMinecraftVersion::V_1_18_2 && entity_type_id == EntityType::PAINTING.id {
|
||||
if version <= JavaMinecraftVersion::V_1_18_2
|
||||
&& entity_type_id == EntityType::PAINTING.id
|
||||
{
|
||||
let painting = CSpawnPainting::new(
|
||||
spawn_entity.entity_id,
|
||||
spawn_entity.entity_uuid,
|
||||
@ -801,7 +839,7 @@ impl PacketTranslator {
|
||||
|
||||
// 2. Check if entity is a living mob in < 1.19
|
||||
if version < JavaMinecraftVersion::V_1_19 {
|
||||
let is_mob = EntityType::from_raw(entity_type_id).map_or(false, |e| e.mob);
|
||||
let is_mob = EntityType::from_raw(entity_type_id).is_some_and(|e| e.mob);
|
||||
if is_mob {
|
||||
let living = CSpawnLivingEntity::new(
|
||||
spawn_entity.entity_id,
|
||||
@ -824,9 +862,14 @@ impl PacketTranslator {
|
||||
|
||||
// 3. Normal entity: remap object/entity type and falling block state
|
||||
let remapped_type = if version < JavaMinecraftVersion::V_1_14 {
|
||||
VarInt(i32::from(remap_object_type_for_version(entity_type_id, version)))
|
||||
VarInt(i32::from(remap_object_type_for_version(
|
||||
entity_type_id,
|
||||
version,
|
||||
)))
|
||||
} else {
|
||||
VarInt(i32::from(remap::entity_id_remap::remap_entity_id_for_version(entity_type_id, version)))
|
||||
VarInt(i32::from(
|
||||
remap::entity_id_remap::remap_entity_id_for_version(entity_type_id, version),
|
||||
))
|
||||
};
|
||||
|
||||
let remapped_data = if entity_type_id == EntityType::FALLING_BLOCK.id {
|
||||
@ -855,7 +898,6 @@ impl PacketTranslator {
|
||||
return Some((target_id, buf));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Generic packet ID translation
|
||||
let client_id = Self::translate_clientbound_packet_id(packet_id, version)?;
|
||||
|
||||
@ -12,6 +12,6 @@ pub mod menu_id_remap;
|
||||
pub mod painting_variant_id_remap;
|
||||
pub mod particle_id_remap;
|
||||
pub mod recipe_serializer_id_remap;
|
||||
pub mod sign;
|
||||
pub mod slot_display_id_remap;
|
||||
pub mod sound_id_remap;
|
||||
pub mod sign;
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
/* This file is generated. Do not edit manually. */
|
||||
#![allow(clippy::all)]
|
||||
use pumpkin_util::version::JavaMinecraftVersion;
|
||||
pub type Tag = (&'static [&'static str], &'static [u16]);
|
||||
#[derive(Eq, PartialEq, Hash, Debug, Clone, Copy)]
|
||||
|
||||
Loading…
Reference in New Issue
Block a user