Coder Social home page Coder Social logo

samualtnorman / hackmud-script-manager Goto Github PK

View Code? Open in Web Editor NEW
10.0 2.0 4.0 1.12 MB

Script manager for game hackmud, with minification, TypeScript support, and player script type definition generation.

Home Page: https://www.npmjs.com/package/hackmud-script-manager

License: MIT License

TypeScript 81.92% JavaScript 17.71% Shell 0.37%
hackmd minifier javascipt typescipt manager script command-line api hackmud minification

hackmud-script-manager's Introduction

Hackmud Script Manager

Command made for Hackmud Scripting Environment, which is a scripting environment for hackmud with minification, autocompletes / intellisense, and TypeScript support.

ko-fi

You can read about how HSM works in my blog post.

Install

  1. Install Node.js
  2. Run npm install -g hackmud-script-manager

Usage

  1. Run #dir in game, then cd to that folder
  2. Name your source script file to <name>.src.js
  3. Run hsm golf <name>.src.js and it will create a minified script file called <name>.js

NOTE: If you get an error message that looks like this:

[...]\AppData\Local\pnpm\hsm.ps1 cannot be loaded because running scripts is disabled on this system. [...]

You will need to run Set-ExecutionPolicy -ExecutionPolicy Unrestricted -Scope CurrentUser in PowerShell as an administrator. For more information, see Microsoft's page about Execution Policies.

image image image

Features

  • Minification
    • This includes auto quine cheating.
      • Supported types are null, numbers, strings, and JSON compatible objects and arrays.
      • Non JSON compatible object keys are quine cheated.
      • Member expressions are converted to index notation so the index string can be quine cheated.
      • And template literals are converted to string concatenation so the strings can be quine cheated.
    • Global variable aliasing.
    • Convert function declarations to arrow function assigned to variable hoisted to the top of the block (function foo() { ... } -> let foo = () => ...).
    • Convert _START and _TIMEOUT to _ST and _TO.
    • Remove unused parameters from the main function expression.
  • Modern Javascript Syntax and Features
  • Future JavaScript Syntax and Features
  • TypeScript Support
    • This command/module does not do type checking, it simply removes type annotations so you'll need to rely on your IDE or run tsc seperatly with noEmit.
  • And “Cool” Unnecessary Features.
    • Variables declared outside the main function expression automatically become #G global variables.
    • Any code outside the function expression will only run once per top level script execution (#FMCL).
    • Basic seclevel verification.
      • Declaring // @seclevel HIGHSEC or any other seclevel before all of your code stops you from accidentally using #ls. or #ns..
    • Import node_modules modules into your script using import { foo } from "bar" syntax.
    • _SOURCE is replaced with a string of the source code of the script it's in.
    • _BUILD_DATE is replaced with a unix timestamp (Date.now()) of the build date of the script.
    • _SCRIPT_USER is replaced with a string of the user the script was pushed to.
      • This saves characters compared to context.this_script.split(".")[0].
    • _SCRIPT_NAME is like _SCRIPT_USER but for the name of the script.
      • Saves characters compared to context.this_script.split(".")[1].
    • _FULL_SCRIPT_NAME is replaced with what would be context.this_script.
    • #s. can be used and it'll automatically have the seclevel inserted.
    • Subscript and #db methods names are verified.
    • All references to preprocessor syntax functions not being called are turned into arrow function wrappers e.g. let debug = #D; -> let debug = v => #D(v);.
    • _SECLEVEL is replaced with a number (0 to 4) representing the seclevel of the script.
    • When exports are present in the script, it becomes a script that returns an object of the exported values.
      • _EXPORTS becomes an array of the names of the exported values.
  • And Neat Weird Fixes
    • Like .__proto__ and .prototype being converted to ["__proto__"] and ["prototype"].
    • Illegal and unsafe strings.
      • Appearences of _SC and friends are either renamed or have an escape inserted so that script is legal.
      • Preprocessor syntax in strings are escaped so hackmud doesn't recognise them as preprocessor syntax.
      • And appearences of // in strings and regexes have a backslash inserted between to stop hackmud's overagressive comment remover from removing half the line of code.
    • Classes are actually usable now, this module replaces instances of this with a variable referencing what would be this.
    • Function.prototype can be referenced (but only the .prototype property, nothing else).
    • Object.getPrototypeOf and Object.setPrototypeOf are replaced with equivalent functions.

hackmud-script-manager's People

Contributors

anihilprj avatar dependabot[bot] avatar longboyy avatar samualtnorman avatar vincentguinaudeau avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

hackmud-script-manager's Issues

Nested string arrays disappear when minified

Not sure if related to #146.
Only happens when the strings are long enough to justify quine cheat.

Input (nested declaration):

export default function (context: Context, args: { row: number }) {
	const data = [
		["aaaaaaaaaa", "bbbbbbbbbb", "cccccccccc"],
		["dddddddddd", "eeeeeeeeee", "ffffffffff"],
		["gggggggggg", "hhhhhhhhhh", "iiiiiiiiii"],
	];
	return data[args.row];
}

Output (nested declaration):

function($,e){
//	[[],"row"]	
let[t,c]=JSON.parse(#fs.scripts.quine().split`	`[1])
return t[e[c]]}

Input (flat declaration):

export default function (context: Context, args: { row: number }) {
	const row1 = ["aaaaaaaaaa", "bbbbbbbbbb", "cccccccccc"],
		row2 = ["dddddddddd", "eeeeeeeeee", "ffffffffff"],
		row3 = ["gggggggggg", "hhhhhhhhhh", "iiiiiiiiii"];
	const data = [row1, row2, row3];
	return data[args.row];
}

Output (flat declaration):

function($,s){
//	[["aaaaaaaaaa","bbbbbbbbbb","cccccccccc"],["dddddddddd","eeeeeeeeee","ffffffffff"],["gggggggggg","hhhhhhhhhh","iiiiiiiiii"],"row"]	
let[t,c,e,i]=JSON.parse(#fs.scripts.quine().split`	`[1])
return[t,c,e][s[i]]}

dummy error script

when the script can't be created due to an error
rather than creating an empty script, create a script that prints the error

Strange behaviour using functions

If I do this

export default (_context: Context, args: unknown) => { 
    $db.us(
        {
            _id: 'harvest'
        },
        {
            _id: 'harvest',
            filter: ['.pub', '.entry'],
            blacklist: ['accenture',
                'arino',
                'blackcore',
                'blackstar',
                'dynamo_corp',
                'jinteki_corp',
                'l4sh',
                'lunar_systems',
                'n_inc',
                'onion',
                'perimeter_systems',
                'ploogle',
                'pwnhub',
                'reinit',
                'rozas',
            ],
            commandRegex: 'with ([a-z`$]+):"([a-z]+)',
            userRegex: '([a-z0-9_]+) (of project|when being)',
            projectRegex: '(date for|continues on|of the|developments on|of project|review of).([a-z0-9.`_]+)',
            passwordRegex: 'strategy.([a-z0-9_]+)'
        }
    )
}

i get down to 74 chars.

If I do this

export default (_context: Context, args: unknown) => { 
    i();
}
function i() {
    $db.us(
        {
            _id: 'harvest'
        },
        {
            _id: 'harvest',
            filter: ['.pub', '.entry'],
            blacklist: ['accenture',
                'arino',
                'blackcore',
                'blackstar',
                'dynamo_corp',
                'jinteki_corp',
                'l4sh',
                'lunar_systems',
                'n_inc',
                'onion',
                'perimeter_systems',
                'ploogle',
                'pwnhub',
                'reinit',
                'rozas',
            ],
            commandRegex: 'with ([a-z`$]+):"([a-z]+)',
            userRegex: '([a-z0-9_]+) (of project|when being)',
            projectRegex: '(date for|continues on|of the|developments on|of project|review of).([a-z0-9.`_]+)',
            passwordRegex: 'strategy.([a-z0-9_]+)'
        }
    )
}

I get 208 chars.

object/array inside functons/loops can be quine cheated

export default () => () => [[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[]]

currently becomes

function(){return()=>[[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[]]}

an 86 char script which does not use quine cheating to preserve js semantics of getting a new instance every time the expression is evaluated. but it could become

function(){
//	["parse","[[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[]]"]	
let[s,t]=JSON.parse(#fs.scripts.quine().split`	`[1])
return()=>JSON[s](t)}

which is only 83 chars by using quine cheating but using JSON.parse() on a quine cheated string to preserve js semantics shaving off a whole 3 chars in this case

over aggressive object and array quine cheating

a non quine cheated version of

function () {
	return { foo: "bar" }
}

will return a new object every call

however the quine cheated version will return the same object every call per top level script execution

Make 0.20 Release

right before release

  1. update dependencies of and push to @samual/rollup-config
  2. update dependencies of @samual/lib
    • update to @samual/rollup-config@dev
  3. make a release of @samual/lib
  4. update dependencies of @samual/rollup-config (again)
  5. make a release @samual/rollup-config
  6. update pnpm version using
  7. update dependencies

after release

  • push changes to template

Support for autocompletion

Does HSM support autocompletion like
export default (_context: Context, args: Arguments) => { // t:[#s.]

Destructured `args` parameter name gets wrongfully minified into a comment

Initial script:

function (
  _,
  { really_long_parameter_name_that_should_not_be_minified_into_a_comment },
) {
  return really_long_parameter_name_that_should_not_be_minified_into_a_comment;
}

Command used:

npx hsm golf test.js /dev/stdout

Minified:

function($,{[e]:t}){
//	really_long_parameter_name_that_should_not_be_minified_into_a_comment	
let e=#fs.scripts.quine().split`	`[1]
return t}

The generated code fails to execute, because e is referenced before its creation.

alias function definitions to variables so terser can mangle their names

like as in turn

let someFunctionWithALongName = () => {
	// do some stuff
}

someFunctionWithALongName()
someFunctionWithALongName()

into

let someFunctionWithALongName = () => {
	// do some stuff
}

let _00000000000_LOCAL_FUNCTION_ALIAS_someFunctionWithALongName_ = someFunctionWithALongName

_00000000000_LOCAL_FUNCTION_ALIAS_someFunctionWithALongName_()
_00000000000_LOCAL_FUNCTION_ALIAS_someFunctionWithALongName_()

and then hand it off to terser.

terser currently has a bug that will cause the name of someFunctionWithALongName() to be clobbered if I do the above transformation.
I will wait for terser to amend this.

$s. does not get transformed to correct scriptspace

When I use $s. to call scripts, it gets transformed to #fs. in the result js file, even if the called script has another seclevel. This example can be used to reproduce it:

// @seclevel MIDSEC
export default (_context: Context, args: unknown) => {
    $s.chats.join({channel:""});
}

It results in
function(){#fs.chats.join({channel:""})}
despite chat.join is midsec.
Omiting // @seclevel MIDSEC does not change the result.

complain about unrecognised options

currently you can typo or misremember the name of an option and not notice. detecting and erroring on unrecognised options will make this obvious.
currently this will require a rework of how command parsing works

not using quine cheated version in weird case

export default args => args.foo(`aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa`)

quine cheats to 98 chars

function(a){return a.foo("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")}

but

export default args => args.foo(`aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa`)

quine cheats to 77 chars

function(o){
//	["foo","aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"]	
let[$,n]=JSON.parse(#fs.scripts.quine().split`	`[1])
return o[$](n)}

despite the source being longer

clean command

just delete all scripts in hackmud directory

maybe a smart version that checks the src folder first and only deletes scripts that don't have a source file

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.