From 90720c34f98ec3f1889ab23f6a7866b324f06814 Mon Sep 17 00:00:00 2001 From: Walidoux Date: Tue, 2 May 2023 15:51:22 +0100 Subject: [PATCH] feat(all-in-one): update prettier config, enable format on save Update the VSCode settings.json to include the Prettier VSCode formatter, and enable formatting on save. A new LICENSE file is added to comply with the MIT license due to the open-source nature of the project. The README.md file has now core features and to-dos that should be taken care of as the project continues to evolve. The index.html file is modified to match changes in src/index.tsx. The postcss configuration files are created, and some files are updated. Finally, new files like build.rs, draworder.json, and commands.rs were created --- LICENSE | 21 +++++ README.md | 60 ++++++++++++ index.html | 2 +- postcss.config.cjs | 7 ++ postcss.config.js | 6 -- prettier.config.cjs | 4 + src-tauri/build.rs | 3 - src-tauri/data/draworder.json | 1 + src-tauri/src/build.rs | 5 + src-tauri/src/commands.rs | 108 ++++++++++++++++++++++ src-tauri/src/main.rs | 21 ++++- src-tauri/src/structs.rs | 39 ++++++++ src-tauri/src/utils.rs | 25 +++++ src-tauri/tauri.conf.json | 10 +- tailwind.config.js => tailwind.config.cjs | 2 +- tsconfig.json | 8 +- tsconfig.node.json | 9 -- vite.config.tauri.ts | 32 +++++++ vite.config.ts | 29 +----- 19 files changed, 335 insertions(+), 57 deletions(-) create mode 100644 LICENSE create mode 100644 README.md create mode 100644 postcss.config.cjs delete mode 100644 postcss.config.js create mode 100644 prettier.config.cjs delete mode 100644 src-tauri/build.rs create mode 100644 src-tauri/data/draworder.json create mode 100644 src-tauri/src/build.rs create mode 100644 src-tauri/src/commands.rs create mode 100644 src-tauri/src/structs.rs create mode 100644 src-tauri/src/utils.rs rename tailwind.config.js => tailwind.config.cjs (75%) delete mode 100644 tsconfig.node.json create mode 100644 vite.config.tauri.ts diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..fe57347 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +# MIT License + +Copyright (c) 2023 Rypî Dev + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..54a30f2 --- /dev/null +++ b/README.md @@ -0,0 +1,60 @@ +# 🧿 Getting started + +## 🎯 Todos + +- [ ] Two options for downloading Habbo resources: + - [ ] Default data extraction. (Without conversion) + - [ ] Using [Scuti](https://scuti.netlify.app/) dataset for its [renderer.](https://github.com/kozennnn/scuti-renderer) +- [ ] Languages feature. (Default: EN) +- [ ] Download Habbo assets. (>800 MB of disk memory, make sure the IPC handles it correctly) +- [ ] Fix rendering animation issues. +- [ ] Add "abort" button with written data suppression feature. +- [x] Convert front-end with SolidJS +- [x] Fix issue of prettier-plugin-tailwindcss + +- [ ] Export helpers/utils methods into Rust. + + - [ ] Implementing typesafety with types' collections using Tauri Specta + - [ ] Handling extracted data in: + - [ ] JSON (Default + Adjustements for Scuti) + - [ ] XML (Using quickxml_to_serde) + - [ ] TXT (no idea...) + - [ ] Parsing data using `std::{fs::File, io::Write}` + +- [ ] Avoid conflicts in open-source. +- [ ] Undertsand: Memory cache and disk cache. + +## Overview + +- [How it works](#🏗️-how-it-works) +- [Techs stack](#📦-techs-stack) +- [Interesting topics](#📤-interesting-topics) +- [Credits](#🤝-credits) + +## 📦 Techs stack + +![Rust lang](https://img.shields.io/badge/Rust-black?style=for-the-badge&logo=rust&logoColor=#E57324) +![Typescript lang](https://img.shields.io/badge/TypeScript-007ACC?style=for-the-badge&logo=typescript&logoColor=white) + +![Vite](https://img.shields.io/badge/Vite-B73BFE?style=for-the-badge&logo=vite&logoColor=FFD62E) +![SolidJS](https://img.shields.io/badge/Solid%20JS-2C4F7C?style=for-the-badge&logo=solid&logoColor=white) +![Tailwind framework](https://img.shields.io/badge/Tailwind_CSS-38B2AC?style=for-the-badge&logo=tailwind-css&logoColor=white) + +## 🏗️ How it works + +### Gamedata/Generic + +It comes first with fetching data using the `@tauri-apps/api/http` module. +Converting uncoming data into minified JSON file formats. +(No need for avro, parquet, protobuf nor CSV for efficient data compression +and encoding schemas for fast data storing/retrieval) + +## 📤 Interesting topics + +### 🦀 Rust-related + +- [Why serde_json crate is the best choice?](https://blog.logrocket.com/json-and-rust-why-serde_json-is-the-top-choice/) + +## 🤝 Credits + +This wouldn't be possible without the help of [KOZEN](https://github.com/kozennnn)'s contribution. diff --git a/index.html b/index.html index a47b3d1..59fa081 100644 --- a/index.html +++ b/index.html @@ -8,6 +8,6 @@
- + diff --git a/postcss.config.cjs b/postcss.config.cjs new file mode 100644 index 0000000..1039228 --- /dev/null +++ b/postcss.config.cjs @@ -0,0 +1,7 @@ +module.exports = { + plugins: { + tailwindcss: {}, + autoprefixer: {}, + ...(!process.env.TAURI_DEBUG ? { cssnano: { preset: 'advanced' } } : {}) + } +} diff --git a/postcss.config.js b/postcss.config.js deleted file mode 100644 index 85f717c..0000000 --- a/postcss.config.js +++ /dev/null @@ -1,6 +0,0 @@ -module.exports = { - plugins: { - tailwindcss: {}, - autoprefixer: {} - } -} diff --git a/prettier.config.cjs b/prettier.config.cjs new file mode 100644 index 0000000..9ad75ed --- /dev/null +++ b/prettier.config.cjs @@ -0,0 +1,4 @@ +module.exports = { + ...require("@walidoux/prettier-config"), + plugins: ["prettier-plugin-tailwindcss"], +}; diff --git a/src-tauri/build.rs b/src-tauri/build.rs deleted file mode 100644 index 795b9b7..0000000 --- a/src-tauri/build.rs +++ /dev/null @@ -1,3 +0,0 @@ -fn main() { - tauri_build::build() -} diff --git a/src-tauri/data/draworder.json b/src-tauri/data/draworder.json new file mode 100644 index 0000000..a176cdc --- /dev/null +++ b/src-tauri/data/draworder.json @@ -0,0 +1 @@ +{"std":[["li","lh","ls","lc","ri","bd","sh","lg","ch","cc","cp","wa","ca","rh","rs","rc","hd","fc","ey","hr","hrb","fa","ea","ha","he"],["li","lh","ls","lc","bd","sh","lg","ch","cc","cp","wa","ca","ri","rh","rs","rc","hd","fc","ey","hr","hrb","fa","ea","ha","he"],["li","lh","ls","lc","bd","sh","lg","ch","cc","cp","wa","ca","hd","fc","ey","hr","hrb","fa","ea","ha","he","ri","rh","rs","rc"],["bd","sh","lg","ch","cc","cp","wa","ca","li","lh","ls","lc","hd","fc","ey","hr","hrb","fa","ea","ha","he","ri","rh","rs","rc"],["bd","sh","lg","ch","cc","cp","wa","ca","lh","ls","lc","li","hd","fc","ey","hr","hrb","fa","ea","ha","he","rh","rs","rc","ri"],["rh","rs","rc","ri","bd","sh","lg","ch","cc","cp","wa","ca","li","lh","ls","lc","hd","fc","ey","hr","hrb","fa","ea","ha","he"],["bd","sh","lg","ch","cc","cp","wa","ca","li","lh","ls","lc","hd","fc","ey","hr","hrb","fa","ea","ha","he","rh","rs","rc","ri"],["li","lh","ls","lc","ri","rh","rs","rc","bd","sh","lg","ch","cc","cp","wa","ca","hd","fc","ey","hr","hrb","fa","ea","ha","he"]],"lh-up":{"4":["rh","rs","rc","bd","sh","lg","ch","cc","cp","wa","ri","ca","hd","fc","ey","hr","hrb","fa","ea","ha","he","lh","ls","lc","li"],"5":["rh","rs","rc","ri","bd","sh","lg","ch","cc","cp","wa","ca","hd","fc","ey","hr","hrb","fa","ea","ha","he","li","lh","ls","lc"],"6":["rh","rs","rc","ri","bd","sh","lg","ch","cc","cp","wa","ca","hd","fc","ey","hr","hrb","fa","ea","ha","he","li","lh","ls","lc"]},"rh-up":[["li","lh","ls","lc","ri","bd","sh","lg","ch","cc","cp","wa","ca","hd","fc","ey","hr","hrb","fa","ea","ha","he","rh","rs","rc"],["li","lh","ls","lc","bd","sh","lg","ch","cc","cp","wa","ca","hd","fc","ey","hr","hrb","fa","ea","ha","he","ri","rh","rs","rc"],["li","lh","ls","lc","bd","sh","lg","ch","cc","cp","wa","ca","hd","fc","ey","hr","hrb","fa","ea","ha","he","ri","rh","rs","rc"],["bd","sh","lg","ch","cc","cp","wa","li","lh","ls","lc","ca","hd","fc","ey","hr","hrb","fa","ea","ha","he","ri","rh","rs","rc"]],"sit":{"2":["li","lh","ls","lc","bd","lg","ch","cc","cp","wa","ca","rh","rs","rc","hd","fc","ey","hr","hrb","fa","ea","ha","he","ri","sh"],"3":["bd","lg","ch","cc","cp","wa","ca","li","lh","ls","lc","rh","rs","rc","hd","fc","ey","hr","hrb","fa","ea","ha","he","ri","sh"],"4":["rh","rs","rc","bd","lg","ch","cc","cp","wa","ca","lh","ls","lc","li","hd","fc","ey","hr","hrb","fa","ea","ha","he","ri","sh"]},"sit.lh-up":{"4":["rh","rs","rc","bd","lg","ch","cc","cp","wa","ri","ca","hd","fc","ey","hr","hrb","fa","ea","ha","he","lh","ls","lc","li","sh"]},"sit.rh-up":{"2":["li","lh","ls","lc","bd","lg","ch","cc","cp","wa","ca","hd","fc","ey","hr","hrb","fa","ea","ha","he","ri","rh","rs","rc","sh"],"3":["bd","lg","ch","cc","cp","wa","li","lh","ls","lc","ca","hd","fc","ey","hr","hrb","fa","ea","ha","he","ri","rh","rs","rc","sh"]},"lay":{"2":["lh","ls","lc","li","bd","lg","sh","ch","cc","cp","hd","fc","ey","wa","ri","rh","rs","rc","ca","hr","hrb","fa","ea","ha","he"],"4":["rh","rs","rc","ri","bd","lg","sh","ch","cc","cp","hd","fc","ey","wa","li","lh","ls","lc","ca","hr","hrb","fa","ea","ha","he"]}} \ No newline at end of file diff --git a/src-tauri/src/build.rs b/src-tauri/src/build.rs new file mode 100644 index 0000000..7ffb2fc --- /dev/null +++ b/src-tauri/src/build.rs @@ -0,0 +1,5 @@ +use tauri_build::build; + +fn main() { + build() +} diff --git a/src-tauri/src/commands.rs b/src-tauri/src/commands.rs new file mode 100644 index 0000000..d7a124b --- /dev/null +++ b/src-tauri/src/commands.rs @@ -0,0 +1,108 @@ +use quickxml_to_serde::{xml_string_to_json, Config, NullValue}; +use specta::specta; + +use crate::{ + structs::{ConvertTypes, GamedataEndpoints}, + utils::convert_json, +}; + +#[specta] +#[tauri::command] +pub fn download_gamedata(data: &str, endpoint: GamedataEndpoints) { + match endpoint.convert { + ConvertTypes::XML => { + let conf = Config::new_with_custom_values(true, "", "txt", NullValue::Null); + let json = xml_string_to_json(data.to_owned(), &conf); + + println!("{}", json.expect("Malformed XML").to_string()); + } + + ConvertTypes::TXT => println!("TXT CONVERTION"), + ConvertTypes::JSON => convert_json(data, endpoint.file_name), + } +} + +/* #[specta] +#[tauri::command] +pub fn parse_data( + path: String, + file_name: String, + file_content: String, +) -> Result<(), Box> { + let file_dir = PathBuf::from(&path).join(format!("{}.json", file_name)); + + // By default, output files will be overwritten. I cannot recursively remove the entire output folder + // and create it again because it just won't parse files' contents for some reason + if !exists(&Convertion::gamedata_dir()) { + create_dir_all(&Convertion::gamedata_dir())?; + } + + write_file(&file_dir, file_content.as_bytes()); + + Ok(()) +} */ + +/* pub async fn convert_txt(path: &str, data: &str) -> Result<(), Box> { + let mut badges: Vec = Vec::new(); + + let lines: Vec<&str> = data.split('\n').collect(); + + let badge_pattern = Regex::new(r"^badge_(?:name|desc)_([^=]+)").unwrap(); + let description_pattern = Regex::new(r"^badge_desc_(\s*\w+)").unwrap(); + let name_pattern = Regex::new(r"^badge_name_(\s*\w+)").unwrap(); + + for (index, line) in lines.iter().enumerate() { + let parts: Vec<&str> = line.split('=').collect(); + + if parts.len() < 2 { + continue; + } + + let key = parts[0]; + let value = parts[1]; + + if badge_pattern.is_match(key) { + if name_pattern.is_match(key) { + let badge_code = name_pattern.captures(key).unwrap()[1].to_owned(); + let existing_badge = badges.iter_mut().find(|badge| badge.code == badge_code); + + if let Some(badge) = existing_badge { + badge.name = Some(value.to_owned()); + } else { + badges.push(Badge { + code: badge_code, + name: Some(value.to_owned()), + description: None, + }); + } + } else if description_pattern.is_match(key) { + let badge_code = description_pattern.captures(key).unwrap()[1].to_owned(); + let existing_badge = badges.iter_mut().find(|badge| badge.code == badge_code); + + if let Some(badge) = existing_badge { + badge.description = Some(value.to_owned()); + } else { + badges.push(Badge { + code: badge_code, + name: None, + description: Some(value.to_owned()), + }); + } + } + + // Remove the line from the vector + lines[index] = ""; + } + } + + // Remove empty lines + let lines: Vec<&str> = lines + .iter() + .filter(|line| !line.is_empty()) + .cloned() + .collect(); + + parse_habbo_data(path, "Badges", &badges); + + Ok(()) +} */ diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index e6ad770..a85b26f 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -1,8 +1,27 @@ -// Prevents additional console window on Windows in release, DO NOT REMOVE!! #![cfg_attr(not(debug_assertions), windows_subsystem = "windows")] +pub mod commands; +pub mod structs; +pub mod utils; + +use commands::download_gamedata; +use specta::collect_types; +use tauri_specta::ts; + fn main() { + ts::export(collect_types![download_gamedata], "../src/tools/rusty.ts").unwrap(); + + // This is useful for custom eslint, prettier overrides at the top of the file. + // ts::export_with_cfg_with_header( + // collect_types![download_gamedata].unwrap(), + // Default::default(), + // "../src/tools/rusty.ts", + // "/* eslint-disable */\n".into(), + // ) + // .unwrap(); + tauri::Builder::default() + .invoke_handler(tauri::generate_handler![download_gamedata]) .run(tauri::generate_context!()) .expect("error while running tauri application"); } diff --git a/src-tauri/src/structs.rs b/src-tauri/src/structs.rs new file mode 100644 index 0000000..70c44b0 --- /dev/null +++ b/src-tauri/src/structs.rs @@ -0,0 +1,39 @@ +use serde::{Deserialize, Serialize}; +use specta::Type; + +/* pub struct Badge { + pub code: String, + pub name: Option, + pub description: Option, +} */ + +#[derive(Serialize, Deserialize, Type, Debug)] +pub enum ConvertTypes { + TXT, + XML, + JSON, +} + +#[derive(Serialize, Deserialize, Type, Debug)] +pub enum Converters { + FigureData, + FigureMap, + EffectMap, + FurniData, +} + +#[derive(Serialize, Deserialize, Type, Debug)] +pub struct GamedataEndpoints { + pub src: String, + pub convert: ConvertTypes, + pub file_name: Converters, +} + +pub struct FigureData { + pub floor_items: Vec, + pub wall_items: Vec, +} + +pub struct IFloorItem {} + +pub struct IFurni {} diff --git a/src-tauri/src/utils.rs b/src-tauri/src/utils.rs new file mode 100644 index 0000000..7123e40 --- /dev/null +++ b/src-tauri/src/utils.rs @@ -0,0 +1,25 @@ +use serde_json::Value; + +use crate::structs::Converters; + +pub fn debug_typeof(_: &T) { + println!("{}", std::any::type_name::()) +} + +pub fn convert_json(data: &str, file_name: Converters) { + let object: Value = serde_json::from_str(data).unwrap(); + + println!("{}", object); + + match file_name { + /* Converters::FurniData => { + for (key, value) in object["wallitemtypes"]["furnitype"].as_object().unwrap() { + println!("{} {}", key, value); + } + } */ + Converters::FigureData => unimplemented!(), + Converters::FigureMap => todo!(), + Converters::EffectMap => todo!(), + Converters::FurniData => todo!(), + } +} diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index afc03f6..7a7c0f8 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -1,11 +1,5 @@ { - "build": { - "beforeDevCommand": "yarn dev", - "beforeBuildCommand": "yarn build", - "devPath": "http://localhost:1420", - "distDir": "../dist", - "withGlobalTauri": false - }, + "$schema": "../node_modules/@tauri-apps/cli/schema.json", "package": { "productName": "rypi-scrapper", "version": "0.0.0" @@ -44,7 +38,7 @@ "targets": "all" }, "security": { - "csp": null + "csp": "default-src blob: data: filesystem: ws: wss: http: https: tauri: 'unsafe-eval' 'unsafe-inline' 'self' img-src: 'self'" }, "updater": { "active": false diff --git a/tailwind.config.js b/tailwind.config.cjs similarity index 75% rename from tailwind.config.js rename to tailwind.config.cjs index 1e770f0..f063698 100644 --- a/tailwind.config.js +++ b/tailwind.config.cjs @@ -1,6 +1,6 @@ /** @type {import('tailwindcss').Config} */ module.exports = { - content: ['./src/**/*.tsx'], + content: ['./index.html', './src/**/*.{js,ts,jsx,tsx,css,md,mdx,html,json,scss}'], theme: { extend: { colors: { diff --git a/tsconfig.json b/tsconfig.json index 8debd34..b23217d 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -4,7 +4,6 @@ "useDefineForClassFields": true, "lib": ["DOM", "DOM.Iterable", "ESNext"], "allowJs": false, - "esModuleInterop": false, "allowSyntheticDefaultImports": true, "strict": true, "forceConsistentCasingInFileNames": true, @@ -13,8 +12,9 @@ "resolveJsonModule": true, "isolatedModules": true, "noEmit": true, - "jsx": "react-jsx" + "jsx": "preserve", + "types": ["vite/client"], + "jsxImportSource": "solid-js" }, - "include": ["src"], - "references": [{ "path": "./tsconfig.node.json" }] + "include": ["src"] } diff --git a/tsconfig.node.json b/tsconfig.node.json deleted file mode 100644 index 9d31e2a..0000000 --- a/tsconfig.node.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "compilerOptions": { - "composite": true, - "module": "ESNext", - "moduleResolution": "Node", - "allowSyntheticDefaultImports": true - }, - "include": ["vite.config.ts"] -} diff --git a/vite.config.tauri.ts b/vite.config.tauri.ts new file mode 100644 index 0000000..257858c --- /dev/null +++ b/vite.config.tauri.ts @@ -0,0 +1,32 @@ +import { defineConfig, mergeConfig } from 'vite' +import baseViteConfig from './vite.config' +import { tauri } from 'vite-plugin-tauri' + +// https://vitejs.dev/config/ +export default defineConfig( + mergeConfig( + baseViteConfig, + defineConfig({ + plugins: [tauri()], + // prevent vite from obscuring rust errors + clearScreen: false, + // Tauri expects a fixed port, fail if that port is not available + server: { + strictPort: true, + open: false + }, + // to make use of `TAURI_PLATFORM`, `TAURI_ARCH`, `TAURI_FAMILY`, + // `TAURI_PLATFORM_VERSION`, `TAURI_PLATFORM_TYPE` and `TAURI_DEBUG` + // env variables + envPrefix: ['VITE_', 'TAURI_'], + build: { + // Tauri supports es2021 + target: ['es2022', 'chrome100', 'safari13'], + // don't minify for debug builds + minify: !process.env.TAURI_DEBUG ? 'esbuild' : false, + // produce sourcemaps for debug builds + sourcemap: !!process.env.TAURI_DEBUG, + } + }) + ) +); diff --git a/vite.config.ts b/vite.config.ts index e1fc5f8..a1be805 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -1,26 +1,7 @@ import { defineConfig } from 'vite' -import react from '@vitejs/plugin-react' +import solidPlugin from 'vite-plugin-solid' -export default defineConfig(async () => ({ - plugins: [react()], - - // Vite options tailored for Tauri development and only applied in `tauri dev` or `tauri build` - // prevent vite from obscuring rust errors - clearScreen: false, - // tauri expects a fixed port, fail if that port is not available - server: { - port: 1420, - strictPort: true - }, - // to make use of `TAURI_DEBUG` and other env variables - // https://tauri.studio/v1/api/config#buildconfig.beforedevcommand - envPrefix: ['VITE_', 'TAURI_'], - build: { - // Tauri supports es2021 - target: process.env.TAURI_PLATFORM == 'windows' ? 'chrome105' : 'safari13', - // don't minify for debug builds - minify: !process.env.TAURI_DEBUG ? 'esbuild' : false, - // produce sourcemaps for debug builds - sourcemap: !!process.env.TAURI_DEBUG - } -})) +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [solidPlugin()] +})