244 lines
8.4 KiB
Lua

local modwarning = require "modwarning"
-- position and direction of the buttons
local blpflip_location = "top" -- top/left/center
local blpflip_flow_direction = "horizontal" -- horizontal/vertical
local flipdata = require "flip-data"
local fv,fh = assert(flipdata.fv), assert(flipdata.fh)
--------------------------------------------------------------------
-- a generic function to walk into structure to manage avoid error when it does not exists.
local walk = require "walk"
local safecall = require "safecall"
local get_user_setting = require "get_user_setting"
local function getBlueprintCursorStack(player)
local cursor = player.cursor_stack
if cursor == nil then
return nil
end
if (
cursor.valid and cursor.valid_for_read and
(cursor.is_blueprint or cursor.is_blueprint_book) and
safecall(cursor.is_blueprint_setup) -- 0.18 (>= 0.18.37 ?) can raise an error "Item is no blueprint", catch it to avoid game crash.
) then --check if is a blueprint, work in book as well
return cursor
end
return nil
end
--[[
--old way setup -- OH my god Why???
if cursor.valid_for_read and cursor.name == "blueprint" and cursor.is_blueprint_setup() then
return cursor
elseif cursor.valid_for_read and cursor.name == "blueprint-book" then
local bookInv = cursor.get_inventory(defines.inventory.item_active)
if (bookInv[1].valid_for_read and bookInv[1].name == "blueprint") then
if bookInv[1].is_blueprint_setup() then
return bookInv[1]
end
end
end
]]--
local function flip_v(player_index)
local player = game.players[player_index]
local cursor = getBlueprintCursorStack(player)
if cursor then
if cursor.get_blueprint_entities() ~= nil then
local ents = cursor.get_blueprint_entities()
for i = 1, #ents do
local ent = ents[i]
-- local dir = ent.direction or 0
local handler = fv[ent.name] or fv["*"]
handler(ent)
--game.print("DEBUG fv: "..tostring(i).."/"..tostring(#ents).." name="..tostring(ent.name).." dir="..dir.." ent.direction="..tostring(ent.direction).." handler="..(handler==fv["*"] and "default" or tostring(handler)) .. " ent is "..type(ent))
ent.position.y = -ent.position.y
if ent.drop_position then
ent.drop_position.y = -ent.drop_position.y
end
if ent.pickup_position then
ent.pickup_position.y = -ent.pickup_position.y
end
end
cursor.set_blueprint_entities(ents)
end
-- also flip tiles if they exists in the blueprint
if cursor.get_blueprint_tiles() ~= nil then
local ents = cursor.get_blueprint_tiles()
for i = 1, #ents do
local ent = ents[i]
local dir = ent.direction or 0
ent.direction = (12 - dir)%8
ent.position.y = -ent.position.y
end
cursor.set_blueprint_tiles(ents)
end
end
end
local function flip_h(player_index)
local player = game.players[player_index]
local cursor = getBlueprintCursorStack(player)
if cursor then
if cursor.get_blueprint_entities() ~= nil then
local ents = cursor.get_blueprint_entities()
for i = 1, #ents do
local ent = ents[i]
-- local dir = ent.direction or 0
local handler = fh[ent.name] or fh["*"]
handler(ent)
--game.print("DEBUG fh: "..tostring(i).."/"..tostring(#ents).." name="..tostring(ent.name).." dir="..dir.." ent.direction="..tostring(ent.direction).." handler="..(handler==fh["*"] and "default" or tostring(handler)) )
ent.position.x = -ent.position.x
if ent.drop_position then
ent.drop_position.x = -ent.drop_position.x
end
if ent.pickup_position then
ent.pickup_position.x = -ent.pickup_position.x
end
end
cursor.set_blueprint_entities(ents)
end
if cursor.get_blueprint_tiles() ~= nil then
local ents = cursor.get_blueprint_tiles()
for i = 1, #ents do
local ent = ents[i]
local dir = ent.direction or 0
ent.direction = (16 - dir)%8
ent.position.x = -ent.position.x
end
cursor.set_blueprint_tiles(ents)
end
end
end
local function reverse_inserters(player_index)
local player = game.players[player_index]
local cursor = getBlueprintCursorStack(player)
if cursor then
if cursor.get_blueprint_entities() ~= nil then
local ents = cursor.get_blueprint_entities()
for i = 1, #ents do
local ent = ents[i]
if ent.pickup_position and ent.drop_position then
local old_drop_y = ent.drop_position.y
local old_drop_x = ent.drop_position.x
ent.drop_position.y = ent.pickup_position.y
ent.drop_position.x = ent.pickup_position.x
ent.pickup_position.y = old_drop_y
ent.pickup_position.x = old_drop_x
end
end
cursor.set_blueprint_entities(ents)
end
end
end
-- remove older mod stuff ? --
local function oldStrangeStuff(player_index)
local gui_top = walk(game, {"players", player_index, "gui", "top"})
if gui_top and gui_top.blueprint_flipper_flow then
gui_top.blueprint_flipper_flow.destroy()
end
end
local function doButtons(player_index)
local gui_location = walk(game, {"players", player_index, "gui", blpflip_location})
if not gui_location then
-- avoid error but there are something strange!
modwarning("doButtons: there is no gui_location for player_index="..tostring(player_index)..". Please report it to the mod's Author.")
return
end
local exists = walk(gui_location, {"blpflip_flow"})
if not exists then
local flow = gui_location.add{type = "flow", name = "blpflip_flow", direction = blpflip_flow_direction}
flow.add{type = "button", name = "blueprint_flip_horizontal", style = "blpflip_button_horizontal"}
flow.add{type = "button", name = "blueprint_flip_vertical", style = "blpflip_button_vertical"}
-- flow.add{type = "button", name = "blueprint_reverse_inserters", style = "blpflip_button_reverse_inserters"}
end
oldStrangeStuff(player_index)
end
-- hide buttons = remove them --
local function rmButtons(player_index)
local exists = walk(game, {"players", player_index, "gui", blpflip_location, "blpflip_flow"})
if exists then
exists.destroy()
end
end
-- create or hide buttons (per user) --
local function manageButtons(player_index)
-- avoid strange case where player_index is nil
if not player_index then return end
-- get the user setting --
local show_buttons = get_user_setting(player_index, "blueprint_flip_and_turn_show_buttons")
-- it should be true or false (not nil)
--if show_buttons == nil then show_buttons = true end
if show_buttons then
--game.print("DEBUG: show_buttons yes (doButtons)")
doButtons(player_index)
else
--game.print("DEBUG: show_buttons nope (rmButtons)")
rmButtons(player_index)
end
end
-- button click -> action --
script.on_event(defines.events.on_gui_click,function(event)
if event.element.name == "blueprint_flip_horizontal" then
flip_h(event.player_index)
elseif event.element.name == "blueprint_flip_vertical" then
flip_v(event.player_index)
elseif event.element.name == "blueprint_reverse_inserters" then
reverse_inserters(event.player_index)
end
end)
local function manageButtonsAllPlayers()
for player_index=1,#game.players do manageButtons(player_index) end
end
-- create buttons --
script.on_event(defines.events.on_player_created,function(event)
--game.print("DEBUG: EVENT on_player_created")
manageButtons(event.player_index)
end)
-- compat-check: defines.events.on_player_created 0.16/0.17 ok
script.on_configuration_changed(function(data)
--game.print("DEBUG: EVENT on_configuration_changed")
manageButtonsAllPlayers()
end)
-- compat-check: script.on_configuration_changed 0.16/0.17 ok
script.on_init(function()
--game.print("DEBUG: EVENT on_init")
manageButtonsAllPlayers()
--for i=1,#game.players do manageButtons(i) end
end)
-- compat-check: script.on_init 0.16/0.17 ok
script.on_event(defines.events.on_runtime_mod_setting_changed, function(event)
-- player_index: the player index
-- setting: the setting name (string)
-- setting_type: "runtime-per-user", or "runtime-global"
local setting, setting_type = event.setting, event.setting_type
if setting_type=="runtime-per-user" and setting=="blueprint_flip_and_turn_show_buttons" then
--game.print("DEBUG: EVENT on_runtime_mod_setting_changed "..tostring(setting).." "..tostring(setting_type))
manageButtons(event.player_index)
end
end)
-- compat-check: defines.events.on_runtime_mod_setting_changed 0.16/0.17 ok
-- actions by shortcut --
script.on_event("blueprint_hotkey_flip_horizontal", function(event) flip_h(event.player_index) end)
script.on_event("blueprint_hotkey_flip_vertical", function(event) flip_v(event.player_index) end)
--pcall(function()
--script.on_event("blueprint_hotkey_reverse_inserters", function(event) reverse_inserters(event.player_index) end)
--end)