Site2 code is now hot-reloadable with 'hot-site2' feature.

This commit is contained in:
Sam 2023-01-05 21:06:28 -05:00
parent 185dccc1cc
commit 7d42c45fdd
19 changed files with 135 additions and 15 deletions

2
Cargo.lock generated
View File

@ -7168,6 +7168,7 @@ dependencies = [
"kiddo 0.2.4", "kiddo 0.2.4",
"lazy_static", "lazy_static",
"lz-fear", "lz-fear",
"mimalloc",
"minifb", "minifb",
"noise", "noise",
"num 0.4.0", "num 0.4.0",
@ -7189,6 +7190,7 @@ dependencies = [
"vek 0.15.8", "vek 0.15.8",
"veloren-common", "veloren-common",
"veloren-common-base", "veloren-common-base",
"veloren-common-dynlib",
"veloren-common-frontend", "veloren-common-frontend",
"veloren-common-net", "veloren-common-net",
] ]

View File

@ -91,6 +91,10 @@ fn main() -> io::Result<()> {
{ {
agent::init(); agent::init();
} }
#[cfg(feature = "hot-site2")]
{
world::init();
}
// Load server settings // Load server settings
let mut server_settings = server::Settings::load(&server_data_dir); let mut server_settings = server::Settings::load(&server_data_dir);

View File

@ -11,6 +11,7 @@ plugins = ["common-state/plugins"]
persistent_world = [] persistent_world = []
hot-reloading = ["common/hot-reloading"] hot-reloading = ["common/hot-reloading"]
hot-agent = ["server-agent/use-dyn-lib"] hot-agent = ["server-agent/use-dyn-lib"]
hot-site2 = ["world/use-dyn-lib"]
default = ["worldgen", "plugins", "persistent_world", "simd"] default = ["worldgen", "plugins", "persistent_world", "simd"]

View File

@ -5,6 +5,8 @@ authors = ["Joshua Barretto <joshua.s.barretto@gmail.com>"]
edition = "2021" edition = "2021"
[features] [features]
use-dyn-lib = ["common-dynlib"]
be-dyn-lib = []
simd = ["vek/platform_intrinsics", "packed_simd"] simd = ["vek/platform_intrinsics", "packed_simd"]
bin_compression = ["lz-fear", "deflate", "flate2", "image/jpeg", "num-traits", "fallible-iterator", "clap", "rstar"] bin_compression = ["lz-fear", "deflate", "flate2", "image/jpeg", "num-traits", "fallible-iterator", "clap", "rstar"]
@ -14,6 +16,7 @@ default = ["simd"]
common = { package = "veloren-common", path = "../common" } common = { package = "veloren-common", path = "../common" }
common_base = { package = "veloren-common-base", path = "../common/base"} common_base = { package = "veloren-common-base", path = "../common/base"}
common-net = { package = "veloren-common-net", path = "../common/net" } common-net = { package = "veloren-common-net", path = "../common/net" }
common-dynlib = {package = "veloren-common-dynlib", path = "../common/dynlib", optional = true}
bincode = "1.3.1" bincode = "1.3.1"
bitvec = "1.0.1" bitvec = "1.0.1"
@ -39,6 +42,9 @@ inline_tweak = "1.0.2"
kiddo = "0.2" kiddo = "0.2"
strum = "0.24.0" strum = "0.24.0"
[target.'cfg(windows)'.dependencies]
mimalloc = "0.1.29"
# compression benchmarks # compression benchmarks
lz-fear = { version = "0.1.1", optional = true } lz-fear = { version = "0.1.1", optional = true }
deflate = { version = "1.0.0", optional = true } deflate = { version = "1.0.0", optional = true }

View File

@ -1,4 +1,3 @@
#![deny(unsafe_code)]
#![allow(incomplete_features)] #![allow(incomplete_features)]
#![allow( #![allow(
clippy::option_map_unit_fn, clippy::option_map_unit_fn,
@ -63,6 +62,25 @@ use serde::Deserialize;
use std::time::Duration; use std::time::Duration;
use vek::*; use vek::*;
#[cfg(all(feature = "be-dyn-lib", feature = "use-dyn-lib"))]
compile_error!("Can't use both \"be-dyn-lib\" and \"use-dyn-lib\" features at once");
#[cfg(all(target_os = "windows", feature = "be-dyn-lib"))]
#[global_allocator]
static GLOBAL: mimalloc::MiMalloc = mimalloc::MiMalloc;
#[cfg(feature = "use-dyn-lib")]
use {common_dynlib::LoadedLib, lazy_static::lazy_static, std::sync::Arc, std::sync::Mutex};
#[cfg(feature = "use-dyn-lib")]
lazy_static! {
pub static ref LIB: Arc<Mutex<Option<LoadedLib>>> =
common_dynlib::init("veloren-world", "world");
}
#[cfg(feature = "use-dyn-lib")]
pub fn init() { lazy_static::initialize(&LIB); }
#[derive(Debug)] #[derive(Debug)]
pub enum Error { pub enum Error {
Other(String), Other(String),

View File

@ -1,3 +1,6 @@
#[cfg(feature = "use-dyn-lib")]
use {crate::LIB, std::ffi::CStr};
use super::*; use super::*;
use crate::{ use crate::{
block::block_from_structure, block::block_from_structure,
@ -1339,7 +1342,41 @@ impl<const N: usize> PrimitiveGroupFill<N> for [PrimitiveRef<'_>; N] {
} }
pub trait Structure { pub trait Structure {
fn render(&self, site: &Site, land: &Land, painter: &Painter); #[cfg(feature = "use-dyn-lib")]
const UPDATE_FN: &'static [u8];
fn render_inner(&self, site: &Site, land: &Land, painter: &Painter);
fn render(&self, site: &Site, land: &Land, painter: &Painter) {
#[cfg(not(feature = "use-dyn-lib"))]
{
self.render_inner(site, land, painter);
}
#[cfg(feature = "use-dyn-lib")]
{
let lock = LIB.lock().unwrap();
let lib = &lock.as_ref().unwrap().lib;
let update_fn: common_dynlib::Symbol<fn(&Self, &Site, &Land, &Painter)> = unsafe {
//let start = std::time::Instant::now();
// Overhead of 0.5-5 us (could use hashmap to mitigate if this is an issue)
lib.get(Self::UPDATE_FN)
//println!("{}", start.elapsed().as_nanos());
}
.unwrap_or_else(|e| {
panic!(
"Trying to use: {} but had error: {:?}",
CStr::from_bytes_with_nul(Self::UPDATE_FN)
.map(CStr::to_str)
.unwrap()
.unwrap(),
e
)
});
update_fn(self, site, land, painter);
}
}
// Generate a primitive tree and fills for this structure // Generate a primitive tree and fills for this structure
fn render_collect( fn render_collect(

View File

@ -944,7 +944,11 @@ impl Bridge {
} }
impl Structure for Bridge { impl Structure for Bridge {
fn render(&self, _site: &Site, _land: &Land, painter: &Painter) { #[cfg(feature = "use-dyn-lib")]
const UPDATE_FN: &'static [u8] = b"render_bridge\0";
#[cfg_attr(feature = "be-dyn-lib", export_name = "render_bridge")]
fn render_inner(&self, _site: &Site, _land: &Land, painter: &Painter) {
match &self.kind { match &self.kind {
BridgeKind::Flat => render_flat(self, painter), BridgeKind::Flat => render_flat(self, painter),
BridgeKind::Tower(roof) => render_tower(self, painter, roof), BridgeKind::Tower(roof) => render_tower(self, painter, roof),

View File

@ -42,7 +42,11 @@ impl Castle {
} }
impl Structure for Castle { impl Structure for Castle {
fn render(&self, site: &Site, _land: &Land, painter: &Painter) { #[cfg(feature = "use-dyn-lib")]
const UPDATE_FN: &'static [u8] = b"render_castle\0";
#[cfg_attr(feature = "be-dyn-lib", export_name = "render_castle")]
fn render_inner(&self, site: &Site, _land: &Land, painter: &Painter) {
let wall_height = 24; let wall_height = 24;
let parapet_height = 2; let parapet_height = 2;
let parapet_gap = 2; let parapet_gap = 2;

View File

@ -101,7 +101,11 @@ impl Citadel {
} }
impl Structure for Citadel { impl Structure for Citadel {
fn render(&self, _site: &Site, land: &Land, painter: &Painter) { #[cfg(feature = "use-dyn-lib")]
const UPDATE_FN: &'static [u8] = b"render_citadel\0";
#[cfg_attr(feature = "be-dyn-lib", export_name = "render_citadel")]
fn render_inner(&self, _site: &Site, land: &Land, painter: &Painter) {
for (pos, cell) in self.grid.iter_area( for (pos, cell) in self.grid.iter_area(
self.wpos_cell(painter.render_aabr().min) - 1, self.wpos_cell(painter.render_aabr().min) - 1,
Vec2::<i32>::from(painter.render_aabr().size()) / CELL_SIZE + 2, Vec2::<i32>::from(painter.render_aabr().size()) / CELL_SIZE + 2,

View File

@ -43,7 +43,11 @@ impl CliffTower {
} }
impl Structure for CliffTower { impl Structure for CliffTower {
fn render(&self, _site: &Site, _land: &Land, painter: &Painter) { #[cfg(feature = "use-dyn-lib")]
const UPDATE_FN: &'static [u8] = b"render_clifftower\0";
#[cfg_attr(feature = "be-dyn-lib", export_name = "render_clifftower")]
fn render_inner(&self, _site: &Site, _land: &Land, painter: &Painter) {
let base = self.alt + 1; let base = self.alt + 1;
let center = self.bounds.center(); let center = self.bounds.center();
let variant_pos = center.with_z(base); let variant_pos = center.with_z(base);

View File

@ -129,7 +129,11 @@ impl DesertCityMultiPlot {
} }
impl Structure for DesertCityMultiPlot { impl Structure for DesertCityMultiPlot {
fn render(&self, _site: &Site, _land: &Land, painter: &Painter) { #[cfg(feature = "use-dyn-lib")]
const UPDATE_FN: &'static [u8] = b"render_desertcitymultiplot\0";
#[cfg_attr(feature = "be-dyn-lib", export_name = "render_desertcitymultiplot")]
fn render_inner(&self, _site: &Site, _land: &Land, painter: &Painter) {
let sandstone = Fill::Sampling(Arc::new(|center| { let sandstone = Fill::Sampling(Arc::new(|center| {
Some(match (RandomField::new(0).get(center)) % 37 { Some(match (RandomField::new(0).get(center)) % 37 {
0..=8 => Block::new(BlockKind::Rock, Rgb::new(245, 212, 129)), 0..=8 => Block::new(BlockKind::Rock, Rgb::new(245, 212, 129)),

View File

@ -38,7 +38,11 @@ impl DesertCityTemple {
} }
impl Structure for DesertCityTemple { impl Structure for DesertCityTemple {
fn render(&self, _site: &Site, _land: &Land, painter: &Painter) { #[cfg(feature = "use-dyn-lib")]
const UPDATE_FN: &'static [u8] = b"render_desertcitytemple\0";
#[cfg_attr(feature = "be-dyn-lib", export_name = "render_desertcitytemple")]
fn render_inner(&self, _site: &Site, _land: &Land, painter: &Painter) {
let sandstone = Fill::Sampling(Arc::new(|center| { let sandstone = Fill::Sampling(Arc::new(|center| {
Some(match (RandomField::new(0).get(center)) % 37 { Some(match (RandomField::new(0).get(center)) % 37 {
0..=8 => Block::new(BlockKind::Rock, Rgb::new(245, 212, 129)), 0..=8 => Block::new(BlockKind::Rock, Rgb::new(245, 212, 129)),

View File

@ -1377,7 +1377,11 @@ impl Floor {
} }
impl SiteStructure for Dungeon { impl SiteStructure for Dungeon {
fn render(&self, _site: &Site, land: &Land, painter: &Painter) { #[cfg(feature = "use-dyn-lib")]
const UPDATE_FN: &'static [u8] = b"render_dungeon\0";
#[cfg_attr(feature = "be-dyn-lib", export_name = "render_dungeon")]
fn render_inner(&self, _site: &Site, land: &Land, painter: &Painter) {
let origin = (self.origin + Vec2::broadcast(TILE_SIZE / 2)).with_z(self.alt + ALT_OFFSET); let origin = (self.origin + Vec2::broadcast(TILE_SIZE / 2)).with_z(self.alt + ALT_OFFSET);
lazy_static! { lazy_static! {

View File

@ -79,7 +79,11 @@ impl GiantTree {
} }
impl Structure for GiantTree { impl Structure for GiantTree {
fn render(&self, _site: &Site, _land: &Land, painter: &Painter) { #[cfg(feature = "use-dyn-lib")]
const UPDATE_FN: &'static [u8] = b"render_gianttree\0";
#[cfg_attr(feature = "be-dyn-lib", export_name = "render_gianttree")]
fn render_inner(&self, _site: &Site, _land: &Land, painter: &Painter) {
let fast_noise = FastNoise::new(self.seed); let fast_noise = FastNoise::new(self.seed);
let dark = Rgb::new(10, 70, 50).map(|e| e as f32); let dark = Rgb::new(10, 70, 50).map(|e| e as f32);
let light = Rgb::new(80, 140, 10).map(|e| e as f32); let light = Rgb::new(80, 140, 10).map(|e| e as f32);

View File

@ -436,7 +436,11 @@ impl GnarlingFortification {
} }
impl Structure for GnarlingFortification { impl Structure for GnarlingFortification {
fn render(&self, _site: &Site, land: &Land, painter: &Painter) { #[cfg(feature = "use-dyn-lib")]
const UPDATE_FN: &'static [u8] = b"render_gnarlingfortification\0";
#[cfg_attr(feature = "be-dyn-lib", export_name = "render_gnarlingfortification")]
fn render_inner(&self, _site: &Site, land: &Land, painter: &Painter) {
// Create outer wall // Create outer wall
for (point, next_point) in self.wall_segments.iter() { for (point, next_point) in self.wall_segments.iter() {
// This adds additional points for the wall on the line between two points, // This adds additional points for the wall on the line between two points,

View File

@ -92,7 +92,11 @@ impl House {
const STOREY: i32 = 5; const STOREY: i32 = 5;
impl Structure for House { impl Structure for House {
fn render(&self, site: &Site, _land: &Land, painter: &Painter) { #[cfg(feature = "use-dyn-lib")]
const UPDATE_FN: &'static [u8] = b"render_house\0";
#[cfg_attr(feature = "be-dyn-lib", export_name = "render_house")]
fn render_inner(&self, site: &Site, _land: &Land, painter: &Painter) {
let storey = STOREY; let storey = STOREY;
let roof = storey * self.levels as i32 - 1; let roof = storey * self.levels as i32 - 1;
let foundations = 12; let foundations = 12;

View File

@ -35,7 +35,11 @@ impl SavannahPit {
} }
impl Structure for SavannahPit { impl Structure for SavannahPit {
fn render(&self, _site: &Site, _land: &Land, painter: &Painter) { #[cfg(feature = "use-dyn-lib")]
const UPDATE_FN: &'static [u8] = b"render_savannahpit\0";
#[cfg_attr(feature = "be-dyn-lib", export_name = "render_savannahpit")]
fn render_inner(&self, _site: &Site, _land: &Land, painter: &Painter) {
let base = self.alt + 1; let base = self.alt + 1;
let center = self.bounds.center(); let center = self.bounds.center();
let sprite_fill = Fill::Sampling(Arc::new(|wpos| { let sprite_fill = Fill::Sampling(Arc::new(|wpos| {

View File

@ -31,7 +31,11 @@ impl SeaChapel {
} }
impl Structure for SeaChapel { impl Structure for SeaChapel {
fn render(&self, _site: &Site, _land: &Land, painter: &Painter) { #[cfg(feature = "use-dyn-lib")]
const UPDATE_FN: &'static [u8] = b"render_seachapel\0";
#[cfg_attr(feature = "be-dyn-lib", export_name = "render_seachapel")]
fn render_inner(&self, _site: &Site, _land: &Land, painter: &Painter) {
let base = self.alt + 1; let base = self.alt + 1;
let center = self.bounds.center(); let center = self.bounds.center();
let diameter = 54; let diameter = 54;

View File

@ -40,7 +40,11 @@ impl Workshop {
} }
impl Structure for Workshop { impl Structure for Workshop {
fn render(&self, _site: &Site, _land: &Land, painter: &Painter) { #[cfg(feature = "use-dyn-lib")]
const UPDATE_FN: &'static [u8] = b"render_workshop\0";
#[cfg_attr(feature = "be-dyn-lib", export_name = "render_workshop")]
fn render_inner(&self, _site: &Site, _land: &Land, painter: &Painter) {
let brick = Fill::Brick(BlockKind::Rock, Rgb::new(80, 75, 85), 24); let brick = Fill::Brick(BlockKind::Rock, Rgb::new(80, 75, 85), 24);
let base = self.alt + 1; let base = self.alt + 1;