Добавлены все обновления от сообщества, вплоть до #148

This commit is contained in:
2024-09-12 14:28:43 +03:00
parent 98159766c4
commit 487a0e6e16
8841 changed files with 23077 additions and 20175 deletions

78
Teleporters/changelog.txt Normal file
View File

@@ -0,0 +1,78 @@
---------------------------------------------------------------------------------------------------
Version: 1.0.5
Date: 2021-02-24
Changes:
- Refined graphics (entity, icon).
- New smoke animation.
- New mod icon.
- New technology icon.
- (changes by snouz)
---------------------------------------------------------------------------------------------------
Version: 1.0.4
Date: 2021-02-23
Changes:
- Fix sorting again (merge error from last fix).
---------------------------------------------------------------------------------------------------
Version: 1.0.3
Date: 2021-02-21
Changes:
- Fix crash due to deleting surface with teleporters on them.
---------------------------------------------------------------------------------------------------
Version: 1.0.2
Date: 2021-02-17
Changes:
- Fix sorting order of non-recent teleporters.
---------------------------------------------------------------------------------------------------
Version: 1.0.1
Date: 2021-02-14
Changes:
- Recently used teleporters will sort above all others.
---------------------------------------------------------------------------------------------------
Version: 1.0.0
Date: 2020-11-25
Changes:
- 1.1 update.
---------------------------------------------------------------------------------------------------
Version: 0.2.3
Date: 2020-05-25
Changes:
- Fixes for GUI update.
---------------------------------------------------------------------------------------------------
Version: 0.2.2
Date: 2020-03-18
Changes:
- Fix compatibility with new Character GUI.
---------------------------------------------------------------------------------------------------
Version: 0.2.1
Date: 2020-02-01
Changes:
- Fix icon mipmaps error on startup.
---------------------------------------------------------------------------------------------------
Version: 0.2.0
Date: 2020-01-12
Changes:
- 0.18 update.
---------------------------------------------------------------------------------------------------
Version: 0.1.14
Date: 2019-07
Changes:
- Fixed script error naming teleporters 'help' or 'valid' etc.
- Rename teleporter GUI will no longer show when building a new teleporter.
---------------------------------------------------------------------------------------------------
Version: 0.1.11
Date: 2019-07
Changes:
- Fixed script error due to removed 'want_elipsis' LuaStyle.
- The teleporter list GUI is now sorted alphabetically.
---------------------------------------------------------------------------------------------------
Version: 0.1.10
Date: 2019-06
Changes:
- Fixed script error when entering '[' or other special characters into the search.
---------------------------------------------------------------------------------------------------
Version: 0.1.9
Date: 2019-05
Changes:
- Added changelog.
- Fix compatibility with Factorio version 0.17.35+.
- Slight optimization of teleporter triggering logic.

2
Teleporters/control.lua Normal file
View File

@@ -0,0 +1,2 @@
local handler = require("event_handler")
handler.add_lib(require("script/teleporters"))

View File

@@ -0,0 +1,29 @@
local tp = data.raw["land-mine"]["teleporter"]
tp.trigger_radius = 2
tp.collision_box = {{-2, -2},{2, 2}}
tp.selection_box = {{-2, -2},{2, 2}}
tp.picture_safe.filename = "__Teleporters__/data/entities/teleporters/hr-teleporter-closed.png"
tp.picture_safe.width = 160
tp.picture_safe.height = 160
tp.picture_safe.hr_version.scale = 1
tp.picture_set.filename = "__Teleporters__/data/entities/teleporters/hr-teleporter-open.png"
tp.picture_set.width = 160
tp.picture_set.height = 160
tp.picture_set.hr_version.scale = 1
tp.picture_set_enemy.filename = "__Teleporters__/data/entities/teleporters/hr-teleporter-open.png"
tp.picture_set_enemy.width = 160
tp.picture_set_enemy.height = 160
tp.picture_set_enemy.hr_version.scale = 1

3
Teleporters/data.lua Normal file
View File

@@ -0,0 +1,3 @@
util = require "data/tf_util/tf_util"
names = require("shared")
require "data/entities/entities"

View File

@@ -0,0 +1,2 @@
local require = function(name) return require("data/entities/"..name) end
require("teleporters/teleporters")

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

View File

@@ -0,0 +1,194 @@
local path = util.path("data/entities/teleporters/")
local teleporter = util.copy(data.raw["land-mine"]["land-mine"])
local names = require("shared")
local name = names.entities.teleporter
local localised_name = {name}
teleporter.name = name
teleporter.localised_name = localised_name
teleporter.trigger_radius = 1
teleporter.timeout = 5 * 60
teleporter.max_health = 200
--teleporter.shooting_cursor_size = 0
teleporter.dying_explosion = nil
teleporter.action =
{
type = "direct",
action_delivery =
{
type = "instant",
target_effects =
{
{
type = "create-sticker",
sticker = names.entities.teleporter_sticker,
trigger_created_entity = true
}
}
}
}
teleporter.force_die_on_attack = false
teleporter.trigger_force = "all"
--teleporter.create_ghost_on_death = false
teleporter.order = name
teleporter.picture_safe =
{
filename = path.."teleporter-closed.png",
priority = "medium",
width = 80,
height = 80,
hr_version = {
filename = path.."hr-teleporter-closed.png",
priority = "medium",
width = 160,
height = 160,
scale = 0.5,
}
}
teleporter.picture_set =
{
filename = path.."teleporter-open.png",
priority = "medium",
width = 80,
height = 80,
hr_version = {
filename = path.."hr-teleporter-open.png",
priority = "medium",
width = 160,
height = 160,
scale = 0.5,
}
}
teleporter.picture_set_enemy =
{
filename = path.."teleporter-open.png",
priority = "medium",
width = 80,
height = 80,
hr_version = {
filename = path.."hr-teleporter-open.png",
priority = "medium",
width = 160,
height = 160,
scale = 0.5,
}
}
teleporter.minable = {result = name, mining_time = 3}
teleporter.flags =
{
--"not-blueprintable",
"placeable-neutral",
"placeable-player",
"player-creation",
"not-upgradable"
}
teleporter.collision_box = {{-1, -1},{1, 1}}
teleporter.selection_box = {{-1, -1},{1, 1}}
teleporter.map_color = {r = 0.5, g = 1, b = 1}
local sticker =
{
type = "sticker",
name = names.entities.teleporter_sticker,
--icon = "__base__/graphics/icons/slowdown-sticker.png",
flags = {},
animation = util.empty_sprite(),
duration_in_ticks = 1,
--target_movement_modifier = 1
}
local teleporter_item = util.copy(data.raw.item["land-mine"])
teleporter_item.name = name
teleporter_item.localised_name = localised_name
teleporter_item.place_result = name
teleporter_item.icon = path.."teleporter-icon.png"
teleporter_item.icon_size = 64
teleporter_item.icon_mipmaps = 0
teleporter_item.subgroup = "circuit-network"
local fire = require("data/tf_util/tf_fire_util")
local teleporter_explosion = util.copy(data.raw.explosion.explosion)
teleporter_explosion.name = "teleporter-explosion"
teleporter_explosion.animations = fire.create_fire_pictures({scale = 1, animation_speed = 0.3})
teleporter_explosion.sound =
{
filename = path.."teleporter-explosion.ogg",
volume = 0.45
}
local teleporter_explosion_2 = util.copy(teleporter_explosion)
teleporter_explosion_2.name = "teleporter-explosion-no-sound"
teleporter_explosion_2.sound = nil
local recipe = {
type = "recipe",
name = name,
localised_name = localised_name,
enabled = false,
ingredients =
{
{"steel-plate", 45},
{"advanced-circuit", 20},
{"battery", 25},
},
energy_required = 5,
result = name
}
local technology =
{
type = "technology",
name = name,
localised_name = localised_name,
localised_description = "",
icon_size = 256,
icon = path.."teleporter-technology.png",
effects =
{
{
type = "unlock-recipe",
recipe = name
}
},
unit =
{
count = 500,
ingredients = {
{"automation-science-pack", 1},
{"logistic-science-pack", 1},
{"chemical-science-pack", 1},
},
time = 30
},
prerequisites = {"advanced-electronics", "battery"},
order = "y-a"
}
local teleporter_flying_text = util.copy(data.raw["flying-text"]["tutorial-flying-text"])
teleporter_flying_text.name = "teleporter-flying-text"
local hotkey_name = require"shared".hotkeys.focus_search
local hotkey =
{
type = "custom-input",
name = hotkey_name,
linked_game_control = "focus-search",
key_sequence = "Control + F"
}
data:extend
{
teleporter,
teleporter_item,
teleporter_explosion,
teleporter_explosion_2,
recipe,
technology,
teleporter_flying_text,
hotkey,
sticker
}

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 126 B

View File

@@ -0,0 +1,324 @@
local rename_recipe = function(old, new)
local recipes = data.raw.recipe
for k, recipe in pairs (recipes) do
if recipe.normal then
for k, v in pairs(recipe.normal) do
recipe[k] = v
end
recipe.normal = nil
recipe.expensive = nil
end
for k, ingredient in pairs (recipe.ingredients) do
if ingredient.name and ingredient.name == old then
ingredient.name = new
end
if ingredient[1] and ingredient[1] == old then
ingredient[1] = new
end
end
if recipe.result and recipe.result == old then
recipe.result = new
end
for k, product in pairs (recipe.products or {}) do
if product.name and product.name == old then
product.name = new
end
if product[1] and product[1] == old then
product[1] = new
end
end
-- Will have to handle technologies.. so lets do it only when nescessary
--if recipe.name == old then
-- recipe.name = new
-- recipe.localised_name = new
-- recipes[new] = recipe
-- recipes[old] = nil
--end
end
end
local rename_item = function(old, new)
local items = data.raw.item
for k, item in pairs (items) do
if item.place_result and item.place_result == old then
item.place_result = new
end
if item.name == old then
item.name = new
item.localised_name = new
items[new] = item
items[old] = nil
rename_recipe(old, new)
end
end
end
local rename_recipe = function(old, new)
local recipes = data.raw.recipe
for k, recipe in pairs (recipes) do
if recipe.normal then
for k, v in pairs(recipe.normal) do
recipe[k] = v
end
recipe.normal = nil
recipe.expensive = nil
end
for k, ingredient in pairs (recipe.ingredients) do
if ingredient.name and ingredient.name == old then
ingredient.name = new
end
if ingredient[1] and ingredient[1] == old then
ingredient[1] = new
end
end
if recipe.result and recipe.result == old then
recipe.result = new
end
for k, product in pairs (recipe.products or {}) do
if product.name and product.name == old then
product.name = new
end
if product[1] and product[1] == old then
product[1] = new
end
end
-- Will have to handle technologies.. so lets do it only when nescessary
--if recipe.name == old then
-- recipe.name = new
-- recipe.localised_name = new
-- recipes[new] = recipe
-- recipes[old] = nil
--end
end
end
local remove_from_recipe = function(recipe, name)
--log(name)
if recipe.normal then
--Screw this half-assed system
for k, v in pairs (recipe.normal) do
recipe[k] = v
end
recipe.normal = nil
recipe.expensive = nil
end
local result = recipe.result
if result == name then
return
end
local ingredients = recipe.ingredients
if ingredients then
for i = #ingredients, 1, -1 do
if (ingredients[i].name or ingredients[i][1]) == name then
table.remove(ingredients, i)
end
end
if #ingredients == 0 then
return
end
end
local products = recipe.products
if products then
for i = #products, 1, -1 do
if (products[i].name or products[i][1]) == name then
table.remove(products, i)
end
end
if #products == 0 then
return
end
end
if recipe.main_product and recipe.main_product == name then
recipe.main_product = nil
end
return recipe
end
local remove_technology = function(name)
local technologies = data.raw.technology
for k, tech in pairs (technologies) do
local req = tech.prerequisites
if req then
for i = #req, 1, -1 do
if req[i] == name then
table.remove(req, i)
end
end
if #req == 0 then
tech.prerequisites = nil
end
end
end
technologies[name] = nil
end
local remove_item_from_technologies = function(name)
local technologies = data.raw.technology
for k, tech in pairs (technologies) do
local packs = tech.unit.ingredients
for i = #packs, 1, -1 do
if (packs[i].name or packs[i][1]) == name then
table.remove(packs, i)
end
end
if #packs == 0 then
remove_technology(tech.name)
end
end
end
local remove_recipe_from_technologies = function(name)
--log("Removing recipe from technologies: "..name)
local technologies = data.raw.technology
for k, technology in pairs (technologies) do
local effects = technology.effects
if effects then
--log(technology.name.." = "..#effects)
for i = #effects, 1, -1 do
--log((effects[i].recipe or "nil").. " == "..name)
if (effects[i].recipe == name) then
--log("Removed from: "..k)
table.remove(effects, i)
end
end
if #effects == 0 then
remove_technology(technology.name)
end
end
end
end
local remove_item_from_recipes = function(name)
if type(name) ~= "string" then error("I EXPECT A STRING") end
--log("Removing item from recipes: "..name)
local recipes = data.raw.recipe
for k, recipe in pairs (recipes) do
local result = remove_from_recipe(recipe, name)
if not result then
remove_recipe_from_technologies(recipe.name)
recipes[k] = nil
end
end
end
local remove_from_items = function(name)
if type(name) ~= "string" then error("I EXPECT A STRING") end
local items = data.raw.item
for k, item in pairs (items) do
if item.place_result == name then
remove_item_from_recipes(item.name)
items[k] = nil
return
end
if item.rocket_launch_product == name then
item.rocket_launch_product = nil
end
if item.rocket_launch_products then
util.remove_from_list(item.rocket_launch_products, name)
end
end
local items = data.raw["item-with-entity-data"]
for k, item in pairs (items) do
if item.place_result == name then
remove_item_from_recipes(item.name)
items[k] = nil
return
end
if item.rocket_launch_product == name then
item.rocket_launch_product = nil
end
if item.rocket_launch_products then
util.remove_from_list(item.rocket_launch_products, name)
end
end
end
local find_mention
find_mention = function(table, name)
for k, v in pairs (table) do
if type(v) == "table" then
find_mention(v, name)
elseif k == name or ((type(v) == "string") and (v == name)) then
return true
end
end
end
local remove_from_achievements = function(name)
for type_name, type in pairs (data.raw) do
if string.find(type_name, "achievement") then
for k, achievement in pairs (type) do
if find_mention(achievement, name) then
type[k] = nil
end
end
end
end
end
local remove_entity_prototype = function(ent)
if not ent then return end
--So, if we actually delete the prototype, we get some error about traversing old prototypes for migrations or some BS... so we just nuke all items and hide them
--log(ent.name)
remove_from_items(ent.name)
remove_from_achievements(ent.name)
ent.minable = nil
ent.order = "Z-DELETED"
ent.autoplace = nil
end
local remove_from_minable = function(name)
for k, type in pairs (data.raw) do
for j, v in pairs (type) do
if v.minable and v.minable.result == name then
v.minable = nil
end
end
end
end
local remove_item_prototype = function(item)
if not item then log("Well item to remove was nil anyway so great job") return end
remove_item_from_recipes(item.name)
remove_item_from_technologies(item.name)
remove_from_minable(item.name)
data.raw.item[item.name] = nil
item = nil
end
remove_technology_effect_type = function(dict)
for k, tech in pairs (data.raw.technology) do
local effects = tech.effects
if effects then
for i = #effects, 1, -1 do
if dict[effects[i].type] then
table.remove(effects, i)
end
end
if #effects == 0 then
remove_technology(tech.name)
end
end
end
end
local lib = {}
lib.rename_item = rename_item
lib.rename_recipe = rename_recipe
lib.remove_from_achievements = remove_from_achievements
lib.remove_from_items = remove_from_items
lib.remove_item_from_recipes = remove_item_from_recipes
lib.remove_item_from_technologies = remove_item_from_technologies
lib.remove_recipe_from_technologies = remove_recipe_from_technologies
lib.remove_entity_prototype = remove_entity_prototype
lib.remove_item_prototype = remove_item_prototype
lib.remove_technology_effect_type = remove_technology_effect_type
lib.remove_technology = remove_technology
return lib

View File

@@ -0,0 +1,48 @@
--Copy paste from base game
local fire_util = {}
local path = util.path("data/entities/teleporters/")
fire_util.create_fire_pictures = function(opts)
local opts = opts or {}
local fire_blend_mode = opts.blend_mode or "additive"
local fire_animation_speed = opts.animation_speed or 0.5
local fire_scale = opts.scale or 1
local fire_tint = opts.tint or {r=1,g=1,b=1,a=1}
local fire_flags = opts.flags or { "compressed" }
return
{
{
filename = path.."teleporter-explosion.png",
draw_as_glow = true,
priority = "high",
line_length = 6,
width = 44,
height = 90,
frame_count = 24,
shift = util.by_pixel(-1,6),
blend_mode = fire_blend_mode,
animation_speed = fire_animation_speed,
scale = fire_scale,
tint = fire_tint,
flags = fire_flags,
hr_version =
{
filename = path.."hr-teleporter-explosion.png",
draw_as_glow = true,
priority = "high",
line_length = 6,
width = 88,
height = 178,
frame_count = 24,
shift = util.by_pixel(-1,6),
blend_mode = fire_blend_mode,
animation_speed = fire_animation_speed,
scale = fire_scale / 2,
tint = fire_tint,
flags = fire_flags,
}
},
}
end
return fire_util

View File

@@ -0,0 +1,254 @@
local util = require("util")
local is_sprite_def = function(array)
return array.width and array.height and (array.filename or array.stripes or array.filenames)
end
util.is_sprite_def = is_sprite_def
local recursive_hack_scale
recursive_hack_scale = function(array, scale)
for k, v in pairs (array) do
if type(v) == "table" then
if is_sprite_def(v) then
v.scale = (v.scale or 1) * scale
if v.shift then
v.shift[1], v.shift[2] = v.shift[1] * scale, v.shift[2] * scale
end
end
if v.source_offset then
v.source_offset[1] = v.source_offset[1] * scale
v.source_offset[2] = v.source_offset[2] * scale
end
if v.projectile_center then
v.projectile_center[1] = v.projectile_center[1] * scale
v.projectile_center[2] = v.projectile_center[2] * scale
end
if v.projectile_creation_distance then
v.projectile_creation_distance = v.projectile_creation_distance * scale
end
recursive_hack_scale(v, scale)
end
end
end
util.recursive_hack_scale = recursive_hack_scale
local recursive_hack_animation_speed
recursive_hack_animation_speed = function(array, scale)
for k, v in pairs (array) do
if type(v) == "table" then
if is_sprite_def(v) then
v.animation_speed = v.animation_speed * scale
end
recursive_hack_animation_speed(v, scale)
end
end
end
util.recursive_hack_animation_speed = recursive_hack_animation_speed
local recursive_hack_tint
recursive_hack_tint = function(array, tint)
for k, v in pairs (array) do
if type(v) == "table" then
if is_sprite_def(v) then
v.tint = tint
end
recursive_hack_tint(v, tint)
end
end
end
util.recursive_hack_tint = recursive_hack_tint
local recursive_hack_make_hr
recursive_hack_make_hr = function(prototype)
for k, v in pairs (prototype) do
if type(v) == "table" then
if is_sprite_def(v) and v.hr_version then
prototype[k] = v.hr_version
--v.scale = v.scale * 0.5
v.hr_version = nil
end
recursive_hack_make_hr(v)
end
end
end
util.recursive_hack_make_hr = recursive_hack_make_hr
util.scale_box = function(box, scale)
box[1][1] = box[1][1] * scale
box[1][2] = box[1][2] * scale
box[2][1] = box[2][1] * scale
box[2][2] = box[2][2] * scale
return box
end
util.scale_boxes = function(prototype, scale)
for k, v in pairs {"collision_box", "selection_box"} do
local box = prototype[v]
if box then
local width = (box[2][1] - box[1][1]) * (scale / 2)
local height = (box[2][2] - box[1][2]) * (scale / 2)
local x = (box[1][1] + box[2][1]) / 2
local y = (box[1][2] + box[2][2]) / 2
box[1][1], box[2][1] = x - width, x + width
box[1][2], box[2][2] = y - height, y + height
end
end
end
util.remove_flag = function(prototype, flag)
if not prototype.flags then return end
for k, v in pairs (prototype.flags) do
if v == flag then
table.remove(prototype.flags, k)
break
end
end
end
util.add_flag = function(prototype, flag)
if not prototype.flags then return end
table.insert(prototype.flags, flag)
end
util.base_player = function()
local player = util.table.deepcopy(data.raw.player.player or error("Wat man cmon why"))
player.ticks_to_keep_gun = SU(600)
player.ticks_to_keep_aiming_direction = SU(100)
player.ticks_to_stay_in_combat = SU(600)
util.remove_flag(player, "not-flammable")
return player
end
util.path = function(str)
return "__Teleporters__/" .. str
end
util.empty_sound = function()
return
{
filename = util.path("data/tf_util/empty-sound.ogg"),
volume = 0
}
end
util.empty_sprite = function()
return
{
filename = util.path("data/tf_util/empty-sprite.png"),
height = 1,
width = 1,
frame_count = 1
}
end
util.damage_type = function(name)
if not data.raw["damage-type"][name] then
data:extend{{type = "damage-type", name = name, localised_name = name}}
end
return name
end
util.ammo_category = function(name)
if not data.raw["ammo-category"][name] then
data:extend{{type = "ammo-category", name = name, localised_name = name}}
end
return name
end
util.base_gun = function(name)
return
{
name = name,
localised_name = name,
type = "gun",
stack_size = 1,
flags = {}
}
end
util.base_ammo = function(name)
return
{
name = name,
localised_name = name,
type = "ammo",
stack_size = 1,
magazine_size = 1,
flags = {}
}
end
local base_speed = 0.25
util.speed = function(multiplier)
return multiplier * SD(base_speed)
end
util.remove_from_list = function(list, name)
local remove = table.remove
for i = #list, 1, -1 do
if list[i] == name then
remove(list, i)
end
end
end
local recursive_hack_something
recursive_hack_something = function(prototype, key, value)
for k, v in pairs (prototype) do
if type(v) == "table" then
recursive_hack_something(v, key, value)
end
end
prototype[key] = value
end
util.recursive_hack_something = recursive_hack_something
local recursive_hack_blend_mode
recursive_hack_blend_mode = function(prototype, value)
for k, v in pairs (prototype) do
if type(v) == "table" then
if util.is_sprite_def(v) then
v.blend_mode = value
end
recursive_hack_blend_mode(v, value)
end
end
end
util.copy = util.table.deepcopy
util.prototype = require("data/tf_util/prototype_util")
util.flying_unit_collision_mask = function()
return {"not-colliding-with-itself", "layer-15"}
end
util.ground_unit_collision_mask = function()
return {"not-colliding-with-itself", "player-layer", "train-layer"}
end
util.projectile_collision_mask = function()
return {"layer-15", "player-layer", "train-layer"}
end
util.shift_box = function(box, shift)
local left_top = box[1]
local right_bottom = box[2]
left_top[1] = left_top[1] + shift[1]
left_top[2] = left_top[2] + shift[2]
right_bottom[1] = right_bottom[1] + shift[1]
right_bottom[2] = right_bottom[2] + shift[2]
return box
end
util.shift_layer = function(layer, shift)
layer.shift = layer.shift or {0,0}
layer.shift[1] = layer.shift[1] + shift[1]
layer.shift[2] = layer.shift[2] + shift[2]
return layer
end
return util

BIN
Teleporters/gallery/01.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

BIN
Teleporters/gallery/02.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

BIN
Teleporters/gallery/03.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

11
Teleporters/info.json Normal file
View File

@@ -0,0 +1,11 @@
{
"name": "Teleporters",
"version": "1.0.5",
"title": "Teleporters",
"author": "Klonan",
"contact": "",
"homepage": "",
"description": "Adds Teleporters",
"dependencies": ["base >= 1.1.0"],
"factorio_version": "1.1"
}

67
Teleporters/license.txt Normal file
View File

@@ -0,0 +1,67 @@
GNU LESSER GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed.
This version of the GNU Lesser General Public License incorporates the terms and conditions of version 3 of the GNU General Public License, supplemented by the additional permissions listed below.
0. Additional Definitions.
As used herein, “this License” refers to version 3 of the GNU Lesser General Public License, and the “GNU GPL” refers to version 3 of the GNU General Public License.
“The Library” refers to a covered work governed by this License, other than an Application or a Combined Work as defined below.
An “Application” is any work that makes use of an interface provided by the Library, but which is not otherwise based on the Library. Defining a subclass of a class defined by the Library is deemed a mode of using an interface provided by the Library.
A “Combined Work” is a work produced by combining or linking an Application with the Library. The particular version of the Library with which the Combined Work was made is also called the “Linked Version”.
The “Minimal Corresponding Source” for a Combined Work means the Corresponding Source for the Combined Work, excluding any source code for portions of the Combined Work that, considered in isolation, are based on the Application, and not on the Linked Version.
The “Corresponding Application Code” for a Combined Work means the object code and/or source code for the Application, including any data and utility programs needed for reproducing the Combined Work from the Application, but excluding the System Libraries of the Combined Work.
1. Exception to Section 3 of the GNU GPL.
You may convey a covered work under sections 3 and 4 of this License without being bound by section 3 of the GNU GPL.
2. Conveying Modified Versions.
If you modify a copy of the Library, and, in your modifications, a facility refers to a function or data to be supplied by an Application that uses the facility (other than as an argument passed when the facility is invoked), then you may convey a copy of the modified version:
a) under this License, provided that you make a good faith effort to ensure that, in the event an Application does not supply the function or data, the facility still operates, and performs whatever part of its purpose remains meaningful, or
b) under the GNU GPL, with none of the additional permissions of this License applicable to that copy.
3. Object Code Incorporating Material from Library Header Files.
The object code form of an Application may incorporate material from a header file that is part of the Library. You may convey such object code under terms of your choice, provided that, if the incorporated material is not limited to numerical parameters, data structure layouts and accessors, or small macros, inline functions and templates (ten or fewer lines in length), you do both of the following:
a) Give prominent notice with each copy of the object code that the Library is used in it and that the Library and its use are covered by this License.
b) Accompany the object code with a copy of the GNU GPL and this license document.
4. Combined Works.
You may convey a Combined Work under terms of your choice that, taken together, effectively do not restrict modification of the portions of the Library contained in the Combined Work and reverse engineering for debugging such modifications, if you also do each of the following:
a) Give prominent notice with each copy of the Combined Work that the Library is used in it and that the Library and its use are covered by this License.
b) Accompany the Combined Work with a copy of the GNU GPL and this license document.
c) For a Combined Work that displays copyright notices during execution, include the copyright notice for the Library among these notices, as well as a reference directing the user to the copies of the GNU GPL and this license document.
d) Do one of the following:
0) Convey the Minimal Corresponding Source under the terms of this License, and the Corresponding Application Code in a form suitable for, and under terms that permit, the user to recombine or relink the Application with a modified version of the Linked Version to produce a modified Combined Work, in the manner specified by section 6 of the GNU GPL for conveying Corresponding Source.
1) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (a) uses at run time a copy of the Library already present on the user's computer system, and (b) will operate properly with a modified version of the Library that is interface-compatible with the Linked Version.
e) Provide Installation Information, but only if you would otherwise be required to provide such information under section 6 of the GNU GPL, and only to the extent that such information is necessary to install and execute a modified version of the Combined Work produced by recombining or relinking the Application with a modified version of the Linked Version. (If you use option 4d0, the Installation Information must accompany the Minimal Corresponding Source and Corresponding Application Code. If you use option 4d1, you must provide the Installation Information in the manner specified by section 6 of the GNU GPL for conveying Corresponding Source.)
5. Combined Libraries.
You may place library facilities that are a work based on the Library side by side in a single library together with other library facilities that are not Applications and are not covered by this License, and convey such a combined library under terms of your choice, if you do both of the following:
a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities, conveyed under the terms of this License.
b) Give prominent notice with the combined library that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work.
6. Revised Versions of the GNU Lesser General Public License.
The Free Software Foundation may publish revised and/or new versions of the GNU Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the Library as you received it specifies that a certain numbered version of the GNU Lesser General Public License “or any later version” applies to it, you have the option of following the terms and conditions either of that published version or of any later version published by the Free Software Foundation. If the Library as you received it does not specify a version number of the GNU Lesser General Public License, you may choose any version of the GNU Lesser General Public License ever published by the Free Software Foundation.
If the Library as you received it specifies that a proxy can decide whether future versions of the GNU Lesser General Public License shall apply, that proxy's public statement of acceptance of any version is permanent authorization for you to choose that version for the Library.

View File

@@ -0,0 +1,7 @@
teleporter=Teleporter
no-teleporters=Da ist kein Teleporter um dich zu einem anderen zu teleportieren.
name-already-taken=Name bereits vergeben.
name-teleporter=Teleporter Name
teleporter-network=Teleporter Netzwerk
search=__CONTROL__focus-search__

View File

@@ -0,0 +1,8 @@
teleporter=Teleporter
no-teleporters=No teleporters to teleport to.
name-already-taken=Name already taken.
name-teleporter=Name teleporter
teleporter-network=Teleporter network
cant-add-tag=You can not add a chart tag with the teleporter icon.
cant-change-icon=You can not modify a teleporter chart tags icon.
search=__CONTROL__focus-search__

View File

@@ -0,0 +1,8 @@
teleporter=Телепортер
no-teleporters=Нет телепортов для телепортации.
name-already-taken=Имя уже занято.
name-teleporter=Имя телепорта
teleporter-network=Сеть телепортов
cant-add-tag=Вы не можете добавить тег диаграммы со значком телепорта.
cant-change-icon=Вы не можете изменить значок тегов диаграммы телепорта.
search=__CONTROL__focus-search__

13
Teleporters/readme.md Normal file
View File

@@ -0,0 +1,13 @@
## Teleporters
![](data/entities/teleporters/teleporter-technology.png)
--------------------------------------
This mod adds teleporters you can stand on, and teleport around the world and between surfaces with.
![](gallery/02.png)
![](gallery/03.png)
![](gallery/01.png)

View File

@@ -0,0 +1,76 @@
local util = require("util")
local deregister_gui_internal
deregister_gui_internal = function(gui_element, data)
data[gui_element.index] = nil
for k, child in pairs (gui_element.children) do
deregister_gui_internal(child, data)
end
end
util.deregister_gui = function(gui_element, data)
local player_data = data[gui_element.player_index]
if not player_data then return end
deregister_gui_internal(gui_element, player_data)
end
util.register_gui = function(data, gui_element, param)
local player_data = data[gui_element.player_index]
if not player_data then
data[gui_element.player_index] = {}
player_data = data[gui_element.player_index]
end
player_data[gui_element.index] = param
end
util.gui_action_handler = function(event, data, functions)
error("don't actually use me")
if not data then error("Gui action handler data is nil") end
if not functions then error("Gui action handler functions is nil") end
local element = event.element
if not (element and element.valid) then return end
local player_data = data[event.player_index]
if not player_data then return end
local action = player_data[element.index]
if action then
functions[action.type](event, action)
return true
end
end
util.center = function(area)
return {x = (area.left_top.x + area.right_bottom.x) / 2, y = (area.left_top.y + area.right_bottom.y) / 2}
end
util.distance = function(p1, p2)
return (((p1.x - p2.x) ^ 2) + ((p1.y - p2.y) ^ 2)) ^ 0.5
end
util.radius = function(area)
return util.distance(area.right_bottom, area.left_top) / 2
end
util.clear_item = function(entity, item_name)
if not (entity and entity.valid and item_name) then return end
entity.remove_item{name = item_name, count = entity.get_item_count(item_name)}
end
util.copy = util.table.deepcopy
util.first_key = function(map)
local k, v = next(map)
return k
end
util.first_value = function(map)
local k, v = next(map)
return v
end
util.angle = function(position_1, position_2)
local d_x = (position_2[1] or position_2.x) - (position_1[1] or position_1.x)
local d_y = (position_2[2] or position_2.y) - (position_1[2] or position_1.y)
return math.atan2(d_y, d_x)
end
return util

View File

@@ -0,0 +1,812 @@
local util = require("script/script_util")
local names = require("shared")
local teleporter_name = names.entities.teleporter
local teleporter_sticker = names.entities.teleporter_sticker
local data =
{
networks = {},
rename_frames = {},
button_actions = {},
teleporter_map = {},
teleporter_frames = {},
player_linked_teleporter = {},
to_be_removed = {},
tag_map = {},
search_boxes = {},
recent = {}
}
local preview_size = 256
local debug_print = false
local print = function(string)
if not debug_print then return end
game.print(string)
log(string)
end
local create_flash = function(surface, position)
surface.create_entity{name = "teleporter-explosion", position = position}
for k = 1, 3 do
surface.create_entity{name = "teleporter-explosion-no-sound", position = position}
end
end
local clear_gui = function(frame)
if not (frame and frame.valid) then return end
util.deregister_gui(frame, data.button_actions)
frame.clear()
end
local close_gui = function(frame)
if not (frame and frame.valid) then return end
util.deregister_gui(frame, data.button_actions)
frame.destroy()
end
local get_rename_frame = function(player)
local frame = data.rename_frames[player.index]
if frame and frame.valid then return frame end
data.rename_frames[player.index] = nil
end
local get_teleporter_frame = function(player)
local frame = data.teleporter_frames[player.index]
if frame and frame.valid then return frame end
data.teleporter_frames[player.index] = nil
end
local make_rename_frame = function(player, caption)
local teleporter_frame = get_teleporter_frame(player)
if teleporter_frame then
teleporter_frame.ignored_by_interaction = true
end
player.opened = nil
local force = player.force
local teleporters = data.networks[force.name]
local param = teleporters[caption]
local text = param.flying_text
local gui = player.gui.screen
local frame = gui.add{type = "frame", caption = {"gui-train-rename.title", caption}, direction = "horizontal"}
frame.auto_center = true
player.opened = frame
data.rename_frames[player.index] = frame
local textfield = frame.add{type = "textfield", text = caption}
textfield.style.horizontally_stretchable = true
textfield.focus()
textfield.select_all()
util.register_gui(data.button_actions, textfield, {type = "confirm_rename_textfield", textfield = textfield, flying_text = text, tag = param.tag})
local confirm = frame.add{type = "sprite-button", sprite = "utility/enter", style = "tool_button", tooltip = {"gui-train-rename.perform-change"}}
util.register_gui(data.button_actions, confirm, {type = "confirm_rename_button", textfield = textfield, flying_text = text, tag = param.tag})
end
local get_force_color = function(force)
local player = force.connected_players[1]
if player and player.valid then
return player.chat_color
end
return {r = 1, b = 1, g = 1}
end
local add_recent = function(player, teleporter)
local recent = data.recent[player.name]
if not recent then
recent = {}
data.recent[player.name] = recent
end
recent[teleporter.unit_number] = game.tick
if table_size(recent) >= 9 then
local min = math.huge
local index
for k, tick in pairs (recent) do
if tick < min then
min = tick
index = k
end
end
if index then recent[index] = nil end
end
end
local unlink_teleporter = function(player)
if player.character then player.character.active = true end
close_gui(get_teleporter_frame(player))
local source = data.player_linked_teleporter[player.index]
if source and source.valid then
source.active = true
add_recent(player, source)
end
data.player_linked_teleporter[player.index] = nil
end
local clear_teleporter_data = function(teleporter_data)
local flying_text = teleporter_data.flying_text
if flying_text and flying_text.valid then
flying_text.destroy()
end
local map_tag = teleporter_data.tag
if map_tag and map_tag.valid then
data.tag_map[map_tag.tag_number] = nil
map_tag.destroy()
end
end
local get_sort_function = function()
return
function(t, a, b) return a < b end
end
local make_teleporter_gui = function(player, source)
local location
local teleporter_frame = get_teleporter_frame(player)
if teleporter_frame then
location = teleporter_frame.location
data.teleporter_frames[player.index] = nil
print("Frame already exists")
close_gui(teleporter_frame)
player.opened = nil
end
print("Making new frame")
if not (source and source.valid and not data.to_be_removed[source.unit_number]) then
unlink_teleporter(player)
return
end
local force = source.force
local network = data.networks[force.name]
if not network then return end
local gui = player.gui.screen
local frame = gui.add{type = "frame", direction = "vertical", ignored_by_interaction = false}
if location then
frame.location = location
else
frame.auto_center = true
end
player.opened = frame
data.teleporter_frames[player.index] = frame
frame.ignored_by_interaction = false
local title_flow = frame.add{type = "flow", direction = "horizontal"}
title_flow.style.vertical_align = "center"
local title = title_flow.add{type = "label", style = "heading_1_label"}
title.drag_target = frame
local rename_button = title_flow.add{type = "sprite-button", sprite = "utility/rename_icon_small_white", style = "frame_action_button", visible = source.force == player.force}
local pusher = title_flow.add{type = "empty-widget", direction = "horizontal", style = "draggable_space_header"}
pusher.style.horizontally_stretchable = true
pusher.style.vertically_stretchable = true
pusher.drag_target = frame
local search_box = title_flow.add{type = "textfield", visible = false}
local search_button = title_flow.add{type = "sprite-button", style = "frame_action_button", sprite = "utility/search_white", tooltip = {"gui.search-with-focus", {"search"}}}
util.register_gui(data.button_actions, search_button, {type = "search_button", box = search_box})
data.search_boxes[player.index] = search_box
local inner = frame.add{type = "frame", style = "inside_deep_frame"}
local scroll = inner.add{type = "scroll-pane", direction = "vertical"}
scroll.style.maximal_height = (player.display_resolution.height / player.display_scale) * 0.8
local column_count = ((player.display_resolution.width / player.display_scale) * 0.6) / preview_size
local holding_table = scroll.add{type = "table", column_count = column_count}
util.register_gui(data.button_actions, search_box, {type = "search_text_changed", parent = holding_table})
holding_table.style.horizontal_spacing = 2
holding_table.style.vertical_spacing = 2
local any = false
--print(table_size(network))
local recent = data.recent[player.name] or {}
local sorted = {}
local i = 1
for name, teleporter in pairs (network) do
if teleporter.teleporter.valid then
sorted[i] = {name = name, teleporter = teleporter, unit_number = teleporter.teleporter.unit_number}
i = i + 1
else
clear_teleporter_data(teleporter)
end
end
table.sort(sorted, function(a, b)
if recent[a.unit_number] and recent[b.unit_number] then
return recent[a.unit_number] > recent[b.unit_number]
end
if recent[a.unit_number] then
return true
end
if recent[b.unit_number] then
return false
end
return a.name:lower() < b.name:lower()
end)
local sorted_network = {}
for k, sorted_data in pairs (sorted) do
sorted_network[sorted_data.name] = sorted_data.teleporter
end
local chart = player.force.chart
for name, teleporter in pairs(sorted_network) do
local teleporter_entity = teleporter.teleporter
if not (teleporter_entity.valid) then
clear_teleporter_data(teleporter)
elseif teleporter_entity == source then
title.caption = name
util.register_gui(data.button_actions, rename_button, {type = "rename_button", caption = name})
else
local position = teleporter_entity.position
local area = {{position.x - preview_size / 2, position.y - preview_size / 2}, {position.x + preview_size / 2, position.y + preview_size / 2}}
chart(teleporter_entity.surface, area)
local button = holding_table.add{type = "button", name = "_"..name}
button.style.height = preview_size + 32 + 8
button.style.width = preview_size + 8
button.style.left_padding = 0
button.style.right_padding = 0
local inner_flow = button.add{type = "flow", direction = "vertical", ignored_by_interaction = true}
inner_flow.style.vertically_stretchable = true
inner_flow.style.horizontally_stretchable = true
inner_flow.style.horizontal_align = "center"
local map = inner_flow.add
{
type = "minimap",
surface_index = teleporter_entity.surface.index,
zoom = 1,
force = teleporter_entity.force.name,
position = position,
}
map.ignored_by_interaction = true
map.style.height = preview_size
map.style.width = preview_size
map.style.horizontally_stretchable = true
map.style.vertically_stretchable = true
local caption = name
if recent[teleporter_entity.unit_number] then
caption = "[img=quantity-time] "..name
end
local label = inner_flow.add{type = "label", caption = caption}
label.style.horizontally_stretchable = true
label.style.font = "default-dialog-button"
label.style.font_color = {}
label.style.horizontally_stretchable = true
label.style.maximal_width = preview_size
util.register_gui(data.button_actions, button, {type = "teleport_button", param = teleporter})
any = true
end
end
if not any then
holding_table.add{type = "label", caption = {"no-teleporters"}}
end
end
function spairs(t, order)
-- collect the keys
local keys = {}
for k in pairs(t) do keys[#keys+1] = k end
-- if order function given, sort by it by passing the table and keys a, b,
-- otherwise just sort the keys
if order then
table.sort(keys, function(a,b) return order(t, a, b) end)
else
table.sort(keys)
end
-- return the iterator function
local i = 0
return function()
i = i + 1
if keys[i] then
return keys[i], t[keys[i]]
end
end
end
local refresh_teleporter_frames = function()
local players = game.players
for player_index, source in pairs (data.player_linked_teleporter) do
local player = players[player_index]
local frame = get_teleporter_frame(player)
if frame then
print("Refreshing frame")
make_teleporter_gui(player, source)
end
end
end
local check_player_linked_teleporter = function(player)
print("Checking player linked teleporter")
local source = data.player_linked_teleporter[player.index]
if source and source.valid then
print("Linked teleporter exists...")
make_teleporter_gui(player, source)
else
print("Unlinnkgin")
unlink_teleporter(player)
end
end
local resync_teleporter = function(name, teleporter_data)
local teleporter = teleporter_data.teleporter
if not (teleporter and teleporter.valid) then
return
end
local force = teleporter.force
local surface = teleporter.surface
local color = get_force_color(force)
clear_teleporter_data(teleporter_data)
local flying_text = teleporter.surface.create_entity
{
name = "teleporter-flying-text",
text = name,
position = {teleporter.position.x, teleporter.position.y - 2},
force = force,
color = color
}
flying_text.active = false
teleporter_data.flying_text = flying_text
data.adding_tag = true
local map_tag = force.add_chart_tag(surface,
{
icon = {type = "item", name = teleporter_name},
position = teleporter.position,
text = name
})
data.adding_tag = false
if map_tag then
teleporter_data.tag = map_tag
data.tag_map[map_tag.tag_number] = teleporter_data
end
end
local is_name_available = function(force, name)
local network = data.networks[force.name]
return not network[name]
end
local rename_teleporter = function(force, old_name, new_name)
if old_name == new_name then
refresh_teleporter_frames()
return
end
local network = data.networks[force.name]
local teleporter_data = network[old_name]
network[new_name] = teleporter_data
network[old_name] = nil
resync_teleporter(new_name, teleporter_data)
refresh_teleporter_frames()
end
local gui_actions =
{
rename_button = function(event, param)
make_rename_frame(game.get_player(event.player_index), param.caption)
end,
cancel_rename = function(event, param)
local player = game.get_player(event.player_index)
close_gui(get_rename_frame(player))
print("On cancel rename linked check")
check_player_linked_teleporter(player)
end,
confirm_rename_button = function(event, param)
if event.name ~= defines.events.on_gui_click then return end
local flying_text = param.flying_text
if not (flying_text and flying_text.valid) then return end
local player = game.players[event.player_index]
if not (player and player.valid) then return end
local old_name = flying_text.text
local new_name = param.textfield.text
if new_name ~= old_name and not is_name_available(player.force, new_name) then
player.print({"name-already-taken"})
return
end
close_gui(get_rename_frame(player))
rename_teleporter(player.force, old_name, new_name)
print("On rename linked check")
--check_player_linked_teleporter(player)
end,
confirm_rename_textfield = function(event, param)
if event.name ~= defines.events.on_gui_confirmed then return end
local flying_text = param.flying_text
if not (flying_text and flying_text.valid) then return end
local player = game.players[event.player_index]
if not (player and player.valid) then return end
local old_name = flying_text.text
local new_name = param.textfield.text
if new_name ~= old_name and not is_name_available(player.force, new_name) then
player.print({"name-already-taken"})
return
end
close_gui(get_rename_frame(player))
rename_teleporter(player.force, old_name, new_name)
print("On rename linked check")
--check_player_linked_teleporter(player)
end,
teleport_button = function(event, param)
local teleport_param = param.param
if not teleport_param then return end
local destination = teleport_param.teleporter
if not (destination and destination.valid) then return end
destination.timeout = destination.prototype.timeout
local destination_surface = destination.surface
local destination_position = destination.position
local player = game.players[event.player_index]
if not (player and player.valid) then return end
create_flash(destination_surface, destination_position)
create_flash(player.surface, player.position)
--This teleport doesn't check collisions. If someone complains, make it check 'can_place' and if false find a positions etc....
player.teleport(destination_position, destination_surface)
unlink_teleporter(player)
add_recent(player, destination)
end,
search_text_changed = function(event, param)
local box = event.element
local search = box.text
local parent = param.parent
for k, child in pairs (parent.children) do
child.visible = child.name:lower():find(search:lower(), 1, true)
end
end,
search_button = function(event, param)
param.box.visible = not param.box.visible
if param.box.visible then param.box.focus() end
end
}
local get_network = function(force)
local name = force.name
local network = data.networks[name]
if network then return network end
data.networks[name] = {}
return data.networks[name]
end
local on_built_entity = function(event)
local entity = event.created_entity or event.entity or event.destination
if not (entity and entity.valid) then return end
if entity.name ~= teleporter_name then return end
local surface = entity.surface
local force = entity.force
local name = "Teleporter ".. entity.unit_number
local network = get_network(force)
local teleporter_data = {teleporter = entity, flying_text = text, tag = tag}
network[name] = teleporter_data
data.teleporter_map[entity.unit_number] = teleporter_data
resync_teleporter(name, teleporter_data)
refresh_teleporter_frames()
end
local on_teleporter_removed = function(entity)
if not (entity and entity.valid) then return end
if entity.name ~= teleporter_name then return end
local force = entity.force
local teleporter_data = data.teleporter_map[entity.unit_number]
if not teleporter_data then return end
local caption = teleporter_data.flying_text.text
local network = get_network(force)
network[caption] = nil
clear_teleporter_data(teleporter_data)
data.teleporter_map[entity.unit_number] = nil
data.to_be_removed[entity.unit_number] = true
refresh_teleporter_frames()
data.to_be_removed[entity.unit_number] = nil
end
local teleporter_triggered = function(entity, character)
if not (entity and entity.valid and entity.name == teleporter_name) then return error("HEOK") end
if character.type ~= "character" then return end
local force = entity.force
local surface = entity.surface
local position = entity.position
local param = data.teleporter_map[entity.unit_number]
local player = character.player
if not player then return end
player.teleport(entity.position)
entity.active = false
entity.timeout = entity.prototype.timeout
character.active = false
data.player_linked_teleporter[player.index] = entity
make_teleporter_gui(player, entity)
end
local on_entity_removed = function(event)
local entity = event.entity
if not (entity and entity.valid) then return end
on_teleporter_removed(entity)
end
local on_entity_died = function(event)
on_teleporter_removed(event.entity)
end
local on_player_mined_entity = function(event)
on_teleporter_removed(event.entity)
end
local on_robot_mined_entity = function(event)
on_teleporter_removed(event.entity)
end
local on_gui_action = function(event)
local element = event.element
if not (element and element.valid) then return end
local player_data = data.button_actions[event.player_index]
if not player_data then return end
local action = player_data[element.index]
if action then
gui_actions[action.type](event, action)
return true
end
end
local on_gui_closed = function(event)
--print("CLOSED "..event.tick)
local element = event.element
if not element then return end
local player = game.get_player(event.player_index)
local rename_frame = get_rename_frame(player)
if rename_frame and rename_frame == element then
close_gui(rename_frame)
print("Closed rename frame, checking player linked")
check_player_linked_teleporter(player)
return
end
local teleporter_frame = get_teleporter_frame(player)
if teleporter_frame and teleporter_frame == element and not teleporter_frame.ignored_by_interaction then
close_gui(teleporter_frame)
unlink_teleporter(player)
print("Frame unlinked")
return
end
end
local on_player_removed = function(event)
local player = game.get_player(event.player_index)
close_gui(get_rename_frame(player))
unlink_teleporter(player)
end
local resync_all_teleporters = function()
for force, network in pairs (data.networks) do
for name, teleporter_data in pairs (network) do
resync_teleporter(name, teleporter_data)
end
end
end
local on_chart_tag_modified = function(event)
local force = event.force
local tag = event.tag
if not (force and force.valid and tag and tag.valid) then return end
local teleporter_data = data.tag_map[tag.tag_number]
if not teleporter_data then
--Nothing to do with us...
return
end
local player = event.player_index and game.get_player(event.player_index)
local old_name = event.old_text
local new_name = tag.text
if tag.icon and tag.icon.name ~= teleporter_name then
--They're trying to modify the icon! Straight to JAIL!
if player and player.valid then player.print({"cant-change-icon"}) end
tag.icon = {type = "item", name = teleporter_name}
end
if new_name == old_name then
return
end
if new_name == "" or not is_name_available(force, new_name) then
if player and player.valid then
player.print({"name-already-taken"})
end
tag.text = old_name
return
end
rename_teleporter(force, old_name, new_name)
end
local on_chart_tag_removed = function(event)
local force = event.force
local tag = event.tag
if not (force and force.valid and tag and tag.valid) then return end
local teleporter_data = data.tag_map[tag.tag_number]
if not teleporter_data then
--Nothing to do with us...
return
end
local name = tag.text
resync_teleporter(name, teleporter_data)
end
local on_chart_tag_added = function(event)
if data.adding_tag then return end
local tag = event.tag
if not (tag and tag.valid) then
return
end
local icon = tag.icon
if icon and icon.type == "item" and icon.name == teleporter_name then
--Trying to add a fake teleporter tag! JAIL!
local player = event.player_index and game.get_player(event.player_index)
if player and player.valid then player.print({"cant-add-tag"}) end
tag.destroy()
return
end
end
local toggle_search = function(player)
local box = data.search_boxes[player.index]
if not (box and box.valid) then return end
box.visible = true
box.focus()
end
local on_search_focused = function(event)
local player = game.get_player(event.player_index)
toggle_search(player)
end
local on_player_display_resolution_changed = function(event)
local player = game.get_player(event.player_index)
check_player_linked_teleporter(player)
end
local on_player_display_scale_changed = function(event)
local player = game.get_player(event.player_index)
check_player_linked_teleporter(player)
end
local on_trigger_created_entity = function(event)
local entity = event.entity
if not (entity and entity.valid) then return end
if entity.name ~= teleporter_sticker then return end
local source = event.source
if not (source and source.valid) then return end
local stuck_to = entity.sticked_to
if not (stuck_to and stuck_to.valid) then return end
teleporter_triggered(source, stuck_to)
end
local on_rocket_launched = function(event)
local rocket = event.rocket
if not (rocket and rocket.valid) then return end
local count = rocket.get_item_count(teleporter_name)
if count == 0 then return end
local rand = math.random
local rando = function(i)
return rand() * (i or 5)
end
local rando_autoplace = function(i)
return
{
frequency = rando(i),
richness = rando(i),
size = rando(i)
}
end
local settings = rocket.surface.map_gen_settings
for name, autoplace in pairs(settings.autoplace_controls) do
settings.autoplace_controls[name] = rando_autoplace(rando(2))
end
settings.cliff_settings =
{
cliff_elevation_0 = rando(20),
cliff_elevation_interval = rando(80),
name = "cliff",
richness = 1
}
settings.seed = math.floor(rando(2 ^ 32))
settings.terrain_segmentation = rando(3)
settings.water = rando(3)
settings.starting_area = rando(3)
local new_surface = game.create_surface("teleporter_surface"..game.tick..settings.seed, settings)
new_surface.create_entity{name = teleporter_name, position = {0, 0}, force = rocket.force, raise_built = true}
end
local teleporters = {}
teleporters.events =
{
[defines.events.on_built_entity] = on_built_entity,
[defines.events.on_robot_built_entity] = on_built_entity,
[defines.events.script_raised_built] = on_built_entity,
[defines.events.script_raised_revive] = on_built_entity,
[defines.events.on_entity_cloned] = on_built_entity,
[defines.events.on_entity_died] = on_entity_removed,
[defines.events.on_player_mined_entity] = on_entity_removed,
[defines.events.on_robot_mined_entity] = on_entity_removed,
[defines.events.script_raised_destroy] = on_entity_removed,
[defines.events.on_gui_click] = on_gui_action,
[defines.events.on_gui_text_changed] = on_gui_action,
[defines.events.on_gui_confirmed] = on_gui_action,
[defines.events.on_gui_closed] = on_gui_closed,
[require("shared").hotkeys.focus_search] = on_search_focused,
[defines.events.on_player_display_resolution_changed] = on_player_display_resolution_changed,
[defines.events.on_player_display_scale_changed] = on_player_display_scale_changed,
[defines.events.on_player_died] = on_player_removed,
[defines.events.on_player_left_game] = on_player_removed,
[defines.events.on_player_changed_force] = on_player_removed,
[defines.events.on_chart_tag_modified] = on_chart_tag_modified,
[defines.events.on_chart_tag_removed] = on_chart_tag_removed,
[defines.events.on_chart_tag_added] = on_chart_tag_added,
[defines.events.on_trigger_created_entity] = on_trigger_created_entity,
[defines.events.on_rocket_launched] = on_rocket_launched
}
teleporters.on_init = function()
global.teleporters = global.teleporters or data
end
teleporters.on_load = function()
data = global.teleporters
end
teleporters.on_configuration_changed = function()
-- 0.1.2 migration...
data.player_linked_teleporter = data.player_linked_teleporter or {}
data.rename_frames = data.rename_frames or data.frames or {}
data.to_be_removed = data.to_be_removed or {}
--0.1.5...
data.teleporter_map = data.teleporter_map or data.map or {}
data.tag_map = data.tag_map or {}
resync_all_teleporters()
--0.1.7...
data.search_boxes = data.search_boxes or {}
data.recent = data.recent or {}
end
return teleporters

16
Teleporters/shared.lua Normal file
View File

@@ -0,0 +1,16 @@
--Shared data interface between data and script, notably prototype names.
local data = {}
data.entities =
{
teleporter = "teleporter",
teleporter_sticker = "teleporter-sticker"
}
data.hotkeys =
{
focus_search = "teleporter-focus-search"
}
return data

BIN
Teleporters/thumbnail.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB