Gehen Sie zu Kotlin. Gehen Sie nicht über Los und ziehen Sie nicht 200 RM ein.

Migrate some classes to Kotlin, let's see if I will regret
This commit is contained in:
skippyall
2026-05-02 10:48:13 +02:00
parent 71016f9e70
commit f3c934c619
12 changed files with 412 additions and 269 deletions
@@ -1,98 +1,136 @@
package io.github.skippyall.minions.gui; package io.github.skippyall.minions.gui
import com.mojang.authlib.GameProfile; import com.mojang.authlib.GameProfile
import eu.pb4.sgui.api.elements.GuiElementBuilder; import eu.pb4.sgui.api.elements.GuiElementBuilder
import eu.pb4.sgui.api.gui.SimpleGui; import eu.pb4.sgui.api.gui.SimpleGui
import io.github.skippyall.minions.gui.input.TextInput; import io.github.skippyall.minions.gui.input.TextInput
import io.github.skippyall.minions.minion.MinionData; import io.github.skippyall.minions.minion.MinionData
import io.github.skippyall.minions.minion.MinionItem; import io.github.skippyall.minions.minion.MinionItem
import io.github.skippyall.minions.minion.MinionProfileUtils; import io.github.skippyall.minions.minion.MinionProfileUtils
import io.github.skippyall.minions.minion.skin.SkinProvider; import io.github.skippyall.minions.minion.skin.SkinProvider
import io.github.skippyall.minions.registration.MinionRegistries; import io.github.skippyall.minions.registration.MinionRegistries
import io.github.skippyall.minions.registration.SkinProviders; import io.github.skippyall.minions.registration.SkinProviders
import net.fabricmc.fabric.api.entity.FakePlayer; import kotlinx.coroutines.launch
import net.minecraft.core.component.DataComponents; import net.fabricmc.fabric.api.entity.FakePlayer
import net.minecraft.network.chat.Component; import net.minecraft.core.component.DataComponents
import net.minecraft.server.level.ServerPlayer; import net.minecraft.network.chat.Component
import net.minecraft.world.inventory.MenuType; import net.minecraft.server.level.ServerPlayer
import net.minecraft.world.item.ItemStack; import net.minecraft.world.inventory.MenuType
import net.minecraft.world.item.Items; import net.minecraft.world.item.ItemStack
import net.minecraft.world.item.component.ResolvableProfile; import net.minecraft.world.item.Items
import net.minecraft.world.item.component.ResolvableProfile
import java.util.Optional
import java.util.function.Consumer
import java.util.function.Function
import java.util.Optional; class MinionLookGui(
viewer: ServerPlayer,
private val minionItem: ItemStack
) : MinionsGui(viewer) {
private lateinit var gui: SimpleGui
public class MinionLookGui extends SimpleGui { private var currentSkinProvider: SkinProvider = SkinProviders.NAME
private ItemStack minionItem;
private SkinProvider currentSkinProvider;
public MinionLookGui(ServerPlayer player, ItemStack minionItem) { private val data: MinionData
super(MenuType.GENERIC_9x3, player, false); get() = MinionItem.getDataOrDefault(viewer.level().server, minionItem)
this.minionItem = minionItem;
this.currentSkinProvider = SkinProviders.NAME; init {
open()
} }
public void update() { override fun open() {
updateName(); gui = object : SimpleGui(MenuType.GENERIC_9x3, viewer, false) {
updateSkin(); override fun onPlayerClose(success: Boolean) {
updateSkinProvider(); onBackingClosed()
}
}
update()
gui.open()
} }
private void updateName() { override fun closeBacking() {
setSlot(10, new GuiElementBuilder() gui.close()
}
fun update() {
updateName()
updateSkin()
updateSkinProvider()
}
private fun updateName() {
gui.setSlot(
10, GuiElementBuilder()
.setItem(Items.OAK_SIGN) .setItem(Items.OAK_SIGN)
.setName(Component.literal(getData().name())) .setName(Component.literal(this.data.name))
.setCallback(() -> { .setCallback(this::openRenameGui)
openRenameGui(player, minionItem); )
})
);
} }
private void updateSkin() { private fun updateSkin() {
GuiElementBuilder builder = new GuiElementBuilder() val builder = GuiElementBuilder()
.setItem(Items.PLAYER_HEAD) .setItem(Items.PLAYER_HEAD)
.setCallback(() -> currentSkinProvider.openSkinMenu(player) .setCallback(this::openSkinGui)
.thenCompose(profile -> profile.resolveProfile(player.level().getServer().services().profileResolver()))
.thenAccept(skin -> MinionItem.setData(player.level().getServer(), getData().withSkin(Optional.of(skin.properties())), minionItem))); if (MinionItem.getData(viewer.level().server, minionItem)?.skin?.isPresent ?: false) {
if(MinionItem.getData(player.level().getServer(), minionItem) != null && MinionItem.getData(player.level().getServer(), minionItem).skin().isPresent()) { builder.setComponent(
builder.setComponent(DataComponents.PROFILE, ResolvableProfile.createResolved(new GameProfile(FakePlayer.DEFAULT_UUID, "", getData().skin().get()))); DataComponents.PROFILE,
} ResolvableProfile.createResolved(GameProfile(FakePlayer.DEFAULT_UUID, "", this.data.skin.get()))
setSlot(16, builder); )
} }
private void cycleSkinProvider() { gui.setSlot(16, builder)
int currentId = MinionRegistries.SKIN_PROVIDERS.getId(currentSkinProvider);
currentId++;
if(MinionRegistries.SKIN_PROVIDERS.size() == currentId) {
currentId = 0;
} }
currentSkinProvider = MinionRegistries.SKIN_PROVIDERS.byId(currentId); fun openSkinGui() {
updateSkinProvider(); currentSkinProvider.openSkinMenu(this)
.thenCompose(Function { profile: ResolvableProfile? ->
profile!!.resolveProfile(
viewer.level().server.services().profileResolver()
)
})
.thenAccept(Consumer { skin: GameProfile? ->
MinionItem.setData(
viewer.level().server, this.data.withSkin(
Optional.of(skin!!.properties())
), minionItem
)
})
} }
private void updateSkinProvider() { private fun cycleSkinProvider() {
setSlot(25, new GuiElementBuilder() var currentId = MinionRegistries.SKIN_PROVIDERS.getId(currentSkinProvider)
currentId++
if (MinionRegistries.SKIN_PROVIDERS.size() == currentId) {
currentId = 0
}
currentSkinProvider = MinionRegistries.SKIN_PROVIDERS.byId(currentId)!!
updateSkinProvider()
}
private fun updateSkinProvider() {
gui.setSlot(
25, GuiElementBuilder()
.setItem(Items.GREEN_STAINED_GLASS_PANE) .setItem(Items.GREEN_STAINED_GLASS_PANE)
.setComponent(DataComponents.CUSTOM_NAME, currentSkinProvider.getDisplayName()) .setComponent(DataComponents.CUSTOM_NAME, currentSkinProvider.getDisplayName())
.setCallback(this::cycleSkinProvider) .setCallback(Runnable { this.cycleSkinProvider() })
); )
} }
private MinionData getData() { fun openRenameGui() {
return MinionItem.getDataOrDefault(player.level().getServer(), minionItem); scope.launch {
val newName = TextInput.input(
this@MinionLookGui,
Component.translatable("minions.gui.look.rename.title"),
"Minion",
) { name ->
MinionProfileUtils.checkMinionNameWithoutPrefix(viewer.level().server, name)
} }
public static void open(ServerPlayer player, ItemStack minionItem) { if(newName != null) {
MinionLookGui gui = new MinionLookGui(player, minionItem); this@MinionLookGui.data.withName(newName)
gui.update(); }
gui.open();
} }
public void openRenameGui(ServerPlayer player, ItemStack minionItem) {
TextInput.inputSync(player, Component.translatable("minions.gui.look.rename.title"), "Minion", name -> MinionProfileUtils.checkMinionNameWithoutPrefix(player.level().getServer(), name))
.thenAccept(name -> {
MinionItem.setData(player.level().getServer(), getData().withName(MinionProfileUtils.getPrefix() + name), minionItem);
open();
});
} }
} }
@@ -1,76 +1,84 @@
package io.github.skippyall.minions.gui; package io.github.skippyall.minions.gui
import eu.pb4.sgui.api.elements.GuiElementBuilder; import eu.pb4.sgui.api.elements.GuiElementBuilder
import net.minecraft.network.chat.Component; import kotlinx.coroutines.CompletableJob
import net.minecraft.server.level.ServerPlayer; import kotlinx.coroutines.CoroutineName
import net.minecraft.world.item.Items; import kotlinx.coroutines.CoroutineScope
import org.jetbrains.annotations.Nullable; import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.cancel
import net.minecraft.network.chat.Component
import net.minecraft.server.level.ServerPlayer
import net.minecraft.world.item.Items
public abstract class MinionsGui { abstract class MinionsGui {
protected final @Nullable MinionsGui parent; protected val parent: MinionsGui?
protected final ServerPlayer viewer; @JvmField
protected @Nullable MinionsGui child = null; val viewer: ServerPlayer
private boolean open = true; protected var child: MinionsGui? = null
private var open = true
public MinionsGui(MinionsGui parent) { private val job: CompletableJob
this.viewer = parent.viewer; val scope: CoroutineScope
this.parent = parent;
parent.child = this; constructor(parent: MinionsGui) {
this.viewer = parent.viewer
this.parent = parent
parent.child = this
job = Job(parent.job)
scope = CoroutineScope(Dispatchers.Unconfined.plus(CoroutineName("MinionsGui")).plus(job))
} }
public MinionsGui(ServerPlayer viewer) { constructor(viewer: ServerPlayer) {
this.viewer = viewer; this.viewer = viewer
this.parent = null; this.parent = null
job = Job(null)
scope = CoroutineScope(Dispatchers.Unconfined.plus(CoroutineName("MinionsGui")).plus(job))
} }
public ServerPlayer getViewer() { protected abstract fun open()
return viewer;
protected fun reopen() {
open()
} }
protected abstract void open(); fun onBackingClosed() {
if (child != null && child!!.open) {
protected void reopen() { return
open();
} }
public void onBackingClosed() { close(true)
if(child != null && child.open) {
return;
} }
close(true); @JvmOverloads
} fun close(alreadyClosed: Boolean = false) {
if (open) {
public void close() { scope.cancel(null)
close(false); open = false
} if (child != null) {
child!!.close(alreadyClosed)
public void close(boolean alreadyClosed) { } else if (!alreadyClosed) {
if(open) { closeBacking()
open = false;
if(child != null) {
child.close(alreadyClosed);
} else if(!alreadyClosed) {
closeBacking();
} }
} }
} }
public void goBack() { fun goBack() {
if(parent != null) { if (parent != null) {
open = false; open = false
parent.child = null; parent.child = null
parent.reopen(); parent.reopen()
close(true)
} else { } else {
close(false); close(false)
} }
} }
public GuiElementBuilder backButton() { fun backButton(): GuiElementBuilder? {
return new GuiElementBuilder(Items.MANGROVE_DOOR) return GuiElementBuilder(Items.MANGROVE_DOOR)
.setName(Component.translatable("gui.back")) .setName(Component.translatable("gui.back"))
.setCallback(this::goBack); .setCallback(Runnable { this.goBack() })
} }
protected abstract void closeBacking(); protected abstract fun closeBacking()
} }
@@ -78,7 +78,7 @@ public class ChoiceInput {
CompletableFuture<Boolean> future = new CompletableFuture<>(); CompletableFuture<Boolean> future = new CompletableFuture<>();
new SimpleMinionsGui(parent, (onClose, me) -> { new SimpleMinionsGui(parent, (onClose, me) -> {
SimpleGui gui = new SimpleGui(MenuType.GENERIC_3x3, parent.getViewer(), false) { SimpleGui gui = new SimpleGui(MenuType.GENERIC_3x3, parent.viewer, false) {
@Override @Override
public void onPlayerClose(boolean success) { public void onPlayerClose(boolean success) {
future.complete(false); future.complete(false);
@@ -1,125 +1,222 @@
package io.github.skippyall.minions.gui.input; package io.github.skippyall.minions.gui.input
import eu.pb4.sgui.api.elements.GuiElementBuilder; import eu.pb4.sgui.api.elements.GuiElementBuilder
import eu.pb4.sgui.api.gui.AnvilInputGui; import eu.pb4.sgui.api.gui.AnvilInputGui
import io.github.skippyall.minions.gui.MinionsGui; import io.github.skippyall.minions.gui.MinionsGui
import io.github.skippyall.minions.gui.minion.SimpleMinionsGui; import kotlinx.coroutines.Job
import net.minecraft.network.chat.Component; import kotlinx.coroutines.async
import net.minecraft.server.level.ServerPlayer; import kotlinx.coroutines.future.asCompletableFuture
import net.minecraft.world.inventory.AnvilMenu; import kotlinx.coroutines.launch
import net.minecraft.world.item.Items; import net.minecraft.network.chat.Component
import net.minecraft.world.inventory.AnvilMenu
import net.minecraft.world.item.Items
import java.util.concurrent.CompletableFuture
import java.util.concurrent.CompletableFuture; class TextInput<T>(
import java.util.function.Function; parent: MinionsGui,
val title: Component,
public class TextInput<T> extends AnvilInputGui { val defaultValue: String,
private final GuiElementBuilder valid = new GuiElementBuilder() val parser: suspend (String) -> Result<T, Component>
) : MinionsGui(parent) {
private val valid: GuiElementBuilder = GuiElementBuilder()
.setItem(Items.EMERALD_BLOCK) .setItem(Items.EMERALD_BLOCK)
.setName(Component.literal("OK")) .setName(Component.literal("OK"))
.setCallback(this::onConfirm); .setCallback(Runnable { this.onConfirm() })
private final GuiElementBuilder invalid = new GuiElementBuilder() private val invalid: GuiElementBuilder = GuiElementBuilder()
.setItem(Items.REDSTONE_BLOCK); .setItem(Items.REDSTONE_BLOCK)
private final Function<String, CompletableFuture<Result<T, Component>>> parser;
private final CompletableFuture<T> future;
private Result<T, Component> result;
private boolean isConfirm;
public TextInput(ServerPlayer player, Component title, String defaultValue, Function<String, CompletableFuture<Result<T, Component>>> parser, CompletableFuture<T> future) { private lateinit var gui: AnvilInputGui
super(player, false);
setTitle(title);
setDefaultInputValue(defaultValue);
this.parser = parser;
this.future = future;
updateConfirmButton(defaultValue); private var result: Result<T, Component>? = null
private var isConfirm = false
val job = Job()
init {
updateConfirmButton(defaultValue)
open()
} }
public static <T> CompletableFuture<T> inputSync(ServerPlayer player, Component title, String defaultValue, Function<String, Result<T, Component>> parser) { override fun open() {
return input(player, title, defaultValue, (String string) -> CompletableFuture.completedFuture(parser.apply(string))); gui = object : AnvilInputGui(viewer, false) {
override fun onInput(input: String) {
updateConfirmButton(input)
} }
public static <T> CompletableFuture<T> inputSync(MinionsGui gui, Component title, String defaultValue, Function<String, Result<T, Component>> parser) { override fun onPlayerClose(success: Boolean) {
return input(gui, title, defaultValue, (String string) -> CompletableFuture.completedFuture(parser.apply(string))); onBackingClosed()
if (job.isActive && !isConfirm) {
job.cancel()
}
}
} }
public static <T> CompletableFuture<T> input(ServerPlayer player, Component title, String defaultValue, Function<String, CompletableFuture<Result<T, Component>>> parser) { gui.setTitle(title)
CompletableFuture<T> future = new CompletableFuture<>(); gui.setDefaultInputValue(defaultValue)
new TextInput<>(player, title, defaultValue, parser, future).open(); gui.open()
return future;
} }
public static <T> CompletableFuture<T> input(MinionsGui gui, Component title, String defaultValue, Function<String, CompletableFuture<Result<T, Component>>> parser) { override fun closeBacking() {
CompletableFuture<T> future = new CompletableFuture<>(); gui.close()
new SimpleMinionsGui(gui, (onClose, me) -> { }
TextInput<T> input = new TextInput<>(gui.getViewer(), title, defaultValue, parser, future);
future.whenComplete((v, e) -> { fun updateConfirmButton(input: String) {
if(e != null) { scope.launch {
onClose.run(); val result = parser(input)
this@TextInput.result = result
if (result.isSuccess()) {
gui.setSlot(AnvilMenu.RESULT_SLOT, valid)
} else { } else {
me.goBack(); val text = result.getErrorOrThrow()
gui.setSlot(AnvilMenu.RESULT_SLOT, invalid.setName(text))
} }
});
input.open();
return input;
});
return future;
}
public static CompletableFuture<String> inputString(ServerPlayer player, Component title, String defaultValue) {
return inputSync(player, title, defaultValue, Result.Success::new);
}
public static CompletableFuture<String> inputString(MinionsGui gui, Component title, String defaultValue) {
return inputSync(gui, title, defaultValue, Result.Success::new);
}
public static CompletableFuture<Long> inputLong(ServerPlayer player, Component title, String defaultValue) {
return inputSync(player, title, defaultValue, string -> Result.wrapCustomError(() -> Long.valueOf(string), Component.translatable("minions.command.input.int.fail")));
}
public static CompletableFuture<Long> inputLong(MinionsGui gui, Component title, String defaultValue) {
return inputSync(gui, title, defaultValue, string -> Result.wrapCustomError(() -> Long.valueOf(string), Component.translatable("minions.command.input.int.fail")));
}
public static CompletableFuture<Double> inputDouble(ServerPlayer player, Component title, String defaultValue) {
return inputSync(player, title, defaultValue, string -> Result.wrapCustomError(() -> Double.valueOf(string), Component.translatable("minions.command.input.float.fail")));
}
public static CompletableFuture<Double> inputDouble(MinionsGui gui, Component title, String defaultValue) {
return inputSync(gui, title, defaultValue, string -> Result.wrapCustomError(() -> Double.valueOf(string), Component.translatable("minions.command.input.float.fail")));
}
@Override
public void onInput(String input) {
updateConfirmButton(input);
}
public void updateConfirmButton(String input) {
parser.apply(input).thenAccept(result -> {
this.result = result;
if(result.isSuccess()) {
setSlot(AnvilMenu.RESULT_SLOT, valid);
} else {
Component text = result.getErrorOrThrow();
setSlot(AnvilMenu.RESULT_SLOT, invalid.setName(text));
}
});
}
@Override
public void onPlayerClose(boolean success) {
if(!future.isDone() && !isConfirm) {
future.cancel(false);
} }
} }
public void onConfirm() { fun onConfirm() {
if(result != null) { result?.ifSuccess { _: T? ->
result.ifSuccess(success -> { isConfirm = true
isConfirm = true; }
future.complete(success); job.complete()
}); }
companion object {
@JvmStatic
suspend fun <T>input(
gui: MinionsGui,
title: Component,
defaultValue: String,
parser: suspend (String) -> Result<T, Component>,
): T? {
val input = TextInput(
parent = gui,
title = title,
defaultValue = defaultValue,
parser = parser,
)
input.job.join()
return input.result?.getOrDefault(null)
}
@JvmStatic
fun <T>inputFuture(
gui: MinionsGui,
title: Component,
defaultValue: String,
parser: (String) -> Result<T, Component>,
): CompletableFuture<T?> {
return gui.scope.async {
val input = TextInput(
parent = gui,
title = title,
defaultValue = defaultValue,
parser = parser,
)
input.job.join()
return@async input.result?.getOrDefault(null)
}.asCompletableFuture()
}
@JvmStatic
suspend fun inputString(
gui: MinionsGui,
title: Component,
defaultValue: String,
): String? {
return input<String>(
gui = gui,
title = title,
defaultValue = defaultValue,
parser = { result: String? -> Result.Success<String, Component>(result) },
)
}
@JvmStatic
fun inputStringFuture(
gui: MinionsGui,
title: Component,
defaultValue: String,
): CompletableFuture<String?> {
return gui.scope.async {
inputString(
gui,
title,
defaultValue
)
}.asCompletableFuture()
}
@JvmStatic
suspend fun inputLong(
gui: MinionsGui,
title: Component,
defaultValue: Long,
): Long? {
return input<Long>(
gui = gui,
title = title,
defaultValue = defaultValue.toString(),
parser = { string ->
Result.wrapCustomError<Long, Component>(
{ string.toLong() },
Component.translatable("minions.command.input.int.fail")
)
},
)
}
@JvmStatic
fun inputLongFuture(
gui: MinionsGui,
title: Component,
defaultValue: Long,
): CompletableFuture<Long?> {
return gui.scope.async {
inputLong(
gui,
title,
defaultValue
)
}.asCompletableFuture()
}
@JvmStatic
suspend fun inputDouble(
gui: MinionsGui,
title: Component,
defaultValue: Double,
): Double? {
return input<Double>(
gui = gui,
title = title,
defaultValue = defaultValue.toString(),
parser = { string ->
Result.wrapCustomError<Double, Component>(
{ string.toDouble() },
Component.translatable("minions.command.input.int.fail")
)
},
)
}
@JvmStatic
fun inputDoubleFuture(
gui: MinionsGui,
title: Component,
defaultValue: Double,
): CompletableFuture<Double?> {
return gui.scope.async {
inputDouble(
gui,
title,
defaultValue
)
}.asCompletableFuture()
} }
} }
} }
@@ -32,7 +32,7 @@ import java.util.concurrent.CompletableFuture;
public class InstructionGui { public class InstructionGui {
public static void openInstructionMainMenu(MinionsGui parent, GuiContext.Minion context) { public static void openInstructionMainMenu(MinionsGui parent, GuiContext.Minion context) {
new SimpleMinionsGui(parent, (onClose, me) -> { new SimpleMinionsGui(parent, (onClose, me) -> {
ServerPlayer player = parent.getViewer(); ServerPlayer player = parent.viewer;
SimpleGui gui = new SimpleGui(MenuType.GENERIC_3x3, player, false) { SimpleGui gui = new SimpleGui(MenuType.GENERIC_3x3, player, false) {
@Override @Override
@@ -61,7 +61,7 @@ public class InstructionGui {
public static void createNewInstruction(MinionsGui parent, GuiContext.Minion context) { public static void createNewInstruction(MinionsGui parent, GuiContext.Minion context) {
MinionFakePlayer minion = context.getMinion(); MinionFakePlayer minion = context.getMinion();
ServerPlayer viewer = parent.getViewer(); ServerPlayer viewer = parent.viewer;
selectInstructionModuleMenu(parent, context).thenAccept(instructionType -> selectInstructionModuleMenu(parent, context).thenAccept(instructionType ->
inputInstructionName(parent, context, "Instruction").thenAccept(name -> { inputInstructionName(parent, context, "Instruction").thenAccept(name -> {
if (!minion.isRemoved() && !minion.hasDisconnected()) { if (!minion.isRemoved() && !minion.hasDisconnected()) {
@@ -73,7 +73,7 @@ public class InstructionGui {
} }
public static CompletableFuture<String> inputInstructionName(MinionsGui parent, GuiContext.Minion context, String defaultValue) { public static CompletableFuture<String> inputInstructionName(MinionsGui parent, GuiContext.Minion context, String defaultValue) {
return TextInput.inputSync(parent, Component.translatable("minions.gui.instruction.enter_name"), defaultValue, name -> { return TextInput.inputFuture(parent, Component.translatable("minions.gui.instruction.enter_name"), defaultValue, name -> {
if (context.getMinion().getInstructionManager().hasInstruction(name)) { if (context.getMinion().getInstructionManager().hasInstruction(name)) {
return new Result.Error<>(Component.translatable("minions.gui.instruction.name_already_used")); return new Result.Error<>(Component.translatable("minions.gui.instruction.name_already_used"));
} }
@@ -92,7 +92,7 @@ public class InstructionGui {
public static CompletableFuture<InstructionType<MinionRuntime>> selectInstructionModuleMenu(MinionsGui parent, GuiContext.Minion context) { public static CompletableFuture<InstructionType<MinionRuntime>> selectInstructionModuleMenu(MinionsGui parent, GuiContext.Minion context) {
MinionFakePlayer minion = context.getMinion(); MinionFakePlayer minion = context.getMinion();
ServerPlayer viewer = parent.getViewer(); ServerPlayer viewer = parent.viewer;
if (minion.getModuleInventory().getModules().isEmpty()) { if (minion.getModuleInventory().getModules().isEmpty()) {
viewer.sendSystemMessage(Component.translatable("minions.gui.instruction.no_modules")); viewer.sendSystemMessage(Component.translatable("minions.gui.instruction.no_modules"));
@@ -137,7 +137,7 @@ public class InstructionGui {
CompletableFuture<InstructionType<MinionRuntime>> future = new CompletableFuture<>(); CompletableFuture<InstructionType<MinionRuntime>> future = new CompletableFuture<>();
new SimpleMinionsGui(parent, (closeHandler, me) -> { new SimpleMinionsGui(parent, (closeHandler, me) -> {
SimpleGui gui = new SimpleGui(MenuType.GENERIC_9x4, parent.getViewer(), false) { SimpleGui gui = new SimpleGui(MenuType.GENERIC_9x4, parent.viewer, false) {
@Override @Override
public void onPlayerClose(boolean success) { public void onPlayerClose(boolean success) {
if (!future.isDone()) { if (!future.isDone()) {
@@ -151,7 +151,7 @@ public class InstructionGui {
gui.setSlot(8, me.backButton()); gui.setSlot(8, me.backButton());
int slot = 9; int slot = 9;
for (InstructionType<MinionRuntime> instructionType : module.instructions()) { for (InstructionType<MinionRuntime> instructionType : module.instructions()) {
gui.setSlot(slot, createInstructionElement(instructionType, parent.getViewer().registryAccess()) gui.setSlot(slot, createInstructionElement(instructionType, parent.viewer.registryAccess())
.setCallback(() -> future.complete(instructionType)) .setCallback(() -> future.complete(instructionType))
); );
slot++; slot++;
@@ -51,17 +51,17 @@ public class MinionItem extends Item implements PolymerItem {
@Override @Override
public void appendHoverText(ItemStack stack, TooltipContext context, TooltipDisplay component, Consumer<Component> tooltip, TooltipFlag type) { public void appendHoverText(ItemStack stack, TooltipContext context, TooltipDisplay component, Consumer<Component> tooltip, TooltipFlag type) {
MinionData data = null /*getData(stack)*/; //MinionData data = getData(stack);
if(data != null) { //if(data != null) {
tooltip.accept(Component.translatable("minions.minion_item.tooltip", data.name())); // tooltip.accept(Component.translatable("minions.minion_item.tooltip", data.name()));
} //}
} }
@Override @Override
public InteractionResult use(Level world, Player user, InteractionHand hand) { public InteractionResult use(Level world, Player user, InteractionHand hand) {
if(user instanceof ServerPlayer serverPlayer) { if(user instanceof ServerPlayer serverPlayer) {
ItemStack stack = user.getItemInHand(hand); ItemStack stack = user.getItemInHand(hand);
MinionLookGui.open(serverPlayer, stack); new MinionLookGui(serverPlayer, stack);
return InteractionResult.SUCCESS; return InteractionResult.SUCCESS;
} }
@@ -79,7 +79,7 @@ public class AnalogInputSupplier implements ValueSupplier<Long, MinionRuntime> {
public <T> CompletableFuture<ValueSupplier<?, MinionRuntime>> openConfiguration(MinionsGui parent, ValueType<T> valueType, @Nullable ValueSupplier<?, MinionRuntime> previous) { public <T> CompletableFuture<ValueSupplier<?, MinionRuntime>> openConfiguration(MinionsGui parent, ValueType<T> valueType, @Nullable ValueSupplier<?, MinionRuntime> previous) {
CompletableFuture<ValueSupplier<?, MinionRuntime>> future = new CompletableFuture<>(); CompletableFuture<ValueSupplier<?, MinionRuntime>> future = new CompletableFuture<>();
new SimpleMinionsGui(parent, (onClose, me) -> { new SimpleMinionsGui(parent, (onClose, me) -> {
SimpleGui gui = new SimpleGui(MenuType.GENERIC_3x3, parent.getViewer(), false) { SimpleGui gui = new SimpleGui(MenuType.GENERIC_3x3, parent.viewer, false) {
@Override @Override
public void onPlayerClose(boolean success) { public void onPlayerClose(boolean success) {
onClose.run(); onClose.run();
@@ -90,7 +90,7 @@ public class AnalogInputSupplier implements ValueSupplier<Long, MinionRuntime> {
gui.setSlot(2, me.backButton()); gui.setSlot(2, me.backButton());
gui.setSlot(4, new GuiElementBuilder(MinionItems.REFERENCE_ITEM) gui.setSlot(4, new GuiElementBuilder(MinionItems.REFERENCE_ITEM)
.setCallback(() -> { .setCallback(() -> {
ItemStack cursor = parent.getViewer().containerMenu.getCarried(); ItemStack cursor = parent.viewer.containerMenu.getCarried();
if (cursor.is(MinionItems.REFERENCE_ITEM) && cursor.get(MinionComponentTypes.REFERENCE) instanceof BlockPosClipboard pos) { if (cursor.is(MinionItems.REFERENCE_ITEM) && cursor.get(MinionComponentTypes.REFERENCE) instanceof BlockPosClipboard pos) {
future.complete(new AnalogInputSupplier(pos.world(), pos.pos())); future.complete(new AnalogInputSupplier(pos.world(), pos.pos()));
me.goBack(); me.goBack();
@@ -5,6 +5,7 @@ import com.mojang.authlib.GameProfile;
import com.mojang.authlib.properties.Property; import com.mojang.authlib.properties.Property;
import com.mojang.authlib.properties.PropertyMap; import com.mojang.authlib.properties.PropertyMap;
import io.github.skippyall.minions.Minions; import io.github.skippyall.minions.Minions;
import io.github.skippyall.minions.gui.MinionsGui;
import net.fabricmc.fabric.api.entity.FakePlayer; import net.fabricmc.fabric.api.entity.FakePlayer;
import net.minecraft.core.Holder; import net.minecraft.core.Holder;
import net.minecraft.core.registries.Registries; import net.minecraft.core.registries.Registries;
@@ -22,7 +23,6 @@ import net.minecraft.server.dialog.Input;
import net.minecraft.server.dialog.NoticeDialog; import net.minecraft.server.dialog.NoticeDialog;
import net.minecraft.server.dialog.action.CustomAll; import net.minecraft.server.dialog.action.CustomAll;
import net.minecraft.server.dialog.input.TextInput; import net.minecraft.server.dialog.input.TextInput;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.item.component.ResolvableProfile; import net.minecraft.world.item.component.ResolvableProfile;
import java.util.HashMap; import java.util.HashMap;
@@ -39,9 +39,9 @@ public class Base64SkinProvider implements SkinProvider {
private static Map<Long, CompletableFuture<ResolvableProfile>> futures = new HashMap<>(); private static Map<Long, CompletableFuture<ResolvableProfile>> futures = new HashMap<>();
@Override @Override
public CompletableFuture<ResolvableProfile> openSkinMenu(ServerPlayer player) { public CompletableFuture<ResolvableProfile> openSkinMenu(MinionsGui parent) {
dialogIdCounter++; dialogIdCounter++;
player.openDialog(getDialog()); parent.viewer.openDialog(getDialog());
CompletableFuture<ResolvableProfile> future = new CompletableFuture<>(); CompletableFuture<ResolvableProfile> future = new CompletableFuture<>();
futures.put(dialogIdCounter, future); futures.put(dialogIdCounter, future);
return future; return future;
@@ -1,17 +1,17 @@
package io.github.skippyall.minions.minion.skin; package io.github.skippyall.minions.minion.skin;
import io.github.skippyall.minions.gui.MinionsGui;
import io.github.skippyall.minions.gui.input.TextInput; import io.github.skippyall.minions.gui.input.TextInput;
import net.minecraft.network.chat.Component; import net.minecraft.network.chat.Component;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.item.component.ResolvableProfile; import net.minecraft.world.item.component.ResolvableProfile;
import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletableFuture;
public class NameSkinProvider implements SkinProvider { public class NameSkinProvider implements SkinProvider {
@Override @Override
public CompletableFuture<ResolvableProfile> openSkinMenu(ServerPlayer player) { public CompletableFuture<ResolvableProfile> openSkinMenu(MinionsGui parent) {
return TextInput.inputString(player, Component.translatable("minions.gui.look.skin.name.title"), "") return TextInput.inputStringFuture(parent, Component.translatable("minions.gui.look.skin.name.title"), "")
.thenApply(ResolvableProfile::createUnresolved); .thenApply(name -> name != null ? ResolvableProfile.createUnresolved(name) : null);
} }
@Override @Override
@@ -1,13 +1,13 @@
package io.github.skippyall.minions.minion.skin; package io.github.skippyall.minions.minion.skin;
import io.github.skippyall.minions.gui.MinionsGui;
import net.minecraft.network.chat.Component; import net.minecraft.network.chat.Component;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.item.component.ResolvableProfile; import net.minecraft.world.item.component.ResolvableProfile;
import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletableFuture;
public interface SkinProvider { public interface SkinProvider {
CompletableFuture<ResolvableProfile> openSkinMenu(ServerPlayer player); CompletableFuture<ResolvableProfile> openSkinMenu(MinionsGui parent);
Component getDisplayName(); Component getDisplayName();
} }
@@ -1,17 +1,17 @@
package io.github.skippyall.minions.minion.skin; package io.github.skippyall.minions.minion.skin;
import io.github.skippyall.minions.gui.MinionsGui;
import io.github.skippyall.minions.gui.input.TextInput; import io.github.skippyall.minions.gui.input.TextInput;
import net.minecraft.network.chat.Component; import net.minecraft.network.chat.Component;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.item.component.ResolvableProfile; import net.minecraft.world.item.component.ResolvableProfile;
import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletableFuture;
public class UUIDSkinProvider implements SkinProvider { public class UUIDSkinProvider implements SkinProvider {
@Override @Override
public CompletableFuture<ResolvableProfile> openSkinMenu(ServerPlayer player) { public CompletableFuture<ResolvableProfile> openSkinMenu(MinionsGui parent) {
return TextInput.inputString(player, Component.translatable("minions.gui.look.skin.uuid.title"), "") return TextInput.inputStringFuture(parent, Component.translatable("minions.gui.look.skin.uuid.title"), "")
.thenApply(ResolvableProfile::createUnresolved); .thenApply(name -> name != null ? ResolvableProfile.createUnresolved(name) : null);
} }
@Override @Override
@@ -19,10 +19,10 @@ public class ValueTypes {
Codec.LONG, Codec.LONG,
0L, 0L,
o -> o instanceof Long l ? l : null, o -> o instanceof Long l ? l : null,
(parent, oldValue) -> TextInput.inputLong( (parent, oldValue) -> TextInput.inputLongFuture(
parent, parent,
Component.literal("Integer"), Component.literal("Integer"),
String.valueOf(oldValue) oldValue
), ),
value -> Component.literal(value.toString()) value -> Component.literal(value.toString())
) )
@@ -34,10 +34,10 @@ public class ValueTypes {
Codec.DOUBLE, Codec.DOUBLE,
0D, 0D,
o -> o instanceof Double d ? d : null, o -> o instanceof Double d ? d : null,
(parent, oldValue) -> TextInput.inputDouble( (parent, oldValue) -> TextInput.inputDoubleFuture(
parent, parent,
Component.literal("Number"), Component.literal("Number"),
String.valueOf(oldValue) oldValue
), ),
value -> Component.literal(value.toString()) value -> Component.literal(value.toString())
) )
@@ -61,11 +61,11 @@ public class ValueTypes {
Codec.STRING, Codec.STRING,
"", "",
o -> o instanceof String s ? s : null, o -> o instanceof String s ? s : null,
((parent, oldValue) -> TextInput.inputString( ((parent, oldValue) -> TextInput.inputStringFuture(
parent, parent,
Component.literal("Text"), Component.literal("Text"),
oldValue) oldValue
), )),
value -> Component.literal("\"" + value + "\"") value -> Component.literal("\"" + value + "\"")
) )
); );