@expcluster/legacy 7.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (108) hide show
  1. package/LICENSE.md +21 -0
  2. package/dist/browser/package.json +40 -0
  3. package/dist/browser/tsconfig.browser.tsbuildinfo +1 -0
  4. package/dist/browser/web/index.d.ts +1 -0
  5. package/dist/browser/web/index.d.ts.map +1 -0
  6. package/dist/browser/web/index.js +2 -0
  7. package/dist/browser/web/index.js.map +1 -0
  8. package/dist/node/index.d.ts +3 -0
  9. package/dist/node/index.d.ts.map +1 -0
  10. package/dist/node/index.js +10 -0
  11. package/dist/node/index.js.map +1 -0
  12. package/dist/node/instance.d.ts +4 -0
  13. package/dist/node/instance.d.ts.map +1 -0
  14. package/dist/node/instance.js +8 -0
  15. package/dist/node/instance.js.map +1 -0
  16. package/dist/node/tsconfig.node.tsbuildinfo +1 -0
  17. package/dist/web/manifest.json +7 -0
  18. package/dist/web/static/exp_legacy.9b6538559ed5e689539c.js +355 -0
  19. package/dist/web/static/index_ts.8f9d451c8d3f7f293da6.js +22 -0
  20. package/dist/web/static/main.94e1b48804112ca8bdfc.js +118 -0
  21. package/dist/web/static/package_json.a83729efdb0697b12396.js +22 -0
  22. package/dist/web/static/web_index_tsx.e5a01ac0e4b0a6f6517f.js +21 -0
  23. package/index.ts +8 -0
  24. package/instance.ts +7 -0
  25. package/module/config/_file_loader.lua +29 -0
  26. package/module/config/advanced_start.lua +112 -0
  27. package/module/config/afk_kick.lua +14 -0
  28. package/module/config/bonus.lua +105 -0
  29. package/module/config/chat_reply.lua +136 -0
  30. package/module/config/compilatron.lua +25 -0
  31. package/module/config/death_logger.lua +15 -0
  32. package/module/config/deconlog.lua +11 -0
  33. package/module/config/discord_alerts.lua +25 -0
  34. package/module/config/expcore/permission_groups.lua +143 -0
  35. package/module/config/graftorio.lua +7 -0
  36. package/module/config/gui/autofill.lua +129 -0
  37. package/module/config/gui/player_list_actions.lua +201 -0
  38. package/module/config/gui/rockets.lua +47 -0
  39. package/module/config/gui/science.lua +21 -0
  40. package/module/config/gui/tasks.lua +13 -0
  41. package/module/config/gui/warps.lua +52 -0
  42. package/module/config/inventory_clear.lua +9 -0
  43. package/module/config/join_messages.lua +8 -0
  44. package/module/config/lawnmower.lua +6 -0
  45. package/module/config/logging.lua +30 -0
  46. package/module/config/miner.lua +8 -0
  47. package/module/config/module.lua +86 -0
  48. package/module/config/nukeprotect.lua +30 -0
  49. package/module/config/pollution_grading.lua +9 -0
  50. package/module/config/popup_messages.lua +10 -0
  51. package/module/config/preset_player_colours.lua +33 -0
  52. package/module/config/preset_player_quickbar.lua +6 -0
  53. package/module/config/protection.lua +17 -0
  54. package/module/config/repair.lua +8 -0
  55. package/module/config/research.lua +179 -0
  56. package/module/config/scorched_earth.lua +116 -0
  57. package/module/config/spawn_area.lua +255 -0
  58. package/module/config/station_auto_name.lua +11 -0
  59. package/module/config/statistics.lua +46 -0
  60. package/module/config/vlayer.lua +180 -0
  61. package/module/config/warnings.lua +38 -0
  62. package/module/control.lua +46 -0
  63. package/module/expcore/datastore.lua +884 -0
  64. package/module/expcore/external.lua +146 -0
  65. package/module/expcore/permission_groups.lua +355 -0
  66. package/module/expcore/player_data.lua +152 -0
  67. package/module/locale/en/addons.cfg +31 -0
  68. package/module/locale/en/data.cfg +114 -0
  69. package/module/locale/en/expcore.cfg +16 -0
  70. package/module/locale/en/gui.cfg +114 -0
  71. package/module/locale/zh-CN/addons.cfg +31 -0
  72. package/module/locale/zh-CN/data.cfg +114 -0
  73. package/module/locale/zh-CN/expcore.cfg +16 -0
  74. package/module/locale/zh-CN/gui.cfg +122 -0
  75. package/module/locale/zh-TW/addons.cfg +31 -0
  76. package/module/locale/zh-TW/data.cfg +114 -0
  77. package/module/locale/zh-TW/expcore.cfg +16 -0
  78. package/module/locale/zh-TW/gui.cfg +122 -0
  79. package/module/module.json +14 -0
  80. package/module/module_exports.lua +3 -0
  81. package/module/modules/control/jail.lua +119 -0
  82. package/module/modules/control/protection.lua +204 -0
  83. package/module/modules/control/reports.lua +225 -0
  84. package/module/modules/control/spectate.lua +173 -0
  85. package/module/modules/control/vlayer.lua +807 -0
  86. package/module/modules/control/warnings.lua +331 -0
  87. package/module/modules/control/warps.lua +488 -0
  88. package/module/modules/data/alt-view.lua +26 -0
  89. package/module/modules/data/greetings.lua +45 -0
  90. package/module/modules/data/language.lua +21 -0
  91. package/module/modules/data/player-colours.lua +63 -0
  92. package/module/modules/data/quickbar.lua +72 -0
  93. package/module/modules/data/statistics.lua +181 -0
  94. package/module/modules/data/tag.lua +82 -0
  95. package/module/modules/data/toolbar.lua +31 -0
  96. package/module/modules/graftorio/forcestats.lua +196 -0
  97. package/module/modules/graftorio/general.lua +63 -0
  98. package/module/modules/graftorio/require.lua +28 -0
  99. package/module/modules/graftorio/statics.lua +36 -0
  100. package/module/modules/gui/vlayer.lua +547 -0
  101. package/module/modules/gui/warp-list.lua +909 -0
  102. package/module/utils/event.lua +86 -0
  103. package/package.json +38 -0
  104. package/tsconfig.browser.json +4 -0
  105. package/tsconfig.json +7 -0
  106. package/tsconfig.node.json +5 -0
  107. package/web/index.tsx +0 -0
  108. package/webpack.config.js +29 -0
@@ -0,0 +1,16 @@
1
+ [expcore-data]
2
+ description-preference=允許寫入資料。
3
+ description-data=把用戶資料寫入電腦
4
+ arg-option="All", "Statistics", "Settings", "Required" 之中
5
+ set-preference=你的喜好已設定為 __1__ 。在你重新加入前將不會有任何改動。
6
+ get-preference=你的喜好為 __1__ 。使用 /set-preference 來更改,使用 /save-data 來獲得一份資料副本。
7
+ get-data=你的個人資料已寫入: factorio/script_output/expgaming_player_data.json
8
+ data-failed=無法載入你的個人資料,任何改動將不會保存。
9
+ data-restore=已載入你的個人資料,所有改動將會被保存。
10
+ preference=儲存喜好
11
+ preference-tooltip=那種資料將在退出時保存
12
+ preference-value-tooltip=使用 /set-preference 來更換儲存喜好
13
+ preference-All=所有資料都會被儲存
14
+ preference-Statistics=只有數據, 設定和資料會被儲存
15
+ preference-Settings=只有設定和資料會被儲存
16
+ preference-Required=只有需要的資料會被儲存
@@ -0,0 +1,122 @@
1
+ [player-list]
2
+ main-tooltip=用戶名單
3
+ open-action-bar=選項
4
+ close-action-bar=關閉選項
5
+ reason-confirm=確認原因
6
+ reason-entry=輸入原因
7
+ goto-player=傳送到用戶
8
+ bring-player=傳送用戶到自己
9
+ report-player=舉報用戶
10
+ warn-player=警告用戶
11
+ jail-player=監禁用戶
12
+ kick-player=踢除用戶
13
+ ban-player=封禁用戶
14
+ afk-time=__1__% 地圖時間\n上次移動: __2__
15
+ open-map=__1__ __2__\n__3__\n按下打開地圖
16
+
17
+ [warp-list]
18
+ main-caption=傳送陣清單 [img=info]
19
+ main-tooltip=傳送陣清單
20
+ sub-tooltip=傳送陣在 __1__ 秒內只能使用一次。 亦需在 __2__ 格之內使用\n__3__\n__4__\n__5__\n__6__\n__7__\n__8__
21
+ sub-tooltip-current= - __1__ 你目前的傳送陣;
22
+ sub-tooltip-connected= - __1__ 你可以到本傳送陣;
23
+ sub-tooltip-different= - __1__ 該傳送陣未連接;
24
+ sub-tooltip-cooldown= - __1__ 傳送冷卻中;
25
+ sub-tooltip-not_available= - __1__ 你不在傳送陣範圍;
26
+ sub-tooltip-bypass= - __1__ 你可以傳送到這裏;
27
+ too-close=無法新建傳送陣; 太接近 __1__ 了
28
+ too-close-to-water=無法新建傳送陣; 太接近水源了, 請移動 __1__ 格又或者填平該地方
29
+ too-close-to-entities=無法新建傳送陣; 太接近其他東西, 請移動 __1__ 格又或者拆除該東西
30
+ last-edit=最後由 __1__ 在 __2__ 更改\n按這在地圖上看
31
+ add-tooltip=新建傳送陣
32
+ confirm-tooltip=儲存更改
33
+ cancel-tooltip=放棄更改
34
+ edit-tooltip=現被 __1__ 修改中
35
+ edit-tooltip-none=現沒有被人修改
36
+ remove-tooltip=拆除傳送陣
37
+ timer-tooltip=請等 __1__ 秒才再次傳送
38
+ timer-tooltip-zero=你要等 __1__ 秒才可以再次傳送
39
+ goto-tooltip=到 X __1__ Y __2__
40
+ goto-bypass=到 X __1__ Y __2__, 繞行模式
41
+ goto-bypass-different-network=到 X __1__ Y __2__, 繞行模式 (不同網絡)
42
+ goto-same-warp=你已在該傳送陣
43
+ goto-different-network=該傳送陣未連接, 你可使用電纜連接
44
+ goto-cooldown=傳送冷卻中, 請等候冷卻
45
+ goto-disabled=你不在傳送陣, 請移至任意傳送陣
46
+ goto-edit=修改傳送陣圖案
47
+
48
+ [bonus]
49
+ description=取得 / 設定 Bonus 量。
50
+ arg-amount=Bonus 數量, 0 來停用。
51
+ set=你的 Bonus 已設為 __1__。
52
+ get=你的 Bonus 為 __1__。
53
+ perm=你沒有足夠權限設多過 __1__。
54
+ display-fmms=挖掘速度
55
+ display-fmms-tooltip=勢力挖掘速度
56
+ display-frs=跑步速度
57
+ display-frs-tooltip=勢力跑步速度
58
+ display-fcs=合成速度
59
+ display-fcs-tooltip=勢力合成速度
60
+ display-fisb=儲存位
61
+ display-fisb-tooltip=勢力儲存位
62
+ display-fhb=生命
63
+ display-fhb-tooltip=勢力生命
64
+ display-frdb=到達距離
65
+ display-frdb-tooltip=勢力到達距離
66
+ display-fwrsm=機械人速度
67
+ display-fwrsm-tooltip=勢力機械人速度
68
+ display-fwrbm=機械人電力
69
+ display-fwrbm-tooltip=勢力機械人電力
70
+ display-fwrsb=械人儲存
71
+ display-fwrsb-tooltip=勢力機械人儲存
72
+ display-ffrlm=機械人生命
73
+ display-ffrlm-tooltip=勢力戰鬥機械人生命時間
74
+
75
+ [vlayer]
76
+ main-tooltip=Vlayer 介面
77
+ description-pbr=使用 Vlayer 為玩家電池充電
78
+ description-vi=Vlayer 資訊
79
+ pbr-not-running=vlayer 沒有運行
80
+ display-item-solar=[img=entity/solar-panel] 太陽能板
81
+ display-item-accumulator=[img=entity/accumulator] 蓄電池
82
+ display-current-production=[virtual-signal=signal-P] 現時產能
83
+ display-sustained-production=[virtual-signal=signal-S] 持續產能
84
+ display-max-capacity=[virtual-signal=signal-C] 電池容量
85
+ display-current-capacity=[virtual-signal=signal-E] 電池電量
86
+ display-remaining-surface-area=[virtual-signal=signal-R] 餘下土地
87
+ display-item-solar-tooltip=太陽能板數量
88
+ display-item-accumulator-tooltip=蓄電池數量
89
+ display-current-production-tooltip=現時電力產能
90
+ display-sustained-production-tooltip=持續電力產能
91
+ display-max-capacity-tooltip=電池最大容量
92
+ display-current-capacity-tooltip=現時電池電量
93
+ display-remaining-surface-area-tooltip=餘下土地。 放入堆填來增加
94
+ steel-chest-detect=沒檢測到鋼箱
95
+ steel-chest-empty=鋼箱不是空的
96
+ control-refresh=刷新列表
97
+ control-see=查看介面
98
+ control-build=建造介面
99
+ control-remove=拆除介面
100
+ result-build=建造了
101
+ result-remove=拆除了
102
+ result-interface-location=__1__ 介面在 __2__
103
+ interface-result=__1__ 在 __2__ __3__ __4__ 介面
104
+ result-unable=無法建造 __1__ 介面,因 __2__
105
+ result-multiple=檢測到多個鋼箱
106
+ result-limit=超出最大限制
107
+ result-space=空間不足
108
+ control-type-energy=電力
109
+ control-type-circuit=回路
110
+ control-type-storage-input=放入箱
111
+ control-type-storage-output=提取箱
112
+ power-on-space-research=你要研究 [technology=__1__] 在 __2__ 級 才可使用太空平台 vlayer 功能。
113
+ enter=現在進入 vlayer 區域選擇
114
+ exit=已進入 vlayer 區域選擇
115
+
116
+ [toolbar]
117
+ main-caption=工具箱
118
+ main-tooltip=工具箱設定\n選上來設定喜好
119
+ reset=重設
120
+ toggle=啟用喜好
121
+ move-up=向上
122
+ move-down=向下
@@ -0,0 +1,14 @@
1
+ {
2
+ "name": "exp_legacy",
3
+ "load": [
4
+ "control.lua"
5
+ ],
6
+ "require": [
7
+ ],
8
+ "dependencies": {
9
+ "clusterio": "*",
10
+ "exp_util": "*",
11
+ "exp_roles": "*",
12
+ "exp_gui": "*"
13
+ }
14
+ }
@@ -0,0 +1,3 @@
1
+ --- Can contain anything you want to allow other plugins to have access to, this example exposes the control file
2
+ -- Access the exports from other modules using require("modules/exp_legacy")
3
+ return require("modules/exp_legacy/control")
@@ -0,0 +1,119 @@
1
+ --[[-- Control Module - Jail
2
+ - Adds a way to jail players.
3
+ @control Jail
4
+ @alias Jail
5
+
6
+ @usage
7
+ -- import the module from the control modules
8
+ local Jail = require("modules.exp_legacy.modules.control.jail") --- @dep modules.control.jail
9
+
10
+ -- This will give 'MrBiter' the jail role, which suppresses all of their other roles
11
+ -- the player name and reason are only so they can be included in the event for user feedback
12
+ Jail.jail_player('MrBiter', 'Cooldude2606', 'Likes biters too much')
13
+
14
+ -- This will remove the jail role from 'MrBiter', restoring their other roles
15
+ -- again as above the player name is only used in the event for user feedback
16
+ Jail.unjail_player('MrBiter', 'Cooldude2606')
17
+ ]]
18
+
19
+ local Roles = require("modules/exp_roles")
20
+
21
+ local valid_player = function(p) return type(p) == "userdata" and p or game.get_player(p) end
22
+
23
+ --- The role given to jailed players, it has a higher priority than every other role
24
+ local function jail_role()
25
+ return assert(Roles.get_role_by_name("Jail"), "The Jail role does not exist")
26
+ end
27
+
28
+ local Jail = {
29
+ events = {
30
+ --- When a player is assigned to jail
31
+ -- @event on_player_jailed
32
+ -- @tparam number player_index the index of the player who was jailed
33
+ -- @tparam string by_player_name the name of the player who jailed the other player
34
+ -- @tparam string reason the reason that the player was jailed
35
+ on_player_jailed = script.generate_event_name(),
36
+ --- When a player is unassigned from jail
37
+ -- @event on_player_unjailed
38
+ -- @tparam number player_index the index of the player who was unjailed
39
+ -- @tparam string by_player_name the name of the player who unjailed the other player
40
+ on_player_unjailed = script.generate_event_name(),
41
+ },
42
+ }
43
+
44
+ --- Used to emit the jail related events
45
+ -- @tparam number event the name of the event that will be emited
46
+ -- @tparam LuaPlayer player the player who is being acted on
47
+ -- @tparam string by_player_name the player who is doing the action
48
+ -- @tparam string reason the reason for the action (jail)
49
+ local function event_emit(event, player, by_player_name, reason)
50
+ script.raise_event(event, {
51
+ name = event,
52
+ tick = game.tick,
53
+ player_index = player.index,
54
+ by_player_name = by_player_name,
55
+ reason = reason,
56
+ })
57
+ end
58
+
59
+ --- Jail.
60
+ -- Functions related to jail
61
+ -- @section jail-functions
62
+
63
+ --- Checks if the player is currently in jail
64
+ -- @tparam LuaPlayer player the player to check if they are in jail
65
+ -- @treturn boolean whether the player is currently in jail
66
+ function Jail.is_jailed(player)
67
+ local valid = valid_player(player)
68
+ return valid ~= nil and jail_role():has_player(valid)
69
+ end
70
+
71
+ --- Moves a player to jail, which suppresses all of their other roles
72
+ -- @tparam LuaPlayer player the player who will be jailed
73
+ -- @tparam string by_player_name the name of the player who is doing the jailing
74
+ -- @tparam[opt='Non given.'] string reason the reason that the player is being jailed
75
+ -- @treturn boolean wheather the user was jailed successfully
76
+ function Jail.jail_player(player, by_player_name, reason)
77
+ player = valid_player(player)
78
+ if not player then return end
79
+ if not by_player_name then return end
80
+
81
+ reason = reason or "Non given."
82
+
83
+ local role = jail_role()
84
+ if role:has_player(player) then return end
85
+
86
+ player.walking_state = { walking = false, direction = player.walking_state.direction }
87
+ player.riding_state = { acceleration = defines.riding.acceleration.nothing, direction = player.riding_state.direction }
88
+ player.mining_state = { mining = false }
89
+ player.shooting_state = { state = defines.shooting.not_shooting, position = player.shooting_state.position }
90
+ player.picking_state = false
91
+ player.repair_state = { repairing = false, position = player.repair_state.position }
92
+
93
+ role:assign(player, { by_player_name = by_player_name, silent = true })
94
+
95
+ event_emit(Jail.events.on_player_jailed, player, by_player_name, reason)
96
+
97
+ return true
98
+ end
99
+
100
+ --- Moves a player out of jail, which restores all of their other roles
101
+ -- @tparam LuaPlayer player the player that will be unjailed
102
+ -- @tparam string by_player_name the name of the player that is doing the unjail
103
+ -- @treturn boolean whether the player was unjailed successfully
104
+ function Jail.unjail_player(player, by_player_name)
105
+ player = valid_player(player)
106
+ if not player then return end
107
+ if not by_player_name then return end
108
+
109
+ local role = jail_role()
110
+ if not role:has_player(player) then return end
111
+
112
+ role:unassign(player, { by_player_name = by_player_name, silent = true })
113
+
114
+ event_emit(Jail.events.on_player_unjailed, player, by_player_name)
115
+
116
+ return true
117
+ end
118
+
119
+ return Jail
@@ -0,0 +1,204 @@
1
+ --[[-- Control Module - Protection
2
+ - Controls protected entities
3
+ @control Protection
4
+ @alias Protection
5
+ ]]
6
+
7
+ local Storage = require("modules/exp_util/storage")
8
+ local Event = require("modules/exp_legacy/utils/event") --- @dep utils.event
9
+ local config = require("modules.exp_legacy.config.protection") --- @dep config.protection
10
+ local EntityProtection = {
11
+ protected_entity_names = table.deep_copy(config.always_protected_names),
12
+ protected_entity_types = table.deep_copy(config.always_protected_types),
13
+ events = {
14
+ --- When a player mines a protected entity
15
+ -- @event on_player_mined_protected
16
+ -- @tparam number player_index the player index of the player who got mined the entity
17
+ -- @tparam LuaEntity entity the entity which was mined
18
+ on_player_mined_protected = script.generate_event_name(),
19
+ --- When a player repeatedly mines protected entities
20
+ -- @event on_repeat_violation
21
+ -- @tparam number player_index the player index of the player who got mined the entities
22
+ -- @tparam LuaEntity entity the last entity which was mined
23
+ on_repeat_violation = script.generate_event_name(),
24
+ },
25
+ }
26
+
27
+ -- Convert config tables into lookup tables
28
+ for _, config_key in ipairs{ "always_protected_names", "always_protected_types", "always_trigger_repeat_names", "always_trigger_repeat_types" } do
29
+ local tbl = config[config_key]
30
+ for key, value in ipairs(tbl) do
31
+ tbl[key] = nil
32
+ tbl[value] = true
33
+ end
34
+ end
35
+
36
+ local Roles = require("modules/exp_roles")
37
+
38
+ ----- Storage Variables -----
39
+ --- Variables stored in the global table
40
+
41
+ local protected_entities = {} -- All entities which are protected
42
+ local protected_areas = {} -- All areas which are protected
43
+ local repeats = {} -- Stores repeat removals by players
44
+
45
+ Storage.register({
46
+ protected_entities = protected_entities,
47
+ protected_areas = protected_areas,
48
+ repeats = repeats,
49
+ }, function(tbl)
50
+ protected_entities = tbl.protected_entities
51
+ protected_areas = tbl.protected_areas
52
+ repeats = tbl.repeats
53
+ end)
54
+
55
+ ----- Local Functions -----
56
+ --- Functions used internally to search and add to the protected array
57
+
58
+ --- Get the key used in protected_entities
59
+ local function get_entity_key(entity)
60
+ return string.format("%i,%i", math.floor(entity.position.x), math.floor(entity.position.y))
61
+ end
62
+
63
+ --- Get the key used in protected_areas
64
+ local function get_area_key(area)
65
+ return string.format("%i,%i", math.floor(area.left_top.x), math.floor(area.left_top.y))
66
+ end
67
+
68
+ --- Check if an entity is always protected
69
+ local function check_always_protected(entity)
70
+ return config.always_protected_names[entity.name] or config.always_protected_types[entity.type] or false
71
+ end
72
+
73
+ --- Check if an entity always triggers repeat protection
74
+ local function check_always_trigger_repeat(entity)
75
+ return config.always_trigger_repeat_names[entity.name] or config.always_trigger_repeat_types[entity.type] or false
76
+ end
77
+
78
+ ----- Public Functions -----
79
+ --- Functions used to add and remove protected entities
80
+
81
+ --- Add an entity to the protected list
82
+ function EntityProtection.add_entity(entity)
83
+ local entities = protected_entities[entity.surface.index]
84
+ if not entities then
85
+ entities = {}
86
+ protected_entities[entity.surface.index] = entities
87
+ end
88
+ entities[get_entity_key(entity)] = entity
89
+ end
90
+
91
+ --- Remove an entity from the protected list
92
+ function EntityProtection.remove_entity(entity)
93
+ local entities = protected_entities[entity.surface.index]
94
+ if not entities then return end
95
+ entities[get_entity_key(entity)] = nil
96
+ end
97
+
98
+ --- Get all protected entities on a surface
99
+ function EntityProtection.get_entities(surface)
100
+ return protected_entities[surface.index] or {}
101
+ end
102
+
103
+ --- Check if an entity is protected
104
+ function EntityProtection.is_entity_protected(entity)
105
+ if check_always_protected(entity) then return true end
106
+ local entities = protected_entities[entity.surface.index]
107
+ if not entities then return false end
108
+ return entities[get_entity_key(entity)] == entity
109
+ end
110
+
111
+ --- Add an area to the protected list
112
+ function EntityProtection.add_area(surface, area)
113
+ local areas = protected_areas[surface.index]
114
+ if not areas then
115
+ areas = {}
116
+ protected_areas[surface.index] = areas
117
+ end
118
+ areas[get_area_key(area)] = area
119
+ end
120
+
121
+ --- Remove an area from the protected list
122
+ function EntityProtection.remove_area(surface, area)
123
+ local areas = protected_areas[surface.index]
124
+ if not areas then return end
125
+ areas[get_area_key(area)] = nil
126
+ end
127
+
128
+ --- Get all protected areas on a surface
129
+ function EntityProtection.get_areas(surface)
130
+ return protected_areas[surface.index] or {}
131
+ end
132
+
133
+ --- Check if an entity is protected
134
+ function EntityProtection.is_position_protected(surface, position)
135
+ local areas = protected_areas[surface.index]
136
+ if not areas then return false end
137
+ for _, area in pairs(areas) do
138
+ if area.left_top.x <= position.x and area.left_top.y <= position.y
139
+ and area.right_bottom.x >= position.x and area.right_bottom.y >= position.y
140
+ then
141
+ return true
142
+ end
143
+ end
144
+
145
+ return false
146
+ end
147
+
148
+ ----- Events -----
149
+ --- All events registered by this module
150
+
151
+ --- Raise events for protected entities
152
+ Event.add(defines.events.on_pre_player_mined_item, function(event)
153
+ local entity = event.entity
154
+ local player = game.players[event.player_index]
155
+ -- Check if the player should be ignored
156
+ if config.ignore_admins and player.admin then return end
157
+ if entity.last_user == nil or entity.last_user.index == player.index then return end
158
+ if config.ignore_permission and Roles.player_has_permission(player, config.ignore_permission) then return end
159
+
160
+ -- Check if the entity is protected
161
+ if EntityProtection.is_entity_protected(entity)
162
+ or EntityProtection.is_position_protected(entity.surface, entity.position)
163
+ then
164
+ -- Update repeats
165
+ local player_repeats = repeats[player.name]
166
+ if not player_repeats then
167
+ player_repeats = { last = game.tick, count = 0 }
168
+ repeats[player.name] = player_repeats
169
+ end
170
+ player_repeats.last = game.tick
171
+ player_repeats.count = player_repeats.count + 1
172
+ -- Send events
173
+ event.name = EntityProtection.events.on_player_mined_protected
174
+ script.raise_event(EntityProtection.events.on_player_mined_protected, event)
175
+ if check_always_trigger_repeat(entity) or player_repeats.count >= config.repeat_count then
176
+ player_repeats.count = 0 -- Reset to avoid spamming of events
177
+ event.name = EntityProtection.events.on_repeat_violation
178
+ script.raise_event(EntityProtection.events.on_repeat_violation, event)
179
+ end
180
+ end
181
+ end)
182
+
183
+ --- Remove old repeats
184
+ Event.on_nth_tick(config.refresh_rate, function()
185
+ local old = game.tick - config.repeat_lifetime
186
+ for player_name, player_repeats in pairs(repeats) do
187
+ if player_repeats.last <= old then
188
+ repeats[player_name] = nil
189
+ end
190
+ end
191
+ end)
192
+
193
+ --- When an entity is removed remove it from the protection list
194
+ local function event_remove_entity(event)
195
+ EntityProtection.remove_entity(event.entity)
196
+ end
197
+
198
+ Event.add(defines.events.on_space_platform_pre_mined, event_remove_entity)
199
+ Event.add(defines.events.on_pre_player_mined_item, event_remove_entity)
200
+ Event.add(defines.events.on_robot_pre_mined, event_remove_entity)
201
+ Event.add(defines.events.on_entity_died, event_remove_entity)
202
+ Event.add(defines.events.script_raised_destroy, event_remove_entity)
203
+
204
+ return EntityProtection