Git Product home page Git Product logo

pshy0 / pshy_merge Goto Github PK

View Code? Open in Web Editor NEW
6.0 0.0 0.0 2.9 MB

"Transformice Lua Compiler" - Compiles several standard Lua files into one script you can run in Transformice - `require` is supported - This repository also includes a few ready-to-run scripts. - Aka "pshy_merge".

Makefile 0.29% Python 5.53% Lua 94.18%
transformice transformice-module transformice-script transformice-tools

pshy_merge's Introduction

TLC (pshy_merge)

Introduction

This project contains a Python script to merge TFM lua scripts/modules, and some TFM modules I made as well. TAKE CAUTION USING THOSE SCRIPTS, THEY MAY BE VERY UNSTABLE BEFORE 1.0

Compiled TFM Lua Scripts

You can find ready-to-run-in-game compiled scripts here. You should find the same scripts in the tfm_lua folder after running make.

Some scripts exist in an anticheat variant, ask Pshy to get them (only for FunCorps).

Scripts included in this repository:

Older scripts (Not maintained):

  • Mario 1: Script that runs nnaaaz's Mario 1 map (DISMAINTAINED).

Projects using pshy_merge:

Help about ingame commands is available here.

You can also see all previous and pre-release versions here.

Compiling Modules

The compiler script combine.py compiles the given Lua modules into a single script that can run in TFM.

By defaults, modules will be looked for in ./lua/ and ./pshy_merge/lua/. Folders containing an init.lua files are also considered modules. Modules are included in the order given on the command-line, except if an early module requires a later one.

Options:

  • --out <file>: Specifies the file to output to (Outputs on stdout by default).
  • --deps <file>: Outputs a dependency file includable by Makefiles.
  • --add-path <path>: Adds a Lua path to look for modules at.
  • --lua-command <interpreter>: Allows including Lua modules installed on your computer. The argument is the interpreter name. Then you can use the require() function.
  • --include-sources: Next modules will have their source included in the output as a string (see pshy.compiler.modules).
  • --no-include-sources (default): Next modules will not have their source added as a string in the output.
  • --test-init: Simulate the initialization of the script, and display errors if there would be.
  • --werror: If --test-init fails then abort and exit with code 1.
  • --enabled-modules (default): Next specified modules will be manually enabled by default.
  • --disabled-modules: Next specified modules will be manually disabled by default. They can be enabled in-game with !enablemodule <module_name> or by enabling modules that depends on them.
  • --direct-modules: The next modules are not enabled when they are dependencies for enabled modules. They can be manually or directly enabled or disabled.
  • --indirect-modules (default): The next modules are automatically enabled when they are dependencies of enabled modules.
  • --reference-locals Adds accessors to locals. See pshy.debug.glocals. Use !ls ~/module.name/~ to list locals and !ls/set ~/module.name/local_name to access. Locals must be on their own line.
  • --minify-comments: Removes comments from the output script (keep the header).
  • --minify-spaces: Removes unnecessary spaces from the output (keep line returns).
  • --minify: Equivalent to --minify-comments --minify-spaces.
  • --minify-unreadable: Removes unnecessary new lines plus --minify (minimal gain, becomes unreadable).
  • --minify-globally: Minimize the whole generated script instead of minimizing per-module (minimal gain, becomes unreadable).
  • --minify-strings: Creates a string index when this saves size (minimal gain, becomes unreadable).
  • --minify-luamin: Runs luamin over individual modules before they are merged. Gain is slightly better than running luamin by itself, and you wont end up with a giant lagging line of code.
  • --clip: Send the output to the clipboard.
  • --old-physics: Use old game physics (divides speed passed to movePhysicObject by 10).
  • --test: Run basic tests and display the output on stderr.

Example to compile pshy.games.fasttime, test that it initialize without error, minify it while keeping it readable, and output the result to your clipboard:

./combine.py --test-init --minify pshy.games.fasttime --clip

The module pshy.essentials.everything contains most of this repository features.

To compile from anywhere, you could use an alias for combine.py:

alias tlc="~/projects/transformice/pshy_merge/combine.py --add-path ./\?.lua --add-path ./\?/init.lua"

Writing Modules

When reading source files, the compiler includes files based on the pshy.require() calls it finds. Modules can return something, which will also be returned by pshy.require(). Modules are only loaded once, the value returned by pshy.require() is cached.

For instance:

  • lua/submodules/submodule.lua:
local namespace = {}
namespace.custom_print = function(text) print("> " .. tostring(text)) end
return namespace
  • lua/main.lua:
local sm = pshy.require("submodules.submodule")
sm.custom_print("Hello World")

outputs > Hello World.

Files are ordered accordingly, but their content only runs at runtime. This means conditional requires should work.

Additionaly, the following doctags can be used:

  • -- @author: Adds an author for the file.
  • -- @header: Adds a line in the output file's header.
  • -- @preload: The module will load where it is included, rather than when it is required.
  • -- @hardmerge: The module will be included without being listed in pshy.modules.

The compiler also adds some definitions. See pshy.compiler.definitions for details.

The compiler will define those per-module variables if you use them:

  • __IS_MAIN_MODULE__: Is this module the last specified module on the command-line.
  • __MODULE_NAME__: The current module's name.
  • __MODULE_INDEX__: Index of this module in pshy.modules_list.
  • __MODULE__: A table with information about the current module.

Use __MODULE__.require_direct_enabling = true to cause the module to only be enabled either manually or directly, but not by modules requiring it. This is useful for modules that only run on a specific map. Modules required by a map can be specified in the map's xml when using pshy.rotations.newgame with pshy.rotations.mapinfo.

Depending on the modules you use, those additional events may be available:

  • eventInit(time): Called when all modules were loaded, before they are enabled.
  • eventThisModuleEnabled(): Called when this module have just been enabled. Dependencies are enabled beforehand (requires pshy.moduleswitch).
  • eventThisModuleDisabled(): Called when this module have just been disabled. Dependencies are disabled afterhand (requires pshy.moduleswitch).
  • eventModuleEnabled(module_name): Called when a module have been enabled (requires pshy.moduleswitch).
  • eventModuleDisabled(module_name): Called when a module have been disabled (requires pshy.moduleswitch).
  • eventSoulmateChanged(player_name, new_soulmate_name): Called when the player's spouse changed (requires pshy.bases.events.soulmatechanged).
  • eventNinthLoop(time_elapsed, time_remaining): Loop event ran after some time is elapsed since map change to split computation time. Doesnt run if map is about to change.

The module pshy.alternatives.mt replaces most features that are module-team-only, so you can run Lua Event scripts. You can run !modulereload event_module_name to play the event again.

Fixing conflicts / issues

Commands may optionally be prefixed by either:

  • !pshy.: Run a command from a pshy_merge script.
  • !other.: Run a command from another script.

The script loader is automatically added as admin in pshy_merge scripts, and you can add more admins with !admin. The script will attempt to make pshy_merge admins also admin in other included scripts. However, not all scripts are implemented the same, so you may still need to add your nickname in the other scripts by hand.

The module pshy.events contains the features used to make scripts using events compatible. You need to include it if it is not already included by one of the pshy_merge scripts.

When a module abort an event by returning a value, the whole event is aborted in other modules too (except for some events). ready-to-run scripts should not be doing that anyway since this is not used by TFM, but if they do, this can cause issues.

Modules are currently not run in different environments (perhaps in the near future?). This means that if two scripts are using the same global identifier names, they may collide. You can fix this by making the colliding identifiers local.

If several modules use a graphic interfaces or ingame objects, they may conflict because of the use of identical ids. This cannot be fixed yet.

If several modules use the keyboard and mouse, they may obviously conflict. This cannot be fixed yet.

If a module calls an event itself, then it will be raised in all modules (except if done before eventInit). Avoid calling an event yourself, unless your REALY want all modules to receive the event. If you want to run some code from more than a single event, you may put this code into its own function and call it instead of calling the event.

References

pshy_merge's People

Contributors

pshy0 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar

pshy_merge's Issues

The rotation "class" should be reverted back to a table

I earlier made an attempt at using Lua metatables to simulate classes and improve code maintainability.
An official standard way of doing so existed, and it was also done in some other TFM scripts.

Unfortunately, this had a very bad performance impact.
Metatables cause some algorithms to be as bad as 2 or 3 times more expensive at runtime.

Additionally, while the technique make a code LOOKS LIKE object oriented, it actually is not, which is misleading.
Also, the readability of the class code itself is questionable.

Therefore, to provide better performances and unify how my code looks like, I will be reverting those changes, and not implementing any new metatable.

Rename variables

Those variables should be renamed.
This requires updating dependent modules.

Maps that are called lists:
command_list: command_map or command_dictionary
Using "dictionary" would prevent confusions with the game's concept of maps.

Misspelled:
modules_list: module_list

Safe HTML function

Forgetting to close a markup can mess up the game's chat.
A function to assert room admins don't fail their html messages would help.

Event paintest command

Add a command that triggers invalid events players could theoretically send to the module, to test if it survives it (can also be tested a compile/test time).

Ground images are not displayed at the same location than on miceditor

The image on the map from this script does not display in the right location:

map = [[<C><P F="0" MEDATA="2,1;;;;-0;0:::1-"/><Z><S><S T="6" X="727" Y="196" L="160" H="30" P="0,0,0.3,0.2,140,0,0,0"/><S T="6" X="400" Y="370" L="600" H="60" P="0,0,0.3,0.2,0,0,0,0"/><S T="13" X="193" Y="323" L="10" P="1,0,0.3,0.2,20,0,1,1" o="D3D3D3" col="" i="-5,-5,17bf4c421bb.png" tint="FF0000"/><S T="6" X="760" Y="370" L="80" H="60" P="0,0,0.3,0.2,0,0,0,0"/><S T="6" X="40" Y="370" L="80" H="60" P="0,0,0.3,0.2,0,0,0,0"/><S T="6" X="595" Y="244" L="160" H="30" P="0,0,0.3,0.2,180,0,0,0"/><S T="6" X="42" Y="286" L="80" H="30" P="0,0,0.3,0.2,180,0,0,0"/><S T="6" X="42" Y="282" L="80" H="30" P="0,0,0.3,0.2,0,0,0,0"/><S T="6" X="279" Y="206" L="80" H="30" P="0,0,0.3,0.2,210,0,0,0"/><S T="6" X="281" Y="203" L="80" H="30" P="0,0,0.3,0.2,30,0,0,0"/><S T="6" X="595" Y="240" L="160" H="30" P="0,0,0.3,0.2,0,0,0,0"/><S T="6" X="725" Y="192" L="160" H="30" P="0,0,0.3,0.2,-40,0,0,0"/><S T="2" X="89" Y="385" L="10" H="10" P="0,0,0,1.2,0,0,0,0"/><S T="12" X="228" Y="297" L="10" H="10" P="1,0,0.3,0.2,0,0,0,0" o="C6BDBD"/></S><D><DS X="143" Y="325"/></D><O><O X="782" Y="321" C="1" P="0"/><O X="708" Y="321" C="0" P="0"/><O X="398" Y="321" C="6" P="0"/><O X="489" Y="337" C="34" P="0"/><O X="539" Y="336" C="97" P="0"/><O X="623" Y="200" C="95" P="0"/></O><L/></Z></C>]]
tfm.exec.newGame(map)

Custom emoticons

A module exists to add custom emoticons.

However, this is now possible to do in game, so much less useful.
It can still be used for emotes that are not yet added, or to display an emote over someone else.

Many players also cannot use emotes from this module due to not having a numpad.

Possible improvements:

  • Bind the two keys after Zero to emotes
  • Let players choose what emote to bind to those keys

Team VS script with fixed rounds.

Existing FC scripts causes a team to when upon reaching a certain score.

This makes the duration of the animation unpredictable, as teams can be either balanced or uneven.

A script could count rounds instead, so that an animation have a predictable duration. The last point must still be made by the winning team, so the winner is only determined at the very end.

Map Triggers

Add easy ways for maps to add triggers and actions - perhaps even scripting features.

Optimize rotations

This is a list of a few optimizations that can be done to the rotation system:

  • #5
  • When items only appear in the same order, only use a index instead of additional lists.
  • Instead of popping an item from the list, move the last item to the location where an item was popped.
  • Fill up the next rotation index table progressively, as items are popped, instead of doing it in one go.

Map `@336108`

Playing this map causes this error:

ASSERTION FAILED
passed a null inner_xml to GetParam
stack traceback:
	Pshy#3752.lua:4175 in function assert
	Pshy#3752.lua:5994 in function GetParam
	Pshy#3752.lua:6014 in function UpdateFromXML
	Pshy#3752.lua:6202 in function ?
	pcall in function pcall
	Pshy#3752.lua:6206 in function Update
	Pshy#3752.lua:6213 in function func
	Pshy#3752.lua:249 in function func
	Pshy#3752.lua:249 in main chunk

The script does not crash. The map's XML is apparently non-standard. This may be fixable by mapcrews.

Move commands to module tables

Currently, a table lists all commands that modules add into it.

Instead, modules could have a commands table in their module table.
This would make command definitions independent from the module listing them, and allow to identify to what module a command belongs.

This would also make the code briefer and simpler.

Also, with this change, commands from disabled modules could be made to be disabled (except for commands such as !lobby that enables the module)

Install TLC

Add a way to run TLC from anywhere, without the need of including it as a submodule (so it's only a dependency).

Better Aliases

Allow a command to be an alias for a command and parameters.

Allow FunCorps to use `!adminme`

Allow FunCorp players to use the !adminme command when the script is run in FunCorp mode.

This is not yet possible due to missing api features.
This issue serves as a reminder for when the feature is available.

Remove the physics fix

A fix is currently implemented to account for changes in the physic speed unit used by some of TFM's Lua api functions.
Because it's not going to be reverted, this fix should be removed and all scripts upgraded.

Rename the script to TLC...

...unless a better idea arises.

TLC stands for Transformice Lua Compiler.
It's more descriptive of what this project is for.

This may involve major changes, including changes required to be done in dependencies. As such, this is delayed to v1.0.

Help pages could be generated from module tables

Currently, a table lists all help pages, to which modules add theirs.

Instead, modules tables could have fields describing the module directly.

This would make the code simpler.
Such table could also act as documentation, at the beginning of each file.

Rain module

Refactor the rain module so that it handles map size and handles different frequencies for spawned objects.

TouchPlayer and disabled modules

Some modules rely on eventNewPlayer.
They will not see the event while they are disabled, which could cause issues in the future.

Redesign the bonus modules

When I implemented the bonus module, I wanted to allow to change different settings per bonus so that a common algorithm would be able to handle them all.

The result is that bonuses are easy to add, but anything that is not supported by the main algorithm will be harder to add or more expensive in performances.
Also, the color code system to determine custom bonuses in maps is sub-optimal, limiting available grounds, and making it harder to identify bonus effects.
Other problems exists, this is not an exhaustive list.

Caveats
Many maps use the current system and would need to be converted to the new one.
Support for displaying those bonuses in map editors is non-existent. With the current ground system, it's at least possible to see where you are putting the bonuses.
In the meantime, this issue serves as a reminder, as this huge change is not a priority.

Bonuses sound

Some bonuses could be made to play a sound.

For instance, the ice bonus should play the "mouse being frozen" sound.

Split commands in more modules.

Some commands can be split further:

  • Sound commands could go together (also add a separate !music command).
  • Chat related commands.
  • Commands to get infos on the scripts like !modules or !version.

Add a `!music` command.

The current !sound command would cause two musics to play on each other.

Instead, !music should stop the previous played music.
Additionally, a number could be used as an alternative for music names.

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.