Skip to content

Commit

Permalink
Add opacity, removing entities from map
Browse files Browse the repository at this point in the history
  • Loading branch information
Danielv123 committed Apr 14, 2024
1 parent da11ae9 commit 499e8be
Show file tree
Hide file tree
Showing 9 changed files with 138 additions and 37 deletions.
33 changes: 33 additions & 0 deletions module/gridworld.lua
Original file line number Diff line number Diff line change
Expand Up @@ -66,8 +66,12 @@ gridworld.events[clusterio_api.events.on_server_startup] = function()
global.gridworld.map = {
added_entities_to_update = nil,
removed_entities_to_update = nil,
entity_registrations = {},
}
end
if global.gridworld.map.entity_registrations == nil then
global.gridworld.map.entity_registrations = {}
end

-- Fun factions inititalization
setup_forces()
Expand Down Expand Up @@ -133,6 +137,14 @@ gridworld.events[defines.events.on_built_entity] = function(event)
end
end
end
gridworld.events[defines.events.on_biter_base_built] = function(event)
if not global.gridworld.lobby_server then
local entity = event.entity
if entity.valid then
map.events.on_biter_base_built(event, entity)
end
end
end
gridworld.events[defines.events.on_entity_cloned] = function(event)
if not global.gridworld.lobby_server then
local entity = event.destination
Expand Down Expand Up @@ -177,6 +189,27 @@ gridworld.events[defines.events.on_entity_destroyed] = function(event)
load_balancing.events.on_entity_destroyed(event)
end
end
-- "Soft" entity removal events, used for cleanup of things we havent registered
gridworld.events[defines.events.on_player_mined_entity] = function(event)
if not global.gridworld.lobby_server then
map.events.on_player_mined_entity(event)
end
end
gridworld.events[defines.events.on_robot_mined_entity] = function(event)
if not global.gridworld.lobby_server then
map.events.on_robot_mined_entity(event)
end
end
gridworld.events[defines.events.on_entity_died] = function(event)
if not global.gridworld.lobby_server then
map.events.on_entity_died(event)
end
end
gridworld.events[defines.events.on_pre_robot_exploded_cliff] = function(event)
if not global.gridworld.lobby_server then
map.events.on_pre_robot_exploded_cliff(event)
end
end
gridworld.events[defines.events.on_gui_click] = function(event)
local player = game.players[event.player_index]
local action = gui.read_action(event)
Expand Down
75 changes: 45 additions & 30 deletions module/map/dump_entities.lua
Original file line number Diff line number Diff line change
Expand Up @@ -4,49 +4,64 @@

local clusterio_api = require("modules/clusterio/api")

local function dump_entities(entities)
local function dump_entities(entities, removed_entities)
-- Do removals first, then additions afterwards to avoid issues with entities being removed and added in the same cycle
-- Additions check .valid so the race condition can't happen that way
local tasks = removed_entities or {}
if entities ~= nil then
-- Add entities to tasks
for _, entity in pairs(entities) do
table.insert(tasks, entity)
end
end

local map_data = {}
-- Get entities in the area
for _, entity in pairs(entities) do
for _, entity in pairs(tasks) do
if entity == nil or entity.valid == false then
goto continue
end
local position = entity.position
local map_color = entity.prototype.friendly_map_color or entity.prototype.map_color or entity.prototype.enemy_map_color
if map_color ~= nil then
local is_resource = entity.prototype.collision_mask["resource-layer"]
if is_resource then
-- Create checkerboard pattern associated with resources
if (math.floor(position.x/2) + math.floor(position.y/2)) % 2 == 0 then
table.insert(map_data, position.x)
table.insert(map_data, position.y)
table.insert(map_data, string.format("%02x%02x%02x", map_color.r, map_color.g, map_color.b))
end
else
-- Determine size of entity to draw
-- TODO: Does not seem to get the correct shape for trees and cliffs
local size_x = math.ceil((entity.bounding_box.left_top.x - entity.bounding_box.right_bottom.x) * -1)
local size_y = math.ceil((entity.bounding_box.left_top.y - entity.bounding_box.right_bottom.y) * -1)
local map_color = {r = 255, g = 255, b = 255, a = 0}
if entity.valid then
map_color = entity.prototype.friendly_map_color or entity.prototype.map_color or entity.prototype.enemy_map_color
end
if entity.valid == nil and entity.deleted then
map_color.a = 0 -- Remove alpha channel to make it transparent
end
local is_resource = entity.valid and entity.prototype.collision_mask["resource-layer"]
if is_resource then
-- Create checkerboard pattern associated with resources
if (math.floor(position.x/2) + math.floor(position.y/2)) % 2 == 0 then
table.insert(map_data, position.x)
table.insert(map_data, position.y)
table.insert(map_data, string.format("%02x%02x%02x%02x", map_color.r, map_color.g, map_color.b, map_color.a))
end
else
-- Determine size of entity to draw
-- TODO: Does not seem to get the correct shape for trees and cliffs, probably due to rotation
local size_x = math.ceil((entity.bounding_box.left_top.x - entity.bounding_box.right_bottom.x) * -1)
local size_y = math.ceil((entity.bounding_box.left_top.y - entity.bounding_box.right_bottom.y) * -1)

-- Add pixels
for x = 0, size_x-1 do
for y = 0, size_y-1 do
-- Format as hexadecimal
table.insert(map_data, position.x + x - (size_x-1)/2)
table.insert(map_data, position.y + y - (size_y-1)/2)
if entity.type == "entity-ghost" then
-- Render as purple
table.insert(map_data, "A800A8")
else
table.insert(map_data, string.format("%02x%02x%02x", map_color.r, map_color.g, map_color.b))
end
-- Add pixels
for x = 0, size_x-1 do
for y = 0, size_y-1 do
-- Format as hexadecimal
table.insert(map_data, position.x + x - (size_x-1)/2)
table.insert(map_data, position.y + y - (size_y-1)/2)
if entity.type == "entity-ghost" then
-- Render as transparent purple
table.insert(map_data, string.format("%02x%02x%02x%02x", 168, 0, 168, 127))
else
table.insert(map_data, string.format("%02x%02x%02x%02x", map_color.r, map_color.g, map_color.b, map_color.a))
end
end
end
end
::continue::
end

game.print(table.concat(map_data, ";"))
game.print("Sending "..(#map_data / 3).." pixels to nodejs")
clusterio_api.send_json("gridworld:tile_data", {
type = "pixels",
data = table.concat(map_data, ";"),
Expand Down
11 changes: 11 additions & 0 deletions module/map/entity_added.lua
Original file line number Diff line number Diff line change
@@ -1,8 +1,19 @@
local ignored_entities = require("modules/gridworld/map/ignored_entities")

local function on_entity_added(_, entity)
if ignored_entities[entity.type] then
return
end
if global.gridworld.map.added_entities_to_update == nil then
global.gridworld.map.added_entities_to_update = {}
end
table.insert(global.gridworld.map.added_entities_to_update, entity)
local registration = script.register_on_entity_destroyed(entity)
global.gridworld.map.entity_registrations[registration] = {
position = entity.position,
bounding_box = entity.bounding_box,
deleted = true,
}
end

return on_entity_added
10 changes: 7 additions & 3 deletions module/map/entity_removed.lua
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
-- TODO: Add batching of updates with on_nth_tick
local function on_entity_removed(_event)
-- dump_entities({event.entity})
local function on_entity_removed(event)
if global.gridworld.map.removed_entities_to_update == nil then
global.gridworld.map.removed_entities_to_update = {}
end
local entity = global.gridworld.map.entity_registrations[event.registration_number]
table.insert(global.gridworld.map.removed_entities_to_update, entity)
global.gridworld.map.entity_registrations[event.registration_number] = nil
end

return on_entity_removed
18 changes: 18 additions & 0 deletions module/map/entity_removed_unregistered.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
local ignored_entities = require("modules/gridworld/map/ignored_entities")

local function on_entity_removed(event)
local entity = event.entity or event.cliff
if ignored_entities[entity.type] then
return
end
if global.gridworld.map.removed_entities_to_update == nil then
global.gridworld.map.removed_entities_to_update = {}
end
table.insert(global.gridworld.map.removed_entities_to_update, {
position = entity.position,
bounding_box = entity.bounding_box,
deleted = true,
})
end

return on_entity_removed
5 changes: 3 additions & 2 deletions module/map/events/on_nth_tick.lua
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
local dump_entities = require("modules/gridworld/map/dump_entities")

local function on_nth_tick()
if global.gridworld.map.added_entities_to_update then
dump_entities(global.gridworld.map.added_entities_to_update)
if global.gridworld.map.added_entities_to_update or #global.gridworld.map.removed_entities_to_update > 0 then
dump_entities(global.gridworld.map.added_entities_to_update, global.gridworld.map.removed_entities_to_update)
global.gridworld.map.added_entities_to_update = nil
global.gridworld.map.removed_entities_to_update = {}
end
end

Expand Down
13 changes: 13 additions & 0 deletions module/map/ignored_entities.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
local ignored_entities = {
-- "entity-ghost", -- Should be rendered as transparent purple
"locomotive",
"cargo-wagon",
"fluid-wagon",
"artillery-wagon",
"car",
"spider-vehicle",
"character",
"character-corpse",
}

return ignored_entities
7 changes: 7 additions & 0 deletions module/map/map.lua
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ local dump_entities = require("modules/gridworld/map/dump_entities")

local entity_added = require("modules/gridworld/map/entity_added")
local entity_removed = require("modules/gridworld/map/entity_removed")
local entity_removed_unregistered = require("modules/gridworld/map/entity_removed_unregistered")

local on_nth_tick = require("modules/gridworld/map/events/on_nth_tick")

Expand All @@ -12,10 +13,16 @@ return {
events = {
on_nth_tick = on_nth_tick,
on_built_entity = entity_added,
on_biter_base_built = entity_added,
on_entity_cloned = entity_added,
on_entity_destroyed = entity_removed,
on_robot_built_entity = entity_added,
script_raised_built = entity_added,
script_raised_revive = entity_added,
-- Pre-destruction events, not reliable but used for cleanup of things we havent registered
on_player_mined_entity = entity_removed_unregistered,
on_robot_mined_entity = entity_removed_unregistered,
on_entity_died = entity_removed_unregistered,
on_pre_robot_exploded_cliff = entity_removed_unregistered,
},
}
3 changes: 1 addition & 2 deletions src/mapview/tileDataEventHandler.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,10 @@ module.exports = async function tileDataEventHandler({ type, data, size, positio
// Image tiles are 512x512 pixels arranged in a grid, starting at 0,0
const TILE_SIZE = 512;
if (type === "pixels") {
// console.log(data);
for (let i = 0; i < data.length; i += 3) {
const x = Math.floor(data[i]); // Convert from string and strip decimals
const y = Math.floor(data[i + 1]); // Convert from string and strip decimals
const rgba = [Number(`0x${data[i + 2].slice(0, 2)}`), Number(`0x${data[i + 2].slice(2, 4)}`), Number(`0x${data[i + 2].slice(4, 6)}`), 255];
const rgba = [Number(`0x${data[i + 2].slice(0, 2)}`), Number(`0x${data[i + 2].slice(2, 4)}`), Number(`0x${data[i + 2].slice(4, 6)}`), Number(`0x${data[i + 2].slice(6, 8)}`)];

// Figure out which image tile the pixel belongs to
const x_tile = (x - x % TILE_SIZE) / TILE_SIZE + (x < 0 ? -1 : 0);
Expand Down

0 comments on commit 499e8be

Please sign in to comment.