mirror of
https://github.com/OpenDiablo2/OpenDiablo2
synced 2024-09-06 11:34:15 -04:00
681 lines
22 KiB
Go
681 lines
22 KiB
Go
// Package d2gamescreen contains the screens
|
|
package d2gamescreen
|
|
|
|
import (
|
|
"fmt"
|
|
"net"
|
|
"os"
|
|
"os/exec"
|
|
"runtime"
|
|
"strings"
|
|
|
|
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2hero"
|
|
|
|
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum"
|
|
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
|
|
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2resource"
|
|
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2util"
|
|
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2asset"
|
|
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2screen"
|
|
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2ui"
|
|
"github.com/OpenDiablo2/OpenDiablo2/d2networking/d2client/d2clientconnectiontype"
|
|
"github.com/OpenDiablo2/OpenDiablo2/d2script"
|
|
)
|
|
|
|
type mainMenuScreenMode int
|
|
|
|
// mainMenuScreenMode types
|
|
const (
|
|
ScreenModeUnknown mainMenuScreenMode = iota
|
|
ScreenModeTrademark
|
|
ScreenModeMainMenu
|
|
ScreenModeMultiplayer
|
|
ScreenModeTCPIP
|
|
ScreenModeServerIP
|
|
)
|
|
|
|
const (
|
|
joinGameDialogX, joinGameDialogY = 318, 245
|
|
serverIPbackgroundX, serverIPbackgroundY = 270, 175
|
|
backgroundX, backgroundY = 0, 0
|
|
versionLabelX, versionLabelY = 795, -10
|
|
commitLabelX, commitLabelY = 2, 2
|
|
copyrightX, copyrightY = 400, 500
|
|
copyright2X, copyright2Y = 400, 525
|
|
od2LabelX, od2LabelY = 400, 580
|
|
tcpOptionsX, tcpOptionsY = 400, 23
|
|
joinGameX, joinGameY = 400, 190
|
|
diabloLogoX, diabloLogoY = 400, 120
|
|
exitDiabloBtnX, exitDiabloBtnY = 264, 535
|
|
creditBtnX, creditBtnY = 264, 505
|
|
cineBtnX, cineBtnY = 401, 505
|
|
singlePlayerBtnX, singlePlayerBtnY = 264, 290
|
|
githubBtnX, githubBtnY = 264, 400
|
|
mapTestBtnX, mapTestBtnY = 264, 440
|
|
tcpBtnX, tcpBtnY = 33, 543
|
|
srvCancelBtnX, srvCancelBtnY = 285, 305
|
|
srvOkBtnX, srvOkBtnY = 420, 305
|
|
multiplayerBtnX, multiplayerBtnY = 264, 330
|
|
tcpNetBtnX, tcpNetBtnY = 264, 280
|
|
networkCancelBtnX, networkCancelBtnY = 264, 540
|
|
tcpHostBtnX, tcpHostBtnY = 264, 200
|
|
tcpJoinBtnX, tcpJoinBtnY = 264, 240
|
|
errorLabelX, errorLabelY = 400, 250
|
|
machineIPX, machineIPY = 400, 90
|
|
tipX, tipY = 400, 300
|
|
)
|
|
|
|
const (
|
|
white = 0xffffffff
|
|
lightYellow = 0xffff8cff
|
|
gold = 0xd8c480ff
|
|
red = 0xff0000ff
|
|
)
|
|
|
|
const (
|
|
joinGameCharacterFilter = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890._:"
|
|
)
|
|
|
|
const (
|
|
logPrefix = "Game Screen"
|
|
)
|
|
|
|
// BuildInfo contains information about the current build
|
|
type BuildInfo struct {
|
|
Branch, Commit string
|
|
}
|
|
|
|
// CreateMainMenu creates an instance of MainMenu
|
|
func CreateMainMenu(
|
|
navigator d2interface.Navigator,
|
|
asset *d2asset.AssetManager,
|
|
renderer d2interface.Renderer,
|
|
inputManager d2interface.InputManager,
|
|
audioProvider d2interface.AudioProvider,
|
|
ui *d2ui.UIManager,
|
|
buildInfo BuildInfo,
|
|
l d2util.LogLevel,
|
|
errorMessageOptional ...string,
|
|
) (*MainMenu, error) {
|
|
heroStateFactory, err := d2hero.NewHeroStateFactory(asset)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
mainMenu := &MainMenu{
|
|
asset: asset,
|
|
screenMode: ScreenModeUnknown,
|
|
leftButtonHeld: true,
|
|
renderer: renderer,
|
|
inputManager: inputManager,
|
|
audioProvider: audioProvider,
|
|
navigator: navigator,
|
|
buildInfo: buildInfo,
|
|
uiManager: ui,
|
|
heroState: heroStateFactory,
|
|
}
|
|
|
|
mainMenu.Logger = d2util.NewLogger()
|
|
mainMenu.Logger.SetPrefix(logPrefix)
|
|
mainMenu.Logger.SetLevel(l)
|
|
|
|
if len(errorMessageOptional) != 0 {
|
|
mainMenu.errorLabel = ui.NewLabel(d2resource.FontFormal12, d2resource.PaletteUnits)
|
|
mainMenu.errorLabel.SetText(errorMessageOptional[0])
|
|
}
|
|
|
|
return mainMenu, nil
|
|
}
|
|
|
|
// MainMenu represents the main menu
|
|
type MainMenu struct {
|
|
tcpIPBackground *d2ui.Sprite
|
|
trademarkBackground *d2ui.Sprite
|
|
background *d2ui.Sprite
|
|
diabloLogoLeft *d2ui.Sprite
|
|
diabloLogoRight *d2ui.Sprite
|
|
diabloLogoLeftBack *d2ui.Sprite
|
|
diabloLogoRightBack *d2ui.Sprite
|
|
serverIPBackground *d2ui.Sprite
|
|
singlePlayerButton *d2ui.Button
|
|
multiplayerButton *d2ui.Button
|
|
githubButton *d2ui.Button
|
|
exitDiabloButton *d2ui.Button
|
|
creditsButton *d2ui.Button
|
|
cinematicsButton *d2ui.Button
|
|
mapTestButton *d2ui.Button
|
|
networkTCPIPButton *d2ui.Button
|
|
networkCancelButton *d2ui.Button
|
|
btnTCPIPCancel *d2ui.Button
|
|
btnTCPIPHostGame *d2ui.Button
|
|
btnTCPIPJoinGame *d2ui.Button
|
|
btnServerIPCancel *d2ui.Button
|
|
btnServerIPOk *d2ui.Button
|
|
copyrightLabel *d2ui.Label
|
|
copyrightLabel2 *d2ui.Label
|
|
openDiabloLabel *d2ui.Label
|
|
versionLabel *d2ui.Label
|
|
commitLabel *d2ui.Label
|
|
tcpIPOptionsLabel *d2ui.Label
|
|
tcpJoinGameLabel *d2ui.Label
|
|
machineIP *d2ui.Label
|
|
errorLabel *d2ui.Label
|
|
joinTipLabel *d2ui.Label
|
|
hostTipLabel *d2ui.Label
|
|
tcpJoinGameEntry *d2ui.TextBox
|
|
screenMode mainMenuScreenMode
|
|
leftButtonHeld bool
|
|
|
|
asset *d2asset.AssetManager
|
|
inputManager d2interface.InputManager
|
|
renderer d2interface.Renderer
|
|
audioProvider d2interface.AudioProvider
|
|
scriptEngine *d2script.ScriptEngine // nolint:structcheck,unused // it will be used...
|
|
navigator d2interface.Navigator
|
|
uiManager *d2ui.UIManager
|
|
heroState *d2hero.HeroStateFactory
|
|
|
|
buildInfo BuildInfo
|
|
|
|
*d2util.Logger
|
|
}
|
|
|
|
// OnLoad is called to load the resources for the main menu
|
|
func (v *MainMenu) OnLoad(loading d2screen.LoadingState) {
|
|
v.audioProvider.PlayBGM(d2resource.BGMTitle)
|
|
loading.Progress(twentyPercent)
|
|
|
|
v.createMainMenuLabels(loading)
|
|
v.createMultiplayerLabels()
|
|
v.loadBackgroundSprites()
|
|
v.createLogos(loading)
|
|
v.createMainMenuButtons(loading)
|
|
v.createMultiplayerMenuButtons()
|
|
|
|
v.tcpJoinGameEntry = v.uiManager.NewTextbox()
|
|
v.tcpJoinGameEntry.SetPosition(joinGameDialogX, joinGameDialogY)
|
|
v.tcpJoinGameEntry.SetFilter(joinGameCharacterFilter)
|
|
loading.Progress(ninetyPercent)
|
|
|
|
if v.screenMode == ScreenModeUnknown {
|
|
v.SetScreenMode(ScreenModeTrademark)
|
|
} else {
|
|
v.SetScreenMode(ScreenModeMainMenu)
|
|
}
|
|
|
|
if err := v.inputManager.BindHandler(v); err != nil {
|
|
v.Error("failed to add main menu as event handler")
|
|
}
|
|
}
|
|
|
|
func (v *MainMenu) loadBackgroundSprites() {
|
|
var err error
|
|
|
|
v.background, err = v.uiManager.NewSprite(d2resource.GameSelectScreen, d2resource.PaletteSky)
|
|
if err != nil {
|
|
v.Error(err.Error())
|
|
}
|
|
|
|
v.background.SetPosition(backgroundX, backgroundY)
|
|
|
|
v.trademarkBackground, err = v.uiManager.NewSprite(d2resource.TrademarkScreen, d2resource.PaletteSky)
|
|
if err != nil {
|
|
v.Error(err.Error())
|
|
}
|
|
|
|
v.trademarkBackground.SetPosition(backgroundX, backgroundY)
|
|
|
|
v.tcpIPBackground, err = v.uiManager.NewSprite(d2resource.TCPIPBackground, d2resource.PaletteSky)
|
|
if err != nil {
|
|
v.Error(err.Error())
|
|
}
|
|
|
|
v.tcpIPBackground.SetPosition(backgroundX, backgroundY)
|
|
|
|
v.serverIPBackground, err = v.uiManager.NewSprite(d2resource.PopUpOkCancel, d2resource.PaletteFechar)
|
|
if err != nil {
|
|
v.Error(err.Error())
|
|
}
|
|
|
|
v.serverIPBackground.SetPosition(serverIPbackgroundX, serverIPbackgroundY)
|
|
}
|
|
|
|
func (v *MainMenu) createMainMenuLabels(loading d2screen.LoadingState) {
|
|
v.versionLabel = v.uiManager.NewLabel(d2resource.FontFormal12, d2resource.PaletteStatic)
|
|
v.versionLabel.Alignment = d2ui.HorizontalAlignRight
|
|
v.versionLabel.SetText("OpenDiablo2 - " + v.buildInfo.Branch)
|
|
v.versionLabel.Color[0] = d2util.Color(white)
|
|
v.versionLabel.SetPosition(versionLabelX, versionLabelY)
|
|
|
|
v.commitLabel = v.uiManager.NewLabel(d2resource.FontFormal10, d2resource.PaletteStatic)
|
|
v.commitLabel.Alignment = d2ui.HorizontalAlignLeft
|
|
v.commitLabel.SetText(v.buildInfo.Commit)
|
|
v.commitLabel.Color[0] = d2util.Color(white)
|
|
v.commitLabel.SetPosition(commitLabelX, commitLabelY)
|
|
|
|
v.copyrightLabel = v.uiManager.NewLabel(d2resource.FontFormal12, d2resource.PaletteStatic)
|
|
v.copyrightLabel.Alignment = d2ui.HorizontalAlignCenter
|
|
v.copyrightLabel.SetText(v.asset.TranslateString(d2enum.CopyrightLabel))
|
|
v.copyrightLabel.Color[0] = d2util.Color(lightBrown)
|
|
v.copyrightLabel.SetPosition(copyrightX, copyrightY)
|
|
loading.Progress(thirtyPercent)
|
|
|
|
v.copyrightLabel2 = v.uiManager.NewLabel(d2resource.FontFormal12, d2resource.PaletteStatic)
|
|
v.copyrightLabel2.Alignment = d2ui.HorizontalAlignCenter
|
|
v.copyrightLabel2.SetText(v.asset.TranslateString(d2enum.AllRightsReservedLabel))
|
|
v.copyrightLabel2.Color[0] = d2util.Color(lightBrown)
|
|
v.copyrightLabel2.SetPosition(copyright2X, copyright2Y)
|
|
|
|
v.openDiabloLabel = v.uiManager.NewLabel(d2resource.FontFormal10, d2resource.PaletteStatic)
|
|
v.openDiabloLabel.Alignment = d2ui.HorizontalAlignCenter
|
|
v.openDiabloLabel.SetText("OpenDiablo2 is neither developed by, nor endorsed by Blizzard or its parent company Activision")
|
|
v.openDiabloLabel.Color[0] = d2util.Color(lightYellow)
|
|
v.openDiabloLabel.SetPosition(od2LabelX, od2LabelY)
|
|
loading.Progress(fiftyPercent)
|
|
|
|
if v.errorLabel != nil {
|
|
v.errorLabel.SetPosition(errorLabelX, errorLabelY)
|
|
v.errorLabel.Alignment = d2ui.HorizontalAlignCenter
|
|
v.errorLabel.Color[0] = d2util.Color(red)
|
|
}
|
|
}
|
|
|
|
func (v *MainMenu) createMultiplayerLabels() {
|
|
v.tcpIPOptionsLabel = v.uiManager.NewLabel(d2resource.Font42, d2resource.PaletteUnits)
|
|
v.tcpIPOptionsLabel.SetPosition(tcpOptionsX, tcpOptionsY)
|
|
v.tcpIPOptionsLabel.Alignment = d2ui.HorizontalAlignCenter
|
|
v.tcpIPOptionsLabel.SetText(v.asset.TranslateString(d2enum.TCPIPOptionsLabel))
|
|
|
|
v.tcpJoinGameLabel = v.uiManager.NewLabel(d2resource.Font16, d2resource.PaletteUnits)
|
|
v.tcpJoinGameLabel.Alignment = d2ui.HorizontalAlignCenter
|
|
v.tcpJoinGameLabel.SetText(strings.Join(
|
|
d2util.SplitIntoLinesWithMaxWidth(v.asset.TranslateString(
|
|
d2enum.TCPIPEnterHostIPLabel,
|
|
), 27), "\n"))
|
|
|
|
v.tcpJoinGameLabel.Color[0] = d2util.Color(gold)
|
|
v.tcpJoinGameLabel.SetPosition(joinGameX, joinGameY)
|
|
|
|
v.machineIP = v.uiManager.NewLabel(d2resource.Font24, d2resource.PaletteUnits)
|
|
v.machineIP.Alignment = d2ui.HorizontalAlignCenter
|
|
v.machineIP.SetText(v.asset.TranslateString(d2enum.TCPIPYourIPLabel) + "\n" + v.getLocalIP())
|
|
v.machineIP.Color[0] = d2util.Color(lightYellow)
|
|
v.machineIP.SetPosition(machineIPX, machineIPY)
|
|
|
|
v.hostTipLabel = v.uiManager.NewLabel(d2resource.FontFormal12, d2resource.PaletteUnits)
|
|
v.hostTipLabel.Alignment = d2ui.HorizontalAlignCenter
|
|
v.hostTipLabel.SetText(d2ui.ColorTokenize(strings.Join(d2util.SplitIntoLinesWithMaxWidth(
|
|
v.asset.TranslateString(d2enum.TipHostLabel), 36),
|
|
"\n"), d2ui.ColorTokenGold))
|
|
v.hostTipLabel.SetPosition(tipX, tipY)
|
|
v.hostTipLabel.SetVisible(false)
|
|
|
|
v.joinTipLabel = v.uiManager.NewLabel(d2resource.FontFormal12, d2resource.PaletteUnits)
|
|
v.joinTipLabel.Alignment = d2ui.HorizontalAlignCenter
|
|
v.joinTipLabel.SetText(d2ui.ColorTokenize(strings.Join(d2util.SplitIntoLinesWithMaxWidth(
|
|
v.asset.TranslateString(d2enum.TipJoinLabel), 36),
|
|
"\n"), d2ui.ColorTokenGold))
|
|
v.joinTipLabel.SetPosition(tipX, tipY)
|
|
v.joinTipLabel.SetVisible(false)
|
|
}
|
|
|
|
func (v *MainMenu) createLogos(loading d2screen.LoadingState) {
|
|
var err error
|
|
|
|
v.diabloLogoLeft, err = v.uiManager.NewSprite(d2resource.Diablo2LogoFireLeft, d2resource.PaletteUnits)
|
|
if err != nil {
|
|
v.Error(err.Error())
|
|
}
|
|
|
|
v.diabloLogoLeft.SetEffect(d2enum.DrawEffectModulate)
|
|
v.diabloLogoLeft.PlayForward()
|
|
v.diabloLogoLeft.SetPosition(diabloLogoX, diabloLogoY)
|
|
loading.Progress(sixtyPercent)
|
|
|
|
v.diabloLogoRight, err = v.uiManager.NewSprite(d2resource.Diablo2LogoFireRight, d2resource.PaletteUnits)
|
|
if err != nil {
|
|
v.Error(err.Error())
|
|
}
|
|
|
|
v.diabloLogoRight.SetEffect(d2enum.DrawEffectModulate)
|
|
v.diabloLogoRight.PlayForward()
|
|
v.diabloLogoRight.SetPosition(diabloLogoX, diabloLogoY)
|
|
|
|
v.diabloLogoLeftBack, err = v.uiManager.NewSprite(d2resource.Diablo2LogoBlackLeft, d2resource.PaletteUnits)
|
|
if err != nil {
|
|
v.Error(err.Error())
|
|
}
|
|
|
|
v.diabloLogoLeftBack.SetPosition(diabloLogoX, diabloLogoY)
|
|
|
|
v.diabloLogoRightBack, err = v.uiManager.NewSprite(d2resource.Diablo2LogoBlackRight, d2resource.PaletteUnits)
|
|
if err != nil {
|
|
v.Error(err.Error())
|
|
}
|
|
|
|
v.diabloLogoRightBack.SetPosition(diabloLogoX, diabloLogoY)
|
|
}
|
|
|
|
func (v *MainMenu) createMainMenuButtons(loading d2screen.LoadingState) {
|
|
v.exitDiabloButton = v.uiManager.NewButton(d2ui.ButtonTypeWide, v.asset.TranslateString(d2enum.ExitGameLabel))
|
|
v.exitDiabloButton.SetPosition(exitDiabloBtnX, exitDiabloBtnY)
|
|
v.exitDiabloButton.OnActivated(func() { v.onExitButtonClicked() })
|
|
|
|
v.creditsButton = v.uiManager.NewButton(d2ui.ButtonTypeShort, v.asset.TranslateString(d2enum.CreditsLabel))
|
|
v.creditsButton.SetPosition(creditBtnX, creditBtnY)
|
|
v.creditsButton.OnActivated(func() { v.onCreditsButtonClicked() })
|
|
|
|
v.cinematicsButton = v.uiManager.NewButton(d2ui.ButtonTypeShort, v.asset.TranslateString(d2enum.CinematicsLabel))
|
|
v.cinematicsButton.SetPosition(cineBtnX, cineBtnY)
|
|
v.cinematicsButton.OnActivated(func() { v.onCinematicsButtonClicked() })
|
|
loading.Progress(seventyPercent)
|
|
|
|
v.singlePlayerButton = v.uiManager.NewButton(d2ui.ButtonTypeWide, v.asset.TranslateString(d2enum.SinglePlayerLabel))
|
|
v.singlePlayerButton.SetPosition(singlePlayerBtnX, singlePlayerBtnY)
|
|
v.singlePlayerButton.OnActivated(func() { v.onSinglePlayerClicked() })
|
|
|
|
v.githubButton = v.uiManager.NewButton(d2ui.ButtonTypeWide, "PROJECT WEBSITE")
|
|
v.githubButton.SetPosition(githubBtnX, githubBtnY)
|
|
v.githubButton.OnActivated(func() { v.onGithubButtonClicked() })
|
|
|
|
v.mapTestButton = v.uiManager.NewButton(d2ui.ButtonTypeWide, "MAP ENGINE TEST")
|
|
v.mapTestButton.SetPosition(mapTestBtnX, mapTestBtnY)
|
|
v.mapTestButton.OnActivated(func() { v.onMapTestClicked() })
|
|
|
|
v.btnTCPIPCancel = v.uiManager.NewButton(d2ui.ButtonTypeMedium,
|
|
v.asset.TranslateString(d2enum.CancelLabel))
|
|
v.btnTCPIPCancel.SetPosition(tcpBtnX, tcpBtnY)
|
|
v.btnTCPIPCancel.OnActivated(func() { v.onTCPIPCancelClicked() })
|
|
|
|
v.btnServerIPCancel = v.uiManager.NewButton(d2ui.ButtonTypeOkCancel, v.asset.TranslateString(d2enum.CancelLabel))
|
|
v.btnServerIPCancel.SetPosition(srvCancelBtnX, srvCancelBtnY)
|
|
v.btnServerIPCancel.OnActivated(func() { v.onBtnTCPIPCancelClicked() })
|
|
|
|
v.btnServerIPOk = v.uiManager.NewButton(d2ui.ButtonTypeOkCancel, v.asset.TranslateString(d2enum.OKLabel))
|
|
v.btnServerIPOk.SetPosition(srvOkBtnX, srvOkBtnY)
|
|
v.btnServerIPOk.OnActivated(func() { v.onBtnTCPIPOkClicked() })
|
|
loading.Progress(eightyPercent)
|
|
}
|
|
|
|
func (v *MainMenu) createMultiplayerMenuButtons() {
|
|
v.multiplayerButton = v.uiManager.NewButton(d2ui.ButtonTypeWide,
|
|
v.asset.TranslateString(d2enum.OtherMultiplayerLabel))
|
|
v.multiplayerButton.SetPosition(multiplayerBtnX, multiplayerBtnY)
|
|
v.multiplayerButton.OnActivated(func() { v.onMultiplayerClicked() })
|
|
|
|
v.networkTCPIPButton = v.uiManager.NewButton(d2ui.ButtonTypeWide, v.asset.TranslateString(d2enum.TCPIPGameLabel))
|
|
v.networkTCPIPButton.SetPosition(tcpNetBtnX, tcpNetBtnY)
|
|
v.networkTCPIPButton.OnActivated(func() { v.onNetworkTCPIPClicked() })
|
|
|
|
v.networkCancelButton = v.uiManager.NewButton(d2ui.ButtonTypeWide,
|
|
v.asset.TranslateString(d2enum.CancelLabel))
|
|
v.networkCancelButton.SetPosition(networkCancelBtnX, networkCancelBtnY)
|
|
v.networkCancelButton.OnActivated(func() { v.onNetworkCancelClicked() })
|
|
|
|
v.btnTCPIPHostGame = v.uiManager.NewButton(d2ui.ButtonTypeWide, v.asset.TranslateString(d2enum.TCPIPHostGameLabel))
|
|
v.btnTCPIPHostGame.SetPosition(tcpHostBtnX, tcpHostBtnY)
|
|
v.btnTCPIPHostGame.OnActivated(func() { v.onTCPIPHostGameClicked() })
|
|
v.btnTCPIPHostGame.OnHoverStart(func() { v.hostTipLabel.SetVisible(true) })
|
|
v.btnTCPIPHostGame.OnHoverEnd(func() { v.hostTipLabel.SetVisible(false) })
|
|
|
|
v.btnTCPIPJoinGame = v.uiManager.NewButton(d2ui.ButtonTypeWide, v.asset.TranslateString(d2enum.TCPIPJoinGameLabel))
|
|
v.btnTCPIPJoinGame.SetPosition(tcpJoinBtnX, tcpJoinBtnY)
|
|
v.btnTCPIPJoinGame.OnActivated(func() { v.onTCPIPJoinGameClicked() })
|
|
v.btnTCPIPJoinGame.OnHoverStart(func() { v.joinTipLabel.SetVisible(true) })
|
|
v.btnTCPIPJoinGame.OnHoverEnd(func() { v.joinTipLabel.SetVisible(false) })
|
|
}
|
|
|
|
func (v *MainMenu) onMapTestClicked() {
|
|
v.navigator.ToMapEngineTest(0, 1)
|
|
}
|
|
|
|
func (v *MainMenu) onSinglePlayerClicked() {
|
|
v.SetScreenMode(ScreenModeUnknown)
|
|
|
|
if v.heroState.HasGameStates() {
|
|
// Go here only if existing characters are available to select
|
|
v.navigator.ToCharacterSelect(d2clientconnectiontype.Local, v.tcpJoinGameEntry.GetText())
|
|
} else {
|
|
v.navigator.ToSelectHero(d2clientconnectiontype.Local, v.tcpJoinGameEntry.GetText())
|
|
}
|
|
}
|
|
|
|
func (v *MainMenu) onGithubButtonClicked() {
|
|
url := "https://www.github.com/OpenDiablo2/OpenDiablo2"
|
|
|
|
var err error
|
|
|
|
switch runtime.GOOS {
|
|
case "linux":
|
|
err = exec.Command("xdg-open", url).Start()
|
|
case "windows":
|
|
err = exec.Command("rundll32", "url.dll,FileProtocolHandler", url).Start()
|
|
case "darwin":
|
|
err = exec.Command("open", url).Start()
|
|
default:
|
|
err = fmt.Errorf("unsupported platform")
|
|
}
|
|
|
|
if err != nil {
|
|
v.Error(err.Error())
|
|
}
|
|
}
|
|
|
|
func (v *MainMenu) onExitButtonClicked() {
|
|
os.Exit(0)
|
|
}
|
|
|
|
func (v *MainMenu) onCreditsButtonClicked() {
|
|
v.navigator.ToCredits()
|
|
}
|
|
|
|
func (v *MainMenu) onCinematicsButtonClicked() {
|
|
v.navigator.ToCinematics()
|
|
}
|
|
|
|
// Render renders the main menu
|
|
func (v *MainMenu) Render(screen d2interface.Surface) {
|
|
v.renderBackgrounds(screen)
|
|
v.renderLogos(screen)
|
|
v.renderLabels(screen)
|
|
}
|
|
|
|
func (v *MainMenu) renderBackgrounds(screen d2interface.Surface) {
|
|
switch v.screenMode {
|
|
case ScreenModeTrademark:
|
|
v.trademarkBackground.RenderSegmented(screen, 4, 3, 0)
|
|
case ScreenModeServerIP:
|
|
v.tcpIPBackground.RenderSegmented(screen, 4, 3, 0)
|
|
v.serverIPBackground.RenderSegmented(screen, 2, 1, 0)
|
|
case ScreenModeTCPIP:
|
|
v.tcpIPBackground.RenderSegmented(screen, 4, 3, 0)
|
|
default:
|
|
v.background.RenderSegmented(screen, 4, 3, 0)
|
|
}
|
|
}
|
|
|
|
func (v *MainMenu) renderLogos(screen d2interface.Surface) {
|
|
switch v.screenMode {
|
|
case ScreenModeTrademark, ScreenModeMainMenu, ScreenModeMultiplayer:
|
|
v.diabloLogoLeftBack.Render(screen)
|
|
v.diabloLogoRightBack.Render(screen)
|
|
v.diabloLogoLeft.Render(screen)
|
|
v.diabloLogoRight.Render(screen)
|
|
}
|
|
}
|
|
|
|
func (v *MainMenu) renderLabels(screen d2interface.Surface) {
|
|
switch v.screenMode {
|
|
case ScreenModeServerIP:
|
|
v.tcpIPOptionsLabel.Render(screen)
|
|
v.tcpJoinGameLabel.Render(screen)
|
|
v.machineIP.Render(screen)
|
|
case ScreenModeTCPIP:
|
|
v.tcpIPOptionsLabel.Render(screen)
|
|
v.machineIP.Render(screen)
|
|
case ScreenModeTrademark:
|
|
v.copyrightLabel.Render(screen)
|
|
v.copyrightLabel2.Render(screen)
|
|
|
|
if v.errorLabel != nil {
|
|
v.errorLabel.Render(screen)
|
|
}
|
|
case ScreenModeMainMenu:
|
|
v.openDiabloLabel.Render(screen)
|
|
v.versionLabel.Render(screen)
|
|
v.commitLabel.Render(screen)
|
|
}
|
|
}
|
|
|
|
// Advance runs the update logic on the main menu
|
|
func (v *MainMenu) Advance(tickTime float64) error {
|
|
switch v.screenMode {
|
|
case ScreenModeMainMenu, ScreenModeTrademark, ScreenModeMultiplayer:
|
|
if err := v.diabloLogoLeftBack.Advance(tickTime); err != nil {
|
|
return err
|
|
}
|
|
|
|
if err := v.diabloLogoRightBack.Advance(tickTime); err != nil {
|
|
return err
|
|
}
|
|
|
|
if err := v.diabloLogoLeft.Advance(tickTime); err != nil {
|
|
return err
|
|
}
|
|
|
|
if err := v.diabloLogoRight.Advance(tickTime); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// OnMouseButtonDown is called when a mouse button is clicked
|
|
func (v *MainMenu) OnMouseButtonDown(event d2interface.MouseEvent) bool {
|
|
if v.screenMode == ScreenModeTrademark && event.Button() == d2enum.MouseButtonLeft {
|
|
v.SetScreenMode(ScreenModeMainMenu)
|
|
return true
|
|
}
|
|
|
|
return false
|
|
}
|
|
|
|
func (v *MainMenu) onEscapePressed(event d2interface.KeyEvent, mode mainMenuScreenMode) {
|
|
if event.Key() == d2enum.KeyEscape {
|
|
v.SetScreenMode(mode)
|
|
}
|
|
}
|
|
|
|
// OnKeyUp is called when a key is released
|
|
func (v *MainMenu) OnKeyUp(event d2interface.KeyEvent) bool {
|
|
preventKeyEventPropagation := false
|
|
|
|
switch v.screenMode {
|
|
case ScreenModeTrademark: // On retail version of D2, some specific key events (Escape, Space and Enter) puts you onto the main menu.
|
|
switch event.Key() {
|
|
case d2enum.KeyEscape, d2enum.KeyEnter, d2enum.KeySpace:
|
|
v.SetScreenMode(ScreenModeMainMenu)
|
|
}
|
|
|
|
preventKeyEventPropagation = true
|
|
case ScreenModeMainMenu: // pressing escape in Main Menu close the game
|
|
if event.Key() == d2enum.KeyEscape {
|
|
v.onExitButtonClicked()
|
|
}
|
|
case ScreenModeMultiplayer: // back to previous menu
|
|
v.onEscapePressed(event, ScreenModeMainMenu)
|
|
|
|
preventKeyEventPropagation = true
|
|
case ScreenModeTCPIP: // back to previous menu
|
|
v.onEscapePressed(event, ScreenModeMultiplayer)
|
|
|
|
preventKeyEventPropagation = true
|
|
case ScreenModeServerIP: // back to previous menu
|
|
v.onEscapePressed(event, ScreenModeTCPIP)
|
|
|
|
preventKeyEventPropagation = true
|
|
}
|
|
|
|
return preventKeyEventPropagation
|
|
}
|
|
|
|
// SetScreenMode sets the screen mode (which sub-menu the screen is on)
|
|
func (v *MainMenu) SetScreenMode(screenMode mainMenuScreenMode) {
|
|
v.screenMode = screenMode
|
|
isMainMenu := screenMode == ScreenModeMainMenu
|
|
isMultiplayer := screenMode == ScreenModeMultiplayer
|
|
isTCPIP := screenMode == ScreenModeTCPIP
|
|
isServerIP := screenMode == ScreenModeServerIP
|
|
|
|
v.exitDiabloButton.SetVisible(isMainMenu)
|
|
v.creditsButton.SetVisible(isMainMenu)
|
|
v.cinematicsButton.SetVisible(isMainMenu)
|
|
v.singlePlayerButton.SetVisible(isMainMenu)
|
|
v.githubButton.SetVisible(isMainMenu)
|
|
v.mapTestButton.SetVisible(isMainMenu)
|
|
v.multiplayerButton.SetVisible(isMainMenu)
|
|
v.networkTCPIPButton.SetVisible(isMultiplayer)
|
|
v.networkCancelButton.SetVisible(isMultiplayer)
|
|
v.btnTCPIPCancel.SetVisible(isTCPIP)
|
|
v.btnTCPIPHostGame.SetVisible(isTCPIP)
|
|
v.btnTCPIPJoinGame.SetVisible(isTCPIP)
|
|
v.tcpJoinGameEntry.SetVisible(isServerIP)
|
|
|
|
if isServerIP {
|
|
v.tcpJoinGameEntry.Activate()
|
|
}
|
|
|
|
v.btnServerIPOk.SetVisible(isServerIP)
|
|
v.btnServerIPCancel.SetVisible(isServerIP)
|
|
}
|
|
|
|
func (v *MainMenu) onNetworkCancelClicked() {
|
|
v.SetScreenMode(ScreenModeMainMenu)
|
|
}
|
|
|
|
func (v *MainMenu) onMultiplayerClicked() {
|
|
v.SetScreenMode(ScreenModeMultiplayer)
|
|
}
|
|
|
|
func (v *MainMenu) onNetworkTCPIPClicked() {
|
|
v.SetScreenMode(ScreenModeTCPIP)
|
|
}
|
|
|
|
func (v *MainMenu) onTCPIPCancelClicked() {
|
|
v.SetScreenMode(ScreenModeMultiplayer)
|
|
}
|
|
|
|
func (v *MainMenu) onTCPIPHostGameClicked() {
|
|
v.navigator.ToCharacterSelect(d2clientconnectiontype.LANServer, "")
|
|
}
|
|
|
|
func (v *MainMenu) onTCPIPJoinGameClicked() {
|
|
v.SetScreenMode(ScreenModeServerIP)
|
|
}
|
|
|
|
func (v *MainMenu) onBtnTCPIPCancelClicked() {
|
|
v.SetScreenMode(ScreenModeTCPIP)
|
|
}
|
|
|
|
func (v *MainMenu) onBtnTCPIPOkClicked() {
|
|
v.navigator.ToCharacterSelect(d2clientconnectiontype.LANClient, v.tcpJoinGameEntry.GetText())
|
|
}
|
|
|
|
// getLocalIP returns local machine IP address
|
|
func (v *MainMenu) getLocalIP() string {
|
|
// https://stackoverflow.com/a/28862477
|
|
host, _ := os.Hostname()
|
|
addrs, _ := net.LookupIP(host)
|
|
|
|
for _, addr := range addrs {
|
|
if ipv4 := addr.To4(); ipv4 != nil {
|
|
return ipv4.String()
|
|
}
|
|
}
|
|
|
|
v.Warning("no IPv4 Address could be found")
|
|
|
|
return v.asset.TranslateString(d2enum.IPNotFoundLabel)
|
|
}
|