2 Commits

Author SHA1 Message Date
skippyall f3c934c619 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
2026-05-02 10:48:13 +02:00
skippyall 71016f9e70 Rename .java to .kt 2026-05-02 10:48:13 +02:00
15 changed files with 476 additions and 333 deletions
@@ -1,98 +0,0 @@
package io.github.skippyall.minions.gui;
import com.mojang.authlib.GameProfile;
import eu.pb4.sgui.api.elements.GuiElementBuilder;
import eu.pb4.sgui.api.gui.SimpleGui;
import io.github.skippyall.minions.gui.input.TextInput;
import io.github.skippyall.minions.minion.MinionData;
import io.github.skippyall.minions.minion.MinionItem;
import io.github.skippyall.minions.minion.MinionProfileUtils;
import io.github.skippyall.minions.minion.skin.SkinProvider;
import io.github.skippyall.minions.registration.MinionRegistries;
import io.github.skippyall.minions.registration.SkinProviders;
import net.fabricmc.fabric.api.entity.FakePlayer;
import net.minecraft.core.component.DataComponents;
import net.minecraft.network.chat.Component;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.inventory.MenuType;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Items;
import net.minecraft.world.item.component.ResolvableProfile;
import java.util.Optional;
public class MinionLookGui extends SimpleGui {
private ItemStack minionItem;
private SkinProvider currentSkinProvider;
public MinionLookGui(ServerPlayer player, ItemStack minionItem) {
super(MenuType.GENERIC_9x3, player, false);
this.minionItem = minionItem;
this.currentSkinProvider = SkinProviders.NAME;
}
public void update() {
updateName();
updateSkin();
updateSkinProvider();
}
private void updateName() {
setSlot(10, new GuiElementBuilder()
.setItem(Items.OAK_SIGN)
.setName(Component.literal(getData().name()))
.setCallback(() -> {
openRenameGui(player, minionItem);
})
);
}
private void updateSkin() {
GuiElementBuilder builder = new GuiElementBuilder()
.setItem(Items.PLAYER_HEAD)
.setCallback(() -> currentSkinProvider.openSkinMenu(player)
.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(player.level().getServer(), minionItem) != null && MinionItem.getData(player.level().getServer(), minionItem).skin().isPresent()) {
builder.setComponent(DataComponents.PROFILE, ResolvableProfile.createResolved(new GameProfile(FakePlayer.DEFAULT_UUID, "", getData().skin().get())));
}
setSlot(16, builder);
}
private void cycleSkinProvider() {
int currentId = MinionRegistries.SKIN_PROVIDERS.getId(currentSkinProvider);
currentId++;
if(MinionRegistries.SKIN_PROVIDERS.size() == currentId) {
currentId = 0;
}
currentSkinProvider = MinionRegistries.SKIN_PROVIDERS.byId(currentId);
updateSkinProvider();
}
private void updateSkinProvider() {
setSlot(25, new GuiElementBuilder()
.setItem(Items.GREEN_STAINED_GLASS_PANE)
.setComponent(DataComponents.CUSTOM_NAME, currentSkinProvider.getDisplayName())
.setCallback(this::cycleSkinProvider)
);
}
private MinionData getData() {
return MinionItem.getDataOrDefault(player.level().getServer(), minionItem);
}
public static void open(ServerPlayer player, ItemStack minionItem) {
MinionLookGui gui = new MinionLookGui(player, minionItem);
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();
});
}
}
@@ -0,0 +1,136 @@
package io.github.skippyall.minions.gui
import com.mojang.authlib.GameProfile
import eu.pb4.sgui.api.elements.GuiElementBuilder
import eu.pb4.sgui.api.gui.SimpleGui
import io.github.skippyall.minions.gui.input.TextInput
import io.github.skippyall.minions.minion.MinionData
import io.github.skippyall.minions.minion.MinionItem
import io.github.skippyall.minions.minion.MinionProfileUtils
import io.github.skippyall.minions.minion.skin.SkinProvider
import io.github.skippyall.minions.registration.MinionRegistries
import io.github.skippyall.minions.registration.SkinProviders
import kotlinx.coroutines.launch
import net.fabricmc.fabric.api.entity.FakePlayer
import net.minecraft.core.component.DataComponents
import net.minecraft.network.chat.Component
import net.minecraft.server.level.ServerPlayer
import net.minecraft.world.inventory.MenuType
import net.minecraft.world.item.ItemStack
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
class MinionLookGui(
viewer: ServerPlayer,
private val minionItem: ItemStack
) : MinionsGui(viewer) {
private lateinit var gui: SimpleGui
private var currentSkinProvider: SkinProvider = SkinProviders.NAME
private val data: MinionData
get() = MinionItem.getDataOrDefault(viewer.level().server, minionItem)
init {
open()
}
override fun open() {
gui = object : SimpleGui(MenuType.GENERIC_9x3, viewer, false) {
override fun onPlayerClose(success: Boolean) {
onBackingClosed()
}
}
update()
gui.open()
}
override fun closeBacking() {
gui.close()
}
fun update() {
updateName()
updateSkin()
updateSkinProvider()
}
private fun updateName() {
gui.setSlot(
10, GuiElementBuilder()
.setItem(Items.OAK_SIGN)
.setName(Component.literal(this.data.name))
.setCallback(this::openRenameGui)
)
}
private fun updateSkin() {
val builder = GuiElementBuilder()
.setItem(Items.PLAYER_HEAD)
.setCallback(this::openSkinGui)
if (MinionItem.getData(viewer.level().server, minionItem)?.skin?.isPresent ?: false) {
builder.setComponent(
DataComponents.PROFILE,
ResolvableProfile.createResolved(GameProfile(FakePlayer.DEFAULT_UUID, "", this.data.skin.get()))
)
}
gui.setSlot(16, builder)
}
fun openSkinGui() {
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 fun cycleSkinProvider() {
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)
.setComponent(DataComponents.CUSTOM_NAME, currentSkinProvider.getDisplayName())
.setCallback(Runnable { this.cycleSkinProvider() })
)
}
fun openRenameGui() {
scope.launch {
val newName = TextInput.input(
this@MinionLookGui,
Component.translatable("minions.gui.look.rename.title"),
"Minion",
) { name ->
MinionProfileUtils.checkMinionNameWithoutPrefix(viewer.level().server, name)
}
if(newName != null) {
this@MinionLookGui.data.withName(newName)
}
}
}
}
@@ -1,76 +0,0 @@
package io.github.skippyall.minions.gui;
import eu.pb4.sgui.api.elements.GuiElementBuilder;
import net.minecraft.network.chat.Component;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.item.Items;
import org.jetbrains.annotations.Nullable;
public abstract class MinionsGui {
protected final @Nullable MinionsGui parent;
protected final ServerPlayer viewer;
protected @Nullable MinionsGui child = null;
private boolean open = true;
public MinionsGui(MinionsGui parent) {
this.viewer = parent.viewer;
this.parent = parent;
parent.child = this;
}
public MinionsGui(ServerPlayer viewer) {
this.viewer = viewer;
this.parent = null;
}
public ServerPlayer getViewer() {
return viewer;
}
protected abstract void open();
protected void reopen() {
open();
}
public void onBackingClosed() {
if(child != null && child.open) {
return;
}
close(true);
}
public void close() {
close(false);
}
public void close(boolean alreadyClosed) {
if(open) {
open = false;
if(child != null) {
child.close(alreadyClosed);
} else if(!alreadyClosed) {
closeBacking();
}
}
}
public void goBack() {
if(parent != null) {
open = false;
parent.child = null;
parent.reopen();
} else {
close(false);
}
}
public GuiElementBuilder backButton() {
return new GuiElementBuilder(Items.MANGROVE_DOOR)
.setName(Component.translatable("gui.back"))
.setCallback(this::goBack);
}
protected abstract void closeBacking();
}
@@ -0,0 +1,84 @@
package io.github.skippyall.minions.gui
import eu.pb4.sgui.api.elements.GuiElementBuilder
import kotlinx.coroutines.CompletableJob
import kotlinx.coroutines.CoroutineName
import kotlinx.coroutines.CoroutineScope
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
abstract class MinionsGui {
protected val parent: MinionsGui?
@JvmField
val viewer: ServerPlayer
protected var child: MinionsGui? = null
private var open = true
private val job: CompletableJob
val scope: CoroutineScope
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))
}
constructor(viewer: ServerPlayer) {
this.viewer = viewer
this.parent = null
job = Job(null)
scope = CoroutineScope(Dispatchers.Unconfined.plus(CoroutineName("MinionsGui")).plus(job))
}
protected abstract fun open()
protected fun reopen() {
open()
}
fun onBackingClosed() {
if (child != null && child!!.open) {
return
}
close(true)
}
@JvmOverloads
fun close(alreadyClosed: Boolean = false) {
if (open) {
scope.cancel(null)
open = false
if (child != null) {
child!!.close(alreadyClosed)
} else if (!alreadyClosed) {
closeBacking()
}
}
}
fun goBack() {
if (parent != null) {
open = false
parent.child = null
parent.reopen()
close(true)
} else {
close(false)
}
}
fun backButton(): GuiElementBuilder? {
return GuiElementBuilder(Items.MANGROVE_DOOR)
.setName(Component.translatable("gui.back"))
.setCallback(Runnable { this.goBack() })
}
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 +0,0 @@
package io.github.skippyall.minions.gui.input;
import eu.pb4.sgui.api.elements.GuiElementBuilder;
import eu.pb4.sgui.api.gui.AnvilInputGui;
import io.github.skippyall.minions.gui.MinionsGui;
import io.github.skippyall.minions.gui.minion.SimpleMinionsGui;
import net.minecraft.network.chat.Component;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.inventory.AnvilMenu;
import net.minecraft.world.item.Items;
import java.util.concurrent.CompletableFuture;
import java.util.function.Function;
public class TextInput<T> extends AnvilInputGui {
private final GuiElementBuilder valid = new GuiElementBuilder()
.setItem(Items.EMERALD_BLOCK)
.setName(Component.literal("OK"))
.setCallback(this::onConfirm);
private final GuiElementBuilder invalid = new GuiElementBuilder()
.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) {
super(player, false);
setTitle(title);
setDefaultInputValue(defaultValue);
this.parser = parser;
this.future = future;
updateConfirmButton(defaultValue);
}
public static <T> CompletableFuture<T> inputSync(ServerPlayer player, Component title, String defaultValue, Function<String, Result<T, Component>> parser) {
return input(player, title, defaultValue, (String string) -> CompletableFuture.completedFuture(parser.apply(string)));
}
public static <T> CompletableFuture<T> inputSync(MinionsGui gui, Component title, String defaultValue, Function<String, Result<T, Component>> parser) {
return input(gui, title, defaultValue, (String string) -> CompletableFuture.completedFuture(parser.apply(string)));
}
public static <T> CompletableFuture<T> input(ServerPlayer player, Component title, String defaultValue, Function<String, CompletableFuture<Result<T, Component>>> parser) {
CompletableFuture<T> future = new CompletableFuture<>();
new TextInput<>(player, title, defaultValue, parser, future).open();
return future;
}
public static <T> CompletableFuture<T> input(MinionsGui gui, Component title, String defaultValue, Function<String, CompletableFuture<Result<T, Component>>> parser) {
CompletableFuture<T> future = new CompletableFuture<>();
new SimpleMinionsGui(gui, (onClose, me) -> {
TextInput<T> input = new TextInput<>(gui.getViewer(), title, defaultValue, parser, future);
future.whenComplete((v, e) -> {
if(e != null) {
onClose.run();
} else {
me.goBack();
}
});
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() {
if(result != null) {
result.ifSuccess(success -> {
isConfirm = true;
future.complete(success);
});
}
}
}
@@ -0,0 +1,222 @@
package io.github.skippyall.minions.gui.input
import eu.pb4.sgui.api.elements.GuiElementBuilder
import eu.pb4.sgui.api.gui.AnvilInputGui
import io.github.skippyall.minions.gui.MinionsGui
import kotlinx.coroutines.Job
import kotlinx.coroutines.async
import kotlinx.coroutines.future.asCompletableFuture
import kotlinx.coroutines.launch
import net.minecraft.network.chat.Component
import net.minecraft.world.inventory.AnvilMenu
import net.minecraft.world.item.Items
import java.util.concurrent.CompletableFuture
class TextInput<T>(
parent: MinionsGui,
val title: Component,
val defaultValue: String,
val parser: suspend (String) -> Result<T, Component>
) : MinionsGui(parent) {
private val valid: GuiElementBuilder = GuiElementBuilder()
.setItem(Items.EMERALD_BLOCK)
.setName(Component.literal("OK"))
.setCallback(Runnable { this.onConfirm() })
private val invalid: GuiElementBuilder = GuiElementBuilder()
.setItem(Items.REDSTONE_BLOCK)
private lateinit var gui: AnvilInputGui
private var result: Result<T, Component>? = null
private var isConfirm = false
val job = Job()
init {
updateConfirmButton(defaultValue)
open()
}
override fun open() {
gui = object : AnvilInputGui(viewer, false) {
override fun onInput(input: String) {
updateConfirmButton(input)
}
override fun onPlayerClose(success: Boolean) {
onBackingClosed()
if (job.isActive && !isConfirm) {
job.cancel()
}
}
}
gui.setTitle(title)
gui.setDefaultInputValue(defaultValue)
gui.open()
}
override fun closeBacking() {
gui.close()
}
fun updateConfirmButton(input: String) {
scope.launch {
val result = parser(input)
this@TextInput.result = result
if (result.isSuccess()) {
gui.setSlot(AnvilMenu.RESULT_SLOT, valid)
} else {
val text = result.getErrorOrThrow()
gui.setSlot(AnvilMenu.RESULT_SLOT, invalid.setName(text))
}
}
}
fun onConfirm() {
result?.ifSuccess { _: T? ->
isConfirm = true
}
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 + "\"")
) )
); );