Drop map-tool dependency (#375)
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
Paste the 80 lines of utility functions and drop the heavy dependency. Reviewed-on: #375 Co-authored-by: Rhys Lloyd <krakow20@gmail.com> Co-committed-by: Rhys Lloyd <krakow20@gmail.com>
This commit was merged in pull request #375.
This commit is contained in:
31
Cargo.lock
generated
31
Cargo.lock
generated
@@ -802,9 +802,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "bytemuck_derive"
|
||||
version = "1.10.2"
|
||||
version = "1.11.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f9abbd1bc6865053c427f7198e6af43bfdedc55ab791faed4fbd361d789575ff"
|
||||
checksum = "f65693059b6b9c588b9f62fed1cedbf0a8b805631457ea162d68f0de186f3de5"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@@ -2139,29 +2139,6 @@ dependencies = [
|
||||
"twox-hash",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "map-tool"
|
||||
version = "5.0.0"
|
||||
source = "sparse+https://git.itzana.me/api/packages/strafesnet/cargo/"
|
||||
checksum = "cfc12859c2a0257bd824aec8be77c45456a411826bedef9923ad225bff0e1c66"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"flate2",
|
||||
"image",
|
||||
"image_dds",
|
||||
"rbx_asset",
|
||||
"rbx_binary",
|
||||
"rbx_dom_weak",
|
||||
"rbx_reflection_database",
|
||||
"rbx_xml",
|
||||
"rbxassetid",
|
||||
"strafesnet_deferred_loader",
|
||||
"strafesnet_rbx_loader",
|
||||
"strafesnet_snf",
|
||||
"thiserror 2.0.18",
|
||||
"tokio",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "maps-combobulator"
|
||||
version = "0.1.0"
|
||||
@@ -2170,10 +2147,12 @@ dependencies = [
|
||||
"aws-config",
|
||||
"aws-sdk-s3",
|
||||
"futures-util",
|
||||
"map-tool",
|
||||
"image",
|
||||
"image_dds",
|
||||
"rbx_asset",
|
||||
"rbx_binary",
|
||||
"rbx_dom_weak",
|
||||
"rbx_xml",
|
||||
"rbxassetid",
|
||||
"serde",
|
||||
"serde_json",
|
||||
|
||||
@@ -12,6 +12,7 @@ futures-util = "0.3.31"
|
||||
rbx_asset = { version = "0.7.1", features = ["cloud", "cookie", "gzip", "rustls-tls"], default-features = false, registry = "strafesnet" }
|
||||
rbx_binary = "3.0.0"
|
||||
rbx_dom_weak = "4.2.0"
|
||||
rbx_xml = "3.0.0"
|
||||
serde = { version = "1.0.215", features = ["derive"] }
|
||||
serde_json = "1.0.133"
|
||||
tokio = { version = "1.41.1", features = ["macros", "rt-multi-thread", "signal"] }
|
||||
|
||||
@@ -8,10 +8,12 @@ async-nats.workspace = true
|
||||
aws-config = { version = "1", features = ["behavior-version-latest"] }
|
||||
aws-sdk-s3 = "1"
|
||||
futures-util.workspace = true
|
||||
map-tool = { version = "5.0.0", registry = "strafesnet", features = ["roblox"], default-features = false }
|
||||
image = { version = "0.25.10", features = ["png", "jpeg"], default-features = false }
|
||||
image_dds = { version = "0.7.2", features = ["ddsfile", "encode"], default-features = false }
|
||||
rbx_asset.workspace = true
|
||||
rbx_binary.workspace = true
|
||||
rbx_dom_weak.workspace = true
|
||||
rbx_xml.workspace = true
|
||||
rbxassetid = { version = "0.1.0", registry = "strafesnet" }
|
||||
serde.workspace = true
|
||||
serde_json.workspace = true
|
||||
|
||||
@@ -3,6 +3,7 @@ use tokio_stream::StreamExt;
|
||||
mod nats_types;
|
||||
mod process;
|
||||
mod s3;
|
||||
mod util;
|
||||
|
||||
const SUBJECT_MAPFIX_RELEASE:&str="maptest.mapfixes.release";
|
||||
const SUBJECT_SUBMISSION_BATCHRELEASE:&str="maptest.submissions.batchrelease";
|
||||
|
||||
@@ -2,6 +2,7 @@ use std::io::Cursor;
|
||||
|
||||
use crate::nats_types::ReleaseMapfixRequest;
|
||||
use crate::s3::S3Cache;
|
||||
use crate::util;
|
||||
|
||||
use futures_util::stream::iter as stream_iter;
|
||||
use futures_util::{StreamExt,TryStreamExt};
|
||||
@@ -16,9 +17,8 @@ const CONCURRENT_REQUESTS:usize=16;
|
||||
#[derive(Debug)]
|
||||
pub enum Error{
|
||||
ArchivedModel,
|
||||
LoadDom(map_tool::roblox::LoadDomError),
|
||||
DownloadAsset(map_tool::roblox::DownloadAssetError),
|
||||
IO(std::io::Error),
|
||||
LoadDom(util::LoadDomError),
|
||||
DownloadAsset(util::DownloadAssetError),
|
||||
SNFMap(strafesnet_snf::map::Error),
|
||||
S3Get(crate::s3::GetError),
|
||||
S3Put(crate::s3::PutError),
|
||||
@@ -49,9 +49,9 @@ impl Processor{
|
||||
}
|
||||
/// Download an asset, returning None if the asset is archived.
|
||||
async fn download_asset(&self,asset_id:u64)->Result<Option<Vec<u8>>,Error>{
|
||||
match map_tool::roblox::download_asset(&self.cloud_context,asset_id).await{
|
||||
match util::download_asset(&self.cloud_context,asset_id).await{
|
||||
Ok(data)=>Ok(Some(data)),
|
||||
Err(map_tool::roblox::DownloadAssetError::NonFreeModel)=>{
|
||||
Err(util::DownloadAssetError::NonFreeModel)=>{
|
||||
println!("[combobulator] Asset {asset_id} is inaccessible");
|
||||
Ok(None)
|
||||
},
|
||||
@@ -69,7 +69,7 @@ impl Processor{
|
||||
// check raw cache, download if missing
|
||||
let raw_key=S3Cache::texture_raw_key(asset_id);
|
||||
let dds_result=if let Some(data)=self.s3.get(&raw_key).await.map_err(Error::S3Get)?{
|
||||
map_tool::roblox::convert_texture_to_dds(&data)
|
||||
util::convert_texture_to_dds(&data)
|
||||
}else{
|
||||
println!("[combobulator] Downloading texture {asset_id}");
|
||||
let Some(data)=self.download_asset(asset_id).await? else{
|
||||
@@ -77,7 +77,7 @@ impl Processor{
|
||||
};
|
||||
|
||||
// decode while we have ownership
|
||||
let dds_result=map_tool::roblox::convert_texture_to_dds(&data);
|
||||
let dds_result=util::convert_texture_to_dds(&data);
|
||||
|
||||
self.s3.put(&raw_key,data).await.map_err(Error::S3Put)?;
|
||||
dds_result
|
||||
@@ -87,7 +87,7 @@ impl Processor{
|
||||
let dds=match dds_result{
|
||||
Ok(dds)=>dds,
|
||||
Err(e)=>{
|
||||
println!("[combobulator] Texture {asset_id} convert error: {e}");
|
||||
println!("[combobulator] Texture {asset_id} convert error: {e:?}");
|
||||
return Ok(None);
|
||||
}
|
||||
};
|
||||
@@ -176,7 +176,7 @@ impl Processor{
|
||||
.ok_or(Error::ArchivedModel)?;
|
||||
|
||||
// decode dom
|
||||
let dom=map_tool::roblox::load_dom(&rbxl_bytes)
|
||||
let dom=util::load_dom(&rbxl_bytes)
|
||||
.map_err(Error::LoadDom)?;
|
||||
|
||||
// run scripts
|
||||
|
||||
84
combobulator/src/util.rs
Normal file
84
combobulator/src/util.rs
Normal file
@@ -0,0 +1,84 @@
|
||||
|
||||
#[expect(dead_code)]
|
||||
#[derive(Debug)]
|
||||
pub enum LoadDomError{
|
||||
Binary(rbx_binary::DecodeError),
|
||||
Xml(rbx_xml::DecodeError),
|
||||
UnknownFormat,
|
||||
}
|
||||
impl std::fmt::Display for LoadDomError{
|
||||
fn fmt(&self,f:&mut std::fmt::Formatter<'_>)->std::fmt::Result{
|
||||
write!(f,"{self:?}")
|
||||
}
|
||||
}
|
||||
impl std::error::Error for LoadDomError{}
|
||||
pub fn load_dom(data:&[u8])->Result<rbx_dom_weak::WeakDom,LoadDomError>{
|
||||
match data.get(0..8){
|
||||
Some(b"<roblox!")=>rbx_binary::from_reader(data).map_err(LoadDomError::Binary),
|
||||
Some(b"<roblox ")=>rbx_xml::from_reader_default(data).map_err(LoadDomError::Xml),
|
||||
_=>Err(LoadDomError::UnknownFormat),
|
||||
}
|
||||
}
|
||||
|
||||
#[expect(dead_code)]
|
||||
#[derive(Debug)]
|
||||
pub enum DownloadAssetError{
|
||||
GetLocation(rbx_asset::cloud::GetError),
|
||||
NonFreeModel,
|
||||
GetAsset(rbx_asset::cloud::GetError),
|
||||
IO(std::io::Error),
|
||||
}
|
||||
impl std::fmt::Display for DownloadAssetError{
|
||||
fn fmt(&self,f:&mut std::fmt::Formatter<'_>)->std::fmt::Result{
|
||||
write!(f,"{self:?}")
|
||||
}
|
||||
}
|
||||
impl std::error::Error for DownloadAssetError{}
|
||||
|
||||
pub async fn download_asset(context:&rbx_asset::cloud::Context,asset_id:u64)->Result<Vec<u8>,DownloadAssetError>{
|
||||
let asset_location_info=context.get_asset_location(rbx_asset::cloud::GetAssetLatestRequest{
|
||||
asset_id,
|
||||
}).await.map_err(DownloadAssetError::GetLocation)?;
|
||||
let Some(asset_location)=asset_location_info.location else{
|
||||
return Err(DownloadAssetError::NonFreeModel);
|
||||
};
|
||||
let data=context.get_asset(&asset_location).await.map_err(DownloadAssetError::GetAsset)?;
|
||||
data.to_vec().map_err(DownloadAssetError::IO)
|
||||
}
|
||||
|
||||
#[expect(dead_code)]
|
||||
#[derive(Debug)]
|
||||
pub enum ConvertTextureError{
|
||||
Image(image::ImageError),
|
||||
DdsEncode(image_dds::error::SurfaceError),
|
||||
Dds(image_dds::CreateDdsError),
|
||||
DdsWrite(image_dds::ddsfile::Error),
|
||||
}
|
||||
pub fn convert_texture_to_dds(data:&[u8])->Result<Vec<u8>,ConvertTextureError>{
|
||||
let image=image::load_from_memory(data).map_err(ConvertTextureError::Image)?.to_rgba8();
|
||||
|
||||
let format=if image.width()%4!=0||image.height()%4!=0{
|
||||
image_dds::ImageFormat::Rgba8UnormSrgb
|
||||
}else{
|
||||
image_dds::ImageFormat::BC7RgbaUnormSrgb
|
||||
};
|
||||
|
||||
let surface=image_dds::SurfaceRgba8{
|
||||
width:image.width(),
|
||||
height:image.height(),
|
||||
depth:1,
|
||||
layers:1,
|
||||
mipmaps:1,
|
||||
data:image.as_raw(),
|
||||
}.encode(
|
||||
format,
|
||||
image_dds::Quality::Slow,
|
||||
image_dds::Mipmaps::GeneratedAutomatic
|
||||
).map_err(ConvertTextureError::DdsEncode)?;
|
||||
|
||||
let dds=surface.to_dds().map_err(ConvertTextureError::Dds)?;
|
||||
|
||||
let mut buf=Vec::new();
|
||||
dds.write(&mut buf).map_err(ConvertTextureError::DdsWrite)?;
|
||||
Ok(buf)
|
||||
}
|
||||
@@ -10,7 +10,7 @@ rbx_asset.workspace = true
|
||||
rbx_binary.workspace = true
|
||||
rbx_dom_weak.workspace = true
|
||||
rbx_reflection_database = "3.0.0"
|
||||
rbx_xml = "3.0.0"
|
||||
rbx_xml.workspace = true
|
||||
regex = { version = "1.11.3", default-features = false }
|
||||
serde.workspace = true
|
||||
serde_json.workspace = true
|
||||
|
||||
Reference in New Issue
Block a user