unit tests, wip command parsing

This commit is contained in:
Bixilon 2022-05-18 12:33:48 +02:00
parent 7231ae703e
commit 8087e5c9d9
No known key found for this signature in database
GPG Key ID: 5CAD791931B09AC4
34 changed files with 1084 additions and 1 deletions

View File

@ -48,7 +48,7 @@ Minosoft is an open source minecraft client, written from scratch in kotlin (and
- GUI (inventory, menus)
- block entities (e.g. signs, chests)
- basic entity rendering (hitboxes)
- ~~original physics~
- ~~original physics~~
![Rendering](doc/img/rendering5.png)
A world, with a ton of hud features exposed

View File

@ -499,5 +499,11 @@
<artifactId>fastutil-core</artifactId>
<version>8.5.8</version>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>5.8.2</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,22 @@
/*
* Minosoft
* Copyright (C) 2020-2022 Moritz Zwerger
*
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
*
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
*/
package de.bixilon.minosoft.commands.errors
import de.bixilon.minosoft.commands.util.CommandReader
abstract class ReaderError(
val reader: CommandReader,
val start: Int,
val end: Int,
) : Exception("Error at $start-$end: ${reader.string}")

View File

@ -0,0 +1,20 @@
/*
* Minosoft
* Copyright (C) 2020-2022 Moritz Zwerger
*
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
*
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
*/
package de.bixilon.minosoft.commands.errors.parser
import de.bixilon.minosoft.commands.errors.ReaderError
import de.bixilon.minosoft.commands.util.CommandReader
import de.bixilon.minosoft.commands.util.ReadResult
abstract class ParserError(reader: CommandReader, val result: ReadResult<*>) : ReaderError(reader, result.start, result.end)

View File

@ -0,0 +1,24 @@
/*
* Minosoft
* Copyright (C) 2020-2022 Moritz Zwerger
*
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
*
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
*/
package de.bixilon.minosoft.commands.errors.reader
import de.bixilon.minosoft.commands.errors.ReaderError
import de.bixilon.minosoft.commands.util.CommandReader
class InvalidPeekError(
reader: CommandReader,
pointer: Int,
val found: Int,
val required: IntArray,
) : ReaderError(reader, pointer, pointer + 1)

View File

@ -0,0 +1,24 @@
/*
* Minosoft
* Copyright (C) 2020-2022 Moritz Zwerger
*
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
*
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
*/
package de.bixilon.minosoft.commands.errors.reader
import de.bixilon.minosoft.commands.errors.ReaderError
import de.bixilon.minosoft.commands.util.CommandReader
class InvalidReadError(
reader: CommandReader,
pointer: Int,
val found: Int,
val required: IntArray,
) : ReaderError(reader, pointer, pointer + 1)

View File

@ -0,0 +1,22 @@
/*
* Minosoft
* Copyright (C) 2020-2022 Moritz Zwerger
*
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
*
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
*/
package de.bixilon.minosoft.commands.errors.reader
import de.bixilon.minosoft.commands.errors.ReaderError
import de.bixilon.minosoft.commands.util.CommandReader
class OutOfBoundsError(
reader: CommandReader,
start: Int,
) : ReaderError(reader, start, reader.length)

View File

@ -0,0 +1,24 @@
/*
* Minosoft
* Copyright (C) 2020-2022 Moritz Zwerger
*
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
*
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
*/
package de.bixilon.minosoft.commands.errors.reader
import de.bixilon.minosoft.commands.errors.ReaderError
import de.bixilon.minosoft.commands.util.CommandReader
class UnexpectedBackslashError(
reader: CommandReader,
start: Int,
end: Int,
val read: Int,
) : ReaderError(reader, start, end)

View File

@ -0,0 +1,22 @@
/*
* Minosoft
* Copyright (C) 2020-2022 Moritz Zwerger
*
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
*
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
*/
package de.bixilon.minosoft.commands.errors.reader
import de.bixilon.minosoft.commands.errors.ReaderError
import de.bixilon.minosoft.commands.util.CommandReader
class UnfinishedQuotedStringError(
reader: CommandReader,
start: Int,
) : ReaderError(reader, start, reader.length)

View File

@ -0,0 +1,23 @@
/*
* Minosoft
* Copyright (C) 2020-2022 Moritz Zwerger
*
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
*
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
*/
package de.bixilon.minosoft.commands.errors.suggestion
import de.bixilon.minosoft.commands.errors.parser.ParserError
import de.bixilon.minosoft.commands.util.CommandReader
import de.bixilon.minosoft.commands.util.ReadResult
class NoSuggestionError(
reader: CommandReader,
result: ReadResult<*>,
) : ParserError(reader, result)

View File

@ -0,0 +1,38 @@
/*
* Minosoft
* Copyright (C) 2020-2022 Moritz Zwerger
*
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
*
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
*/
package de.bixilon.minosoft.commands.nodes
import de.bixilon.minosoft.commands.parser.ArgumentParser
import de.bixilon.minosoft.commands.stack.CommandExecutor
import de.bixilon.minosoft.commands.suggestion.types.SuggestionType
class ArgumentNode : ExecutableNode {
private val parser: ArgumentParser<*>
constructor(
name: String,
parser: ArgumentParser<*>,
suggestion: SuggestionType<*>? = null,
executable: Boolean = false,
redirect: CommandNode? = null,
) : super(name, suggestion, false, null, executable, redirect) {
this.parser = parser
}
constructor(name: String, parser: ArgumentParser<*>, onlyDirectExecution: Boolean = true, executor: CommandExecutor) : super(name, executable = true, onlyDirectExecution = onlyDirectExecution, executor = executor) {
this.executor = executor
this.parser = parser
}
}

View File

@ -0,0 +1,19 @@
/*
* Minosoft
* Copyright (C) 2020-2022 Moritz Zwerger
*
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
*
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
*/
package de.bixilon.minosoft.commands.nodes
abstract class CommandNode(
val executable: Boolean,
val redirect: CommandNode?,
)

View File

@ -0,0 +1,26 @@
/*
* Minosoft
* Copyright (C) 2020-2022 Moritz Zwerger
*
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
*
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
*/
package de.bixilon.minosoft.commands.nodes
import de.bixilon.minosoft.commands.stack.CommandExecutor
import de.bixilon.minosoft.commands.suggestion.types.SuggestionType
abstract class ExecutableNode(
val name: String,
val suggestion: SuggestionType<*>? = null,
var onlyDirectExecution: Boolean = true,
var executor: CommandExecutor? = null,
executable: Boolean = executor != null,
redirect: CommandNode? = null,
) : CommandNode(executable, redirect)

View File

@ -0,0 +1,30 @@
/*
* Minosoft
* Copyright (C) 2020-2022 Moritz Zwerger
*
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
*
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
*/
package de.bixilon.minosoft.commands.nodes
import de.bixilon.minosoft.commands.stack.CommandExecutor
import de.bixilon.minosoft.commands.suggestion.types.SuggestionType
class LiteralNode : ExecutableNode {
constructor(
name: String,
suggestion: SuggestionType<*>? = null,
executable: Boolean = false,
redirect: CommandNode? = null,
) : super(name, suggestion, false, null, executable, redirect)
constructor(name: String, onlyDirectExecution: Boolean = true, executor: CommandExecutor) : super(name, onlyDirectExecution = onlyDirectExecution, executor = executor, executable = true)
}

View File

@ -0,0 +1,23 @@
/*
* Minosoft
* Copyright (C) 2020-2022 Moritz Zwerger
*
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
*
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
*/
package de.bixilon.minosoft.commands.nodes
import de.bixilon.minosoft.commands.suggestion.types.SuggestionType
abstract class NamedNode(
val name: String,
val suggestion: SuggestionType<*>?,
executable: Boolean,
redirect: CommandNode?,
) : CommandNode(executable, redirect)

View File

@ -0,0 +1,16 @@
/*
* Minosoft
* Copyright (C) 2020-2022 Moritz Zwerger
*
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
*
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
*/
package de.bixilon.minosoft.commands.nodes
class RootNode : CommandNode(false, null)

View File

@ -0,0 +1,28 @@
/*
* Minosoft
* Copyright (C) 2020-2022 Moritz Zwerger
*
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
*
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
*/
package de.bixilon.minosoft.commands.parser
import de.bixilon.minosoft.commands.util.CommandReader
import de.bixilon.minosoft.data.text.ChatComponent
import de.bixilon.minosoft.protocol.protocol.PlayInByteBuffer
interface ArgumentParser<T> {
val examples: List<T>
val placeholder: ChatComponent
fun parse(reader: CommandReader): T
fun getSuggestions(reader: CommandReader): List<T>
fun read(buffer: PlayInByteBuffer) = Unit
}

View File

@ -0,0 +1,18 @@
/*
* Minosoft
* Copyright (C) 2020-2022 Moritz Zwerger
*
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
*
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
*/
package de.bixilon.minosoft.commands.parser.brigadier
import de.bixilon.minosoft.commands.parser.ArgumentParser
interface BrigadierParser<T> : ArgumentParser<T>

View File

@ -0,0 +1,23 @@
/*
* Minosoft
* Copyright (C) 2020-2022 Moritz Zwerger
*
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
*
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
*/
package de.bixilon.minosoft.commands.parser.brigadier.bool
import de.bixilon.minosoft.commands.errors.parser.ParserError
import de.bixilon.minosoft.commands.util.CommandReader
import de.bixilon.minosoft.commands.util.ReadResult
class BooleanParseError(
reader: CommandReader,
result: ReadResult<Boolean?>,
) : ParserError(reader, result)

View File

@ -0,0 +1,53 @@
/*
* Minosoft
* Copyright (C) 2020-2022 Moritz Zwerger
*
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
*
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
*/
package de.bixilon.minosoft.commands.parser.brigadier.bool
import de.bixilon.minosoft.commands.errors.suggestion.NoSuggestionError
import de.bixilon.minosoft.commands.parser.brigadier.BrigadierParser
import de.bixilon.minosoft.commands.parser.factory.ArgumentFactory
import de.bixilon.minosoft.commands.suggestion.ArraySuggestion
import de.bixilon.minosoft.commands.util.CommandReader
import de.bixilon.minosoft.data.registries.ResourceLocation
import de.bixilon.minosoft.data.text.ChatComponent
import de.bixilon.minosoft.protocol.network.connection.play.PlayConnection
import de.bixilon.minosoft.util.KUtil.toResourceLocation
object BooleanParser : BrigadierParser<Boolean>, ArgumentFactory<BooleanParser> {
override val RESOURCE_LOCATION: ResourceLocation = "brigadier:bool".toResourceLocation()
override val examples: List<Boolean> = listOf(true, false)
private val suggestion = ArraySuggestion(examples)
override val placeholder = ChatComponent.of("<boolean>")
override fun parse(reader: CommandReader): Boolean {
reader.readResult { reader.readBoolean() }.let { return it.result ?: throw BooleanParseError(reader, it) }
}
fun CommandReader.readBoolean(): Boolean? {
return when (readUnquotedString()) {
"true" -> true
"false" -> false
else -> null
}
}
override fun getSuggestions(reader: CommandReader): List<Boolean> {
val text = reader.readResult { reader.readUnquotedString() }
if (text.result == null) {
return examples
}
return suggestion.suggest(text.result) ?: throw NoSuggestionError(reader, text)
}
override fun build(connection: PlayConnection?) = this
}

View File

@ -0,0 +1,21 @@
/*
* Minosoft
* Copyright (C) 2020-2022 Moritz Zwerger
*
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
*
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
*/
package de.bixilon.minosoft.commands.parser.factory
import de.bixilon.minosoft.commands.parser.brigadier.bool.BooleanParser
import de.bixilon.minosoft.data.registries.factory.DefaultFactory
object ArgumentFactories : DefaultFactory<ArgumentFactory<*>>(
BooleanParser,
)

View File

@ -0,0 +1,23 @@
/*
* Minosoft
* Copyright (C) 2020-2022 Moritz Zwerger
*
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
*
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
*/
package de.bixilon.minosoft.commands.parser.factory
import de.bixilon.minosoft.commands.parser.ArgumentParser
import de.bixilon.minosoft.data.registries.CompanionResourceLocation
import de.bixilon.minosoft.protocol.network.connection.play.PlayConnection
interface ArgumentFactory<T : ArgumentParser<*>> : CompanionResourceLocation {
fun build(connection: PlayConnection?): T
}

View File

@ -0,0 +1,16 @@
/*
* Minosoft
* Copyright (C) 2020-2022 Moritz Zwerger
*
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
*
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
*/
package de.bixilon.minosoft.commands.stack
typealias CommandExecutor = (stack: CommandStack) -> Unit

View File

@ -0,0 +1,16 @@
/*
* Minosoft
* Copyright (C) 2020-2022 Moritz Zwerger
*
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
*
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
*/
package de.bixilon.minosoft.commands.stack
class CommandStack

View File

@ -0,0 +1,35 @@
/*
* Minosoft
* Copyright (C) 2020-2022 Moritz Zwerger
*
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
*
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
*/
package de.bixilon.minosoft.commands.suggestion
import de.bixilon.minosoft.commands.suggestion.types.SuggestionType
class ArraySuggestion<T>(val values: List<T>) : SuggestionType<T> {
override fun suggest(input: String): List<T>? {
if (input.isBlank()) {
return values
}
val list: MutableList<T> = mutableListOf()
for (entry in values) {
if (entry.toString().startsWith(input)) {
list += entry
}
}
if (list.isEmpty()) {
return null
}
return list
}
}

View File

@ -0,0 +1,19 @@
/*
* Minosoft
* Copyright (C) 2020-2022 Moritz Zwerger
*
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
*
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
*/
package de.bixilon.minosoft.commands.suggestion.factory
import de.bixilon.minosoft.data.registries.factory.DefaultFactory
object SuggestionFactories : DefaultFactory<SuggestionFactory<*>>(
)

View File

@ -0,0 +1,24 @@
/*
* Minosoft
* Copyright (C) 2020-2022 Moritz Zwerger
*
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
*
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
*/
package de.bixilon.minosoft.commands.suggestion.factory
import de.bixilon.minosoft.commands.suggestion.types.SuggestionType
import de.bixilon.minosoft.data.registries.CompanionResourceLocation
import de.bixilon.minosoft.protocol.network.connection.play.PlayConnection
import de.bixilon.minosoft.protocol.protocol.PlayInByteBuffer
interface SuggestionFactory<T : SuggestionType<*>> : CompanionResourceLocation {
fun build(connection: PlayConnection?, buffer: PlayInByteBuffer?): T
}

View File

@ -0,0 +1,19 @@
/*
* Minosoft
* Copyright (C) 2020-2022 Moritz Zwerger
*
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
*
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
*/
package de.bixilon.minosoft.commands.suggestion.types
interface SuggestionType<T> {
fun suggest(input: String): List<T>?
}

View File

@ -0,0 +1,208 @@
/*
* Minosoft
* Copyright (C) 2020-2022 Moritz Zwerger
*
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
*
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
*/
package de.bixilon.minosoft.commands.util
import de.bixilon.minosoft.commands.errors.reader.*
open class CommandReader(val string: String) {
var pointer = 0
val length = string.length
fun canPeek(ignoreWhitespaces: Boolean = true): Boolean {
if (pointer >= length) {
return false
}
val whitespaces = if (ignoreWhitespaces) peekWhitespaces() else 0
return pointer + whitespaces < length
}
fun checkPeekNext(pointer: Int = this.pointer) {
if (!canPeekNext(pointer)) {
throw OutOfBoundsError(this, length - 1)
}
}
fun canPeekNext(pointer: Int = this.pointer): Boolean {
return pointer < length
}
fun peekNext(pointer: Int = this.pointer): Int? {
if (!canPeekNext()) {
return null
}
return string.codePointAt(pointer)
}
fun readNext(): Int? {
val next = peekNext(pointer) ?: return null
pointer++
return next
}
fun unsafePeekNext(): Int {
return peekNext() ?: throw OutOfBoundsError(this, length - 1)
}
fun unsafeReadNext(): Int {
return readNext() ?: throw OutOfBoundsError(this, length - 1)
}
fun peekWhitespaces(): Int {
var count = 0
while (true) {
val peek = peekNext(pointer + count) ?: return count
if (!Character.isWhitespace(peek)) {
break
}
count++
}
return count
}
fun skipWhitespaces(): Int {
val count = peekWhitespaces()
pointer += count
return count
}
fun peek(ignoreWhitespaces: Boolean = true): Int? {
if (ignoreWhitespaces) {
skipWhitespaces()
}
return peekNext()
}
fun read(ignoreWhitespaces: Boolean = true): Int? {
if (ignoreWhitespaces) {
skipWhitespaces()
}
val peek = peekNext() ?: return null
pointer++
return peek
}
fun unsafePeek(ignoreWhitespaces: Boolean = true): Int {
if (ignoreWhitespaces) {
skipWhitespaces()
}
return unsafePeekNext()
}
fun unsafeRead(ignoreWhitespaces: Boolean = true): Int {
val peek = unsafePeek(ignoreWhitespaces)
pointer++
return peek
}
fun peek(vararg chars: Int, ignoreWhitespaces: Boolean = true): Int? {
val peek = peek(ignoreWhitespaces) ?: return null
if (peek !in chars) {
return null
}
return peek
}
fun read(vararg chars: Int, ignoreWhitespaces: Boolean = true): Int? {
val read = read(ignoreWhitespaces) ?: return null
if (read !in chars) {
return null
}
return read
}
fun unsafePeek(vararg chars: Int, ignoreWhitespaces: Boolean = true): Int {
val peek = unsafePeek(ignoreWhitespaces)
if (peek !in chars) {
throw InvalidPeekError(this, pointer, peek, chars)
}
return peek
}
fun unsafeRead(vararg chars: Int, ignoreWhitespaces: Boolean = true): Int {
val read = unsafeRead(ignoreWhitespaces)
if (read !in chars) {
throw InvalidReadError(this, pointer, read, chars)
}
return read
}
fun readUnquotedString(): String? {
val builder = StringBuilder()
skipWhitespaces()
if (!canPeekNext()) {
return null
}
while (true) {
val char = read(false) ?: return builder.toString()
if (Character.isWhitespace(char)) {
return builder.toString()
}
builder.appendCodePoint(char)
}
}
fun readQuotedString(): String {
skipWhitespaces()
val start = pointer
unsafeRead(STRING_QUOTE)
val string = StringBuilder()
var skipNextChar = false
while (true) {
val read = readNext() ?: throw UnfinishedQuotedStringError(this, pointer)
if (read == '\\'.code) {
if (skipNextChar) {
string.append('\\')
skipNextChar = false
continue
}
skipNextChar = true
continue
}
if (skipNextChar) {
if (read != STRING_QUOTE) {
throw UnexpectedBackslashError(this, start, pointer, read)
}
string.append('"')
skipNextChar = false
continue
}
if (read == STRING_QUOTE) {
return string.toString()
}
string.appendCodePoint(read)
}
}
fun readString(): String? {
skipWhitespaces()
val start = unsafePeek()
if (start == STRING_QUOTE) {
return readQuotedString()
}
return readUnquotedString()
}
fun <T> readResult(reader: CommandReader.() -> T): ReadResult<T> {
val start = pointer
val result = reader(this)
val end = pointer
val read = string.substring(start, end)
return ReadResult(start, end, read, result)
}
companion object {
const val STRING_QUOTE = '"'.code
}
}

View File

@ -0,0 +1,21 @@
/*
* Minosoft
* Copyright (C) 2020-2022 Moritz Zwerger
*
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
*
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
*/
package de.bixilon.minosoft.commands.util
class ReadResult<T>(
val start: Int,
val end: Int,
val read: String,
val result: T,
)

View File

@ -0,0 +1,21 @@
/*
* Minosoft
* Copyright (C) 2020-2022 Moritz Zwerger
*
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
*
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
*/
package de.bixilon.minosoft.terminal.commands
import de.bixilon.minosoft.commands.nodes.LiteralNode
interface Command {
fun build(): LiteralNode
}

View File

@ -0,0 +1,23 @@
/*
* Minosoft
* Copyright (C) 2020-2022 Moritz Zwerger
*
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
*
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
*/
package de.bixilon.minosoft.terminal.commands
import de.bixilon.minosoft.commands.nodes.LiteralNode
class HelpCommand : Command {
override fun build(): LiteralNode {
TODO("Not yet implemented")
}
}

View File

@ -0,0 +1,88 @@
/*
* Minosoft
* Copyright (C) 2020-2022 Moritz Zwerger
*
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
*
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
*/
package de.bixilon.minosoft.commands.parser.brigadier.bool
import de.bixilon.minosoft.commands.errors.suggestion.NoSuggestionError
import de.bixilon.minosoft.commands.util.CommandReader
import org.junit.jupiter.api.Assertions.*
import org.junit.jupiter.api.Test
internal class BooleanParserTest {
@Test
fun testTrue() {
val reader = CommandReader("true")
assertTrue(BooleanParser.parse(reader))
}
@Test
fun testFalse() {
val reader = CommandReader("false")
assertFalse(BooleanParser.parse(reader))
}
@Test
fun testCaseSensitivity() {
val reader = CommandReader("True")
assertThrows(BooleanParseError::class.java) { (BooleanParser.parse(reader)) }
}
@Test
fun testEmpty() {
val reader = CommandReader("")
assertThrows(BooleanParseError::class.java) { (BooleanParser.parse(reader)) }
}
@Test
fun testTrash() {
val reader = CommandReader("this is trash")
assertThrows(BooleanParseError::class.java) { (BooleanParser.parse(reader)) }
}
@Test
fun testEmptySuggestion() {
val reader = CommandReader("")
assertEquals(BooleanParser.getSuggestions(reader).size, 2)
}
@Test
fun testTrueSuggestion() {
val reader = CommandReader("t")
assertEquals(BooleanParser.getSuggestions(reader).getOrNull(0), true)
}
@Test
fun testFullTrueSuggestion() {
val reader = CommandReader("true")
assertEquals(BooleanParser.getSuggestions(reader).getOrNull(0), true)
}
@Test
fun testFalseSuggestion() {
val reader = CommandReader("fa")
assertEquals(BooleanParser.getSuggestions(reader).getOrNull(0), false)
}
@Test
fun testFullFalseSuggestion() {
val reader = CommandReader("false")
assertEquals(BooleanParser.getSuggestions(reader).getOrNull(0), false)
}
@Test
fun testNoSuggestion() {
val reader = CommandReader("a")
assertThrows(NoSuggestionError::class.java) { BooleanParser.getSuggestions(reader).size }
}
}

View File

@ -0,0 +1,88 @@
/*
* Minosoft
* Copyright (C) 2020-2022 Moritz Zwerger
*
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
*
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
*/
package de.bixilon.minosoft.commands.util
import de.bixilon.minosoft.commands.errors.reader.OutOfBoundsError
import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.api.Assertions.assertThrows
import org.junit.jupiter.api.Test
internal class CommandReaderTest {
@Test
fun `Peek char`() {
val reader = CommandReader("test")
assertEquals(reader.peek(), 't'.code)
assertEquals(reader.peek(), 't'.code)
}
@Test
fun `Read test`() {
val reader = CommandReader("test")
assertEquals(reader.read(), 't'.code)
assertEquals(reader.read(), 'e'.code)
assertEquals(reader.read(), 's'.code)
assertEquals(reader.read(), 't'.code)
}
@Test
fun `Check OutOfBounds null`() {
val reader = CommandReader("test")
assertEquals(reader.read(), 't'.code)
assertEquals(reader.read(), 'e'.code)
assertEquals(reader.read(), 's'.code)
assertEquals(reader.read(), 't'.code)
assertEquals(reader.read(), null)
}
@Test
fun `Check OutOfBounds throw`() {
val reader = CommandReader("test")
assertEquals(reader.read(), 't'.code)
assertEquals(reader.read(), 'e'.code)
assertEquals(reader.read(), 's'.code)
assertEquals(reader.read(), 't'.code)
assertThrows(OutOfBoundsError::class.java) { reader.unsafeRead() }
}
@Test
fun `Check unquotedString read`() {
val reader = CommandReader("test")
assertEquals(reader.readString(), "test")
}
@Test
fun `Check unquotedString read 2`() {
val reader = CommandReader("test test2")
assertEquals(reader.readString(), "test")
assertEquals(reader.readString(), "test2")
}
@Test
fun `Read quoted string`() {
val reader = CommandReader("\"test\"")
assertEquals(reader.readString(), "test")
}
@Test
fun `Read separated quoted string`() {
val reader = CommandReader("\"test test\"")
assertEquals(reader.readString(), "test test")
}
@Test
fun `Read escaped quoted string`() {
val reader = CommandReader("\"test \\\"test\"")
assertEquals(reader.readString(), "test \"test")
}
}