Skip to content

Commit 8a6e8fd

Browse files
committed
Build simulator and transfer command
1 parent d3b2fa4 commit 8a6e8fd

28 files changed

+785
-389
lines changed
Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
/*
2+
* Copyright 2023 The Quilt Project
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
/*
18+
* Preserve binary compatibility when moving extensions between files
19+
*/
20+
@file:JvmMultifileClass
21+
@file:JvmName("ArgumentsKt")
22+
23+
package com.lambda.brigadier.argument
24+
25+
26+
import com.lambda.brigadier.*
27+
import com.lambda.brigadier.assumeSourceNotUsed
28+
import net.minecraft.command.CommandRegistryAccess
29+
import net.minecraft.command.argument.ItemPredicateArgumentType
30+
import net.minecraft.command.argument.ItemSlotArgumentType
31+
import net.minecraft.command.argument.ItemStackArgument
32+
import net.minecraft.command.argument.ItemStackArgumentType
33+
import net.minecraft.item.ItemStack
34+
import java.util.function.Predicate
35+
36+
/**
37+
* Reads the [ItemStack] predicate value from the
38+
* argument in the receiver [ArgumentReader].
39+
*
40+
* @see ItemPredicateArgumentType.getItemPredicate
41+
*/
42+
@JvmName("valueItemPredicateArg")
43+
@BrigadierDsl
44+
fun DefaultArgumentReader<ItemPredicateArgumentType>.value(): Predicate<ItemStack> {
45+
return ItemPredicateArgumentType.getItemStackPredicate(context.assumeSourceNotUsed(), name)
46+
}
47+
48+
/**
49+
* Reads the integer value from the
50+
* argument in the receiver [ArgumentReader].
51+
*
52+
* @see ItemSlotArgumentType.getItemSlot
53+
*/
54+
@JvmName("valueItemSlotArg")
55+
@BrigadierDsl
56+
fun DefaultArgumentReader<ItemSlotArgumentType>.value(): Int {
57+
return ItemSlotArgumentType.getItemSlot(context.assumeSourceNotUsed(), name)
58+
}
59+
60+
/**
61+
* Reads the [ItemStackArgument] value from the
62+
* argument in the receiver [ArgumentReader].
63+
*
64+
* @see ItemStackArgumentType.getItemStackArgument
65+
*/
66+
@JvmName("valueItemStackArg")
67+
@BrigadierDsl
68+
fun DefaultArgumentReader<ItemStackArgumentType>.value(): ItemStackArgument {
69+
return ItemStackArgumentType.getItemStackArgument(context, name)
70+
}
71+
72+
/**
73+
* Creates an item predicate argument with [name] as the parameter name.
74+
*
75+
* @param context The command build context
76+
*/
77+
@BrigadierDsl
78+
fun <S> itemPredicate(
79+
name: String,
80+
context: CommandRegistryAccess
81+
): DefaultArgumentConstructor<S, ItemPredicateArgumentType> {
82+
return argument(name, ItemPredicateArgumentType.itemPredicate(context))
83+
}
84+
85+
/**
86+
* Creates an item slot argument with [name] as the parameter name.
87+
*/
88+
@BrigadierDsl
89+
fun <S> itemSlot(
90+
name: String
91+
): DefaultArgumentConstructor<S, ItemSlotArgumentType> {
92+
return argument(name, ItemSlotArgumentType.itemSlot())
93+
}
94+
95+
/**
96+
* Creates an item stack argument with [name] as the parameter name.
97+
*
98+
* @param context The command build context
99+
*/
100+
@BrigadierDsl
101+
fun <S> itemStack(
102+
name: String,
103+
context: CommandRegistryAccess
104+
): DefaultArgumentConstructor<S, ItemStackArgumentType> {
105+
return argument(name, ItemStackArgumentType.itemStack(context))
106+
}

common/src/main/kotlin/com/lambda/command/LambdaCommand.kt

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,21 @@ import com.lambda.command.CommandManager.dispatcher
44
import com.lambda.util.Nameable
55
import com.lambda.util.primitives.extension.CommandBuilder
66
import com.mojang.brigadier.builder.LiteralArgumentBuilder
7+
import net.minecraft.command.CommandRegistryAccess
78
import net.minecraft.command.CommandSource
9+
import net.minecraft.registry.BuiltinRegistries
10+
import net.minecraft.server.command.CommandManager
811

912
abstract class LambdaCommand(
1013
final override val name: String,
1114
val aliases: Set<String> = emptySet(),
1215
val usage: String = "",
1316
val description: String = "",
1417
) : Nameable {
18+
val registry: CommandRegistryAccess by lazy {
19+
CommandManager.createRegistryAccess(BuiltinRegistries.createWrapperLookup())
20+
}
21+
1522
// ToDo: Include usage and description in the help command
1623
init {
1724
(listOf(name) + aliases).forEach {
Lines changed: 66 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,81 @@
11
package com.lambda.command.commands
22

3-
import com.lambda.brigadier.execute
3+
import com.lambda.brigadier.CommandResult
4+
import com.lambda.brigadier.argument.integer
5+
import com.lambda.brigadier.argument.itemStack
6+
import com.lambda.brigadier.argument.string
7+
import com.lambda.brigadier.argument.value
8+
import com.lambda.brigadier.executeWithResult
9+
import com.lambda.brigadier.required
410
import com.lambda.command.LambdaCommand
11+
import com.lambda.interaction.material.ContainerManager
12+
import com.lambda.interaction.material.ContainerManager.containerMatchSelection
13+
import com.lambda.interaction.material.ContainerManager.findContainerWithSelection
514
import com.lambda.interaction.material.ContainerManager.transfer
6-
import com.lambda.interaction.material.StackSelection.Companion.select
7-
import com.lambda.interaction.material.container.MainHandContainer
15+
import com.lambda.interaction.material.StackSelection.Companion.selectStack
16+
import com.lambda.interaction.material.transfer.TransferResult
17+
import com.lambda.util.Communication.info
818
import com.lambda.util.primitives.extension.CommandBuilder
9-
import net.minecraft.item.Items
1019

1120
object TransferCommand : LambdaCommand(
1221
name = "transfer",
1322
usage = "transfer <item> <amount> <to>",
1423
description = "Transfer items to a container"
1524
) {
1625
override fun CommandBuilder.create() {
17-
execute {
18-
Items.OBSIDIAN.select().transfer(MainHandContainer)?.solve?.start(null)
26+
required(itemStack("stack", registry)) { stack ->
27+
required(integer("amount")) { amount ->
28+
required(string("from")) { from ->
29+
suggests { ctx, builder ->
30+
val selection = selectStack(amount(ctx).value()) {
31+
isItem(stack(ctx).value().item)
32+
}
33+
containerMatchSelection(selection).forEach {
34+
builder.suggest("\"${it.name} with ${it.available(selection)}\"")
35+
}
36+
builder.buildFuture()
37+
}
38+
required(string("to")) { to ->
39+
suggests { ctx, builder ->
40+
val selection = selectStack(amount(ctx).value()) {
41+
isItem(stack(ctx).value().item)
42+
}
43+
ContainerManager.container().forEach {
44+
builder.suggest("\"${it.name} with space left ${it.spaceLeft(selection)}\"")
45+
}
46+
builder.buildFuture()
47+
}
48+
executeWithResult {
49+
val selection = selectStack(amount().value()) {
50+
isItem(stack().value().item)
51+
}
52+
val fromContainer = ContainerManager.container().find {
53+
it.name == from().value().split(" with ").firstOrNull()
54+
} ?: return@executeWithResult CommandResult.failure("From container not found")
55+
56+
val toContainer = ContainerManager.container().find {
57+
it.name == to().value().split(" with ").firstOrNull()
58+
} ?: return@executeWithResult CommandResult.failure("To container not found")
59+
60+
when (val result = fromContainer.transfer(selection, toContainer)) {
61+
is TransferResult.Success -> {
62+
info("Transferring $selection from ${fromContainer.name} to ${toContainer.name}")
63+
result.solve.start(null)
64+
return@executeWithResult CommandResult.success()
65+
}
66+
is TransferResult.MissingItems -> {
67+
return@executeWithResult CommandResult.failure("Missing items: ${result.missing}")
68+
}
69+
is TransferResult.NoSpace -> {
70+
return@executeWithResult CommandResult.failure("No space in ${toContainer.name}")
71+
}
72+
}
73+
74+
return@executeWithResult CommandResult.success()
75+
}
76+
}
77+
}
78+
}
1979
}
2080
}
2181
}

common/src/main/kotlin/com/lambda/interaction/construction/result/BreakResult.kt

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,21 @@
11
package com.lambda.interaction.construction.result
22

3+
import baritone.api.pathing.goals.GoalBlock
4+
import baritone.api.pathing.goals.GoalInverted
35
import com.lambda.interaction.construction.context.BreakContext
46
import com.lambda.interaction.material.ContainerManager.findBestAvailableTool
57
import com.lambda.interaction.material.ContainerManager.transfer
68
import com.lambda.interaction.material.StackSelection.Companion.select
79
import com.lambda.interaction.material.StackSelection.Companion.selectStack
810
import com.lambda.interaction.material.container.MainHandContainer
11+
import com.lambda.task.Task
912
import com.lambda.task.Task.Companion.emptyTask
1013
import com.lambda.task.tasks.BreakBlock.Companion.breakBlock
14+
import com.lambda.task.tasks.GoalTask.Companion.moveToGoalUntil
1115
import net.minecraft.block.BlockState
1216
import net.minecraft.item.Item
1317
import net.minecraft.util.math.BlockPos
18+
import net.minecraft.util.math.Box
1419
import net.minecraft.util.math.Direction
1520

1621
sealed class BreakResult : BuildResult() {
@@ -112,7 +117,14 @@ sealed class BreakResult : BuildResult() {
112117
data class PlayerOnTop(
113118
override val blockPos: BlockPos,
114119
val blockState: BlockState
115-
) : BreakResult() {
120+
) : Resolvable, BreakResult() {
116121
override val rank = Rank.BREAK_PLAYER_ON_TOP
122+
123+
override val resolve =
124+
moveToGoalUntil(GoalInverted(GoalBlock(blockPos))) {
125+
val pBox = player.boundingBox
126+
val aabb = Box(pBox.minX, pBox.minY - 1.0E-6, pBox.minZ, pBox.maxX, pBox.minY, pBox.maxZ)
127+
world.findSupportingBlockPos(player, aabb).orElse(null) != blockPos
128+
}
117129
}
118130
}

common/src/main/kotlin/com/lambda/interaction/construction/result/BuildResult.kt

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
package com.lambda.interaction.construction.result
22

3-
import baritone.process.BuilderProcess.GoalAdjacent
3+
import baritone.process.BuilderProcess.GoalPlace
44
import com.lambda.interaction.construction.context.BuildContext
55
import com.lambda.interaction.material.ContainerManager.transfer
66
import com.lambda.interaction.material.StackSelection.Companion.select
@@ -12,6 +12,7 @@ import com.lambda.task.tasks.GoalTask.Companion.moveToGoal
1212
import com.lambda.task.tasks.GoalTask.Companion.moveUntilLoaded
1313
import net.minecraft.block.BlockState
1414
import net.minecraft.item.Item
15+
import net.minecraft.item.ItemStack
1516
import net.minecraft.util.math.BlockPos
1617
import net.minecraft.util.math.Direction
1718
import net.minecraft.util.math.Vec3d
@@ -85,7 +86,7 @@ abstract class BuildResult : ComparableResult<Rank> {
8586
data class OutOfWorld(
8687
override val blockPos: BlockPos
8788
) : BuildResult() {
88-
override val rank = Rank.BREAK_OUT_OF_WORLD
89+
override val rank = Rank.OUT_OF_WORLD
8990
}
9091

9192
/**
@@ -113,7 +114,7 @@ abstract class BuildResult : ComparableResult<Rank> {
113114
) : Resolvable, BuildResult() {
114115
override val rank = Rank.NOT_VISIBLE
115116

116-
override val resolve = moveToGoal(GoalAdjacent(hitPos, blockPos, true))
117+
override val resolve = moveToGoal(GoalPlace(blockPos))
117118

118119
override fun compareTo(other: ComparableResult<Rank>): Int {
119120
return when (other) {
@@ -145,6 +146,29 @@ abstract class BuildResult : ComparableResult<Rank> {
145146
}
146147
}
147148

149+
/**
150+
* The Player has the wrong item stack selected.
151+
* @param blockPos The position of the block that needs a different tool.
152+
* @param neededStack The best tool for the block state.
153+
*/
154+
data class WrongStack(
155+
override val blockPos: BlockPos,
156+
val context: BuildContext,
157+
val neededStack: ItemStack
158+
) : Resolvable, BuildResult() {
159+
override val rank = Rank.WRONG_ITEM
160+
161+
override val resolve: Task<*> =
162+
neededStack.select().transfer(MainHandContainer)?.solve ?: emptyTask() // ToDo: Should throw error
163+
164+
override fun compareTo(other: ComparableResult<Rank>): Int {
165+
return when (other) {
166+
is WrongItem -> context.compareTo(other.context)
167+
else -> super.compareTo(other)
168+
}
169+
}
170+
}
171+
148172
/**
149173
* Represents a break out of reach.
150174
* @param blockPos The position of the block that is out of reach.

common/src/main/kotlin/com/lambda/interaction/construction/result/PlaceResult.kt

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,19 @@
11
package com.lambda.interaction.construction.result
22

3+
import baritone.api.pathing.goals.GoalBlock
4+
import baritone.api.pathing.goals.GoalInverted
35
import com.lambda.interaction.construction.context.PlaceContext
46
import com.lambda.task.Task
57
import com.lambda.task.tasks.BuildStructure.Companion.breakBlock
8+
import com.lambda.task.tasks.GoalTask.Companion.moveToGoal
9+
import com.lambda.task.tasks.GoalTask.Companion.moveToGoalUntil
610
import com.lambda.task.tasks.PlaceBlock.Companion.placeBlock
711
import net.minecraft.block.BlockState
812
import net.minecraft.item.ItemPlacementContext
913
import net.minecraft.item.ItemStack
1014
import net.minecraft.util.math.BlockPos
15+
import net.minecraft.util.math.Box
16+
import net.minecraft.util.shape.VoxelShape
1117

1218
/**
1319
* [PlaceResult] represents the result of a placement simulation.
@@ -51,6 +57,16 @@ sealed class PlaceResult : BuildResult() {
5157
override val rank = Rank.PLACE_NO_INTEGRITY
5258
}
5359

60+
data class BlockedByPlayer(
61+
override val blockPos: BlockPos
62+
) : Resolvable, PlaceResult() {
63+
override val rank = Rank.PLACE_BLOCKED_BY_PLAYER
64+
65+
override val resolve = moveToGoalUntil(GoalInverted(GoalBlock(blockPos))) {
66+
!world.canCollide(player, Box(blockPos))
67+
}
68+
}
69+
5470
/**
5571
* The placement configuration cannot replace the block at the target position.
5672
* @param simulated The simulated placement configuration.
@@ -61,7 +77,10 @@ sealed class PlaceResult : BuildResult() {
6177
) : Resolvable, PlaceResult() {
6278
override val rank = Rank.PLACE_CANT_REPLACE
6379

64-
override val resolve = breakBlock(simulated.blockPos)
80+
// override val resolve = breakBlock(simulated.blockPos)
81+
override val resolve = moveToGoalUntil(GoalInverted(GoalBlock(blockPos))) {
82+
!world.canCollide(player, Box(blockPos))
83+
}
6584
}
6685

6786
/**

common/src/main/kotlin/com/lambda/interaction/construction/result/Rank.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,11 @@ enum class Rank {
66
PLACE_SUCCESS,
77
WRONG_ITEM,
88
BREAK_ITEM_CANT_MINE,
9+
PLACE_BLOCKED_BY_PLAYER,
910
NOT_VISIBLE,
1011
OUT_OF_REACH,
1112
BREAK_NOT_EXPOSED,
12-
BREAK_OUT_OF_WORLD,
13-
PLACE_OUT_OF_WORLD,
13+
OUT_OF_WORLD,
1414
CHUNK_NOT_LOADED,
1515
PLACE_NO_INTEGRITY,
1616
PLACE_CANT_REPLACE,

0 commit comments

Comments
 (0)