Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

1.18.2 #75

Merged
merged 19 commits into from
Jul 27, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
290 changes: 155 additions & 135 deletions Cargo.lock

Large diffs are not rendered by default.

50 changes: 4 additions & 46 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[workspace]
members = ["proc_macros", "redpiler_graph"]
members = ["crates/proc_macros", "crates/redpiler_graph"]

[package]
name = "mchprs"
Expand All @@ -22,50 +22,8 @@ include = [
# MCHPRS runs far too slow without any optimizations to even be usable for testing
opt-level = 1

[dev-dependencies]
criterion = "0.3"

[[bench]]
name = "bitbuffer"
harness = false

[[bench]]
name = "chungus"
harness = false

[dependencies]
mchprs_proc_macros = { path = "./proc_macros" }
toml = "0.5"
flate2 = "1"
byteorder = "1.4"
# hematite-nbt = "0.5"
hematite-nbt = { git = "https://github.com/PistonDevelopers/hematite_nbt" }
bitflags = "1.2"
serde = "1"
serde_json = "1.0"
md5 = "0.7"
bus = "2.2"
bincode = "1.3"
ctrlc = { version = "3.1", features = ["termination"] }
log = "0.4"
fern = { version = "0.6", features = ["colored"] }
chrono = "0.4"
rand = "0.8"
regex = { version = "1.4", features = ["pattern"] }
backtrace = "0.3"
rusqlite = { version="0.27", features=["bundled"] }
anyhow = "1.0"
rayon = "1.5"
cranelift = { version = "0.77", optional = true }
cranelift-jit = { version = "0.77", optional = true }
cranelift-module = { version = "0.77", optional = true }
toml_edit = "0.14"
mysql = "22"
tokio = { version = "1", features = ["rt-multi-thread"] }
reqwest = { version = "0.11", features = ["json"] }
itertools = "0.10"
impls = "1"
redpiler_graph = { path = "./redpiler_graph" }
mchprs_core = { path = "./crates/core" }

[features]
jit_cranelift = ["cranelift", "cranelift-jit", "cranelift-module"]
[patch.crates-io]
hematite-nbt = { git = "https://github.com/StackDoubleFlow/hematite_nbt" }
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

[![Build Status](https://travis-ci.org/MCHPR/MCHPRS.svg?branch=master)](https://travis-ci.org/MCHPR/MCHPRS) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) [![Discord Banner 2](https://discordapp.com/api/guilds/724072903083163679/widget.png)](https://discord.com/invite/svK9JU7)

A Minecraft creative server built for redstone. Each 256x256 plot runs on a separate thread, allowing for less lag, more concurrency, and many awesome extra features!
A Minecraft 1.18.2 creative server built for redstone. Each 256x256 plot runs on a separate thread, allowing for less lag, more concurrency, and many awesome extra features!

MCHPRS is very different from traditional servers. Because this server is tailored to the use of computation redstone, many things that are a part of Vanilla Minecraft servers don't exist here. That being said, MCHPRS comes with many of its own unique features.

Expand Down
12 changes: 12 additions & 0 deletions crates/blocks/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
[package]
name = "mchprs_blocks"
version = "0.1.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
serde = "1"
hematite-nbt = "0.5"
mchprs_utils = { path = "../utils" }
mchprs_proc_macros = { path = "../proc_macros" }
232 changes: 232 additions & 0 deletions crates/blocks/src/block_entities.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,232 @@
use mchprs_utils::{map, nbt_unwrap_val};
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use std::str::FromStr;

use crate::items::Item;

/// A single item in an inventory
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct InventoryEntry {
pub id: u32,
pub slot: i8,
pub count: i8,
pub nbt: Option<Vec<u8>>,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SignBlockEntity {
pub rows: [String; 4],
}

#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)]
pub enum ContainerType {
Furnace,
Barrel,
Hopper,
}

impl FromStr for ContainerType {
type Err = ();

fn from_str(s: &str) -> Result<Self, Self::Err> {
Ok(match s {
"barrel" => ContainerType::Barrel,
"furnace" => ContainerType::Furnace,
"hopper" => ContainerType::Hopper,
_ => return Err(()),
})
}
}

impl ToString for ContainerType {
fn to_string(&self) -> String {
match self {
ContainerType::Furnace => "minecraft:furnace",
ContainerType::Barrel => "minecraft:barrel",
ContainerType::Hopper => "minecraft:hopper",
}
.to_owned()
}
}

impl ContainerType {
pub fn num_slots(self) -> u8 {
match self {
ContainerType::Furnace => 3,
ContainerType::Barrel => 27,
ContainerType::Hopper => 5,
}
}

pub fn window_type(self) -> u8 {
// https://wiki.vg/Inventory
match self {
ContainerType::Furnace => 13,
ContainerType::Barrel => 2,
ContainerType::Hopper => 15,
}
}
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum BlockEntity {
Comparator {
output_strength: u8,
},
Container {
comparator_override: u8,
inventory: Vec<InventoryEntry>,
ty: ContainerType,
},
Sign(Box<SignBlockEntity>),
}

impl BlockEntity {
/// The protocol id for the block entity
pub fn ty(&self) -> i32 {
match self {
BlockEntity::Comparator { .. } => 17,
BlockEntity::Container { ty, .. } => match ty {
ContainerType::Furnace => 0,
ContainerType::Barrel => 25,
ContainerType::Hopper => 16,
},
BlockEntity::Sign(_) => 7,
}
}

fn load_container(slots_nbt: &[nbt::Value], ty: ContainerType) -> Option<BlockEntity> {
use nbt::Value;
let num_slots = ty.num_slots();
let mut fullness_sum: f32 = 0.0;
let mut inventory = Vec::new();
for item in slots_nbt {
let item_compound = nbt_unwrap_val!(item, Value::Compound);
let count = nbt_unwrap_val!(item_compound["Count"], Value::Byte);
let slot = nbt_unwrap_val!(item_compound["Slot"], Value::Byte);
let namespaced_name = nbt_unwrap_val!(
item_compound
.get("Id")
.or_else(|| item_compound.get("id"))?,
Value::String
);
let item_type = Item::from_name(namespaced_name.split(':').last()?);

let mut blob = nbt::Blob::new();
for (k, v) in item_compound {
blob.insert(k, v.clone()).unwrap();
}
let mut data = Vec::new();
blob.to_writer(&mut data).unwrap();

let tag = match item_compound.get("tag") {
Some(nbt::Value::Compound(map)) => {
let mut blob = nbt::Blob::new();
for (k, v) in map {
blob.insert(k, v.clone()).unwrap();
}

let mut data = Vec::new();
blob.to_writer(&mut data).unwrap();
Some(data)
}
_ => None,
};
inventory.push(InventoryEntry {
slot,
count,
id: item_type.unwrap_or(Item::Redstone {}).get_id(),
nbt: tag,
});

fullness_sum += count as f32 / item_type.map_or(64, Item::max_stack_size) as f32;
}
Some(BlockEntity::Container {
comparator_override: (if fullness_sum > 0.0 { 1.0 } else { 0.0 }
+ (fullness_sum / num_slots as f32) * 14.0)
.floor() as u8,
inventory,
ty,
})
}

pub fn from_nbt(nbt: &HashMap<String, nbt::Value>) -> Option<BlockEntity> {
use nbt::Value;
let id = nbt_unwrap_val!(&nbt.get("Id").or_else(|| nbt.get("id"))?, Value::String);
match id.as_ref() {
"minecraft:comparator" => Some(BlockEntity::Comparator {
output_strength: *nbt_unwrap_val!(&nbt["OutputSignal"], Value::Int) as u8,
}),
"minecraft:furnace" => BlockEntity::load_container(
nbt_unwrap_val!(&nbt["Items"], Value::List),
ContainerType::Furnace,
),
"minecraft:barrel" => BlockEntity::load_container(
nbt_unwrap_val!(&nbt["Items"], Value::List),
ContainerType::Barrel,
),
"minecraft:hopper" => BlockEntity::load_container(
nbt_unwrap_val!(&nbt["Items"], Value::List),
ContainerType::Hopper,
),
"minecraft:sign" => Some({
BlockEntity::Sign(Box::new(SignBlockEntity {
rows: [
// This cloning is really dumb
nbt_unwrap_val!(nbt["Text1"].clone(), Value::String),
nbt_unwrap_val!(nbt["Text2"].clone(), Value::String),
nbt_unwrap_val!(nbt["Text3"].clone(), Value::String),
nbt_unwrap_val!(nbt["Text4"].clone(), Value::String),
],
}))
}),
_ => None,
}
}

pub fn to_nbt(&self, sign_only: bool) -> Option<nbt::Blob> {
if sign_only && !matches!(self, BlockEntity::Sign(_)) {
return None;
}

use nbt::Value;
match self {
BlockEntity::Sign(sign) => Some({
let [r1, r2, r3, r4] = sign.rows.clone();
nbt::Blob::with_content(map! {
"Text1" => Value::String(r1),
"Text2" => Value::String(r2),
"Text3" => Value::String(r3),
"Text4" => Value::String(r4),
"id" => Value::String("minecraft:sign".to_owned())
})
}),
BlockEntity::Comparator { output_strength } => Some({
nbt::Blob::with_content(map! {
"OutputSignal" => Value::Int(*output_strength as i32),
"id" => Value::String("minecraft:comparator".to_owned())
})
}),
BlockEntity::Container { inventory, ty, .. } => Some({
let mut items = Vec::new();
for entry in inventory {
let nbt = map! {
"Count" => nbt::Value::Byte(entry.count),
"id" => nbt::Value::String("minecraft:".to_string() + Item::from_id(entry.id).get_name()),
"Slot" => nbt::Value::Byte(entry.slot)
};
// TODO: item nbt data in containers
// if let Some(tag) = &entry.nbt {
// let blob = nbt::Blob::from_reader(&mut Cursor::new(tag)).unwrap();
// }
items.push(nbt::Value::Compound(nbt));
}
nbt::Blob::with_content(map! {
"id" => Value::String(ty.to_string()),
"Items" => Value::List(items)
})
}),
}
}
}
Loading