1
0
mirror of https://github.com/ComfyFactory/ComfyFactorio.git synced 2025-11-23 22:22:34 +02:00

Fix modules

This commit is contained in:
Gerkiz
2025-11-16 21:12:05 +01:00
parent 80f1eb7891
commit 2e22f2702c
6 changed files with 551 additions and 251 deletions

View File

@@ -27,6 +27,102 @@ require 'modules.autostash'
require 'utils.remote_chunks'
---------------- ENABLE MAPS HERE ----------------
--!Make sure only one map is enabled at a time.
--!Remove the "--" in front of the line to enable.
--!All lines with the "require" keyword are different maps.
--![[Comfylatron has seized the Fish Train and turned it into a time machine]]--
--require 'maps.chronosphere.main'
--![[Guide a Train through rough terrain, while defending it from the biters]]--
--require 'maps.mountain_fortress_v3.main'
--require 'maps.mountain_fortress_v2.main'
--require 'maps.mountain_fortress'
--![[Launch rockets in increasingly harder getting worlds.]]--
--require 'maps.journey.main'
--![[Infestation Islands]]--
--require 'maps.infestation_islands.main'
--![[Infinite random dungeon with RPG]]--
--require 'maps.dungeons.main'
--![[Defend the market against waves of biters]]--
--require 'maps.fish_defender_v2.main'
--require 'maps.crab_defender.main'
--require 'maps.fish_defender_v1.fish_defender'
--require 'maps.fish_defender.main'
--![[Adventure as a crew of pirates]]--
--require 'maps.pirates.main'
--![[East VS West Survival PVP, where you breed biters with science flasks]]--
--require 'maps.biter_hatchery.main'
--![[Fight in a world where everyone are prisoners]]
--require 'maps.planet_prison'
--![[Chop trees to gain resources]]--
--require 'maps.choppy'
--require 'maps.choppy_dx'
--![[Minesweeper?]]--
--require 'maps.minesweeper.main'
--![[Tower defense system]]--
--require 'maps.tower_defense.main'
--![[North VS South Survival PVP, feed the opposing team's biters with science flasks. Disable Autostash, Group and Poll modules.]]--
--require 'maps.biter_battles_v2.main'
--require 'maps.biter_battles.biter_battles'
--![[Randomly generating Islands that have to be beaten in levels to gain credits]]--
--require 'maps.island_troopers.main'
--![[Infinitely expanding mazes]]--
--require 'maps.stone_maze.main'
--require 'maps.labyrinth'
--![[Extreme survival mode with thirst and limited building room]]--
--require 'maps.desert_oasis'
--![[The trees are your enemy here]]--
--require 'maps.overgrowth'
--![[Wave Defense Map split in 4 Quarters]]--
--require 'maps.quarters'
--![[Flee from the collapsing map with portable base inside train]]--
--require 'maps.railway_troopers_v2.main'
--![[Another simliar version without collapsing terrain]]--
--require 'maps.railway_troopers.main'
--![[Territorial Control - reveal the map as you walk through the mist]]--
--require 'maps.territorial_control'
--![[Deep Jungle - dangerous map]]--
--require 'maps.deep_jungle.main'
--![[You fell in a dark cave, will you survive?]]--
--require 'maps.cave_choppy.main'
--require 'maps.cave_miner'
--require 'maps.cave_miner_v2.main'
--![[Hungry boxes eat your items, but reward you with new territory to build.]]--
--require 'maps.expanse.main'
--![[Dangerous forest with unique map revealing]]--
--require 'maps.spooky_forest'
--![[Defeat the biters and unlock new areas]]--
--require 'maps.spiral_troopers'
--![[Test map spawns all entities for testing]]--
--require 'maps.test_map.main'
---------------- !ENABLE MODULES HERE ----------------
--require 'modules.rpg.main'
--require 'modules.admins_operate_biters'
@@ -74,102 +170,6 @@ require 'utils.remote_chunks'
--require 'modules.turret_filler'
---------------------------------------------------------------
---------------- ENABLE MAPS HERE ----------------
--!Make sure only one map is enabled at a time.
--!Remove the "--" in front of the line to enable.
--!All lines with the "require" keyword are different maps.
--![[North VS South Survival PVP, feed the opposing team's biters with science flasks. Disable Autostash, Group and Poll modules.]]--
--require 'maps.biter_battles_v2.main'
--require 'maps.biter_battles.biter_battles'
--![[Guide a Train through rough terrain, while defending it from the biters]]--
--require 'maps.mountain_fortress_v3.main'
--require 'maps.mountain_fortress_v2.main'
--require 'maps.mountain_fortress'
--![[Comfylatron has seized the Fish Train and turned it into a time machine]]--
--require 'maps.chronosphere.main'
--![[Launch rockets in increasingly harder getting worlds.]]--
--require 'maps.journey.main'
--![[Infestation Islands]]--
--require 'maps.infestation_islands.main'
--![[Infinite random dungeon with RPG]]--
--require 'maps.dungeons.main'
--![[Defend the market against waves of biters]]--
--require 'maps.fish_defender_v2.main'
--require 'maps.crab_defender.main'
--require 'maps.fish_defender_v1.fish_defender'
--require 'maps.fish_defender.main'
--![[Adventure as a crew of pirates]]--
--require 'maps.pirates.main'
--![[East VS West Survival PVP, where you breed biters with science flasks]]--
--require 'maps.biter_hatchery.main'
--![[Fight in a world where everyone are prisoners]]
--require 'maps.planet_prison'
--![[Chop trees to gain resources]]--
--require 'maps.choppy'
--require 'maps.choppy_dx'
--![[Minesweeper?]]--
--require 'maps.minesweeper.main'
--![[Tower defense system]]--
--require 'maps.tower_defense.main'
--![[Randomly generating Islands that have to be beaten in levels to gain credits]]--
--require 'maps.island_troopers.main'
--![[Infinitely expanding mazes]]--
--require 'maps.stone_maze.main'
--require 'maps.labyrinth'
--![[Extreme survival mode with thirst and limited building room]]--
--require 'maps.desert_oasis'
--![[The trees are your enemy here]]--
--require 'maps.overgrowth'
--![[Wave Defense Map split in 4 Quarters]]--
--require 'maps.quarters'
--![[Flee from the collapsing map with portable base inside train]]--
--require 'maps.railway_troopers_v2.main'
--![[Another simliar version without collapsing terrain]]--
--require 'maps.railway_troopers.main'
--![[Territorial Control - reveal the map as you walk through the mist]]--
--require 'maps.territorial_control'
--![[Deep Jungle - dangerous map]]--
--require 'maps.deep_jungle.main'
--![[You fell in a dark cave, will you survive?]]--
--require 'maps.cave_choppy.main'
--require 'maps.cave_miner'
--require 'maps.cave_miner_v2.main'
--![[Hungry boxes eat your items, but reward you with new territory to build.]]--
--require 'maps.expanse.main'
--![[Dangerous forest with unique map revealing]]--
--require 'maps.spooky_forest'
--![[Defeat the biters and unlock new areas]]--
--require 'maps.spiral_troopers'
--![[Test map spawns all entities for testing]]--
--require 'maps.test_map.main'
--- this file exists only for the panel to sync and start from within the panel
-- it does nothing if it's not synced from within the panel

View File

@@ -19,6 +19,7 @@ local Score = require 'utils.gui.score'
local AntiGrief = require 'utils.antigrief'
local Core = require 'utils.core'
local RobotLimits = require 'modules.robot_limits'
local JailData = require 'utils.datastore.jail_data'
local format_number = require 'util'.format_number
local random = math.random
local insert = table.insert
@@ -1487,6 +1488,7 @@ function Public.reset_game()
end
Difficulty.reset_difficulty_poll({ difficulty_poll_closing_timeout = wave_grace_period })
local difficulties =
{
[1] =
@@ -1602,6 +1604,8 @@ function Public.reset_game()
return
end
JailData.set_valid_surface(surface.name)
for _, tile in pairs(surface.find_tiles_filtered({ name = { 'water', 'deepwater' }, area = { { -300, -256 }, { 300, 300 } } })) do
surface.set_tiles({ { name = Public.get_replacement_tile(surface, tile.position), position = { tile.position.x, tile.position.y } } }, true)
end
@@ -1691,6 +1695,8 @@ local function on_tick()
market.die()
game.print('Game won!', { r = 0.22, g = 0.88, b = 0.22 })
game.print('Game wave limit reached! Game will soft-reset shortly.', { r = 0.22, g = 0.88, b = 0.22 })
local message = 'Game won! Game wave limit reached! Game will soft-reset shortly.'
Server.to_discord_bold(table.concat { '*** ', message, ' ***' })
end
end

View File

@@ -4,9 +4,11 @@ local Task = require 'utils.task_token'
local Global = require 'utils.global'
local hotpatch = '[color=yellow]Hotpatch:[/color] '
local halt_after_timer = 60 * 60 * 1 -- 1 minute
local this = {}
local this =
{
halt_after_timer = 60 * 60 * 1 -- 1 minute
}
Global.register(
this,
@@ -21,6 +23,8 @@ local save_hot_patch_token = Task.register(
this.halted = nil
return
end
this.halt_after = nil
this.halted = nil
Server.save_hot_patch()
end
@@ -43,23 +47,42 @@ local save_hot_patch_notify_token =
end
game.print(hotpatch .. 'The server will be stopped in ' .. time_left .. ' seconds.')
game.print(hotpatch .. 'To abort the hotpatch, use the command /save-hot-patch-abort.')
game.print(hotpatch .. 'To abort the hotpatch, use the command /abort-patch-save.')
end
end
)
Commands.new('save-hot-patch', 'Tries to hotpatch the current save from the panel if possible.')
Commands.new('patch-save', 'Tries to hotpatch the current save from the panel if possible.')
:require_admin()
:add_alias('ps')
:add_alias('hot-patch')
:require_backend()
:add_parameter('halt_after', true, 'number')
:require_validation('Running this will stop the server and hotpatch, only run this if you really want to!')
:callback(
function (player)
function (player, halt_after)
if halt_after then
if halt_after == 0 then
this.halt_after_timer = 60
elseif halt_after < 1 then
player.print(hotpatch .. 'Halt after time cannot be less than 1 minute.')
return false
elseif halt_after > 60 then
player.print(hotpatch .. 'Halt after time cannot be greater than 60 minutes.')
return false
end
if not this.halt_after_timer == 60 then
this.halt_after_timer = 60 * 60 * halt_after
end
end
if not this.halt_after then
this.halt_after = game.tick + halt_after_timer
this.halt_after = game.tick + this.halt_after_timer
game.print(hotpatch .. 'Save hot-patching has been initiated by ' .. player.name .. '.')
game.print(hotpatch .. 'The server will be stopped, hotpatched and resumed in ' .. math.round(halt_after_timer / 60, 0) .. ' seconds.')
Task.set_duration_task(500, halt_after_timer, save_hot_patch_notify_token, {})
Task.set_timeout_in_ticks(halt_after_timer, save_hot_patch_token)
game.print(hotpatch .. 'The server will be stopped, hotpatched and resumed in ' .. math.round(this.halt_after_timer / 60, 0) .. ' seconds.')
Task.set_duration_task(500, this.halt_after_timer, save_hot_patch_notify_token, {})
Task.set_timeout_in_ticks(this.halt_after_timer, save_hot_patch_token)
else
player.print(hotpatch .. 'A hotpatch is already in progress.')
return false
@@ -67,11 +90,15 @@ Commands.new('save-hot-patch', 'Tries to hotpatch the current save from the pane
end
)
Commands.new('save-hot-patch-abort', 'Aborts the hotpatch if it is in progress.')
Commands.new('abort-patch-save', 'Aborts the hotpatch if it is in progress.')
:require_admin()
:require_backend()
:add_alias('aps')
:add_alias('hot-patch-abort')
:callback(
function (player)
this.halt_after_timer = 60 * 60 * 1
if not this.halted and this.halt_after then
game.print(hotpatch .. 'Hotpatch has been aborted by ' .. player.name .. '.')
this.halted = true

View File

@@ -4,7 +4,7 @@ require 'utils.datastore.session_data'
require 'utils.datastore.statistics'
require 'utils.datastore.jail_data'
require 'utils.datastore.quickbar_data'
require 'utils.datastore.warning_on_join_data'
require 'utils.datastore.warning_data'
require 'utils.datastore.message_on_join_data'
require 'utils.datastore.player_tag_data'
require 'utils.datastore.supporters'

View File

@@ -0,0 +1,411 @@
-- created by Gerkiz for ComfyFactorio
local Global = require 'utils.global'
local Server = require 'utils.server'
local Event = require 'utils.event'
local Utils = require 'utils.core'
local Gui = require 'utils.gui'
local Commands = require 'utils.commands'
local Token = require 'utils.token'
local Discord = require 'utils.discord'
local DiscordHandler = require 'utils.discord_handler'
local module_name = '[Warning handler] '
local warning_data_set = 'warnings'
local warnings = {}
local set_data = Server.set_data
local try_get_data = Server.try_get_data
local warning_frame_name = Gui.uid_name()
local ok_button_name = Gui.uid_name()
Global.register(
{
warnings = warnings
},
function (t)
warnings = t.warnings
end
)
local Public = {}
local function generate_warning_id()
return game.tick .. '_' .. math.random(1000, 9999)
end
local function set_character_state(player, state)
if not player or not player.valid then
return false
end
if player.character ~= nil then
player.character.active = state
end
return true
end
local function draw_warning_frame(player, warning_data)
local main_frame, inside_table = Gui.add_main_frame_with_toolbar(player, 'screen', warning_frame_name, nil, nil, 'Warning', true, 2)
if not main_frame or not inside_table then
return
end
main_frame.style.width = 500
main_frame.auto_center = true
local content_flow = inside_table.add
{
type = 'flow',
direction = 'vertical'
}
content_flow.style.top_padding = 16
content_flow.style.bottom_padding = 16
content_flow.style.left_padding = 24
content_flow.style.right_padding = 24
content_flow.style.vertical_spacing = 12
local top_row = content_flow.add
{
type = 'flow',
direction = 'horizontal'
}
local sprite_flow = top_row.add { type = 'flow' }
sprite_flow.style.vertical_align = 'center'
sprite_flow.add { type = 'sprite', sprite = 'utility/warning_icon' }
local label_flow = top_row.add { type = 'flow' }
label_flow.style.left_padding = 24
label_flow.style.top_padding = 6
local warning_message = '[font=heading-2]You have received a warning[/font]\n' .. (warning_data.reason or 'No reason provided.')
local label = label_flow.add
{
type = 'label',
caption = warning_message
}
label.style.single_line = false
label.style.width = 400
local notice_message = '[font=heading-2]Breaking our rules multiple times will result in a ban.[/font]'
local notice_label = content_flow.add
{
type = 'label',
caption = notice_message
}
notice_label.style.single_line = false
notice_label.style.width = 400
local bottom_flow = main_frame.add
{
type = 'flow',
direction = 'horizontal'
}
local right_flow = bottom_flow.add { type = 'flow' }
right_flow.style.horizontally_stretchable = true
right_flow.style.horizontal_align = 'right'
set_character_state(player, false)
local ok_button = right_flow.add
{
type = 'button',
name = ok_button_name,
caption = 'OK',
style = 'confirm_button'
}
Gui.set_data(ok_button, { warning_id = warning_data.id })
player.opened = main_frame
end
local function show_next_warning(player)
if not warnings[player.name] then
return
end
local player_warnings = warnings[player.name]
for _, warning in ipairs(player_warnings) do
if not warning.accepted then
draw_warning_frame(player, warning)
return
end
end
end
local function send_warning_discord_message(offender_name, admin_name, reason, accepted)
local data = Server.build_embed_data()
data.username = offender_name
data.admin = admin_name
data.reason = reason
data.accepted = accepted or false
local message = offender_name .. ' has ' .. (accepted and 'accepted' or 'received') .. ' a warning from ' .. admin_name .. '. Reason: ' .. reason
DiscordHandler.send_notification(
{
title = 'Warning',
description = message,
color = 'warning'
})
end
local function assign_warning(offender_name, admin_name, reason)
if not offender_name or not reason then
return false
end
local offender = game.get_player(offender_name)
local date = Server.get_current_date_with_time()
local warning_id = generate_warning_id()
local warning_data =
{
id = warning_id,
reason = reason,
admin = admin_name,
date = date,
accepted = false
}
if not warnings[offender_name] then
warnings[offender_name] = {}
end
table.insert(warnings[offender_name], warning_data)
set_data(warning_data_set, offender_name, warnings[offender_name])
send_warning_discord_message(offender_name, admin_name, reason, false)
if offender and offender.valid then
local frame = offender.gui.screen[warning_frame_name]
if not frame or not frame.valid then
draw_warning_frame(offender, warning_data)
end
end
return true
end
local function accept_warning(player_name, warning_id)
if not warnings[player_name] then
return false
end
local player_warnings = warnings[player_name]
local warning_data = nil
for _, warning in ipairs(player_warnings) do
if warning.id == warning_id then
warning_data = warning
break
end
end
if not warning_data then
return false
end
warning_data.accepted = true
warning_data.accepted_date = Server.get_current_date_with_time()
set_data(warning_data_set, player_name, player_warnings)
warnings[player_name] = player_warnings
send_warning_discord_message(player_name, warning_data.admin, warning_data.reason, true)
local p = game.get_player(player_name)
if p and p.valid then
set_character_state(p, true)
end
return true
end
local load_warning_token =
Token.register(
function (data)
local key = data.key
local value = data.value
if not key or not value then
return
end
local player = game.get_player(key)
if not player or not player.valid then
return
end
if type(value) ~= 'table' then
return
end
if not value[1] and value.id then
value = { value }
end
if not value[1] then
return
end
local needs_save = false
for _, warning in ipairs(value) do
if not warning.id then
warning.id = generate_warning_id()
needs_save = true
end
end
warnings[key] = value
if needs_save then
set_data(warning_data_set, key, value)
end
show_next_warning(player)
end
)
function Public.try_dl_data(key)
key = tostring(key)
local secs = Server.get_current_time()
if not secs then
return
else
try_get_data(warning_data_set, key, load_warning_token)
end
end
Commands.new('warn', 'Assigns a warning to a player.')
:add_parameter('offender', false, 'player')
:add_parameter('reason', false, 'string')
:require_backend()
:callback(function (player, offender, reason)
if not offender then
Utils.print_to(player, module_name .. 'No valid player given.')
return false
end
if not reason or string.len(reason) <= 0 then
Utils.print_to(player, module_name .. 'No valid reason was given.')
return false
end
if string.len(reason) < 10 then
Utils.print_to(player, module_name .. 'Reason is too short.')
return false
end
if assign_warning(offender.name, player.name, reason) then
Utils.print_to(player, module_name .. 'Warning assigned to ' .. offender.name .. '.')
return true
else
Utils.print_to(player, module_name .. 'Failed to assign warning.')
return false
end
end)
Event.add(
defines.events.on_player_joined_game,
function (event)
local player = game.get_player(event.player_index)
if not player or not player.valid then
return
end
Public.try_dl_data(player.name)
end
)
Gui.on_click(
ok_button_name,
function (event)
local player = event.player
if not player or not player.valid then
return
end
local screen = player.gui.screen
local frame = screen[warning_frame_name]
if not frame or not frame.valid then
return
end
local data = Gui.get_data(event.element)
if not data or not data.warning_id then
return
end
accept_warning(player.name, data.warning_id)
frame.destroy()
show_next_warning(player)
end
)
Server.on_data_set_changed(
warning_data_set,
function (data)
if not data then
return
end
local key = data.key
local value = data.value
if not key or not value then
return
end
if type(value) ~= 'table' then
warnings[key] = nil
return
end
if not value[1] and value.id then
value = { value }
end
if not value[1] then
warnings[key] = nil
return
end
for _, warning in ipairs(value) do
if not warning.id then
warning.id = generate_warning_id()
end
end
warnings[key] = value
local player = game.get_player(key)
if player and player.valid then
local frame = player.gui.screen[warning_frame_name]
if not frame or not frame.valid then
show_next_warning(player)
end
end
end
)
Public.assign_warning = assign_warning
Public.accept_warning = accept_warning
Public.get_warnings = function ()
return warnings
end
return Public

View File

@@ -1,144 +0,0 @@
-- created by Gerkiz for ComfyFactorio
local Token = require 'utils.token'
local Server = require 'utils.server'
local Event = require 'utils.event'
local Gui = require 'utils.gui'
local dataset = 'warnings'
local set_data = Server.set_data
local try_get_data = Server.try_get_data
local warning_frame_name = Gui.uid_name()
local discard_button_name = Gui.uid_name()
local Public = {}
local function draw_warning_frame(player, message)
local main_frame, inside_table = Gui.add_main_frame_with_toolbar(player, 'screen', warning_frame_name, nil, nil, 'Warning', true, 2)
if not main_frame or not inside_table then
return
end
local main_frame_style = main_frame.style
main_frame_style.width = 400
main_frame.auto_center = true
local content_flow = inside_table.add {type = 'flow', direction = 'horizontal'}
content_flow.style.top_padding = 16
content_flow.style.bottom_padding = 16
content_flow.style.left_padding = 24
content_flow.style.right_padding = 24
content_flow.style.horizontally_stretchable = false
local sprite_flow = content_flow.add {type = 'flow'}
sprite_flow.style.vertical_align = 'center'
sprite_flow.style.vertically_stretchable = false
sprite_flow.add {type = 'sprite', sprite = 'utility/warning_icon'}
local label_flow = content_flow.add {type = 'flow'}
label_flow.style.horizontal_align = 'left'
label_flow.style.top_padding = 10
label_flow.style.left_padding = 24
local warning_message = '[font=heading-2]Message from Comfy to: ' .. player.name .. '[/font]\n' .. message
label_flow.style.horizontally_stretchable = false
local label = label_flow.add {type = 'label', caption = warning_message}
label.style.single_line = false
local bottom_flow = main_frame.add({type = 'flow', direction = 'horizontal'})
local left_flow = bottom_flow.add({type = 'flow'})
left_flow.style.horizontal_align = 'left'
left_flow.style.horizontally_stretchable = true
local close_button = left_flow.add({type = 'button', name = discard_button_name, caption = 'Understood'})
close_button.style = 'back_button'
player.opened = main_frame
end
local fetch =
Token.register(
function(data)
local key = data.key
if not key then
return
end
local value = data.value
if not value then
return
end
local player = game.get_player(key)
if not player or not player.valid then
return
end
draw_warning_frame(player, value)
end
)
--- Tries to get data from the webpanel and applies the value to the player.
-- @param data_set player token
function Public.fetch(key)
local secs = Server.get_current_time()
if not secs then
local player = game.players[key]
if not player or not player.valid then
return
end
return
else
try_get_data(dataset, key, fetch)
end
end
Event.add(
defines.events.on_player_joined_game,
function(event)
local player = game.get_player(event.player_index)
if not player or not player.valid then
return
end
Public.fetch(player.name)
end
)
Gui.on_click(
discard_button_name,
function(event)
local player = event.player
local screen = player.gui.screen
local frame = screen[warning_frame_name]
if not player or not player.valid then
return
end
if frame and frame.valid then
frame.destroy()
set_data(dataset, player.name)
end
end
)
Server.on_data_set_changed(
dataset,
function(data)
if not data then
return
end
local key = data.key
local value = data.value
local player = game.get_player(key)
if not player or not player.valid then
return
end
draw_warning_frame(player, value)
end
)
return Public