Repository navigation
Connecting Other Mods
Another mod can bring buildings and goods that build on Production Revamp — without a single line of Lua. That is the key point of this interface: as soon as a mod contains even one Lua file, it is no longer console-compatible. A pure placeable or crop mod would lose all console players just to register itself.
Both go through a file revamp_extension.xml in the root directory of the other mod. Revamp looks for it itself in all loaded mods; if Revamp is not installed, nobody reads it and the mod keeps running normally.
<?xml version="1.0" encoding="utf-8" standalone="no"?>
<revampExtension>
<storeItems>
<storeItem xmlFilename="SmallUndergroundStorageRevamp.xml"/>
</storeItems>
<fillTypes>
<fillType name="MY_CROP" like="WHEAT" addToStorage="true"/>
</fillTypes>
</revampExtension>A building that uses a Revamp placeable type cannot simply be listed as a <storeItem> in the modDesc of the other mod. Without Revamp the game does not know the type and writes Unknown type '...' to the log — for every player of that mod, even if they never had anything to do with Revamp.
That is why the store item is not declared in the other mod's modDesc but registered by Revamp at runtime. If Revamp is not there, nobody registers anything and the placeable simply does not exist for the game: it is missing from the build menu, without any message in the log.
| Attribute | Meaning |
|---|---|
storeItem#xmlFilename |
Path to the placeable XML, relative to the root directory of the registering mod |
Any number of entries. Revamp registers each of them as if it came from the other mod's modDesc — with that mod's environment, so its own $l10n_ texts, images and placeable types apply.
Keep in mind:
- The placeable type needs the full name with the mod prefix, i.e.
FS25_0_ProductionRevamp.RevampSilo. - A
<dependency>in the modDesc is not needed for this approach and not wanted either — the building is supposed to be optional after all. - If the registration file names an XML that does not exist, Revamp reports this in the log during loading, with the file name and mod name.
If at least one store item gets through, a summary appears in the log:
Info: Production Revamp: added 1 store items from 1 mods
If a station lists its fill types as a category (fillTypeCategories="GRAIN"), the mod's own fillTypes.xml is enough. A category that already exists is extended, not rejected:
<fillTypeCategories>
<fillTypeCategory name="GRAIN">MY_CROP</fillTypeCategory>
<fillTypeCategory name="REVAMP_GRAIN">MY_CROP</fillTypeCategory>
</fillTypeCategories>With this, every unloading station, every silo and every Revamp recipe that uses the category accepts the new good automatically. This is also the only way to get another mod's good into a recipe — the registration below explicitly cannot do that.
For the rest: stations that list their fill types by name (fillTypes="WHEAT BARLEY OAT"), and there are plenty of those on the maps. For these, the mod registers its good with a reference fill type — "wherever wheat is accepted, accept my crop as well".
| Attribute | Default | Meaning |
|---|---|---|
name |
– | Required. The mod's own fill type |
like |
– | Required. Existing fill type as a reference point: wherever this one is accepted, the mod's own fill type will be accepted as well from now on |
addToStorage |
false |
Additionally add it to storages that serve the reference fill type from a total capacity |
| Station | Behaviour |
|---|---|
| Selling station without its own storage | accepts the good and sells it, the price comes from the good itself |
| Silo with total capacity | takes it in, but only with addToStorage="true"
|
| Storage with fixed individual amounts per good | stays untouched — there would be no amount for it that the map maker ever planned |
| Production points and factories | never, even if they process the reference fill type: a production can only do what is in its recipes |
| Animal husbandries | never: the husbandry would store the good, but only what the feeding system knows gets eaten |
Also worth knowing: if a good is accepted somewhere that has no storage space for it, simply nothing arrives when unloading. So if you leave out addToStorage, you register your good for selling only.
- The registration file is read while the store items are loaded, i.e. before the fill types. The names are therefore only resolved once all fill types are loaded, including those of other mods.
- The stations themselves are extended when they register with the game. This applies equally to the stations of the map and to everything built later in the running game.
- The order of the mods does not matter.
The log contains a line:
Production Revamp: added 1 fill types to existing stations
With the debug switch turned on, there is an extra line per station and per storage — helpful above all for silos, because a built silo gives no visible sign of what it accepts:
RevampDebug: loadStorage(): MILK in ein Lager mit 500000 l Gesamtkapazitaet aufgenommen (placeable.silo.storages.storage(0))
RevampDebug: addUnloadingStation(): Getreide Flusssilo nimmt jetzt auch MILK an
Errors in the registration (unknown fill type, unknown reference fill type, good referring to itself) are also written to the log, with the name of the registering mod.
If a mod does need this from Lua after all — because it already contains scripts anyway and therefore has nothing left to lose:
local mod = g_modManager:getModByName("FS25_0_ProductionRevamp")
if mod ~= nil and g_modIsLoaded[mod.modName] then
-- Revamp is loaded
endThe mod name must be exactly FS25_0_ProductionRevamp for this, see Compatibility.
What such a mod can then read from Revamp's runtime data — recipes, mix groups, boosters, fill levels — is described under Reading runtime data.
The button bar of the production menu has six fixed slots. Vanilla uses up to five of them, Revamp adds Manage and Spawn goods — a seventh button is no longer displayed by the game and disappears without any comment. Which mod is affected depends solely on the load order.
That is why Revamp keeps one slot free for another mod in each of the two button rows of its Manage dialog. The mod registers its button there instead of putting it into the full bar.
Every mod runs in its own environment. Revamp's tables can therefore only be seen from outside through its mod environment, which the game stores under the mod name:
local revampEnvironment = _G["FS25_0_ProductionRevamp"]
local revampApi = revampEnvironment ~= nil and revampEnvironment.ProductionRevampApi or nilIf Revamp is not installed, revampApi simply stays nil and your own mod keeps running unchanged.
revampApi.registerManageButton({
modName = "FS25_MeinMod",
text = g_i18n:getText("meinMod_buttonText"),
scope = revampApi.SCOPE.PRODUCTION_POINT,
isVisible = function(productionPoint) return true end,
callback = function(productionPoint) MeinDialog.show(productionPoint) end
})| Field | Default | Meaning |
|---|---|---|
modName |
– | Required. Your own mod name, appears in Revamp's log messages |
text |
– | Required. Finished label, already translated |
scope |
– |
Required. SCOPE.PRODUCTION_POINT or SCOPE.FILLTYPE, see below |
callback |
– |
Required. Called on click, with the production point and, for SCOPE.FILLTYPE, additionally the fill type |
isVisible |
always visible | Decides per production point or per good whether the button appears. Same parameters as callback
|
The return value is true if the button was accepted.
scope says what the button refers to. Its row follows from that — the registering mod does not need to know the layout of the dialog.
| Scope | Where the button is placed | When it is visible |
|---|---|---|
SCOPE.PRODUCTION_POINT |
lower row, next to Spawn goods and the view switch | in every view |
SCOPE.FILLTYPE |
upper row, next to Buy and Sell | only in the Goods view, and only while a good is selected |
The registration belongs in your own mod's mission start, for example in loadMap — when your own files are sourced, not all mods are loaded yet.
Revamp accepts exactly one button per scope, because exactly one slot is free per row. If a second mod registers for the same scope, it is rejected; registerManageButton returns false and the log says which mod already has the slot:
Error: Production Revamp: 'FS25_MeinMod' wants the manage dialog button for scope 'productionPoint', but 'FS25_AndererMod' already has it. Only one button per scope can be shown.
Your own mod should be prepared for this and stick to its previous approach in that case.
- There, other mods registered store items through their own
revamp_check.lua, and fill types likewise through their own Lua file. Neither exists anymore — the registration is purely declarative, for the console reason above. - The conditions of the FS22 version (show or hide a store item only if certain fill types exist) do not exist at the moment. The fact that the file is read at all is already the condition "Revamp is installed". Further conditions can be added later without anything changing for existing registrations.