Skip to content
This repository was archived by the owner on Dec 13, 2023. It is now read-only.

Commit

Permalink
Data restructuring and add preload error screen
Browse files Browse the repository at this point in the history
  • Loading branch information
cookta2012 committed Jan 10, 2022
1 parent 1799a38 commit 720db7c
Show file tree
Hide file tree
Showing 21 changed files with 319 additions and 114 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -61,4 +61,6 @@ dkms.conf
d2*.mpq
*_d2.mpq
mpqs/extracted/
DATA/MPQ-D2/extracted/
tags
/.disable*
File renamed without changes.
File renamed without changes.
1 change: 1 addition & 0 deletions DATA/MPQ-D2/.loadorder
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
patch_d2.mpq,d2exp.mpq,d2xmusic.mpq,d2xtalk.mpq,d2xvideo.mpq,d2data.mpq,d2char.mpq,d2music.mpq,d2sfx.mpq,d2video.mpq,d2speech.mpq
1 change: 1 addition & 0 deletions DATA/README
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Place the *d2*.mpq files in the MPQ-D2 folder.
142 changes: 114 additions & 28 deletions bootstrap.lua
Original file line number Diff line number Diff line change
Expand Up @@ -21,47 +21,134 @@ require 'common/globals'
-- Create load providers for all of the available MPQs and CASCs
------------------------------------------------------------------------------------------------------------------------

local cascs = Split(abyss.getConfig("OpenDiablo2", "CASCs"), ",")
for i in pairs(cascs) do
abyss.log("info", string.format("Loading CASC %s...", cascs[i]))
pcall(function()
abyss.addLoaderProvider("casc", cascs[i])
end)
end
local function loadGameData()
local baseDataDir = abyss.getConfig("OpenDiablo2", "BASE_DATA_DIR")

local casc, mpq

local function loadBaseCASC()
local errored = false
local missingCASCs = {}
local erroredCASCs = {}

if abyss.fileExists(".disableCASC") then
local missingText = "D2R CASC LOADING DISABLED BY FILE: .disableCASC"
return { loaded = false, data={missing = {missingText}, errored = erroredCASCs} }
end

local cascs = Split(abyss.getConfig("OpenDiablo2", "CASCs"), ",")
for _, _casc in ipairs(cascs) do
abyss.log("info", string.format("Loading CASC %s...", baseDataDir .. "/" .. _casc))
local loaded = pcall(function()
abyss.addLoaderProvider("casc", baseDataDir .. "/" .. _casc)
end)
if not loaded then
abyss.log("error", string.format("Possible corrupt or missing CASC: %s", baseDataDir .. "/" .. _casc))
table.insert(erroredCASCs, baseDataDir .. "/" .. _casc)
errored = true
end
end
return {loaded = not errored, data={missing = missingCASCs, errored = erroredCASCs}}
end

local function loadBaseMPQs()
local errored = false
local toLoadMPQs = {}
local missingMPQs = {}
local erroredMPQs = {}

if abyss.fileExists(".disableMPQ") then
local missingText = "MPQ LOADING DISABLED BY FILE: .disableMPQ"
return { loaded = false, data={missing = {missingText}, errored = erroredMPQs} }
end

local mpqFolderNames = Split(abyss.getConfig("OpenDiablo2", "MPQs"), ",")

for i in pairs(mpqFolderNames) do
local mpqPath = baseDataDir .. "/" .. mpqFolderNames[i]
local mpqLoadOrderFileName = mpqPath .. "/" .. ".loadorder"
local file = io.open (mpqLoadOrderFileName, "r")
local fileData = file:read("a")
file:close()
local mpqFiles = Split(fileData, ",")
for _, mpqFile in ipairs(mpqFiles) do
if file_exists(mpqPath .. "/" .. mpqFile) then
table.insert(toLoadMPQs,mpqPath .. "/" .. mpqFile)
else
table.insert(missingMPQs, mpqPath .. "/" .. mpqFile)
errored = true
end
end
end

-- If no files are missing then really load them
for _, _mpq in ipairs(toLoadMPQs) do
local mpqPath = baseDataDir .. "/" .. _mpq
local loadStr = string.format("Loading MPQ %s...", _mpq)
abyss.log("info", loadStr)
local loaded = pcall(function() abyss.addLoaderProvider("mpq", _mpq) end)
if not loaded then
table.insert(erroredMPQs, _mpq)
abyss.log("error", string.format("Possible corrupt MPQ: %s", _mpq))
errored = true
end
end
local result = {loaded = not errored, data={ missing = missingMPQs, errored = erroredMPQs}}
return result
end

abyss.addLoaderProvider("filesystem", "./fallback-data")
abyss.addLoaderProvider("filesystem", "./DATA/FS-fallback")
casc = loadBaseCASC()
mpq = loadBaseMPQs()

local mpqs = Split(abyss.getConfig("OpenDiablo2", "MPQs"), ",")
for i in pairs(mpqs) do
local mpqPath = MPQRoot .. "/" .. mpqs[i]
local loadStr = string.format("Loading MPQ %s...", mpqPath)
abyss.log("info", loadStr)
pcall(function()
abyss.addLoaderProvider("mpq", mpqPath)
end)
local resultData = { missing = {}, errored = {}}
for _,obj in ipairs(casc.data.missing) do table.insert(resultData.missing, obj) end
for _,obj in ipairs(casc.data.errored) do table.insert(resultData.errored, obj) end
for _,obj in ipairs(mpq.data.missing) do table.insert(resultData.missing, obj) end
for _,obj in ipairs(mpq.data.errored) do table.insert(resultData.errored, obj) end

return casc.loaded or mpq.loaded, {message = resultData}
end

------------------------------------------------------------------------------------------------------------------------
-- Load in all of the palettes
------------------------------------------------------------------------------------------------------------------------
for _, name in ipairs(ResourceDefs.Palettes) do
local lineLog = string.format("Loading Palette: %s...", name[1])
abyss.log("info", lineLog)
abyss.createPalette(name[1], name[2]) end
local function loadPalettes()
for _, name in ipairs(ResourceDefs.Palettes) do
local lineLog = string.format("Loading Palette: %s...", name[1])
abyss.log("info", lineLog)
abyss.createPalette(name[1], name[2])
end
end

------------------------------------------------------------------------------------------------------------------------
-- Detect the language
------------------------------------------------------------------------------------------------------------------------
local configLanguageCode = abyss.getConfig("OpenDiablo2", "Language")
local function detectLanguage()
local configLanguageCode = abyss.getConfig("OpenDiablo2", "Language")

if configLanguageCode ~= "auto" then
Language:setLanguage(configLanguageCode)
else
Language:autoDetect()
if configLanguageCode ~= "auto" then
Language:setLanguage(configLanguageCode)
else
Language:autoDetect()
end

abyss.log("info", "System language has been set to " .. Language:name() or '<invalid>' .. ".")
end

abyss.log("info", "System language has been set to " .. or_else(Language:name(), '<invalid>') .. ".")
------------------------------------------------------------------------------------------------------------------------
-- Actually load everything
------------------------------------------------------------------------------------------------------------------------

local loaded, data = loadGameData()
if not loaded then
local ErrorScreen = require("screens/internal-error")
data.header = "Crash"
ErrorScreen:new(data)
return
end
loadPalettes()
detectLanguage()

------------------------------------------------------------------------------------------------------------------------
-- Load the global objects
Expand All @@ -72,8 +159,7 @@ LoadGlobals()
------------------------------------------------------------------------------------------------------------------------
-- Play Startup Videos
------------------------------------------------------------------------------------------------------------------------

function StartGame()
local function StartGame()
abyss.setCursor(CursorSprite, 1, -24)
abyss.showSystemCursor(true)
SetScreen(Screen.MAIN_MENU)
Expand Down
2 changes: 1 addition & 1 deletion common/globals.lua
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
print = function (message) abyss.log("info", message); end;
require ('common/util')
require ('common/ui')
require ('screens/screens')
Expand All @@ -7,7 +8,6 @@ MusicDefs = require('common/enum/music')
RegionDefs = require('common/enum/region')
ResourceDefs = require("common/enum/resource")
BasePath = abyss.getConfig("#Abyss", "BasePath")
MPQRoot = abyss.getConfig("OpenDiablo2", "MPQRoot")
IsOnButton = false
ShowTrademarkScreen = true

Expand Down
27 changes: 27 additions & 0 deletions common/interface/label.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
local Label = {}
local Node = require("common/interface/node")
Label.__index = Label


function Label:new(data)
local this = Node:new(data)
function this:setAlignment(alignment)
alignment = alignment or {"start", "start"}
self.node:setAlignment(alignment[1],alignment[2])
end
local parent = data.parent
local font = data.font
local caption = data.caption
local alignment = data.alignment
local position = data.position
this.node = abyss.createLabel(font)
this:setPosition{position[1], position[2]}
this.node.caption = caption
this:setAlignment{alignment[1], alignment[2]}
table.insert(parent.data, this.node)
parent:appendChild(this.node)
setmetatable(Label, Label)
return this
end

return Label
18 changes: 18 additions & 0 deletions common/interface/node.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
local Node = {}
Node.__index = Node

function Node:new(data)
local this = {}
function Node:setPosition(position)
position = position or {0, 0}
this.node:setPosition( math.floor(position[1]), math.floor(position[2]) )
end
if data.node ~= nil and type(data.node) == "userdata" then
this.node = data.node
return this
end
setmetatable(this, self)
return this
end

return Node
2 changes: 1 addition & 1 deletion common/layout.lua
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ LayoutLoader.__index = LayoutLoader
function LayoutLoader:new()
local this = {}
setmetatable(this, self)
self:initialize()
this:initialize() -- Init the _new_ loader not the parent object
return this
end

Expand Down
26 changes: 16 additions & 10 deletions common/util.lua
Original file line number Diff line number Diff line change
Expand Up @@ -116,17 +116,23 @@ function or_else(x, y)
return x
end

function file_exists(name)
local f=io.open(name,"r")
if f~=nil then io.close(f) return true else return false end
end


function dump(o)
if type(o) == 'table' then
local s = '{ '
for k,v in pairs(o) do
if type(k) ~= 'number' then k = '"'..k..'"' end
s = s .. '['..k..'] = ' .. dump(v) .. ','
end
return s .. '} '
else
return tostring(o)
end
if type(o) == 'table' then
local s = '{ '
for k,v in pairs(o) do
if type(k) ~= 'number' then k = '"'..k..'"' end
s = s .. '['..k..'] = ' .. dump(v) .. ','
end
return s .. '} '
else
return tostring(o)
end
end

function dumplayout()
Expand Down
5 changes: 3 additions & 2 deletions config.ini
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,9 @@ BackgroundMusicVolume=0.75
LuaGCRateMsecs=256

[OpenDiablo2]
MPQs=patch_d2.mpq,d2exp.mpq,d2xmusic.mpq,d2xtalk.mpq,d2xvideo.mpq,d2data.mpq,d2char.mpq,d2music.mpq,d2sfx.mpq,d2video.mpq,d2speech.mpq
CASCs=./D2RData
BASE_DATA_DIR=./DATA
MPQs=MPQ-D2
CASCs=CASC-D2R
; Language can be one of enUS, deDE, esES, esMX, frFR, itIT, jaJP, koKR, plPL, ptBR, ruRU, zhCN, zhTW, depending on which MPQs you have.
; You can set it to 'auto', and language will be detected automatically depending on the files present.
Language=auto
Expand Down
1 change: 0 additions & 1 deletion mpqs/README

This file was deleted.

Loading

0 comments on commit 720db7c

Please sign in to comment.