321 lines
9.8 KiB
Lua
321 lines
9.8 KiB
Lua
lotj = lotj or {}
|
|
lotj.galaxyMap = lotj.galaxyMap or {
|
|
data = {
|
|
labelAsPlanets = true,
|
|
systems = {},
|
|
planets = {},
|
|
govToColor = {
|
|
["Neutral Government"] = "#AAAAAA",
|
|
},
|
|
}
|
|
}
|
|
|
|
local dataFileName = getMudletHomeDir().."/galaxyMap"
|
|
function lotj.galaxyMap.setup()
|
|
lotj.galaxyMap.container = Geyser.Label:new({
|
|
name = "galaxy",
|
|
x = 0, y = 0,
|
|
width = "100%",
|
|
height = "100%",
|
|
}, lotj.layout.upperRightTabData.contents["galaxy"])
|
|
lotj.galaxyMap.container:setBackgroundImage(getMudletHomeDir().."/@PKGNAME@/space.jpg")
|
|
-- This seems necessary when recreating the UI after upgrading the package.
|
|
lotj.galaxyMap.container:raiseAll()
|
|
|
|
lotj.galaxyMap.refreshButton = Geyser.Label:new({
|
|
name = "galaxyMapRefresh",
|
|
x = "20%", y = "35%",
|
|
width = "60%", height = 40,
|
|
}, lotj.galaxyMap.container)
|
|
lotj.galaxyMap.refreshButton:setStyleSheet([[
|
|
background-color: grey;
|
|
border: 1px solid white;
|
|
]])
|
|
lotj.galaxyMap.refreshButton:echo("Click here to populate this map.", "white", "c14")
|
|
lotj.galaxyMap.refreshButton:setClickCallback(function()
|
|
expandAlias("gmap refresh", false)
|
|
end)
|
|
|
|
disableTrigger("galaxy-map-refresh")
|
|
if io.exists(dataFileName) then
|
|
table.load(dataFileName, lotj.galaxyMap.data)
|
|
lotj.galaxyMap.log("Loaded map data.")
|
|
lotj.galaxyMap.drawSystems()
|
|
end
|
|
|
|
lotj.setup.registerEventHandler("gmcp.Ship.System", lotj.galaxyMap.setShipGalCoords)
|
|
end
|
|
|
|
|
|
function lotj.galaxyMap.log(text)
|
|
cecho("[<cyan>LOTJ Galaxy Map<reset>] "..text.."\n")
|
|
end
|
|
|
|
function lotj.galaxyMap.setShipGalCoords()
|
|
if not gmcp.Ship then return end
|
|
if gmcp.Ship.System.x ~= nil and gmcp.Ship.System.y ~= nil then
|
|
lotj.galaxyMap.currentX = gmcp.Ship.System.x
|
|
lotj.galaxyMap.currentY = gmcp.Ship.System.y
|
|
lotj.galaxyMap.drawSystems()
|
|
end
|
|
end
|
|
|
|
local function container()
|
|
return lotj.galaxyMap.container
|
|
end
|
|
|
|
-- Fire off any showplanet commands we still need to run to load data for all known planets
|
|
function lotj.galaxyMap.enqueuePendingRefreshCommands()
|
|
for planet in pairs(gatherPlanetsState.pendingBasic) do
|
|
send("showplanet \""..planet.."\"", false)
|
|
gatherPlanetsState.pendingCommands = gatherPlanetsState.pendingCommands + 1
|
|
end
|
|
for planet in pairs(gatherPlanetsState.pendingResources) do
|
|
send("showplanet \""..planet.."\" resources", false)
|
|
gatherPlanetsState.pendingCommands = gatherPlanetsState.pendingCommands + 1
|
|
end
|
|
|
|
-- We didn't have to retry any, so we're done getting info.
|
|
if gatherPlanetsState.pendingCommands == 0 then
|
|
disableTrigger("galaxy-map-refresh")
|
|
return
|
|
end
|
|
|
|
echo("\n")
|
|
lotj.galaxyMap.log("Enqueueing "..gatherPlanetsState.pendingCommands.." showplanet commands.")
|
|
end
|
|
|
|
function lotj.galaxyMap.resetData()
|
|
lotj.galaxyMap.data.planets = {}
|
|
lotj.galaxyMap.data.systems = {}
|
|
end
|
|
|
|
local govColorIdx = 1
|
|
local govColorList = {}
|
|
table.insert(govColorList, "#E69F00")
|
|
table.insert(govColorList, "#56B4E9")
|
|
table.insert(govColorList, "#009E73")
|
|
table.insert(govColorList, "#F0E442")
|
|
table.insert(govColorList, "#D55E00")
|
|
table.insert(govColorList, "#CC79A7")
|
|
|
|
function lotj.galaxyMap.recordSystem(name, x, y)
|
|
lotj.galaxyMap.data.systems = lotj.galaxyMap.data.systems or {}
|
|
lotj.galaxyMap.data.systems[name] = {
|
|
name = name,
|
|
planets = {},
|
|
gov = "Neutral Government",
|
|
x = x,
|
|
y = y,
|
|
}
|
|
table.save(dataFileName, lotj.galaxyMap.data)
|
|
|
|
lotj.galaxyMap.drawSystems()
|
|
end
|
|
|
|
function lotj.galaxyMap.recordPlanet(planetData)
|
|
if not lotj.galaxyMap.data.planets[planetData.name] then
|
|
lotj.galaxyMap.data.planets[planetData.name] = {
|
|
name = planetData.name,
|
|
gov = planetData.gov,
|
|
system = planetData.system,
|
|
}
|
|
|
|
local system = lotj.galaxyMap.data.systems[planetData.system]
|
|
if system ~= nil then
|
|
system.gov = planetData.gov
|
|
table.insert(system.planets, planetData.name)
|
|
else
|
|
lotj.galaxyMap.log("Unable to find system "..planetData.system.." for planet "..planetData.name)
|
|
end
|
|
|
|
if lotj.galaxyMap.data.govToColor[planetData.gov] == nil then
|
|
govColorIdx = govColorIdx+1
|
|
lotj.galaxyMap.data.govToColor[planetData.gov] = govColorList[govColorIdx]
|
|
end
|
|
end
|
|
|
|
if planetData.coords ~= nil then
|
|
lotj.galaxyMap.data.planets[planetData.name].coords = planetData.coords
|
|
end
|
|
if planetData.freeport ~= nil then
|
|
lotj.galaxyMap.data.planets[planetData.name].freeport = planetData.freeport
|
|
end
|
|
if planetData.taxRate ~= nil then
|
|
lotj.galaxyMap.data.planets[planetData.name].taxRate = planetData.taxRate
|
|
end
|
|
if planetData.resources ~= nil then
|
|
lotj.galaxyMap.data.planets[planetData.name].resources = planetData.resources
|
|
end
|
|
|
|
table.save(dataFileName, lotj.galaxyMap.data)
|
|
|
|
lotj.galaxyMap.drawSystems()
|
|
end
|
|
|
|
local systemPointSize = 14
|
|
local function stylePoint(point, gov, currentSystem)
|
|
local backgroundColor = lotj.galaxyMap.data.govToColor[gov] or "#AAAAAA"
|
|
local borderStyle = ""
|
|
if currentSystem then
|
|
borderStyle = "border: 2px solid red;"
|
|
end
|
|
point:setStyleSheet([[
|
|
border-radius: ]]..math.floor(systemPointSize/2)..[[px;
|
|
background-color: ]]..backgroundColor..[[;
|
|
]]..borderStyle..[[
|
|
]])
|
|
end
|
|
|
|
local function systemDisplayName(system)
|
|
if lotj.galaxyMap.data.labelAsPlanets and #(system.planets or {}) > 0 then
|
|
local labelString = ""
|
|
for _, planet in ipairs(system.planets) do
|
|
if #labelString > 0 then
|
|
labelString = labelString..", "
|
|
end
|
|
labelString = labelString..planet
|
|
end
|
|
return labelString
|
|
else
|
|
-- Cut off common extra words from the system name to keep labels short
|
|
local labelString = system.name
|
|
labelString = string.gsub(labelString, " System$", "")
|
|
labelString = string.gsub(labelString, " Sector$", "")
|
|
return labelString
|
|
end
|
|
end
|
|
|
|
function lotj.galaxyMap.drawSystems()
|
|
local minX, _, _, maxY = lotj.galaxyMap.coordRange()
|
|
local xOffset, yOffset, pxPerCoord = lotj.galaxyMap.calculateSizing()
|
|
|
|
lotj.galaxyMap.systemPoints = lotj.galaxyMap.systemPoints or {}
|
|
for _, point in pairs(lotj.galaxyMap.systemPoints) do
|
|
point:hide()
|
|
end
|
|
|
|
lotj.galaxyMap.systemLabels = lotj.galaxyMap.systemLabels or {}
|
|
for _, label in pairs(lotj.galaxyMap.systemLabels) do
|
|
label:hide()
|
|
end
|
|
|
|
|
|
local foundCurrentLocation = false
|
|
local systemsToDraw = {}
|
|
for _, system in pairs(lotj.galaxyMap.data.systems) do
|
|
table.insert(systemsToDraw, system)
|
|
if system.x == lotj.galaxyMap.currentX and system.y == lotj.galaxyMap.currentY then
|
|
foundCurrentLocation = true
|
|
end
|
|
end
|
|
if not foundCurrentLocation and lotj.galaxyMap.currentX and lotj.galaxyMap.currentY then
|
|
table.insert(systemsToDraw, {
|
|
name = "Current",
|
|
x = lotj.galaxyMap.currentX,
|
|
y = lotj.galaxyMap.currentY
|
|
})
|
|
end
|
|
|
|
-- Hide or show the refresh button accordingly, based on whether we have any data.
|
|
if #systemsToDraw > 0 then
|
|
lotj.galaxyMap.refreshButton:hide()
|
|
else
|
|
lotj.galaxyMap.refreshButton:show()
|
|
end
|
|
|
|
for _, system in ipairs(systemsToDraw) do
|
|
local point = lotj.galaxyMap.systemPoints[system.name]
|
|
if point == nil then
|
|
point = Geyser.Label:new({width=systemPointSize, height=systemPointSize}, container())
|
|
stylePoint(point, system.gov, false)
|
|
lotj.galaxyMap.systemPoints[system.name] = point
|
|
else
|
|
point:show()
|
|
end
|
|
|
|
local label = lotj.galaxyMap.systemLabels[system.name]
|
|
if label == nil then
|
|
label = Geyser.Label:new({
|
|
height = 16, width = 100,
|
|
fillBg = 0,
|
|
}, container())
|
|
|
|
lotj.galaxyMap.systemLabels[system.name] = label
|
|
else
|
|
label:show()
|
|
end
|
|
label:echo(systemDisplayName(system), "white", "12c")
|
|
|
|
local sysX = math.floor(xOffset + (system.x-minX)*pxPerCoord - systemPointSize/2 + 0.5)
|
|
local sysY = math.floor(yOffset + (maxY-system.y)*pxPerCoord - systemPointSize/2 + 0.5)
|
|
point:move(sysX, sysY)
|
|
if system.x == lotj.galaxyMap.currentX and system.y == lotj.galaxyMap.currentY then
|
|
stylePoint(point, system.gov, true)
|
|
else
|
|
stylePoint(point, system.gov, false)
|
|
end
|
|
|
|
label:move(math.max(sysX-45, 0), sysY+systemPointSize)
|
|
end
|
|
end
|
|
|
|
-- Returns X starting point, Y starting point, and pixels per coordinate
|
|
function lotj.galaxyMap.calculateSizing()
|
|
local minX, maxX, minY, maxY = lotj.galaxyMap.coordRange()
|
|
local xRange = maxX-minX
|
|
local yRange = maxY-minY
|
|
local contWidth = container():get_width()
|
|
local contHeight = container():get_height()
|
|
|
|
-- Determine whether the map would be limited by height or width first.
|
|
local mapWidth = nil
|
|
local mapHeight = nil
|
|
local pxPerCoord = nil
|
|
local pxHeightIfLimitedByWidth = (contWidth/xRange)*yRange
|
|
local pxWidthIfLimitedByHeight = (contHeight/yRange)*xRange
|
|
if pxHeightIfLimitedByWidth <= contHeight then
|
|
-- Width was the limiting factor, so use it to determine sizing
|
|
mapWidth = contWidth
|
|
mapHeight = pxHeightIfLimitedByWidth
|
|
pxPerCoord = contWidth/xRange
|
|
elseif pxWidthIfLimitedByHeight <= contWidth then
|
|
-- Width was the limiting factor, so use it to determine sizing
|
|
mapWidth = pxWidthIfLimitedByHeight
|
|
mapHeight = contHeight
|
|
pxPerCoord = contHeight/yRange
|
|
else
|
|
echo("Unable to determine appropriate galaxy map dimensions. This is a script bug.\n")
|
|
end
|
|
|
|
local mapAnchorX = (contWidth-mapWidth)/2
|
|
local mapAnchorY = (contHeight-mapHeight)/2
|
|
|
|
return mapAnchorX, mapAnchorY, pxPerCoord
|
|
end
|
|
|
|
function lotj.galaxyMap.coordRange()
|
|
local minX = 0
|
|
local maxX = 0
|
|
local minY = 0
|
|
local maxY = 0
|
|
|
|
for _, system in pairs(lotj.galaxyMap.data.systems) do
|
|
if minX > system.x then
|
|
minX = system.x
|
|
end
|
|
if maxX < system.x then
|
|
maxX = system.x
|
|
end
|
|
if minY > system.y then
|
|
minY = system.y
|
|
end
|
|
if maxY < system.y then
|
|
maxY = system.y
|
|
end
|
|
end
|
|
|
|
-- Pad all values by 10 to ensure points are displayed reasonably.
|
|
return minX-10, maxX+10, minY-10, maxY+10
|
|
end
|