1
1
mirror of https://github.com/OpenDiablo2/OpenDiablo2 synced 2024-06-04 15:00:42 +00:00

abstracted d2config to an interface (still have a singleton, though) (#538)

This commit is contained in:
dk 2020-07-03 21:49:16 -07:00 committed by GitHub
parent 3757ff1ac5
commit cf35285b48
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 205 additions and 70 deletions

View File

@ -130,7 +130,7 @@ func (p *App) initialize() error {
}
config := d2config.Get()
d2resource.LanguageCode = config.Language
d2resource.LanguageCode = config.Language()
p.renderer.SetWindowIcon("d2logo.png")
p.terminal.BindLogger()
@ -164,7 +164,7 @@ func (p *App) initialize() error {
return err
}
p.audio.SetVolumes(config.BgmVolume, config.SfxVolume)
p.audio.SetVolumes(config.BgmVolume(), config.SfxVolume())
if err := p.loadDataDict(); err != nil {
return err
@ -583,7 +583,8 @@ func updateInitError(target d2interface.Surface) error {
width, height := target.GetSize()
target.PushTranslation(width/5, height/2)
target.DrawText("Could not find the MPQ files in the directory: %s\nPlease put the files and re-run the game.", d2config.Get().MpqPath)
target.DrawText(`Could not find the MPQ files in the directory:
%s\nPlease put the files and re-run the game.`, d2config.Get().MpqPath())
return nil
}

View File

@ -0,0 +1,21 @@
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
}

View File

@ -2,13 +2,12 @@ package d2asset
import (
"errors"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
"path"
"sync"
"github.com/OpenDiablo2/OpenDiablo2/d2common"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2fileformats/d2mpq"
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2config"
)
type archiveEntry struct {
@ -18,7 +17,7 @@ type archiveEntry struct {
type archiveManager struct {
cache d2interface.Cache
config *d2config.Configuration
config d2interface.Configuration
entries []archiveEntry
mutex sync.Mutex
}
@ -27,7 +26,7 @@ const (
archiveBudget = 1024 * 1024 * 512
)
func createArchiveManager(config *d2config.Configuration) *archiveManager {
func createArchiveManager(config d2interface.Configuration) *archiveManager {
return &archiveManager{cache: d2common.CreateCache(archiveBudget), config: config}
}
@ -86,14 +85,14 @@ func (am *archiveManager) loadArchive(archivePath string) (*d2mpq.MPQ, error) {
}
func (am *archiveManager) cacheArchiveEntries() error {
if len(am.entries) == len(am.config.MpqLoadOrder) {
if len(am.entries) == len(am.config.MpqLoadOrder()) {
return nil
}
am.entries = nil
for _, archiveName := range am.config.MpqLoadOrder {
archivePath := path.Join(am.config.MpqPath, archiveName)
for _, archiveName := range am.config.MpqLoadOrder() {
archivePath := path.Join(am.config.MpqPath(), archiveName)
archive, err := am.loadArchive(archivePath)
if err != nil {

View File

@ -1,24 +1,24 @@
package d2asset
import (
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2config"
"log"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2fileformats/d2dat"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2fileformats/d2mpq"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2config"
)
var singleton *assetManager
// Initialize creates and assigns all necessary dependencies for the assetManager top-level functions to work correctly
func Initialize(renderer d2interface.Renderer, term d2interface.Terminal) error {
func Initialize(renderer d2interface.Renderer,
term d2interface.Terminal) error {
var (
config = d2config.Get()
archiveManager = createArchiveManager(&config)
fileManager = createFileManager(&config, archiveManager)
archiveManager = createArchiveManager(config)
fileManager = createFileManager(config, archiveManager)
paletteManager = createPaletteManager()
paletteTransformManager = createPaletteTransformManager()
animationManager = createAnimationManager(renderer)
@ -51,12 +51,8 @@ func Initialize(renderer d2interface.Renderer, term d2interface.Terminal) error
}
if err := term.BindAction("assetstat", "display asset manager cache statistics", func() {
type cache interface {
GetWeight() int
GetBudget() int
}
var cacheStatistics = func(c cache) float64 {
var cacheStatistics = func(c d2interface.Cache) float64 {
const percent = 100.0
return float64(c.GetWeight()) / float64(c.GetBudget()) * percent
}

View File

@ -7,7 +7,6 @@ import (
"github.com/OpenDiablo2/OpenDiablo2/d2common"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2resource"
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2config"
)
const (
@ -17,11 +16,16 @@ const (
type fileManager struct {
cache d2interface.Cache
archiveManager *archiveManager
config *d2config.Configuration
config d2interface.Configuration
}
func createFileManager(config *d2config.Configuration, archiveManager *archiveManager) *fileManager {
return &fileManager{d2common.CreateCache(fileBudget), archiveManager, config}
func createFileManager(config d2interface.Configuration,
archiveManager *archiveManager) *fileManager {
return &fileManager{
d2common.CreateCache(fileBudget),
archiveManager,
config,
}
}
func (fm *fileManager) loadFileStream(filePath string) (*d2mpq.MpqDataStream, error) {
@ -76,7 +80,7 @@ func (fm *fileManager) removeLocaleTokens(filePath string) string {
tableToken := d2resource.LanguageTableToken
fontToken := d2resource.LanguageFontToken
filePath = strings.ReplaceAll(filePath, tableToken, fm.config.Language)
filePath = strings.ReplaceAll(filePath, tableToken, fm.config.Language())
// fixme: not all languages==latin
filePath = strings.ReplaceAll(filePath, fontToken, "latin")

View File

@ -14,16 +14,16 @@ 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{
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",
@ -41,11 +41,11 @@ func getDefaultConfig() *Configuration {
switch runtime.GOOS {
case "windows":
if runtime.GOARCH == "386" {
config.MpqPath = "C:/Program Files/Diablo II"
config.mpqPath = "C:/Program Files/Diablo II"
}
case "darwin":
config.MpqPath = "/Applications/Diablo II/"
config.MpqLoadOrder = []string{
config.mpqPath = "/Applications/Diablo II/"
config.mpqLoadOrder = []string{
"Diablo II Patch",
"Diablo II Expansion Data",
"Diablo II Expansion Movies",
@ -60,7 +60,7 @@ func getDefaultConfig() *Configuration {
}
case "linux":
if usr, err := user.Current(); err == nil {
config.MpqPath = path.Join(usr.HomeDir, ".wine/drive_c/Program Files (x86)/Diablo II")
config.mpqPath = path.Join(usr.HomeDir, ".wine/drive_c/Program Files (x86)/Diablo II")
}
}
@ -92,7 +92,7 @@ func load(configPath string) error {
return err
}
if err = json.Unmarshal(data, &singleton); err != nil {
if err := unmarshalIntoInterface(data); err != nil {
return err
}
@ -105,6 +105,60 @@ func load(configPath string) error {
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)
@ -118,14 +172,16 @@ func save(configPath string) error {
return err
}
data, err := json.MarshalIndent(singleton, "", " ")
tmp := &hack{}
cfg2tmp(singleton, tmp)
data, err := json.MarshalIndent(tmp, "", " ")
if err != nil {
return err
}
if _, err := configFile.Write(data); err != nil {
return err
if _, writeErr := configFile.Write(data); writeErr != nil {
return writeErr
}
err = configFile.Close()

View File

@ -6,25 +6,68 @@ import (
// Configuration defines the configuration for the engine, loaded from config.json
type Configuration struct {
MpqLoadOrder []string
Language string
MpqPath string
TicksPerSecond int
FpsCap int
SfxVolume float64
BgmVolume float64
FullScreen bool
RunInBackground bool
VsyncEnabled bool
Backend string
mpqLoadOrder []string
language string
mpqPath string
ticksPerSecond int
fpsCap int
sfxVolume float64
bgmVolume float64
fullScreen bool
runInBackground bool
vsyncEnabled bool
backend string
}
var singleton = getDefaultConfig()
func (c *Configuration) MpqLoadOrder() []string {
return c.mpqLoadOrder
}
func Load() error {
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
func (c *Configuration) Load() error {
configPaths := []string{
getLocalConfigPath(),
getDefaultConfigPath(),
getLocalConfigPath(),
}
var loaded bool
@ -49,7 +92,8 @@ func Load() error {
return nil
}
func Save() error {
// Save saves the configuration object to disk
func (c *Configuration) Save() error {
configPath := getDefaultConfigPath()
log.Printf("saving configuration file to %s...", configPath)
@ -60,11 +104,3 @@ func Save() error {
return err
}
func Get() Configuration {
if singleton == nil {
panic("configuration is not initialized")
}
return *singleton
}

View File

@ -0,0 +1,22 @@
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
}

View File

@ -33,10 +33,10 @@ func CreateRenderer() (*Renderer, error) {
config := d2config.Get()
ebiten.SetCursorMode(ebiten.CursorModeHidden)
ebiten.SetFullscreen(config.FullScreen)
ebiten.SetRunnableOnUnfocused(config.RunInBackground)
ebiten.SetVsyncEnabled(config.VsyncEnabled)
ebiten.SetMaxTPS(config.TicksPerSecond)
ebiten.SetFullscreen(config.FullScreen())
ebiten.SetRunnableOnUnfocused(config.RunInBackground())
ebiten.SetVsyncEnabled(config.VsyncEnabled())
ebiten.SetMaxTPS(config.TicksPerSecond())
return result, nil
}