Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
c4dc1fb
remove incorrect destroy logic
hrshtt Aug 21, 2025
756e3e4
remove old restart logic
hrshtt Aug 21, 2025
2591c79
force amd flag
hrshtt Aug 21, 2025
7eadc55
run with saves
hrshtt Aug 21, 2025
c9868f2
clean_instance
hrshtt Aug 21, 2025
330d5c9
clear_entities flag
hrshtt Aug 21, 2025
5dd3e8b
formatting
hrshtt Aug 21, 2025
fc4fd48
fixes for clear entities
hrshtt Aug 21, 2025
a33476c
dup script loading bug fix
hrshtt Aug 21, 2025
f6c0186
Merge remote-tracking branch 'upstream/main' into clean_instance
hrshtt Aug 21, 2025
226dbd7
merged
hrshtt Aug 21, 2025
9b538cf
cleaned up lua scripts
hrshtt Aug 22, 2025
568f147
more explicit mods structure
hrshtt Aug 22, 2025
4bdf19b
more explicit mods structure
hrshtt Aug 22, 2025
35b04db
cleaned serialize
hrshtt Aug 22, 2025
4e9b276
minor changes
hrshtt Aug 22, 2025
3606d93
incorrect position reset flag
hrshtt Aug 22, 2025
71355ef
formatting
hrshtt Aug 22, 2025
dc047e2
formatting
hrshtt Aug 22, 2025
c67acb8
formatting
hrshtt Aug 22, 2025
57acd6f
remove unused functions
hrshtt Aug 22, 2025
88be7bc
naively move setup tools to lua manager
hrshtt Aug 22, 2025
6fac240
formatting
hrshtt Aug 22, 2025
d589fd8
formatting
hrshtt Aug 22, 2025
1b084db
fix
hrshtt Aug 22, 2025
36dba95
trying something
hrshtt Aug 22, 2025
ce1fd46
use self.player_index
hrshtt Aug 22, 2025
ffbbb65
fixed indexing
hrshtt Aug 22, 2025
ba488e1
naive module declaration
hrshtt Aug 23, 2025
bf32166
proper modules + replace
hrshtt Aug 23, 2025
a9d1436
events decoupled
hrshtt Aug 23, 2025
7ea482a
removed log
hrshtt Aug 23, 2025
2ecdc15
stable modules, tests passing
hrshtt Aug 23, 2025
cf57b08
formatting
hrshtt Aug 23, 2025
277c21c
control lua template
hrshtt Aug 23, 2025
08b92bc
level safe but desync unsafe
hrshtt Aug 23, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 0 additions & 38 deletions .github/workflows/factorio-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,48 +36,10 @@ jobs:
cd fle/cluster
bash run-envs.sh start -n 4

- name: Check server status
run: |
cd fle/cluster
docker compose -f docker-compose.yml ps
docker compose -f docker-compose.yml logs factorio_0

- name: Install Python dependencies
run: |
uv sync --all-extras --dev

- name: Debug container IPs and ports
run: |
echo "=== Docker containers ==="
docker ps -a

echo -e "\n=== Container port mappings ==="
docker ps --format "table {{.Names}}\t{{.Ports}}"

echo -e "\n=== Listening ports on host ==="
sudo netstat -tlnp | grep -E ':(270|34197)' || echo "No matching ports found"


- name: Test RCON connectivity
run: |
echo "=== Testing RCON connectivity ==="
# First, let's see what port the container is actually exposing
CONTAINER_ID=$(docker ps -q -f name=factorio_1)
if [ -n "$CONTAINER_ID" ]; then
echo "Found container ID: $CONTAINER_ID"
docker inspect $CONTAINER_ID | grep -A 10 "Ports"
fi

# Try common RCON ports
for port in 27000 27016 27017 27018 27019 27020; do
echo -n "Testing port $port: "
if nc -z -w 2 localhost $port 2>/dev/null; then
echo "✓ Open"
else
echo "✗ Closed"
fi
done

- name: Run Python tests (4 workers)
run: |
uv run pytest -n 4 --dist=load -v -s --tb=short tests/actions/
Expand Down
23 changes: 13 additions & 10 deletions fle/commons/models/game_state.py
Original file line number Diff line number Diff line change
Expand Up @@ -111,9 +111,11 @@ def parse_raw(cls, json_str: str) -> "GameState":
current_research=data["research"]["current_research"],
research_progress=data["research"]["research_progress"],
research_queue=data["research"]["research_queue"],
progress=data["research"]["progress"]
if "progress" in data["research"]
else {},
progress=(
data["research"]["progress"]
if "progress" in data["research"]
else {}
),
)

return cls(
Expand Down Expand Up @@ -149,9 +151,11 @@ def parse(cls, data) -> "GameState":
current_research=data["research"]["current_research"],
research_progress=data["research"]["research_progress"],
research_queue=data["research"]["research_queue"],
progress=data["research"]["progress"]
if "progress" in data["research"]
else {},
progress=(
data["research"]["progress"]
if "progress" in data["research"]
else {}
),
)

return cls(
Expand Down Expand Up @@ -201,8 +205,8 @@ def to_instance(self, instance):

# Set inventory for each player
if self.inventories:
for i in range(instance.num_agents):
instance.set_inventory(self.inventories[i], i)
for namespace, inventory in zip(instance.namespaces, self.inventories):
namespace._set_inventory(inventory)

# Restore research state if present (only need to do this once)
if self.research: # Only do this for the first instance
Expand All @@ -216,8 +220,7 @@ def to_instance(self, instance):

# Merge pickled namespace with existing persistent_vars for each player
if self.namespaces:
for i in range(instance.num_agents):
namespace = self.namespaces[i]
for namespace in instance.namespaces:
if namespace:
restored_vars = pickle.loads(namespace)
if (
Expand Down
103 changes: 103 additions & 0 deletions fle/env/control-template.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
-- control.lua
-- This file is automatically generated by the LuaModuleManager
-- Do not edit this file manually

util = require('util')
local module_names = {
-- libs first
'{lib_names}',

-- admin tools
'{admin_tool_names}',

-- agent tools
'{agent_tool_names}'
}

local loaded_modules = {}

-- Load all modules and store them
log("Loading modules")
for _, name in ipairs(module_names) do
local ok, mod = pcall(require, name)
if not ok then
log("Error loading module: " .. name .. " - error: " .. mod)
else
log("Loaded module: " .. name .. " - success: " .. tostring(ok))
loaded_modules[name] = mod -- Store the actual module object
end
end

local function initialize_all()
log("Initializing all modules")
for name, module in pairs(loaded_modules) do -- Now iterating over actual modules
log('Initializing module: ' .. name)
if module.initialize then
local ok, err = pcall(module.initialize)
if ok then
log("Successfully initialized module: " .. name)
else
log("Error initializing module: " .. name .. " - error: " .. err)
end
end
end
end


local function register_events()
log("Registering events")
for name, module in pairs(loaded_modules) do
if module.events then
for event_id, handler in pairs(module.events) do
log('Registering event: ' .. tostring(event_id) .. ' from module: ' .. name)
script.on_event(event_id, handler)
end
end
if module.nth then
for nth, handler in pairs(module.nth) do
log('Registering nth-tick: ' .. tostring(nth) .. ' from module: ' .. name)
script.on_nth_tick(nth, handler)
end
end
end
end


-- One-shot first tick initializer (safe fallback for existing saves)
local function first_tick_init(event)
-- Unregister ourselves immediately to avoid repeated runs
script.on_nth_tick(1, nil)
if not global.fle_initialized then
log("Running delayed initialization on first tick via on_nth_tick(1)")
initialize_all()
register_events()
global.fle_initialized = true
end
log("First tick initialization complete; on_nth_tick(1) handler removed")
end

script.on_load(function()
log("Hii from on_load")
-- Rebuild all event subscriptions (safe in on_load; does not mutate game state)
register_events()

-- If this save predates our init, schedule a deterministic one-shot init
if not global.fle_initialized then
log("Scheduling first-tick initialization via on_nth_tick(1)")
script.on_nth_tick(1, first_tick_init)
end
end)

script.on_init(function()
log("Hii from on_init")
initialize_all()
register_events()
global.fle_initialized = true
end)

script.on_configuration_changed(function()
log("Hii from on_configuration_changed")
initialize_all()
register_events()
global.fle_initialized = true
end)
Loading