Contents |
General
Supported types of communication
- GS can query NewGRF and get information instantly. The querying does not affect the game state.
- NewGRF can query GS information, which has been set in advance by the GS.
- GS can trigger NewGRF entities (e.g. industries) to change their game state. This is done via a command, so at most one trigger per (1 + network.frame_freq) ticks (by default 1). GS may have to address groups of entities at once.
Emulatable types of communication
- NewGRF triggering GS:
- GS have no interrupts, they can only poll.
- NewGRF can only do stuff in callbacks, this always involves some NewGRF entitiy.
- The 'query information from NewGRF entity' covers this case.
Not supported types of communication
- GS cannot supply information instantly, thus NewGRF cannot query information which hasn't been set in advance. This limits parameterized queries.
- No communication in settings GUI. Neither the GS nor the NewGRF are active at this point.
- Communication during game-initialisation. NewGRFs are loaded first. They cannot query GS information at this point. GS can then also not influence placement of initial industries etc.
AIs
- AI may also be enabled to read the information shared between GS and NewGRF, though the information may need a flag noting that the information is 'also knows to humans in some way'.
Overview
GS/AI info query callback
- The GS/AI asks a NewGRF or a NewGRF industry about information wrt. some 'format identifier'. This triggers a callback to the NewGRF on the server. The result is returned as a structure to the GS/AI. An Action 14 describes conversion between callback parameters and result registers to a JSON structure.
- This does not change the gamestate!
-
Parameters:
- Result format identifier
-
Target:
- Single industry
- Industry type
- Single NewGRF (later)
-
Result:
- JSON with dynamic values
GS trigger callback
- The GS issues a command for a NewGRF entity (e.g. industry). Input is a 'format identifier' and a matching structure. The data is transfered to all clients (as command), and then triggers a NewGRF callback for the addressed entity.The callback result instruct OpenTTD to call further callbacks, like 'production change callback' or 'animation trigger'. An Action 14 describes conversion from the input structure (JSON) to callback parameters and registers.
-
Parameters:
- Input format identifier
- JSON input
-
Target:
- Single industry
-
Result:
- ok/failure
- Request to trigger random-production-change callback.
- Request to trigger animation trigger for all tiles
GS announcement board
- The GS writes information on a global announcement board, which NewGRF can query, if they want to. The data is identified via a 'format identifier'. The GS can store a structure addressed by this data. NewGRF can query this information in VarAction2 via a new 60+x variable. An Action 14 describes conversion from the input structure (JSON) to the 60+x variable.
-
Parameters:
- Input format identifier
- JSON input
-
Target:
- All NewGRF
- Single NewGRF (later)
- Visible/hidden to AI (later)
-
Result:
- None
Structure details
-
The JSON structures are limited.
- Integers, strings, arrays, tables, booleans. No 'null' and no classes.
- NewGRF cannot iterate arrays, so all arrays must have a known/limited/fixed size.
GS Details
-
SquirrelTable ScriptIndustry::GetNewGRFInfo(IndustryId ind, const char *formatid, SquirrelTable param);
Read information, without changing gamesate.
local param; param.foo = 123; local data = GSIndustry.GetNewGRFInfo(industry, "bar", param); if (data.rawin("foobar")) { data.foobar ... }
-
bool ScriptIndustry::SendNewGRFTrigger(IndustryId ind, const char *formatid, SquirrelTable data);
Trigger NewGRF to change gamestate.
local data; data.foo = 123; GSIndustry.SendNewGRFTrigger(industry, "bar", data);
-
bool ScriptController::SetNewGRFInfo(const char *formatid, SquirrelTable data);
Set information globally for NewGRF to read, if they want.
local data; data.foo = 123; GSController.SetNewGRFInfo("bar", data);
-
SquirrelTable ScriptController::GetNewGRFInfo(const char *formatid);
Get what has been set via SetNewGRFInfo before.
local data; data.foo = 123; GSController.SetNewGRFInfo("bar", data);
NewGRF Details
Announcement board: Conversion from global JSON to 60+x variable
Action14:
JSON -> VARI <60+x parameter> FMT_ FormatId PATH JSON path, e.g 'Foo.Bar[2].Doh'. VALU <val> String enum literal DFLT Default value if unassigned (required!)
New global 60+x variable:
- Parameter: Index into JSON->VARI
- Result: Data according to JSON->VARI
Query: Conversion from Callback result to JSON
Action14:
JSON -> CBOU <callback result> TMPL JSON template string with <1> <2> parameters Example: '{ "Supports": ["GSProduction"], "Production": <1>, "Technology": <2> }' PARA <paramid> TYPE 0 = uint/enum, 1 bool, 2 = sint/enum MASK \w register (0x00-0x10F) \b first-bit \b num-bit VALU <val> String enum literal
New callback:
-
Target:
- Single industry
- 'Purchase list'-style for industry type.
- Generic callback for feature 08 (global settings).
-
Input:
- Var 10: FormatId according to JSON->CBIN
- Registers 0x00 to 0xFF according to JSON->CBIN
-
Result:
- CB Result: FormatId according to JSON->CBOU
- Registers 0x00 to 0x10F according to JSON->CBOU
Conversion from input JSON to callback paramters
Action14:
JSON -> CBIN <callback param 1> FMT_ FormatId TMPL JSON template string with <1> <2> paramters Example '{ "ProductionLevel": <1>, "InputCargoEfficiency": [ <1>, <2> ] }' PARA <paramid> MASK \w register (0x00-0xFF) \b first-bit \b num-bit VALU <val> String enum literal DFLT default value if missing
Template matching:
- Structure members which are present in the input data, but missing the template, are skipped/ignored/dropped.
- Missing members in the input data are filled up with the DFLT value. If there is no DFLT, the input is considered invalid.
- The same rules apply to arrays with more/too few items.
- Bools are converted to 0/1.
- Strings are converted according to the VALU enum values. If there is no matching value, the input is considered invalid.
TODO: This is quite complicated, the format for the 60+x variable looks both easier to use and to implement. So, use it for this as well.
New callback:
-
Target:
- Single industry
-
Input:
- Var 10: FormatId according to JSON->CBIN
- Registers 0x00 to 0xFF according to JSON->CBIN
-
Result:
-
CB Result:
- Bit 0: Report success
- Bit 1: Call callback 29 (random production change) now. (data must be passed via persistent storage)
- Bit 2: Trigger animation trigger for all tiles. (new trigger; other data must be passed via persistent storage)
-
CB Result: