write something there
This commit is contained in:
commit
b4b6c08f4f
8546 changed files with 309825 additions and 0 deletions
92
mods/worldgate/API.md
Normal file
92
mods/worldgate/API.md
Normal file
|
@ -0,0 +1,92 @@
|
|||
API
|
||||
---
|
||||
|
||||
All of the API functions for Worldgate are defined in the `worldgate` global variable.
|
||||
|
||||
### `worldgate.add_gate(def)`
|
||||
|
||||
This function adds a worldgate to the world. This is useful for adding your own custom worldgates to the world. The `def` parameter must be a table with the following fields:
|
||||
|
||||
```lua
|
||||
{
|
||||
-- position: The x/y/z location where the worldgate will be generated. This
|
||||
-- value must be a vector created with vector.new.
|
||||
position = vector.new(...),
|
||||
|
||||
-- base: A schematic specifier that identifies a 'base' schematic that forms
|
||||
-- the base, or bottom half, of the worldgate which typically contains a
|
||||
-- Telemosaic beacon and range extender marker nodes.
|
||||
base = worldgate.get_random_base(pcgr),
|
||||
|
||||
-- decor: A schematic specifier that identifies a 'decor' schematic that forms
|
||||
-- a decoration placed on the worldgate base. This is typically some form of
|
||||
-- housing or adornment for the worldgate.
|
||||
decor = worldgate.get_random_decor(pcgr),
|
||||
|
||||
-- quality: Determines the quality of range extenders that generate as part
|
||||
-- of this worldgate. It must be an integer with a value of -1, 0, or 1 which
|
||||
-- corresponds to lower quality, equal quality, or better quality extenders,
|
||||
-- respectively.
|
||||
quality = worldgate.get_random_quality(pcgr),
|
||||
|
||||
-- exact: A boolean value that specifies if the worldgate should be placed at
|
||||
-- the exact position specified. If true, the worldgate will be placed at the
|
||||
-- point specified by the position parameter regardless of surrounding
|
||||
-- terrain. If false, the mod will attempt to place the worldgate according to
|
||||
-- the available terrain which favors the heightmap first, below air second,
|
||||
-- then any random position in the mapchunk if all else fails.
|
||||
exact = false,
|
||||
|
||||
-- destination: A vector that matches the position of another worldgate that
|
||||
-- this worldgate will be linked to automatically. If this value is nil, then
|
||||
-- the gate's beacon will be deactivated and it will have no destination.
|
||||
destination = nil,
|
||||
}
|
||||
```
|
||||
|
||||
### `worldgate.get_random_base(pcgr)`
|
||||
|
||||
This function returns a path to a random schematic file in the `worldgate/schematics/base/` directory that corresponds to a worldgate base. Every built-in base schematic will contain a single beacon and extender marker nodes. The optional argument is a PcgRandom object that can be used to choose the random base schematic.
|
||||
|
||||
### `worldgate.get_random_decor(pcgr)`
|
||||
|
||||
This function returns a path to a random schematic file in the `worldgate/schematics/decor/` directory that corresponds to a worldgate decoration. Decorations typically provide some form of housing or adornment surrounding the worldgate's Telemosaic beacon. A decoration schematic is not necessary for a worldgate to function, but decor does look pretty nice!
|
||||
|
||||
The optional argument is a PcgRandom object that can be used to choose the random decor schematic.
|
||||
|
||||
### `worldgate.get_random_quality(pcgr)`
|
||||
|
||||
This function returns a random value of either -1, 0, or 1, values which correspond to the quality values of a worldgate. This is useful for creating gates with a random quality. The optional argument is a PcgRandom object that can be used to choose the random value.
|
||||
|
||||
### `worldgate.get_gates_for_mapblock(position)`
|
||||
|
||||
This function returns a list of all gates that should be generated for the mapblock of the given vector location. The `position` parameter must be a vector created with `vector.new`.
|
||||
|
||||
### `worldgate.reigster_on_worldgate_generated(fn)`
|
||||
|
||||
This function registers a callback function that will be called when a worldgate is successfully generated in the world. The function is called with three parameters:
|
||||
|
||||
- `location`: A vector representing the point at which the worldgate was actually placed in the world
|
||||
- `gate`: The definition of the generated worldgate as specified for `worldgate.add_gate(def)`
|
||||
- `strategy`: A string that specifies the placement algorithm that the mapgen function used to place the worldgate, in order of mapgen preference:
|
||||
- `"exact"`: The location is the worldgate's `position` value specified with `exact = true`
|
||||
- `"heightmap"`: A suitable location was found matching the heightmap for the worldgate's mapchunk
|
||||
- `"grounded"`: A suitable location was found by probing downwards from a random air node
|
||||
- `"random"`: A location was selected at random with no regards for the surrounding terrain
|
||||
|
||||
### `worldgate.register_on_worldgate_failed(fn)`
|
||||
|
||||
This function registers a callback function that will be called when a worldgate tries but fails to generate. This is most likely to happen if mod settings prevent worldgates from spawning in midair or underwater and such a position is selected via the `random` placement strategy during mapgen. A gate that fails to generate in this manner will not attempt to be generated again.
|
||||
|
||||
The callback function is called with just one parameter
|
||||
|
||||
- `gate`: The gate definition of the worldgate that failed to generate as specified for `worldgate.add_gate(def)`
|
||||
|
||||
Dark and Dangerous API
|
||||
----------------------
|
||||
|
||||
**WARNING: ACCESSING THESE FUNCTIONS/VARIABLES CAN CAUSE UNPREDICTABLE LOSS/DAMAGE TO YOUR WORLD; DO NOT USE UNLESS YOU KNOW WHAT YOU ARE DOING**
|
||||
|
||||
### `worldgate.add_gate_unsafe(def)`
|
||||
|
||||
This function fills the same role as `worldgate.add_gate(def)`, but it doesn't perform any validation checks to ensure that the gate is valid. This function is used internally during native gate generation for faster performance. Use only if you're sure that your gate definitions do not require validation.
|
9
mods/worldgate/LICENSE
Normal file
9
mods/worldgate/LICENSE
Normal file
|
@ -0,0 +1,9 @@
|
|||
MIT License
|
||||
|
||||
Copyright © 2023 EmptyStar <https://github.com/EmptyStar>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
24
mods/worldgate/README.md
Normal file
24
mods/worldgate/README.md
Normal file
|
@ -0,0 +1,24 @@
|
|||
Worldgate
|
||||
=========
|
||||
|
||||
Discover the Worldgates, an ancient teleportation network that can carry you to distant lands in an instant. Despite their long abandonment, the Worldgates are still highly functional. They can be found throughout the world, some more intact than others, and each adorned in stone by the elder hands that wrought them.
|
||||
|
||||
Gates found at the surface of the world are linked randomly to neighboring gates, and gates found at elevations above and below ground are linked to gates on the surface. To use a Worldgate, right-click its active teleportation beacon. But understand the danger of teleporting through a random gate as it may take you very far from your starting point with no way back!
|
||||
|
||||
The gates can be linked to any gate through use of mese crystal fragments, and additional teleportation beacons can be crafted. To learn more, see [the Telemosaic mod](https://content.minetest.net/packages/mt-mods/telemosaic/) which is the teleportation technology that underpins the Worldgates.
|
||||
|
||||
For the truly brave of heart who wish to fundamentally alter their Worldgate experience, see the mod settings and [the API documentation](https://github.com/EmptyStar/worldgate/blob/main/API.md).
|
||||
|
||||
Notes
|
||||
-----
|
||||
|
||||
- Worldgates will only generate in parts of the world that have not yet been explored.
|
||||
- By default, Worldgates will generate roughly every 1000 nodes between (0,0,0) and 29000 nodes in every direction for a possible total of 195112 Worldgates per world (although many will not generate if midair spawning is disabled which it is by default); this can be configured via mod settings.
|
||||
|
||||
Caveats
|
||||
-------
|
||||
|
||||
- When you first approach a newly discovered Worldgate, it may take a few seconds to become fully active.
|
||||
- Teleportation has a five-second cooldown to prevent spamming and to give new Worldgates a little extra time to configure themselves.
|
||||
- Rarely, a Worldgate may fail to link to a neighboring Worldgate, thus leaving you stranded at your destination.
|
||||
- Rarely, depending on the terrain, a Worldgate can fail to generate.
|
46
mods/worldgate/init.lua
Normal file
46
mods/worldgate/init.lua
Normal file
|
@ -0,0 +1,46 @@
|
|||
--
|
||||
-- Globals
|
||||
--
|
||||
|
||||
worldgate = {
|
||||
modpath = minetest.get_modpath("worldgate"),
|
||||
gates = {},
|
||||
hash_index = {},
|
||||
forceload_index = {},
|
||||
settings = {
|
||||
mapgen = minetest.settings:get_bool("worldgate.mapgen",true),
|
||||
native = minetest.settings:get_bool("worldgate.native",true),
|
||||
native_link = minetest.settings:get_bool("worldgate.native.link",true),
|
||||
native_spread = tonumber(minetest.settings:get("worldgate.native.spread",1000) or 1000),
|
||||
native_xzjitter = tonumber(minetest.settings:get("worldgate.native.xzjitter",12.5) or 12.5),
|
||||
ymin = tonumber(minetest.settings:get("worldgate.ymin",-29900) or -29900),
|
||||
ymax = tonumber(minetest.settings:get("worldgate.ymax",29900) or 29900),
|
||||
underwaterspawn = minetest.settings:get_bool("worldgate.underwaterspawn",false),
|
||||
midairspawn = minetest.settings:get_bool("worldgate.midairspawn",false),
|
||||
breakage = tonumber(minetest.settings:get("worldgate.breakage",8) or 8),
|
||||
superextenders = minetest.settings:get_bool("worldgate.superextenders",true),
|
||||
beaconglow = minetest.settings:get_bool("worldgate.beaconglow",true),
|
||||
destroykeys = minetest.settings:get_bool("worldgate.destroykeys",true),
|
||||
},
|
||||
}
|
||||
|
||||
-- Disable mapgen via Asuna settings if set
|
||||
if minetest.get_modpath("asuna_core") then
|
||||
worldgate.settings.mapgen = minetest.settings:get_bool("asuna.content.wayfarer.worldgate",true)
|
||||
end
|
||||
|
||||
--
|
||||
-- Modules
|
||||
--
|
||||
|
||||
local function load(file)
|
||||
dofile(worldgate.modpath .. "/src/" .. file .. ".lua")
|
||||
end
|
||||
|
||||
load("nodes")
|
||||
load("functions")
|
||||
load("gates")
|
||||
load("mapgen")
|
||||
load("logging")
|
||||
load("settings_overrides")
|
||||
load("link")
|
4
mods/worldgate/mod.conf
Normal file
4
mods/worldgate/mod.conf
Normal file
|
@ -0,0 +1,4 @@
|
|||
name = worldgate
|
||||
title = Worldgate
|
||||
author = EmptyStar
|
||||
depends = telemosaic, default, stairs
|
BIN
mods/worldgate/schematics/base/worldgate_base_basic.mts
Normal file
BIN
mods/worldgate/schematics/base/worldgate_base_basic.mts
Normal file
Binary file not shown.
BIN
mods/worldgate/schematics/base/worldgate_base_basic_better.mts
Normal file
BIN
mods/worldgate/schematics/base/worldgate_base_basic_better.mts
Normal file
Binary file not shown.
BIN
mods/worldgate/schematics/base/worldgate_base_basic_crumbled.mts
Normal file
BIN
mods/worldgate/schematics/base/worldgate_base_basic_crumbled.mts
Normal file
Binary file not shown.
BIN
mods/worldgate/schematics/base/worldgate_base_flower.mts
Normal file
BIN
mods/worldgate/schematics/base/worldgate_base_flower.mts
Normal file
Binary file not shown.
BIN
mods/worldgate/schematics/base/worldgate_base_fountain.mts
Normal file
BIN
mods/worldgate/schematics/base/worldgate_base_fountain.mts
Normal file
Binary file not shown.
BIN
mods/worldgate/schematics/base/worldgate_base_lava.mts
Normal file
BIN
mods/worldgate/schematics/base/worldgate_base_lava.mts
Normal file
Binary file not shown.
BIN
mods/worldgate/schematics/base/worldgate_base_smiling.mts
Normal file
BIN
mods/worldgate/schematics/base/worldgate_base_smiling.mts
Normal file
Binary file not shown.
BIN
mods/worldgate/schematics/base/worldgate_base_smiling_better.mts
Normal file
BIN
mods/worldgate/schematics/base/worldgate_base_smiling_better.mts
Normal file
Binary file not shown.
BIN
mods/worldgate/schematics/base/worldgate_base_strong.mts
Normal file
BIN
mods/worldgate/schematics/base/worldgate_base_strong.mts
Normal file
Binary file not shown.
BIN
mods/worldgate/schematics/base/worldgate_base_strong_better.mts
Normal file
BIN
mods/worldgate/schematics/base/worldgate_base_strong_better.mts
Normal file
Binary file not shown.
BIN
mods/worldgate/schematics/base/worldgate_base_wide.mts
Normal file
BIN
mods/worldgate/schematics/base/worldgate_base_wide.mts
Normal file
Binary file not shown.
BIN
mods/worldgate/schematics/base/worldgate_base_wide_better.mts
Normal file
BIN
mods/worldgate/schematics/base/worldgate_base_wide_better.mts
Normal file
Binary file not shown.
BIN
mods/worldgate/schematics/base/worldgate_base_ziggurat.mts
Normal file
BIN
mods/worldgate/schematics/base/worldgate_base_ziggurat.mts
Normal file
Binary file not shown.
Binary file not shown.
BIN
mods/worldgate/schematics/decor/worldgate_decor_arches.mts
Normal file
BIN
mods/worldgate/schematics/decor/worldgate_decor_arches.mts
Normal file
Binary file not shown.
BIN
mods/worldgate/schematics/decor/worldgate_decor_basic.mts
Normal file
BIN
mods/worldgate/schematics/decor/worldgate_decor_basic.mts
Normal file
Binary file not shown.
Binary file not shown.
BIN
mods/worldgate/schematics/decor/worldgate_decor_basic_super.mts
Normal file
BIN
mods/worldgate/schematics/decor/worldgate_decor_basic_super.mts
Normal file
Binary file not shown.
BIN
mods/worldgate/schematics/decor/worldgate_decor_collapsed.mts
Normal file
BIN
mods/worldgate/schematics/decor/worldgate_decor_collapsed.mts
Normal file
Binary file not shown.
BIN
mods/worldgate/schematics/decor/worldgate_decor_cube.mts
Normal file
BIN
mods/worldgate/schematics/decor/worldgate_decor_cube.mts
Normal file
Binary file not shown.
BIN
mods/worldgate/schematics/decor/worldgate_decor_fortress.mts
Normal file
BIN
mods/worldgate/schematics/decor/worldgate_decor_fortress.mts
Normal file
Binary file not shown.
BIN
mods/worldgate/schematics/decor/worldgate_decor_mini_pillars.mts
Normal file
BIN
mods/worldgate/schematics/decor/worldgate_decor_mini_pillars.mts
Normal file
Binary file not shown.
BIN
mods/worldgate/schematics/decor/worldgate_decor_minimal.mts
Normal file
BIN
mods/worldgate/schematics/decor/worldgate_decor_minimal.mts
Normal file
Binary file not shown.
BIN
mods/worldgate/schematics/decor/worldgate_decor_none.mts
Normal file
BIN
mods/worldgate/schematics/decor/worldgate_decor_none.mts
Normal file
Binary file not shown.
BIN
mods/worldgate/schematics/decor/worldgate_decor_pagoda.mts
Normal file
BIN
mods/worldgate/schematics/decor/worldgate_decor_pagoda.mts
Normal file
Binary file not shown.
BIN
mods/worldgate/schematics/decor/worldgate_decor_pillars.mts
Normal file
BIN
mods/worldgate/schematics/decor/worldgate_decor_pillars.mts
Normal file
Binary file not shown.
BIN
mods/worldgate/schematics/decor/worldgate_decor_stargate.mts
Normal file
BIN
mods/worldgate/schematics/decor/worldgate_decor_stargate.mts
Normal file
Binary file not shown.
BIN
mods/worldgate/schematics/decor/worldgate_decor_supertotem.mts
Normal file
BIN
mods/worldgate/schematics/decor/worldgate_decor_supertotem.mts
Normal file
Binary file not shown.
BIN
mods/worldgate/schematics/decor/worldgate_decor_totems.mts
Normal file
BIN
mods/worldgate/schematics/decor/worldgate_decor_totems.mts
Normal file
Binary file not shown.
BIN
mods/worldgate/schematics/decor/worldgate_decor_ziggurat.mts
Normal file
BIN
mods/worldgate/schematics/decor/worldgate_decor_ziggurat.mts
Normal file
Binary file not shown.
BIN
mods/worldgate/schematics/worldgate_airspace.mts
Normal file
BIN
mods/worldgate/schematics/worldgate_airspace.mts
Normal file
Binary file not shown.
BIN
mods/worldgate/schematics/worldgate_platform.mts
Normal file
BIN
mods/worldgate/schematics/worldgate_platform.mts
Normal file
Binary file not shown.
38
mods/worldgate/settingtypes.txt
Normal file
38
mods/worldgate/settingtypes.txt
Normal file
|
@ -0,0 +1,38 @@
|
|||
# Enable mapgen? Unset this to prevent all worldgates from generating.
|
||||
worldgate.mapgen (Enable mapgen?) bool true
|
||||
|
||||
# Generate native worldgates? Native worldgates are the built-in worldgates that this mod provides by default.
|
||||
worldgate.native (Generate native worldgates?) bool true
|
||||
|
||||
# Link native worldgates? This links surface worldgates to a random neighbor and underground/aerial worldgates to worldgates on the surface.
|
||||
worldgate.native.link (Link native worldgates?) bool true
|
||||
|
||||
# Average number of nodes between native worldgates.
|
||||
worldgate.native.spread (Distance between native worldgates) int 1000 500 25000
|
||||
|
||||
# The percentage of spread by which to randomly offset the x/z coordinates of native worldgates. A higher jitter randomly moves the gates further from their generated positions, thereby making their locations less predictable.
|
||||
worldgate.native.xzjitter (Native worldgate x/z jitter) float 12.5 0 25
|
||||
|
||||
# The maximum y position of any worldgate. Any worldgates above this elevation will not generate.
|
||||
worldgate.ymax (Worldgate maximum y position) int 29900 0 29900
|
||||
|
||||
# The minimum y position of any worldgate. Any worldgates below this elevation will not generate.
|
||||
worldgate.ymin (Worldgate minimum y position) int -29900 -29900 0
|
||||
|
||||
# Generate worldgates underwater? If set, worldgates can spawn on the ocean floor; if unset, worldgates will spawn on the water's surface.
|
||||
worldgate.underwaterspawn (Generate worldgates underwater?) bool false
|
||||
|
||||
# Generate worldgates in midair? If set, worldgates can be floating on their own in the air; if unset, gates that attempt to generate in the air will fail to generate.
|
||||
worldgate.midairspawn (Generate worldgates in midair?) bool false
|
||||
|
||||
# Percentage chance of a Telemosaic extender structure node being broken when a gate generates. This causes extenders to be replaced with cobblestone.
|
||||
worldgate.breakage (Percent chance of an extender being broken) int 8 0 100
|
||||
|
||||
# Increase extender range? This supersedes the Telemosaic configuration values for extender ranges. If you wish to use the Telemosaic settings instead, unset this configuration option and change the Telemosaic settings accordingly.
|
||||
worldgate.superextenders (Increase extender range?) bool true
|
||||
|
||||
# Glowing Telemosaic beacons?
|
||||
worldgate.beaconglow (Glowing Telemosaic beacons?) bool true
|
||||
|
||||
# Consume Mese Crystal Fragments after converting to a Telemosaic key? By default, Telemosaic keys are converted back to crystal fragments after use.
|
||||
worldgate.destroykeys (Consume Telemosaic keys?) bool true
|
122
mods/worldgate/src/functions.lua
Normal file
122
mods/worldgate/src/functions.lua
Normal file
|
@ -0,0 +1,122 @@
|
|||
--
|
||||
-- Worldgate functions
|
||||
--
|
||||
|
||||
-- Function for selecting a random base schematic
|
||||
local base_schematics = (function()
|
||||
local schems = {}
|
||||
for _,schematic in ipairs(minetest.get_dir_list(worldgate.modpath .. "/schematics/base/",false)) do
|
||||
table.insert(schems,worldgate.modpath .. "/schematics/base/" .. schematic)
|
||||
end
|
||||
return schems
|
||||
end)()
|
||||
local base_count = #base_schematics
|
||||
worldgate.schematics = {}
|
||||
worldgate.schematics.base = base_schematics
|
||||
|
||||
function worldgate.get_random_base(pcgr)
|
||||
return base_schematics[pcgr and pcgr:next(1,base_count) or math.random(1,base_count)]
|
||||
end
|
||||
|
||||
-- Function for selecting a random decor schematic
|
||||
local decor_schematics = (function()
|
||||
local schems = {}
|
||||
for _,schematic in ipairs(minetest.get_dir_list(worldgate.modpath .. "/schematics/decor/",false)) do
|
||||
table.insert(schems,worldgate.modpath .. "/schematics/decor/" .. schematic)
|
||||
end
|
||||
return schems
|
||||
end)()
|
||||
local decor_count = #decor_schematics
|
||||
worldgate.schematics.decor = decor_schematics
|
||||
|
||||
function worldgate.get_random_decor(pcgr)
|
||||
return decor_schematics[pcgr and pcgr:next(1,decor_count) or math.random(1,decor_count)]
|
||||
end
|
||||
|
||||
-- Function for selecting a random quality value
|
||||
function worldgate.get_random_quality(pcgr)
|
||||
return pcgr and pcgr:next(-1,1) or math.random(-1,1)
|
||||
end
|
||||
|
||||
-- Function for adding new worldgates without data checks
|
||||
function worldgate.add_gate_unsafe(def)
|
||||
-- Add gate to list of gates
|
||||
local ngates = #worldgate.gates
|
||||
worldgate.gates[ngates + 1] = def
|
||||
|
||||
-- Index the gate via mapblock hashing
|
||||
local hash = minetest.hash_node_position(def.position:divide(16):floor())
|
||||
local gates = worldgate.hash_index[hash] or {}
|
||||
gates[#gates + 1] = ngates + 1
|
||||
worldgate.hash_index[hash] = gates
|
||||
end
|
||||
|
||||
-- Function for adding new worldgates
|
||||
local ymin = math.max(-29900,worldgate.settings.ymin)
|
||||
local ymax = math.min(29900,worldgate.settings.ymax)
|
||||
function worldgate.add_gate(def)
|
||||
-- Position must be a valid vector
|
||||
if not def.position then
|
||||
error("Attempted to add a worldgate without a position")
|
||||
elseif not vector.check(def.position) then
|
||||
error("Worldgate position must be a vector created with vector.new")
|
||||
elseif def.position.y > ymax or def.position.y < ymin then
|
||||
error("Worldgate position " .. minetest.pos_to_string(def.position) .. " is beyond ymin/ymax values")
|
||||
end
|
||||
|
||||
if not def.base then
|
||||
def.base = worldgate.get_random_base()
|
||||
elseif type(def.base) ~= "string" then
|
||||
error("Worldgate base must be a string that identifies a schematic")
|
||||
end
|
||||
|
||||
if not def.decor then
|
||||
def.decor = worldgate.get_random_decor()
|
||||
elseif type(def.decor) ~= "string" then
|
||||
error("Worldgate decor must be a string that identifies a schematic")
|
||||
end
|
||||
|
||||
if not def.quality then
|
||||
def.quality = worldgate.get_random_quality()
|
||||
elseif not (def.quality == -1 or def.quality == 0 or def.quality == 1) then
|
||||
error("Worldgate quality must be an integer between -1 and 1 inclusive")
|
||||
end
|
||||
|
||||
if def.exact == nil then
|
||||
def.exact = false
|
||||
else
|
||||
def.exact = not not def.exact -- boolean cast
|
||||
end
|
||||
|
||||
-- Add gate via unsafe function
|
||||
worldgate.add_gate_unsafe(def)
|
||||
end
|
||||
|
||||
-- Function for checking a mapblock against the gate hash index
|
||||
function worldgate.get_gates_for_mapblock(pos)
|
||||
local gates = worldgate.hash_index[minetest.hash_node_position(pos:divide(16):floor())] or {}
|
||||
for i = 0, #gates do
|
||||
gates[i] = worldgate.gates[gates[i]]
|
||||
end
|
||||
return gates
|
||||
end
|
||||
|
||||
-- Function for finding a suitable placement for a worldgate within a given area
|
||||
function worldgate.find_worldgate_location_in_area(minp,maxp)
|
||||
end
|
||||
|
||||
-- Function for spawning a worldgate
|
||||
function worldgate.generate_gate(pos)
|
||||
end
|
||||
|
||||
-- Function for gate generation callbacks
|
||||
worldgate.worldgate_generated_callbacks = {}
|
||||
function worldgate.reigster_on_worldgate_generated(fn)
|
||||
table.insert(worldgate.worldgate_generated_callbacks,fn)
|
||||
end
|
||||
|
||||
-- Function for failed gate generation callbacks
|
||||
worldgate.worldgate_failed_callbacks = {}
|
||||
function worldgate.reigster_on_worldgate_failed(fn)
|
||||
table.insert(worldgate.worldgate_failed_callbacks,fn)
|
||||
end
|
123
mods/worldgate/src/gates.lua
Normal file
123
mods/worldgate/src/gates.lua
Normal file
|
@ -0,0 +1,123 @@
|
|||
--
|
||||
-- Native worldgate generation
|
||||
--
|
||||
|
||||
-- Generate gates if the mod is configured to do so
|
||||
if worldgate.settings.native then
|
||||
-- Define rng based on the world seed
|
||||
local pcgr = PcgRandom(minetest.get_mapgen_setting("seed"))
|
||||
|
||||
-- Get distance between gates (spread)
|
||||
local spread = worldgate.settings.native_spread
|
||||
|
||||
-- Do not generate gates beyond totalmax to prevent any wierdness with world
|
||||
-- boundaries
|
||||
local totalmax = 29900
|
||||
|
||||
-- Get minimum and maximum y values
|
||||
local ymin = math.max(-totalmax,worldgate.settings.ymin)
|
||||
local ymax = math.min(totalmax,worldgate.settings.ymax)
|
||||
|
||||
-- Cache frequently used global functions for better performance
|
||||
local add_gate = worldgate.add_gate_unsafe -- native gates are made with respect to checks
|
||||
local get_random_base = worldgate.get_random_base
|
||||
local get_random_decor = worldgate.get_random_decor
|
||||
local get_random_quality = worldgate.get_random_quality
|
||||
local vn = vector.new
|
||||
|
||||
-- Align coordinate values with 0 for more centered/grounded generation
|
||||
local alignment_offset = totalmax - spread * math.floor(totalmax / spread)
|
||||
local ymin_offset = -ymin - spread * math.floor(-ymin / spread)
|
||||
local ymax_offset = ymax - spread * math.floor(ymax / spread)
|
||||
local min = -totalmax + alignment_offset
|
||||
local max = totalmax - alignment_offset
|
||||
ymin = ymin + ymin_offset
|
||||
ymax = ymax - ymax_offset
|
||||
|
||||
-- Generate x/z values with jitter so that worldgate locations are less
|
||||
-- predictable
|
||||
local xzjitterp = math.floor(spread * worldgate.settings.native_xzjitter / 100)
|
||||
local xzjittern = -xzjitterp
|
||||
|
||||
-- Function to get a gate based on an x/y/z coordinate
|
||||
local function generate_gate(x,y,z)
|
||||
return {
|
||||
position = vn(x + pcgr:next(xzjittern,xzjitterp),y + pcgr:next(0,24),z + pcgr:next(xzjittern,xzjitterp)),
|
||||
base = get_random_base(pcgr),
|
||||
decor = get_random_decor(pcgr),
|
||||
quality = get_random_quality(pcgr),
|
||||
exact = false,
|
||||
}
|
||||
end
|
||||
|
||||
-- Probability table for gate quality bias in favor of average and above
|
||||
-- average quality values (20% poor, 50% average, 30% above average)
|
||||
local quality_bias = {-1,-1,0,0,0,0,0,1,1,1}
|
||||
|
||||
-- Link gates if configured, else generate gates with no destinations
|
||||
if worldgate.settings.native_link then
|
||||
-- Generate x/z gate definitions for y = 0 since these are the destination
|
||||
-- gates of all native gates
|
||||
local surface_gates = {}
|
||||
for x = min, max, spread do
|
||||
for z = min, max, spread do
|
||||
local pos = vn(x,0,z)
|
||||
local hpos = minetest.hash_node_position(pos)
|
||||
surface_gates[hpos] = {
|
||||
position = vn(x + pcgr:next(xzjittern,xzjitterp),pcgr:next(0,24),z + pcgr:next(xzjittern,xzjitterp)),
|
||||
base = get_random_base(pcgr),
|
||||
decor = get_random_decor(pcgr),
|
||||
quality = quality_bias[pcgr:next(1,10)],
|
||||
exact = false,
|
||||
destination = (function() -- placeholder to be converted to an actual gate
|
||||
local nhashes = {
|
||||
minetest.hash_node_position(vn(x == min and x + spread or x - spread,0,z == min and z + spread or z - spread)),
|
||||
minetest.hash_node_position(vn(x == min and x + spread or x - spread,0,z == max and z - spread or z + spread)),
|
||||
minetest.hash_node_position(vn(x == max and x - spread or x + spread,0,z == min and z + spread or z - spread)),
|
||||
minetest.hash_node_position(vn(x == max and x - spread or x + spread,0,z == max and z - spread or z + spread)),
|
||||
}
|
||||
local neighbors = {}
|
||||
for n = 1, 4 do
|
||||
n = nhashes[n]
|
||||
local g = surface_gates[n]
|
||||
if not g or g.destination ~= hpos then
|
||||
neighbors[#neighbors + 1] = n
|
||||
end
|
||||
end
|
||||
return neighbors[1] and neighbors[pcgr:next(1,#neighbors)] or nhashes[pcgr:next(1,4)]
|
||||
end)(),
|
||||
}
|
||||
end
|
||||
|
||||
-- Override gate generation function to generate destinations
|
||||
generate_gate = function(x,y,z)
|
||||
local pos = vn(x,y,z)
|
||||
local gate
|
||||
if y == 0 then
|
||||
gate = surface_gates[minetest.hash_node_position(pos)]
|
||||
gate.destination = surface_gates[gate.destination].position
|
||||
else
|
||||
gate = {
|
||||
position = vn(x + pcgr:next(xzjittern,xzjitterp),y + pcgr:next(0,24),z + pcgr:next(xzjittern,xzjitterp)),
|
||||
base = get_random_base(pcgr),
|
||||
decor = get_random_decor(pcgr),
|
||||
quality = get_random_quality(pcgr),
|
||||
exact = false,
|
||||
}
|
||||
pos.y = 0
|
||||
gate.destination = surface_gates[minetest.hash_node_position(pos)].position
|
||||
end
|
||||
return gate
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Generate gates
|
||||
for x = min, max, spread do
|
||||
for y = ymin, ymax, spread do
|
||||
for z = min, max, spread do
|
||||
add_gate(generate_gate(x,y,z))
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
188
mods/worldgate/src/link.lua
Normal file
188
mods/worldgate/src/link.lua
Normal file
|
@ -0,0 +1,188 @@
|
|||
--
|
||||
-- Worldgate linking functions
|
||||
--
|
||||
|
||||
-- Telemosaic location hashing and unhashing functions
|
||||
local function hash_pos(pos)
|
||||
return math.floor(pos.x + 0.5)..':'..
|
||||
math.floor(pos.y + 0.5)..':'..
|
||||
math.floor(pos.z + 0.5)
|
||||
end
|
||||
|
||||
local function unhash_pos(hash)
|
||||
local list = string.split(hash, ':')
|
||||
local p = {
|
||||
x = tonumber(list[1]),
|
||||
y = tonumber(list[2]),
|
||||
z = tonumber(list[3])
|
||||
}
|
||||
if p.x and p.y and p.z then
|
||||
return p
|
||||
end
|
||||
end
|
||||
|
||||
-- Polyfill for vector.in_area
|
||||
if not vector.in_area then
|
||||
function vector.in_area(pos, min, max)
|
||||
return (pos.x >= min.x) and (pos.x <= max.x) and
|
||||
(pos.y >= min.y) and (pos.y <= max.y) and
|
||||
(pos.z >= min.z) and (pos.z <= max.z)
|
||||
end
|
||||
end
|
||||
|
||||
-- Garbage collection index to manage force-loaded chunks
|
||||
local forceloader = {
|
||||
index = {},
|
||||
load = function(self,blockpos)
|
||||
-- Get the reference counter for the mapblock
|
||||
local hash = minetest.hash_node_position(blockpos)
|
||||
local refcounter = self.index[hash] or 0
|
||||
|
||||
-- Force-load mapblock if it is not yet force-loaded
|
||||
if refcounter == 0 then
|
||||
minetest.forceload_block(blockpos,true)
|
||||
end
|
||||
|
||||
-- Store updated reference counter
|
||||
refcounter = refcounter + 1
|
||||
self.index[hash] = refcounter
|
||||
end,
|
||||
unload = function(self,blockpos)
|
||||
-- Get the reference counter for the mapblock
|
||||
local hash = minetest.hash_node_position(blockpos)
|
||||
local refcounter = self.index[hash] or 1
|
||||
|
||||
-- Decrement reference counter and unload mapblock if there are no more
|
||||
-- references to it
|
||||
refcounter = refcounter - 1
|
||||
if refcounter == 0 then
|
||||
minetest.forceload_free_block(blockpos,true)
|
||||
end
|
||||
|
||||
-- Store updated reference counter
|
||||
self.index[hash] = refcounter
|
||||
end,
|
||||
}
|
||||
|
||||
-- Function for linking and force-loading gate destinations
|
||||
function worldgate.link(pos)
|
||||
-- Get meta/destination
|
||||
local nodemeta = minetest.get_meta(pos)
|
||||
local destination = nodemeta:get("telemosaic:dest")
|
||||
local do_worldgate_link = false
|
||||
|
||||
-- Check for worldgate destination and convert to vector
|
||||
local dpos = nil
|
||||
if not destination then
|
||||
dpos = nodemeta:get("worldgate:destination")
|
||||
if not dpos then
|
||||
return true
|
||||
end
|
||||
destination = minetest.string_to_pos(dpos)
|
||||
do_worldgate_link = true
|
||||
else
|
||||
destination = vector.new(unhash_pos(destination))
|
||||
end
|
||||
|
||||
-- Look for players near this gate
|
||||
local players = minetest.get_connected_players()
|
||||
for i = 1, #players do
|
||||
-- If a player is found, then force-load the destination
|
||||
local player = players[i]
|
||||
if player and player:get_pos():in_area(pos:add(-32),pos:add(32)) then
|
||||
if not nodemeta:get("worldgate:player_nearby") then
|
||||
-- Define destination area to emerge
|
||||
local mapblock = destination:divide(16):floor():multiply(16)
|
||||
local emin = mapblock:add(vector.new(0,-32,0))
|
||||
local emax = mapblock:add(vector.new(0,47,0))
|
||||
|
||||
-- Emerge the destination mapblocks
|
||||
minetest.emerge_area(emin,emax,function(blockpos,action,calls_remaining)
|
||||
-- Do worldgate link to Telemosaic if defined for this gate
|
||||
if calls_remaining == 0 then
|
||||
if do_worldgate_link then
|
||||
destination = nil
|
||||
local beacons = minetest.find_nodes_in_area(emin:add(vector.new(-1,-1,-1)),emax:add(vector.new(1,1,1)),"group:telemosaic")
|
||||
for beacon = 1, #beacons do
|
||||
beacon = beacons[beacon]
|
||||
local spos = minetest.get_meta(beacon):get("worldgate:source")
|
||||
if dpos == spos then
|
||||
destination = beacon
|
||||
nodemeta:set_string("telemosaic:dest",hash_pos(beacon))
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if destination then
|
||||
-- Force-load destination mapblocks and own mapblock
|
||||
forceloader:load(pos:divide(16):floor())
|
||||
for p = -32, 32, 16 do
|
||||
forceloader:load(destination:add(vector.new(0,p,0)):divide(16):floor())
|
||||
end
|
||||
else
|
||||
-- Beacon cannot be linked
|
||||
minetest.swap_node(pos,{ name = "telemosaic:beacon_off", param2 = 0 })
|
||||
return false
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
-- Flag this beacon as having a player nearby
|
||||
nodemeta:set_string("worldgate:player_nearby","1")
|
||||
end
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
-- No players found, unload all force-loaded blocks and unflag the beacon
|
||||
if nodemeta:get("worldgate:player_nearby") then
|
||||
forceloader:unload(pos:divide(16):floor())
|
||||
for p = -32, 32, 16 do
|
||||
forceloader:unload(destination:add(vector.new(0,p,0)):divide(16):floor())
|
||||
end
|
||||
nodemeta:set_string("worldgate:player_nearby","")
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
-- Run linking function on node timer
|
||||
for _,beacon in ipairs({
|
||||
"telemosaic:beacon",
|
||||
"telemosaic:beacon_protected",
|
||||
}) do
|
||||
minetest.override_item(beacon,{
|
||||
on_timer = worldgate.link,
|
||||
})
|
||||
end
|
||||
|
||||
-- Queue for linking function calls
|
||||
local linkq = {}
|
||||
|
||||
-- Run linking function when a player teleports
|
||||
local tt = telemosaic.teleport
|
||||
telemosaic.teleport = function(player,src,dest)
|
||||
tt(player,src,dest)
|
||||
dest.y = dest.y - 1
|
||||
worldgate.link(vector.new(src))
|
||||
worldgate.link(vector.new(dest))
|
||||
end
|
||||
|
||||
-- Run linking function when a beacon changes its state
|
||||
local tss = telemosaic.set_state
|
||||
telemosaic.set_state = function(pos,state)
|
||||
tss(pos,state)
|
||||
worldgate.link(vector.new(pos))
|
||||
end
|
||||
|
||||
-- Register LBM to jump-start force-load timers
|
||||
minetest.register_abm({
|
||||
label = "Run worldgate linking function",
|
||||
nodenames = "group:telemosaic",
|
||||
interval = 3,
|
||||
chance = 1,
|
||||
catch_up = false,
|
||||
action = function(pos)
|
||||
worldgate.link(pos)
|
||||
end,
|
||||
})
|
9
mods/worldgate/src/logging.lua
Normal file
9
mods/worldgate/src/logging.lua
Normal file
|
@ -0,0 +1,9 @@
|
|||
-- Logging for successfully generated worldgates
|
||||
worldgate.reigster_on_worldgate_generated(function(pos,gate,strategy)
|
||||
minetest.log("action","Worldgate generated at " .. minetest.pos_to_string(pos) .. " using the " .. strategy .. " strategy")
|
||||
end)
|
||||
|
||||
-- Logging for worldgates that failed to generate
|
||||
worldgate.reigster_on_worldgate_failed(function(gate)
|
||||
minetest.log("warning","Worldgate failed to generate" .. (gate.exact and " at " or " near ") .. minetest.pos_to_string(gate.position))
|
||||
end)
|
301
mods/worldgate/src/mapgen.lua
Normal file
301
mods/worldgate/src/mapgen.lua
Normal file
|
@ -0,0 +1,301 @@
|
|||
--
|
||||
-- Worldgate mapgen
|
||||
--
|
||||
|
||||
-- Do not register mapgen if worldgate mapgen is disabled
|
||||
if not worldgate.settings.mapgen then
|
||||
return
|
||||
end
|
||||
|
||||
-- Spawning flags
|
||||
local underwaterspawn = worldgate.settings.underwaterspawn
|
||||
local midairspawn = worldgate.settings.midairspawn
|
||||
|
||||
-- Telemosaic location hashing function
|
||||
local function hash_pos(pos)
|
||||
return math.floor(pos.x + 0.5)..':'..
|
||||
math.floor(pos.y + 0.5)..':'..
|
||||
math.floor(pos.z + 0.5)
|
||||
end
|
||||
|
||||
-- Common cached variables and functions
|
||||
local vmcache = {} -- VoxelManip data cache, increases performance
|
||||
|
||||
local schematic_airspace = worldgate.modpath .. "/schematics/worldgate_airspace.mts"
|
||||
local schematic_platform = worldgate.modpath .. "/schematics/worldgate_platform.mts"
|
||||
|
||||
local extender_break_chance = worldgate.settings.breakage
|
||||
|
||||
local quality_selector = {
|
||||
[0] = function(pcgr) -- 25% chance for tier 1 extender to be cobblestone
|
||||
return { name = (pcgr:next(1,4) == 1 and "default:cobble" or "telemosaic:extender_one"), param2 = 0 }
|
||||
end,
|
||||
function() return { name = "telemosaic:extender_one", param2 = 0 } end,
|
||||
function() return { name = "telemosaic:extender_two", param2 = 0 } end,
|
||||
function() return { name = "telemosaic:extender_three", param2 = 0 } end,
|
||||
function() return { name = "telemosaic:extender_three", param2 = 0 } end,
|
||||
}
|
||||
|
||||
local water = {
|
||||
[minetest.get_content_id("mapgen_water_source")] = true,
|
||||
[minetest.get_content_id("mapgen_river_water_source")] = true,
|
||||
}
|
||||
|
||||
local vn = vector.new
|
||||
|
||||
-- Disallowed nodes to spawn on; no prefix means group
|
||||
local disallowed_nodes = {
|
||||
"leaves",
|
||||
"tree",
|
||||
}
|
||||
local disallowed_nodes_length = #disallowed_nodes
|
||||
local disallowed_cids = {[minetest.CONTENT_AIR] = true}
|
||||
|
||||
minetest.register_on_mods_loaded(function()
|
||||
for node,def in pairs(minetest.registered_nodes) do
|
||||
for i = 1, disallowed_nodes_length do
|
||||
i = disallowed_nodes[i]
|
||||
if node == i or minetest.get_item_group(node,i) > 0 then
|
||||
disallowed_cids[minetest.get_content_id(node)] = true
|
||||
end
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
-- Bricks to cobblestone map for quality degradation
|
||||
local bricks_list = {
|
||||
"default:stonebrick",
|
||||
"stairs:stair_stonebrick",
|
||||
"stairs:stair_inner_stonebrick",
|
||||
"stairs:stair_outer_stonebrick",
|
||||
"stairs:slab_stonebrick",
|
||||
}
|
||||
|
||||
local bricks_map = {
|
||||
["default:stonebrick"] = "default:cobble",
|
||||
["stairs:stair_stonebrick"] = "stairs:stair_cobble",
|
||||
["stairs:stair_inner_stonebrick"] = "stairs:stair_inner_cobble",
|
||||
["stairs:stair_outer_stonebrick"] = "stairs:stair_outer_cobble",
|
||||
["stairs:slab_stonebrick"] = "stairs:slab_cobble",
|
||||
}
|
||||
|
||||
local bricks_degrade_chance = {
|
||||
[-1] = 9,
|
||||
[0] = 42,
|
||||
[1] = 200,
|
||||
}
|
||||
|
||||
-- Worldgate mapgen function
|
||||
minetest.register_on_generated(function(minp,maxp,blockseed)
|
||||
-- Find all gates within the emerged area of the current mapchunk
|
||||
local gates = {}
|
||||
for x = 0, 4 do
|
||||
for y = 0, 4 do
|
||||
for z = 0, 4 do
|
||||
local hashed = worldgate.get_gates_for_mapblock(vn(minp.x + x * 16,minp.y + y * 16,minp.z + z * 16))
|
||||
for h = 1, #hashed do
|
||||
gates[#gates + 1] = hashed[h]
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if #gates == 0 then
|
||||
return -- no gates to generate
|
||||
end
|
||||
|
||||
-- Get LVM values
|
||||
local vm, emin, emax = minetest.get_mapgen_object("voxelmanip")
|
||||
local va = VoxelArea(emin,emax)
|
||||
local ystride = va.ystride
|
||||
local zstride = va.zstride
|
||||
|
||||
-- Generate the gates in this mapchunk, if any
|
||||
for gate = 1, #gates do
|
||||
gate = gates[gate]
|
||||
|
||||
-- Random number generator
|
||||
local pcgr = PcgRandom(minetest.hash_node_position(gate.position))
|
||||
|
||||
-- Define location variable
|
||||
local location = nil
|
||||
|
||||
-- Variable for tracking location selection strategy
|
||||
local strategy = nil
|
||||
|
||||
-- Set the exact position if gate is exact, else find a suitable location
|
||||
-- in the current mapchunk
|
||||
if gate.exact then
|
||||
location = gate.position
|
||||
strategy = "exact"
|
||||
else
|
||||
-- Load LVM data
|
||||
local vdata = vm:get_data(vmcache)
|
||||
|
||||
-- Constrain the area to +/- 2 vertical mapblocks for more consistent and
|
||||
-- deterministic mapgen
|
||||
local mapblock = gate.position:divide(16):floor():multiply(16)
|
||||
emin = mapblock:add(vn(0,-32,0))
|
||||
emax = mapblock:add(vn(0,47,0))
|
||||
|
||||
-- Function for indexing 2D heightmap array
|
||||
local function index2d(x,z) -- (portions of this function © FaceDeer 2018, licensed MIT, copied from https://github.com/minetest-mods/mapgen_helper/blob/2521562a42472271d9d761f2b1e84ead59250a14/noise_manager.lua)
|
||||
return x - minp.x +
|
||||
(maxp.x - minp.x + 1)
|
||||
*(z - minp.z)
|
||||
+ 1
|
||||
end
|
||||
|
||||
-- Probe heightmap for suitable location
|
||||
local heightmap = minetest.get_mapgen_object("heightmap") or {}
|
||||
for i = 1, 8 do
|
||||
local randomx = pcgr:next(emin.x,emax.x)
|
||||
local randomz = pcgr:next(emin.z,emax.z)
|
||||
local heightmapy = heightmap[index2d(randomx,randomz)]
|
||||
|
||||
if not heightmapy then
|
||||
goto retry_probe
|
||||
end
|
||||
|
||||
local pos = va:index(randomx,heightmapy,randomz)
|
||||
local cid = vdata[pos]
|
||||
local above = vdata[pos + ystride]
|
||||
|
||||
if cid and cid ~= minetest.CONTENT_AIR and cid ~= minetest.CONTENT_IGNORE and above and above ~= cid then
|
||||
-- Only spawn underwater if allowed
|
||||
if not underwaterspawn and (water[cid] or water[above]) then
|
||||
goto retry_probe
|
||||
end
|
||||
|
||||
-- Check for valid space above
|
||||
for ypos = pos + ystride * 2, pos + ystride * 10, ystride do
|
||||
local ydata = vdata[ypos]
|
||||
if not ydata or ydata == minetest.CONTENT_IGNORE or (not underwaterspawn and water[ydata]) then
|
||||
goto retry_probe
|
||||
end
|
||||
end
|
||||
|
||||
-- A valid location was found on the heightmap
|
||||
location = vn(randomx,heightmapy,randomz)
|
||||
strategy = "heightmap"
|
||||
break
|
||||
end
|
||||
::retry_probe::
|
||||
end
|
||||
|
||||
-- If no heightmap location found, then generate on a random node under air
|
||||
if not location then
|
||||
local air, nodecount = minetest.find_nodes_in_area(emin,emax,"air")
|
||||
local nair = nodecount.air
|
||||
for i = 1, math.min(nair,8) do
|
||||
local pos = va:indexp(air[pcgr:next(1,nair)])
|
||||
while disallowed_cids[vdata[pos]] do
|
||||
pos = pos - ystride -- probe downwards until we find something that isn't air
|
||||
end
|
||||
if vdata[pos] and vdata[pos] ~= minetest.CONTENT_IGNORE then
|
||||
location = va:position(pos)
|
||||
strategy = "grounded"
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- If mapchunk is completely solid or empty, then generate in a random location
|
||||
if not location then
|
||||
for i = 1, 8 do
|
||||
local randomx = pcgr:next(emin.x,emax.x)
|
||||
local randomy = pcgr:next(emin.y,emax.y)
|
||||
local randomz = pcgr:next(emin.z,emax.z)
|
||||
|
||||
-- Only spawn in midair or underwater if allowed
|
||||
local pos = va:indexp(vn(randomx,randomy,randomz))
|
||||
for ypos = pos, pos + ystride * 11, ystride do
|
||||
local ydata = vdata[ypos]
|
||||
if ydata and ydata ~= minetest.CONTENT_IGNORE and (underwaterspawn or not water[ydata]) and (ypos == pos and (midairspawn or ydata ~= minetest.CONTENT_AIR) or true) then
|
||||
location = va:position(pos)
|
||||
strategy = "random"
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Fail if no suitable location found
|
||||
if not location then
|
||||
-- Trigger failure callbacks
|
||||
for c = 1, #worldgate.worldgate_failed_callbacks do
|
||||
worldgate.worldgate_failed_callbacks[c](gate)
|
||||
end
|
||||
return -- cannot generate this worldgate
|
||||
end
|
||||
|
||||
-- Adjust location by y + 1
|
||||
location = location:add(vn(0,1,0))
|
||||
end
|
||||
|
||||
-- Place airspace
|
||||
minetest.place_schematic_on_vmanip(vm,location,schematic_airspace,"90",nil,true,"place_center_x,place_center_z")
|
||||
|
||||
-- Place platform
|
||||
minetest.place_schematic_on_vmanip(vm,location:add(vn(0,-8,0)),schematic_platform,"random",nil,true,"place_center_x,place_center_z")
|
||||
|
||||
-- Place base
|
||||
minetest.place_schematic_on_vmanip(vm,location,gate.base,"random",nil,false,"place_center_x,place_center_z")
|
||||
|
||||
-- Place decor
|
||||
minetest.place_schematic_on_vmanip(vm,location:add(vn(0,3,0)),gate.decor,"random",nil,false,"place_center_x,place_center_z")
|
||||
|
||||
-- Update liquids
|
||||
vm:update_liquids()
|
||||
|
||||
-- Write back to LVM
|
||||
vm:write_to_map()
|
||||
|
||||
-- Process extenders based on gate quality
|
||||
for _,epos in ipairs(minetest.find_nodes_in_area(location:add(vn(-6,0,-6)),location:add(vn(6,3,6)),"group:worldgate_extender")) do
|
||||
if pcgr:next(1,100) <= extender_break_chance then -- chance for any extender to be broken
|
||||
minetest.swap_node(epos,{ name = "default:cobble", param2 = 0 })
|
||||
else
|
||||
minetest.swap_node(epos,quality_selector[minetest.get_item_group(minetest.get_node(epos).name,"worldgate_extender") + gate.quality](pcgr))
|
||||
end
|
||||
end
|
||||
|
||||
-- Replace bricks with cobblestone based on gate quality
|
||||
local bricks = minetest.find_nodes_in_area(location:add(vn(-6,0,-6)),location:add(vn(6,13,6)),bricks_list)
|
||||
local brick_degrade_chance = bricks_degrade_chance[gate.quality]
|
||||
for _,brick in ipairs(bricks) do
|
||||
if pcgr:next(1,brick_degrade_chance) == 1 then
|
||||
local brick_node = minetest.get_node(brick)
|
||||
local cobble_node = bricks_map[brick_node.name]
|
||||
if cobble_node then
|
||||
minetest.swap_node(brick,{ name = cobble_node, param2 = brick_node.param2 })
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Write the gate's position to the beacon's node meta for linking purposes
|
||||
local beacon = (function()
|
||||
for dy = 2, 0, -1 do
|
||||
local beacon_location = location:add(vn(0,dy,0))
|
||||
local beacon_node = minetest.get_node(beacon_location)
|
||||
if beacon_node and beacon_node.name:find("^telemosaic:beacon") then
|
||||
return beacon_location
|
||||
end
|
||||
end
|
||||
end)()
|
||||
local nodemeta = minetest.get_meta(beacon)
|
||||
nodemeta:set_string("worldgate:source",minetest.pos_to_string(gate.position))
|
||||
if gate.destination then
|
||||
nodemeta:set_string("worldgate:destination",minetest.pos_to_string(gate.destination))
|
||||
minetest.swap_node(beacon,{ name = "telemosaic:beacon", param2 = 0 })
|
||||
end
|
||||
|
||||
-- Fix lighting
|
||||
minetest.fix_light(location:add(vn(-6,-8,-6)),location:add(vn(6,11,6)))
|
||||
|
||||
-- Trigger callbacks
|
||||
for c = 1, #worldgate.worldgate_generated_callbacks do
|
||||
worldgate.worldgate_generated_callbacks[c](location,gate,strategy)
|
||||
end
|
||||
end
|
||||
end)
|
31
mods/worldgate/src/nodes.lua
Normal file
31
mods/worldgate/src/nodes.lua
Normal file
|
@ -0,0 +1,31 @@
|
|||
--
|
||||
-- Worldgate structure nodes
|
||||
-- These get replaced with "real" nodes defined by games/mods/mapgen
|
||||
|
||||
for name,def in pairs({
|
||||
Extender1 = {
|
||||
color = "#00FF00",
|
||||
group = "worldgate_extender",
|
||||
group_value = 1,
|
||||
},
|
||||
Extender2 = {
|
||||
color = "#0000FF",
|
||||
group = "worldgate_extender",
|
||||
group_value = 2,
|
||||
},
|
||||
Extender3 = {
|
||||
color = "#FF00FF",
|
||||
group = "worldgate_extender",
|
||||
group_value = 3,
|
||||
},
|
||||
}) do
|
||||
minetest.register_node("worldgate:structure_" .. name:lower(),{
|
||||
description = "Worldgate Structure Node: " .. name,
|
||||
groups = {
|
||||
not_in_creative_inventory = 1,
|
||||
oddly_breakable_by_hand = 1,
|
||||
[def.group] = def.group_value,
|
||||
},
|
||||
color = def.color,
|
||||
})
|
||||
end
|
78
mods/worldgate/src/settings_overrides.lua
Normal file
78
mods/worldgate/src/settings_overrides.lua
Normal file
|
@ -0,0 +1,78 @@
|
|||
--
|
||||
-- Overrides for Telemosaic settings
|
||||
--
|
||||
|
||||
-- Give extenders a lot more range
|
||||
if worldgate.settings.superextenders then
|
||||
-- Global extender values
|
||||
telemosaic.extender_ranges = { 250, 750, 1500 }
|
||||
|
||||
-- Tier 1 extenders
|
||||
local tier1range = telemosaic.extender_ranges[1]
|
||||
local tier1groups = minetest.registered_nodes["telemosaic:extender_one"].groups
|
||||
tier1groups.telemosaic_extender = tier1range
|
||||
minetest.override_item("telemosaic:extender_one",{ groups = tier1groups })
|
||||
|
||||
-- Tier 2 extenders
|
||||
local tier2range = telemosaic.extender_ranges[2]
|
||||
local tier2groups = minetest.registered_nodes["telemosaic:extender_two"].groups
|
||||
tier2groups.telemosaic_extender = tier2range
|
||||
minetest.override_item("telemosaic:extender_two",{ groups = tier2groups })
|
||||
|
||||
-- Tier 3 extenders
|
||||
local tier3range = telemosaic.extender_ranges[3]
|
||||
local tier3groups = minetest.registered_nodes["telemosaic:extender_three"].groups
|
||||
tier3groups.telemosaic_extender = tier3range
|
||||
minetest.override_item("telemosaic:extender_three",{ groups = tier3groups })
|
||||
end
|
||||
|
||||
-- Implement a longer minimum delay for teleportation to prevent spamming and
|
||||
-- weirdness with loading/unloading mapblocks
|
||||
local min_delay = 5
|
||||
if telemosaic.teleport_delay < min_delay then
|
||||
telemosaic.teleport_delay = min_delay
|
||||
end
|
||||
|
||||
-- Override beacons to give off light if configured
|
||||
if worldgate.settings.beaconglow then
|
||||
for _,beacon in ipairs({
|
||||
"telemosaic:beacon",
|
||||
"telemosaic:beacon_protected",
|
||||
"telemosaic:beacon_err",
|
||||
"telemosaic:beacon_err_protected",
|
||||
}) do
|
||||
minetest.override_item(beacon,{
|
||||
light_source = 15,
|
||||
})
|
||||
end
|
||||
end
|
||||
|
||||
-- Override right-click function to consume mese crystal shards after use as a
|
||||
-- Telemosaic key, if configured
|
||||
if worldgate.settings.destroykeys then
|
||||
local trc = telemosaic.rightclick
|
||||
telemosaic.rightclick = function(pos, node, player, itemstack, pointed_thing)
|
||||
local item = itemstack:get_name()
|
||||
local returned_item = trc(pos, node, player, itemstack, pointed_thing)
|
||||
if item == "telemosaic:key" and returned_item:get_name() == "default:mese_crystal_fragment" then
|
||||
return ItemStack()
|
||||
else
|
||||
return returned_item
|
||||
end
|
||||
end
|
||||
|
||||
for _,beacon in ipairs({
|
||||
"telemosaic:beacon",
|
||||
"telemosaic:beacon_err",
|
||||
"telemosaic:beacon_disabled",
|
||||
"telemosaic:beacon_off",
|
||||
"telemosaic:beacon_protected",
|
||||
"telemosaic:beacon_err_protected",
|
||||
"telemosaic:beacon_disabled_protected",
|
||||
"telemosaic:beacon_off_protected",
|
||||
}) do
|
||||
minetest.override_item(beacon,{
|
||||
on_rightclick = telemosaic.rightclick
|
||||
})
|
||||
end
|
||||
end
|
Loading…
Add table
Add a link
Reference in a new issue