Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,4 @@ factorio.tar
cw-local-config.json
.cw-channel-update
support/modUpdateHistory.dat
map-gen-json/
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ Common generated files and directories:
- `cw.lock`
- `../playerdb.json`
- `../map-gen-json/`
- `./map-gen-json/` for per-server `/map-exchange` custom settings
- `./log/`
- `./audit-log/`
- `../www/public_html/archive/`
Expand Down
21 changes: 10 additions & 11 deletions cfg/globalCfg.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,10 +44,18 @@ func setGlobalDefaults() {
if Global.Paths.DataFiles.DBFile == "" {
Global.Paths.DataFiles.DBFile = "playerdb.json"
}
if Global.Paths.Folders.ServersRoot == "" {
ex, err := os.Executable()
if err == nil {
exPath := filepath.Dir(ex)
p := filepath.Clean(filepath.Join(exPath, ".."))
Global.Paths.Folders.ServersRoot = p + "/"
}
}
if Global.Paths.Folders.MapGenerators == "" {
Global.Paths.Folders.MapGenerators = "map-gen-json"
Global.Paths.Folders.MapGenerators = constants.DefaultMapGeneratorsDir

err := os.MkdirAll(Global.Paths.Folders.ServersRoot+"/"+Global.Paths.Folders.MapGenerators, os.ModePerm)
err := os.MkdirAll(filepath.Join(Global.Paths.Folders.ServersRoot, Global.Paths.Folders.MapGenerators), os.ModePerm)
if err != nil {
cwlog.DoLogCW("Could not create map-gen-json directory.")
}
Expand All @@ -64,15 +72,6 @@ func setGlobalDefaults() {
cwlog.DoLogCW("No group name specified. Random one generated.")
}

if Global.Paths.Folders.ServersRoot == "" {
ex, err := os.Executable()
if err == nil {
exPath := filepath.Dir(ex)
p := filepath.Clean(filepath.Join(exPath, ".."))
Global.Paths.Folders.ServersRoot = p + "/"
}
}

if Global.Paths.ChatWirePrefix == "" {
Global.Paths.ChatWirePrefix = "cw-"
}
Expand Down
46 changes: 45 additions & 1 deletion cfg/pathutil.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
package cfg

import "ChatWire/constants"
import (
"os"
"path/filepath"
"strings"

"ChatWire/constants"
)

// GetFactorioFolder returns the path to the Factorio installation for the current server.
func GetFactorioFolder() string {
Expand All @@ -27,3 +33,41 @@ func GetSavesFolder() string {
Global.Paths.Folders.FactorioDir + "/" +
Global.Paths.Folders.Saves
}

// GetSharedMapGeneratorFolder returns the parent-level folder for reusable named generators.
func GetSharedMapGeneratorFolder() string {
return filepath.Join(Global.Paths.Folders.ServersRoot, Global.Paths.Folders.MapGenerators)
}

// GetLocalMapGeneratorFolder returns this ChatWire instance's local generator folder.
func GetLocalMapGeneratorFolder() string {
folder := Global.Paths.Folders.MapGenerators
if folder == "" {
folder = constants.DefaultMapGeneratorsDir
}

folder = filepath.Base(filepath.Clean(folder))
if folder == "." || folder == string(os.PathSeparator) {
folder = constants.DefaultMapGeneratorsDir
}

localPath := filepath.Join(".", folder)
if absPath, err := filepath.Abs(localPath); err == nil {
return absPath
}
return localPath
}

// GetMapGeneratorFolder returns the folder where a generator's JSON files live.
func GetMapGeneratorFolder(name string) string {
if strings.EqualFold(name, constants.CustomMapGeneratorName) {
return GetLocalMapGeneratorFolder()
}
return GetSharedMapGeneratorFolder()
}

// GetMapGeneratorFiles returns Factorio's map-gen and map-settings JSON paths for a generator.
func GetMapGeneratorFiles(name string) (string, string) {
dir := GetMapGeneratorFolder(name)
return filepath.Join(dir, name+"-gen.json"), filepath.Join(dir, name+"-set.json")
}
14 changes: 14 additions & 0 deletions commands/commands_moderator.go
Original file line number Diff line number Diff line change
Expand Up @@ -295,6 +295,20 @@ func moderatorCommands() []glob.CommandData {
Type: discordgo.ChatApplicationCommand,
},
Function: moderator.MapReset, ModeratorOnly: true},
{AppCmd: glob.AppCmdData{
Name: "map-exchange",
Description: "Generate a custom map from a Factorio map exchange string.",
Type: discordgo.ChatApplicationCommand,
Options: []glob.OptionData{
{
Name: "exchange-string",
Description: "Paste the Factorio map exchange string.",
Type: discordgo.ApplicationCommandOptionString,
Required: true,
},
},
},
Function: moderator.MapExchange, ModeratorOnly: true},
{AppCmd: glob.AppCmdData{
Name: "config-server",
Description: "Server settings and options, such as the name.",
Expand Down
55 changes: 55 additions & 0 deletions commands/moderator/mapExchange.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package moderator

import (
"fmt"
"strings"
"time"

"github.com/bwmarrin/discordgo"

"ChatWire/constants"
"ChatWire/disc"
"ChatWire/fact"
"ChatWire/glob"
"ChatWire/modupdate"
)

// MapExchange converts a Factorio map exchange string into the custom map
// generator files and immediately generates a new save from them.
func MapExchange(cmd *glob.CommandData, i *discordgo.InteractionCreate) {
if fact.FactorioBooted || fact.FactIsRunning {
disc.InteractionEphemeralResponse(i, "Error:", "Factorio is currently running. You must stop Factorio first.")
return
}

exchangeString := ""
for _, arg := range i.ApplicationCommandData().Options {
if arg.Type == discordgo.ApplicationCommandOptionString && strings.EqualFold(arg.Name, "exchange-string") {
exchangeString = arg.StringValue()
break
}
}

if strings.TrimSpace(exchangeString) == "" {
disc.InteractionEphemeralResponse(i, "Error:", "You must supply a map exchange string.")
return
}

disc.InteractionEphemeralResponse(i, "Status:", "Converting map exchange string and generating a custom map.")

fileName, err := fact.GenCustomMapFromExchange(exchangeString)
if err != nil {
msg := fmt.Sprintf("Unable to generate custom map: %v", err)
disc.InteractionEphemeralResponseColor(i, "Error:", msg, glob.COLOR_RED)
return
}

if i != nil && i.Member != nil && i.Member.User != nil {
newHist := modupdate.ModHistoryItem{InfoItem: true,
Name: "Generate Custom Map By: " + i.Member.User.Username, Notes: fileName, Date: time.Now()}
modupdate.AddModHistory(newHist)
}

msg := fmt.Sprintf("Generated `%s` using `%s` map settings.", fileName, constants.CustomMapGeneratorName)
disc.InteractionEphemeralResponse(i, "Map exchange", msg)
}
14 changes: 8 additions & 6 deletions commands/moderator/settingsUtil.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,19 +11,21 @@ import (

/* Get list of map generation presets, because an invalid one will make map generation fail */
func getMapGenNames() []string {
path := cfg.Global.Paths.Folders.ServersRoot + cfg.Global.Paths.Folders.MapGenerators
output := []string{"none", constants.CustomMapGeneratorName}

path := cfg.GetSharedMapGeneratorFolder()
files, err := os.ReadDir(path)
if err != nil {
cwlog.DoLogCW(err.Error())
return nil
return output
}

var output []string

output = append(output, "none")
for _, f := range files {
if strings.HasSuffix(f.Name(), "-gen.json") {
output = append(output, strings.TrimSuffix(f.Name(), "-gen.json"))
name := strings.TrimSuffix(f.Name(), "-gen.json")
if !strings.EqualFold(name, constants.CustomMapGeneratorName) {
output = append(output, name)
}
}
}
return output
Expand Down
50 changes: 26 additions & 24 deletions constants/consts.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import "time"
const (
ProgName = "ChatWire"
Version = "2706-04.27.2026-1905a" // build-mm.dd.yyyy-hhmmsuffix
CWEpoch = 1653239822390688174 //Never change this
CWEpoch = 1653239822390688174 //Never change this
SeenDivisor = 60
SeenEpoch = 1546326000
Unknown = "Unknown"
Expand All @@ -15,29 +15,31 @@ const (
PassExpireSec = 5 * 60

/* ChatWire files */
CWGlobalConfig = "../cw-global-config.json"
CWLocalConfig = "cw-local-config.json"
WhitelistName = "server-whitelist.json"
AdminlistName = "server-adminlist.json"
ServSettingsName = "server-settings.json"
ModSettingsName = "mod-settings.dat"
ModListName = "mod-list.json"
ModVersionsName = "mod-versions.json"
ModsQueueFolder = "mods-queue"
ModsFolder = "mods"
OldModsDir = "old"
RoleListFile = "../RoleList.dat"
VoteFile = "votes.dat"
ArchiveFolderSuffix = " maps"
TempSaveName = "softmod.tmp"
BootUpdateDelayMin = 2
SusWarningInterval = 2
CrashReportInterval = 300
MaxSaveBackups = 10
ModPackLifeMins = 180
ModPackCooldownMin = 5
MaxModPacks = 4
ErrMsgDelay = time.Second * 3
CWGlobalConfig = "../cw-global-config.json"
CWLocalConfig = "cw-local-config.json"
WhitelistName = "server-whitelist.json"
AdminlistName = "server-adminlist.json"
ServSettingsName = "server-settings.json"
ModSettingsName = "mod-settings.dat"
ModListName = "mod-list.json"
ModVersionsName = "mod-versions.json"
DefaultMapGeneratorsDir = "map-gen-json"
CustomMapGeneratorName = "custom"
ModsQueueFolder = "mods-queue"
ModsFolder = "mods"
OldModsDir = "old"
RoleListFile = "../RoleList.dat"
VoteFile = "votes.dat"
ArchiveFolderSuffix = " maps"
TempSaveName = "softmod.tmp"
BootUpdateDelayMin = 2
SusWarningInterval = 2
CrashReportInterval = 300
MaxSaveBackups = 10
ModPackLifeMins = 180
ModPackCooldownMin = 5
MaxModPacks = 4
ErrMsgDelay = time.Second * 3
// Default offset added to Factorio server port for RCON
RconPortOffset = 10000

Expand Down
Loading
Loading