diff --git a/handlers/feature_rule.go b/handlers/feature_rule.go index 9e3c108..ecf1a31 100644 --- a/handlers/feature_rule.go +++ b/handlers/feature_rule.go @@ -10,6 +10,16 @@ import ( var FeatureRule = &JsonHandler{ Pattern: shared.FeatureRuleGlob, Entries: []JsonEntry{ + { + Store: stores.FeatureRuleId.Source, + Path: []shared.JsonPath{shared.JsonValue("minecraft:feature_rules/description/identifier")}, + Source: func(ctx *JsonContext) []core.Symbol { + return stores.FeatureRuleId.References.Get() + }, + References: func(ctx *JsonContext) []core.Symbol { + return stores.FeatureRuleId.Source.Get() + }, + }, { Store: stores.FeatureId.References, Path: []shared.JsonPath{shared.JsonValue("minecraft:feature_rules/description/places_feature")}, diff --git a/handlers/handler_command.go b/handlers/handler_command.go new file mode 100644 index 0000000..caa8bce --- /dev/null +++ b/handlers/handler_command.go @@ -0,0 +1,1091 @@ +package handlers + +import ( + "log" + "slices" + "strings" + + mapset "github.com/deckarep/golang-set/v2" + "github.com/rockide/language-server/core" + "github.com/rockide/language-server/internal/mcfunction" + "github.com/rockide/language-server/internal/protocol" + "github.com/rockide/language-server/internal/protocol/semtok" + "github.com/rockide/language-server/internal/sliceutil" + "github.com/rockide/language-server/internal/textdocument" + "github.com/rockide/language-server/shared" + "github.com/rockide/language-server/stores" +) + +// TODO: +// JSON Parse +// JSON Defintions +// JSON Rename + +type CommandHandler struct { + Pattern shared.Pattern + Parser *mcfunction.Parser + EscapeQuotes bool +} + +func (h *CommandHandler) GetPattern() shared.Pattern { + return h.Pattern +} + +func (h *CommandHandler) Parse(uri protocol.DocumentURI) error { + if strings.HasSuffix(uri.Path(), ".mcfunction") { + stores.McFunctionPath.Insert(h.Pattern, uri) + } + document, err := textdocument.GetOrReadFile(uri) + if err != nil { + return err + } + content := document.GetContent() + root, _ := h.Parser.Parse(content) + mcfunction.WalkNodeTree(root, func(i mcfunction.INode) bool { + nodeSpec, ok := i.(mcfunction.NodeParam) + if !ok { + return true + } + paramSpec, ok := nodeSpec.ParamSpec() + if !ok { + return true + } + for _, tag := range paramSpec.Tags { + entry, ok := commandEntries[tag] + if !ok || entry.Store == nil { + continue + } + scope := defaultScope + if entry.Scope != nil { + scope = entry.Scope(i) + } + s, e := i.Range() + entry.Store.Insert(scope, core.Symbol{ + URI: uri, + Value: i.Text(content), + Range: &protocol.Range{ + Start: document.PositionAt(s), + End: document.PositionAt(e), + }, + }) + } + return true + }) + return nil +} + +func (h *CommandHandler) Delete(uri protocol.DocumentURI) { + if strings.HasSuffix(uri.Path(), ".mcfunction") { + stores.McFunctionPath.Delete(uri) + } + for _, entry := range commandEntries { + if entry.Store != nil { + entry.Store.Delete(uri) + } + } +} + +func (h *CommandHandler) Completions(document *textdocument.TextDocument, position protocol.Position) []protocol.CompletionItem { + result := []protocol.CompletionItem{} + parsed := h.parseLine(document, position) + root := parsed.Root + rOffset := parsed.RelativeOffset + startOffset := parsed.StartOffset + line := parsed.Content + + node := mcfunction.NodeAt(root, rOffset) + rStart, rEnd := node.Range() + cursorRange := protocol.Range{ + Start: position, + End: position, + } + nodeRange := protocol.Range{ + Start: document.PositionAt(startOffset + rStart), + End: document.PositionAt(startOffset + rEnd), + } + switch node.Kind() { + case mcfunction.NodeKindFile: + result = h.commandCompletions(cursorRange) + case mcfunction.NodeKindCommandLit: + result = h.commandCompletions(nodeRange) + case mcfunction.NodeKindCommandArg: + arg, ok := node.(mcfunction.INodeArg) + if ok { + switch arg.ParamKind() { + case mcfunction.ParameterKindMap, mcfunction.ParameterKindMapPair, mcfunction.ParameterKindSelectorArg, mcfunction.ParameterKindMapJSON: + return h.mapCompletions(arg, cursorRange, nodeRange) + case mcfunction.ParameterKindRawMessage: + doc := document.CreateVirtualDocument(nodeRange) + rawMessage.CommandHandler = h + return rawMessage.Completions(doc, position) + case mcfunction.ParameterKindItemNbt: + doc := document.CreateVirtualDocument(nodeRange) + return itemNbt.Completions(doc, position) + } + } + invalid := node.Parent().Kind() == mcfunction.NodeKindInvalidCommand + if _, ok := node.(mcfunction.INodeCommand); invalid || !ok { + root, _ := h.Parser.Parse(line[:rStart]) + n := mcfunction.NodeAt(root, rStart) + if n, ok := n.(mcfunction.INodeCommand); ok { + node = n + cursorRange = nodeRange + } + } + fallthrough + case mcfunction.NodeKindCommand: + nodeCommand, ok := node.(mcfunction.INodeCommand) + if !ok { + log.Printf("Failed to cast node to INodeCommand") + return result + } + result = h.paramCompletions(nodeCommand, cursorRange) + } + return result +} + +func (h *CommandHandler) commandCompletions(editRange protocol.Range) []protocol.CompletionItem { + result := []protocol.CompletionItem{} + set := mapset.NewThreadUnsafeSet[string]() + for name, spec := range h.Parser.RegisteredCommands() { + if set.ContainsOne(name) { + continue + } + set.Add(name) + result = append(result, protocol.CompletionItem{ + Label: name, + Detail: spec.Description, + Kind: protocol.MethodCompletion, + TextEdit: &protocol.Or_CompletionItem_textEdit{ + Value: protocol.TextEdit{ + NewText: name, + Range: editRange, + }, + }, + }) + } + return result +} + +func (h *CommandHandler) innerCompletions(node mcfunction.INodeCommand, paramSpec *mcfunction.ParameterSpec, editRange protocol.Range) []protocol.CompletionItem { + result := []protocol.CompletionItem{} + set := mapset.NewThreadUnsafeSet[string]() + escape := func(s string) string { + if strings.ContainsAny(s, " /") { + s = `"` + s + `"` + } + if h.EscapeQuotes { + s = strings.ReplaceAll(s, `"`, `\"`) + } + return s + } + addItem := func(value string, kind ...protocol.CompletionItemKind) { + if set.ContainsOne(value) { + return + } + set.Add(value) + var k protocol.CompletionItemKind + if len(kind) > 0 { + k = kind[0] + } + result = append(result, protocol.CompletionItem{ + Label: value, + Kind: k, + TextEdit: &protocol.Or_CompletionItem_textEdit{ + Value: protocol.TextEdit{ + NewText: value, + Range: editRange, + }, + }, + }) + } + var paramCompletions func(param *mcfunction.ParameterSpec) + paramCompletions = func(param *mcfunction.ParameterSpec) { + if len(param.Literals) > 0 { + for _, lit := range param.Literals { + addItem(escape(lit), protocol.KeywordCompletion) + } + } + switch param.Kind { + case mcfunction.ParameterKindNumber: + addItem("0.0") + case mcfunction.ParameterKindInteger: + addItem("0") + case mcfunction.ParameterKindBoolean: + addItem("true", protocol.KeywordCompletion) + addItem("false", protocol.KeywordCompletion) + case mcfunction.ParameterKindSelector: + for sel, ok := range h.Parser.GetSelectors() { + if ok { + addItem("@" + sel) + } + } + case mcfunction.ParameterKindMap: + result = append(result, protocol.CompletionItem{ + Label: "[]", + Kind: protocol.SnippetCompletion, + InsertTextFormat: &snippetTextFormat, + InsertText: "[$1=$0]", + }) + case mcfunction.ParameterKindMapJSON, mcfunction.ParameterKindJSON: + result = append(result, protocol.CompletionItem{ + Label: "{}", + Kind: protocol.SnippetCompletion, + InsertTextFormat: &snippetTextFormat, + InsertText: "{$0}", + }) + case mcfunction.ParameterKindVector2: + addItem("~~") + addItem("0 0") + addItem("^^") + case mcfunction.ParameterKindVector3: + addItem("~~~") + addItem("0 0 0") + addItem("^^^") + case mcfunction.ParameterKindRange: + addItem("0..0") + addItem("..0") + addItem("0..") + addItem("!0..0") + case mcfunction.ParameterKindSuffixedInteger: + addItem("1" + param.Suffix) + case mcfunction.ParameterKindWildcardInteger: + addItem("*") + addItem("0") + case mcfunction.ParameterKindChainedCommand: + if node != nil { + for _, o := range node.OverloadStates() { + paramCompletions(&o.Parameters()[0]) + } + } + case mcfunction.ParameterKindCommand: + for name := range h.Parser.RegisteredCommands() { + addItem(name, protocol.MethodCompletion) + } + case mcfunction.ParameterKindRawMessage: + result = append(result, protocol.CompletionItem{ + Label: "Raw Message Snippet...", + Kind: protocol.SnippetCompletion, + InsertTextFormat: &snippetTextFormat, + InsertText: escape(`{"rawtext":[$0]}`), + }) + case mcfunction.ParameterKindItemNbt: + result = append(result, protocol.CompletionItem{ + Label: "Item NBT Snippet...", + Kind: protocol.SnippetCompletion, + InsertTextFormat: &snippetTextFormat, + InsertText: escape(`{$0}`), + }) + case mcfunction.ParameterKindRelativeNumber: + addItem("~") + addItem("0") + } + } + tagSet := mapset.NewThreadUnsafeSet[string]() + tagCompletions := func(param *mcfunction.ParameterSpec) { + for _, tag := range param.Tags { + if tagSet.ContainsOne(tag) { + continue + } + tagSet.Add(tag) + entry, ok := commandEntries[tag] + if !ok || entry.Source == nil { + continue + } + for _, item := range entry.Source(node) { + value := item.Value + if entry.Transform != nil { + value = entry.Transform(value) + } + addItem(escape(value)) + } + if entry.Store != nil && entry.Store.VanillaData != nil { + for value := range mapset.Elements(entry.Store.VanillaData) { + if entry.Namespaced && !strings.HasPrefix(value, "minecraft:") { + continue + } + addItem(escape(value), protocol.EnumCompletion) + } + } + } + } + if node != nil { + for _, o := range node.OverloadStates() { + if !o.Matched() { + continue + } + param, ok := o.Peek() + if !ok { + continue + } + paramCompletions(¶m) + tagCompletions(¶m) + } + } + if paramSpec != nil { + paramCompletions(paramSpec) + tagCompletions(paramSpec) + } + return result +} + +func (h *CommandHandler) paramCompletions(node mcfunction.INodeCommand, editRange protocol.Range) []protocol.CompletionItem { + return h.innerCompletions(node, nil, editRange) +} + +func (h *CommandHandler) paramSpecCompletions(spec *mcfunction.ParameterSpec, editRange protocol.Range) []protocol.CompletionItem { + return h.innerCompletions(nil, spec, editRange) +} + +func (h *CommandHandler) mapCompletions(node mcfunction.INodeArg, cursorRange protocol.Range, nodeRange protocol.Range) []protocol.CompletionItem { + keyCompletions := func(spec *mcfunction.ParameterSpec, keys []string, editRange protocol.Range) []protocol.CompletionItem { + var result []protocol.CompletionItem + for _, key := range keys { + result = append(result, protocol.CompletionItem{ + Label: key, + Kind: protocol.FieldCompletion, + TextEdit: &protocol.Or_CompletionItem_textEdit{ + Value: protocol.TextEdit{ + NewText: key, + Range: editRange, + }, + }, + }) + } + if spec != nil && spec.Kind != mcfunction.ParameterKindUnknown { + result = slices.Concat(result, h.paramSpecCompletions(spec, editRange)) + } + return result + } + switch n := node.(type) { + case mcfunction.INodeArgMap: + spec, _ := n.MapSpec().KeySpec() + return keyCompletions(spec, n.MapSpec().Keys(), cursorRange) + case mcfunction.INodeArgPairChild: + kind := n.PairKind() + switch kind { + case mcfunction.PairKindKey: + spec, _ := n.KeySpec() + keys := n.Keys() + return keyCompletions(&spec, keys, nodeRange) + case mcfunction.PairKindEqual, mcfunction.PairKindValue: + spec, ok := n.ValueSpec() + if ok { + if kind == mcfunction.PairKindValue { + cursorRange = nodeRange + } + return h.paramSpecCompletions(&spec, cursorRange) + } + } + } + return []protocol.CompletionItem{} +} + +func (h *CommandHandler) Definitions(document *textdocument.TextDocument, position protocol.Position) []protocol.LocationLink { + result := []protocol.LocationLink{} + parsed := h.parseLine(document, position) + root := parsed.Root + rOffset := parsed.RelativeOffset + startOffset := parsed.StartOffset + line := parsed.Content + if root == nil { + return nil + } + node := mcfunction.NodeAt(root, rOffset) + nodeSpec, ok := node.(mcfunction.NodeParam) + if !ok { + return result + } + paramSpec, ok := nodeSpec.ParamSpec() + if !ok { + return result + } + rStart, rEnd := node.Range() + nodeRange := protocol.Range{ + Start: document.PositionAt(startOffset + rStart), + End: document.PositionAt(startOffset + rEnd), + } + nodeValue := node.Text(line) + if h.EscapeQuotes { + nodeValue = strings.Trim(nodeValue, `\"`) + } else { + nodeValue = strings.Trim(nodeValue, `"`) + } + for _, tag := range paramSpec.Tags { + entry, ok := commandEntries[tag] + if !ok || entry.Source == nil { + continue + } + for _, item := range entry.Source(node) { + value := item.Value + if entry.Transform != nil { + value = entry.Transform(value) + } + if value != nodeValue { + continue + } + location := protocol.LocationLink{ + OriginSelectionRange: &nodeRange, + TargetURI: item.URI, + } + if item.Range != nil { + location.TargetRange = *item.Range + location.TargetSelectionRange = *item.Range + } + result = append(result, location) + } + } + return result +} + +func (h *CommandHandler) PrepareRename(document *textdocument.TextDocument, position protocol.Position) *protocol.PrepareRenamePlaceholder { + parsed := h.parseLine(document, position) + root := parsed.Root + rOffset := parsed.RelativeOffset + startOffset := parsed.StartOffset + line := parsed.Content + if root == nil { + return nil + } + node := mcfunction.NodeAt(root, rOffset) + nodeSpec, ok := node.(mcfunction.NodeParam) + if !ok { + return nil + } + paramSpec, ok := nodeSpec.ParamSpec() + if !ok { + return nil + } + rStart, rEnd := node.Range() + nodeRange := protocol.Range{ + Start: document.PositionAt(startOffset + rStart), + End: document.PositionAt(startOffset + rEnd), + } + nodeValue := node.Text(line) + for _, tag := range paramSpec.Tags { + entry, ok := commandEntries[tag] + if !ok || entry.DisableRename { + continue + } + return &protocol.PrepareRenamePlaceholder{ + Range: nodeRange, + Placeholder: nodeValue, + } + } + return nil +} + +func (h *CommandHandler) Rename(document *textdocument.TextDocument, position protocol.Position, newName string) *protocol.WorkspaceEdit { + parsed := h.parseLine(document, position) + root := parsed.Root + rOffset := parsed.RelativeOffset + line := parsed.Content + if root == nil { + return nil + } + node := mcfunction.NodeAt(root, rOffset) + nodeSpec, ok := node.(mcfunction.NodeParam) + if !ok { + return nil + } + paramSpec, ok := nodeSpec.ParamSpec() + if !ok { + return nil + } + nodeValue := node.Text(line) + // TODO: Check cross rename between unescaped and escaped strings + changes := make(map[protocol.DocumentURI][]protocol.TextEdit) + for _, tag := range paramSpec.Tags { + entry, ok := commandEntries[tag] + if !ok || entry.DisableRename { + continue + } + items := entry.Source(node) + if entry.References != nil { + items = slices.Concat(items, entry.References(node)) + } + for _, item := range items { + if item.Value != nodeValue { + continue + } + edit := protocol.TextEdit{ + NewText: newName, + Range: *item.Range, + } + changes[item.URI] = append(changes[item.URI], edit) + } + } + return &protocol.WorkspaceEdit{Changes: changes} +} + +func (h *CommandHandler) Hover(document *textdocument.TextDocument, position protocol.Position) *protocol.Hover { + parsed := h.parseLine(document, position) + root := parsed.Root + rOffset := parsed.RelativeOffset + if root == nil { + return nil + } + node := mcfunction.NodeAt(root, rOffset) + var commandNode mcfunction.INodeCommand + switch n := node.(type) { + case mcfunction.INodeCommand: + commandNode = n + case mcfunction.INodeArg: + if parent := n.CommandNode(); parent != nil && parent.IsValid() { + commandNode = parent + } + } + if commandNode == nil { + return nil + } + spec := commandNode.Spec() + if spec == nil { + return nil + } + return &protocol.Hover{ + Contents: protocol.MarkupContent{ + Kind: protocol.Markdown, + Value: "```\n" + + commandNode.CommandName() + + "\n```\n" + + spec.Description, + }, + } +} + +func (h *CommandHandler) SignatureHelp(document *textdocument.TextDocument, position protocol.Position) *protocol.SignatureHelp { + parsed := h.parseLine(document, position) + root := parsed.Root + rOffset := parsed.RelativeOffset + line := parsed.Content + if root == nil { + return nil + } + node := mcfunction.NodeAt(root, rOffset) + var commandNode mcfunction.INodeCommand + switch n := node.(type) { + case mcfunction.INodeCommand: + commandNode = n + case mcfunction.INodeArg: + if parent := n.CommandNode(); parent != nil && parent.IsValid() { + commandNode = parent + } else { + s, _ := n.Range() + root, _ := h.Parser.Parse(line[:s]) + node = mcfunction.NodeAt(root, s) + if n, ok := node.(mcfunction.INodeCommand); ok { + commandNode = n + } + } + } + if commandNode == nil { + return nil + } + spec := commandNode.Spec() + signatures := make([]protocol.SignatureInformation, 0, len(commandNode.OverloadStates())) + for _, o := range commandNode.OverloadStates() { + if !o.Matched() { + continue + } + params := o.Parameters() + index := uint32(o.Index()) + paramLabels := make([]string, len(params)) + for j, p := range params { + paramLabels[j] = p.ToString() + } + signatures = append(signatures, protocol.SignatureInformation{ + Label: commandNode.CommandName() + " " + strings.Join(paramLabels, " "), + Documentation: &protocol.Or_SignatureInformation_documentation{ + Value: spec.Description, + }, + Parameters: sliceutil.Map(paramLabels, func(label string) protocol.ParameterInformation { + return protocol.ParameterInformation{ + Label: label, + } + }), + ActiveParameter: index, + }) + } + return &protocol.SignatureHelp{ + Signatures: signatures, + } +} + +func (h *CommandHandler) ComputeSemanticTokens(document *textdocument.TextDocument) []semtok.Token { + content := document.GetContent() + root, _ := h.Parser.Parse(content) + tokens := []semtok.Token{} + molangRanges := []protocol.Range{} + isMolang := func(node mcfunction.INodeArg) bool { + param, ok := node.ParamSpec() + if ok && slices.Contains(param.Tags, mcfunction.TagMolang) { + start, end := node.Range() + length := end - start + if length >= 2 { + if content[start] == '"' && content[end-1] == '"' { + return true + } + } + } + return false + } + mcfunction.WalkNodeTree(root, func(i mcfunction.INode) bool { + start, end := i.Range() + length := end - start + pA := document.PositionAt(start) + pB := document.PositionAt(end) + switch n := i.(type) { + case mcfunction.INodeCommand: + if p, ok := i.(mcfunction.INodeArg); n.Kind() != mcfunction.NodeKindCommandArg || (ok && p.ParamKind() == mcfunction.ParameterKindCommand) { + tokens = append(tokens, semtok.Token{ + Type: semtok.TokNamespace, + Line: pA.Line, + Start: pA.Character, + Len: uint32(len(n.CommandName())), + }) + } + case mcfunction.INodeArg: + if isMolang(n) { + tokens = append(tokens, semtok.Token{ + Type: semtok.TokString, + Line: pA.Line, + Start: pA.Character, + Len: 1, + }) + tokens = append(tokens, semtok.Token{ + Type: semtok.TokString, + Line: pB.Line, + Start: pB.Character - 1, + Len: 1, + }) + pA.Character += 1 + pB.Character -= 1 + molangRanges = append(molangRanges, protocol.Range{ + Start: pA, + End: pB, + }) + } else if tokType, ok := commandParamTokenMap[n.ParamKind()]; ok { + spec, ok := n.ParamSpec() + if ok && slices.Contains(spec.Tags, mcfunction.TagExecuteChain) { + tokType = semtok.TokKeyword + } + tokens = append(tokens, semtok.Token{ + Type: tokType, + Line: pA.Line, + Start: pA.Character, + Len: length, + }) + } + } + return true + }) + molangDocument := document.CreateVirtualDocument(molangRanges...) + tokens = slices.Concat(tokens, Molang.ComputeSemanticTokens(molangDocument)) + return tokens +} + +func (h *CommandHandler) SemanticTokens(document *textdocument.TextDocument) *protocol.SemanticTokens { + tokens := h.ComputeSemanticTokens(document) + return &protocol.SemanticTokens{ + Data: semtok.Encode(tokens, tokenType, tokenModifier), + } +} + +func (h *CommandHandler) parseLine(document *textdocument.TextDocument, position protocol.Position) parsedCommandLine { + content := document.GetContent() + startOffset := document.OffsetAt(protocol.Position{ + Line: position.Line, + }) + offset := document.OffsetAt(position) + rOffset := offset - startOffset + line := content[startOffset:] + root, _ := h.Parser.Parse(line) + return parsedCommandLine{ + Content: line, + StartOffset: startOffset, + RelativeOffset: rOffset, + Root: root, + } +} + +type parsedCommandLine struct { + Content []rune + StartOffset uint32 + RelativeOffset uint32 + Root mcfunction.INode +} + +var commandParamTokenMap = map[mcfunction.ParameterKind]semtok.Type{ + mcfunction.ParameterKindLiteral: semtok.TokMethod, + mcfunction.ParameterKindString: semtok.TokString, + mcfunction.ParameterKindNumber: semtok.TokNumber, + mcfunction.ParameterKindInteger: semtok.TokNumber, + mcfunction.ParameterKindBoolean: semtok.TokMacro, + mcfunction.ParameterKindSelector: semtok.TokEnumMember, + mcfunction.ParameterKindMap: semtok.TokEnumMember, + mcfunction.ParameterKindRange: semtok.TokNumber, + mcfunction.ParameterKindSuffixedInteger: semtok.TokNumber, + mcfunction.ParameterKindWildcardInteger: semtok.TokNumber, + mcfunction.ParameterKindChainedCommand: semtok.TokKeyword, + mcfunction.ParameterKindRawMessage: semtok.TokString, + mcfunction.ParameterKindItemNbt: semtok.TokString, + mcfunction.ParameterKindRelativeNumber: semtok.TokNumber, +} + +type commandEntry struct { + Store *stores.SymbolStore + Source func(node mcfunction.INode) []core.Symbol + References func(node mcfunction.INode) []core.Symbol + Transform func(s string) string + Scope func(node mcfunction.INode) string + Namespaced bool + DisableRename bool +} + +var commandEntries = map[string]commandEntry{ + mcfunction.TagAimAssistId: { + Store: stores.AimAssistCategory.References, + Source: func(node mcfunction.INode) []core.Symbol { + return stores.AimAssistCategory.Source.Get() + }, + References: func(node mcfunction.INode) []core.Symbol { + return stores.AimAssistCategory.References.Get() + }, + }, + mcfunction.TagBiomeId: { + Store: stores.BiomeId.References, + Source: func(node mcfunction.INode) []core.Symbol { + return stores.BiomeId.Source.Get() + }, + References: func(node mcfunction.INode) []core.Symbol { + return stores.BiomeId.References.Get() + }, + }, + mcfunction.TagBlockId: { + Store: stores.ItemId.References, + Scope: func(node mcfunction.INode) string { + return "block" + }, + Namespaced: true, + Source: func(node mcfunction.INode) []core.Symbol { + return stores.ItemId.Source.Get("block") + }, + References: func(node mcfunction.INode) []core.Symbol { + return stores.ItemId.References.Get("block") + }, + }, + mcfunction.TagBlockState: { + Store: stores.BlockState.References, + Source: func(node mcfunction.INode) []core.Symbol { + return stores.BlockState.Source.Get() + }, + References: func(node mcfunction.INode) []core.Symbol { + return stores.BlockState.References.Get() + }, + }, + mcfunction.TagCameraId: { + Store: stores.CameraId.References, + Source: func(node mcfunction.INode) []core.Symbol { + return stores.CameraId.Source.Get() + }, + References: func(node mcfunction.INode) []core.Symbol { + return stores.CameraId.References.Get() + }, + }, + mcfunction.TagClientAnimationId: { + Store: stores.ClientAnimation.References, + Source: func(node mcfunction.INode) []core.Symbol { + return stores.ClientAnimation.Source.Get() + }, + References: func(node mcfunction.INode) []core.Symbol { + return stores.ClientAnimation.References.Get() + }, + }, + mcfunction.TagDialogueId: { + Store: stores.DialogueId.References, + Source: func(node mcfunction.INode) []core.Symbol { + return stores.DialogueId.Source.Get() + }, + References: func(node mcfunction.INode) []core.Symbol { + return stores.DialogueId.References.Get() + }, + }, + mcfunction.TagEntityEvent: { + DisableRename: true, + Store: stores.EntityEvent.References, + Source: func(node mcfunction.INode) []core.Symbol { + return stores.EntityEvent.Source.Get() + }, + }, + mcfunction.TagEntityId: { + Store: stores.EntityId.References, + Namespaced: true, + Source: func(node mcfunction.INode) []core.Symbol { + return stores.EntityId.Source.Get() + }, + References: func(node mcfunction.INode) []core.Symbol { + return stores.EntityId.References.Get() + }, + }, + mcfunction.TagFeatureId: { + Store: stores.FeatureId.References, + Source: func(node mcfunction.INode) []core.Symbol { + return stores.FeatureId.Source.Get() + }, + References: func(node mcfunction.INode) []core.Symbol { + return stores.FeatureId.References.Get() + }, + }, + mcfunction.TagFeatureRuleId: { + Store: stores.FeatureRuleId.References, + Source: func(node mcfunction.INode) []core.Symbol { + return stores.FeatureRuleId.Source.Get() + }, + References: func(node mcfunction.INode) []core.Symbol { + return stores.FeatureRuleId.References.Get() + }, + }, + mcfunction.TagFogId: { + Store: stores.Fog.References, + Source: func(node mcfunction.INode) []core.Symbol { + return stores.Fog.Source.Get() + }, + References: func(node mcfunction.INode) []core.Symbol { + return stores.Fog.References.Get() + }, + }, + mcfunction.TagFunctionFile: { + DisableRename: true, + Source: func(node mcfunction.INode) []core.Symbol { + return stores.McFunctionPath.Get() + }, + Transform: func(s string) string { + return strings.TrimPrefix(s, "functions/") + }, + }, + mcfunction.TagItemId: { + Store: stores.ItemId.References, + Namespaced: true, + Source: func(node mcfunction.INode) []core.Symbol { + return stores.ItemId.Source.Get() + }, + References: func(node mcfunction.INode) []core.Symbol { + return stores.ItemId.References.Get() + }, + }, + mcfunction.TagJigsawId: { + Store: stores.WorldgenJigsaw.References, + Source: func(node mcfunction.INode) []core.Symbol { + return stores.WorldgenJigsaw.Source.Get() + }, + References: func(node mcfunction.INode) []core.Symbol { + return stores.WorldgenJigsaw.References.Get() + }, + }, + mcfunction.TagJigsawTemplatePoolId: { + Store: stores.WorldgenTemplatePool.References, + Source: func(node mcfunction.INode) []core.Symbol { + return stores.WorldgenTemplatePool.Source.Get() + }, + References: func(node mcfunction.INode) []core.Symbol { + return stores.WorldgenTemplatePool.References.Get() + }, + }, + mcfunction.TagLootTableFile: { + DisableRename: true, + Source: func(node mcfunction.INode) []core.Symbol { + return stores.LootTablePath.Get() + }, + Transform: func(s string) string { + s = strings.TrimPrefix(s, "loot_tables/") + s = strings.TrimSuffix(s, ".json") + return s + }, + }, + mcfunction.TagMusicId: { + Store: stores.MusicDefinition.References, + Source: func(node mcfunction.INode) []core.Symbol { + return stores.MusicDefinition.Source.Get() + }, + References: func(node mcfunction.INode) []core.Symbol { + return stores.MusicDefinition.References.Get() + }, + }, + mcfunction.TagProvidedFogId: { + Store: stores.ProvidedFogId.Source, + Source: func(node mcfunction.INode) []core.Symbol { + return stores.ProvidedFogId.Source.Get() + }, + }, + mcfunction.TagRecipeId: { + Store: stores.RecipeId.References, + Source: func(node mcfunction.INode) []core.Symbol { + return stores.RecipeId.Source.Get() + }, + References: func(node mcfunction.INode) []core.Symbol { + return stores.RecipeId.References.Get() + }, + }, + mcfunction.TagSoundId: { + Store: stores.SoundDefinition.References, + Source: func(node mcfunction.INode) []core.Symbol { + return stores.SoundDefinition.Source.Get() + }, + References: func(node mcfunction.INode) []core.Symbol { + return stores.SoundDefinition.References.Get() + }, + }, + mcfunction.TagStructureFile: { + DisableRename: true, + Source: func(node mcfunction.INode) []core.Symbol { + return stores.StructurePath.Get() + }, + }, + mcfunction.TagTagId: { + Store: stores.Tag.Source, + Source: func(node mcfunction.INode) []core.Symbol { + return stores.Tag.Source.Get() + }, + }, + mcfunction.TagTickingAreaId: { + Store: stores.TickingArea.Source, + Source: func(node mcfunction.INode) []core.Symbol { + return stores.TickingArea.Source.Get() + }, + }, + mcfunction.TagTypeFamilyId: { + Store: stores.EntityFamily.References, + Source: func(node mcfunction.INode) []core.Symbol { + return stores.EntityFamily.Source.Get() + }, + References: func(node mcfunction.INode) []core.Symbol { + return stores.EntityFamily.References.Get() + }, + }, + mcfunction.TagScoreboardObjectiveId: { + Store: stores.ScoreboardObjective.Source, + Source: func(node mcfunction.INode) []core.Symbol { + return stores.ScoreboardObjective.Source.Get() + }, + }, +} + +var rawMessage = &JsonRawMessageHandler{ + JsonSnippetHandler: &JsonSnippetHandler{ + JsonHandler: &JsonHandler{ + Entries: []JsonEntry{ + { + Store: stores.Lang.References, + Path: []shared.JsonPath{shared.JsonValue("rawtext/**/translate")}, + Source: func(ctx *JsonContext) []core.Symbol { + return stores.Lang.Source.Get() + }, + References: func(ctx *JsonContext) []core.Symbol { + return stores.Lang.References.Get() + }, + }, + { + Store: stores.ScoreboardObjective.Source, + Path: []shared.JsonPath{shared.JsonValue("rawtext/**/score/objective")}, + Source: func(ctx *JsonContext) []core.Symbol { + return stores.ScoreboardObjective.Source.Get() + }, + References: func(ctx *JsonContext) []core.Symbol { + return nil + }, + }, + }, + }, + SnippetEntries: []SnippetEntry{ + { + Path: []shared.JsonPath{shared.JsonValue("**/rawtext/*")}, + Snippets: []Snippet{ + { + Label: "Text", + Value: `{"text":"$0"}`, + }, + { + Label: "Score", + Value: `{"score":{"name":"$0","objective":"$1"}}`, + }, + { + Label: "Translate", + Value: `{"translate":"$0"}`, + }, + { + Label: "Translate with", + Value: `{"translate":"$1","with":{"rawtext":[$0]}}`, + }, + }, + }, + { + Path: []shared.JsonPath{shared.JsonKey("**/rawtext/**")}, + Snippets: []Snippet{ + { + Label: "With", + Value: `"with":{"rawtext":[$0]}`, + }, + }, + }, + { + Path: []shared.JsonPath{shared.JsonValue("**/rawtext/**/with/*")}, + Snippets: []Snippet{ + { + Label: "Rawtext", + Value: `{"rawtext":[$0]}`, + }, + }, + }, + }, + }, +} + +var itemNbt = &JsonSnippetHandler{ + JsonHandler: &JsonHandler{ + Entries: []JsonEntry{ + { + Store: stores.ItemId.References, + Path: []shared.JsonPath{ + shared.JsonValue("minecraft:can_place_on/blocks/*"), + shared.JsonValue("minecraft:can_destroy/blocks/*"), + }, + ScopeKey: func(ctx *JsonContext) string { + return "block" + }, + Source: func(ctx *JsonContext) []core.Symbol { + return stores.ItemId.Source.Get("block") + }, + References: func(ctx *JsonContext) []core.Symbol { + return stores.ItemId.References.Get("block") + }, + }, + }, + }, + SnippetEntries: []SnippetEntry{ + { + Path: []shared.JsonPath{shared.JsonKey("*")}, + Snippets: []Snippet{ + { + Label: "Can place on", + Value: `"minecraft:can_place_on":{"blocks":[$0]}`, + }, + { + Label: "Can destroy", + Value: `"minecraft:can_destroy":{"blocks":[$0]}`, + }, + { + Label: "Keep on death", + Value: `"minecraft:keep_on_death":{}`, + }, + { + Label: "Lock in inventory", + Value: `"minecraft:item_lock":{"mode":"lock_in_inventory"}"`, + }, + { + Label: "Lock in slot", + Value: `"minecraft:item_lock":{"mode":"lock_in_slot"}"`, + }, + }, + }, + }, +} diff --git a/handlers/handler_json.go b/handlers/handler_json.go index 43b6e5d..7a3bafe 100644 --- a/handlers/handler_json.go +++ b/handlers/handler_json.go @@ -59,6 +59,10 @@ func (j *JsonHandler) Parse(uri protocol.DocumentURI) error { if err != nil { return err } + return j.ParseDocument(document) +} + +func (j *JsonHandler) ParseDocument(document *textdocument.TextDocument) error { root, _ := jsonc.ParseTree(document.GetText(), nil) for _, entry := range j.Entries { if entry.Store == nil { @@ -71,7 +75,7 @@ func (j *JsonHandler) Parse(uri protocol.DocumentURI) error { continue } ctx := JsonContext{ - URI: uri, + URI: document.URI, NodeValue: nodeValue, GetPath: func() jsonc.Path { return jsonc.GetNodePath(node) @@ -96,7 +100,7 @@ func (j *JsonHandler) Parse(uri protocol.DocumentURI) error { } entry.Store.Insert(scope, core.Symbol{ Value: nodeValue, - URI: uri, + URI: document.URI, Range: &protocol.Range{ Start: document.PositionAt(node.Offset + 1), End: document.PositionAt(node.Offset + node.Length - 1), diff --git a/handlers/handler_json_rawmessage.go b/handlers/handler_json_rawmessage.go new file mode 100644 index 0000000..753df1a --- /dev/null +++ b/handlers/handler_json_rawmessage.go @@ -0,0 +1,44 @@ +package handlers + +import ( + "github.com/rockide/language-server/internal/jsonc" + "github.com/rockide/language-server/internal/protocol" + "github.com/rockide/language-server/internal/textdocument" +) + +type JsonRawMessageHandler struct { + *JsonSnippetHandler + CommandHandler *CommandHandler +} + +func (j *JsonRawMessageHandler) Completions(document *textdocument.TextDocument, position protocol.Position) []protocol.CompletionItem { + offset := document.OffsetAt(position) + location := jsonc.GetLocation(document.GetText(), offset) + if location == nil { + return nil + } + node := location.PreviousNode + if location.Path.Matches(jsonc.NewPath("**/rawtext/*/score/name")) && j.CommandHandler != nil { + result := []protocol.CompletionItem{} + for selector, ok := range j.CommandHandler.Parser.GetSelectors() { + if !ok { + continue + } + value := `"@` + selector + `"` + result = append(result, protocol.CompletionItem{ + Label: value, + TextEdit: &protocol.Or_CompletionItem_textEdit{ + Value: protocol.TextEdit{ + NewText: value, + Range: protocol.Range{ + Start: document.PositionAt(node.Offset), + End: document.PositionAt(node.Offset + node.Length), + }, + }, + }, + }) + } + return result + } + return j.JsonSnippetHandler.Completions(document, position) +} diff --git a/handlers/handler_json_snippet.go b/handlers/handler_json_snippet.go new file mode 100644 index 0000000..9ba5fd3 --- /dev/null +++ b/handlers/handler_json_snippet.go @@ -0,0 +1,58 @@ +package handlers + +import ( + "github.com/rockide/language-server/internal/jsonc" + "github.com/rockide/language-server/internal/protocol" + "github.com/rockide/language-server/internal/textdocument" + "github.com/rockide/language-server/shared" +) + +type JsonSnippetHandler struct { + *JsonHandler + SnippetEntries []SnippetEntry +} + +type SnippetEntry struct { + Path []shared.JsonPath + Snippets []Snippet +} + +type Snippet struct { + Label string + Value string +} + +var snippetTextFormat = protocol.SnippetTextFormat + +func (j *JsonSnippetHandler) prepareSnippet(location *jsonc.Location) *SnippetEntry { + for _, entry := range j.SnippetEntries { + for _, jsonPath := range entry.Path { + if jsonPath.IsKey == location.IsAtPropertyKey && location.Path.Matches(jsonPath.Path) { + return &entry + } + } + } + return nil +} + +func (j *JsonSnippetHandler) Completions(document *textdocument.TextDocument, position protocol.Position) []protocol.CompletionItem { + offset := document.OffsetAt(position) + location := jsonc.GetLocation(document.GetText(), offset) + if location == nil { + return nil + } + snippetEntry := j.prepareSnippet(location) + if snippetEntry == nil { + return j.JsonHandler.Completions(document, position) + } + result := []protocol.CompletionItem{} + for _, snippet := range snippetEntry.Snippets { + result = append(result, protocol.CompletionItem{ + Label: snippet.Label, + Kind: protocol.SnippetCompletion, + InsertTextFormat: &snippetTextFormat, + InsertText: snippet.Value, + }) + } + return result +} diff --git a/handlers/handlers.go b/handlers/handlers.go index 171b408..6f8743a 100644 --- a/handlers/handlers.go +++ b/handlers/handlers.go @@ -57,6 +57,7 @@ var handlerList = []Handler{ Item, Lang, LootTable, + McFunction, Recipe, SpawnRule, Structure, diff --git a/handlers/mcfunction.go b/handlers/mcfunction.go new file mode 100644 index 0000000..dd34e64 --- /dev/null +++ b/handlers/mcfunction.go @@ -0,0 +1,20 @@ +package handlers + +import ( + "github.com/rockide/language-server/internal/mcfunction" + "github.com/rockide/language-server/internal/mcfunction/builtin" + "github.com/rockide/language-server/shared" +) + +func newCommandParser(options mcfunction.ParserOptions) *mcfunction.Parser { + parser := mcfunction.NewParser(options) + parser.RegisterCommands(builtin.Commands...) + return parser +} + +var defaultCommandParser = newCommandParser(mcfunction.ParserOptions{}) + +var McFunction = &CommandHandler{ + Pattern: shared.FunctionGlob, + Parser: defaultCommandParser, +} diff --git a/handlers/recipe.go b/handlers/recipe.go index b0fcb19..93467c7 100644 --- a/handlers/recipe.go +++ b/handlers/recipe.go @@ -9,6 +9,19 @@ import ( var Recipe = &JsonHandler{ Pattern: shared.RecipeGlob, Entries: []JsonEntry{ + { + Store: stores.RecipeId.Source, + Path: []shared.JsonPath{ + shared.JsonValue("minecraft:recipe_shaped/description/identifier"), + shared.JsonValue("minecraft:recipe_shapeless/description/identifier"), + }, + Source: func(ctx *JsonContext) []core.Symbol { + return stores.RecipeId.References.Get() + }, + References: func(ctx *JsonContext) []core.Symbol { + return stores.RecipeId.Source.Get() + }, + }, { Store: stores.ItemId.References, Path: []shared.JsonPath{ diff --git a/internal/jsonc/path.go b/internal/jsonc/path.go index 3148841..9486a59 100644 --- a/internal/jsonc/path.go +++ b/internal/jsonc/path.go @@ -32,12 +32,15 @@ func (path Path) Matches(pattern Path) bool { return true } - // Attempt to find a matching segment for the next part of the path after "**" - for pathIndex < len(path) && path[pathIndex] != pattern[patternIndex+1] { + // Try to match the rest of the pattern starting from the current pathIndex + patternIndex++ + for pathIndex <= len(path) { + if path[pathIndex:].Matches(pattern[patternIndex:]) { + return true + } pathIndex++ } - patternIndex++ - continue + return false } // Match current segment if pattern[patternIndex] == "*" || path[pathIndex] == pattern[patternIndex] { diff --git a/internal/jsonc/path_test.go b/internal/jsonc/path_test.go index fcfcc1a..49f0c10 100644 --- a/internal/jsonc/path_test.go +++ b/internal/jsonc/path_test.go @@ -21,4 +21,6 @@ func TestPathMatches(t *testing.T) { assertPath(t, jsonc.NewPath("a/b/c"), jsonc.NewPath("b/**"), false) assertPath(t, jsonc.NewPath("a/b/c"), jsonc.NewPath("**/c"), true) assertPath(t, jsonc.NewPath("a/b/c"), jsonc.NewPath("**/d"), false) + assertPath(t, jsonc.NewPath("rawtext/0"), jsonc.NewPath("**/rawtext/*"), true) + assertPath(t, jsonc.NewPath("rawtext/0/with/rawtext/0"), jsonc.NewPath("**/rawtext/*"), true) } diff --git a/internal/mcfunction/builtin/aimassist.go b/internal/mcfunction/builtin/aimassist.go new file mode 100644 index 0000000..b97b880 --- /dev/null +++ b/internal/mcfunction/builtin/aimassist.go @@ -0,0 +1,63 @@ +package builtin + +import "github.com/rockide/language-server/internal/mcfunction" + +var Aimassist = &mcfunction.Spec{ + Name: "aimassist", + Description: "Enable Aim Assist", + Overloads: []mcfunction.SpecOverload{ + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindSelector, + Name: "players", + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "set", + Literals: []string{"set"}, + }, + { + Kind: mcfunction.ParameterKindNumber, + Name: "x angle", + Optional: true, + }, + { + Kind: mcfunction.ParameterKindNumber, + Name: "y angle", + Optional: true, + }, + { + Kind: mcfunction.ParameterKindNumber, + Name: "max distance", + Optional: true, + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "target mode", + Optional: true, + Literals: []string{"angle", "distance"}, + }, + { + Kind: mcfunction.ParameterKindString, + Name: "preset id", + Optional: true, + Tags: []string{mcfunction.TagAimAssistId}, + }, + }, + }, + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindSelector, + Name: "players", + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "clear", + Literals: []string{"clear"}, + }, + }, + }, + }, +} diff --git a/internal/mcfunction/builtin/camera.go b/internal/mcfunction/builtin/camera.go new file mode 100644 index 0000000..8c18702 --- /dev/null +++ b/internal/mcfunction/builtin/camera.go @@ -0,0 +1,1531 @@ +package builtin + +import "github.com/rockide/language-server/internal/mcfunction" + +var easeLiterals = []string{ + "linear", + "spring", + "in_quad", + "out_quad", + "in_out_quad", + "in_cubic", + "out_cubic", + "in_out_cubic", + "in_quart", + "out_quart", + "in_out_quart", + "in_quint", + "out_quint", + "in_out_quint", + "in_sine", + "out_sine", + "in_out_sine", + "in_expo", + "out_expo", + "in_out_expo", + "in_circ", + "out_circ", + "in_out_circ", + "in_bounce", + "out_bounce", + "in_out_bounce", + "in_back", + "out_back", + "in_out_back", + "in_elastic", + "out_elastic", + "in_out_elastic", +} + +var ease = mcfunction.ParameterSpec{ + Kind: mcfunction.ParameterKindLiteral, + Name: "ease", + Literals: easeLiterals, +} + +var colorRange = &mcfunction.NumberRange{ + Min: 0, + Max: 255, +} + +var Camera = &mcfunction.Spec{ + Name: "camera", + Description: "Issues a camera instruction", + Overloads: []mcfunction.SpecOverload{ + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindSelector, + Name: "players", + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "set", + Literals: []string{"set"}, + }, + { + Kind: mcfunction.ParameterKindString, + Name: "preset", + Tags: []string{mcfunction.TagAimAssistId}, + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "ease", + Literals: []string{"ease"}, + }, + { + Kind: mcfunction.ParameterKindNumber, + Name: "easeTime", + }, + ease, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "pos", + Literals: []string{"pos"}, + }, + { + Kind: mcfunction.ParameterKindVector3, + Name: "position", + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "rot", + Literals: []string{"rot"}, + }, + { + Kind: mcfunction.ParameterKindRelativeNumber, + Name: "xRot", + Tags: []string{mcfunction.TagPitch}, + }, + { + Kind: mcfunction.ParameterKindRelativeNumber, + Name: "yRot", + Tags: []string{mcfunction.TagYaw}, + }, + }, + }, + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindSelector, + Name: "players", + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "set", + Literals: []string{"set"}, + }, + { + Kind: mcfunction.ParameterKindString, + Name: "preset", + Tags: []string{mcfunction.TagAimAssistId}, + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "ease", + Literals: []string{"ease"}, + }, + { + Kind: mcfunction.ParameterKindNumber, + Name: "easeTime", + }, + ease, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "pos", + Literals: []string{"pos"}, + }, + { + Kind: mcfunction.ParameterKindVector3, + Name: "position", + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "facing", + Literals: []string{"facing"}, + }, + { + Kind: mcfunction.ParameterKindSelector, + Name: "lookAtEntity", + }, + }, + }, + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindSelector, + Name: "players", + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "set", + Literals: []string{"set"}, + }, + { + Kind: mcfunction.ParameterKindString, + Name: "preset", + Tags: []string{mcfunction.TagAimAssistId}, + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "ease", + Literals: []string{"ease"}, + }, + { + Kind: mcfunction.ParameterKindNumber, + Name: "easeTime", + }, + ease, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "pos", + Literals: []string{"pos"}, + }, + { + Kind: mcfunction.ParameterKindVector3, + Name: "position", + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "facing", + Literals: []string{"facing"}, + }, + { + Kind: mcfunction.ParameterKindVector3, + Name: "lookAtPosition", + }, + }, + }, + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindSelector, + Name: "players", + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "set", + Literals: []string{"set"}, + }, + { + Kind: mcfunction.ParameterKindString, + Name: "preset", + Tags: []string{mcfunction.TagAimAssistId}, + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "ease", + Literals: []string{"ease"}, + }, + { + Kind: mcfunction.ParameterKindNumber, + Name: "easeTime", + }, + ease, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "pos", + Literals: []string{"pos"}, + }, + { + Kind: mcfunction.ParameterKindVector3, + Name: "position", + }, + }, + }, + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindSelector, + Name: "players", + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "set", + Literals: []string{"set"}, + }, + { + Kind: mcfunction.ParameterKindString, + Name: "preset", + Tags: []string{mcfunction.TagAimAssistId}, + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "ease", + Literals: []string{"ease"}, + }, + { + Kind: mcfunction.ParameterKindNumber, + Name: "easeTime", + }, + ease, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "rot", + Literals: []string{"rot"}, + }, + { + Kind: mcfunction.ParameterKindRelativeNumber, + Name: "xRot", + Tags: []string{mcfunction.TagPitch}, + }, + { + Kind: mcfunction.ParameterKindRelativeNumber, + Name: "yRot", + Tags: []string{mcfunction.TagYaw}, + }, + }, + }, + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindSelector, + Name: "players", + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "set", + Literals: []string{"set"}, + }, + { + Kind: mcfunction.ParameterKindString, + Name: "preset", + Tags: []string{mcfunction.TagAimAssistId}, + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "ease", + Literals: []string{"ease"}, + }, + { + Kind: mcfunction.ParameterKindNumber, + Name: "easeTime", + }, + ease, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "facing", + Literals: []string{"facing"}, + }, + { + Kind: mcfunction.ParameterKindSelector, + Name: "lookAtEntity", + }, + }, + }, + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindSelector, + Name: "players", + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "set", + Literals: []string{"set"}, + }, + { + Kind: mcfunction.ParameterKindString, + Name: "preset", + Tags: []string{mcfunction.TagAimAssistId}, + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "ease", + Literals: []string{"ease"}, + }, + { + Kind: mcfunction.ParameterKindNumber, + Name: "easeTime", + }, + ease, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "facing", + Literals: []string{"facing"}, + }, + { + Kind: mcfunction.ParameterKindVector3, + Name: "lookAtPosition", + }, + }, + }, + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindSelector, + Name: "players", + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "set", + Literals: []string{"set"}, + }, + { + Kind: mcfunction.ParameterKindString, + Name: "preset", + Tags: []string{mcfunction.TagAimAssistId}, + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "ease", + Literals: []string{"ease"}, + }, + { + Kind: mcfunction.ParameterKindNumber, + Name: "easeTime", + }, + ease, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "default", + Optional: true, + Literals: []string{"default"}, + }, + }, + }, + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindSelector, + Name: "players", + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "set", + Literals: []string{"set"}, + }, + { + Kind: mcfunction.ParameterKindString, + Name: "preset", + Tags: []string{mcfunction.TagAimAssistId}, + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "pos", + Literals: []string{"pos"}, + }, + { + Kind: mcfunction.ParameterKindVector3, + Name: "position", + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "rot", + Literals: []string{"rot"}, + }, + { + Kind: mcfunction.ParameterKindRelativeNumber, + Name: "xRot", + Tags: []string{mcfunction.TagPitch}, + }, + { + Kind: mcfunction.ParameterKindRelativeNumber, + Name: "yRot", + Tags: []string{mcfunction.TagYaw}, + }, + }, + }, + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindSelector, + Name: "players", + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "set", + Literals: []string{"set"}, + }, + { + Kind: mcfunction.ParameterKindString, + Name: "preset", + Tags: []string{mcfunction.TagAimAssistId}, + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "pos", + Literals: []string{"pos"}, + }, + { + Kind: mcfunction.ParameterKindVector3, + Name: "position", + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "facing", + Literals: []string{"facing"}, + }, + { + Kind: mcfunction.ParameterKindSelector, + Name: "lookAtEntity", + }, + }, + }, + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindSelector, + Name: "players", + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "set", + Literals: []string{"set"}, + }, + { + Kind: mcfunction.ParameterKindString, + Name: "preset", + Tags: []string{mcfunction.TagAimAssistId}, + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "pos", + Literals: []string{"pos"}, + }, + { + Kind: mcfunction.ParameterKindVector3, + Name: "position", + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "facing", + Literals: []string{"facing"}, + }, + { + Kind: mcfunction.ParameterKindVector3, + Name: "lookAtPosition", + }, + }, + }, + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindSelector, + Name: "players", + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "attach_to_entity", + Literals: []string{"attach_to_entity"}, + }, + { + Kind: mcfunction.ParameterKindSelector, + Name: "entity", + }, + }, + }, + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindSelector, + Name: "players", + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "detach_from_entity", + Literals: []string{"detach_from_entity"}, + }, + }, + }, + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindSelector, + Name: "players", + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "targetEntity", + Literals: []string{"target_entity"}, + }, + { + Kind: mcfunction.ParameterKindSelector, + Name: "entity", + }, + }, + }, + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindSelector, + Name: "players", + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "targetEntity", + Literals: []string{"target_entity"}, + }, + { + Kind: mcfunction.ParameterKindSelector, + Name: "entity", + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "targetCenterOffset", + Literals: []string{"targetCenterOffset"}, + }, + { + Kind: mcfunction.ParameterKindNumber, + Name: "xTargetCenterOffset", + }, + { + Kind: mcfunction.ParameterKindNumber, + Name: "yTargetCenterOffset", + }, + { + Kind: mcfunction.ParameterKindNumber, + Name: "zTargetCenterOffset", + }, + }, + }, + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindSelector, + Name: "players", + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "removeTarget", + Literals: []string{"remove_target"}, + }, + }, + }, + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindSelector, + Name: "players", + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "set", + Literals: []string{"set"}, + }, + { + Kind: mcfunction.ParameterKindString, + Name: "preset", + Tags: []string{mcfunction.TagAimAssistId}, + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "view_offset", + Literals: []string{"view_offset"}, + }, + { + Kind: mcfunction.ParameterKindNumber, + Name: "xViewOffset", + }, + { + Kind: mcfunction.ParameterKindNumber, + Name: "yViewOffset", + }, + }, + }, + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindSelector, + Name: "players", + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "set", + Literals: []string{"set"}, + }, + { + Kind: mcfunction.ParameterKindString, + Name: "preset", + Tags: []string{mcfunction.TagAimAssistId}, + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "entity_offset", + Literals: []string{"entity_offset"}, + }, + { + Kind: mcfunction.ParameterKindNumber, + Name: "xEntityOffset", + }, + { + Kind: mcfunction.ParameterKindNumber, + Name: "yEntityOffset", + }, + { + Kind: mcfunction.ParameterKindNumber, + Name: "zEntityOffset", + }, + }, + }, + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindSelector, + Name: "players", + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "set", + Literals: []string{"set"}, + }, + { + Kind: mcfunction.ParameterKindString, + Name: "preset", + Tags: []string{mcfunction.TagAimAssistId}, + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "rot", + Literals: []string{"rot"}, + }, + { + Kind: mcfunction.ParameterKindRelativeNumber, + Name: "xRot", + Tags: []string{mcfunction.TagPitch}, + }, + { + Kind: mcfunction.ParameterKindRelativeNumber, + Name: "yRot", + Tags: []string{mcfunction.TagYaw}, + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "view_offset", + Literals: []string{"view_offset"}, + }, + { + Kind: mcfunction.ParameterKindNumber, + Name: "xViewOffset", + }, + { + Kind: mcfunction.ParameterKindNumber, + Name: "yViewOffset", + }, + }, + }, + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindSelector, + Name: "players", + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "set", + Literals: []string{"set"}, + }, + { + Kind: mcfunction.ParameterKindString, + Name: "preset", + Tags: []string{mcfunction.TagAimAssistId}, + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "rot", + Literals: []string{"rot"}, + }, + { + Kind: mcfunction.ParameterKindRelativeNumber, + Name: "xRot", + Tags: []string{mcfunction.TagPitch}, + }, + { + Kind: mcfunction.ParameterKindRelativeNumber, + Name: "yRot", + Tags: []string{mcfunction.TagYaw}, + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "entity_offset", + Literals: []string{"entity_offset"}, + }, + { + Kind: mcfunction.ParameterKindNumber, + Name: "xEntityOffset", + }, + { + Kind: mcfunction.ParameterKindNumber, + Name: "yEntityOffset", + }, + { + Kind: mcfunction.ParameterKindNumber, + Name: "zEntityOffset", + }, + }, + }, + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindSelector, + Name: "players", + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "set", + Literals: []string{"set"}, + }, + { + Kind: mcfunction.ParameterKindString, + Name: "preset", + Tags: []string{mcfunction.TagAimAssistId}, + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "view_offset", + Literals: []string{"view_offset"}, + }, + { + Kind: mcfunction.ParameterKindNumber, + Name: "xViewOffset", + }, + { + Kind: mcfunction.ParameterKindNumber, + Name: "yViewOffset", + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "entity_offset", + Literals: []string{"entity_offset"}, + }, + { + Kind: mcfunction.ParameterKindNumber, + Name: "xEntityOffset", + }, + { + Kind: mcfunction.ParameterKindNumber, + Name: "yEntityOffset", + }, + { + Kind: mcfunction.ParameterKindNumber, + Name: "zEntityOffset", + }, + }, + }, + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindSelector, + Name: "players", + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "set", + Literals: []string{"set"}, + }, + { + Kind: mcfunction.ParameterKindString, + Name: "preset", + Tags: []string{mcfunction.TagAimAssistId}, + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "rot", + Literals: []string{"rot"}, + }, + { + Kind: mcfunction.ParameterKindRelativeNumber, + Name: "xRot", + Tags: []string{mcfunction.TagPitch}, + }, + { + Kind: mcfunction.ParameterKindRelativeNumber, + Name: "yRot", + Tags: []string{mcfunction.TagYaw}, + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "view_offset", + Literals: []string{"view_offset"}, + }, + { + Kind: mcfunction.ParameterKindNumber, + Name: "xViewOffset", + }, + { + Kind: mcfunction.ParameterKindNumber, + Name: "yViewOffset", + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "entity_offset", + Literals: []string{"entity_offset"}, + }, + { + Kind: mcfunction.ParameterKindNumber, + Name: "xEntityOffset", + }, + { + Kind: mcfunction.ParameterKindNumber, + Name: "yEntityOffset", + }, + { + Kind: mcfunction.ParameterKindNumber, + Name: "zEntityOffset", + }, + }, + }, + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindSelector, + Name: "players", + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "set", + Literals: []string{"set"}, + }, + { + Kind: mcfunction.ParameterKindString, + Name: "preset", + Tags: []string{mcfunction.TagAimAssistId}, + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "ease", + Literals: []string{"ease"}, + }, + { + Kind: mcfunction.ParameterKindNumber, + Name: "easeTime", + }, + ease, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "view_offset", + Literals: []string{"view_offset"}, + }, + { + Kind: mcfunction.ParameterKindNumber, + Name: "xViewOffset", + }, + { + Kind: mcfunction.ParameterKindNumber, + Name: "yViewOffset", + }, + }, + }, + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindSelector, + Name: "players", + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "set", + Literals: []string{"set"}, + }, + { + Kind: mcfunction.ParameterKindString, + Name: "preset", + Tags: []string{mcfunction.TagAimAssistId}, + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "ease", + Literals: []string{"ease"}, + }, + { + Kind: mcfunction.ParameterKindNumber, + Name: "easeTime", + }, + ease, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "entity_offset", + Literals: []string{"entity_offset"}, + }, + { + Kind: mcfunction.ParameterKindNumber, + Name: "xEntityOffset", + }, + { + Kind: mcfunction.ParameterKindNumber, + Name: "yEntityOffset", + }, + { + Kind: mcfunction.ParameterKindNumber, + Name: "zEntityOffset", + }, + }, + }, + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindSelector, + Name: "players", + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "set", + Literals: []string{"set"}, + }, + { + Kind: mcfunction.ParameterKindString, + Name: "preset", + Tags: []string{mcfunction.TagAimAssistId}, + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "ease", + Literals: []string{"ease"}, + }, + { + Kind: mcfunction.ParameterKindNumber, + Name: "easeTime", + }, + ease, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "rot", + Literals: []string{"rot"}, + }, + { + Kind: mcfunction.ParameterKindRelativeNumber, + Name: "xRot", + Tags: []string{mcfunction.TagPitch}, + }, + { + Kind: mcfunction.ParameterKindRelativeNumber, + Name: "yRot", + Tags: []string{mcfunction.TagYaw}, + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "view_offset", + Literals: []string{"view_offset"}, + }, + { + Kind: mcfunction.ParameterKindNumber, + Name: "xViewOffset", + }, + { + Kind: mcfunction.ParameterKindNumber, + Name: "yViewOffset", + }, + }, + }, + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindSelector, + Name: "players", + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "set", + Literals: []string{"set"}, + }, + { + Kind: mcfunction.ParameterKindString, + Name: "preset", + Tags: []string{mcfunction.TagAimAssistId}, + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "ease", + Literals: []string{"ease"}, + }, + { + Kind: mcfunction.ParameterKindNumber, + Name: "easeTime", + }, + ease, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "rot", + Literals: []string{"rot"}, + }, + { + Kind: mcfunction.ParameterKindRelativeNumber, + Name: "xRot", + Tags: []string{mcfunction.TagPitch}, + }, + { + Kind: mcfunction.ParameterKindRelativeNumber, + Name: "yRot", + Tags: []string{mcfunction.TagYaw}, + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "entity_offset", + Literals: []string{"entity_offset"}, + }, + { + Kind: mcfunction.ParameterKindNumber, + Name: "xEntityOffset", + }, + { + Kind: mcfunction.ParameterKindNumber, + Name: "yEntityOffset", + }, + { + Kind: mcfunction.ParameterKindNumber, + Name: "zEntityOffset", + }, + }, + }, + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindSelector, + Name: "players", + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "set", + Literals: []string{"set"}, + }, + { + Kind: mcfunction.ParameterKindString, + Name: "preset", + Tags: []string{mcfunction.TagAimAssistId}, + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "ease", + Literals: []string{"ease"}, + }, + { + Kind: mcfunction.ParameterKindNumber, + Name: "easeTime", + }, + ease, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "view_offset", + Literals: []string{"view_offset"}, + }, + { + Kind: mcfunction.ParameterKindNumber, + Name: "xViewOffset", + }, + { + Kind: mcfunction.ParameterKindNumber, + Name: "yViewOffset", + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "entity_offset", + Literals: []string{"entity_offset"}, + }, + { + Kind: mcfunction.ParameterKindNumber, + Name: "xEntityOffset", + }, + { + Kind: mcfunction.ParameterKindNumber, + Name: "yEntityOffset", + }, + { + Kind: mcfunction.ParameterKindNumber, + Name: "zEntityOffset", + }, + }, + }, + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindSelector, + Name: "players", + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "set", + Literals: []string{"set"}, + }, + { + Kind: mcfunction.ParameterKindString, + Name: "preset", + Tags: []string{mcfunction.TagAimAssistId}, + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "ease", + Literals: []string{"ease"}, + }, + { + Kind: mcfunction.ParameterKindNumber, + Name: "easeTime", + }, + ease, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "rot", + Literals: []string{"rot"}, + }, + { + Kind: mcfunction.ParameterKindRelativeNumber, + Name: "xRot", + Tags: []string{mcfunction.TagPitch}, + }, + { + Kind: mcfunction.ParameterKindRelativeNumber, + Name: "yRot", + Tags: []string{mcfunction.TagYaw}, + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "view_offset", + Literals: []string{"view_offset"}, + }, + { + Kind: mcfunction.ParameterKindNumber, + Name: "xViewOffset", + }, + { + Kind: mcfunction.ParameterKindNumber, + Name: "yViewOffset", + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "entity_offset", + Literals: []string{"entity_offset"}, + }, + { + Kind: mcfunction.ParameterKindNumber, + Name: "xEntityOffset", + }, + { + Kind: mcfunction.ParameterKindNumber, + Name: "yEntityOffset", + }, + { + Kind: mcfunction.ParameterKindNumber, + Name: "zEntityOffset", + }, + }, + }, + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindSelector, + Name: "players", + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "set", + Literals: []string{"set"}, + }, + { + Kind: mcfunction.ParameterKindString, + Name: "preset", + Tags: []string{mcfunction.TagAimAssistId}, + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "pos", + Literals: []string{"pos"}, + }, + { + Kind: mcfunction.ParameterKindVector3, + Name: "position", + }, + }, + }, + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindSelector, + Name: "players", + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "set", + Literals: []string{"set"}, + }, + { + Kind: mcfunction.ParameterKindString, + Name: "preset", + Tags: []string{mcfunction.TagAimAssistId}, + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "rot", + Literals: []string{"rot"}, + }, + { + Kind: mcfunction.ParameterKindRelativeNumber, + Name: "xRot", + Tags: []string{mcfunction.TagPitch}, + }, + { + Kind: mcfunction.ParameterKindRelativeNumber, + Name: "yRot", + Tags: []string{mcfunction.TagYaw}, + }, + }, + }, + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindSelector, + Name: "players", + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "set", + Literals: []string{"set"}, + }, + { + Kind: mcfunction.ParameterKindString, + Name: "preset", + Tags: []string{mcfunction.TagAimAssistId}, + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "facing", + Literals: []string{"facing"}, + }, + { + Kind: mcfunction.ParameterKindSelector, + Name: "lookAtEntity", + }, + }, + }, + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindSelector, + Name: "players", + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "set", + Literals: []string{"set"}, + }, + { + Kind: mcfunction.ParameterKindString, + Name: "preset", + Tags: []string{mcfunction.TagAimAssistId}, + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "facing", + Literals: []string{"facing"}, + }, + { + Kind: mcfunction.ParameterKindVector3, + Name: "lookAtPosition", + }, + }, + }, + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindSelector, + Name: "players", + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "set", + Literals: []string{"set"}, + }, + { + Kind: mcfunction.ParameterKindString, + Name: "preset", + Tags: []string{mcfunction.TagAimAssistId}, + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "default", + Optional: true, + Literals: []string{"default"}, + }, + }, + }, + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindSelector, + Name: "players", + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "clear", + Literals: []string{"clear"}, + }, + }, + }, + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindSelector, + Name: "players", + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "fade", + Literals: []string{"fade"}, + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "time", + Literals: []string{"time"}, + }, + { + Kind: mcfunction.ParameterKindNumber, + Name: "fadeInSeconds", + }, + { + Kind: mcfunction.ParameterKindNumber, + Name: "holdSeconds", + }, + { + Kind: mcfunction.ParameterKindNumber, + Name: "fadeOutSeconds", + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "color", + Literals: []string{"color"}, + }, + { + Kind: mcfunction.ParameterKindInteger, + Name: "red", + Range: colorRange, + }, + { + Kind: mcfunction.ParameterKindInteger, + Name: "green", + Range: colorRange, + }, + { + Kind: mcfunction.ParameterKindInteger, + Name: "blue", + Range: colorRange, + }, + }, + }, + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindSelector, + Name: "players", + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "fade", + Literals: []string{"fade"}, + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "time", + Literals: []string{"time"}, + }, + { + Kind: mcfunction.ParameterKindNumber, + Name: "fadeInSeconds", + }, + { + Kind: mcfunction.ParameterKindNumber, + Name: "holdSeconds", + }, + { + Kind: mcfunction.ParameterKindNumber, + Name: "fadeOutSeconds", + }, + }, + }, + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindSelector, + Name: "players", + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "fade", + Literals: []string{"fade"}, + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "color", + Literals: []string{"color"}, + }, + { + Kind: mcfunction.ParameterKindInteger, + Name: "red", + Range: colorRange, + }, + { + Kind: mcfunction.ParameterKindInteger, + Name: "green", + Range: colorRange, + }, + { + Kind: mcfunction.ParameterKindInteger, + Name: "blue", + Range: colorRange, + }, + }, + }, + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindSelector, + Name: "players", + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "fade", + Literals: []string{"fade"}, + }, + }, + }, + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindSelector, + Name: "players", + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "fov_set", + Literals: []string{"fov_set"}, + }, + { + Kind: mcfunction.ParameterKindNumber, + Name: "fov_value", + }, + { + Kind: mcfunction.ParameterKindNumber, + Name: "fovEaseTime", + Optional: true, + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "fovEaseType", + Optional: true, + Literals: ease.Literals, + }, + }, + }, + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindSelector, + Name: "players", + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "fov_clear", + Literals: []string{"fov_clear"}, + }, + { + Kind: mcfunction.ParameterKindNumber, + Name: "fovEaseTime", + Optional: true, + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "fovEaseType", + Optional: true, + Literals: ease.Literals, + }, + }, + }, + }, +} diff --git a/internal/mcfunction/builtin/camerashake.go b/internal/mcfunction/builtin/camerashake.go new file mode 100644 index 0000000..5fd40ac --- /dev/null +++ b/internal/mcfunction/builtin/camerashake.go @@ -0,0 +1,61 @@ +package builtin + +import ( + "math" + + "github.com/rockide/language-server/internal/mcfunction" +) + +var Camerashake = &mcfunction.Spec{ + Name: "camerashake", + Description: "Applies shaking to the players' camera with a specified intensity and duration.", + Overloads: []mcfunction.SpecOverload{ + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindLiteral, + Name: "action", + Literals: []string{"add"}, + }, + { + Kind: mcfunction.ParameterKindSelector, + Name: "player", + }, + { + Kind: mcfunction.ParameterKindNumber, + Name: "intensity", + Optional: true, + }, + { + Kind: mcfunction.ParameterKindNumber, + Name: "seconds", + Optional: true, + Range: &mcfunction.NumberRange{ + Min: 0, + Max: math.MaxFloat64, + }, + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "shakeType", + Optional: true, + Literals: []string{"positional", "rotational"}, + }, + }, + }, + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindLiteral, + Name: "action", + Literals: []string{"stop"}, + }, + { + Kind: mcfunction.ParameterKindSelector, + Name: "player", + Optional: true, + }, + }, + }, + }, +} diff --git a/internal/mcfunction/builtin/clear.go b/internal/mcfunction/builtin/clear.go new file mode 100644 index 0000000..000bed7 --- /dev/null +++ b/internal/mcfunction/builtin/clear.go @@ -0,0 +1,35 @@ +package builtin + +import "github.com/rockide/language-server/internal/mcfunction" + +var Clear = &mcfunction.Spec{ + Name: "clear", + Description: "Clears items from player inventory.", + Overloads: []mcfunction.SpecOverload{ + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindSelector, + Name: "player", + Optional: true, + }, + { + Kind: mcfunction.ParameterKindString, + Name: "itemName", + Optional: true, + Tags: []string{mcfunction.TagItemId}, + }, + { + Kind: mcfunction.ParameterKindInteger, + Name: "data", + Optional: true, + }, + { + Kind: mcfunction.ParameterKindInteger, + Name: "maxCount", + Optional: true, + }, + }, + }, + }, +} diff --git a/internal/mcfunction/builtin/clearspawnpoint.go b/internal/mcfunction/builtin/clearspawnpoint.go new file mode 100644 index 0000000..623bf70 --- /dev/null +++ b/internal/mcfunction/builtin/clearspawnpoint.go @@ -0,0 +1,19 @@ +package builtin + +import "github.com/rockide/language-server/internal/mcfunction" + +var Clearspawnpoint = &mcfunction.Spec{ + Name: "clearspawnpoint", + Description: "Removes the spawn point for a player.", + Overloads: []mcfunction.SpecOverload{ + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindSelector, + Name: "player", + Optional: true, + }, + }, + }, + }, +} diff --git a/internal/mcfunction/builtin/clone.go b/internal/mcfunction/builtin/clone.go new file mode 100644 index 0000000..3ad23dc --- /dev/null +++ b/internal/mcfunction/builtin/clone.go @@ -0,0 +1,70 @@ +package builtin + +import "github.com/rockide/language-server/internal/mcfunction" + +var Clone = &mcfunction.Spec{ + Name: "clone", + Description: "Clones blocks from one region to another.", + Overloads: []mcfunction.SpecOverload{ + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindVector3, + Name: "begin", + }, + { + Kind: mcfunction.ParameterKindVector3, + Name: "end", + }, + { + Kind: mcfunction.ParameterKindVector3, + Name: "destination", + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "maskMode", + Optional: true, + Literals: []string{"replace", "masked"}, + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "cloneMode", + Optional: true, + Literals: []string{"normal", "force", "move"}, + }, + }, + }, + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindVector3, + Name: "begin", + }, + { + Kind: mcfunction.ParameterKindVector3, + Name: "end", + }, + { + Kind: mcfunction.ParameterKindVector3, + Name: "destination", + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "maskMode", + Literals: []string{"replace", "masked"}, + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "cloneMode", + Literals: []string{"normal", "force", "move"}, + }, + { + Kind: mcfunction.ParameterKindString, + Name: "tileName", + Tags: []string{mcfunction.TagBlockId}, + }, + blockStates, + }, + }, + }, +} diff --git a/internal/mcfunction/builtin/commands.go b/internal/mcfunction/builtin/commands.go new file mode 100644 index 0000000..7a49616 --- /dev/null +++ b/internal/mcfunction/builtin/commands.go @@ -0,0 +1,72 @@ +package builtin + +import "github.com/rockide/language-server/internal/mcfunction" + +var Commands = []*mcfunction.Spec{ + Aimassist, + Camera, + Camerashake, + Clear, + Clearspawnpoint, + Clone, + Controlscheme, + Damage, + Daylock, + Dialogue, + Difficulty, + Effect, + Enchant, + Event, + Execute, + Fill, + Fog, + Function, + Gamemode, + Gamerule, + Gametest, + Give, + Hud, + Inputpermission, + Kill, + Locate, + Loot, + Me, + Mobevent, + Music, + Op, + Particle, + Place, + Playanimation, + Playsound, + Recipe, + Reload, + Replaceitem, + Ride, + Say, + Schedule, + Scoreboard, + Script, + Scriptevent, + Setblock, + Setmaxplayers, + Setworldspawn, + Spawnpoint, + Spreadplayers, + Stopsound, + Structure, + Summon, + Tag, + Teleport, + Tell, + Tellraw, + Testfor, + Testforblock, + Testforblocks, + Tickingarea, + Time, + Title, + Titleraw, + Toggledownfall, + Weather, + Xp, +} diff --git a/internal/mcfunction/builtin/common.go b/internal/mcfunction/builtin/common.go new file mode 100644 index 0000000..e053a32 --- /dev/null +++ b/internal/mcfunction/builtin/common.go @@ -0,0 +1,12 @@ +package builtin + +import "github.com/rockide/language-server/internal/mcfunction" + +var blockStates = mcfunction.ParameterSpec{ + Name: "blockStates", + Kind: mcfunction.ParameterKindMap, + MapSpec: mcfunction.NewMapValueSpec(&mcfunction.ParameterSpec{ + Kind: mcfunction.ParameterKindString, + Tags: []string{mcfunction.TagBlockState}, + }, nil), +} diff --git a/internal/mcfunction/builtin/controlscheme.go b/internal/mcfunction/builtin/controlscheme.go new file mode 100644 index 0000000..2cd23bf --- /dev/null +++ b/internal/mcfunction/builtin/controlscheme.go @@ -0,0 +1,47 @@ +package builtin + +import "github.com/rockide/language-server/internal/mcfunction" + +var Controlscheme = &mcfunction.Spec{ + Name: "controlscheme", + Description: "Sets or clears control scheme.", + Overloads: []mcfunction.SpecOverload{ + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindSelector, + Name: "players", + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "set", + Literals: []string{"set"}, + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "control scheme", + Literals: []string{ + "camera_relative", + "camera_relative_strafe", + "player_relative", + "player_relative_strafe", + "locked_player_relative_strafe", + }, + }, + }, + }, + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindSelector, + Name: "players", + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "clear", + Literals: []string{"clear"}, + }, + }, + }, + }, +} diff --git a/internal/mcfunction/builtin/damage.go b/internal/mcfunction/builtin/damage.go new file mode 100644 index 0000000..aeeecbc --- /dev/null +++ b/internal/mcfunction/builtin/damage.go @@ -0,0 +1,94 @@ +package builtin + +import "github.com/rockide/language-server/internal/mcfunction" + +var damageCauseLiterals = []string{ + "anvil", + "block_explosion", + "campfire", + "charging", + "contact", + "drowning", + "entity_attack", + "entity_explosion", + "fall", + "falling_block", + "fire", + "fire_tick", + "fireworks", + "fly_into_wall", + "freezing", + "lava", + "lightning", + "mace_smash", + "magic", + "magma", + "none", + "override", + "piston", + "projectile", + "ram_attack", + "self_destruct", + "sonic_boom", + "soul_campfire", + "stalactite", + "stalagmite", + "starve", + "suffocation", + "suicide", + "temperature", + "thorns", + "void", + "wither", +} + +var Damage = &mcfunction.Spec{ + Name: "damage", + Description: "Apply damage to the specified entities.", + Overloads: []mcfunction.SpecOverload{ + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindSelector, + Name: "target", + }, + { + Kind: mcfunction.ParameterKindNumber, + Name: "amount", + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "cause", + Optional: true, + Literals: damageCauseLiterals, + }, + }, + }, + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindSelector, + Name: "target", + }, + { + Kind: mcfunction.ParameterKindNumber, + Name: "amount", + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "cause", + Literals: damageCauseLiterals, + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "origin", + Literals: []string{"entity"}, + }, + { + Kind: mcfunction.ParameterKindSelector, + Name: "damager", + }, + }, + }, + }, +} diff --git a/internal/mcfunction/builtin/daylock.go b/internal/mcfunction/builtin/daylock.go new file mode 100644 index 0000000..82b7b49 --- /dev/null +++ b/internal/mcfunction/builtin/daylock.go @@ -0,0 +1,20 @@ +package builtin + +import "github.com/rockide/language-server/internal/mcfunction" + +var Daylock = &mcfunction.Spec{ + Name: "daylock", + Aliases: []string{"alwaysday"}, + Description: "Locks and unlocks the day-night cycle.", + Overloads: []mcfunction.SpecOverload{ + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindBoolean, + Name: "lock", + Optional: true, + }, + }, + }, + }, +} diff --git a/internal/mcfunction/builtin/dialogue.go b/internal/mcfunction/builtin/dialogue.go new file mode 100644 index 0000000..eab8a5a --- /dev/null +++ b/internal/mcfunction/builtin/dialogue.go @@ -0,0 +1,56 @@ +package builtin + +import "github.com/rockide/language-server/internal/mcfunction" + +var Dialogue = &mcfunction.Spec{ + Name: "dialogue", + Description: "Opens NPC dialogue for a player.", + Overloads: []mcfunction.SpecOverload{ + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindLiteral, + Name: "open", + Literals: []string{"open"}, + }, + { + Kind: mcfunction.ParameterKindSelector, + Name: "npc", + }, + { + Kind: mcfunction.ParameterKindSelector, + Name: "player", + }, + { + Kind: mcfunction.ParameterKindString, + Name: "sceneName", + Optional: true, + Tags: []string{mcfunction.TagDialogueId}, + }, + }, + }, + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindLiteral, + Name: "change", + Literals: []string{"change"}, + }, + { + Kind: mcfunction.ParameterKindSelector, + Name: "npc", + }, + { + Kind: mcfunction.ParameterKindString, + Name: "sceneName", + Tags: []string{mcfunction.TagDialogueId}, + }, + { + Kind: mcfunction.ParameterKindSelector, + Name: "players", + Optional: true, + }, + }, + }, + }, +} diff --git a/internal/mcfunction/builtin/difficulty.go b/internal/mcfunction/builtin/difficulty.go new file mode 100644 index 0000000..8ca6626 --- /dev/null +++ b/internal/mcfunction/builtin/difficulty.go @@ -0,0 +1,40 @@ +package builtin + +import "github.com/rockide/language-server/internal/mcfunction" + +var Difficulty = &mcfunction.Spec{ + Name: "difficulty", + Description: "Sets the difficulty level.", + Overloads: []mcfunction.SpecOverload{ + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindLiteral, + Name: "difficulty", + Literals: []string{ + "e", + "easy", + "n", + "normal", + "h", + "hard", + "p", + "peaceful", + }, + }, + }, + }, + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindInteger, + Name: "difficulty", + Range: &mcfunction.NumberRange{ + Min: 0, + Max: 3, + }, + }, + }, + }, + }, +} diff --git a/internal/mcfunction/builtin/effect.go b/internal/mcfunction/builtin/effect.go new file mode 100644 index 0000000..97cd280 --- /dev/null +++ b/internal/mcfunction/builtin/effect.go @@ -0,0 +1,137 @@ +package builtin + +import ( + "math" + + "github.com/rockide/language-server/internal/mcfunction" +) + +var effects = []string{ + "absorption", + "bad_omen", + "blindness", + "breath_of_the_nautilus", + "conduit_power", + "darkness", + "fatal_poison", + "fire_resistance", + "haste", + "health_boost", + "hunger", + "infested", + "instant_damage", + "instant_health", + "invisibility", + "jump_boost", + "levitation", + "mining_fatigue", + "nausea", + "night_vision", + "oozing", + "poison", + "raid_omen", + "regeneration", + "resistance", + "saturation", + "slow_falling", + "slowness", + "speed", + "strength", + "trial_omen", + "village_hero", + "water_breathing", + "weakness", + "weaving", + "wind_charged", + "wither", +} + +var Effect = &mcfunction.Spec{ + Name: "effect", + Description: "Add or remove status effects.", + Overloads: []mcfunction.SpecOverload{ + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindSelector, + Name: "player", + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "Mode", + Literals: []string{"clear"}, + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "effect", + Optional: true, + Literals: effects, + }, + }, + }, + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindSelector, + Name: "player", + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "effect", + Literals: effects, + }, + { + Kind: mcfunction.ParameterKindInteger, + Name: "seconds", + Optional: true, + Range: &mcfunction.NumberRange{ + Min: 0, + Max: math.MaxFloat64, + }, + }, + { + Kind: mcfunction.ParameterKindInteger, + Name: "amplifier", + Optional: true, + Range: &mcfunction.NumberRange{ + Min: 0, + Max: 255, + }, + }, + { + Kind: mcfunction.ParameterKindBoolean, + Name: "hideParticles", + Optional: true, + }, + }, + }, + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindSelector, + Name: "player", + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "effect", + Literals: effects, + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "Mode", + Literals: []string{"infinite"}, + }, + { + Kind: mcfunction.ParameterKindInteger, + Name: "amplifier", + Optional: true, + }, + { + Kind: mcfunction.ParameterKindBoolean, + Name: "hideParticles", + Optional: true, + }, + }, + }, + }, +} diff --git a/internal/mcfunction/builtin/enchant.go b/internal/mcfunction/builtin/enchant.go new file mode 100644 index 0000000..16a8bfc --- /dev/null +++ b/internal/mcfunction/builtin/enchant.go @@ -0,0 +1,89 @@ +package builtin + +import "github.com/rockide/language-server/internal/mcfunction" + +var enchantments = []string{ + "protection", + "fire_protection", + "feather_falling", + "blast_protection", + "projectile_protection", + "thorns", + "respiration", + "depth_strider", + "aqua_affinity", + "sharpness", + "smite", + "bane_of_arthropods", + "knockback", + "fire_aspect", + "looting", + "efficiency", + "silk_touch", + "unbreaking", + "fortune", + "power", + "punch", + "flame", + "infinity", + "luck_of_the_sea", + "lure", + "frost_walker", + "mending", + "binding", + "vanishing", + "impaling", + "riptide", + "loyalty", + "channeling", + "multishot", + "piercing", + "quick_charge", + "soul_speed", + "swift_sneak", + "wind_burst", + "density", + "breach", +} + +var Enchant = &mcfunction.Spec{ + Name: "enchant", + Description: "Adds an enchantment to a player's selected item.", + Overloads: []mcfunction.SpecOverload{ + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindSelector, + Name: "player", + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "enchantmentName", + Literals: enchantments, + }, + { + Kind: mcfunction.ParameterKindInteger, + Name: "level", + Optional: true, + }, + }, + }, + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindSelector, + Name: "player", + }, + { + Kind: mcfunction.ParameterKindInteger, + Name: "enchantmentId", + }, + { + Kind: mcfunction.ParameterKindInteger, + Name: "level", + Optional: true, + }, + }, + }, + }, +} diff --git a/internal/mcfunction/builtin/event.go b/internal/mcfunction/builtin/event.go new file mode 100644 index 0000000..8490e85 --- /dev/null +++ b/internal/mcfunction/builtin/event.go @@ -0,0 +1,28 @@ +package builtin + +import "github.com/rockide/language-server/internal/mcfunction" + +var Event = &mcfunction.Spec{ + Name: "event", + Description: "Triggers an event for the specified object(s)", + Overloads: []mcfunction.SpecOverload{ + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindLiteral, + Name: "entity", + Literals: []string{"entity"}, + }, + { + Kind: mcfunction.ParameterKindSelector, + Name: "target", + }, + { + Kind: mcfunction.ParameterKindString, + Name: "eventName", + Tags: []string{mcfunction.TagEntityEvent}, + }, + }, + }, + }, +} diff --git a/internal/mcfunction/builtin/execute.go b/internal/mcfunction/builtin/execute.go new file mode 100644 index 0000000..4b4d6b2 --- /dev/null +++ b/internal/mcfunction/builtin/execute.go @@ -0,0 +1,460 @@ +package builtin + +import "github.com/rockide/language-server/internal/mcfunction" + +var ifUnless = []string{"if", "unless"} + +var Execute = &mcfunction.Spec{ + Name: "execute", + Description: "Executes a command on behalf of one or more entities.", + Overloads: []mcfunction.SpecOverload{ + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindLiteral, + Name: "subcommand", + Literals: []string{"as"}, + Tags: []string{mcfunction.TagExecuteChain}, + }, + { + Kind: mcfunction.ParameterKindSelector, + Name: "origin", + }, + { + Kind: mcfunction.ParameterKindChainedCommand, + Name: "chainedCommand", + }, + }, + }, + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindLiteral, + Name: "subcommand", + Literals: []string{"at"}, + Tags: []string{mcfunction.TagExecuteChain}, + }, + { + Kind: mcfunction.ParameterKindSelector, + Name: "origin", + }, + { + Kind: mcfunction.ParameterKindChainedCommand, + Name: "chainedCommand", + }, + }, + }, + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindLiteral, + Name: "subcommand", + Literals: []string{"in"}, + Tags: []string{mcfunction.TagExecuteChain}, + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "dimension", + Literals: []string{"overworld", "nether", "the_end"}, + Tags: []string{mcfunction.TagDimensionId}, + }, + { + Kind: mcfunction.ParameterKindChainedCommand, + Name: "chainedCommand", + }, + }, + }, + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindLiteral, + Name: "subcommand", + Literals: []string{"positioned"}, + Tags: []string{mcfunction.TagExecuteChain}, + }, + { + Kind: mcfunction.ParameterKindVector3, + Name: "position", + }, + { + Kind: mcfunction.ParameterKindChainedCommand, + Name: "chainedCommand", + }, + }, + }, + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindLiteral, + Name: "subcommand", + Literals: []string{"positioned"}, + Tags: []string{mcfunction.TagExecuteChain}, + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "secondary subcommand", + Literals: []string{"as"}, + }, + { + Kind: mcfunction.ParameterKindSelector, + Name: "origin", + }, + { + Kind: mcfunction.ParameterKindChainedCommand, + Name: "chainedCommand", + }, + }, + }, + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindLiteral, + Name: "subcommand", + Literals: []string{"rotated"}, + Tags: []string{mcfunction.TagExecuteChain}, + }, + { + Kind: mcfunction.ParameterKindNumber, + Name: "yaw", + Tags: []string{mcfunction.TagYaw}, + }, + { + Kind: mcfunction.ParameterKindNumber, + Name: "pitch", + Tags: []string{mcfunction.TagPitch}, + }, + { + Kind: mcfunction.ParameterKindChainedCommand, + Name: "chainedCommand", + }, + }, + }, + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindLiteral, + Name: "subcommand", + Literals: []string{"rotated"}, + Tags: []string{mcfunction.TagExecuteChain}, + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "secondary subcommand", + Literals: []string{"as"}, + }, + { + Kind: mcfunction.ParameterKindSelector, + Name: "origin", + }, + { + Kind: mcfunction.ParameterKindChainedCommand, + Name: "chainedCommand", + }, + }, + }, + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindLiteral, + Name: "subcommand", + Literals: []string{"facing"}, + Tags: []string{mcfunction.TagExecuteChain}, + }, + { + Kind: mcfunction.ParameterKindVector3, + Name: "position", + }, + { + Kind: mcfunction.ParameterKindChainedCommand, + Name: "chainedCommand", + }, + }, + }, + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindLiteral, + Name: "subcommand", + Literals: []string{"facing"}, + Tags: []string{mcfunction.TagExecuteChain}, + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "secondary subcommand", + Literals: []string{"entity"}, + }, + { + Kind: mcfunction.ParameterKindSelector, + Name: "origin", + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "anchor", + Literals: []string{"eyes", "feet"}, + }, + { + Kind: mcfunction.ParameterKindChainedCommand, + Name: "chainedCommand", + }, + }, + }, + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindLiteral, + Name: "subcommand", + Literals: []string{"align"}, + Tags: []string{mcfunction.TagExecuteChain}, + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "axes", + Literals: []string{"xyz", "xy", "xz", "yz", "x", "y", "z"}, + }, + { + Kind: mcfunction.ParameterKindChainedCommand, + Name: "chainedCommand", + }, + }, + }, + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindLiteral, + Name: "subcommand", + Literals: []string{"anchored"}, + Tags: []string{mcfunction.TagExecuteChain}, + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "anchored", + Literals: []string{"eyes", "feet"}, + }, + { + Kind: mcfunction.ParameterKindChainedCommand, + Name: "chainedCommand", + }, + }, + }, + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindLiteral, + Name: "subcommand", + Literals: ifUnless, + Tags: []string{mcfunction.TagExecuteChain}, + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "secondary subcommand", + Literals: []string{"block"}, + }, + { + Kind: mcfunction.ParameterKindVector3, + Name: "position", + }, + { + Kind: mcfunction.ParameterKindString, + Name: "block", + Tags: []string{mcfunction.TagBlockId}, + }, + { + Kind: mcfunction.ParameterKindChainedCommand, + Name: "chainedCommand", + Optional: true, + }, + }, + }, + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindLiteral, + Name: "subcommand", + Literals: ifUnless, + Tags: []string{mcfunction.TagExecuteChain}, + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "secondary subcommand", + Literals: []string{"block"}, + }, + { + Kind: mcfunction.ParameterKindVector3, + Name: "position", + }, + { + Kind: mcfunction.ParameterKindString, + Name: "block", + Tags: []string{mcfunction.TagBlockId}, + }, + blockStates, + { + Kind: mcfunction.ParameterKindChainedCommand, + Name: "chainedCommand", + Optional: true, + }, + }, + }, + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindLiteral, + Name: "subcommand", + Literals: ifUnless, + Tags: []string{mcfunction.TagExecuteChain}, + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "secondary subcommand", + Literals: []string{"blocks"}, + }, + { + Kind: mcfunction.ParameterKindVector3, + Name: "begin", + }, + { + Kind: mcfunction.ParameterKindVector3, + Name: "end", + }, + { + Kind: mcfunction.ParameterKindVector3, + Name: "destination", + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "scan mode", + Literals: []string{"masked", "all"}, + }, + { + Kind: mcfunction.ParameterKindChainedCommand, + Name: "chainedCommand", + Optional: true, + }, + }, + }, + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindLiteral, + Name: "subcommand", + Literals: ifUnless, + Tags: []string{mcfunction.TagExecuteChain}, + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "secondary subcommand", + Literals: []string{"entity"}, + }, + { + Kind: mcfunction.ParameterKindSelector, + Name: "target", + }, + { + Kind: mcfunction.ParameterKindChainedCommand, + Name: "chainedCommand", + Optional: true, + }, + }, + }, + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindLiteral, + Name: "subcommand", + Literals: ifUnless, + Tags: []string{mcfunction.TagExecuteChain}, + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "secondary subcommand", + Literals: []string{"score"}, + }, + { + Kind: mcfunction.ParameterKindSelector, + Name: "target", + }, + { + Kind: mcfunction.ParameterKindString, + Name: "objective", + Tags: []string{mcfunction.TagScoreboardObjectiveId}, + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "operation", + Literals: []string{ + "<", + "<=", + ">", + ">=", + }, + }, + { + Kind: mcfunction.ParameterKindSelector, + Name: "source", + }, + { + Kind: mcfunction.ParameterKindString, + Name: "objective", + Tags: []string{mcfunction.TagScoreboardObjectiveId}, + }, + { + Kind: mcfunction.ParameterKindChainedCommand, + Name: "chainedCommand", + Optional: true, + }, + }, + }, + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindLiteral, + Name: "subcommand", + Literals: ifUnless, + Tags: []string{mcfunction.TagExecuteChain}, + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "secondary subcommand", + Literals: []string{"score"}, + }, + { + Kind: mcfunction.ParameterKindSelector, + Name: "target", + }, + { + Kind: mcfunction.ParameterKindString, + Name: "objective", + Tags: []string{mcfunction.TagScoreboardObjectiveId}, + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "matches", + Literals: []string{"matches"}, + }, + { + Kind: mcfunction.ParameterKindRange, + Name: "range", + }, + { + Kind: mcfunction.ParameterKindChainedCommand, + Name: "chainedCommand", + Optional: true, + }, + }, + }, + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindLiteral, + Name: "subcommand", + Literals: []string{"run"}, + Tags: []string{mcfunction.TagExecuteChain}, + }, + { + Kind: mcfunction.ParameterKindCommand, + Name: "command", + }, + }, + }, + }, +} diff --git a/internal/mcfunction/builtin/fill.go b/internal/mcfunction/builtin/fill.go new file mode 100644 index 0000000..d5a479a --- /dev/null +++ b/internal/mcfunction/builtin/fill.go @@ -0,0 +1,124 @@ +package builtin + +import "github.com/rockide/language-server/internal/mcfunction" + +var oldBlockHandling = []string{ + "destroy", + "hollow", + "keep", + "outline", + "replace", +} + +var Fill = &mcfunction.Spec{ + Name: "fill", + Description: "Fills all or parts of a region with a specific block.", + Overloads: []mcfunction.SpecOverload{ + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindVector3, + Name: "from", + }, + { + Kind: mcfunction.ParameterKindVector3, + Name: "to", + }, + { + Kind: mcfunction.ParameterKindString, + Name: "tileName", + Tags: []string{mcfunction.TagBlockId}, + }, + blockStates, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "oldBlockHandling", + Optional: true, + Literals: oldBlockHandling, + }, + }, + }, + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindVector3, + Name: "from", + }, + { + Kind: mcfunction.ParameterKindVector3, + Name: "to", + }, + { + Kind: mcfunction.ParameterKindString, + Name: "tileName", + Tags: []string{mcfunction.TagBlockId}, + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "oldBlockHandling", + Optional: true, + Literals: oldBlockHandling, + }, + }, + }, + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindVector3, + Name: "from", + }, + { + Kind: mcfunction.ParameterKindVector3, + Name: "to", + }, + { + Kind: mcfunction.ParameterKindString, + Name: "tileName", + Tags: []string{mcfunction.TagBlockId}, + }, + blockStates, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "oldBlockHandling", + Literals: oldBlockHandling, + }, + { + Kind: mcfunction.ParameterKindString, + Name: "replaceTileName", + Optional: true, + Tags: []string{mcfunction.TagBlockId}, + }, + blockStates, + }, + }, + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindVector3, + Name: "from", + }, + { + Kind: mcfunction.ParameterKindVector3, + Name: "to", + }, + { + Kind: mcfunction.ParameterKindString, + Tags: []string{mcfunction.TagBlockId}, + Name: "tileName", + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "oldBlockHandling", + Literals: oldBlockHandling, + }, + { + Kind: mcfunction.ParameterKindString, + Name: "replaceTileName", + Optional: true, + Tags: []string{mcfunction.TagBlockId}, + }, + blockStates, + }, + }, + }, +} diff --git a/internal/mcfunction/builtin/fog.go b/internal/mcfunction/builtin/fog.go new file mode 100644 index 0000000..cc15e3b --- /dev/null +++ b/internal/mcfunction/builtin/fog.go @@ -0,0 +1,51 @@ +package builtin + +import "github.com/rockide/language-server/internal/mcfunction" + +var Fog = &mcfunction.Spec{ + Name: "fog", + Description: "Add or remove fog settings file", + Overloads: []mcfunction.SpecOverload{ + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindSelector, + Name: "victim", + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "mode", + Literals: []string{"push"}, + }, + { + Kind: mcfunction.ParameterKindString, + Name: "fogId", + Tags: []string{mcfunction.TagFogId}, + }, + { + Kind: mcfunction.ParameterKindString, + Name: "userProvidedId", + Tags: []string{mcfunction.TagProvidedFogId}, + }, + }, + }, + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindSelector, + Name: "victim", + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "mode", + Literals: []string{"pop", "remove"}, + }, + { + Kind: mcfunction.ParameterKindString, + Name: "userProvidedId", + Tags: []string{mcfunction.TagProvidedFogId}, + }, + }, + }, + }, +} diff --git a/internal/mcfunction/builtin/function.go b/internal/mcfunction/builtin/function.go new file mode 100644 index 0000000..337fd39 --- /dev/null +++ b/internal/mcfunction/builtin/function.go @@ -0,0 +1,19 @@ +package builtin + +import "github.com/rockide/language-server/internal/mcfunction" + +var Function = &mcfunction.Spec{ + Name: "function", + Description: "Runs commands found in the corresponding function file.", + Overloads: []mcfunction.SpecOverload{ + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindString, + Name: "name", + Tags: []string{mcfunction.TagFunctionFile}, + }, + }, + }, + }, +} diff --git a/internal/mcfunction/builtin/gamemode.go b/internal/mcfunction/builtin/gamemode.go new file mode 100644 index 0000000..4aad840 --- /dev/null +++ b/internal/mcfunction/builtin/gamemode.go @@ -0,0 +1,53 @@ +package builtin + +import "github.com/rockide/language-server/internal/mcfunction" + +var gamemodes = []string{ + "a", + "adventure", + "c", + "creative", + "d", + "default", + "s", + "spectator", + "survival", +} + +var Gamemode = &mcfunction.Spec{ + Name: "gamemode", + Description: "Sets a player's game mode.", + Overloads: []mcfunction.SpecOverload{ + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindLiteral, + Name: "gameMode", + Literals: gamemodes, + }, + { + Kind: mcfunction.ParameterKindSelector, + Name: "player", + Optional: true, + }, + }, + }, + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindInteger, + Name: "gameMode", + Range: &mcfunction.NumberRange{ + Min: 0, + Max: 2, + }, + }, + { + Kind: mcfunction.ParameterKindSelector, + Name: "player", + Optional: true, + }, + }, + }, + }, +} diff --git a/internal/mcfunction/builtin/gamerule.go b/internal/mcfunction/builtin/gamerule.go new file mode 100644 index 0000000..e375000 --- /dev/null +++ b/internal/mcfunction/builtin/gamerule.go @@ -0,0 +1,85 @@ +package builtin + +import "github.com/rockide/language-server/internal/mcfunction" + +var boolGameRules = []string{ + "commandblockoutput", + "dodaylightcycle", + "doentitydrops", + "dofiretick", + "recipesunlock", + "dolimitedcrafting", + "domobloot", + "domobspawning", + "dotiledrops", + "doweathercycle", + "drowningdamage", + "falldamage", + "firedamage", + "keepinventory", + "mobgriefing", + "pvp", + "showcoordinates", + "locatorbar", + "showdaysplayed", + "naturalregeneration", + "tntexplodes", + "sendcommandfeedback", + "doinsomnia", + "commandblocksenabled", + "doimmediaterespawn", + "showdeathmessages", + "showtags", + "freezedamage", + "respawnblocksexplode", + "showbordereffect", + "showrecipemessages", + "projectilescanbreakblocks", + "tntexplosiondropdecay", +} + +var intGameRules = []string{ + "maxcommandchainlength", + "randomtickspeed", + "functioncommandlimit", + "spawnradius", + "playerssleepingpercentage", +} + +var Gamerule = &mcfunction.Spec{ + Name: "gamerule", + Description: "Sets or queries a game rule value.", + Overloads: []mcfunction.SpecOverload{ + { + Parameters: []mcfunction.ParameterSpec{}, + }, + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindLiteral, + Name: "rule", + Literals: boolGameRules, + }, + { + Kind: mcfunction.ParameterKindBoolean, + Name: "value", + Optional: true, + }, + }, + }, + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindLiteral, + Name: "rule", + Literals: intGameRules, + }, + { + Kind: mcfunction.ParameterKindInteger, + Name: "value", + Optional: true, + }, + }, + }, + }, +} diff --git a/internal/mcfunction/builtin/gametest.go b/internal/mcfunction/builtin/gametest.go new file mode 100644 index 0000000..f6729be --- /dev/null +++ b/internal/mcfunction/builtin/gametest.go @@ -0,0 +1,165 @@ +package builtin + +import "github.com/rockide/language-server/internal/mcfunction" + +var Gametest = &mcfunction.Spec{ + Name: "gametest", + Description: "Interacts with gametest.", + Overloads: []mcfunction.SpecOverload{ + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindLiteral, + Name: "mode", + Literals: []string{"runthis"}, + }, + }, + }, + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindLiteral, + Name: "mode", + Literals: []string{"run"}, + }, + { + Kind: mcfunction.ParameterKindString, + Name: "testName", + }, + { + Kind: mcfunction.ParameterKindNumber, + Name: "rotationSteps", + Optional: true, + }, + }, + }, + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindLiteral, + Name: "mode", + Literals: []string{"run"}, + }, + { + Kind: mcfunction.ParameterKindString, + Name: "testName", + }, + { + Kind: mcfunction.ParameterKindBoolean, + Name: "stopOnFailure", + }, + { + Kind: mcfunction.ParameterKindInteger, + Name: "repeatCount", + }, + { + Kind: mcfunction.ParameterKindInteger, + Name: "rotationSteps", + Optional: true, + }, + }, + }, + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindLiteral, + Name: "mode", + Literals: []string{"runset"}, + }, + { + Kind: mcfunction.ParameterKindString, + Name: "tag", + Optional: true, + }, + { + Kind: mcfunction.ParameterKindInteger, + Name: "rotationSteps", + Optional: true, + }, + }, + }, + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindLiteral, + Name: "mode", + Literals: []string{"runsetuntilfail"}, + }, + { + Kind: mcfunction.ParameterKindString, + Name: "tag", + Optional: true, + }, + { + Kind: mcfunction.ParameterKindInteger, + Name: "rotationSteps", + Optional: true, + }, + }, + }, + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindLiteral, + Name: "mode", + Literals: []string{"clearall"}, + }, + }, + }, + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindLiteral, + Name: "mode", + Literals: []string{"pos"}, + }, + }, + }, + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindLiteral, + Name: "mode", + Literals: []string{"create"}, + }, + { + Kind: mcfunction.ParameterKindString, + Name: "testName", + }, + { + Kind: mcfunction.ParameterKindInteger, + Name: "width", + Optional: true, + }, + { + Kind: mcfunction.ParameterKindInteger, + Name: "height", + Optional: true, + }, + { + Kind: mcfunction.ParameterKindInteger, + Name: "depth", + Optional: true, + }, + }, + }, + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindLiteral, + Name: "mode", + Literals: []string{"runthese"}, + }, + }, + }, + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindLiteral, + Name: "mode", + Literals: []string{"stopall"}, + }, + }, + }, + }, +} diff --git a/internal/mcfunction/builtin/give.go b/internal/mcfunction/builtin/give.go new file mode 100644 index 0000000..5a0d6e9 --- /dev/null +++ b/internal/mcfunction/builtin/give.go @@ -0,0 +1,38 @@ +package builtin + +import "github.com/rockide/language-server/internal/mcfunction" + +var Give = &mcfunction.Spec{ + Name: "give", + Description: "Gives an item to a player.", + Overloads: []mcfunction.SpecOverload{ + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindSelector, + Name: "player", + }, + { + Kind: mcfunction.ParameterKindString, + Name: "itemName", + Tags: []string{mcfunction.TagItemId}, + }, + { + Kind: mcfunction.ParameterKindInteger, + Name: "amount", + Optional: true, + }, + { + Kind: mcfunction.ParameterKindInteger, + Name: "data", + Optional: true, + }, + { + Kind: mcfunction.ParameterKindItemNbt, + Name: "components", + Optional: true, + }, + }, + }, + }, +} diff --git a/internal/mcfunction/builtin/hud.go b/internal/mcfunction/builtin/hud.go new file mode 100644 index 0000000..dafda1d --- /dev/null +++ b/internal/mcfunction/builtin/hud.go @@ -0,0 +1,46 @@ +package builtin + +import "github.com/rockide/language-server/internal/mcfunction" + +var hudElements = []string{ + "air_bubbles", + "all", + "armor", + "crosshair", + "health", + "horse_health", + "hotbar", + "hunger", + "item_text", + "paperdoll", + "progress_bar", + "status_effects", + "tooltips", + "touch_controls", +} + +var Hud = &mcfunction.Spec{ + Name: "hud", + Description: "Changes the visibility of hud elements.", + Overloads: []mcfunction.SpecOverload{ + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindSelector, + Name: "target", + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "visible", + Literals: []string{"hide", "reset"}, + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "hud_element", + Optional: true, + Literals: hudElements, + }, + }, + }, + }, +} diff --git a/internal/mcfunction/builtin/inputpermission.go b/internal/mcfunction/builtin/inputpermission.go new file mode 100644 index 0000000..8ae87cf --- /dev/null +++ b/internal/mcfunction/builtin/inputpermission.go @@ -0,0 +1,71 @@ +package builtin + +import "github.com/rockide/language-server/internal/mcfunction" + +var permission = []string{ + "camera", + "dismount", + "jump", + "lateral_movement", + "mount", + "move_backward", + "move_forward", + "move_left", + "move_right", + "movement", + "sneak", +} + +var Inputpermission = &mcfunction.Spec{ + Name: "inputpermission", + Description: "Sets whether or not a player's input can affect their character.", + Overloads: []mcfunction.SpecOverload{ + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindLiteral, + Name: "option", + Literals: []string{"set"}, + }, + { + Kind: mcfunction.ParameterKindSelector, + Name: "targets", + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "permission", + Literals: permission, + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "state", + Literals: []string{"enabled", "disabled"}, + }, + }, + }, + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindLiteral, + Name: "option", + Literals: []string{"query"}, + }, + { + Kind: mcfunction.ParameterKindSelector, + Name: "targets", + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "permission", + Literals: permission, + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "state", + Optional: true, + Literals: []string{"enabled", "disabled"}, + }, + }, + }, + }, +} diff --git a/internal/mcfunction/builtin/kill.go b/internal/mcfunction/builtin/kill.go new file mode 100644 index 0000000..b99eb95 --- /dev/null +++ b/internal/mcfunction/builtin/kill.go @@ -0,0 +1,19 @@ +package builtin + +import "github.com/rockide/language-server/internal/mcfunction" + +var Kill = &mcfunction.Spec{ + Name: "kill", + Description: "Kills entities (players, mobs, etc.).", + Overloads: []mcfunction.SpecOverload{ + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindSelector, + Name: "target", + Optional: true, + }, + }, + }, + }, +} diff --git a/internal/mcfunction/builtin/locate.go b/internal/mcfunction/builtin/locate.go new file mode 100644 index 0000000..80b304c --- /dev/null +++ b/internal/mcfunction/builtin/locate.go @@ -0,0 +1,43 @@ +package builtin + +import "github.com/rockide/language-server/internal/mcfunction" + +var Locate = &mcfunction.Spec{ + Name: "locate", + Description: "Displays the coordinates for the closest structure or biome of a given type.", + Overloads: []mcfunction.SpecOverload{ + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindLiteral, + Name: "subcommand", + Literals: []string{"structure"}, + }, + { + Kind: mcfunction.ParameterKindString, + Name: "structure", + Tags: []string{mcfunction.TagJigsawId}, + }, + { + Kind: mcfunction.ParameterKindBoolean, + Name: "useNewChunksOnly", + Optional: true, + }, + }, + }, + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindLiteral, + Name: "subcommand", + Literals: []string{"biome"}, + }, + { + Kind: mcfunction.ParameterKindString, + Name: "biome", + Tags: []string{mcfunction.TagBiomeId}, + }, + }, + }, + }, +} diff --git a/internal/mcfunction/builtin/loot.go b/internal/mcfunction/builtin/loot.go new file mode 100644 index 0000000..469e05f --- /dev/null +++ b/internal/mcfunction/builtin/loot.go @@ -0,0 +1,835 @@ +package builtin + +import "github.com/rockide/language-server/internal/mcfunction" + +var slotTypes = []string{ + "slot.armor", + "slot.armor.body", + "slot.armor.chest", + "slot.armor.feet", + "slot.armor.head", + "slot.armor.legs", + "slot.chest", + "slot.enderchest", + "slot.equippable", + "slot.hotbar", + "slot.inventory", + "slot.saddle", + "slot.weapon.mainhand", + "slot.weapon.offhand", +} + +var Loot = &mcfunction.Spec{ + Name: "loot", + Description: "Drops the given loot table into the specified inventory or into the world.", + Overloads: []mcfunction.SpecOverload{ + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindLiteral, + Name: "target", + Literals: []string{"spawn"}, + }, + { + Kind: mcfunction.ParameterKindVector3, + Name: "position", + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "source", + Literals: []string{"loot"}, + }, + { + Kind: mcfunction.ParameterKindString, + Name: "loot_table", + Tags: []string{mcfunction.TagLootTableFile}, + }, + { + Kind: mcfunction.ParameterKindString, + Name: "|mainhand|offhand", + Optional: true, + Literals: []string{"mainhand", "offhand"}, + Tags: []string{mcfunction.TagItemId}, + }, + }, + }, + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindLiteral, + Name: "target", + Literals: []string{"spawn"}, + }, + { + Kind: mcfunction.ParameterKindVector3, + Name: "position", + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "source", + Literals: []string{"kill"}, + }, + { + Kind: mcfunction.ParameterKindSelector, + Name: "entity", + }, + { + Kind: mcfunction.ParameterKindString, + Name: "|mainhand|offhand", + Optional: true, + Literals: []string{"mainhand", "offhand"}, + Tags: []string{mcfunction.TagItemId}, + }, + }, + }, + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindLiteral, + Name: "target", + Literals: []string{"spawn"}, + }, + { + Kind: mcfunction.ParameterKindVector3, + Name: "position", + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "source", + Literals: []string{"mine"}, + }, + { + Kind: mcfunction.ParameterKindVector3, + Name: "TargetBlockPosition", + }, + { + Kind: mcfunction.ParameterKindString, + Name: "|mainhand|offhand", + Optional: true, + Literals: []string{"mainhand", "offhand"}, + Tags: []string{mcfunction.TagItemId}, + }, + }, + }, + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindLiteral, + Name: "target", + Literals: []string{"give"}, + }, + { + Kind: mcfunction.ParameterKindSelector, + Name: "players", + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "source", + Literals: []string{"loot"}, + }, + { + Kind: mcfunction.ParameterKindString, + Name: "loot_table", + Tags: []string{mcfunction.TagLootTableFile}, + }, + { + Kind: mcfunction.ParameterKindString, + Name: "|mainhand|offhand", + Optional: true, + Literals: []string{"mainhand", "offhand"}, + Tags: []string{mcfunction.TagItemId}, + }, + }, + }, + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindLiteral, + Name: "target", + Literals: []string{"give"}, + }, + { + Kind: mcfunction.ParameterKindSelector, + Name: "players", + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "source", + Literals: []string{"kill"}, + }, + { + Kind: mcfunction.ParameterKindSelector, + Name: "entity", + }, + { + Kind: mcfunction.ParameterKindString, + Name: "|mainhand|offhand", + Optional: true, + Literals: []string{"mainhand", "offhand"}, + Tags: []string{mcfunction.TagItemId}, + }, + }, + }, + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindLiteral, + Name: "target", + Literals: []string{"give"}, + }, + { + Kind: mcfunction.ParameterKindSelector, + Name: "players", + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "source", + Literals: []string{"mine"}, + }, + { + Kind: mcfunction.ParameterKindVector3, + Name: "TargetBlockPosition", + }, + { + Kind: mcfunction.ParameterKindString, + Name: "|mainhand|offhand", + Optional: true, + Literals: []string{"mainhand", "offhand"}, + Tags: []string{mcfunction.TagItemId}, + }, + }, + }, + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindLiteral, + Name: "target", + Literals: []string{"insert"}, + }, + { + Kind: mcfunction.ParameterKindVector3, + Name: "position", + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "source", + Literals: []string{"loot"}, + }, + { + Kind: mcfunction.ParameterKindString, + Name: "loot_table", + Tags: []string{mcfunction.TagLootTableFile}, + }, + { + Kind: mcfunction.ParameterKindString, + Name: "|mainhand|offhand", + Optional: true, + Literals: []string{"mainhand", "offhand"}, + Tags: []string{mcfunction.TagItemId}, + }, + }, + }, + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindLiteral, + Name: "target", + Literals: []string{"insert"}, + }, + { + Kind: mcfunction.ParameterKindVector3, + Name: "position", + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "source", + Literals: []string{"kill"}, + }, + { + Kind: mcfunction.ParameterKindSelector, + Name: "entity", + }, + { + Kind: mcfunction.ParameterKindString, + Name: "|mainhand|offhand", + Optional: true, + Literals: []string{"mainhand", "offhand"}, + Tags: []string{mcfunction.TagItemId}, + }, + }, + }, + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindLiteral, + Name: "target", + Literals: []string{"insert"}, + }, + { + Kind: mcfunction.ParameterKindVector3, + Name: "position", + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "source", + Literals: []string{"mine"}, + }, + { + Kind: mcfunction.ParameterKindVector3, + Name: "TargetBlockPosition", + }, + { + Kind: mcfunction.ParameterKindString, + Name: "|mainhand|offhand", + Optional: true, + Literals: []string{"mainhand", "offhand"}, + Tags: []string{mcfunction.TagItemId}, + }, + }, + }, + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindLiteral, + Name: "target", + Literals: []string{"replace"}, + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "entity", + Literals: []string{"entity"}, + }, + { + Kind: mcfunction.ParameterKindSelector, + Name: "entity", + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "slotType", + Literals: slotTypes, + }, + { + Kind: mcfunction.ParameterKindInteger, + Name: "slotId", + }, + { + Kind: mcfunction.ParameterKindInteger, + Name: "count", + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "source", + Literals: []string{"loot"}, + }, + { + Kind: mcfunction.ParameterKindString, + Name: "loot_table", + Tags: []string{mcfunction.TagLootTableFile}, + }, + { + Kind: mcfunction.ParameterKindString, + Name: "|mainhand|offhand", + Optional: true, + Literals: []string{"mainhand", "offhand"}, + Tags: []string{mcfunction.TagItemId}, + }, + }, + }, + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindLiteral, + Name: "target", + Literals: []string{"replace"}, + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "entity", + Literals: []string{"entity"}, + }, + { + Kind: mcfunction.ParameterKindSelector, + Name: "entity", + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "slotType", + Literals: slotTypes, + }, + { + Kind: mcfunction.ParameterKindInteger, + Name: "slotId", + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "source", + Literals: []string{"loot"}, + }, + { + Kind: mcfunction.ParameterKindString, + Name: "loot_table", + Tags: []string{mcfunction.TagLootTableFile}, + }, + { + Kind: mcfunction.ParameterKindString, + Name: "|mainhand|offhand", + Optional: true, + Literals: []string{"mainhand", "offhand"}, + Tags: []string{mcfunction.TagItemId}, + }, + }, + }, + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindLiteral, + Name: "target", + Literals: []string{"replace"}, + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "entity", + Literals: []string{"entity"}, + }, + { + Kind: mcfunction.ParameterKindSelector, + Name: "entity", + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "slotType", + Literals: slotTypes, + }, + { + Kind: mcfunction.ParameterKindInteger, + Name: "slotId", + }, + { + Kind: mcfunction.ParameterKindInteger, + Name: "count", + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "source", + Literals: []string{"kill"}, + }, + { + Kind: mcfunction.ParameterKindSelector, + Name: "entity", + }, + { + Kind: mcfunction.ParameterKindString, + Name: "|mainhand|offhand", + Optional: true, + Literals: []string{"mainhand", "offhand"}, + Tags: []string{mcfunction.TagItemId}, + }, + }, + }, + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindLiteral, + Name: "target", + Literals: []string{"replace"}, + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "entity", + Literals: []string{"entity"}, + }, + { + Kind: mcfunction.ParameterKindSelector, + Name: "entity", + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "slotType", + Literals: slotTypes, + }, + { + Kind: mcfunction.ParameterKindInteger, + Name: "slotId", + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "source", + Literals: []string{"kill"}, + }, + { + Kind: mcfunction.ParameterKindSelector, + Name: "entity", + }, + { + Kind: mcfunction.ParameterKindString, + Name: "|mainhand|offhand", + Optional: true, + Literals: []string{"mainhand", "offhand"}, + Tags: []string{mcfunction.TagItemId}, + }, + }, + }, + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindLiteral, + Name: "target", + Literals: []string{"replace"}, + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "entity", + Literals: []string{"entity"}, + }, + { + Kind: mcfunction.ParameterKindSelector, + Name: "entity", + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "slotType", + Literals: slotTypes, + }, + { + Kind: mcfunction.ParameterKindInteger, + Name: "slotId", + }, + { + Kind: mcfunction.ParameterKindInteger, + Name: "count", + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "source", + Literals: []string{"mine"}, + }, + { + Kind: mcfunction.ParameterKindVector3, + Name: "TargetBlockPosition", + }, + { + Kind: mcfunction.ParameterKindString, + Name: "|mainhand|offhand", + Optional: true, + Literals: []string{"mainhand", "offhand"}, + Tags: []string{mcfunction.TagItemId}, + }, + }, + }, + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindLiteral, + Name: "target", + Literals: []string{"replace"}, + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "entity", + Literals: []string{"entity"}, + }, + { + Kind: mcfunction.ParameterKindSelector, + Name: "entity", + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "slotType", + Literals: slotTypes, + }, + { + Kind: mcfunction.ParameterKindInteger, + Name: "slotId", + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "source", + Literals: []string{"mine"}, + }, + { + Kind: mcfunction.ParameterKindVector3, + Name: "TargetBlockPosition", + }, + { + Kind: mcfunction.ParameterKindString, + Name: "|mainhand|offhand", + Optional: true, + Literals: []string{"mainhand", "offhand"}, + Tags: []string{mcfunction.TagItemId}, + }, + }, + }, + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindLiteral, + Name: "target", + Literals: []string{"replace"}, + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "block", + Literals: []string{"block"}, + }, + { + Kind: mcfunction.ParameterKindVector3, + Name: "position", + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "slotType", + Literals: []string{"slot.container"}, + }, + { + Kind: mcfunction.ParameterKindInteger, + Name: "slotId", + }, + { + Kind: mcfunction.ParameterKindInteger, + Name: "count", + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "source", + Literals: []string{"loot"}, + }, + { + Kind: mcfunction.ParameterKindString, + Name: "loot_table", + Tags: []string{mcfunction.TagLootTableFile}, + }, + { + Kind: mcfunction.ParameterKindString, + Name: "|mainhand|offhand", + Optional: true, + Literals: []string{"mainhand", "offhand"}, + Tags: []string{mcfunction.TagItemId}, + }, + }, + }, + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindLiteral, + Name: "target", + Literals: []string{"replace"}, + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "block", + Literals: []string{"block"}, + }, + { + Kind: mcfunction.ParameterKindVector3, + Name: "position", + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "slotType", + Literals: []string{"slot.container"}, + }, + { + Kind: mcfunction.ParameterKindInteger, + Name: "slotId", + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "source", + Literals: []string{"loot"}, + }, + { + Kind: mcfunction.ParameterKindString, + Name: "loot_table", + Tags: []string{mcfunction.TagLootTableFile}, + }, + { + Kind: mcfunction.ParameterKindString, + Name: "|mainhand|offhand", + Optional: true, + Tags: []string{mcfunction.TagItemId}, + Literals: []string{"mainhand", "offhand"}, + }, + }, + }, + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindLiteral, + Name: "target", + Literals: []string{"replace"}, + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "block", + Literals: []string{"block"}, + }, + { + Kind: mcfunction.ParameterKindVector3, + Name: "position", + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "slotType", + Literals: []string{"slot.container"}, + }, + { + Kind: mcfunction.ParameterKindInteger, + Name: "slotId", + }, + { + Kind: mcfunction.ParameterKindInteger, + Name: "count", + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "source", + Literals: []string{"kill"}, + }, + { + Kind: mcfunction.ParameterKindSelector, + Name: "entity", + }, + { + Kind: mcfunction.ParameterKindString, + Name: "|mainhand|offhand", + Optional: true, + Literals: []string{"mainhand", "offhand"}, + Tags: []string{mcfunction.TagItemId}, + }, + }, + }, + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindLiteral, + Name: "target", + Literals: []string{"replace"}, + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "block", + Literals: []string{"block"}, + }, + { + Kind: mcfunction.ParameterKindVector3, + Name: "position", + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "slotType", + Literals: []string{"slot.container"}, + }, + { + Kind: mcfunction.ParameterKindInteger, + Name: "slotId", + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "source", + Literals: []string{"kill"}, + }, + { + Kind: mcfunction.ParameterKindSelector, + Name: "entity", + }, + { + Kind: mcfunction.ParameterKindString, + Name: "|mainhand|offhand", + Optional: true, + Literals: []string{"mainhand", "offhand"}, + Tags: []string{mcfunction.TagItemId}, + }, + }, + }, + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindLiteral, + Name: "target", + Literals: []string{"replace"}, + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "block", + Literals: []string{"block"}, + }, + { + Kind: mcfunction.ParameterKindVector3, + Name: "position", + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "slotType", + Literals: []string{"slot.container"}, + }, + { + Kind: mcfunction.ParameterKindInteger, + Name: "slotId", + }, + { + Kind: mcfunction.ParameterKindInteger, + Name: "count", + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "source", + Literals: []string{"mine"}, + }, + { + Kind: mcfunction.ParameterKindVector3, + Name: "TargetBlockPosition", + }, + { + Kind: mcfunction.ParameterKindString, + Name: "|mainhand|offhand", + Optional: true, + Literals: []string{"mainhand", "offhand"}, + Tags: []string{mcfunction.TagItemId}, + }, + }, + }, + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindLiteral, + Name: "target", + Literals: []string{"replace"}, + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "block", + Literals: []string{"block"}, + }, + { + Kind: mcfunction.ParameterKindVector3, + Name: "position", + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "slotType", + Literals: []string{"slot.container"}, + }, + { + Kind: mcfunction.ParameterKindInteger, + Name: "slotId", + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "source", + Literals: []string{"mine"}, + }, + { + Kind: mcfunction.ParameterKindVector3, + Name: "TargetBlockPosition", + }, + { + Kind: mcfunction.ParameterKindString, + Name: "|mainhand|offhand", + Optional: true, + Literals: []string{"mainhand", "offhand"}, + Tags: []string{mcfunction.TagItemId}, + }, + }, + }, + }, +} diff --git a/internal/mcfunction/builtin/me.go b/internal/mcfunction/builtin/me.go new file mode 100644 index 0000000..676c9ad --- /dev/null +++ b/internal/mcfunction/builtin/me.go @@ -0,0 +1,19 @@ +package builtin + +import "github.com/rockide/language-server/internal/mcfunction" + +var Me = &mcfunction.Spec{ + Name: "me", + Description: "Displays a message about yourself.", + Overloads: []mcfunction.SpecOverload{ + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindString, + Name: "message", + Greedy: true, + }, + }, + }, + }, +} diff --git a/internal/mcfunction/builtin/mobevent.go b/internal/mcfunction/builtin/mobevent.go new file mode 100644 index 0000000..8a9c22f --- /dev/null +++ b/internal/mcfunction/builtin/mobevent.go @@ -0,0 +1,29 @@ +package builtin + +import "github.com/rockide/language-server/internal/mcfunction" + +var Mobevent = &mcfunction.Spec{ + Name: "mobevent", + Description: "Controls what mob events are allowed to run.", + Overloads: []mcfunction.SpecOverload{ + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindLiteral, + Name: "event", + Literals: []string{ + "events_enabled", + "minecraft:ender_dragon_event", + "minecraft:pillager_patrols_event", + "minecraft:wandering_trader_event", + }, + }, + { + Kind: mcfunction.ParameterKindBoolean, + Name: "value", + Optional: true, + }, + }, + }, + }, +} diff --git a/internal/mcfunction/builtin/music.go b/internal/mcfunction/builtin/music.go new file mode 100644 index 0000000..6f47240 --- /dev/null +++ b/internal/mcfunction/builtin/music.go @@ -0,0 +1,121 @@ +package builtin + +import "github.com/rockide/language-server/internal/mcfunction" + +var Music = &mcfunction.Spec{ + Name: "music", + Description: "Allows you to control playing music tracks.", + Overloads: []mcfunction.SpecOverload{ + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindLiteral, + Name: "action", + Literals: []string{"queue"}, + }, + { + Kind: mcfunction.ParameterKindString, + Name: "trackName", + Tags: []string{mcfunction.TagMusicId}, + }, + { + Kind: mcfunction.ParameterKindNumber, + Name: "volume", + Optional: true, + Range: &mcfunction.NumberRange{ + Min: 0.01, + Max: 1, + }, + }, + { + Kind: mcfunction.ParameterKindNumber, + Name: "fadeSeconds", + Optional: true, + Range: &mcfunction.NumberRange{ + Min: 0, + Max: 10, + }, + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "repeatMode", + Optional: true, + Literals: []string{"loop", "play_once"}, + }, + }, + }, + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindLiteral, + Name: "action", + Literals: []string{"play"}, + }, + { + Kind: mcfunction.ParameterKindString, + Name: "trackName", + Tags: []string{mcfunction.TagMusicId}, + }, + { + Kind: mcfunction.ParameterKindNumber, + Name: "volume", + Optional: true, + Range: &mcfunction.NumberRange{ + Min: 0.01, + Max: 1, + }, + }, + { + Kind: mcfunction.ParameterKindNumber, + Name: "fadeSeconds", + Optional: true, + Range: &mcfunction.NumberRange{ + Min: 0, + Max: 10, + }, + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "repeatMode", + Optional: true, + Literals: []string{"loop", "play_once"}, + }, + }, + }, + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindLiteral, + Name: "action", + Literals: []string{"stop"}, + }, + { + Kind: mcfunction.ParameterKindNumber, + Name: "fadeSeconds", + Optional: true, + Range: &mcfunction.NumberRange{ + Min: 0, + Max: 10, + }, + }, + }, + }, + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindLiteral, + Name: "action", + Literals: []string{"volume"}, + }, + { + Kind: mcfunction.ParameterKindNumber, + Name: "volume", + Range: &mcfunction.NumberRange{ + Min: 0.01, + Max: 1, + }, + }, + }, + }, + }, +} diff --git a/internal/mcfunction/builtin/op.go b/internal/mcfunction/builtin/op.go new file mode 100644 index 0000000..8df3976 --- /dev/null +++ b/internal/mcfunction/builtin/op.go @@ -0,0 +1,18 @@ +package builtin + +import "github.com/rockide/language-server/internal/mcfunction" + +var Op = &mcfunction.Spec{ + Name: "op", + Description: "Grants operator status to a player.", + Overloads: []mcfunction.SpecOverload{ + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindSelector, + Name: "player", + }, + }, + }, + }, +} diff --git a/internal/mcfunction/builtin/particle.go b/internal/mcfunction/builtin/particle.go new file mode 100644 index 0000000..db88fd2 --- /dev/null +++ b/internal/mcfunction/builtin/particle.go @@ -0,0 +1,24 @@ +package builtin + +import "github.com/rockide/language-server/internal/mcfunction" + +var Particle = &mcfunction.Spec{ + Name: "particle", + Description: "Creates a particle emitter", + Overloads: []mcfunction.SpecOverload{ + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindString, + Name: "effect", + Tags: []string{mcfunction.TagParticleId}, + }, + { + Kind: mcfunction.ParameterKindVector3, + Name: "position", + Optional: true, + }, + }, + }, + }, +} diff --git a/internal/mcfunction/builtin/place.go b/internal/mcfunction/builtin/place.go new file mode 100644 index 0000000..0290c13 --- /dev/null +++ b/internal/mcfunction/builtin/place.go @@ -0,0 +1,131 @@ +package builtin + +import "github.com/rockide/language-server/internal/mcfunction" + +var Place = &mcfunction.Spec{ + Name: "place", + Description: "Places a jigsaw structure, feature, or feature rule in the world.", + Overloads: []mcfunction.SpecOverload{ + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindLiteral, + Name: "action", + Literals: []string{"place"}, + }, + { + Kind: mcfunction.ParameterKindString, + Name: "structure", + Tags: []string{mcfunction.TagJigsawId}, + }, + { + Kind: mcfunction.ParameterKindVector3, + Name: "pos", + Optional: true, + }, + { + Kind: mcfunction.ParameterKindBoolean, + Name: "ignoreStartHeight", + Optional: true, + }, + { + Kind: mcfunction.ParameterKindBoolean, + Name: "keepJigsaws", + Optional: true, + }, + { + Kind: mcfunction.ParameterKindBoolean, + Name: "includeEntities", + Optional: true, + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "liquidSettings", + Optional: true, + Literals: []string{"apply_waterlogging", "ignore_waterlogging"}, + }, + }, + }, + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindLiteral, + Name: "action", + Literals: []string{"place"}, + }, + { + Kind: mcfunction.ParameterKindString, + Name: "pool", + Tags: []string{mcfunction.TagJigsawTemplatePoolId}, + }, + { + Kind: mcfunction.ParameterKindString, + Name: "jigsawTarget", + }, + { + Kind: mcfunction.ParameterKindNumber, + Name: "maxDepth", + }, + { + Kind: mcfunction.ParameterKindVector3, + Name: "pos", + Optional: true, + }, + { + Kind: mcfunction.ParameterKindBoolean, + Name: "keepJigsaws", + Optional: true, + }, + { + Kind: mcfunction.ParameterKindBoolean, + Name: "includeEntities", + Optional: true, + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "liquidSettings", + Optional: true, + Literals: []string{"apply_waterlogging", "ignore_waterlogging"}, + }, + }, + }, + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindLiteral, + Name: "action", + Literals: []string{"feature"}, + }, + { + Kind: mcfunction.ParameterKindString, + Name: "feature", + Tags: []string{mcfunction.TagFeatureId}, + }, + { + Kind: mcfunction.ParameterKindVector3, + Name: "position", + Optional: true, + }, + }, + }, + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindLiteral, + Name: "action", + Literals: []string{"featurerule"}, + }, + { + Kind: mcfunction.ParameterKindString, + Name: "featurerule", + Tags: []string{mcfunction.TagFeatureRuleId}, + }, + { + Kind: mcfunction.ParameterKindVector3, + Name: "position", + Optional: true, + }, + }, + }, + }, +} diff --git a/internal/mcfunction/builtin/playanimation.go b/internal/mcfunction/builtin/playanimation.go new file mode 100644 index 0000000..6f1df27 --- /dev/null +++ b/internal/mcfunction/builtin/playanimation.go @@ -0,0 +1,46 @@ +package builtin + +import "github.com/rockide/language-server/internal/mcfunction" + +var Playanimation = &mcfunction.Spec{ + Name: "playanimation", + Description: "Makes one or more entities play a one-off animation. Assumes all variables are setup correctly.", + Overloads: []mcfunction.SpecOverload{ + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindSelector, + Name: "entity", + }, + { + Kind: mcfunction.ParameterKindString, + Name: "animation", + Tags: []string{mcfunction.TagClientAnimationId}, + }, + { + Kind: mcfunction.ParameterKindString, + Name: "next_state", + Optional: true, + Tags: []string{mcfunction.TagClientAnimationId}, + }, + { + Kind: mcfunction.ParameterKindNumber, + Name: "blend_out_time", + Optional: true, + }, + { + Kind: mcfunction.ParameterKindString, + Name: "stop_expression", + Optional: true, + Literals: []string{`""`}, + Tags: []string{mcfunction.TagMolang}, + }, + { + Kind: mcfunction.ParameterKindString, + Name: "controller", + Optional: true, + }, + }, + }, + }, +} diff --git a/internal/mcfunction/builtin/playsound.go b/internal/mcfunction/builtin/playsound.go new file mode 100644 index 0000000..bdfa319 --- /dev/null +++ b/internal/mcfunction/builtin/playsound.go @@ -0,0 +1,44 @@ +package builtin + +import "github.com/rockide/language-server/internal/mcfunction" + +var Playsound = &mcfunction.Spec{ + Name: "playsound", + Description: "Plays a sound.", + Overloads: []mcfunction.SpecOverload{ + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindString, + Name: "sound", + Tags: []string{mcfunction.TagSoundId}, + }, + { + Kind: mcfunction.ParameterKindSelector, + Name: "player", + Optional: true, + }, + { + Kind: mcfunction.ParameterKindVector3, + Name: "position", + Optional: true, + }, + { + Kind: mcfunction.ParameterKindNumber, + Name: "volume", + Optional: true, + }, + { + Kind: mcfunction.ParameterKindNumber, + Name: "pitch", + Optional: true, + }, + { + Kind: mcfunction.ParameterKindNumber, + Name: "minimumVolume", + Optional: true, + }, + }, + }, + }, +} diff --git a/internal/mcfunction/builtin/recipe.go b/internal/mcfunction/builtin/recipe.go new file mode 100644 index 0000000..1537575 --- /dev/null +++ b/internal/mcfunction/builtin/recipe.go @@ -0,0 +1,48 @@ +package builtin + +import "github.com/rockide/language-server/internal/mcfunction" + +var Recipe = &mcfunction.Spec{ + Name: "recipe", + Description: "Unlocks recipe in the recipe book for a player.", + Overloads: []mcfunction.SpecOverload{ + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindLiteral, + Name: "give", + Literals: []string{"give"}, + }, + { + Kind: mcfunction.ParameterKindSelector, + Name: "player", + }, + { + Kind: mcfunction.ParameterKindString, + Name: "recipe", + Tags: []string{mcfunction.TagRecipeId}, + Literals: []string{"*"}, + }, + }, + }, + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindLiteral, + Name: "take", + Literals: []string{"take"}, + }, + { + Kind: mcfunction.ParameterKindSelector, + Name: "player", + }, + { + Kind: mcfunction.ParameterKindString, + Name: "recipe", + Tags: []string{mcfunction.TagRecipeId}, + Literals: []string{"*"}, + }, + }, + }, + }, +} diff --git a/internal/mcfunction/builtin/reload.go b/internal/mcfunction/builtin/reload.go new file mode 100644 index 0000000..9b88515 --- /dev/null +++ b/internal/mcfunction/builtin/reload.go @@ -0,0 +1,20 @@ +package builtin + +import "github.com/rockide/language-server/internal/mcfunction" + +var Reload = &mcfunction.Spec{ + Name: "reload", + Description: "Reloads all function and script files from all behavior packs, or optionally reloads the world and all resource and behavior packs.", + Overloads: []mcfunction.SpecOverload{ + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindLiteral, + Name: "all", + Optional: true, + Literals: []string{"all"}, + }, + }, + }, + }, +} diff --git a/internal/mcfunction/builtin/replaceitem.go b/internal/mcfunction/builtin/replaceitem.go new file mode 100644 index 0000000..7f48010 --- /dev/null +++ b/internal/mcfunction/builtin/replaceitem.go @@ -0,0 +1,188 @@ +package builtin + +import "github.com/rockide/language-server/internal/mcfunction" + +var Replaceitem = &mcfunction.Spec{ + Name: "replaceitem", + Description: "Replaces items in inventories.", + Overloads: []mcfunction.SpecOverload{ + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindLiteral, + Name: "block", + Literals: []string{"block"}, + }, + { + Kind: mcfunction.ParameterKindVector3, + Name: "position", + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "slotType", + Literals: []string{"slot.container"}, + }, + { + Kind: mcfunction.ParameterKindInteger, + Name: "slotId", + }, + { + Kind: mcfunction.ParameterKindString, + Name: "itemName", + Tags: []string{mcfunction.TagItemId}, + }, + { + Kind: mcfunction.ParameterKindInteger, + Name: "amount", + Optional: true, + }, + { + Kind: mcfunction.ParameterKindInteger, + Name: "data", + Optional: true, + }, + { + Kind: mcfunction.ParameterKindItemNbt, + Name: "components", + Optional: true, + }, + }, + }, + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindLiteral, + Name: "entity", + Literals: []string{"entity"}, + }, + { + Kind: mcfunction.ParameterKindSelector, + Name: "target", + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "slotType", + Literals: slotTypes, + }, + { + Kind: mcfunction.ParameterKindInteger, + Name: "slotId", + }, + { + Kind: mcfunction.ParameterKindString, + Name: "itemName", + Tags: []string{mcfunction.TagItemId}, + }, + { + Kind: mcfunction.ParameterKindInteger, + Name: "amount", + Optional: true, + }, + { + Kind: mcfunction.ParameterKindInteger, + Name: "data", + Optional: true, + }, + { + Kind: mcfunction.ParameterKindItemNbt, + Name: "components", + Optional: true, + }, + }, + }, + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindLiteral, + Name: "block", + Literals: []string{"block"}, + }, + { + Kind: mcfunction.ParameterKindVector3, + Name: "position", + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "slotType", + Literals: []string{"slot.container"}, + }, + { + Kind: mcfunction.ParameterKindInteger, + Name: "slotId", + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "oldItemHandling", + Literals: []string{"keep", "replace"}, + }, + { + Kind: mcfunction.ParameterKindString, + Name: "itemName", + Tags: []string{mcfunction.TagItemId}, + }, + { + Kind: mcfunction.ParameterKindInteger, + Name: "amount", + Optional: true, + }, + { + Kind: mcfunction.ParameterKindInteger, + Name: "data", + Optional: true, + }, + { + Kind: mcfunction.ParameterKindItemNbt, + Name: "components", + Optional: true, + }, + }, + }, + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindLiteral, + Name: "entity", + Literals: []string{"entity"}, + }, + { + Kind: mcfunction.ParameterKindSelector, + Name: "target", + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "slotType", + Literals: slotTypes, + }, + { + Kind: mcfunction.ParameterKindInteger, + Name: "slotId", + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "oldItemHandling", + Literals: []string{"keep", "replace"}, + }, + { + Kind: mcfunction.ParameterKindString, + Name: "itemName", + Tags: []string{mcfunction.TagItemId}, + }, + { + Kind: mcfunction.ParameterKindInteger, + Name: "amount", + Optional: true, + }, + { + Kind: mcfunction.ParameterKindInteger, + Name: "data", + Optional: true, + }, + { + Kind: mcfunction.ParameterKindItemNbt, + Name: "components", + Optional: true, + }, + }, + }, + }, +} diff --git a/internal/mcfunction/builtin/ride.go b/internal/mcfunction/builtin/ride.go new file mode 100644 index 0000000..46fced8 --- /dev/null +++ b/internal/mcfunction/builtin/ride.go @@ -0,0 +1,129 @@ +package builtin + +import "github.com/rockide/language-server/internal/mcfunction" + +var Ride = &mcfunction.Spec{ + Name: "ride", + Description: "Makes entities ride other entities, stops entities from riding, makes rides evict their riders, or summons rides or riders.", + Overloads: []mcfunction.SpecOverload{ + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindSelector, + Name: "riders", + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "mode", + Literals: []string{"start_riding"}, + }, + { + Kind: mcfunction.ParameterKindSelector, + Name: "ride", + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "teleportRules", + Optional: true, + Literals: []string{"teleport_ride", "teleport_rider"}, + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "howToFill", + Optional: true, + Literals: []string{"if_group_fits", "until_full"}, + }, + }, + }, + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindSelector, + Name: "riders", + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "mode", + Literals: []string{"stop_riding"}, + }, + }, + }, + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindSelector, + Name: "rides", + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "mode", + Literals: []string{"evict_riders"}, + }, + }, + }, + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindSelector, + Name: "rides", + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "mode", + Literals: []string{"summon_rider"}, + }, + { + Kind: mcfunction.ParameterKindString, + Name: "entityType", + Tags: []string{mcfunction.TagEntityId}, + }, + { + Kind: mcfunction.ParameterKindString, + Name: "spawnEvent", + Optional: true, + Tags: []string{mcfunction.TagEntityEvent}, + }, + { + Kind: mcfunction.ParameterKindString, + Name: "nameTag", + Optional: true, + }, + }, + }, + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindSelector, + Name: "riders", + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "mode", + Literals: []string{"summon_ride"}, + }, + { + Kind: mcfunction.ParameterKindString, + Name: "entityType", + Tags: []string{mcfunction.TagEntityId}, + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "rideRules", + Optional: true, + Literals: []string{"no_ride_change", "reassign_rides", "skip_rides"}, + }, + { + Kind: mcfunction.ParameterKindString, + Name: "spawnEvent", + Optional: true, + Tags: []string{mcfunction.TagEntityEvent}, + }, + { + Kind: mcfunction.ParameterKindString, + Name: "nameTag", + Optional: true, + }, + }, + }, + }, +} diff --git a/internal/mcfunction/builtin/say.go b/internal/mcfunction/builtin/say.go new file mode 100644 index 0000000..e16f431 --- /dev/null +++ b/internal/mcfunction/builtin/say.go @@ -0,0 +1,19 @@ +package builtin + +import "github.com/rockide/language-server/internal/mcfunction" + +var Say = &mcfunction.Spec{ + Name: "say", + Description: "Sends a message in the chat to other players.", + Overloads: []mcfunction.SpecOverload{ + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindString, + Name: "message", + Greedy: true, + }, + }, + }, + }, +} diff --git a/internal/mcfunction/builtin/schedule.go b/internal/mcfunction/builtin/schedule.go new file mode 100644 index 0000000..a96fc78 --- /dev/null +++ b/internal/mcfunction/builtin/schedule.go @@ -0,0 +1,304 @@ +package builtin + +import "github.com/rockide/language-server/internal/mcfunction" + +var Schedule = &mcfunction.Spec{ + Name: "schedule", + Description: "Schedules an action to be executed once an area is loaded, or after a certain amount of time.", + Overloads: []mcfunction.SpecOverload{ + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindLiteral, + Name: "mode", + Literals: []string{"delay"}, + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "condition", + Literals: []string{"add"}, + }, + { + Kind: mcfunction.ParameterKindString, + Name: "function", + Tags: []string{mcfunction.TagFunctionFile}, + }, + { + Kind: mcfunction.ParameterKindNumber, + Name: "time", + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "DelayMode", + Optional: true, + Literals: []string{"append", "replace"}, + }, + }, + }, + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindLiteral, + Name: "mode", + Literals: []string{"delay"}, + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "condition", + Literals: []string{"add"}, + }, + { + Kind: mcfunction.ParameterKindString, + Name: "function", + Tags: []string{mcfunction.TagFunctionFile}, + }, + { + Kind: mcfunction.ParameterKindSuffixedInteger, + Name: "time", + Suffix: "t", + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "DelayMode", + Literals: []string{"append", "replace"}, + Optional: true, + }, + }, + }, + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindLiteral, + Name: "mode", + Literals: []string{"delay"}, + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "condition", + Literals: []string{"add"}, + }, + { + Kind: mcfunction.ParameterKindString, + Name: "function", + Tags: []string{mcfunction.TagFunctionFile}, + }, + { + Kind: mcfunction.ParameterKindSuffixedInteger, + Name: "time", + Suffix: "s", + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "DelayMode", + Literals: []string{"append", "replace"}, + Optional: true, + }, + }, + }, + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindLiteral, + Name: "mode", + Literals: []string{"delay"}, + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "condition", + Literals: []string{"add"}, + }, + { + Kind: mcfunction.ParameterKindString, + Name: "function", + Tags: []string{mcfunction.TagFunctionFile}, + }, + { + Kind: mcfunction.ParameterKindSuffixedInteger, + Name: "time", + Suffix: "d", + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "DelayMode", + Literals: []string{"append", "replace"}, + Optional: true, + }, + }, + }, + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindLiteral, + Name: "mode", + Literals: []string{"delay"}, + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "condition", + Literals: []string{"clear"}, + }, + { + Kind: mcfunction.ParameterKindString, + Name: "function", + Tags: []string{mcfunction.TagFunctionFile}, + }, + }, + }, + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindLiteral, + Name: "mode", + Literals: []string{"clear"}, + }, + { + Kind: mcfunction.ParameterKindString, + Name: "function", + Tags: []string{mcfunction.TagFunctionFile}, + }, + }, + }, + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindLiteral, + Name: "mode", + Literals: []string{"on_area_loaded"}, + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "condition", + Literals: []string{"add"}, + }, + { + Kind: mcfunction.ParameterKindVector3, + Name: "from", + }, + { + Kind: mcfunction.ParameterKindVector3, + Name: "to", + }, + { + Kind: mcfunction.ParameterKindString, + Name: "function", + Tags: []string{mcfunction.TagFunctionFile}, + }, + }, + }, + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindLiteral, + Name: "mode", + Literals: []string{"on_area_loaded"}, + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "condition", + Literals: []string{"add"}, + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "type", + Literals: []string{"circle"}, + }, + { + Kind: mcfunction.ParameterKindVector3, + Name: "center", + }, + { + Kind: mcfunction.ParameterKindNumber, + Name: "radius", + }, + { + Kind: mcfunction.ParameterKindString, + Name: "function", + Tags: []string{mcfunction.TagFunctionFile}, + }, + }, + }, + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindLiteral, + Name: "mode", + Literals: []string{"on_area_loaded"}, + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "condition", + Literals: []string{"add"}, + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "type", + Literals: []string{"tickingarea"}, + }, + { + Kind: mcfunction.ParameterKindString, + Name: "name", + Tags: []string{mcfunction.TagTickingAreaId}, + }, + { + Kind: mcfunction.ParameterKindString, + Name: "function", + Tags: []string{mcfunction.TagFunctionFile}, + }, + }, + }, + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindLiteral, + Name: "mode", + Literals: []string{"on_area_loaded"}, + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "condition", + Literals: []string{"clear"}, + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "cleartype", + Literals: []string{"tickingarea"}, + }, + { + Kind: mcfunction.ParameterKindString, + Name: "name", + Tags: []string{mcfunction.TagTickingAreaId}, + }, + { + Kind: mcfunction.ParameterKindString, + Name: "function", + Tags: []string{mcfunction.TagFunctionFile}, + Optional: true, + }, + }, + }, + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindLiteral, + Name: "mode", + Literals: []string{"on_area_loaded"}, + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "condition", + Literals: []string{"clear"}, + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "cleartype", + Literals: []string{"function"}, + }, + { + Kind: mcfunction.ParameterKindString, + Name: "function", + Tags: []string{mcfunction.TagFunctionFile}, + }, + }, + }, + }, +} diff --git a/internal/mcfunction/builtin/scoreboard.go b/internal/mcfunction/builtin/scoreboard.go new file mode 100644 index 0000000..ad6adda --- /dev/null +++ b/internal/mcfunction/builtin/scoreboard.go @@ -0,0 +1,308 @@ +package builtin + +import "github.com/rockide/language-server/internal/mcfunction" + +var Scoreboard = &mcfunction.Spec{ + Name: "scoreboard", + Description: "Tracks and displays scores for various objectives.", + Overloads: []mcfunction.SpecOverload{ + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindLiteral, + Name: "category", + Literals: []string{"objectives"}, + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "action", + Literals: []string{"add"}, + }, + { + Kind: mcfunction.ParameterKindString, + Name: "objective", + Tags: []string{mcfunction.TagScoreboardObjectiveId}, + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "criteria", + Literals: []string{"dummy"}, + }, + { + Kind: mcfunction.ParameterKindString, + Name: "displayName", + Optional: true, + }, + }, + }, + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindLiteral, + Name: "category", + Literals: []string{"objectives"}, + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "action", + Literals: []string{"remove"}, + }, + { + Kind: mcfunction.ParameterKindString, + Name: "objective", + Tags: []string{mcfunction.TagScoreboardObjectiveId}, + }, + }, + }, + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindLiteral, + Name: "category", + Literals: []string{"objectives"}, + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "action", + Literals: []string{"list"}, + }, + }, + }, + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindLiteral, + Name: "category", + Literals: []string{"objectives"}, + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "action", + Literals: []string{"setdisplay"}, + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "displaySlot", + Literals: []string{"belowname", "list", "sidebar"}, + }, + { + Kind: mcfunction.ParameterKindString, + Name: "objective", + Optional: true, + Tags: []string{mcfunction.TagScoreboardObjectiveId}, + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "sortOrder", + Optional: true, + Literals: []string{"ascending", "descending"}, + }, + }, + }, + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindLiteral, + Name: "category", + Literals: []string{"objectives"}, + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "action", + Literals: []string{"setdisplay"}, + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "displaySlot", + Literals: []string{"belowname"}, + }, + { + Kind: mcfunction.ParameterKindString, + Name: "objective", + Optional: true, + Tags: []string{mcfunction.TagScoreboardObjectiveId}, + }, + }, + }, + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindLiteral, + Name: "category", + Literals: []string{"players"}, + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "action", + Literals: []string{"list"}, + }, + { + Kind: mcfunction.ParameterKindSelector, + Name: "playername", + Optional: true, + }, + }, + }, + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindLiteral, + Name: "category", + Literals: []string{"players"}, + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "action", + Literals: []string{"reset"}, + }, + { + Kind: mcfunction.ParameterKindSelector, + Name: "player", + }, + { + Kind: mcfunction.ParameterKindString, + Name: "objective", + Tags: []string{mcfunction.TagScoreboardObjectiveId}, + Optional: true, + }, + }, + }, + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindLiteral, + Name: "category", + Literals: []string{"players"}, + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "action", + Literals: []string{"test"}, + }, + { + Kind: mcfunction.ParameterKindSelector, + Name: "player", + }, + { + Kind: mcfunction.ParameterKindString, + Name: "objective", + Tags: []string{mcfunction.TagScoreboardObjectiveId}, + }, + { + Kind: mcfunction.ParameterKindWildcardInteger, + Name: "min", + }, + { + Kind: mcfunction.ParameterKindWildcardInteger, + Name: "max", + Optional: true, + }, + }, + }, + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindLiteral, + Name: "category", + Literals: []string{"players"}, + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "action", + Literals: []string{"random"}, + }, + { + Kind: mcfunction.ParameterKindSelector, + Name: "player", + }, + { + Kind: mcfunction.ParameterKindString, + Name: "objective", + Tags: []string{mcfunction.TagScoreboardObjectiveId}, + }, + { + Kind: mcfunction.ParameterKindInteger, + Name: "min", + }, + { + Kind: mcfunction.ParameterKindInteger, + Name: "max", + }, + }, + }, + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindLiteral, + Name: "category", + Literals: []string{"players"}, + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "action", + Literals: []string{"set", "add", "remove"}, + }, + { + Kind: mcfunction.ParameterKindSelector, + Name: "player", + }, + { + Kind: mcfunction.ParameterKindString, + Name: "objective", + Tags: []string{mcfunction.TagScoreboardObjectiveId}, + }, + { + Kind: mcfunction.ParameterKindInteger, + Name: "count", + }, + }, + }, + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindLiteral, + Name: "category", + Literals: []string{"players"}, + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "action", + Literals: []string{"operation"}, + }, + { + Kind: mcfunction.ParameterKindSelector, + Name: "targetName", + }, + { + Kind: mcfunction.ParameterKindString, + Name: "targetObjective", + Tags: []string{mcfunction.TagScoreboardObjectiveId}, + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "operation", + Literals: []string{ + "%=", + "*=", + "+=", + "-=", + "/=", + "<", + "=", + ">", + "><", + }, + }, + { + Kind: mcfunction.ParameterKindSelector, + Name: "selector", + }, + { + Kind: mcfunction.ParameterKindString, + Name: "objective", + Tags: []string{mcfunction.TagScoreboardObjectiveId}, + }, + }, + }, + }, +} diff --git a/internal/mcfunction/builtin/script.go b/internal/mcfunction/builtin/script.go new file mode 100644 index 0000000..d318564 --- /dev/null +++ b/internal/mcfunction/builtin/script.go @@ -0,0 +1,122 @@ +package builtin + +import "github.com/rockide/language-server/internal/mcfunction" + +var Script = &mcfunction.Spec{ + Name: "script", + Description: "Script debugger commands.", + Overloads: []mcfunction.SpecOverload{ + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindLiteral, + Name: "mode", + Literals: []string{"debugger"}, + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "action", + Literals: []string{"listen"}, + }, + { + Kind: mcfunction.ParameterKindInteger, + Name: "port", + }, + }, + }, + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindLiteral, + Name: "mode", + Literals: []string{"debugger"}, + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "action", + Literals: []string{"connect"}, + }, + { + Kind: mcfunction.ParameterKindString, + Name: "host", + Optional: true, + }, + { + Kind: mcfunction.ParameterKindInteger, + Name: "port", + Optional: true, + }, + }, + }, + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindLiteral, + Name: "mode", + Literals: []string{"debugger"}, + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "action", + Literals: []string{"close"}, + }, + }, + }, + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindLiteral, + Name: "mode", + Literals: []string{"profiler"}, + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "action", + Literals: []string{"start"}, + }, + }, + }, + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindLiteral, + Name: "mode", + Literals: []string{"profiler"}, + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "action", + Literals: []string{"stop"}, + }, + }, + }, + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindLiteral, + Name: "mode", + Literals: []string{"diagnostics"}, + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "action", + Literals: []string{"startcapture"}, + }, + }, + }, + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindLiteral, + Name: "mode", + Literals: []string{"diagnostics"}, + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "action", + Literals: []string{"stopcapture"}, + }, + }, + }, + }, +} diff --git a/internal/mcfunction/builtin/scriptevent.go b/internal/mcfunction/builtin/scriptevent.go new file mode 100644 index 0000000..87ab0ab --- /dev/null +++ b/internal/mcfunction/builtin/scriptevent.go @@ -0,0 +1,23 @@ +package builtin + +import "github.com/rockide/language-server/internal/mcfunction" + +var Scriptevent = &mcfunction.Spec{ + Name: "scriptevent", + Description: "Triggers a script event with an ID and message.", + Overloads: []mcfunction.SpecOverload{ + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindString, + Name: "messageId", + }, + { + Kind: mcfunction.ParameterKindString, + Name: "message", + Greedy: true, + }, + }, + }, + }, +} diff --git a/internal/mcfunction/builtin/setblock.go b/internal/mcfunction/builtin/setblock.go new file mode 100644 index 0000000..cbe033e --- /dev/null +++ b/internal/mcfunction/builtin/setblock.go @@ -0,0 +1,49 @@ +package builtin + +import "github.com/rockide/language-server/internal/mcfunction" + +var Setblock = &mcfunction.Spec{ + Name: "setblock", + Description: "Changes a block to another block.", + Overloads: []mcfunction.SpecOverload{ + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindVector3, + Name: "position", + }, + { + Kind: mcfunction.ParameterKindString, + Name: "tileName", + Tags: []string{mcfunction.TagBlockId}, + }, + blockStates, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "oldBlockHandling", + Optional: true, + Literals: []string{"destroy", "keep", "replace"}, + }, + }, + }, + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindVector3, + Name: "position", + }, + { + Kind: mcfunction.ParameterKindString, + Name: "tileName", + Tags: []string{mcfunction.TagBlockId}, + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "oldBlockHandling", + Optional: true, + Literals: []string{"destroy", "keep", "replace"}, + }, + }, + }, + }, +} diff --git a/internal/mcfunction/builtin/setmaxplayers.go b/internal/mcfunction/builtin/setmaxplayers.go new file mode 100644 index 0000000..183a852 --- /dev/null +++ b/internal/mcfunction/builtin/setmaxplayers.go @@ -0,0 +1,18 @@ +package builtin + +import "github.com/rockide/language-server/internal/mcfunction" + +var Setmaxplayers = &mcfunction.Spec{ + Name: "setmaxplayers", + Description: "Sets the maximum number of players for this game session.", + Overloads: []mcfunction.SpecOverload{ + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindInteger, + Name: "maxPlayers", + }, + }, + }, + }, +} diff --git a/internal/mcfunction/builtin/setworldspawn.go b/internal/mcfunction/builtin/setworldspawn.go new file mode 100644 index 0000000..b3b6ff4 --- /dev/null +++ b/internal/mcfunction/builtin/setworldspawn.go @@ -0,0 +1,19 @@ +package builtin + +import "github.com/rockide/language-server/internal/mcfunction" + +var Setworldspawn = &mcfunction.Spec{ + Name: "setworldspawn", + Description: "Sets the world spawn.", + Overloads: []mcfunction.SpecOverload{ + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindVector3, + Name: "spawnPoint", + Optional: true, + }, + }, + }, + }, +} diff --git a/internal/mcfunction/builtin/spawnpoint.go b/internal/mcfunction/builtin/spawnpoint.go new file mode 100644 index 0000000..9949f9e --- /dev/null +++ b/internal/mcfunction/builtin/spawnpoint.go @@ -0,0 +1,24 @@ +package builtin + +import "github.com/rockide/language-server/internal/mcfunction" + +var Spawnpoint = &mcfunction.Spec{ + Name: "spawnpoint", + Description: "Sets the spawn point for a player.", + Overloads: []mcfunction.SpecOverload{ + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindSelector, + Name: "player", + Optional: true, + }, + { + Kind: mcfunction.ParameterKindVector3, + Name: "spawnPos", + Optional: true, + }, + }, + }, + }, +} diff --git a/internal/mcfunction/builtin/spreadplayers.go b/internal/mcfunction/builtin/spreadplayers.go new file mode 100644 index 0000000..be8906e --- /dev/null +++ b/internal/mcfunction/builtin/spreadplayers.go @@ -0,0 +1,51 @@ +package builtin + +import ( + "math" + + "github.com/rockide/language-server/internal/mcfunction" +) + +var Spreadplayers = &mcfunction.Spec{ + Name: "spreadplayers", + Description: "Teleports entities to random locations.", + Overloads: []mcfunction.SpecOverload{ + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindRelativeNumber, + Name: "x", + }, + { + Kind: mcfunction.ParameterKindRelativeNumber, + Name: "z", + }, + { + Kind: mcfunction.ParameterKindNumber, + Name: "spreadDistance", + Range: &mcfunction.NumberRange{ + Min: 0, + Max: math.MaxFloat64, + }, + }, + { + Kind: mcfunction.ParameterKindNumber, + Name: "maxRange", + Range: &mcfunction.NumberRange{ + Min: 1, + Max: math.MaxFloat64, + }, + }, + { + Kind: mcfunction.ParameterKindSelector, + Name: "victim", + }, + { + Kind: mcfunction.ParameterKindNumber, + Name: "maxHeight", + Optional: true, + }, + }, + }, + }, +} diff --git a/internal/mcfunction/builtin/stopsound.go b/internal/mcfunction/builtin/stopsound.go new file mode 100644 index 0000000..16f240f --- /dev/null +++ b/internal/mcfunction/builtin/stopsound.go @@ -0,0 +1,24 @@ +package builtin + +import "github.com/rockide/language-server/internal/mcfunction" + +var Stopsound = &mcfunction.Spec{ + Name: "stopsound", + Description: "Stops a sound.", + Overloads: []mcfunction.SpecOverload{ + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindSelector, + Name: "player", + }, + { + Kind: mcfunction.ParameterKindString, + Name: "sound", + Optional: true, + Tags: []string{mcfunction.TagSoundId}, + }, + }, + }, + }, +} diff --git a/internal/mcfunction/builtin/structure.go b/internal/mcfunction/builtin/structure.go new file mode 100644 index 0000000..1c95a25 --- /dev/null +++ b/internal/mcfunction/builtin/structure.go @@ -0,0 +1,216 @@ +package builtin + +import ( + "math" + + "github.com/rockide/language-server/internal/mcfunction" +) + +var Structure = &mcfunction.Spec{ + Name: "structure", + Description: "Saves or loads a structure in the world.", + Overloads: []mcfunction.SpecOverload{ + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindLiteral, + Name: "action", + Literals: []string{"save"}, + }, + { + Kind: mcfunction.ParameterKindString, + Name: "name", + Tags: []string{mcfunction.TagStructureFile}, + }, + { + Kind: mcfunction.ParameterKindVector3, + Name: "from", + }, + { + Kind: mcfunction.ParameterKindVector3, + Name: "to", + }, + { + Kind: mcfunction.ParameterKindBoolean, + Name: "includeEntities", + Optional: true, + }, + { + Kind: mcfunction.ParameterKindBoolean, + Name: "includeBlocks", + Optional: true, + }, + }, + }, + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindLiteral, + Name: "action", + Literals: []string{"delete"}, + }, + { + Kind: mcfunction.ParameterKindString, + Name: "name", + Tags: []string{mcfunction.TagStructureFile}, + }, + }, + }, + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindLiteral, + Name: "action", + Literals: []string{"load"}, + }, + { + Kind: mcfunction.ParameterKindString, + Name: "name", + Tags: []string{mcfunction.TagStructureFile}, + }, + { + Kind: mcfunction.ParameterKindVector3, + Name: "to", + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "rotation", + Optional: true, + Literals: []string{ + "0_degrees", + "90_degrees", + "180_degrees", + "270_degrees", + }, + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "mirror", + Optional: true, + Literals: []string{ + "none", + "x", + "xz", + "z", + }, + }, + { + Kind: mcfunction.ParameterKindBoolean, + Name: "includeEntities", + Optional: true, + }, + { + Kind: mcfunction.ParameterKindBoolean, + Name: "includeBlocks", + Optional: true, + }, + { + Kind: mcfunction.ParameterKindBoolean, + Name: "waterlogged", + Optional: true, + }, + { + Kind: mcfunction.ParameterKindNumber, + Name: "integrity", + Optional: true, + Range: &mcfunction.NumberRange{ + Min: 0, + Max: 100, + }, + }, + { + Kind: mcfunction.ParameterKindString, + Name: "seed", + Optional: true, + }, + }, + }, + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindLiteral, + Name: "action", + Literals: []string{"load"}, + }, + { + Kind: mcfunction.ParameterKindString, + Name: "name", + Tags: []string{mcfunction.TagStructureFile}, + }, + { + Kind: mcfunction.ParameterKindVector3, + Name: "to", + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "rotation", + Optional: true, + Literals: []string{ + "0_degrees", + "90_degrees", + "180_degrees", + "270_degrees", + }, + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "mirror", + Optional: true, + Literals: []string{ + "none", + "x", + "xz", + "z", + }, + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "animationMode", + Optional: true, + Literals: []string{ + "block_by_block", + "layer_by_layer", + }, + }, + { + Kind: mcfunction.ParameterKindInteger, + Name: "animationSeconds", + Optional: true, + Range: &mcfunction.NumberRange{ + Min: 0, + Max: math.MaxFloat64, + }, + }, + { + Kind: mcfunction.ParameterKindBoolean, + Name: "includeEntities", + Optional: true, + }, + { + Kind: mcfunction.ParameterKindBoolean, + Name: "includeBlocks", + Optional: true, + }, + { + Kind: mcfunction.ParameterKindBoolean, + Name: "waterlogged", + Optional: true, + }, + { + Kind: mcfunction.ParameterKindNumber, + Name: "integrity", + Optional: true, + Range: &mcfunction.NumberRange{ + Min: 0, + Max: 100, + }, + }, + { + Kind: mcfunction.ParameterKindString, + Name: "seed", + Optional: true, + }, + }, + }, + }, +} diff --git a/internal/mcfunction/builtin/summon.go b/internal/mcfunction/builtin/summon.go new file mode 100644 index 0000000..e39a358 --- /dev/null +++ b/internal/mcfunction/builtin/summon.go @@ -0,0 +1,133 @@ +package builtin + +import "github.com/rockide/language-server/internal/mcfunction" + +var Summon = &mcfunction.Spec{ + Name: "summon", + Description: "Summons an entity.", + Overloads: []mcfunction.SpecOverload{ + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindString, + Name: "entityType", + Tags: []string{mcfunction.TagEntityId}, + }, + { + Kind: mcfunction.ParameterKindVector3, + Name: "spawnPos", + Optional: true, + }, + { + Kind: mcfunction.ParameterKindRelativeNumber, + Name: "yRot", + Optional: true, + Tags: []string{mcfunction.TagYaw}, + }, + { + Kind: mcfunction.ParameterKindRelativeNumber, + Name: "xRot", + Optional: true, + Tags: []string{mcfunction.TagPitch}, + }, + { + Kind: mcfunction.ParameterKindString, + Name: "spawnEvent", + Tags: []string{mcfunction.TagEntityEvent}, + Optional: true, + }, + { + Kind: mcfunction.ParameterKindString, + Name: "nameTag", + Optional: true, + }, + }, + }, + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindString, + Name: "entityType", + Tags: []string{mcfunction.TagEntityId}, + }, + { + Kind: mcfunction.ParameterKindString, + Name: "nameTag", + }, + { + Kind: mcfunction.ParameterKindVector3, + Name: "spawnPos", + Optional: true, + }, + }, + }, + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindString, + Name: "entityType", + Tags: []string{mcfunction.TagEntityId}, + }, + { + Kind: mcfunction.ParameterKindVector3, + Name: "spawnPos", + Optional: true, + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "facing", + Literals: []string{"facing"}, + }, + { + Kind: mcfunction.ParameterKindVector3, + Name: "lookAtPosition", + }, + { + Kind: mcfunction.ParameterKindString, + Name: "spawnEvent", + Tags: []string{mcfunction.TagEntityEvent}, + Optional: true, + }, + { + Kind: mcfunction.ParameterKindString, + Name: "nameTag", + Optional: true, + }, + }, + }, + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindString, + Name: "entityType", + Tags: []string{mcfunction.TagEntityId}, + }, + { + Kind: mcfunction.ParameterKindVector3, + Name: "spawnPos", + Optional: true, + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "facing", + Literals: []string{"facing"}, + }, + { + Kind: mcfunction.ParameterKindSelector, + Name: "lookAtEntity", + }, + { + Kind: mcfunction.ParameterKindString, + Name: "spawnEvent", + Tags: []string{mcfunction.TagEntityEvent}, + Optional: true, + }, + { + Kind: mcfunction.ParameterKindString, + Name: "nameTag", + Optional: true, + }, + }, + }, + }, +} diff --git a/internal/mcfunction/builtin/tag.go b/internal/mcfunction/builtin/tag.go new file mode 100644 index 0000000..da453a3 --- /dev/null +++ b/internal/mcfunction/builtin/tag.go @@ -0,0 +1,41 @@ +package builtin + +import "github.com/rockide/language-server/internal/mcfunction" + +var Tag = &mcfunction.Spec{ + Name: "tag", + Description: "Manages tags stored in entities.", + Overloads: []mcfunction.SpecOverload{ + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindSelector, + Name: "entity", + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "action", + Literals: []string{"add", "remove"}, + }, + { + Kind: mcfunction.ParameterKindString, + Name: "name", + Tags: []string{mcfunction.TagTagId}, + }, + }, + }, + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindSelector, + Name: "entity", + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "action", + Literals: []string{"list"}, + }, + }, + }, + }, +} diff --git a/internal/mcfunction/builtin/teleport.go b/internal/mcfunction/builtin/teleport.go new file mode 100644 index 0000000..d896b2a --- /dev/null +++ b/internal/mcfunction/builtin/teleport.go @@ -0,0 +1,214 @@ +package builtin + +import "github.com/rockide/language-server/internal/mcfunction" + +var Teleport = &mcfunction.Spec{ + Name: "teleport", + Aliases: []string{"tp"}, + Description: "Teleports entities (players, mobs, etc.).", + Overloads: []mcfunction.SpecOverload{ + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindVector3, + Name: "destination", + }, + { + Kind: mcfunction.ParameterKindBoolean, + Name: "checkForBlocks", + Optional: true, + }, + }, + }, + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindVector3, + Name: "destination", + }, + { + Kind: mcfunction.ParameterKindRelativeNumber, + Name: "yRot", + Optional: true, + Tags: []string{mcfunction.TagYaw}, + }, + { + Kind: mcfunction.ParameterKindRelativeNumber, + Name: "xRot", + Optional: true, + Tags: []string{mcfunction.TagPitch}, + }, + { + Kind: mcfunction.ParameterKindBoolean, + Name: "checkForBlocks", + Optional: true, + }, + }, + }, + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindVector3, + Name: "destination", + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "facing", + Literals: []string{"facing"}, + }, + { + Kind: mcfunction.ParameterKindVector3, + Name: "lookAtPosition", + }, + { + Kind: mcfunction.ParameterKindBoolean, + Name: "checkForBlocks", + Optional: true, + }, + }, + }, + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindVector3, + Name: "destination", + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "facing", + Literals: []string{"facing"}, + }, + { + Kind: mcfunction.ParameterKindSelector, + Name: "lookAtEntity", + }, + { + Kind: mcfunction.ParameterKindBoolean, + Name: "checkForBlocks", + Optional: true, + }, + }, + }, + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindSelector, + Name: "victim", + }, + { + Kind: mcfunction.ParameterKindVector3, + Name: "destination", + }, + { + Kind: mcfunction.ParameterKindRelativeNumber, + Name: "yRot", + Optional: true, + }, + { + Kind: mcfunction.ParameterKindRelativeNumber, + Name: "xRot", + Optional: true, + }, + { + Kind: mcfunction.ParameterKindBoolean, + Name: "checkForBlocks", + Optional: true, + }, + }, + }, + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindSelector, + Name: "victim", + }, + { + Kind: mcfunction.ParameterKindVector3, + Name: "destination", + }, + { + Kind: mcfunction.ParameterKindBoolean, + Name: "checkForBlocks", + Optional: true, + }, + }, + }, + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindSelector, + Name: "victim", + }, + { + Kind: mcfunction.ParameterKindVector3, + Name: "destination", + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "facing", + Literals: []string{"facing"}, + }, + { + Kind: mcfunction.ParameterKindVector3, + Name: "lookAtPosition", + }, + { + Kind: mcfunction.ParameterKindBoolean, + Name: "checkForBlocks", + Optional: true, + }, + }, + }, + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindSelector, + Name: "victim", + }, + { + Kind: mcfunction.ParameterKindVector3, + Name: "destination", + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "facing", + Literals: []string{"facing"}, + }, + { + Kind: mcfunction.ParameterKindSelector, + Name: "lookAtEntity", + }, + { + Kind: mcfunction.ParameterKindBoolean, + Name: "checkForBlocks", + Optional: true, + }, + }, + }, + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindSelector, + Name: "destination", + }, + }, + }, + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindSelector, + Name: "victim", + }, + { + Kind: mcfunction.ParameterKindSelector, + Name: "destination", + }, + { + Kind: mcfunction.ParameterKindBoolean, + Name: "checkForBlocks", + Optional: true, + }, + }, + }, + }, +} diff --git a/internal/mcfunction/builtin/tell.go b/internal/mcfunction/builtin/tell.go new file mode 100644 index 0000000..f92f97a --- /dev/null +++ b/internal/mcfunction/builtin/tell.go @@ -0,0 +1,23 @@ +package builtin + +import "github.com/rockide/language-server/internal/mcfunction" + +var Tell = &mcfunction.Spec{ + Name: "tell", + Description: "Sends a private message to one or more players.", + Overloads: []mcfunction.SpecOverload{ + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindSelector, + Name: "target", + }, + { + Kind: mcfunction.ParameterKindString, + Name: "message", + Greedy: true, + }, + }, + }, + }, +} diff --git a/internal/mcfunction/builtin/tellraw.go b/internal/mcfunction/builtin/tellraw.go new file mode 100644 index 0000000..3d1d5fe --- /dev/null +++ b/internal/mcfunction/builtin/tellraw.go @@ -0,0 +1,22 @@ +package builtin + +import "github.com/rockide/language-server/internal/mcfunction" + +var Tellraw = &mcfunction.Spec{ + Name: "tellraw", + Description: "Sends a JSON message to players.", + Overloads: []mcfunction.SpecOverload{ + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindSelector, + Name: "target", + }, + { + Kind: mcfunction.ParameterKindRawMessage, + Name: "raw json message", + }, + }, + }, + }, +} diff --git a/internal/mcfunction/builtin/testfor.go b/internal/mcfunction/builtin/testfor.go new file mode 100644 index 0000000..91849d2 --- /dev/null +++ b/internal/mcfunction/builtin/testfor.go @@ -0,0 +1,18 @@ +package builtin + +import "github.com/rockide/language-server/internal/mcfunction" + +var Testfor = &mcfunction.Spec{ + Name: "testfor", + Description: "Counts entities (players, mobs, items, etc.) matching specified conditions.", + Overloads: []mcfunction.SpecOverload{ + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindSelector, + Name: "victim", + }, + }, + }, + }, +} diff --git a/internal/mcfunction/builtin/testforblock.go b/internal/mcfunction/builtin/testforblock.go new file mode 100644 index 0000000..a641ca6 --- /dev/null +++ b/internal/mcfunction/builtin/testforblock.go @@ -0,0 +1,24 @@ +package builtin + +import "github.com/rockide/language-server/internal/mcfunction" + +var Testforblock = &mcfunction.Spec{ + Name: "testforblock", + Description: "Tests whether a certain block is in a specific location.", + Overloads: []mcfunction.SpecOverload{ + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindVector3, + Name: "position", + }, + { + Kind: mcfunction.ParameterKindString, + Name: "tileName", + Tags: []string{mcfunction.TagBlockId}, + }, + blockStates, + }, + }, + }, +} diff --git a/internal/mcfunction/builtin/testforblocks.go b/internal/mcfunction/builtin/testforblocks.go new file mode 100644 index 0000000..380c5c9 --- /dev/null +++ b/internal/mcfunction/builtin/testforblocks.go @@ -0,0 +1,32 @@ +package builtin + +import "github.com/rockide/language-server/internal/mcfunction" + +var Testforblocks = &mcfunction.Spec{ + Name: "testforblocks", + Description: "Tests whether the blocks in two regions match.", + Overloads: []mcfunction.SpecOverload{ + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindVector3, + Name: "begin", + }, + { + Kind: mcfunction.ParameterKindVector3, + Name: "end", + }, + { + Kind: mcfunction.ParameterKindVector3, + Name: "destination", + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "mode", + Optional: true, + Literals: []string{"all", "masked"}, + }, + }, + }, + }, +} diff --git a/internal/mcfunction/builtin/tickingarea.go b/internal/mcfunction/builtin/tickingarea.go new file mode 100644 index 0000000..5956d23 --- /dev/null +++ b/internal/mcfunction/builtin/tickingarea.go @@ -0,0 +1,167 @@ +package builtin + +import ( + "math" + + "github.com/rockide/language-server/internal/mcfunction" +) + +var Tickingarea = &mcfunction.Spec{ + Name: "tickingarea", + Description: "Add, remove, or list ticking areas.", + Overloads: []mcfunction.SpecOverload{ + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindLiteral, + Name: "mode", + Literals: []string{"add"}, + }, + { + Kind: mcfunction.ParameterKindVector3, + Name: "from", + }, + { + Kind: mcfunction.ParameterKindVector3, + Name: "to", + }, + { + Kind: mcfunction.ParameterKindString, + Name: "name", + Optional: true, + Tags: []string{mcfunction.TagTickingAreaId}, + }, + { + Kind: mcfunction.ParameterKindBoolean, + Name: "preload", + Optional: true, + }, + }, + }, + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindLiteral, + Name: "mode", + Literals: []string{"add"}, + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "circle", + Literals: []string{"circle"}, + }, + { + Kind: mcfunction.ParameterKindVector3, + Name: "center", + }, + { + Kind: mcfunction.ParameterKindInteger, + Name: "radius", + Range: &mcfunction.NumberRange{ + Min: 0, + Max: math.MaxFloat64, + }, + }, + { + Kind: mcfunction.ParameterKindString, + Name: "name", + Optional: true, + Tags: []string{mcfunction.TagTickingAreaId}, + }, + { + Kind: mcfunction.ParameterKindBoolean, + Name: "preload", + Optional: true, + }, + }, + }, + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindLiteral, + Name: "mode", + Literals: []string{"remove"}, + }, + { + Kind: mcfunction.ParameterKindVector3, + Name: "position", + }, + }, + }, + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindLiteral, + Name: "mode", + Literals: []string{"remove"}, + }, + { + Kind: mcfunction.ParameterKindString, + Name: "name", + Tags: []string{mcfunction.TagTickingAreaId}, + }, + }, + }, + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindLiteral, + Name: "mode", + Literals: []string{"remove_all"}, + }, + }, + }, + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindLiteral, + Name: "mode", + Literals: []string{"list"}, + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "all-dimensions", + Optional: true, + Literals: []string{"all-dimensions"}, + }, + }, + }, + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindLiteral, + Name: "mode", + Literals: []string{"preload"}, + }, + { + Kind: mcfunction.ParameterKindVector3, + Name: "position", + }, + { + Kind: mcfunction.ParameterKindBoolean, + Name: "preload", + Optional: true, + }, + }, + }, + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindLiteral, + Name: "mode", + Literals: []string{"preload"}, + }, + { + Kind: mcfunction.ParameterKindString, + Name: "name", + Tags: []string{mcfunction.TagTickingAreaId}, + }, + { + Kind: mcfunction.ParameterKindBoolean, + Name: "preload", + Optional: true, + }, + }, + }, + }, +} diff --git a/internal/mcfunction/builtin/time.go b/internal/mcfunction/builtin/time.go new file mode 100644 index 0000000..ea4b9ae --- /dev/null +++ b/internal/mcfunction/builtin/time.go @@ -0,0 +1,75 @@ +package builtin + +import "github.com/rockide/language-server/internal/mcfunction" + +var Time = &mcfunction.Spec{ + Name: "time", + Description: "Changes or queries the world's game time.", + Overloads: []mcfunction.SpecOverload{ + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindLiteral, + Name: "mode", + Literals: []string{"add"}, + }, + { + Kind: mcfunction.ParameterKindInteger, + Name: "amount", + }, + }, + }, + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindLiteral, + Name: "mode", + Literals: []string{"set"}, + }, + { + Kind: mcfunction.ParameterKindInteger, + Name: "amount", + }, + }, + }, + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindLiteral, + Name: "mode", + Literals: []string{"set"}, + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "time", + Literals: []string{ + "day", + "midnight", + "night", + "noon", + "sunrise", + "sunset", + }, + }, + }, + }, + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindLiteral, + Name: "mode", + Literals: []string{"query"}, + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "time", + Literals: []string{ + "day", + "daytime", + "gametime", + }, + }, + }, + }, + }, +} diff --git a/internal/mcfunction/builtin/title.go b/internal/mcfunction/builtin/title.go new file mode 100644 index 0000000..306c256 --- /dev/null +++ b/internal/mcfunction/builtin/title.go @@ -0,0 +1,95 @@ +package builtin + +import ( + "math" + + "github.com/rockide/language-server/internal/mcfunction" +) + +var Title = &mcfunction.Spec{ + Name: "title", + Description: "Controls screen titles.", + Overloads: []mcfunction.SpecOverload{ + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindSelector, + Name: "player", + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "clear", + Literals: []string{"clear"}, + }, + }, + }, + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindSelector, + Name: "player", + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "reset", + Literals: []string{"reset"}, + }, + }, + }, + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindSelector, + Name: "player", + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "titleLocation", + Literals: []string{"title", "subtitle", "actionbar"}, + }, + { + Kind: mcfunction.ParameterKindString, + Name: "titleText", + Greedy: true, + }, + }, + }, + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindSelector, + Name: "player", + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "times", + Literals: []string{"times"}, + }, + { + Kind: mcfunction.ParameterKindInteger, + Name: "fadeIn", + Range: &mcfunction.NumberRange{ + Min: 0, + Max: math.MaxFloat64, + }, + }, + { + Kind: mcfunction.ParameterKindInteger, + Name: "stay", + Range: &mcfunction.NumberRange{ + Min: 0, + Max: math.MaxFloat64, + }, + }, + { + Kind: mcfunction.ParameterKindInteger, + Name: "fadeOut", + Range: &mcfunction.NumberRange{ + Min: 0, + Max: math.MaxFloat64, + }, + }, + }, + }, + }, +} diff --git a/internal/mcfunction/builtin/titleraw.go b/internal/mcfunction/builtin/titleraw.go new file mode 100644 index 0000000..e1c7ee4 --- /dev/null +++ b/internal/mcfunction/builtin/titleraw.go @@ -0,0 +1,94 @@ +package builtin + +import ( + "math" + + "github.com/rockide/language-server/internal/mcfunction" +) + +var Titleraw = &mcfunction.Spec{ + Name: "titleraw", + Description: "Controls screen titles with JSON messages.", + Overloads: []mcfunction.SpecOverload{ + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindSelector, + Name: "player", + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "clear", + Literals: []string{"clear"}, + }, + }, + }, + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindSelector, + Name: "player", + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "reset", + Literals: []string{"reset"}, + }, + }, + }, + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindSelector, + Name: "player", + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "titleLocation", + Literals: []string{"title", "subtitle", "actionbar"}, + }, + { + Kind: mcfunction.ParameterKindRawMessage, + Name: "raw json titleText", + }, + }, + }, + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindSelector, + Name: "player", + }, + { + Kind: mcfunction.ParameterKindLiteral, + Name: "times", + Literals: []string{"times"}, + }, + { + Kind: mcfunction.ParameterKindInteger, + Name: "fadeIn", + Range: &mcfunction.NumberRange{ + Min: 0, + Max: math.MaxFloat64, + }, + }, + { + Kind: mcfunction.ParameterKindInteger, + Name: "stay", + Range: &mcfunction.NumberRange{ + Min: 0, + Max: math.MaxFloat64, + }, + }, + { + Kind: mcfunction.ParameterKindInteger, + Name: "fadeOut", + Range: &mcfunction.NumberRange{ + Min: 0, + Max: math.MaxFloat64, + }, + }, + }, + }, + }, +} diff --git a/internal/mcfunction/builtin/toggledownfall.go b/internal/mcfunction/builtin/toggledownfall.go new file mode 100644 index 0000000..b837160 --- /dev/null +++ b/internal/mcfunction/builtin/toggledownfall.go @@ -0,0 +1,13 @@ +package builtin + +import "github.com/rockide/language-server/internal/mcfunction" + +var Toggledownfall = &mcfunction.Spec{ + Name: "toggledownfall", + Description: "Toggles the weather.", + Overloads: []mcfunction.SpecOverload{ + { + Parameters: []mcfunction.ParameterSpec{}, + }, + }, +} diff --git a/internal/mcfunction/builtin/weather.go b/internal/mcfunction/builtin/weather.go new file mode 100644 index 0000000..0934a93 --- /dev/null +++ b/internal/mcfunction/builtin/weather.go @@ -0,0 +1,33 @@ +package builtin + +import "github.com/rockide/language-server/internal/mcfunction" + +var Weather = &mcfunction.Spec{ + Name: "weather", + Description: "Sets the weather.", + Overloads: []mcfunction.SpecOverload{ + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindLiteral, + Name: "type", + Literals: []string{"clear", "rain", "thunder"}, + }, + { + Kind: mcfunction.ParameterKindInteger, + Name: "duration", + Optional: true, + }, + }, + }, + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindLiteral, + Name: "query", + Literals: []string{"query"}, + }, + }, + }, + }, +} diff --git a/internal/mcfunction/builtin/xp.go b/internal/mcfunction/builtin/xp.go new file mode 100644 index 0000000..0df9b2b --- /dev/null +++ b/internal/mcfunction/builtin/xp.go @@ -0,0 +1,37 @@ +package builtin + +import "github.com/rockide/language-server/internal/mcfunction" + +var Xp = &mcfunction.Spec{ + Name: "xp", + Description: "Adds or removes player experience.", + Overloads: []mcfunction.SpecOverload{ + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindInteger, + Name: "amount", + }, + { + Kind: mcfunction.ParameterKindSelector, + Name: "player", + Optional: true, + }, + }, + }, + { + Parameters: []mcfunction.ParameterSpec{ + { + Kind: mcfunction.ParameterKindSuffixedInteger, + Name: "amount", + Suffix: "L", + }, + { + Kind: mcfunction.ParameterKindSelector, + Name: "player", + Optional: true, + }, + }, + }, + }, +} diff --git a/internal/mcfunction/lexer/lexer.go b/internal/mcfunction/lexer/lexer.go new file mode 100644 index 0000000..fae975c --- /dev/null +++ b/internal/mcfunction/lexer/lexer.go @@ -0,0 +1,323 @@ +package lexer + +import ( + "iter" +) + +type Lexer struct { + src []rune + i int + state state + lastPos int +} + +func New(input []rune) *Lexer { + return &Lexer{ + src: input, + state: StateStart, + lastPos: -1, + } +} + +func (l *Lexer) eof() bool { + return l.i >= len(l.src) +} + +func (l *Lexer) peek() rune { + if l.eof() { + return 0 + } + return l.src[l.i] +} + +func (l *Lexer) peekN(n int) rune { + if l.i+n >= len(l.src) { + return 0 + } + return l.src[l.i+n] +} + +func (l *Lexer) advance() rune { + if l.eof() { + return 0 + } + l.lastPos = l.i + r := l.src[l.i] + l.i++ + return r +} + +func (l *Lexer) advanceWhile(cond func(rune) bool) { + for !l.eof() && cond(l.peek()) { + l.advance() + } +} + +func (l *Lexer) pos() uint32 { + return uint32(l.i) +} + +func (l *Lexer) emit(kind TokenKind, start uint32) Token { + end := l.pos() + return Token{ + Kind: kind, + Start: start, + End: end, + } +} + +func (l *Lexer) matchPairs(open, close rune) bool { + depth := 0 + for !l.eof() { + r := l.peek() + if r == open { + depth++ + } else if r == close { + depth-- + if depth == 0 { + l.advance() + return true + } + } else if isNewline(r) { + return false + } + l.advance() + } + return false +} + +func (l *Lexer) isInfiniteLoop() bool { + return l.i == l.lastPos +} + +func (l *Lexer) Next() iter.Seq[Token] { + return func(yield func(Token) bool) { + for !l.eof() { + if l.isInfiniteLoop() { + panic("possible infinite loop in lexer") + } + r := l.peek() + start := l.pos() + switch r { + case '\r': + l.advance() + continue + case ' ', '\t': + l.advanceWhile(isWhitespace) + if !yield(l.emit(TokenWhitespace, start)) { + return + } + continue + case '\n': + l.advance() + if !yield(l.emit(TokenNewline, start)) { + return + } + l.state = StateStart + continue + case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9': + l.state = StateNumber + case '-': + if l.i+1 < len(l.src) && isDigit(l.src[l.i+1]) { + l.state = StateNegativeNumber + } + case '~', '^': + l.state = StateRelativeNumber + case '@': + l.state = StateSelector + case '[': + l.state = StateMap + case '{': + l.state = StateJSON + case '=': + l.advance() + if !yield(l.emit(TokenEquals, start)) { + return + } + continue + case ',': + l.advance() + if !yield(l.emit(TokenComma, start)) { + return + } + continue + case '.': + l.advance() + if l.peek() == '.' { + l.advance() + if !yield(l.emit(TokenRange, start)) { + return + } + } else { + if !yield(l.emit(TokenDot, start)) { + return + } + } + continue + case '!': + l.advance() + if !yield(l.emit(TokenBang, start)) { + return + } + continue + } + + switch l.state { + case StateStart: + if r == '#' { + if l.peek() == '#' { + l.advanceWhile(func(r rune) bool { return !isNewline(r) }) + if !yield(l.emit(TokenComment, start)) { + return + } + continue + } + } + fallthrough + case StateString: + if r == '"' { + l.advance() + l.advanceWhile(func(r rune) bool { return r != '"' && !isNewline(r) }) + if l.peek() == '"' { + l.advance() + if !yield(l.emit(TokenString, start)) { + return + } + } else { + if !yield(l.emit(TokenUnterminatedString, start)) { + return + } + l.state = StateStart + continue + } + } else { + l.advanceWhile(func(r rune) bool { return !isTerminateString(r) }) + if !yield(l.emit(TokenString, start)) { + return + } + } + case StateNegativeNumber: + l.advance() // consume '-' + a := l.i + l.advanceWhile(isDigit) + b := l.i + r := l.peek() + if r == '.' && isDigit(l.peekN(1)) { + l.advance() + l.advanceWhile(isDigit) + } + if a == b { + if !yield(l.emit(TokenString, start)) { + return + } + } else { + if !yield(l.emit(TokenNumber, start)) { + return + } + } + case StateNumber: + l.advanceWhile(isDigit) + r := l.peek() + if r == '.' && isDigit(l.peekN(1)) { + l.advance() // consume '.' + l.advanceWhile(isDigit) + } + if !yield(l.emit(TokenNumber, start)) { + return + } + case StateRelativeNumber: + // possible patterns: + // ~ + // ~2 + // ~2.2 + // ~.2 + // ~-2 + // ~-2.2 + // ~-.2 + l.advance() // consume '~' or '^' + r := l.peek() + if r == '-' { + l.advance() // consume '-' + r = l.peek() + } + if isDigit(r) { + l.advanceWhile(isDigit) + r = l.peek() + } + if r == '.' { + l.advance() // consume '.' + l.advanceWhile(isDigit) + } + if !yield(l.emit(TokenRelativeNumber, start)) { + return + } + case StateSelector: + l.advance() // consume '@' + a := l.i + l.advanceWhile(isLetter) + b := l.i + if a == b { + if !yield(l.emit(TokenString, start)) { + return + } + } else { + if !yield(l.emit(TokenSelector, start)) { + return + } + } + case StateMap: + if l.matchPairs('[', ']') { + if !yield(l.emit(TokenMap, start)) { + return + } + } else { + if !yield(l.emit(TokenUnterminatedMap, start)) { + return + } + } + case StateJSON: + if l.matchPairs('{', '}') { + if !yield(l.emit(TokenJSON, start)) { + return + } + } else { + if !yield(l.emit(TokenUnterminatedJSON, start)) { + return + } + } + } + l.state = StateString + } + } +} + +func (l *Lexer) Reset(input []rune) { + l.src = input + l.i = 0 + l.lastPos = -1 + l.state = StateStart +} + +func isWhitespace(r rune) bool { + return r == ' ' || r == '\t' || r == '\r' +} + +func isNewline(r rune) bool { + return r == '\n' +} + +func isTerminateString(r rune) bool { + return isNewline(r) || isWhitespace(r) || isRelativeNumber(r) || r == '@' || r == '"' || r == '[' || r == '{' || r == '=' || r == ',' || r == '!' +} + +func isRelativeNumber(r rune) bool { + return r == '~' || r == '^' +} + +func isDigit(r rune) bool { + return r >= '0' && r <= '9' +} + +func isLetter(r rune) bool { + return (r >= 'a' && r <= 'z') || (r >= 'A' && r <= 'Z') +} diff --git a/internal/mcfunction/lexer/state.go b/internal/mcfunction/lexer/state.go new file mode 100644 index 0000000..d440600 --- /dev/null +++ b/internal/mcfunction/lexer/state.go @@ -0,0 +1,14 @@ +package lexer + +type state uint8 + +const ( + StateStart state = iota + StateString + StateNumber + StateNegativeNumber + StateRelativeNumber + StateSelector + StateMap + StateJSON +) diff --git a/internal/mcfunction/lexer/token.go b/internal/mcfunction/lexer/token.go new file mode 100644 index 0000000..859789f --- /dev/null +++ b/internal/mcfunction/lexer/token.go @@ -0,0 +1,46 @@ +package lexer + +type TokenKind uint8 + +const ( + TokenUnknown TokenKind = iota + TokenWhitespace + TokenNewline + TokenComment + TokenString + TokenUnterminatedString + TokenNumber + TokenRelativeNumber + TokenSelector + TokenMap + TokenUnterminatedMap + TokenJSON + TokenUnterminatedJSON + TokenEquals + TokenComma + TokenDot + TokenRange + TokenBang +) + +type Token struct { + Kind TokenKind + Start uint32 + End uint32 +} + +func (t Token) Text(input []rune) string { + return string(input[t.Start:t.End]) +} + +func (t Token) Range() (start, end uint32) { + return t.Start, t.End +} + +func (t Token) Len() uint32 { + return t.End - t.Start +} + +func (t Token) IsInside(pos uint32) bool { + return t.Start <= pos && pos < t.End +} diff --git a/internal/mcfunction/node.go b/internal/mcfunction/node.go new file mode 100644 index 0000000..378bbf1 --- /dev/null +++ b/internal/mcfunction/node.go @@ -0,0 +1,90 @@ +package mcfunction + +type NodeKind uint8 + +// file +// ├─ comment +// ├─ command +// │ ├─ command lit +// │ ├─ command arg +// ├─ invalid command +// │ ├─ command lit +// │ ├─ command arg + +const ( + NodeKindFile NodeKind = iota + NodeKindComment + NodeKindCommand + NodeKindInvalidCommand + NodeKindCommandLit + NodeKindCommandArg +) + +type Node struct { + kind NodeKind + parent INode + index int + children []INode + start uint32 + end uint32 +} + +func (n *Node) addChild(child INode) { + child.setParent(n) + child.setIndex(len(n.children)) + n.children = append(n.children, child) +} + +func (n *Node) setParent(parent INode) { + n.parent = parent +} + +func (n *Node) setIndex(index int) { + n.index = index +} + +func (n *Node) Kind() NodeKind { + return n.kind +} + +func (n *Node) Range() (start, end uint32) { + return n.start, n.end +} + +func (n *Node) Text(src []rune) string { + return string(src[n.start:n.end]) +} + +func (n *Node) PrevSibling() INode { + if n.parent == nil || n.index == 0 { + return nil + } + i := n.index - 1 + if i < 0 || i >= len(n.parent.Children()) { + return nil + } + return n.parent.Children()[i] +} + +func (n *Node) NextSibling() INode { + if n.parent == nil || n.index+1 >= len(n.parent.Children()) { + return nil + } + return n.parent.Children()[n.index+1] +} + +func (n *Node) Parent() INode { + return n.parent +} + +func (n *Node) Index() int { + return n.index +} + +func (n *Node) Children() []INode { + return n.children +} + +func (n *Node) IsInside(pos uint32) bool { + return n.start <= pos && pos < n.end +} diff --git a/internal/mcfunction/node_arg.go b/internal/mcfunction/node_arg.go new file mode 100644 index 0000000..e3b26e2 --- /dev/null +++ b/internal/mcfunction/node_arg.go @@ -0,0 +1,91 @@ +package mcfunction + +type NodeArg struct { + *Node + paramKind ParameterKind +} + +func (n *NodeArg) addChild(child INode) { + child.setParent(n) + child.setIndex(len(n.children)) + n.children = append(n.children, child) +} + +func (n *NodeArg) setParent(parent INode) { + n.parent = parent +} + +func (n *NodeArg) setIndex(index int) { + n.index = index +} + +func (n *NodeArg) Kind() NodeKind { + return NodeKindCommandArg +} + +func (n *NodeArg) Range() (start, end uint32) { + return n.start, n.end +} + +func (n *NodeArg) Text(src []rune) string { + return string(src[n.start:n.end]) +} + +func (n *NodeArg) PrevSibling() INode { + if n.parent == nil || n.index == 0 { + return nil + } + i := n.index - 1 + if i < 0 || i >= len(n.parent.Children()) { + return nil + } + return n.parent.Children()[i] +} + +func (n *NodeArg) NextSibling() INode { + if n.parent == nil { + return nil + } + i := n.index + 1 + if i < 0 || i >= len(n.parent.Children()) { + return nil + } + return n.parent.Children()[i] +} + +func (n *NodeArg) Parent() INode { + return n.parent +} + +func (n *NodeArg) Index() int { + return n.index +} + +func (n *NodeArg) Children() []INode { + return n.children +} + +func (n *NodeArg) ParamKind() ParameterKind { + return n.paramKind +} + +func (n *NodeArg) IsInside(pos uint32) bool { + return n.start <= pos && pos < n.end +} + +func (n *NodeArg) ParamSpec() (ParameterSpec, bool) { + commandNode, ok := n.parent.(INodeCommand) + if !ok { + return ParameterSpec{}, false + } + argIndex := n.index + return commandNode.ParamSpecAt(argIndex) +} + +func (n *NodeArg) CommandNode() INodeCommand { + commandNode, ok := n.parent.(INodeCommand) + if !ok { + return nil + } + return commandNode +} diff --git a/internal/mcfunction/node_arg_chain.go b/internal/mcfunction/node_arg_chain.go new file mode 100644 index 0000000..633a7e7 --- /dev/null +++ b/internal/mcfunction/node_arg_chain.go @@ -0,0 +1,124 @@ +package mcfunction + +type NodeArgCommand struct { + *NodeCommand + paramKind ParameterKind +} + +func (n *NodeArgCommand) addChild(child INode) { + child.setParent(n) + child.setIndex(len(n.children)) + n.children = append(n.children, child) +} + +func (n *NodeArgCommand) setParent(parent INode) { + n.parent = parent +} + +func (n *NodeArgCommand) setIndex(index int) { + n.index = index +} + +func (n *NodeArgCommand) Kind() NodeKind { + return NodeKindCommandArg +} + +func (n *NodeArgCommand) Range() (start, end uint32) { + return n.start, n.end +} + +func (n *NodeArgCommand) Text(src []rune) string { + return string(src[n.start:n.end]) +} + +func (n *NodeArgCommand) PrevSibling() INode { + if n.parent == nil || n.index == 0 { + return nil + } + i := n.index - 1 + if i < 0 || i >= len(n.parent.Children()) { + return nil + } + return n.parent.Children()[i] +} + +func (n *NodeArgCommand) NextSibling() INode { + if n.parent == nil { + return nil + } + i := n.index + 1 + if i < 0 || i >= len(n.parent.Children()) { + return nil + } + return n.parent.Children()[i] +} + +func (n *NodeArgCommand) Parent() INode { + return n.parent +} + +func (n *NodeArgCommand) Index() int { + return n.index +} + +func (n *NodeArgCommand) Children() []INode { + return n.children +} + +func (n *NodeArgCommand) ParamKind() ParameterKind { + return n.paramKind +} + +func (n *NodeArgCommand) ParamSpec() (ParameterSpec, bool) { + commandNode, ok := n.parent.(INodeCommand) + if !ok { + return ParameterSpec{}, false + } + argIndex := n.index + return commandNode.ParamSpecAt(argIndex) +} + +func (n *NodeArgCommand) IsInside(pos uint32) bool { + return n.start <= pos && pos < n.end +} + +func (n *NodeArgCommand) CommandName() string { + return n.name +} + +func (n *NodeArgCommand) Args() []INode { + return n.children +} + +func (n *NodeArgCommand) Spec() *Spec { + return n.spec +} + +func (n *NodeArgCommand) OverloadStates() []*overloadState { + return n.overloadStates +} + +func (n *NodeArgCommand) ParamSpecAt(index int) (ParameterSpec, bool) { + for _, o := range n.overloadStates { + if !o.matched { + continue + } + if index >= 0 && index < len(o.ov.Parameters) { + return o.ov.Parameters[index], true + } + } + return ParameterSpec{}, false +} + +func (n *NodeArgCommand) IsValid() bool { + for _, o := range n.overloadStates { + if o.matched { + return true + } + } + return false +} + +func (n *NodeArgCommand) CommandNode() INodeCommand { + return n +} diff --git a/internal/mcfunction/node_arg_map.go b/internal/mcfunction/node_arg_map.go new file mode 100644 index 0000000..4961f82 --- /dev/null +++ b/internal/mcfunction/node_arg_map.go @@ -0,0 +1,24 @@ +package mcfunction + +type nodeArgMap struct { + *NodeArg + mapSpec *MapSpec +} + +func (n *nodeArgMap) addChild(child INode) { + child.setParent(n) + child.setIndex(len(n.children)) + n.children = append(n.children, child) +} + +func (n *nodeArgMap) setParent(parent INode) { + n.parent = parent +} + +func (n *nodeArgMap) setIndex(index int) { + n.index = index +} + +func (n *nodeArgMap) MapSpec() *MapSpec { + return n.mapSpec +} diff --git a/internal/mcfunction/node_arg_pair.go b/internal/mcfunction/node_arg_pair.go new file mode 100644 index 0000000..72b14da --- /dev/null +++ b/internal/mcfunction/node_arg_pair.go @@ -0,0 +1,275 @@ +package mcfunction + +import ( + "github.com/rockide/language-server/internal/mcfunction/lexer" +) + +type PairKind uint8 + +const ( + PairKindUnknown PairKind = iota + PairKindKey + PairKindEqual + PairKindValue +) + +type NodeArgPair struct { + *NodeArg + keySpec *ParameterSpec + valueSpec *ParameterSpec +} + +func (n *NodeArgPair) addChild(child INode) { + child.setParent(n) + child.setIndex(len(n.children)) + n.children = append(n.children, child) +} + +func (n *NodeArgPair) setParent(parent INode) { + n.parent = parent +} + +func (n *NodeArgPair) setIndex(index int) { + n.index = index +} + +func (n *NodeArgPair) KeySpec() (ParameterSpec, bool) { + return *n.keySpec, n.keySpec != nil +} + +func (n *NodeArgPair) ValueSpec() (ParameterSpec, bool) { + return *n.valueSpec, n.valueSpec != nil +} + +type NodeArgPairChild struct { + *NodeArg + pairKind PairKind +} + +func (n *NodeArgPairChild) addChild(child INode) { + child.setParent(n) + child.setIndex(len(n.children)) + n.children = append(n.children, child) +} + +func (n *NodeArgPairChild) setParent(parent INode) { + n.parent = parent +} + +func (n *NodeArgPairChild) setIndex(index int) { + n.index = index +} + +func (n *NodeArgPairChild) PairKind() PairKind { + return n.pairKind +} + +func (n *NodeArgPairChild) KeySpec() (ParameterSpec, bool) { + parent, ok := n.parent.(*NodeArgPair) + if ok { + if parent.keySpec != nil { + return *parent.keySpec, true + } + } + return ParameterSpec{}, false +} + +func (n *NodeArgPairChild) ValueSpec() (ParameterSpec, bool) { + parent, ok := n.parent.(*NodeArgPair) + if ok { + if parent.valueSpec != nil { + return *parent.valueSpec, true + } + } + return ParameterSpec{}, false +} + +func (n *NodeArgPairChild) ParamSpec() (ParameterSpec, bool) { + switch n.pairKind { + case PairKindKey: + return n.KeySpec() + case PairKindValue: + return n.ValueSpec() + } + return ParameterSpec{}, false +} + +func (n *NodeArgPairChild) Keys() []string { + p, ok := n.parent.(*NodeArgPair) + if ok { + a, ok := p.parent.(INodeArgMap) + if ok { + return a.MapSpec().Keys() + } + } + return nil +} + +func createPairs(input []rune, token lexer.Token, spec *MapSpec) []*NodeArgPair { + value := []rune(token.Text(input)) + startOffset := token.Start + 1 + value = value[1 : len(value)-1] + lex := lexer.New(value) + keyTokens := []lexer.Token{} + var assignToken lexer.Token + valueTokens := []lexer.Token{} + createPair := func() *NodeArgPair { + start := assignToken.Start + startOffset + end := assignToken.End + startOffset + tKey, kOk := mergeTokens(keyTokens...) + var keyText string + if kOk { + start = tKey.Start + startOffset + if assignToken.Kind == lexer.TokenUnknown { + end = tKey.End + startOffset + } + } + tValue, vOk := mergeTokens(valueTokens...) + if vOk { + end = tValue.End + startOffset + } + node := &NodeArgPair{ + NodeArg: &NodeArg{ + Node: &Node{ + kind: NodeKindCommandArg, + start: start, + end: end, + }, + paramKind: ParameterKindMapPair, + }, + } + if kOk { + key := &NodeArgPairChild{ + NodeArg: &NodeArg{ + Node: &Node{ + kind: NodeKindCommandArg, + start: tKey.Start + startOffset, + end: tKey.End + startOffset, + }, + paramKind: ParameterKindMapPair, + }, + pairKind: PairKindKey, + } + node.addChild(key) + keyText = tKey.Text(value) + if spec != nil { + node.keySpec = spec.keySpec + if paramSpec, ok := spec.ValueSpec(keyText); ok { + node.valueSpec = paramSpec + } + } + } + if assignToken.Kind != lexer.TokenUnknown { + node.addChild(&NodeArgPairChild{ + NodeArg: &NodeArg{ + Node: &Node{ + kind: NodeKindCommandArg, + start: assignToken.Start + startOffset, + end: assignToken.End + startOffset, + }, + paramKind: ParameterKindMapPair, + }, + pairKind: PairKindEqual, + }) + } + if vOk { + first := valueTokens[0] + first.Start += startOffset + first.End += startOffset + if first.Kind == lexer.TokenMap || first.Kind == lexer.TokenJSON { + if node.valueSpec != nil { + pairs := createPairs(input, first, node.valueSpec.MapSpec) + mapNode := &nodeArgMap{ + NodeArg: &NodeArg{ + Node: &Node{ + kind: NodeKindCommandArg, + start: tValue.Start + startOffset, + end: tValue.End + startOffset, + }, + paramKind: node.valueSpec.Kind, + }, + mapSpec: node.valueSpec.MapSpec, + } + node.addChild(mapNode) + for _, p := range pairs { + mapNode.addChild(p) + } + } + } else { + node.addChild(&NodeArgPairChild{ + NodeArg: &NodeArg{ + Node: &Node{ + kind: NodeKindCommandArg, + start: tValue.Start + startOffset, + end: tValue.End + startOffset, + }, + paramKind: ParameterKindMapPair, + }, + pairKind: PairKindValue, + }) + } + } + keyTokens = []lexer.Token{} + valueTokens = []lexer.Token{} + assignToken = lexer.Token{} + return node + } + pairs := []*NodeArgPair{} + state := 0 + for t := range lex.Next() { + if t.Kind == lexer.TokenComment || t.Kind == lexer.TokenWhitespace { + continue + } + switch state { + case 0: + switch t.Kind { + case lexer.TokenEquals: + assignToken = t + state = 1 + case lexer.TokenComma: + continue + default: + keyTokens = append(keyTokens, t) + } + case 1: + switch t.Kind { + case lexer.TokenComma, lexer.TokenWhitespace: + state = 0 + pairs = append(pairs, createPair()) + case lexer.TokenMap, lexer.TokenJSON: + valueTokens = append(valueTokens, t) + if len(valueTokens) == 1 { + state = 0 + pairs = append(pairs, createPair()) + } + default: + valueTokens = append(valueTokens, t) + } + } + } + if assignToken.Kind != lexer.TokenUnknown || len(keyTokens) > 0 { + pairs = append(pairs, createPair()) + } + return pairs +} + +func mergeTokens(tokens ...lexer.Token) (lexer.Token, bool) { + if len(tokens) == 0 { + return lexer.Token{}, false + } + start := tokens[0].Start + end := tokens[0].End + for i := 1; i < len(tokens); i++ { + if tokens[i].Start < start { + start = tokens[i].Start + } + if tokens[i].End > end { + end = tokens[i].End + } + } + return lexer.Token{ + Kind: lexer.TokenString, + Start: start, + End: end, + }, true +} diff --git a/internal/mcfunction/node_command.go b/internal/mcfunction/node_command.go new file mode 100644 index 0000000..0db3f57 --- /dev/null +++ b/internal/mcfunction/node_command.go @@ -0,0 +1,69 @@ +package mcfunction + +type NodeCommand struct { + *Node + name string + spec *Spec + overloadStates []*overloadState +} + +func (n *NodeCommand) addChild(child INode) { + child.setParent(n) + child.setIndex(len(n.children)) + n.children = append(n.children, child) +} + +func (n *NodeCommand) setParent(parent INode) { + n.parent = parent +} + +func (n *NodeCommand) setIndex(index int) { + n.index = index +} + +func (n *NodeCommand) CommandName() string { + return n.name +} + +func (n *NodeCommand) Args() []INode { + if len(n.children) == 0 { + return nil + } + first := n.children[0] + if first.Kind() != NodeKindCommandLit { + return n.children + } + return n.children[1:] +} + +func (n *NodeCommand) Spec() *Spec { + return n.spec +} + +func (n *NodeCommand) OverloadStates() []*overloadState { + return n.overloadStates +} + +func (n *NodeCommand) ParamSpecAt(index int) (ParameterSpec, bool) { + for _, o := range n.overloadStates { + if !o.matched { + continue + } + if index >= 0 && index < len(o.ov.Parameters) { + return o.ov.Parameters[index], true + } + } + return ParameterSpec{}, false +} + +func (n *NodeCommand) IsValid() bool { + if n.Kind() == NodeKindInvalidCommand { + return false + } + for _, o := range n.overloadStates { + if o.matched { + return true + } + } + return false +} diff --git a/internal/mcfunction/nodes.go b/internal/mcfunction/nodes.go new file mode 100644 index 0000000..12d3dcc --- /dev/null +++ b/internal/mcfunction/nodes.go @@ -0,0 +1,51 @@ +package mcfunction + +type INode interface { + addChild(child INode) + setParent(parent INode) + setIndex(index int) + + Kind() NodeKind + Range() (start, end uint32) + Text([]rune) string + PrevSibling() INode + NextSibling() INode + Parent() INode + Index() int + Children() []INode + IsInside(pos uint32) bool +} + +type NodeParam interface { + ParamSpec() (ParameterSpec, bool) +} + +type INodeArg interface { + INode + NodeParam + ParamKind() ParameterKind + CommandNode() INodeCommand +} + +type INodeArgMap interface { + INodeArg + MapSpec() *MapSpec +} + +type INodeArgPairChild interface { + INodeArg + PairKind() PairKind + Keys() []string + KeySpec() (ParameterSpec, bool) + ValueSpec() (ParameterSpec, bool) +} + +type INodeCommand interface { + INode + CommandName() string + Args() []INode + Spec() *Spec + OverloadStates() []*overloadState + ParamSpecAt(index int) (ParameterSpec, bool) + IsValid() bool +} diff --git a/internal/mcfunction/overload_state.go b/internal/mcfunction/overload_state.go new file mode 100644 index 0000000..758611b --- /dev/null +++ b/internal/mcfunction/overload_state.go @@ -0,0 +1,380 @@ +package mcfunction + +import ( + "fmt" + "math" + "slices" + "strconv" + "strings" + + "github.com/rockide/language-server/internal/mcfunction/lexer" +) + +type overloadState struct { + spec *Spec + ov *SpecOverload + index int + matched bool // Indicates if any parameter has been matched or partially matched + options ParserOptions + commands map[string]*Spec + eol uint32 +} + +func (o *overloadState) Peek() (ParameterSpec, bool) { + if o.eof() { + return ParameterSpec{}, false + } + return o.ov.Parameters[o.index], true +} + +func (o *overloadState) Matched() bool { + return o.matched +} + +func (o *overloadState) Index() int { + return o.index +} + +func (o *overloadState) Parameters() []ParameterSpec { + return o.ov.Parameters +} + +func (o *overloadState) ParamAt(index int) (ParameterSpec, bool) { + if index < 0 || index >= len(o.ov.Parameters) { + return ParameterSpec{}, false + } + return o.ov.Parameters[index], true +} + +func (o *overloadState) eof() bool { + return o.index >= len(o.ov.Parameters) +} + +func (o *overloadState) advance() { + o.index++ +} + +func (o *overloadState) parse(input []rune, tokens []lexer.Token) ([]INodeArg, error) { + if len(tokens) > 0 && o.eof() { + return nil, fmt.Errorf("unexpected extra arguments") + } + if len(tokens) == 0 { + if param, ok := o.Peek(); !ok || param.Optional { + return nil, nil + } else if ok && !param.Optional { + return nil, fmt.Errorf("missing required arguments") + } + } + args := []INodeArg{} + tokenIndex := 0 + for tokenIndex < len(tokens) { + param, ok := o.Peek() + if !ok { + o.matched = false + return args, fmt.Errorf("excess arguments") + } + if param.Greedy { + for ; tokenIndex < len(tokens); tokenIndex++ { + arg, _, err := o.matchParameter(input, tokens, tokenIndex, param) + if err != nil { + break + } + args = append(args, arg) + o.matched = true + } + break + } + + arg, consumed, err := o.matchParameter(input, tokens, tokenIndex, param) + if err != nil { + o.matched = false + break + } + args = append(args, arg) + o.advance() + tokenIndex += consumed + } + if !o.matched { + return args, fmt.Errorf("no overload matched") + } + return args, nil +} + +func (o *overloadState) matchParameter(input []rune, tokens []lexer.Token, tokenIndex int, param ParameterSpec) (INodeArg, int, error) { + token := tokens[tokenIndex] + text := token.Text(input) + arg := &NodeArg{ + Node: &Node{ + kind: NodeKindCommandArg, + start: token.Start, + end: token.End, + }, + paramKind: param.Kind, + } + switch param.Kind { + case ParameterKindLiteral: + if slices.Contains(param.Literals, token.Text(input)) { + return arg, 1, nil + } + case ParameterKindString: + return arg, 1, nil + case ParameterKindNumber: + if token.Kind == lexer.TokenNumber { + return arg, 1, nil + } + case ParameterKindInteger: + if token.Kind == lexer.TokenNumber { + // Strictly integer check, not allowing decimal point + if !strings.Contains(text, ".") { + return arg, 1, nil + } + } + case ParameterKindBoolean: + if text == "true" || text == "false" { + return arg, 1, nil + } + case ParameterKindSelector: + if token.Kind == lexer.TokenSelector { + selector := text[1:] // remove '@' + validSelectors := getSelectors(o.options) + if _, ok := validSelectors[selector]; ok { + advance := 1 + // Check for selector arguments + if tokenIndex+1 < len(tokens) && tokens[tokenIndex+1].Kind == lexer.TokenMap { + next := tokens[tokenIndex+1] + advance = 2 + selArg := &nodeArgMap{ + NodeArg: &NodeArg{ + Node: &Node{ + kind: NodeKindCommandArg, + start: next.Start, + end: next.End, + }, + paramKind: ParameterKindSelectorArg, + }, + mapSpec: SelectorArg, + } + pairs := createPairs(input, next, SelectorArg) + if len(pairs) > 0 { + for _, p := range pairs { + selArg.addChild(p) + } + } + arg.addChild(selArg) + arg.Node.end = tokens[tokenIndex+1].End + } + return arg, advance, nil + } + } + case ParameterKindMap: + if token.Kind == lexer.TokenMap { + mapArg := &nodeArgMap{ + NodeArg: arg, + mapSpec: param.MapSpec, + } + pairs := createPairs(input, token, param.MapSpec) + if len(pairs) > 0 { + for _, p := range pairs { + mapArg.addChild(p) + } + } + return mapArg, 1, nil + } + case ParameterKindJSON: + if token.Kind == lexer.TokenJSON { + return arg, 1, nil + } + case ParameterKindVector2, ParameterKindVector3: + size := 2 + if param.Kind == ParameterKindVector3 { + size = 3 + } + if tokenIndex+size-1 < len(tokens) { + if isValidRelatives(input, tokens[tokenIndex:tokenIndex+size]...) { + for i := range make([]int, size) { + arg.addChild(&NodeArg{ + Node: &Node{ + kind: NodeKindCommandArg, + start: tokens[tokenIndex+i].Start, + end: tokens[tokenIndex+i].End, + }, + paramKind: ParameterKindRelativeNumber, + }) + } + arg.Node.end = tokens[tokenIndex+size-1].End + return arg, size, nil + } + } + case ParameterKindRange: + // 1. Number, Range, Number + if matchTokens(tokens, tokenIndex, lexer.TokenNumber, lexer.TokenRange, lexer.TokenNumber) { + arg.Node.end = tokens[tokenIndex+2].End + return arg, 3, nil + } + // 2. Range, Number + if matchTokens(tokens, tokenIndex, lexer.TokenRange, lexer.TokenNumber) { + arg.Node.end = tokens[tokenIndex+1].End + return arg, 2, nil + } + // 3. Number, Range + if matchTokens(tokens, tokenIndex, lexer.TokenNumber, lexer.TokenRange) { + arg.Node.end = tokens[tokenIndex+1].End + return arg, 2, nil + } + // 4. Bang, Number, Range, Number + if matchTokens(tokens, tokenIndex, lexer.TokenBang, lexer.TokenNumber, lexer.TokenRange, lexer.TokenNumber) { + arg.Node.start = tokens[tokenIndex].Start + arg.Node.end = tokens[tokenIndex+3].End + return arg, 4, nil + } + // 5. Bang, Range, Number + if matchTokens(tokens, tokenIndex, lexer.TokenBang, lexer.TokenRange, lexer.TokenNumber) { + arg.Node.start = tokens[tokenIndex].Start + arg.Node.end = tokens[tokenIndex+2].End + return arg, 3, nil + } + // 6. Bang, Number, Range + if matchTokens(tokens, tokenIndex, lexer.TokenBang, lexer.TokenNumber, lexer.TokenRange) { + arg.Node.start = tokens[tokenIndex].Start + arg.Node.end = tokens[tokenIndex+2].End + return arg, 3, nil + } + case ParameterKindSuffixedInteger: + if token.Kind == lexer.TokenNumber && !strings.Contains(text, ".") && tokenIndex+1 < len(tokens) { + suffixToken := tokens[tokenIndex+1] + suffix := param.Suffix + suffixText := suffixToken.Text(input) + if suffixText == suffix { + arg.Node.end = suffixToken.End + return arg, 2, nil + } + } + case ParameterKindWildcardInteger: + _, err := strconv.Atoi(text) + if token.Text(input) == "*" || (err == nil && !strings.Contains(text, ".")) { + return arg, 1, nil + } + case ParameterKindChainedCommand: + arg := &NodeArgCommand{ + NodeCommand: &NodeCommand{ + Node: &Node{ + kind: NodeKindCommandArg, + start: token.Start, + end: o.eol, + }, + name: o.spec.Name, + spec: o.spec, + }, + paramKind: ParameterKindChainedCommand, + } + rest := tokens[tokenIndex:] + if len(rest) == 0 { + return arg, 1, nil + } + overloadStates := make([]*overloadState, 0, len(o.spec.Overloads)) + for i := range o.spec.Overloads { + state := &overloadState{ + spec: o.spec, + ov: &o.spec.Overloads[i], + options: o.options, + commands: o.commands, + matched: true, + eol: o.eol, + } + overloadStates = append(overloadStates, state) + args, _ := state.parse(input, rest) + if state.matched { + arg.children = make([]INode, 0, len(args)) + for _, a := range args { + arg.addChild(a) + } + } + } + if len(arg.children) == 0 { + for i := range rest { + arg.addChild(&NodeArg{ + Node: &Node{ + kind: NodeKindCommandArg, + start: rest[i].Start, + end: rest[i].End, + }, + }) + } + } + arg.overloadStates = overloadStates + return arg, math.MaxInt32, nil + case ParameterKindCommand: + rest := tokens[tokenIndex:] + commandNode := parseCommand(rest, input, o.commands, o.options, o.eol) + arg := &NodeArgCommand{ + NodeCommand: commandNode, + paramKind: ParameterKindCommand, + } + return arg, math.MaxInt32, nil + case ParameterKindRawMessage, ParameterKindItemNbt: + if token.Kind == lexer.TokenJSON { + return arg, 1, nil + } + case ParameterKindRelativeNumber: + if token.Kind == lexer.TokenRelativeNumber || token.Kind == lexer.TokenNumber { + return arg, 1, nil + } + } + return nil, 0, fmt.Errorf("parameter did not match") +} + +func isValidRelatives(input []rune, tokens ...lexer.Token) bool { + var b byte + for _, token := range tokens { + if token.Kind != lexer.TokenRelativeNumber && token.Kind != lexer.TokenNumber { + return false + } + if f := token.Text(input)[0]; f == '~' || f == '^' { + if b == 0 { + b = f + } else if b != f { + return false + } + } + } + return true +} + +func getSelectors(options ParserOptions) map[string]bool { + res := map[string]bool{ + "p": true, + "a": true, + "r": true, + "s": true, + "e": true, + "n": true, + "initiator": true, + "c": true, + "v": true, + } + for sel := range res { + if sel == "initiator" && !options.InitiatorSelector { + res[sel] = false + continue + } + if sel == "c" || sel == "v" { + if !options.EducationMode { + res[sel] = false + continue + } + } + } + return res +} + +func matchTokens(tokens []lexer.Token, index int, kinds ...lexer.TokenKind) bool { + if index+len(kinds) > len(tokens) { + return false + } + for i, kind := range kinds { + if tokens[index+i].Kind != kind { + return false + } + } + return true +} diff --git a/internal/mcfunction/parser.go b/internal/mcfunction/parser.go new file mode 100644 index 0000000..681f1d1 --- /dev/null +++ b/internal/mcfunction/parser.go @@ -0,0 +1,159 @@ +package mcfunction + +import ( + "fmt" + + "github.com/rockide/language-server/internal/mcfunction/lexer" +) + +type Parser struct { + lexer *lexer.Lexer + commands map[string]*Spec + options ParserOptions +} + +type ParserOptions struct { + InitiatorSelector bool // enables @initiator selector + EducationMode bool // enables education edition specific commands and arguments +} + +func NewParser(options ParserOptions, commands ...*Spec) *Parser { + return &Parser{ + lexer: lexer.New([]rune{}), + commands: make(map[string]*Spec), + options: options, + } +} + +func (p *Parser) RegisterCommands(specs ...*Spec) { + for _, spec := range specs { + p.commands[spec.Name] = spec + for _, alias := range spec.Aliases { + p.commands[alias] = spec + } + } +} + +func (p *Parser) RegisteredCommands() map[string]*Spec { + return p.commands +} + +func (p *Parser) GetSelectors() map[string]bool { + return getSelectors(p.options) +} + +func (p *Parser) Parse(input []rune) (INode, error) { + if len(p.commands) == 0 { + return nil, fmt.Errorf("no commands registered") + } + p.lexer.Reset(input) + root := &Node{} + tokens := []lexer.Token{} + eol := uint32(0) + parse := func() { + if len(tokens) == 0 { + return + } + node := parseCommand(tokens, input, p.commands, p.options, eol) + node.end = eol + root.addChild(node) + } + for token := range p.lexer.Next() { + eol = token.End + switch token.Kind { + case lexer.TokenWhitespace: + continue + case lexer.TokenComment: + root.addChild(&Node{ + kind: NodeKindComment, + start: token.Start, + end: token.End, + }) + case lexer.TokenNewline: + parse() + tokens = []lexer.Token{} + default: + tokens = append(tokens, token) + } + } + parse() + root.end = uint32(len(input)) + return root, nil +} + +func parseCommand(tokens []lexer.Token, input []rune, commands map[string]*Spec, options ParserOptions, eol uint32) *NodeCommand { + first := tokens[0] + commandInput := first.Text(input) + spec, ok := commands[commandInput] + node := &NodeCommand{ + Node: &Node{ + kind: NodeKindInvalidCommand, + start: first.Start, + end: eol, + }, + } + addDefaultArgs := func() { + for i := 1; i < len(tokens); i++ { + node.addChild(&NodeArg{ + Node: &Node{ + kind: NodeKindCommandArg, + start: tokens[i].Start, + end: tokens[i].End, + }, + }) + } + } + node.addChild(&Node{ + kind: NodeKindCommandLit, + start: first.Start, + end: first.End, + }) + if !ok { + node.name = commandInput + addDefaultArgs() + return node + } + if len(spec.Overloads) == 0 && len(tokens) > 1 { + // Immediately invalidate if no overloads exist but arguments are provided + node.name = commandInput + node.spec = spec + addDefaultArgs() + return node + } + if len(spec.Overloads) == 0 && len(tokens) == 1 { + node.kind = NodeKindCommand + node.name = commandInput + node.spec = spec + return node + } + overloadStates := make([]*overloadState, len(spec.Overloads)) + for i := range spec.Overloads { + state := &overloadState{ + spec: spec, + ov: &spec.Overloads[i], + options: options, + commands: commands, + matched: true, + eol: eol, + } + overloadStates[i] = state + args, _ := state.parse(input, tokens[1:]) + if state.matched { + node.kind = NodeKindCommand + node.name = commandInput + node.spec = spec + node.children = make([]INode, 0, len(args)) + for _, arg := range args { + node.addChild(arg) + } + } + } + if node.kind == NodeKindInvalidCommand { + node.name = commandInput + node.spec = spec + addDefaultArgs() + } else { + node.overloadStates = overloadStates + } + return node +} diff --git a/internal/mcfunction/selector_arg.go b/internal/mcfunction/selector_arg.go new file mode 100644 index 0000000..6e8b779 --- /dev/null +++ b/internal/mcfunction/selector_arg.go @@ -0,0 +1,159 @@ +package mcfunction + +var permissionValueSpec = &ParameterSpec{ + Kind: ParameterKindLiteral, + Literals: []string{ + "enabled", + "disabled", + }, +} + +var SelectorArg = NewMapSpec(map[string]*ParameterSpec{ + "c": { + Kind: ParameterKindInteger, + }, + "dx": { + Kind: ParameterKindRelativeNumber, + }, + "dy": { + Kind: ParameterKindRelativeNumber, + }, + "dz": { + Kind: ParameterKindRelativeNumber, + }, + "family": { + Kind: ParameterKindString, + Tags: []string{TagTypeFamilyId}, + }, + "has_property": { + Kind: ParameterKindMapJSON, + MapSpec: NewMapValueSpec(nil, &ParameterSpec{ + Kind: ParameterKindBoolean, + }), + }, + "hasitem": { + Kind: ParameterKindMapJSON, + MapSpec: NewMapSpec(map[string]*ParameterSpec{ + "data": { + Kind: ParameterKindInteger, + }, + "item": { + Kind: ParameterKindString, + Tags: []string{TagItemId}, + }, + "location": { + Kind: ParameterKindLiteral, + Literals: []string{ + "slot.armor", + "slot.armor.body", + "slot.armor.chest", + "slot.armor.feet", + "slot.armor.head", + "slot.armor.legs", + "slot.chest", + "slot.enderchest", + "slot.equippable", + "slot.hotbar", + "slot.inventory", + "slot.saddle", + "slot.weapon.mainhand", + "slot.weapon.offhand", + }, + }, + "quantity": { + Kind: ParameterKindRange, + }, + "slot": { + Kind: ParameterKindRange, + }, + }), + }, + "haspermission": { + Kind: ParameterKindMapJSON, + MapSpec: NewMapSpec(map[string]*ParameterSpec{ + "camera": permissionValueSpec, + "dismount": permissionValueSpec, + "jump": permissionValueSpec, + "lateral_movement": permissionValueSpec, + "mount": permissionValueSpec, + "move_backward": permissionValueSpec, + "move_forward": permissionValueSpec, + "move_left": permissionValueSpec, + "move_right": permissionValueSpec, + "movement": permissionValueSpec, + "sneak": permissionValueSpec, + }), + }, + "l": { + Kind: ParameterKindInteger, + }, + "lm": { + Kind: ParameterKindInteger, + }, + "m": { + Kind: ParameterKindLiteral, + Literals: []string{ + "a", + "adventure", + "c", + "creative", + "d", + "default", + "s", + "spectator", + "survival", + "!a", + "!adventure", + "!c", + "!creative", + "!d", + "!default", + "!s", + "!spectator", + "!survival", + }, + }, + "name": { + Kind: ParameterKindString, + }, + "r": { + Kind: ParameterKindNumber, + }, + "rm": { + Kind: ParameterKindNumber, + }, + "rx": { + Kind: ParameterKindRelativeNumber, + }, + "rxm": { + Kind: ParameterKindRelativeNumber, + }, + "ry": { + Kind: ParameterKindRelativeNumber, + }, + "rym": { + Kind: ParameterKindRelativeNumber, + }, + "scores": { + Kind: ParameterKindMapJSON, + MapSpec: NewMapValueSpec(nil, &ParameterSpec{ + Kind: ParameterKindRange, + }), + }, + "tag": { + Kind: ParameterKindString, + }, + "type": { + Kind: ParameterKindString, + Tags: []string{TagEntityId}, + }, + "x": { + Kind: ParameterKindRelativeNumber, + }, + "y": { + Kind: ParameterKindRelativeNumber, + }, + "z": { + Kind: ParameterKindRelativeNumber, + }, +}) diff --git a/internal/mcfunction/spec.go b/internal/mcfunction/spec.go new file mode 100644 index 0000000..0303893 --- /dev/null +++ b/internal/mcfunction/spec.go @@ -0,0 +1,161 @@ +package mcfunction + +type Spec struct { + Name string + Aliases []string + Description string + Overloads []SpecOverload +} + +type SpecOverload struct { + Parameters []ParameterSpec +} + +type ParameterKind int8 + +const ( + ParameterKindUnknown ParameterKind = iota + ParameterKindLiteral // fixed set of string literals + ParameterKindString // arbitrary string + ParameterKindNumber // allows float + ParameterKindInteger // strictly integer + ParameterKindBoolean // true or false + ParameterKindSelector // @p, @a, @r, @s, @e, @n, @initiator + ParameterKindSelectorArg // selector arguments + ParameterKindMap // [key=value,...] + ParameterKindMapJSON // Just a map but with { } wrapping, {key=value,...} + ParameterKindJSON // JSON object or array + ParameterKindVector2 // x y or rotX rotY + ParameterKindVector3 // x y z + // Misc + ParameterKindRange // start..end + ParameterKindSuffixedInteger // int with suffix like 10L, 10D, 10S, 10T. + ParameterKindWildcardInteger // * or number + ParameterKindChainedCommand // chained command + ParameterKindCommand // commands + ParameterKindRawMessage + ParameterKindItemNbt // item NBT data + ParameterKindRelativeNumber // ~number or ^number (part of vector) + ParameterKindMapPair // key=value (only as part of map) +) + +type Tag string + +const ( + TagAimAssistId = "aim_assist_id" + TagBiomeId = "biome_id" + TagBlockId = "block_id" + TagBlockState = "block_state" + TagCameraId = "camera_id" + TagClientAnimationId = "client_animation_id" + TagDialogueId = "dialogue_id" + TagDimensionId = "dimension_id" + TagEntityEvent = "entity_event" + TagEntityId = "entity_id" + TagExecuteChain = "execute_chain" + TagTypeFamilyId = "type_family_id" + TagFeatureId = "feature_id" + TagFeatureRuleId = "feature_rule_id" + TagFogId = "fog_id" + TagFunctionFile = "function_file" + TagItemId = "item_id" + TagJigsawId = "jigsaw_id" + TagJigsawTemplatePoolId = "jigsaw_template_pool_id" + TagLootTableFile = "loot_table_file" + TagMolang = "molang" + TagMusicId = "music_id" + TagParticleId = "particle_id" + TagPitch = "pitch" + TagProvidedFogId = "provided_fog_id" + TagRecipeId = "recipe_id" + TagScoreboardObjectiveId = "scoreboard_objective_id" + TagScriptEventId = "script_event_id" + TagSoundId = "sound_definition_id" + TagStructureFile = "structure_file" + TagTagId = "tag" + TagTickingAreaId = "ticking_area_id" + TagYaw = "yaw" +) + +type ParameterSpec struct { + Kind ParameterKind + Name string + Optional bool + Literals []string // only for ParameterKindLiteral + Range *NumberRange // For number, integer, and range + Tags []string + Greedy bool // only for KindString + Suffix string // only for KindSuffixedInteger + MapSpec *MapSpec // only for KindMap and KindMapJSON +} + +func (p ParameterSpec) ToString() string { + s := p.Name + if len(p.Literals) == 1 && p.Kind == ParameterKindLiteral { + if !p.Optional { + return p.Literals[0] + } + s = p.Literals[0] + } + if p.Optional { + s = "[" + s + "]" + } else { + s = "<" + s + ">" + } + if p.Kind == ParameterKindSuffixedInteger && p.Suffix != "" { + s += p.Suffix + } + return s +} + +type NumberRange struct { + Min float64 + Max float64 +} + +type MapSpec struct { + mapSpec map[string]*ParameterSpec + keySpec *ParameterSpec + spec *ParameterSpec +} + +func NewMapSpec(spec map[string]*ParameterSpec) *MapSpec { + return &MapSpec{ + mapSpec: spec, + } +} + +func NewMapValueSpec(key *ParameterSpec, value *ParameterSpec) *MapSpec { + return &MapSpec{ + keySpec: key, + spec: value, + } +} + +func (m *MapSpec) KeySpec() (*ParameterSpec, bool) { + if m.keySpec != nil { + return m.keySpec, true + } + return nil, false +} + +func (m *MapSpec) ValueSpec(key string) (*ParameterSpec, bool) { + if m.mapSpec != nil { + s, ok := m.mapSpec[key] + return s, ok + } + return m.spec, m.spec != nil +} + +func (m *MapSpec) Keys() []string { + if m.mapSpec != nil { + keys := make([]string, len(m.mapSpec)) + i := 0 + for k := range m.mapSpec { + keys[i] = k + i++ + } + return keys + } + return []string{} +} diff --git a/internal/mcfunction/util.go b/internal/mcfunction/util.go new file mode 100644 index 0000000..7e93a64 --- /dev/null +++ b/internal/mcfunction/util.go @@ -0,0 +1,27 @@ +package mcfunction + +func WalkNodeTree(root INode, fn func(INode) bool) { + if !fn(root) { + return + } + for _, child := range root.Children() { + WalkNodeTree(child, fn) + } +} + +func IsInside(n INode, pos uint32) bool { + start, end := n.Range() + return pos >= start && pos <= end +} + +func NodeAt(root INode, pos uint32) INode { + var result INode + WalkNodeTree(root, func(n INode) bool { + matched := IsInside(n, pos) + if matched { + result = n + } + return true + }) + return result +} diff --git a/stores/path.go b/stores/path.go index 16ef0e5..e15a577 100644 --- a/stores/path.go +++ b/stores/path.go @@ -58,6 +58,7 @@ func (s *PathStore) Delete(uri protocol.DocumentURI) { var ( LootTablePath = NewPathStore(vanilla.LootTable) + McFunctionPath = NewPathStore(nil, ".mcfunction") StructurePath = NewPathStore(nil, ".mcstructure") TradeTablePath = NewPathStore(vanilla.TradeTable) SoundPath = NewPathStore(vanilla.SoundPath, ".fsb", ".ogg", ".wav") diff --git a/stores/symbol.go b/stores/symbol.go index 29fdfc7..e25e2b7 100644 --- a/stores/symbol.go +++ b/stores/symbol.go @@ -100,10 +100,16 @@ var ( EntityEvent = NewSymbolBinding(nil) EntityFamily = NewSymbolBinding(vanilla.TypeFamily) FeatureId = NewSymbolBinding(vanilla.FeatureId) + FeatureRuleId = NewSymbolBinding(nil) ItemCustomComponent = NewSymbolBinding(nil) ItemId = NewSymbolBinding(vanilla.ItemId) // Blocks are contained within the "block" scope ItemTag = NewSymbolBinding(vanilla.ItemTag) + ProvidedFogId = NewSymbolBinding(nil) + RecipeId = NewSymbolBinding(vanilla.RecipeId) RecipeTag = NewSymbolBinding(vanilla.RecipeTag) + ScoreboardObjective = NewSymbolBinding(nil) + Tag = NewSymbolBinding(nil) + TickingArea = NewSymbolBinding(nil) WorldgenProcessor = NewSymbolBinding(vanilla.WorldgenProcessorId) WorldgenTemplatePool = NewSymbolBinding(vanilla.WorldgenTemplatePoolId) WorldgenJigsaw = NewSymbolBinding(nil)