mirror of
https://github.com/OpenDiablo2/OpenDiablo2
synced 2024-11-18 02:16:23 -05:00
Removed Configuration interface (#560)
This commit is contained in:
parent
f7e0912f5f
commit
db5e844aac
40
d2app/app.go
40
d2app/app.go
@ -17,8 +17,6 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"golang.org/x/image/colornames"
|
|
||||||
|
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2common"
|
"github.com/OpenDiablo2/OpenDiablo2/d2common"
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2data"
|
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2data"
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2data/d2datadict"
|
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2data/d2datadict"
|
||||||
@ -34,7 +32,7 @@ import (
|
|||||||
"github.com/OpenDiablo2/OpenDiablo2/d2game/d2gamescreen"
|
"github.com/OpenDiablo2/OpenDiablo2/d2game/d2gamescreen"
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2script"
|
"github.com/OpenDiablo2/OpenDiablo2/d2script"
|
||||||
"github.com/pkg/profile"
|
"github.com/pkg/profile"
|
||||||
|
"golang.org/x/image/colornames"
|
||||||
"gopkg.in/alecthomas/kingpin.v2"
|
"gopkg.in/alecthomas/kingpin.v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -47,7 +45,6 @@ type App struct {
|
|||||||
captureState captureState
|
captureState captureState
|
||||||
capturePath string
|
capturePath string
|
||||||
captureFrames []*image.RGBA
|
captureFrames []*image.RGBA
|
||||||
profileOption string
|
|
||||||
gitBranch string
|
gitBranch string
|
||||||
gitCommit string
|
gitCommit string
|
||||||
terminal d2interface.Terminal
|
terminal d2interface.Terminal
|
||||||
@ -62,9 +59,12 @@ type bindTerminalEntry struct {
|
|||||||
action interface{}
|
action interface{}
|
||||||
}
|
}
|
||||||
|
|
||||||
const defaultFPS = 0.04 // 1/25
|
const (
|
||||||
const bytesToMegabyte = 1024 * 1024
|
defaultFPS = 0.04 // 1/25
|
||||||
const nSamplesTAlloc = 100
|
bytesToMegabyte = 1024 * 1024
|
||||||
|
nSamplesTAlloc = 100
|
||||||
|
debugPopN = 6
|
||||||
|
)
|
||||||
|
|
||||||
// Create creates a new instance of the application
|
// Create creates a new instance of the application
|
||||||
func Create(gitBranch, gitCommit string,
|
func Create(gitBranch, gitCommit string,
|
||||||
@ -84,7 +84,7 @@ func Create(gitBranch, gitCommit string,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Run executes the application and kicks off the entire game process
|
// Run executes the application and kicks off the entire game process
|
||||||
func (p *App) Run() {
|
func (p *App) Run() error {
|
||||||
profileOption := kingpin.Flag("profile", "Profiles the program, one of (cpu, mem, block, goroutine, trace, thread, mutex)").String()
|
profileOption := kingpin.Flag("profile", "Profiles the program, one of (cpu, mem, block, goroutine, trace, thread, mutex)").String()
|
||||||
kingpin.Parse()
|
kingpin.Parse()
|
||||||
|
|
||||||
@ -99,12 +99,10 @@ func (p *App) Run() {
|
|||||||
// If we fail to initialize, we will show the error screen
|
// If we fail to initialize, we will show the error screen
|
||||||
if err := p.initialize(); err != nil {
|
if err := p.initialize(); err != nil {
|
||||||
if gameErr := p.renderer.Run(updateInitError, 800, 600, windowTitle); gameErr != nil {
|
if gameErr := p.renderer.Run(updateInitError, 800, 600, windowTitle); gameErr != nil {
|
||||||
log.Fatal(gameErr)
|
return gameErr
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Fatal(err)
|
return err
|
||||||
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
d2screen.SetNextScreen(d2gamescreen.CreateMainMenu(p.renderer, p.audio, p.terminal))
|
d2screen.SetNextScreen(d2gamescreen.CreateMainMenu(p.renderer, p.audio, p.terminal))
|
||||||
@ -116,8 +114,10 @@ func (p *App) Run() {
|
|||||||
d2common.SetBuildInfo(p.gitBranch, p.gitCommit)
|
d2common.SetBuildInfo(p.gitBranch, p.gitCommit)
|
||||||
|
|
||||||
if err := p.renderer.Run(p.update, 800, 600, windowTitle); err != nil {
|
if err := p.renderer.Run(p.update, 800, 600, windowTitle); err != nil {
|
||||||
log.Panic(err)
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *App) initialize() error {
|
func (p *App) initialize() error {
|
||||||
@ -125,12 +125,8 @@ func (p *App) initialize() error {
|
|||||||
p.lastTime = d2common.Now()
|
p.lastTime = d2common.Now()
|
||||||
p.lastScreenAdvance = p.lastTime
|
p.lastScreenAdvance = p.lastTime
|
||||||
|
|
||||||
if err := d2config.Load(); err != nil {
|
config := d2config.Config
|
||||||
return err
|
d2resource.LanguageCode = config.Language
|
||||||
}
|
|
||||||
|
|
||||||
config := d2config.Get()
|
|
||||||
d2resource.LanguageCode = config.Language()
|
|
||||||
|
|
||||||
p.renderer.SetWindowIcon("d2logo.png")
|
p.renderer.SetWindowIcon("d2logo.png")
|
||||||
p.terminal.BindLogger()
|
p.terminal.BindLogger()
|
||||||
@ -164,7 +160,7 @@ func (p *App) initialize() error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
p.audio.SetVolumes(config.BgmVolume(), config.SfxVolume())
|
p.audio.SetVolumes(config.BgmVolume, config.SfxVolume)
|
||||||
|
|
||||||
if err := p.loadDataDict(); err != nil {
|
if err := p.loadDataDict(); err != nil {
|
||||||
return err
|
return err
|
||||||
@ -280,7 +276,7 @@ func (p *App) renderDebug(target d2interface.Surface) error {
|
|||||||
target.DrawText("NumGC " + strconv.FormatInt(int64(m.NumGC), 10))
|
target.DrawText("NumGC " + strconv.FormatInt(int64(m.NumGC), 10))
|
||||||
target.PushTranslation(0, 16)
|
target.PushTranslation(0, 16)
|
||||||
target.DrawText("Coords " + strconv.FormatInt(int64(cx), 10) + "," + strconv.FormatInt(int64(cy), 10))
|
target.DrawText("Coords " + strconv.FormatInt(int64(cx), 10) + "," + strconv.FormatInt(int64(cy), 10))
|
||||||
target.PopN(6) //nolint:gomnd This is the number of records we have popped
|
target.PopN(debugPopN)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -584,7 +580,7 @@ func updateInitError(target d2interface.Surface) error {
|
|||||||
|
|
||||||
target.PushTranslation(width/5, height/2)
|
target.PushTranslation(width/5, height/2)
|
||||||
target.DrawText(`Could not find the MPQ files in the directory:
|
target.DrawText(`Could not find the MPQ files in the directory:
|
||||||
%s\nPlease put the files and re-run the game.`, d2config.Get().MpqPath())
|
%s\nPlease put the files and re-run the game.`, d2config.Config.MpqPath)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -1,21 +0,0 @@
|
|||||||
package d2interface
|
|
||||||
|
|
||||||
// Configuration saves, loads, and returns the OpenDiablo2
|
|
||||||
// configuration. This is either loaded from disk, or generated
|
|
||||||
// when one is not found.
|
|
||||||
type Configuration interface {
|
|
||||||
Load() error
|
|
||||||
Save() error
|
|
||||||
// Get() Configuration
|
|
||||||
MpqLoadOrder() []string
|
|
||||||
Language() string
|
|
||||||
MpqPath() string
|
|
||||||
TicksPerSecond() int
|
|
||||||
FpsCap() int
|
|
||||||
SfxVolume() float64
|
|
||||||
BgmVolume() float64
|
|
||||||
FullScreen() bool
|
|
||||||
RunInBackground() bool
|
|
||||||
VsyncEnabled() bool
|
|
||||||
Backend() string
|
|
||||||
}
|
|
@ -5,15 +5,15 @@ import (
|
|||||||
"path"
|
"path"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
|
|
||||||
|
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2common"
|
"github.com/OpenDiablo2/OpenDiablo2/d2common"
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2fileformats/d2mpq"
|
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2fileformats/d2mpq"
|
||||||
|
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
|
||||||
|
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2config"
|
||||||
)
|
)
|
||||||
|
|
||||||
type archiveManager struct {
|
type archiveManager struct {
|
||||||
cache d2interface.Cache
|
cache d2interface.Cache
|
||||||
config d2interface.Configuration
|
config *d2config.Configuration
|
||||||
archives []d2interface.Archive
|
archives []d2interface.Archive
|
||||||
mutex sync.Mutex
|
mutex sync.Mutex
|
||||||
}
|
}
|
||||||
@ -22,7 +22,7 @@ const (
|
|||||||
archiveBudget = 1024 * 1024 * 512
|
archiveBudget = 1024 * 1024 * 512
|
||||||
)
|
)
|
||||||
|
|
||||||
func createArchiveManager(config d2interface.Configuration) d2interface.ArchiveManager {
|
func createArchiveManager(config *d2config.Configuration) d2interface.ArchiveManager {
|
||||||
return &archiveManager{cache: d2common.CreateCache(archiveBudget), config: config}
|
return &archiveManager{cache: d2common.CreateCache(archiveBudget), config: config}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -85,14 +85,14 @@ func (am *archiveManager) LoadArchive(archivePath string) (d2interface.Archive,
|
|||||||
|
|
||||||
// CacheArchiveEntries updates the archive entries
|
// CacheArchiveEntries updates the archive entries
|
||||||
func (am *archiveManager) CacheArchiveEntries() error {
|
func (am *archiveManager) CacheArchiveEntries() error {
|
||||||
if len(am.archives) == len(am.config.MpqLoadOrder()) {
|
if len(am.archives) == len(am.config.MpqLoadOrder) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
am.archives = nil
|
am.archives = nil
|
||||||
|
|
||||||
for _, archiveName := range am.config.MpqLoadOrder() {
|
for _, archiveName := range am.config.MpqLoadOrder {
|
||||||
archivePath := path.Join(am.config.MpqPath(), archiveName)
|
archivePath := path.Join(am.config.MpqPath, archiveName)
|
||||||
|
|
||||||
archive, err := am.LoadArchive(archivePath)
|
archive, err := am.LoadArchive(archivePath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -1,11 +1,12 @@
|
|||||||
package d2asset
|
package d2asset
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
|
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2common"
|
"github.com/OpenDiablo2/OpenDiablo2/d2common"
|
||||||
|
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2resource"
|
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2resource"
|
||||||
|
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2config"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -15,10 +16,10 @@ const (
|
|||||||
type fileManager struct {
|
type fileManager struct {
|
||||||
cache d2interface.Cache
|
cache d2interface.Cache
|
||||||
archiveManager d2interface.ArchiveManager
|
archiveManager d2interface.ArchiveManager
|
||||||
config d2interface.Configuration
|
config *d2config.Configuration
|
||||||
}
|
}
|
||||||
|
|
||||||
func createFileManager(config d2interface.Configuration,
|
func createFileManager(config *d2config.Configuration,
|
||||||
archiveManager d2interface.ArchiveManager) d2interface.ArchivedFileManager {
|
archiveManager d2interface.ArchiveManager) d2interface.ArchivedFileManager {
|
||||||
return &fileManager{
|
return &fileManager{
|
||||||
d2common.CreateCache(fileBudget),
|
d2common.CreateCache(fileBudget),
|
||||||
@ -90,7 +91,7 @@ func (fm *fileManager) removeLocaleTokens(filePath string) string {
|
|||||||
tableToken := d2resource.LanguageTableToken
|
tableToken := d2resource.LanguageTableToken
|
||||||
fontToken := d2resource.LanguageFontToken
|
fontToken := d2resource.LanguageFontToken
|
||||||
|
|
||||||
filePath = strings.ReplaceAll(filePath, tableToken, fm.config.Language())
|
filePath = strings.ReplaceAll(filePath, tableToken, fm.config.Language)
|
||||||
|
|
||||||
// fixme: not all languages==latin
|
// fixme: not all languages==latin
|
||||||
filePath = strings.ReplaceAll(filePath, fontToken, "latin")
|
filePath = strings.ReplaceAll(filePath, fontToken, "latin")
|
||||||
|
@ -1,22 +1,21 @@
|
|||||||
package d2asset
|
package d2asset
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2config"
|
|
||||||
"log"
|
"log"
|
||||||
|
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum"
|
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum"
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
|
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
|
||||||
|
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2config"
|
||||||
)
|
)
|
||||||
|
|
||||||
var singleton *assetManager
|
var singleton *assetManager //nolint:gochecknoglobals // Currently global by design
|
||||||
|
|
||||||
// Initialize creates and assigns all necessary dependencies for the assetManager top-level functions to work correctly
|
// Initialize creates and assigns all necessary dependencies for the assetManager top-level functions to work correctly
|
||||||
func Initialize(renderer d2interface.Renderer,
|
func Initialize(renderer d2interface.Renderer,
|
||||||
term d2interface.Terminal) error {
|
term d2interface.Terminal) error {
|
||||||
var (
|
var (
|
||||||
config = d2config.Get()
|
archiveManager = createArchiveManager(d2config.Config)
|
||||||
archiveManager = createArchiveManager(config)
|
archivedFileManager = createFileManager(d2config.Config, archiveManager)
|
||||||
archivedFileManager = createFileManager(config, archiveManager)
|
|
||||||
paletteManager = createPaletteManager()
|
paletteManager = createPaletteManager()
|
||||||
paletteTransformManager = createPaletteTransformManager()
|
paletteTransformManager = createPaletteTransformManager()
|
||||||
animationManager = createAnimationManager(renderer)
|
animationManager = createAnimationManager(renderer)
|
||||||
|
@ -1,194 +0,0 @@
|
|||||||
package d2config
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"io/ioutil"
|
|
||||||
"os"
|
|
||||||
"os/user"
|
|
||||||
"path"
|
|
||||||
"runtime"
|
|
||||||
)
|
|
||||||
|
|
||||||
const defaultSfxVolume = 1.0
|
|
||||||
const defaultBgmVolume = 0.3
|
|
||||||
|
|
||||||
func getDefaultConfig() *Configuration {
|
|
||||||
config := &Configuration{
|
|
||||||
language: "ENG",
|
|
||||||
fullScreen: false,
|
|
||||||
ticksPerSecond: -1,
|
|
||||||
runInBackground: true,
|
|
||||||
vsyncEnabled: true,
|
|
||||||
sfxVolume: defaultSfxVolume,
|
|
||||||
bgmVolume: defaultBgmVolume,
|
|
||||||
mpqPath: "C:/Program Files (x86)/Diablo II",
|
|
||||||
backend: "Ebiten",
|
|
||||||
mpqLoadOrder: []string{
|
|
||||||
"Patch_D2.mpq",
|
|
||||||
"d2exp.mpq",
|
|
||||||
"d2xmusic.mpq",
|
|
||||||
"d2xtalk.mpq",
|
|
||||||
"d2xvideo.mpq",
|
|
||||||
"d2data.mpq",
|
|
||||||
"d2char.mpq",
|
|
||||||
"d2music.mpq",
|
|
||||||
"d2sfx.mpq",
|
|
||||||
"d2video.mpq",
|
|
||||||
"d2speech.mpq",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
switch runtime.GOOS {
|
|
||||||
case "windows":
|
|
||||||
if runtime.GOARCH == "386" {
|
|
||||||
config.mpqPath = "C:/Program Files/Diablo II"
|
|
||||||
}
|
|
||||||
case "darwin":
|
|
||||||
config.mpqPath = "/Applications/Diablo II/"
|
|
||||||
config.mpqLoadOrder = []string{
|
|
||||||
"Diablo II Patch",
|
|
||||||
"Diablo II Expansion Data",
|
|
||||||
"Diablo II Expansion Movies",
|
|
||||||
"Diablo II Expansion Music",
|
|
||||||
"Diablo II Expansion Speech",
|
|
||||||
"Diablo II Game Data",
|
|
||||||
"Diablo II Graphics",
|
|
||||||
"Diablo II Movies",
|
|
||||||
"Diablo II Music",
|
|
||||||
"Diablo II Sounds",
|
|
||||||
"Diablo II Speech",
|
|
||||||
}
|
|
||||||
case "linux":
|
|
||||||
if usr, err := user.Current(); err == nil {
|
|
||||||
config.mpqPath = path.Join(usr.HomeDir, ".wine/drive_c/Program Files (x86)/Diablo II")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return config
|
|
||||||
}
|
|
||||||
|
|
||||||
func getDefaultConfigPath() string {
|
|
||||||
if configDir, err := os.UserConfigDir(); err == nil {
|
|
||||||
return path.Join(configDir, "OpenDiablo2", "config.json")
|
|
||||||
}
|
|
||||||
|
|
||||||
return getLocalConfigPath()
|
|
||||||
}
|
|
||||||
|
|
||||||
func getLocalConfigPath() string {
|
|
||||||
return path.Join(path.Dir(os.Args[0]), "config.json")
|
|
||||||
}
|
|
||||||
|
|
||||||
func load(configPath string) error {
|
|
||||||
configFile, err := os.Open(configPath) //nolint:gosec will fix the security error later
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
data, err := ioutil.ReadAll(configFile)
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := unmarshalIntoInterface(data); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
err = configFile.Close()
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func unmarshalIntoInterface(d []byte) error {
|
|
||||||
tmp := &hack{} // an empty concrete implementation
|
|
||||||
if err := json.Unmarshal(d, tmp); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
tmp2cfg(tmp, singleton) // transfer tmp values to singleton
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO figure out a way to unmarshal into an interface
|
|
||||||
type hack struct{
|
|
||||||
MpqLoadOrder []string
|
|
||||||
Language string
|
|
||||||
MpqPath string
|
|
||||||
TicksPerSecond int
|
|
||||||
FpsCap int
|
|
||||||
SfxVolume float64
|
|
||||||
BgmVolume float64
|
|
||||||
FullScreen bool
|
|
||||||
RunInBackground bool
|
|
||||||
VsyncEnabled bool
|
|
||||||
Backend string
|
|
||||||
}
|
|
||||||
|
|
||||||
func cfg2tmp (a *Configuration, b *hack) {
|
|
||||||
b.MpqLoadOrder = a.mpqLoadOrder
|
|
||||||
b.Language = a.language
|
|
||||||
b.MpqPath = a.mpqPath
|
|
||||||
b.TicksPerSecond = a.ticksPerSecond
|
|
||||||
b.FpsCap = a.fpsCap
|
|
||||||
b.SfxVolume = a.sfxVolume
|
|
||||||
b.BgmVolume = a.bgmVolume
|
|
||||||
b.FullScreen = a.fullScreen
|
|
||||||
b.RunInBackground = a.runInBackground
|
|
||||||
b.VsyncEnabled = a.vsyncEnabled
|
|
||||||
b.Backend = a.backend
|
|
||||||
}
|
|
||||||
|
|
||||||
func tmp2cfg (b *hack, a *Configuration) {
|
|
||||||
a.mpqLoadOrder = b.MpqLoadOrder
|
|
||||||
a.language = b.Language
|
|
||||||
a.mpqPath = b.MpqPath
|
|
||||||
a.ticksPerSecond = b.TicksPerSecond
|
|
||||||
a.fpsCap = b.FpsCap
|
|
||||||
a.sfxVolume = b.SfxVolume
|
|
||||||
a.bgmVolume = b.BgmVolume
|
|
||||||
a.fullScreen = b.FullScreen
|
|
||||||
a.runInBackground = b.RunInBackground
|
|
||||||
a.vsyncEnabled = b.VsyncEnabled
|
|
||||||
a.backend = b.Backend
|
|
||||||
}
|
|
||||||
|
|
||||||
func save(configPath string) error {
|
|
||||||
configDir := path.Dir(configPath)
|
|
||||||
|
|
||||||
if err := os.MkdirAll(configDir, 0750); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
configFile, err := os.Create(configPath)
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
tmp := &hack{}
|
|
||||||
cfg2tmp(singleton, tmp)
|
|
||||||
data, err := json.MarshalIndent(tmp, "", " ")
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if _, writeErr := configFile.Write(data); writeErr != nil {
|
|
||||||
return writeErr
|
|
||||||
}
|
|
||||||
|
|
||||||
err = configFile.Close()
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
@ -1,106 +1,108 @@
|
|||||||
package d2config
|
package d2config
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/json"
|
||||||
"log"
|
"log"
|
||||||
|
"os"
|
||||||
|
"path"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Config holds the configuration from config.json
|
||||||
|
var Config *Configuration //nolint:gochecknoglobals // Currently global by design
|
||||||
|
|
||||||
// Configuration defines the configuration for the engine, loaded from config.json
|
// Configuration defines the configuration for the engine, loaded from config.json
|
||||||
type Configuration struct {
|
type Configuration struct {
|
||||||
mpqLoadOrder []string
|
MpqLoadOrder []string
|
||||||
language string
|
Language string
|
||||||
mpqPath string
|
MpqPath string
|
||||||
ticksPerSecond int
|
TicksPerSecond int
|
||||||
fpsCap int
|
FpsCap int
|
||||||
sfxVolume float64
|
SfxVolume float64
|
||||||
bgmVolume float64
|
BgmVolume float64
|
||||||
fullScreen bool
|
FullScreen bool
|
||||||
runInBackground bool
|
RunInBackground bool
|
||||||
vsyncEnabled bool
|
VsyncEnabled bool
|
||||||
backend string
|
Backend string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Configuration) MpqLoadOrder() []string {
|
// Load loads a configuration object from disk
|
||||||
return c.mpqLoadOrder
|
func Load() error {
|
||||||
}
|
Config = new(Configuration)
|
||||||
|
return Config.Load()
|
||||||
func (c *Configuration) Language() string {
|
|
||||||
return c.language
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Configuration) MpqPath() string {
|
|
||||||
return c.mpqPath
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Configuration) TicksPerSecond() int {
|
|
||||||
return c.ticksPerSecond
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Configuration) FpsCap() int {
|
|
||||||
return c.fpsCap
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Configuration) SfxVolume() float64 {
|
|
||||||
return c.sfxVolume
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Configuration) BgmVolume() float64 {
|
|
||||||
return c.bgmVolume
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Configuration) FullScreen() bool {
|
|
||||||
return c.fullScreen
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Configuration) RunInBackground() bool {
|
|
||||||
return c.runInBackground
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Configuration) VsyncEnabled() bool {
|
|
||||||
return c.vsyncEnabled
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Configuration) Backend() string {
|
|
||||||
return c.backend
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load loads a configuration object from disk
|
// Load loads a configuration object from disk
|
||||||
func (c *Configuration) Load() error {
|
func (c *Configuration) Load() error {
|
||||||
configPaths := []string{
|
configPaths := []string{
|
||||||
getDefaultConfigPath(),
|
defaultConfigPath(),
|
||||||
getLocalConfigPath(),
|
localConfigPath(),
|
||||||
}
|
}
|
||||||
|
|
||||||
var loaded bool
|
|
||||||
|
|
||||||
for _, configPath := range configPaths {
|
for _, configPath := range configPaths {
|
||||||
log.Printf("loading configuration file from %s...", configPath)
|
log.Printf("loading configuration file from %s...", configPath)
|
||||||
|
|
||||||
if err := load(configPath); err == nil {
|
if _, err := os.Stat(configPath); os.IsNotExist(err) {
|
||||||
loaded = true
|
continue
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if !loaded {
|
configFile, err := os.Open(path.Clean(configPath))
|
||||||
log.Println("failed to load configuration file, saving default configuration...")
|
if err != nil {
|
||||||
|
|
||||||
if err := Save(); err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if err := json.NewDecoder(configFile).Decode(&Config); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := configFile.Close(); err != nil {
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
log.Println("failed to load configuration file, saving default configuration...")
|
||||||
|
|
||||||
|
Config = defaultConfig()
|
||||||
|
|
||||||
|
return Config.Save()
|
||||||
|
}
|
||||||
|
|
||||||
// Save saves the configuration object to disk
|
// Save saves the configuration object to disk
|
||||||
func (c *Configuration) Save() error {
|
func (c *Configuration) Save() error {
|
||||||
configPath := getDefaultConfigPath()
|
configPath := defaultConfigPath()
|
||||||
log.Printf("saving configuration file to %s...", configPath)
|
log.Printf("saving configuration file to %s...", configPath)
|
||||||
|
|
||||||
var err error
|
configDir := path.Dir(configPath)
|
||||||
if err = save(configPath); err != nil {
|
if err := os.MkdirAll(configDir, 0750); err != nil {
|
||||||
log.Printf("failed to write configuration file (%s)", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
configFile, err := os.Create(configPath)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
buf, err := json.MarshalIndent(Config, "", " ")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err := configFile.Write(buf); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return configFile.Close()
|
||||||
|
}
|
||||||
|
|
||||||
|
func defaultConfigPath() string {
|
||||||
|
if configDir, err := os.UserConfigDir(); err == nil {
|
||||||
|
return path.Join(configDir, "OpenDiablo2", "config.json")
|
||||||
|
}
|
||||||
|
|
||||||
|
return localConfigPath()
|
||||||
|
}
|
||||||
|
|
||||||
|
func localConfigPath() string {
|
||||||
|
return path.Join(path.Dir(os.Args[0]), "config.json")
|
||||||
|
}
|
||||||
|
67
d2core/d2config/defaults.go
Normal file
67
d2core/d2config/defaults.go
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
package d2config
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os/user"
|
||||||
|
"path"
|
||||||
|
"runtime"
|
||||||
|
)
|
||||||
|
|
||||||
|
func defaultConfig() *Configuration {
|
||||||
|
const (
|
||||||
|
defaultSfxVolume = 1.0
|
||||||
|
defaultBgmVolume = 0.3
|
||||||
|
)
|
||||||
|
|
||||||
|
config := &Configuration{
|
||||||
|
Language: "ENG",
|
||||||
|
FullScreen: false,
|
||||||
|
TicksPerSecond: -1,
|
||||||
|
RunInBackground: true,
|
||||||
|
VsyncEnabled: true,
|
||||||
|
SfxVolume: defaultSfxVolume,
|
||||||
|
BgmVolume: defaultBgmVolume,
|
||||||
|
MpqPath: "C:/Program Files (x86)/Diablo II",
|
||||||
|
Backend: "Ebiten",
|
||||||
|
MpqLoadOrder: []string{
|
||||||
|
"Patch_D2.mpq",
|
||||||
|
"d2exp.mpq",
|
||||||
|
"d2xmusic.mpq",
|
||||||
|
"d2xtalk.mpq",
|
||||||
|
"d2xvideo.mpq",
|
||||||
|
"d2data.mpq",
|
||||||
|
"d2char.mpq",
|
||||||
|
"d2music.mpq",
|
||||||
|
"d2sfx.mpq",
|
||||||
|
"d2video.mpq",
|
||||||
|
"d2speech.mpq",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
switch runtime.GOOS {
|
||||||
|
case "windows":
|
||||||
|
if runtime.GOARCH == "386" {
|
||||||
|
config.MpqPath = "C:/Program Files/Diablo II"
|
||||||
|
}
|
||||||
|
case "darwin":
|
||||||
|
config.MpqPath = "/Applications/Diablo II/"
|
||||||
|
config.MpqLoadOrder = []string{
|
||||||
|
"Diablo II Patch",
|
||||||
|
"Diablo II Expansion Data",
|
||||||
|
"Diablo II Expansion Movies",
|
||||||
|
"Diablo II Expansion Music",
|
||||||
|
"Diablo II Expansion Speech",
|
||||||
|
"Diablo II Game Data",
|
||||||
|
"Diablo II Graphics",
|
||||||
|
"Diablo II Movies",
|
||||||
|
"Diablo II Music",
|
||||||
|
"Diablo II Sounds",
|
||||||
|
"Diablo II Speech",
|
||||||
|
}
|
||||||
|
case "linux":
|
||||||
|
if usr, err := user.Current(); err == nil {
|
||||||
|
config.MpqPath = path.Join(usr.HomeDir, ".wine/drive_c/Program Files (x86)/Diablo II")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return config
|
||||||
|
}
|
@ -1,22 +0,0 @@
|
|||||||
package d2config
|
|
||||||
|
|
||||||
import "github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
|
|
||||||
|
|
||||||
// TODO remove this shit
|
|
||||||
|
|
||||||
var singleton = getDefaultConfig()
|
|
||||||
|
|
||||||
// Load loads a configuration object from disk
|
|
||||||
func Load() error {
|
|
||||||
return singleton.Load()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Save saves the configuration object to disk
|
|
||||||
func Save() error {
|
|
||||||
return singleton.Save()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get returns a configuration object
|
|
||||||
func Get() d2interface.Configuration {
|
|
||||||
return singleton
|
|
||||||
}
|
|
@ -1,15 +1,13 @@
|
|||||||
package ebiten
|
package ebiten
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum"
|
|
||||||
"image"
|
"image"
|
||||||
|
|
||||||
|
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum"
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
|
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
|
||||||
|
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2config"
|
||||||
"github.com/hajimehoshi/ebiten"
|
"github.com/hajimehoshi/ebiten"
|
||||||
"github.com/hajimehoshi/ebiten/ebitenutil"
|
"github.com/hajimehoshi/ebiten/ebitenutil"
|
||||||
|
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2config"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type Renderer struct {
|
type Renderer struct {
|
||||||
@ -31,13 +29,12 @@ func (r *Renderer) Layout(outsideWidth, outsideHeight int) (screenWidth, screenH
|
|||||||
func CreateRenderer() (*Renderer, error) {
|
func CreateRenderer() (*Renderer, error) {
|
||||||
result := &Renderer{}
|
result := &Renderer{}
|
||||||
|
|
||||||
config := d2config.Get()
|
config := d2config.Config
|
||||||
|
|
||||||
ebiten.SetCursorMode(ebiten.CursorModeHidden)
|
ebiten.SetCursorMode(ebiten.CursorModeHidden)
|
||||||
ebiten.SetFullscreen(config.FullScreen())
|
ebiten.SetFullscreen(config.FullScreen)
|
||||||
ebiten.SetRunnableOnUnfocused(config.RunInBackground())
|
ebiten.SetRunnableOnUnfocused(config.RunInBackground)
|
||||||
ebiten.SetVsyncEnabled(config.VsyncEnabled())
|
ebiten.SetVsyncEnabled(config.VsyncEnabled)
|
||||||
ebiten.SetMaxTPS(config.TicksPerSecond())
|
ebiten.SetMaxTPS(config.TicksPerSecond)
|
||||||
|
|
||||||
return result, nil
|
return result, nil
|
||||||
}
|
}
|
||||||
|
14
main.go
14
main.go
@ -3,13 +3,11 @@ package main
|
|||||||
import (
|
import (
|
||||||
"log"
|
"log"
|
||||||
|
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2render/ebiten"
|
|
||||||
|
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2app"
|
"github.com/OpenDiablo2/OpenDiablo2/d2app"
|
||||||
|
|
||||||
ebiten2 "github.com/OpenDiablo2/OpenDiablo2/d2core/d2audio/ebiten"
|
ebiten2 "github.com/OpenDiablo2/OpenDiablo2/d2core/d2audio/ebiten"
|
||||||
|
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2config"
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2input"
|
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2input"
|
||||||
|
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2render/ebiten"
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2term"
|
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2term"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -25,6 +23,10 @@ func main() {
|
|||||||
log.SetFlags(log.Lshortfile)
|
log.SetFlags(log.Lshortfile)
|
||||||
log.Println("OpenDiablo2 - Open source Diablo 2 engine")
|
log.Println("OpenDiablo2 - Open source Diablo 2 engine")
|
||||||
|
|
||||||
|
if err := d2config.Load(); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
// Initialize our providers
|
// Initialize our providers
|
||||||
renderer, err := ebiten.CreateRenderer()
|
renderer, err := ebiten.CreateRenderer()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -44,5 +46,7 @@ func main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
app := d2app.Create(GitBranch, GitCommit, term, audio, renderer)
|
app := d2app.Create(GitBranch, GitCommit, term, audio, renderer)
|
||||||
app.Run()
|
if err := app.Run(); err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user