up3
Build and deploy / Build (push) Has been cancelled
Build and deploy / Update Contributors (push) Has been cancelled
Build and deploy / Deploy (push) Has been cancelled
Build and deploy / Build (push) Has been cancelled
Build and deploy / Update Contributors (push) Has been cancelled
Build and deploy / Deploy (push) Has been cancelled
This commit is contained in:
@@ -0,0 +1,157 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"strings"
|
||||
|
||||
"github.com/go-gl/mathgl/mgl64"
|
||||
)
|
||||
|
||||
// Parameter is an interface for a generic parameters. Users may have types as command parameters that
|
||||
// implement this parameter.
|
||||
type Parameter interface {
|
||||
// Parse takes an arbitrary amount of arguments from the command Line passed and parses it, so that it can
|
||||
// store it to value v. If the arguments cannot be parsed from the Line, an error should be returned.
|
||||
Parse(line *Line, v reflect.Value) error
|
||||
// Type returns the type of the parameter. It will show up in the usage of the command, and, if one of the
|
||||
// known type names, will also show up client-side.
|
||||
Type() string
|
||||
}
|
||||
|
||||
// Enum is an interface for enum-type parameters. Users may have types as command parameters that implement
|
||||
// this parameter in order to allow a specific set of options only.
|
||||
// Enum implementations must be of the type string, for example:
|
||||
//
|
||||
// type GameMode string
|
||||
// func (GameMode) Type() string { return "GameMode" }
|
||||
// func (GameMode) Options(Source) []string { return []string{"survival", "creative"} }
|
||||
//
|
||||
// Their values will then automatically be set to whichever option returned in Enum.Options is selected by
|
||||
// the user.
|
||||
type Enum interface {
|
||||
// Type returns the type of the enum. This type shows up client-side in the command usage, in the spot
|
||||
// where parameter types otherwise are.
|
||||
// Type names returned are used as an identifier for this enum type. Different Enum implementations must
|
||||
// return a different string in the Type method.
|
||||
Type() string
|
||||
// Options should return a list of options that show up on the client side. The command will ensure that
|
||||
// the argument passed to the enum parameter will be equal to one of these options. The provided Source
|
||||
// can also be used to change the enums for each player.
|
||||
Options(source Source) []string
|
||||
}
|
||||
|
||||
// ParamDescriber may be implemented by a Runnable to programmatically describe its parameters
|
||||
// without relying on struct field reflection.
|
||||
type ParamDescriber interface {
|
||||
DescribeParams(src Source) []ParamInfo
|
||||
}
|
||||
|
||||
// SubCommand represents a subcommand that may be added as a static value that must be written. Adding
|
||||
// multiple Runnable implementations to the command in New with different SubCommand fields as the
|
||||
// first parameter allows for commands with subcommands.
|
||||
type SubCommand struct{}
|
||||
|
||||
// Varargs is an argument type that may be used to capture all arguments that follow. This is useful for,
|
||||
// for example, messages and names.
|
||||
type Varargs string
|
||||
|
||||
// Optional is an argument type that may be used to make any of the available parameter types optional. Optional command
|
||||
// parameters may only occur at the end of the Runnable struct. No non-optional parameter is allowed after an optional
|
||||
// parameter.
|
||||
type Optional[T any] struct {
|
||||
val T
|
||||
set bool
|
||||
}
|
||||
|
||||
// Load returns the value specified upon executing the command and a bool that is true if the parameter was filled out
|
||||
// by the Source.
|
||||
func (o Optional[T]) Load() (T, bool) {
|
||||
return o.val, o.set
|
||||
}
|
||||
|
||||
// LoadOr returns the value specified upon executing the command, or a value 'or' if the parameter was not filled out
|
||||
// by the Source.
|
||||
func (o Optional[T]) LoadOr(or T) T {
|
||||
if o.set {
|
||||
return o.val
|
||||
}
|
||||
return or
|
||||
}
|
||||
|
||||
// with returns an Optional[T] with the value passed. It also sets the 'set' field to true.
|
||||
func (o Optional[T]) with(val any) any {
|
||||
return Optional[T]{val: val.(T), set: true}
|
||||
}
|
||||
|
||||
// optionalT is used to identify a parameter of the Optional type.
|
||||
type optionalT interface {
|
||||
with(val any) any
|
||||
}
|
||||
|
||||
// typeNameOf returns a readable type name for the interface value passed. If none could be found, 'value'
|
||||
// is returned.
|
||||
func typeNameOf(i any, name string) string {
|
||||
switch i.(type) {
|
||||
case int, int8, int16, int32, int64:
|
||||
return "int"
|
||||
case uint, uint8, uint16, uint32, uint64:
|
||||
return "uint"
|
||||
case float32, float64:
|
||||
return "float"
|
||||
case string:
|
||||
return "string"
|
||||
case Varargs:
|
||||
return "text"
|
||||
case bool:
|
||||
return "bool"
|
||||
case mgl64.Vec3:
|
||||
return "x y z"
|
||||
case []Target:
|
||||
return "target"
|
||||
case SubCommand:
|
||||
return name
|
||||
}
|
||||
if param, ok := i.(Parameter); ok {
|
||||
return param.Type()
|
||||
}
|
||||
if enum, ok := i.(Enum); ok {
|
||||
return enum.Type()
|
||||
}
|
||||
return "value"
|
||||
}
|
||||
|
||||
// unwrap returns the underlying reflect.Value of a reflect.Value, assuming it is of the Optional[T] type.
|
||||
func unwrap(v reflect.Value) reflect.Value {
|
||||
if _, ok := v.Interface().(optionalT); ok {
|
||||
return reflect.New(v.Field(0).Type()).Elem()
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
// optional checks if the reflect.Value passed implements the optionalT interface.
|
||||
func optional(v reflect.Value) bool {
|
||||
_, ok := v.Interface().(optionalT)
|
||||
return ok
|
||||
}
|
||||
|
||||
// suffix returns the suffix of the parameter as set in the struct field, if any.
|
||||
func suffix(v reflect.StructField) string {
|
||||
_, str := tag(v)
|
||||
return str
|
||||
}
|
||||
|
||||
// name returns the name of the parameter as set in the struct tag if it exists, or the field's name if not.
|
||||
func name(v reflect.StructField) string {
|
||||
str, _ := tag(v)
|
||||
if str == "" {
|
||||
return v.Name
|
||||
}
|
||||
return str
|
||||
}
|
||||
|
||||
// tag returns the name and suffix as specified in the 'cmd' tag, or empty strings if not present.
|
||||
func tag(v reflect.StructField) (name string, suffix string) {
|
||||
t, _ := v.Tag.Lookup("cmd")
|
||||
a, b, _ := strings.Cut(t, ",")
|
||||
return a, b
|
||||
}
|
||||
Reference in New Issue
Block a user