main commit
This commit is contained in:
@@ -0,0 +1,51 @@
|
||||
name: Asphalt Sync & Submodule Update
|
||||
on:
|
||||
workflow_dispatch:
|
||||
schedule:
|
||||
- cron: "@weekly"
|
||||
|
||||
jobs:
|
||||
sync:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout Principal
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
submodules: "recursive"
|
||||
fetch-depth: 0
|
||||
token: ${{ secrets.ADMIN_TOKEN }}
|
||||
lfs: true
|
||||
|
||||
- name: Update Submodule to Latest And Pull LFS
|
||||
run: |
|
||||
git submodule update --remote --merge assets rooms
|
||||
git lfs pull
|
||||
git submodule foreach git lfs pull
|
||||
|
||||
- name: Setup Rokit
|
||||
uses: CompeyDev/setup-rokit@v0.2.1
|
||||
with:
|
||||
cache: true
|
||||
token: ${{ secrets.GITHUB }}
|
||||
|
||||
- name: Asphalt Sync
|
||||
env:
|
||||
ASPHALT_API_KEY: ${{ secrets.ROBLOX_OPEN_CLOUD_KEY }}
|
||||
run: |
|
||||
asphalt sync
|
||||
|
||||
- name: Commit and Push Changes
|
||||
run: |
|
||||
git config --global http.https://git.azur.webhop.me/.extraheader "AUTHORIZATION: basic $(echo -n :${{ secrets.GITEA_TOKEN }} | base64)"
|
||||
|
||||
git config user.name "Gitea Bot"
|
||||
git config user.email "bot@gitea.io"
|
||||
git add asphalt.lock.toml places/common/src/shared/assets/assets.luau places/common/src/shared/assets/assets.d.ts assets rooms
|
||||
|
||||
# On ne commit que s'il y a des changements
|
||||
if git diff --staged --quiet; then
|
||||
echo "No changes to commit"
|
||||
else
|
||||
git commit -m "chore: auto-sync assets and update submodule pointer"
|
||||
git push origin ${{ gitea.ref }}
|
||||
fi
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
node_modules
|
||||
|
||||
places/*/include
|
||||
places/*/flamework.build
|
||||
places/*/out
|
||||
places/*/dist
|
||||
|
||||
out
|
||||
|
||||
store
|
||||
|
||||
*sourcemap.json
|
||||
dist
|
||||
|
||||
.env
|
||||
.cookie
|
||||
|
||||
build.rbxl
|
||||
build.rbxlx
|
||||
|
||||
.eslintcache
|
||||
.pnpm-store
|
||||
@@ -0,0 +1,3 @@
|
||||
[submodule "assets"]
|
||||
path = assets
|
||||
url = https://git.azur.webhop.me/Next-Station/NS-Assets.git
|
||||
@@ -0,0 +1 @@
|
||||
pnpm exec lint-staged
|
||||
@@ -0,0 +1,9 @@
|
||||
out
|
||||
asphalt.lock.toml
|
||||
pnpm-lock.yaml
|
||||
**/assets.d.ts
|
||||
**/assets.luau
|
||||
.husky/pre-commit
|
||||
.prettierignore
|
||||
.gitignore
|
||||
.pnpm-store
|
||||
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"printWidth": 120,
|
||||
"tabWidth": 4,
|
||||
"trailingComma": "all",
|
||||
"useTabs": false,
|
||||
"plugins": ["prettier-plugin-toml"],
|
||||
"reorderKeys": true
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
# This file is automatically @generated by Asphalt.
|
||||
# It is not intended for manual editing.
|
||||
version = 2
|
||||
|
||||
[inputs.assets.087ddcc2dd2cc2deb264b3e4036fb6328d903d2a4d6bb90968dcbfc279fc4c85]
|
||||
asset_id = 120860142409755
|
||||
|
||||
[inputs.assets.0899ab5a89266f121a555a228662ab3af910d1c71ce167705e39c3fdc448bef1]
|
||||
asset_id = 129493473437352
|
||||
|
||||
[inputs.assets.16254d0038705124ed2810d226afc6d2967c6624929805cbc0228c79aba3fda1]
|
||||
asset_id = 93869395830786
|
||||
|
||||
[inputs.assets.1c58c2fc14f2f516dbd58dc16f34bda6367134641dfcb627f8086c47dede4e90]
|
||||
asset_id = 100562459880003
|
||||
|
||||
[inputs.assets.2e90437a7da6a62d8ae1e876549ae604ec126ba407b15e58a7880bbfafc94a1d]
|
||||
asset_id = 76052577701850
|
||||
|
||||
[inputs.assets.3b92d7f3eb07aff1e39ee3500246c1518432613393221ca6447c8336d171db7a]
|
||||
asset_id = 127096632190841
|
||||
|
||||
[inputs.assets.446d03c7531eabe6b47b594936d8348286244464d839cf3eb72ae3973dccb61b]
|
||||
asset_id = 106235234984065
|
||||
|
||||
[inputs.assets.59a127a8ed610fdff7280da01c188786a6584ee4c7d663306f34da1ceaae8b91]
|
||||
asset_id = 76565610359366
|
||||
|
||||
[inputs.assets.783d05701d8e1c7ee8a921dd38ebce10ac63cf6d9d9d6dc2a0911bd707acf846]
|
||||
asset_id = 74192100149187
|
||||
|
||||
[inputs.assets.7901f94d2cf93eb7c9462aa8cab8b29c9a831aa88d6484658689aeb1dc43b630]
|
||||
asset_id = 108803792430337
|
||||
|
||||
[inputs.assets.790c829c2c9f2b8c834388fcda0995e8faccdd16917566c85ead2889f652d7b7]
|
||||
asset_id = 115382005766484
|
||||
|
||||
[inputs.assets.a33a0096d10f763d9ecaa2bcd2073fbd7459e442bcc513d11b98c0978f0cdb01]
|
||||
asset_id = 76389194668757
|
||||
|
||||
[inputs.assets.a6eda86db3c35c873eebebe4b00bbf4ead1d9ce0b46794c6d7307e76e636a3ac]
|
||||
asset_id = 92619665942094
|
||||
|
||||
[inputs.assets.c1791db6412782a5c20f339cfebd1935e57cbc5a1773049180d5f86d2c13ef0c]
|
||||
asset_id = 119303577477446
|
||||
|
||||
[inputs.assets.ca7ea53a4ccb5537b42bddc6d0acea78aeab2d6b0701bd39b4e93cea0536a508]
|
||||
asset_id = 105469337892524
|
||||
|
||||
[inputs.assets.e202d94e76c0837180f98126df57e46b1736c3c87b21b23a735e6fd766a0ba1b]
|
||||
asset_id = 83329348606912
|
||||
|
||||
[inputs.assets.f2190bbd30b9a4da430e4b7173e580710c06adcfb196a36cb1a9f14c28ab66ba]
|
||||
asset_id = 97452653460582
|
||||
|
||||
[inputs.assets.fc7044e65ab24a62548baf2277b08403730a0fca593d027669ba1eb90aaf46bf]
|
||||
asset_id = 119045003698167
|
||||
|
||||
[inputs.assets.fdaf4607110f33aeef359b058f77c9753c72918fffcc72fc7190db49ca27c8f5]
|
||||
asset_id = 123486861030898
|
||||
@@ -0,0 +1,15 @@
|
||||
[creator]
|
||||
# the type of creator, either user or group
|
||||
type = "group"
|
||||
# Your UserId/GroupId here
|
||||
id = 35677829
|
||||
|
||||
[codegen]
|
||||
output_name = "assets"
|
||||
strip_extension = true
|
||||
style = "nested"
|
||||
typescript = true
|
||||
|
||||
[inputs.assets]
|
||||
output_path = "src/shared/assets"
|
||||
path = "assets/**/*"
|
||||
Submodule
+1
Submodule assets added at ee0a7e620d
@@ -0,0 +1,15 @@
|
||||
// @ts-check
|
||||
|
||||
import { defineConfig } from "cspell";
|
||||
|
||||
export default defineConfig({
|
||||
dictionaries: ["custom"],
|
||||
dictionaryDefinitions: [
|
||||
{
|
||||
addWords: true,
|
||||
name: "custom",
|
||||
path: "custom-words.txt",
|
||||
},
|
||||
],
|
||||
import: ["@isentinel/dict-roblox/cspell-ext.json", "@isentinel/dict-rbxts/cspell-ext.json"],
|
||||
});
|
||||
@@ -0,0 +1,9 @@
|
||||
darklua
|
||||
udim
|
||||
getfenv
|
||||
Serializeable # charm payload converter
|
||||
|
||||
# Project
|
||||
Hoarcekat
|
||||
isentinel
|
||||
rbxts
|
||||
@@ -0,0 +1,176 @@
|
||||
/* eslint-disable @typescript-eslint/naming-convention */
|
||||
// @ts-check
|
||||
import cspellESLint from "@cspell/eslint-plugin/recommended";
|
||||
import js from "@eslint/js";
|
||||
import checkFile from "eslint-plugin-check-file";
|
||||
import perfectionist from "eslint-plugin-perfectionist";
|
||||
import eslintPluginPrettierRecommended from "eslint-plugin-prettier/recommended";
|
||||
import roblox from "eslint-plugin-roblox-ts";
|
||||
import unusedImports from "eslint-plugin-unused-imports";
|
||||
import { defineConfig, globalIgnores } from "eslint/config";
|
||||
import ts from "typescript-eslint";
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore
|
||||
const { "sort-arrays": _, ...perfectionistRules } = perfectionist.rules; // eslint-disable-line @typescript-eslint/no-unused-vars
|
||||
|
||||
export default defineConfig(
|
||||
js.configs.recommended,
|
||||
ts.configs.recommended,
|
||||
roblox.configs.recommended,
|
||||
{
|
||||
...perfectionist.configs["recommended-natural"],
|
||||
rules: Object.fromEntries(
|
||||
Object.keys(perfectionistRules).map((ruleName) => [
|
||||
`perfectionist/${ruleName}`,
|
||||
[
|
||||
"warn",
|
||||
{
|
||||
order: "asc",
|
||||
type: "natural",
|
||||
},
|
||||
],
|
||||
]),
|
||||
),
|
||||
},
|
||||
eslintPluginPrettierRecommended,
|
||||
cspellESLint,
|
||||
{
|
||||
plugins: {
|
||||
"check-file": checkFile,
|
||||
"unused-imports": unusedImports,
|
||||
},
|
||||
rules: {
|
||||
"@typescript-eslint/naming-convention": [
|
||||
"warn",
|
||||
{
|
||||
format: ["PascalCase"],
|
||||
selector: "class",
|
||||
},
|
||||
{
|
||||
format: ["camelCase"],
|
||||
selector: "classMethod",
|
||||
},
|
||||
{
|
||||
format: ["camelCase"],
|
||||
selector: "classProperty",
|
||||
},
|
||||
{
|
||||
format: ["PascalCase"],
|
||||
selector: "enum",
|
||||
},
|
||||
{
|
||||
format: ["PascalCase"],
|
||||
selector: "enumMember",
|
||||
},
|
||||
{
|
||||
custom: {
|
||||
match: true,
|
||||
regex: "^(use[A-Z][a-zA-Z0-9]*|select[A-Z][a-zA-Z0-9]*|[A-Z][a-zA-Z0-9]*)$",
|
||||
},
|
||||
format: ["PascalCase", "camelCase"],
|
||||
modifiers: ["exported"],
|
||||
selector: "function",
|
||||
},
|
||||
{
|
||||
format: ["PascalCase"],
|
||||
leadingUnderscore: "allowSingleOrDouble",
|
||||
selector: "interface",
|
||||
trailingUnderscore: "allowSingleOrDouble",
|
||||
},
|
||||
{
|
||||
format: ["PascalCase", "camelCase"],
|
||||
selector: "objectLiteralMethod",
|
||||
},
|
||||
{
|
||||
format: ["PascalCase", "camelCase"],
|
||||
selector: "objectLiteralProperty",
|
||||
},
|
||||
{
|
||||
format: ["PascalCase", "camelCase"],
|
||||
selector: "objectLiteralProperty",
|
||||
},
|
||||
{
|
||||
format: ["camelCase"],
|
||||
selector: "parameter",
|
||||
},
|
||||
{
|
||||
format: ["camelCase", "PascalCase"],
|
||||
modifiers: ["destructured"],
|
||||
selector: "parameter",
|
||||
},
|
||||
{
|
||||
format: ["camelCase"],
|
||||
selector: "parameterProperty",
|
||||
},
|
||||
{
|
||||
format: ["StrictPascalCase"],
|
||||
selector: "typeAlias",
|
||||
},
|
||||
{
|
||||
custom: {
|
||||
match: true,
|
||||
regex: "^(on[A-Z][a-zA-Z0-9]*|[A-Z][a-zA-Z0-9]*)$",
|
||||
},
|
||||
format: ["StrictPascalCase", "strictCamelCase"],
|
||||
selector: "typeMethod",
|
||||
},
|
||||
{
|
||||
format: ["StrictPascalCase"],
|
||||
selector: "typeParameter",
|
||||
},
|
||||
{
|
||||
format: ["strictCamelCase", "StrictPascalCase", "UPPER_CASE"],
|
||||
leadingUnderscore: "allowSingleOrDouble",
|
||||
selector: "typeProperty",
|
||||
trailingUnderscore: "allowSingleOrDouble",
|
||||
},
|
||||
{
|
||||
format: ["strictCamelCase", "StrictPascalCase", "UPPER_CASE"],
|
||||
leadingUnderscore: "allowSingleOrDouble",
|
||||
selector: "typeProperty",
|
||||
trailingUnderscore: "allowSingleOrDouble",
|
||||
},
|
||||
{
|
||||
format: ["UPPER_CASE", "PascalCase"],
|
||||
modifiers: ["exported", "const"],
|
||||
selector: "variable",
|
||||
},
|
||||
{
|
||||
custom: {
|
||||
match: true,
|
||||
regex: "^(use[A-Z][a-zA-Z0-9]*|get[A-Z][a-zA-Z0-9]*|[A-Z][a-zA-Z0-9]*|[a-z][a-zA-Z0-9]*Atom)$",
|
||||
},
|
||||
format: ["PascalCase", "camelCase"],
|
||||
modifiers: ["exported", "const"],
|
||||
selector: "variable",
|
||||
types: ["function"],
|
||||
},
|
||||
{
|
||||
format: ["UPPER_CASE"],
|
||||
modifiers: ["exported", "const"],
|
||||
selector: "variable",
|
||||
types: ["boolean", "number", "string"],
|
||||
},
|
||||
],
|
||||
"@typescript-eslint/no-array-constructor": "off",
|
||||
"@typescript-eslint/no-empty-object-type": "off",
|
||||
"@typescript-eslint/no-require-imports": "off",
|
||||
"@typescript-eslint/no-unused-vars": [
|
||||
"error",
|
||||
{
|
||||
varsIgnorePattern: "^[A-Z].*(Service|Controller|Component)$",
|
||||
},
|
||||
],
|
||||
"check-file/filename-naming-convention": [
|
||||
"error",
|
||||
{ "**/*": "KEBAB_CASE" },
|
||||
{ ignoreMiddleExtensions: true },
|
||||
],
|
||||
"check-file/folder-naming-convention": ["error", { "**/": "KEBAB_CASE" }],
|
||||
"no-array-constructor": "off",
|
||||
"prettier/prettier": "warn",
|
||||
},
|
||||
},
|
||||
globalIgnores(["/out", "**/assets.d.ts", "scripts"]),
|
||||
);
|
||||
@@ -0,0 +1,7 @@
|
||||
/* eslint-disable @typescript-eslint/naming-convention */
|
||||
// @ts-check
|
||||
|
||||
export default {
|
||||
"!(*.ts|*.tsx)": ["prettier -u --write --cache"],
|
||||
"*.{ts,tsx}": ["eslint --fix --cache", "prettier --write --cache"],
|
||||
};
|
||||
@@ -0,0 +1,61 @@
|
||||
{
|
||||
"name": "@next-station/common",
|
||||
"version": "1.0.0",
|
||||
"description": "Common code of next station.",
|
||||
"main": "index.js",
|
||||
"trustedDependencies": [
|
||||
"husky"
|
||||
],
|
||||
"scripts": {
|
||||
"lint": "eslint --cache",
|
||||
"prepare": "husky"
|
||||
},
|
||||
"keywords": [],
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"devDependencies": {
|
||||
"@cspell/eslint-plugin": "^10.0.0",
|
||||
"@eslint/js": "^10.0.0",
|
||||
"@isentinel/dict-rbxts": "^1.0.2",
|
||||
"@isentinel/dict-roblox": "^1.0.4",
|
||||
"@rbxts/compiler-types": "3.0.0-types.0",
|
||||
"@rbxts/types": "^1.0.912",
|
||||
"@types/node": "^25.6.0",
|
||||
"@typescript-eslint/eslint-plugin": "^8.57.1",
|
||||
"@typescript-eslint/parser": "^8.57.1",
|
||||
"cspell": "^10.0.0",
|
||||
"eslint": "^10.0.0",
|
||||
"eslint-config-prettier": "^10.1.8",
|
||||
"eslint-plugin-check-file": "^3.3.1",
|
||||
"eslint-plugin-perfectionist": "^5.7.0",
|
||||
"eslint-plugin-prettier": "^5.5.5",
|
||||
"eslint-plugin-roblox-ts": "^1.4.0",
|
||||
"eslint-plugin-unused-imports": "^4.4.1",
|
||||
"husky": "^9.1.7",
|
||||
"lint-staged": "^17.0.0",
|
||||
"prettier": "^3.8.1",
|
||||
"prettier-plugin-toml": "^2.0.6",
|
||||
"rbxts-transformer-access": "^1.1.2",
|
||||
"rbxts-transformer-flamework": "^1.3.2",
|
||||
"rbxts-transformer-instances": "^1.0.1",
|
||||
"rbxts-transformer-services": "^1.1.1",
|
||||
"roblox-ts": "^3.0.0",
|
||||
"tsc-progress": "^1.0.4",
|
||||
"typescript": "^5.5.4",
|
||||
"typescript-eslint": "^8.57.1",
|
||||
"typescript-file-copy-plugin": "^1.0.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"@flamework/components": "^1.3.2",
|
||||
"@flamework/core": "^1.3.2",
|
||||
"@flamework/networking": "^1.3.2",
|
||||
"@rbxts/charm": "^0.10.0",
|
||||
"@rbxts/charm-sync": "^0.3.0",
|
||||
"@rbxts/object-utils": "^1.0.4",
|
||||
"@rbxts/services": "^1.6.0",
|
||||
"@rbxts/t": "^3.2.1",
|
||||
"@rbxts/vide": "^0.6.1",
|
||||
"@rbxts/vide-charm": "^0.3.0"
|
||||
},
|
||||
"packageManager": "pnpm@11.5.0"
|
||||
}
|
||||
Generated
+3086
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,3 @@
|
||||
publicHoistPattern:
|
||||
- "*@rbxts*"
|
||||
- "*@flamework*"
|
||||
@@ -0,0 +1,19 @@
|
||||
{
|
||||
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
|
||||
"packageRules": [
|
||||
{
|
||||
"matchPackageNames": ["typescript"],
|
||||
"enabled": false
|
||||
}
|
||||
],
|
||||
|
||||
"customManagers": [
|
||||
{
|
||||
"customType": "regex",
|
||||
"fileMatch": ["(^|/)rokit\\.toml$"],
|
||||
"matchStrings": ["\\s*(?<depName>[\\w\\d\\-_]+\\/[\\w\\d\\-_]+)@(?<currentValue>[\\d\\.]+)"],
|
||||
"datasourceTemplate": "github-releases",
|
||||
"depNameTemplate": "{{{depName}}}"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
# This file lists tools managed by Rokit, a toolchain manager for Roblox projects.
|
||||
# For more information, see https://github.com/rojo-rbx/rokit
|
||||
|
||||
# New tools can be added by running `rokit add <tool>` in a terminal.
|
||||
|
||||
[tools]
|
||||
asphalt = "jackTabsCode/asphalt@2.0.1"
|
||||
@@ -0,0 +1,95 @@
|
||||
import settingsFile from "@common/shared/settings";
|
||||
import { SettingDefinition, SettingRealType, SettingType } from "@common/shared/typings/settings";
|
||||
import { Controller, OnStart } from "@flamework/core";
|
||||
import { Atom, atom } from "@rbxts/charm";
|
||||
import Object, { keys } from "@rbxts/object-utils";
|
||||
|
||||
import { Events, Functions } from "../network";
|
||||
|
||||
/**
|
||||
* Setting Management Controller
|
||||
*/
|
||||
@Controller()
|
||||
export class SettingsController implements OnStart {
|
||||
private atomsCache: Map<string, Map<string, Atom<SettingRealType<SettingType>>>> = new Map();
|
||||
private defCache: Map<string, Map<string, SettingDefinition>> = new Map();
|
||||
/**
|
||||
* Fetch player settings from the server.
|
||||
*/
|
||||
fetchSettings() {
|
||||
Functions.settings.GetSettings().then((settings) => {
|
||||
settings.forEach((section, sectionKey) => {
|
||||
const sectionAtoms = this.atomsCache.get(sectionKey)!;
|
||||
section.forEach((val, key) => {
|
||||
sectionAtoms.get(key)?.(val);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
/**
|
||||
* Get all sections names.
|
||||
* @returns Sections names in the settings file.
|
||||
*/
|
||||
getSections() {
|
||||
return keys(this.atomsCache);
|
||||
}
|
||||
/**
|
||||
* Get All atoms and their definition in the given section.
|
||||
* @param section The name of the section.
|
||||
* @returns An array with setting definition and an the atom linked to the type definition.
|
||||
*/
|
||||
getSectionWithDef(section: string) {
|
||||
const ret: [SettingDefinition, Atom<unknown>][] = [];
|
||||
this.atomsCache.get(section)?.forEach((value, key) => {
|
||||
ret.push([this.defCache.get(section)!.get(key)!, value]);
|
||||
});
|
||||
return ret;
|
||||
}
|
||||
/**
|
||||
* Get an atom with an section name and a setting name.
|
||||
* @param section Section name.
|
||||
* @param setting Setting name.
|
||||
* @returns The atom linked to the setting.
|
||||
*/
|
||||
getSetting(section: string, setting: string) {
|
||||
return this.atomsCache.get(section)?.get(setting);
|
||||
}
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
onStart(): void {
|
||||
this.setupAtoms();
|
||||
this.fetchSettings();
|
||||
}
|
||||
/**
|
||||
* Send a section of settings to the server to save.
|
||||
* @param section The section to save.
|
||||
*/
|
||||
saveSettings(section: string) {
|
||||
const atoms = this.atomsCache.get(section);
|
||||
if (!atoms) return;
|
||||
const map = new Map<string, boolean | number | string>();
|
||||
atoms.forEach((value, key) => {
|
||||
map.set(key, value() as boolean | number | string);
|
||||
});
|
||||
Events.settings.SetSettings(section, map);
|
||||
}
|
||||
/**
|
||||
* Setup atoms and definition at service start.
|
||||
*/
|
||||
private setupAtoms() {
|
||||
const sections = Object.keys<Record<string, SettingDefinition[]>>(settingsFile).filter((key) =>
|
||||
typeIs(settingsFile[key], "table"),
|
||||
);
|
||||
sections.forEach((key) => {
|
||||
const map = new Map<string, Charm.Atom<unknown>>();
|
||||
const defMap = new Map<string, SettingDefinition>();
|
||||
this.atomsCache.set(key, map);
|
||||
this.defCache.set(key, defMap);
|
||||
settingsFile[key].forEach((def) => {
|
||||
map.set(def.id, atom(def.default));
|
||||
defMap.set(def.id, def);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
import { GlobalEvents, GlobalFunctions } from "@common/shared/network";
|
||||
|
||||
export const Events = GlobalEvents.createClient({});
|
||||
export const Functions = GlobalFunctions.createClient({});
|
||||
@@ -0,0 +1,59 @@
|
||||
import { NotDerivate, useBox } from "@common/shared/utils/ui/vide";
|
||||
import { Atom } from "@rbxts/charm";
|
||||
import Vide, { Derivable, source } from "@rbxts/vide";
|
||||
|
||||
/**
|
||||
* Props of a toggle.
|
||||
*/
|
||||
interface ToggleProps {
|
||||
/**
|
||||
* A charm atom linked to the toggle.
|
||||
*/
|
||||
Atom?: Atom<boolean>;
|
||||
/**
|
||||
* The position of the toggle in roblox ui.
|
||||
*/
|
||||
Position?: Derivable<UDim2>;
|
||||
/**
|
||||
* The size of the toggle
|
||||
*/
|
||||
Size?: Derivable<UDim2>;
|
||||
}
|
||||
|
||||
/**
|
||||
* A toggle is a UI component linked to an boolean.
|
||||
* @param props Props of the toggle.
|
||||
* @returns A Vide node with the toggle.
|
||||
*/
|
||||
export function Toggle(props: ToggleProps = {}) {
|
||||
const [enable, setEnable] = useBox(props.Atom, false);
|
||||
const sphereSize = source(0);
|
||||
return (
|
||||
<imagebutton
|
||||
BackgroundColor3={new Color3(1, 1, 1)}
|
||||
MouseButton1Click={() => setEnable(!enable())}
|
||||
Position={props?.Position}
|
||||
Size={props?.Size ?? UDim2.fromOffset(90, 30)}
|
||||
>
|
||||
<uicorner CornerRadius={new UDim(1, 0)} />
|
||||
<uiaspectratioconstraint AspectRatio={1.8} />
|
||||
<frame
|
||||
BackgroundColor3={new Color3(0.5, 0.5, 0.5)}
|
||||
Position={new UDim2(0, 2, 0, 2)}
|
||||
Size={new UDim2(1, -4, 1, -4)}
|
||||
Visible={NotDerivate(enable)}
|
||||
>
|
||||
<uicorner CornerRadius={new UDim(1, 0)} />
|
||||
</frame>
|
||||
<frame
|
||||
AbsoluteSizeChanged={(value) => sphereSize(value.X)}
|
||||
BackgroundColor3={new Color3(0, 0, 0)}
|
||||
Position={() => (enable() ? new UDim2(1, -sphereSize() - 2, 0, 2) : new UDim2(0, 2, 0, 2))}
|
||||
Size={new UDim2(1, -4, 1, -4)}
|
||||
>
|
||||
<uicorner CornerRadius={new UDim(1, 0)} />
|
||||
<uiaspectratioconstraint AspectRatio={1} />
|
||||
</frame>
|
||||
</imagebutton>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,127 @@
|
||||
import { SettingsController } from "@common/client/controllers/settings";
|
||||
import { SettingDefinition, SettingRealType, SettingType } from "@common/shared/typings/settings";
|
||||
import { Atom } from "@rbxts/charm";
|
||||
import Vide, { Case, For, Source, source, Switch } from "@rbxts/vide";
|
||||
|
||||
import { Toggle } from "../global/toggle";
|
||||
|
||||
/**
|
||||
* The settings menu as vide components.
|
||||
* @param settingsController The settings Controller for fetching settings.
|
||||
* @returns A Vide node with the settings menu.
|
||||
*/
|
||||
export function Settings(settingsController: SettingsController) {
|
||||
const keys = source(settingsController.getSections());
|
||||
const panel = source(keys()[0]);
|
||||
|
||||
return (
|
||||
<frame
|
||||
BackgroundColor3={new Color3(0, 0, 0)}
|
||||
Position={UDim2.fromScale(0.05, 0.05)}
|
||||
Size={UDim2.fromScale(0.9, 0.9)}
|
||||
>
|
||||
<uicorner />
|
||||
<uistroke Color={new Color3(1, 1, 1)} />
|
||||
<scrollingframe BackgroundTransparency={1} Size={UDim2.fromScale(0.3, 1)}>
|
||||
<uigridlayout CellPadding={UDim2.fromOffset(0, 0)} CellSize={new UDim2(1, 0, 0, 40)} />
|
||||
<For each={keys}>{(group) => <SettingsGroup name={group} panelSource={panel} />}</For>
|
||||
</scrollingframe>
|
||||
<frame Position={UDim2.fromScale(0.3, 0)} Size={new UDim2(0, 1, 1, 0)} />
|
||||
<frame BackgroundTransparency={1} Position={new UDim2(0.3, 10, 0, 0)} Size={new UDim2(0.7, -10, 1, 0)}>
|
||||
<uilistlayout Padding={new UDim(0, 10)} />
|
||||
<For each={() => settingsController.getSectionWithDef(panel())}>
|
||||
{([def, atom]) => <SettingsEntry atom={atom} definition={def} />}
|
||||
</For>
|
||||
</frame>
|
||||
</frame>
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* An entry in the settings menu.
|
||||
* @param props Properties of the entry.
|
||||
* @param props.definition Setting definition.
|
||||
* @param props.atom Charm atom with the value of the setting.
|
||||
* @returns A setting entry.
|
||||
*/
|
||||
export function SettingsEntry<T extends SettingType>(props: {
|
||||
/**
|
||||
* The atom with the value of the setting.
|
||||
*/
|
||||
atom: Atom<SettingRealType<T>>;
|
||||
/**
|
||||
* The definition of the setting.
|
||||
*/
|
||||
definition: SettingDefinition<T>;
|
||||
}) {
|
||||
return (
|
||||
<frame AutomaticSize={Enum.AutomaticSize.Y} BackgroundTransparency={1}>
|
||||
<uilistlayout />
|
||||
<textlabel
|
||||
AutomaticSize={Enum.AutomaticSize.Y}
|
||||
BackgroundTransparency={1}
|
||||
Text={props.definition.name}
|
||||
TextColor3={new Color3(1, 1, 1)}
|
||||
TextSize={30}
|
||||
TextXAlignment={Enum.TextXAlignment.Left}
|
||||
/>
|
||||
<textlabel
|
||||
AutomaticSize={Enum.AutomaticSize.Y}
|
||||
BackgroundTransparency={1}
|
||||
Text={props.definition.description}
|
||||
TextColor3={new Color3(1, 1, 1)}
|
||||
TextSize={25}
|
||||
TextTransparency={0.5}
|
||||
TextXAlignment={Enum.TextXAlignment.Left}
|
||||
/>
|
||||
<Switch condition={() => props.definition.type}>
|
||||
<Case match={SettingType.Boolean}>
|
||||
{() => (
|
||||
<>
|
||||
<frame Size={UDim2.fromOffset(0, 10)} />
|
||||
<Toggle Atom={props.atom as unknown as Atom<boolean>} />
|
||||
</>
|
||||
)}
|
||||
</Case>
|
||||
</Switch>
|
||||
</frame>
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* A button for each setting section the settings menu.
|
||||
* @param props Properties of the button.
|
||||
* @param props.name The name of the entry.
|
||||
* @param props.panelSource A vide source for the current panel.
|
||||
* @returns The Settings group button.
|
||||
*/
|
||||
export function SettingsGroup(props: {
|
||||
/**
|
||||
* The name of the settings group.
|
||||
*/
|
||||
name: string;
|
||||
/**
|
||||
* A vide source with the name of the current panel.
|
||||
*/
|
||||
panelSource: Source<string>;
|
||||
}) {
|
||||
return (
|
||||
<frame BackgroundTransparency={1}>
|
||||
<textbutton
|
||||
BackgroundTransparency={1}
|
||||
FontFace={() =>
|
||||
props.name === props.panelSource()
|
||||
? Font.fromEnum(Enum.Font.SourceSansBold)
|
||||
: Font.fromEnum(Enum.Font.SourceSans)
|
||||
}
|
||||
MouseButton1Click={() => {
|
||||
props.panelSource(props.name);
|
||||
}}
|
||||
Size={UDim2.fromScale(1, 1)}
|
||||
Text={props.name}
|
||||
TextColor3={new Color3(1, 1, 1)}
|
||||
TextScaled={true}
|
||||
/>
|
||||
</frame>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
import { Toggle } from "@common/client/ui/components/global/toggle";
|
||||
import { Hoarcekat } from "@common/shared/utils/ui/hoarcekat";
|
||||
import { Node } from "@rbxts/vide";
|
||||
|
||||
export = Hoarcekat(Toggle as () => Node);
|
||||
@@ -0,0 +1,4 @@
|
||||
import { GlobalEvents, GlobalFunctions } from "@common/shared/network";
|
||||
|
||||
export const Events = GlobalEvents.createServer({});
|
||||
export const Functions = GlobalFunctions.createServer({});
|
||||
@@ -0,0 +1,59 @@
|
||||
import { Service } from "@flamework/core";
|
||||
import { DataStoreService } from "@rbxts/services";
|
||||
|
||||
/**
|
||||
* A data store, linked to a roblox DataStore and the DataService.
|
||||
*/
|
||||
export class Store {
|
||||
/**
|
||||
* @param service The instance of the data service.
|
||||
* @param name The name of the store.
|
||||
* @param realStore The real roblox dataStore.
|
||||
*/
|
||||
constructor(
|
||||
private service: DataService,
|
||||
private name: string,
|
||||
private realStore: DataStore,
|
||||
) {}
|
||||
/**
|
||||
* Get a data in the database.
|
||||
* @param key The key of the data.
|
||||
* @returns The value of the key.
|
||||
*/
|
||||
get<T>(key: string): T | undefined {
|
||||
const [value] = this.realStore.GetAsync(key);
|
||||
return value as T;
|
||||
}
|
||||
/**
|
||||
* Set a data in the database.
|
||||
* @param key The key of the data.
|
||||
* @param value The value to set.
|
||||
*/
|
||||
set<T>(key: string, value: T) {
|
||||
this.realStore.SetAsync(key, value);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Alias Alastor Service
|
||||
*
|
||||
* Work in Progress
|
||||
*
|
||||
* A flamework service to manage the roblox DataStoreService.
|
||||
*/
|
||||
@Service()
|
||||
export class DataService {
|
||||
private cache = new Map<string, Store>();
|
||||
/**
|
||||
* Get a store with his name.
|
||||
* @param name The name of the store.
|
||||
* @returns A Store class linked the given name.
|
||||
*/
|
||||
getStore(name: string): Store {
|
||||
const store = this.cache.get(name);
|
||||
if (store) return store;
|
||||
const newStore = new Store(this, name, DataStoreService.GetDataStore(name));
|
||||
this.cache.set(name, newStore);
|
||||
return newStore;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
import { OnPlayerJoined, OnPlayerQuit } from "@common/shared/modding/players";
|
||||
import { Modding, OnStart } from "@flamework/core";
|
||||
import { Players } from "@rbxts/services";
|
||||
|
||||
/**
|
||||
* This Service Manage some player event with modding.
|
||||
*/
|
||||
export class PlayerEventsService implements OnStart {
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
onStart() {
|
||||
const playerJoinListener = new Set<OnPlayerJoined>();
|
||||
const playerQuitListener = new Set<OnPlayerQuit>();
|
||||
|
||||
Modding.onListenerAdded<OnPlayerJoined>((object) => playerJoinListener.add(object));
|
||||
Modding.onListenerRemoved<OnPlayerJoined>((object) => playerJoinListener.delete(object));
|
||||
Modding.onListenerAdded<OnPlayerQuit>((object) => playerQuitListener.add(object));
|
||||
Modding.onListenerRemoved<OnPlayerQuit>((object) => playerQuitListener.delete(object));
|
||||
|
||||
Players.PlayerAdded.Connect((player) => {
|
||||
for (const listener of playerJoinListener) {
|
||||
task.spawn(() => listener.onPlayerJoined(player));
|
||||
}
|
||||
});
|
||||
|
||||
Players.PlayerRemoving.Connect((player) => {
|
||||
for (const listener of playerQuitListener) {
|
||||
task.spawn(() => listener.onPlayerQuit(player));
|
||||
}
|
||||
});
|
||||
|
||||
for (const player of Players.GetPlayers()) {
|
||||
for (const listener of playerJoinListener) {
|
||||
task.spawn(() => listener.onPlayerJoined(player));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
import { OnPlayerJoined } from "@common/shared/modding/players";
|
||||
import SettingsFile from "@common/shared/settings";
|
||||
import { SetSetting, SettingTypeChecker } from "@common/shared/typings/settings";
|
||||
import { OnStart, Service } from "@flamework/core";
|
||||
|
||||
import { Events, Functions } from "../network";
|
||||
import { DataService, Store } from "./data";
|
||||
|
||||
/**
|
||||
* The Setting Manager service
|
||||
*/
|
||||
@Service()
|
||||
export class SettingsService implements OnPlayerJoined, OnStart {
|
||||
cache = new Map<number, SetSetting>();
|
||||
store: Store;
|
||||
/**
|
||||
* @param dataService The instance of the DataService.
|
||||
*/
|
||||
constructor(private dataService: DataService) {
|
||||
this.store = this.dataService.getStore("UserSettings");
|
||||
}
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
onPlayerJoined(player: Player): void {
|
||||
const store: SetSetting = this.store.get(tostring(player.UserId)) ?? new Map();
|
||||
this.cache.set(player.UserId, store);
|
||||
}
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
onStart(): void {
|
||||
Functions.settings.GetVersion.setCallback(() => SettingsFile.version);
|
||||
|
||||
Functions.settings.GetSettings.setCallback((player) => {
|
||||
return this.cache.get(player.UserId) ?? this.store.get<SetSetting>(tostring(player.UserId)) ?? new Map();
|
||||
});
|
||||
|
||||
Events.settings.SetSettings.connect((player, section, settings) => {
|
||||
settings.forEach((value, key) => {
|
||||
const setting = SettingsFile[section]?.find((sett) => sett.id === key);
|
||||
if (setting === undefined) return;
|
||||
if (typeIs(value, SettingTypeChecker[setting.type])) {
|
||||
// TODO Better checker
|
||||
this.cache.get(player.UserId)?.get(section)?.set(key, value);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
Vendored
+39
@@ -0,0 +1,39 @@
|
||||
// This file is automatically @generated by Asphalt.
|
||||
// It is not intended for manual editing.
|
||||
declare const assets: {
|
||||
audio: {
|
||||
music: {
|
||||
"a-bench-for-ducks.ogg": Content
|
||||
"eggplants-in-the-sky.ogg": Content
|
||||
"lobby.ogg": Content
|
||||
"meowmeowmeow.ogg": Content
|
||||
"railway-resonance.ogg": Content
|
||||
"root.ogg": Content
|
||||
"solstice.ogg": Content
|
||||
"stay-on-track.ogg": Content
|
||||
"weltschmerz.ogg": Content
|
||||
}
|
||||
}
|
||||
images: {
|
||||
kiwirina: {
|
||||
"LUNA....png": Content
|
||||
"eyes.png": Content
|
||||
"kiwi tag.png": Content
|
||||
"lateworkerconceptmob.png": Content
|
||||
"next station ost cover.png": Content
|
||||
"porte closed.png": Content
|
||||
"porte open.png": Content
|
||||
}
|
||||
svg: {
|
||||
"cube.svg": Content
|
||||
}
|
||||
}
|
||||
rooms: {
|
||||
normal: {
|
||||
"plus-corridor.rbxm": Content
|
||||
"straight-corridor.rbxm": Content
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export = assets
|
||||
@@ -0,0 +1,39 @@
|
||||
-- This file is automatically @generated by Asphalt.
|
||||
-- It is not intended for manual editing.
|
||||
local assets = {
|
||||
audio = {
|
||||
music = {
|
||||
["a-bench-for-ducks.ogg"] = Content.fromUri("rbxassetid://93869395830786"),
|
||||
["eggplants-in-the-sky.ogg"] = Content.fromUri("rbxassetid://74192100149187"),
|
||||
["lobby.ogg"] = Content.fromUri("rbxassetid://119303577477446"),
|
||||
["meowmeowmeow.ogg"] = Content.fromUri("rbxassetid://106235234984065"),
|
||||
["railway-resonance.ogg"] = Content.fromUri("rbxassetid://97452653460582"),
|
||||
["root.ogg"] = Content.fromUri("rbxassetid://76389194668757"),
|
||||
["solstice.ogg"] = Content.fromUri("rbxassetid://76565610359366"),
|
||||
["stay-on-track.ogg"] = Content.fromUri("rbxassetid://123486861030898"),
|
||||
["weltschmerz.ogg"] = Content.fromUri("rbxassetid://108803792430337"),
|
||||
},
|
||||
},
|
||||
images = {
|
||||
kiwirina = {
|
||||
["LUNA....png"] = Content.fromUri("rbxassetid://105469337892524"),
|
||||
["eyes.png"] = Content.fromUri("rbxassetid://115382005766484"),
|
||||
["kiwi tag.png"] = Content.fromUri("rbxassetid://100562459880003"),
|
||||
["lateworkerconceptmob.png"] = Content.fromUri("rbxassetid://120860142409755"),
|
||||
["next station ost cover.png"] = Content.fromUri("rbxassetid://127096632190841"),
|
||||
["porte closed.png"] = Content.fromUri("rbxassetid://119045003698167"),
|
||||
["porte open.png"] = Content.fromUri("rbxassetid://83329348606912"),
|
||||
},
|
||||
svg = {
|
||||
["cube.svg"] = Content.fromUri("rbxassetid://92619665942094"),
|
||||
},
|
||||
},
|
||||
rooms = {
|
||||
normal = {
|
||||
["plus-corridor.rbxm"] = Content.fromUri("rbxassetid://129493473437352"),
|
||||
["straight-corridor.rbxm"] = Content.fromUri("rbxassetid://76052577701850"),
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
return assets
|
||||
@@ -0,0 +1,50 @@
|
||||
import { Modding } from "@flamework/core";
|
||||
|
||||
export class Generation {
|
||||
/**
|
||||
* Load all rooms in the given folder.
|
||||
* @metadata macro intrinsic-arg-shift
|
||||
*/
|
||||
addPaths<T extends string>(path: T, meta?: Modding.Intrinsic<"path", [T]>): void;
|
||||
addPaths<T extends string>(paths: T[][]): void {
|
||||
// WIP
|
||||
print(paths);
|
||||
}
|
||||
}
|
||||
|
||||
// Placeholder
|
||||
export class PrefixSumArray<T extends defined> {
|
||||
private bounds: number[] = [];
|
||||
private totalLength: number = 0;
|
||||
private values: T[] = [];
|
||||
|
||||
add(size: number, value: T) {
|
||||
if (size <= 0) return;
|
||||
this.totalLength += size;
|
||||
|
||||
this.bounds.push(this.totalLength);
|
||||
this.values.push(value);
|
||||
}
|
||||
|
||||
get(index: number) {
|
||||
if (typeIs(index, "number") && index < 1 && index > this.totalLength) return undefined;
|
||||
|
||||
let low = 1;
|
||||
let high = this.bounds.size();
|
||||
|
||||
while (low < high) {
|
||||
const mid = math.floor((low + high) / 2);
|
||||
if (this.bounds[mid] < index) {
|
||||
low = mid + 1;
|
||||
} else {
|
||||
high = mid;
|
||||
}
|
||||
}
|
||||
|
||||
return this.values[low];
|
||||
}
|
||||
|
||||
size() {
|
||||
return this.totalLength;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
type ToNumberTuple<T extends readonly defined[]> = {
|
||||
[K in keyof T]: number;
|
||||
};
|
||||
|
||||
export class NArray<N extends number[], T extends defined> {
|
||||
private array: Array<T>;
|
||||
private dims: N;
|
||||
|
||||
constructor(value?: T, ...dims: N) {
|
||||
this.dims = dims;
|
||||
const size = factorAnArray(dims);
|
||||
this.array = value !== undefined ? new Array(size, value) : new Array(size);
|
||||
}
|
||||
|
||||
get(...index: ToNumberTuple<N>): T | undefined {
|
||||
return this.array[this.getIndex(index)];
|
||||
}
|
||||
|
||||
set(value: T, ...index: ToNumberTuple<N>) {
|
||||
this.array[this.getIndex(index)] = value;
|
||||
}
|
||||
|
||||
private getIndex(index: ToNumberTuple<N>) {
|
||||
let factor = 1;
|
||||
let ret = 0;
|
||||
index.forEach((value, index) => {
|
||||
if (index === 0) ret += value;
|
||||
factor *= this.dims[index - 1];
|
||||
ret += value * factor;
|
||||
});
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
function factorAnArray(arr: number[]) {
|
||||
let size = 1;
|
||||
for (const dim of arr) {
|
||||
size *= dim;
|
||||
}
|
||||
return size;
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
/**
|
||||
* Hook into the Singleton to a event which trigger each player join.
|
||||
*/
|
||||
export interface OnPlayerJoined {
|
||||
/**
|
||||
* This function will be called when a player join the game.
|
||||
*/
|
||||
onPlayerJoined(player: Player): void;
|
||||
}
|
||||
|
||||
/**
|
||||
* Hook into the Singleton to a event which trigger each player quit.
|
||||
*/
|
||||
export interface OnPlayerQuit {
|
||||
/**
|
||||
* This function will be called when a player quit the game.
|
||||
*/
|
||||
onPlayerQuit(player: Player): void;
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
import { Networking } from "@flamework/networking";
|
||||
|
||||
import { SetSetting } from "./typings/settings";
|
||||
|
||||
/**
|
||||
* Global client to server events.
|
||||
*/
|
||||
export interface ClientToServerEvents {
|
||||
/**
|
||||
* Setting client to server events.
|
||||
*/
|
||||
settings: {
|
||||
/**
|
||||
* Send current player setting to the player.
|
||||
*/
|
||||
SetSettings(section: string, settings: Map<string, boolean | number | string>): void;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Global client to server functions.
|
||||
*/
|
||||
export interface ClientToServerFunctions {
|
||||
/**
|
||||
* Setting client to server functions.
|
||||
*/
|
||||
settings: {
|
||||
/**
|
||||
* Get saved settings.
|
||||
*/
|
||||
GetSettings(): SetSetting;
|
||||
/**
|
||||
* Get server settings version
|
||||
*/
|
||||
GetVersion(): number;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Global server to client events.
|
||||
*/
|
||||
export interface ServerToClientEvents {}
|
||||
|
||||
/**
|
||||
* Global server to client functions.
|
||||
*/
|
||||
export interface ServerToClientFunctions {}
|
||||
|
||||
export const GlobalEvents = Networking.createEvent<ClientToServerEvents, ServerToClientEvents>();
|
||||
export const GlobalFunctions = Networking.createFunction<ClientToServerFunctions, ServerToClientFunctions>();
|
||||
Vendored
+16
@@ -0,0 +1,16 @@
|
||||
import { SettingDefinition } from "@common/shared/typings/settings";
|
||||
|
||||
/**
|
||||
* Type definition of the setting definition file.
|
||||
*/
|
||||
export declare interface SettingsFile {
|
||||
[group: string]: SettingDefinition[];
|
||||
/**
|
||||
* The current version of the setting file.
|
||||
*/
|
||||
version: number;
|
||||
}
|
||||
|
||||
declare const settingsFile: SettingsFile;
|
||||
|
||||
export = settingsFile;
|
||||
@@ -0,0 +1,104 @@
|
||||
version = 2
|
||||
|
||||
[[Accessibility]]
|
||||
default = false
|
||||
description = "Reduce the visual effects of flashing lights and fast motion."
|
||||
name = "Epilepsy mode"
|
||||
type = "Boolean"
|
||||
|
||||
[[Accessibility]]
|
||||
default = true
|
||||
description = "Enable the shaking screen."
|
||||
name = "Shaking Screen"
|
||||
type = "Boolean"
|
||||
|
||||
[[Accessibility]]
|
||||
default = false
|
||||
description = "Disables all game sounds and adds information about them."
|
||||
name = "Deaf mode"
|
||||
type = "Boolean"
|
||||
|
||||
[[Accessibility]]
|
||||
default = 1
|
||||
description = "You know what is subtitle isn't it"
|
||||
name = "Subtitle"
|
||||
option = ["Nothing", "Dialogue only", "All Sound"]
|
||||
type = "Enum"
|
||||
|
||||
[[Accessibility]]
|
||||
default = true
|
||||
description = "Activities mod to be fair with the blind people"
|
||||
name = "Blind mode"
|
||||
type = "Boolean"
|
||||
|
||||
[[Graphic]]
|
||||
default = true
|
||||
description = "Allow you to see your body in first person."
|
||||
name = "Introspection"
|
||||
type = "Boolean"
|
||||
|
||||
[[Control]]
|
||||
default = true
|
||||
description = "Do like if you are on mobile"
|
||||
name = "Force mobile"
|
||||
type = "Boolean"
|
||||
|
||||
[[Control]]
|
||||
default = true
|
||||
description = "let you Edit mobile bouton"
|
||||
name = "Edit mobile bouton"
|
||||
type = "Boolean"
|
||||
|
||||
[[Sond]]
|
||||
default = 90
|
||||
description = " Change l'angle de vision"
|
||||
max = 120
|
||||
min = 30
|
||||
name = "FOV"
|
||||
type = "Int"
|
||||
|
||||
[[Sond]]
|
||||
default = 100
|
||||
description = "Change the volume of Main"
|
||||
max = 200
|
||||
min = 0
|
||||
name = "Main Volume"
|
||||
type = "Int"
|
||||
|
||||
[[Sond]]
|
||||
default = 100
|
||||
description = "Change the volume of SFX"
|
||||
max = 200
|
||||
min = 0
|
||||
name = "SFX Volume"
|
||||
type = "Int"
|
||||
|
||||
[[Sond]]
|
||||
default = 100
|
||||
description = "Change the volume of Musique"
|
||||
max = 200
|
||||
min = 0
|
||||
name = "Musique Volume"
|
||||
type = "Int"
|
||||
|
||||
[[Sond]]
|
||||
default = 100
|
||||
description = "Change the volume of Mob"
|
||||
max = 200
|
||||
min = 0
|
||||
name = "Mob Volume"
|
||||
type = "Int"
|
||||
|
||||
[[Sond]]
|
||||
default = 100
|
||||
description = "Change the volume of Radio"
|
||||
max = 200
|
||||
min = 0
|
||||
name = "Musique Radio"
|
||||
type = "Int"
|
||||
|
||||
[[Performance]]
|
||||
default = false
|
||||
description = "Do you have a potato PC ?if it the case enable is"
|
||||
name = "Toaster mod"
|
||||
type = "Boolean"
|
||||
@@ -0,0 +1,53 @@
|
||||
/**
|
||||
* Possible types of Setting.
|
||||
*/
|
||||
export enum SettingType {
|
||||
Boolean = "Boolean",
|
||||
Enum = "Enum",
|
||||
Float = "Float",
|
||||
Int = "Int",
|
||||
String = "String",
|
||||
}
|
||||
|
||||
/**
|
||||
* A setting definition.
|
||||
*/
|
||||
export interface SettingDefinition<T extends SettingType = SettingType> {
|
||||
/**
|
||||
* The default value of the setting.
|
||||
*/
|
||||
default: SettingRealType<T>;
|
||||
/**
|
||||
* The english description of the setting.
|
||||
*/
|
||||
description: string;
|
||||
/**
|
||||
* The unique id of the setting.
|
||||
*/
|
||||
id: string;
|
||||
/**
|
||||
* The name of the setting.
|
||||
*/
|
||||
name: string;
|
||||
/**
|
||||
* The type of the setting.
|
||||
*/
|
||||
type: T;
|
||||
}
|
||||
|
||||
export const SettingTypeChecker: Record<SettingType, keyof CheckableTypes> = {
|
||||
Boolean: "boolean",
|
||||
Enum: "number",
|
||||
Float: "number",
|
||||
Int: "number",
|
||||
String: "string",
|
||||
};
|
||||
|
||||
/**
|
||||
* The data storage form of saved setting.
|
||||
*/
|
||||
export type SetSetting = Map<string, Map<string, boolean | number | string>>;
|
||||
/**
|
||||
* Transform Setting type enum to real typescript/lua type.
|
||||
*/
|
||||
export type SettingRealType<T extends SettingType> = CheckableTypes[(typeof SettingTypeChecker)[T]];
|
||||
@@ -0,0 +1,12 @@
|
||||
import { mount } from "@rbxts/vide";
|
||||
|
||||
/**
|
||||
* Transform a vide component into a Hoarcekat story.
|
||||
* @param component A vide component.
|
||||
* @returns A Hoarcekat story.
|
||||
*/
|
||||
export function Hoarcekat<T>(component: () => T) {
|
||||
return (target: Instance) => {
|
||||
return mount(component, target);
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
import { Atom } from "@rbxts/charm";
|
||||
import { derive, source, Source } from "@rbxts/vide";
|
||||
import { useAtom } from "@rbxts/vide-charm";
|
||||
|
||||
/**
|
||||
* Create an derivate which a "not" (`!`) operator on an boolean source.
|
||||
* @param source A Boolean Source
|
||||
* @returns The derivate.
|
||||
*/
|
||||
export function NotDerivate(source: Source<boolean>): () => boolean {
|
||||
return derive(() => !source());
|
||||
}
|
||||
|
||||
/**
|
||||
* Create two function linked to an charm atom or a vide source.
|
||||
* @param atom An optional charm atom.
|
||||
* @param defaultValue The default value if `atom` is `undefined`.
|
||||
* @returns Two function, one to get the value of the box, one to set the value of the box.
|
||||
*/
|
||||
export function useBox<T>(atom: Atom<T>, defaultValue?: T): [getter: () => T, setter: (value: T) => T];
|
||||
export function useBox<T>(atom: Atom<T> | undefined, defaultValue: T): [getter: () => T, setter: (value: T) => T];
|
||||
export function useBox<T>(atom: Atom<T> | undefined, defaultValue: T): [getter: () => T, setter: (value: T) => T] {
|
||||
if (atom) {
|
||||
return [useAtom(atom), atom];
|
||||
} else {
|
||||
const value = source(defaultValue);
|
||||
return [value, value];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"jsx": "react",
|
||||
"jsxFactory": "Vide.jsx",
|
||||
"jsxFragmentFactory": "Vide.Fragment",
|
||||
"module": "commonjs",
|
||||
"moduleResolution": "Node",
|
||||
"noLib": true,
|
||||
"resolveJsonModule": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"moduleDetection": "force",
|
||||
"strict": true,
|
||||
"target": "ESNext",
|
||||
"skipLibCheck": true,
|
||||
"paths": {
|
||||
"@common/*": ["./src/*"],
|
||||
},
|
||||
"typeRoots": ["node_modules/@rbxts", "node_modules/@flamework"],
|
||||
"types": ["compiler-types", "types"],
|
||||
"incremental": true,
|
||||
"experimentalDecorators": true,
|
||||
|
||||
"plugins": [
|
||||
{
|
||||
"transform": "rbxts-transformer-access"
|
||||
},
|
||||
{
|
||||
"transform": "rbxts-transformer-flamework",
|
||||
"obfuscation": true
|
||||
},
|
||||
{
|
||||
"transform": "rbxts-transformer-services"
|
||||
},
|
||||
{
|
||||
"transform": "typescript-file-copy-plugin",
|
||||
"copy": [
|
||||
{
|
||||
"src": "src/*.toml",
|
||||
"dest": "src"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"transform": "tsc-progress",
|
||||
"title": "Building...",
|
||||
"color": "magenta"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"extends": "./tsconfig.base.json",
|
||||
"compilerOptions": {
|
||||
"rootDir": "src",
|
||||
"rootDirs": ["src"],
|
||||
"outDir": "out",
|
||||
"typeRoots": [
|
||||
"node_modules/@rbxts",
|
||||
"node_modules/@flamework",
|
||||
]
|
||||
},
|
||||
"include": ["src/**/*", "node_modules/rbxts-transformer-instances"]
|
||||
}
|
||||
Reference in New Issue
Block a user