diff --git a/_datafiles/world/default/templates/admincommands/help/command.zone.template b/_datafiles/world/default/templates/admincommands/help/command.zone.template index e870e4d7..f5584c0c 100644 --- a/_datafiles/world/default/templates/admincommands/help/command.zone.template +++ b/_datafiles/world/default/templates/admincommands/help/command.zone.template @@ -4,3 +4,6 @@ The zone command can be used in the following ways: Get the zone config info zone set autoscale [lowend] [highend] - e.g. zone set autoscale 5 10 Set the mob auto-scaling to a min/max range. Set to zeroes or empty to clear. + +You can interactively modify zone properties to the room using the command: +zone edit \ No newline at end of file diff --git a/_datafiles/world/empty/templates/admincommands/help/command.zone.template b/_datafiles/world/empty/templates/admincommands/help/command.zone.template index e870e4d7..f5584c0c 100644 --- a/_datafiles/world/empty/templates/admincommands/help/command.zone.template +++ b/_datafiles/world/empty/templates/admincommands/help/command.zone.template @@ -4,3 +4,6 @@ The zone command can be used in the following ways: Get the zone config info zone set autoscale [lowend] [highend] - e.g. zone set autoscale 5 10 Set the mob auto-scaling to a min/max range. Set to zeroes or empty to clear. + +You can interactively modify zone properties to the room using the command: +zone edit \ No newline at end of file diff --git a/internal/usercommands/admin.zone.go b/internal/usercommands/admin.zone.go index b5406096..c503fa62 100644 --- a/internal/usercommands/admin.zone.go +++ b/internal/usercommands/admin.zone.go @@ -2,9 +2,11 @@ package usercommands import ( "fmt" + "sort" "strconv" "strings" + "github.com/volte6/gomud/internal/mutators" "github.com/volte6/gomud/internal/rooms" "github.com/volte6/gomud/internal/templates" "github.com/volte6/gomud/internal/users" @@ -28,16 +30,21 @@ func Zone(rest string, user *users.UserRecord, room *rooms.Room) (bool, error) { return handled, nil } - roomCmd := strings.ToLower(args[0]) + zoneCmd := strings.ToLower(args[0]) args = args[1:] + // Interactive Editing + if zoneCmd == `edit` { + return zone_Edit(``, user, room) + } + zoneConfig := rooms.GetZoneConfig(room.Zone) if zoneConfig == nil { user.SendText(fmt.Sprintf(`Couldn't find zone info for %s`, room.Zone)) return true, nil } - if roomCmd == `info` { + if zoneCmd == `info` { user.SendText(``) user.SendText(fmt.Sprintf(`Zone Config for %s`, room.Zone)) @@ -60,7 +67,7 @@ func Zone(rest string, user *users.UserRecord, room *rooms.Room) (bool, error) { return true, nil } - if roomCmd == `set` { + if zoneCmd == `set` { setWhat := args[0] @@ -92,3 +99,183 @@ func Zone(rest string, user *users.UserRecord, room *rooms.Room) (bool, error) { return true, nil } + +func zone_Edit(rest string, user *users.UserRecord, room *rooms.Room) (bool, error) { + + originalZoneConfig := rooms.GetZoneConfig(room.Zone) + if originalZoneConfig == nil { + user.SendText(`Could not find zone config.`) + return true, nil + } + + // Make a copy that we'll edit + editZoneConfig := *originalZoneConfig + + allZoneMutators := []string{} + for _, roomMut := range editZoneConfig.Mutators { + allZoneMutators = append(allZoneMutators, roomMut.MutatorId) + } + + cmdPrompt, _ := user.StartPrompt(`zone edit`, rest) + + selectedMutatorList := []string{} + if muts, ok := cmdPrompt.Recall(`mutators`); ok { + selectedMutatorList = muts.([]string) + } else { + if len(selectedMutatorList) == 0 { + selectedMutatorList = append(selectedMutatorList, allZoneMutators...) + } + } + + // Keep track of the state + cmdPrompt.Store(`mutators`, selectedMutatorList) + + selectedMutatorLookup := map[string]bool{} + for _, mutId := range selectedMutatorList { + selectedMutatorLookup[mutId] = true + } + + mutatorOptions := []templates.NameDescription{} + + for _, mutId := range mutators.GetAllMutatorIds() { + marked := false + if _, ok := selectedMutatorLookup[mutId]; ok { + marked = true + } + + mutatorOptions = append(mutatorOptions, templates.NameDescription{Id: mutId, Marked: marked, Name: mutId}) + + } + + sort.SliceStable(mutatorOptions, func(i, j int) bool { + return mutatorOptions[i].Name < mutatorOptions[j].Name + }) + + question := cmdPrompt.Ask(`Select a mutator to add/remove, or nothing to continue:`, []string{}, `0`) + if !question.Done { + tplTxt, _ := templates.Process("tables/numbered-list-doubled", mutatorOptions) + user.SendText(tplTxt) + return true, nil + } + + if question.Response != `0` { + + mutatorSelected := `` + + if restNum, err := strconv.Atoi(question.Response); err == nil { + if restNum > 0 && restNum <= len(mutatorOptions) { + mutatorSelected = mutatorOptions[restNum-1].Id.(string) + } + } + + if mutatorSelected == `` { + for _, b := range mutatorOptions { + if strings.EqualFold(b.Name, question.Response) { + mutatorSelected = b.Id.(string) + break + } + } + } + + if mutatorSelected == `` { + + user.SendText("Invalid selection.") + question.RejectResponse() + + tplTxt, _ := templates.Process("tables/numbered-list-doubled", mutatorOptions) + user.SendText(tplTxt) + return true, nil + } + + if _, ok := selectedMutatorLookup[mutatorSelected]; ok { + + delete(selectedMutatorLookup, mutatorSelected) + for idx, mutId := range selectedMutatorList { + if mutId == mutatorSelected { + selectedMutatorList = append(selectedMutatorList[0:idx], selectedMutatorList[idx+1:]...) + break + } + } + + } else { + + selectedMutatorList = append(selectedMutatorList, mutatorSelected) + selectedMutatorLookup[mutatorSelected] = true + + } + + cmdPrompt.Store(`mutators`, selectedMutatorList) + + question.RejectResponse() + + for idx, data := range mutatorOptions { + _, data.Marked = selectedMutatorLookup[data.Id.(string)] + mutatorOptions[idx] = data + } + + tplTxt, _ := templates.Process("tables/numbered-list-doubled", mutatorOptions) + user.SendText(tplTxt) + return true, nil + + } + + // + // Auto-scaling Options + // + { + + question := cmdPrompt.Ask(`Mob Autoscaling MINIMUM level?`, []string{strconv.Itoa(editZoneConfig.MobAutoScale.Minimum)}, strconv.Itoa(editZoneConfig.MobAutoScale.Minimum)) + if !question.Done { + return true, nil + } + editZoneConfig.MobAutoScale.Minimum, _ = strconv.Atoi(question.Response) + + question = cmdPrompt.Ask(`Mob Autoscaling MAXIMUM level?`, []string{strconv.Itoa(editZoneConfig.MobAutoScale.Maximum)}, strconv.Itoa(editZoneConfig.MobAutoScale.Maximum)) + if !question.Done { + return true, nil + } + editZoneConfig.MobAutoScale.Maximum, _ = strconv.Atoi(question.Response) + + } + + // + // Music Options + // + { + + question := cmdPrompt.Ask(`Zone music file?`, []string{editZoneConfig.MusicFile}, editZoneConfig.MusicFile) + if !question.Done { + return true, nil + } + editZoneConfig.MusicFile = question.Response + + } + + // + // Done editing. Save results + // + editZoneConfig.Mutators = mutators.MutatorList{} + for _, mutId := range selectedMutatorList { + editZoneConfig.Mutators = append(editZoneConfig.Mutators, mutators.Mutator{MutatorId: mutId}) + } + + // Make sure the edited zone config's roomId gets the changes. + if r := rooms.LoadRoom(editZoneConfig.RoomId); r != nil { + r.ZoneConfig = editZoneConfig + } + + // If the root zone room has been changed, clear the original rooms zone config. + if originalZoneConfig.RoomId != editZoneConfig.RoomId { + if r := rooms.LoadRoom(originalZoneConfig.RoomId); r != nil { + room.ZoneConfig = rooms.ZoneConfig{} + } + } + + user.SendText(``) + user.SendText(`Changes saved.`) + user.SendText(``) + + user.ClearPrompt() + + return true, nil +}