4 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
skippyall 08f9763b83 Go Back! 2026-04-30 23:56:21 +02:00
skippyall e117139a63 Port to 26.1 2026-04-29 17:20:13 +02:00
105 changed files with 1134 additions and 886 deletions
-138
View File
@@ -1,138 +0,0 @@
plugins {
id 'net.fabricmc.fabric-loom-remap' version '1.16-SNAPSHOT'
id 'maven-publish'
}
version = project.mod_version
group = project.maven_group
base {
archivesName = project.archives_base_name
}
loom {
accessWidenerPath = file("src/main/resources/minions.accesswidener")
splitEnvironmentSourceSets()
mods {
minions {
sourceSet sourceSets.main
sourceSet sourceSets.client
}
}
runs.forEach {
it.vmArg("-XX:+AllowEnhancedClassRedefinition")
}
}
repositories {
// Add repositories to retrieve artifacts from in here.
// You should only use this when depending on other mods because
// Loom adds the essential maven repositories to download Minecraft and libraries from automatically.
// See https://docs.gradle.org/current/userguide/declaring_repositories.html
// for more information about repositories.
maven { url 'https://maven.nucleoid.xyz' }
exclusiveContent {
forRepository {
maven {
name = "Modrinth"
url = "https://api.modrinth.com/maven"
}
}
filter {
includeGroup "maven.modrinth"
}
}
}
dependencies {
// To change the versions see the gradle.properties file
minecraft "com.mojang:minecraft:${project.minecraft_version}"
mappings loom.officialMojangMappings()
modImplementation "net.fabricmc:fabric-loader:${project.loader_version}"
// Fabric API. This is technically optional, but you probably want it anyway.
modImplementation "net.fabricmc.fabric-api:fabric-api:${project.fabric_version}"
modImplementation "eu.pb4:polymer-core:${project.polymer_version}"
modImplementation "eu.pb4:polymer-virtual-entity:${project.polymer_version}"
modImplementation "eu.pb4:polymer-resource-pack:${project.polymer_version}"
modLocalRuntime "eu.pb4:polymer-autohost:${project.polymer_version}"
modImplementation include("eu.pb4:sgui:${project.sgui_version}")
modImplementation include("xyz.nucleoid:server-translations-api:${project.server_translations_version}")
implementation include("com.electronwill.night-config:toml:${project.night_config_version}")
modCompileOnly "maven.modrinth:universal-graves:${project.universal_graves_version}"
}
processResources {
inputs.property "version", project.version
inputs.property "minecraft_version", project.minecraft_version
inputs.property "loader_version", project.loader_version
filteringCharset "UTF-8"
filesMatching("fabric.mod.json") {
expand "version": project.version,
"minecraft_version": project.minecraft_version,
"loader_version": project.loader_version
}
}
def targetJavaVersion = 21
tasks.withType(JavaCompile).configureEach {
// ensure that the encoding is set to UTF-8, no matter what the system default is
// this fixes some edge cases with special characters not displaying correctly
// see http://yodaconditions.net/blog/fix-for-java-file-encoding-problems-with-gradle.html
// If Javadoc is generated, this must be specified in that task too.
it.options.encoding = "UTF-8"
if (targetJavaVersion >= 10 || JavaVersion.current().isJava10Compatible()) {
it.options.release.set(targetJavaVersion)
}
}
java {
def javaVersion = JavaVersion.toVersion(targetJavaVersion)
if (JavaVersion.current() < javaVersion) {
toolchain.languageVersion = JavaLanguageVersion.of(targetJavaVersion)
}
// Loom will automatically attach sourcesJar to a RemapSourcesJar task and to the "build" task
// if it is present.
// If you remove this line, sources will not be generated.
withSourcesJar()
}
jar {
from("LICENSE") {
rename { "${it}_${project.archives_base_name}"}
}
from("src/main/resoures/assets/minions/lang") {
include("*")
into("data/minions/lang/")
}
}
// configure the maven publication
publishing {
publications {
maven (MavenPublication) {
from components.java
}
}
// See https://docs.gradle.org/current/userguide/publishing_maven.html for information on how to set up publishing.
repositories {
// Add repositories to publish to here.
// Notice: This block does NOT have the same function as the block in the top level.
// The repositories here will be used for publishing your artifact, not for
// retrieving dependencies.
maven {
name = "foxgalaxy"
url = "https://maven.foxgalaxy.de/private"
credentials(PasswordCredentials)
}
}
}
+128
View File
@@ -0,0 +1,128 @@
import org.jetbrains.kotlin.gradle.dsl.JvmTarget
plugins {
id("net.fabricmc.fabric-loom")
`maven-publish`
id("org.jetbrains.kotlin.jvm") version "2.3.21"
}
version = providers.gradleProperty("mod_version").get()
group = providers.gradleProperty("maven_group").get()
repositories {
// Add repositories to retrieve artifacts from in here.
// You should only use this when depending on other mods because
// Loom adds the essential maven repositories to download Minecraft and libraries from automatically.
// See https://docs.gradle.org/current/userguide/declaring_repositories.html
// for more information about repositories.
maven("https://maven.nucleoid.xyz")
exclusiveContent {
forRepository {
maven ("https://api.modrinth.com/maven")
}
filter {
includeGroup("maven.modrinth")
}
}
}
loom {
splitEnvironmentSourceSets()
mods {
register("minions") {
sourceSet(sourceSets.main.get())
sourceSet(sourceSets.getByName("client"))
}
}
for (settings in runs) {
settings.vmArg("-XX:+AllowEnhancedClassRedefinition")
}
accessWidenerPath = file("src/main/resources/minions.classtweaker")
}
dependencies {
// To change the versions see the gradle.properties file
minecraft("com.mojang:minecraft:${providers.gradleProperty("minecraft_version").get()}")
implementation("net.fabricmc:fabric-loader:${providers.gradleProperty("loader_version").get()}")
// Fabric API. This is technically optional, but you probably want it anyway.
implementation("net.fabricmc.fabric-api:fabric-api:${providers.gradleProperty("fabric_api_version").get()}")
implementation("net.fabricmc:fabric-language-kotlin:${providers.gradleProperty("fabric_kotlin_version").get()}")
val polymer_version = providers.gradleProperty("polymer_version").get()
implementation("eu.pb4:polymer-core:${polymer_version}")
implementation("eu.pb4:polymer-virtual-entity:${polymer_version}")
implementation("eu.pb4:polymer-resource-pack:${polymer_version}")
localRuntime("eu.pb4:polymer-autohost:${polymer_version}")
implementation("eu.pb4:sgui:${providers.gradleProperty("sgui_version").get()}")
implementation("xyz.nucleoid:server-translations-api:${providers.gradleProperty("server_translations_version").get()}")
implementation("com.electronwill.night-config:toml:${providers.gradleProperty("night_config_version").get()}")
compileOnly("maven.modrinth:universal-graves:${providers.gradleProperty("universal_graves_version").get()}")
}
tasks.processResources {
val version = version
inputs.property("version", version)
filesMatching("fabric.mod.json") {
expand("version" to version)
}
}
tasks.withType<JavaCompile>().configureEach {
options.release = 25
}
kotlin {
compilerOptions {
jvmTarget = JvmTarget.JVM_25
}
}
java {
// Loom will automatically attach sourcesJar to a RemapSourcesJar task and to the "build" task
// if it is present.
// If you remove this line, sources will not be generated.
withSourcesJar()
sourceCompatibility = JavaVersion.VERSION_25
targetCompatibility = JavaVersion.VERSION_25
}
tasks.jar {
val projectName = project.name
inputs.property("projectName", projectName)
from("LICENSE") {
rename { "${it}_$projectName" }
}
}
// configure the maven publication
publishing {
publications {
register<MavenPublication>("mavenJava") {
from(components["java"])
}
}
// See https://docs.gradle.org/current/userguide/publishing_maven.html for information on how to set up publishing.
repositories {
// Add repositories to publish to here.
// Notice: This block does NOT have the same function as the block in the top level.
// The repositories here will be used for publishing your artifact, not for
// retrieving dependencies.
maven("https://maven.foxgalaxy.de/private") {
name = "foxgalaxy"
credentials(PasswordCredentials::class.java)
}
}
}
+9 -8
View File
@@ -3,9 +3,9 @@ org.gradle.jvmargs=-Xmx1G
# Fabric Properties
# check these on https://modmuss50.me/fabric.html
minecraft_version=1.21.7
loader_version=0.16.14
yarn_mappings=1.21.7+build.2
loom_version=1.16-SNAPSHOT
minecraft_version=26.1.2
loader_version=0.19.2
# Mod Properties
mod_version = 1.0.0-TEST-1
@@ -14,12 +14,13 @@ org.gradle.jvmargs=-Xmx1G
# Dependencies
# check this on https://modmuss50.me/fabric.html
fabric_version=0.128.1+1.21.7
fabric_api_version=0.147.0+26.1.2
fabric_kotlin_version=1.13.11+kotlin.2.3.21
polymer_version=0.13.3+1.21.6
sgui_version=1.10.0+1.21.6
server_translations_version=2.5.1+1.21.5
polymer_version=0.16.3+26.1.2
sgui_version=2.0.0+26.1
server_translations_version=3.0.3+26.1
night_config_version=3.8.3
universal_graves_version=3.8.0+1.21.6
universal_graves_version=3.11.0+26.1.2
-9
View File
@@ -1,9 +0,0 @@
pluginManagement {
repositories {
maven {
name = 'Fabric'
url = 'https://maven.fabricmc.net/'
}
gradlePluginPortal()
}
}
+17
View File
@@ -0,0 +1,17 @@
pluginManagement {
repositories {
maven {
name = "Fabric"
url = uri("https://maven.fabricmc.net/")
}
mavenCentral()
gradlePluginPortal()
}
plugins {
id("net.fabricmc.fabric-loom") version providers.gradleProperty("loom_version")
}
}
// Should match your modid
rootProject.name = "minions"
@@ -2,16 +2,11 @@ package io.github.skippyall.minions.client;
import eu.pb4.polymer.networking.api.client.PolymerClientNetworking;
import io.github.skippyall.minions.polymer.VersionSync;
import io.github.skippyall.minions.registration.MinionBlocks;
import net.fabricmc.api.ClientModInitializer;
import net.fabricmc.fabric.api.client.rendering.v1.BlockRenderLayerMap;
import net.minecraft.client.renderer.chunk.ChunkSectionLayer;
public class MinionsClient implements ClientModInitializer {
@Override
public void onInitializeClient() {
BlockRenderLayerMap.putBlock(MinionBlocks.MINION_TRIGGER_BLOCK, ChunkSectionLayer.TRANSLUCENT);
PolymerClientNetworking.registerCommonHandler(VersionSync.VersionSyncPayload.class, (client, handler, payload) -> {});
}
}
@@ -16,7 +16,7 @@ public class AnalogInputBlock extends Block {
@Override
protected InteractionResult useWithoutItem(BlockState state, Level world, BlockPos pos, Player player, BlockHitResult hit) {
if(!world.isClientSide) {
if(!world.isClientSide()) {
player.getInventory().placeItemBackInInventory(ClipboardItem.createBlockPosReference(world, pos), true);
}
return InteractionResult.SUCCESS;
@@ -7,7 +7,9 @@ import io.github.skippyall.minions.registration.MinionBlocks;
import io.github.skippyall.minions.registration.MinionComponentTypes;
import net.minecraft.core.BlockPos;
import net.minecraft.network.chat.Component;
import net.minecraft.network.protocol.game.ClientboundSoundPacket;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.sounds.SoundEvents;
import net.minecraft.sounds.SoundSource;
import net.minecraft.world.InteractionHand;
@@ -30,10 +32,10 @@ public abstract class InstructionBoundBlock extends Block implements EntityBlock
@Override
protected InteractionResult useItemOn(ItemStack stack, BlockState state, Level world, BlockPos pos, Player player, InteractionHand hand, BlockHitResult hit) {
if(stack.get(MinionComponentTypes.REFERENCE) instanceof InstructionClipboard instruction) {
if(stack.get(MinionComponentTypes.REFERENCE) instanceof InstructionClipboard instruction && player instanceof ServerPlayer serverPlayer) {
world.getBlockEntity(pos, getBlockEntityType()).ifPresent(be -> {
be.setInstruction(instruction.selectedMinion(), instruction.selectedInstruction());
player.playNotifySound(SoundEvents.NOTE_BLOCK_CHIME.value(), SoundSource.BLOCKS, 1, 1);
serverPlayer.connection.send(new ClientboundSoundPacket(SoundEvents.NOTE_BLOCK_CHIME, SoundSource.BLOCKS, pos.getX(), pos.getY(), pos.getZ(), 1, 1, 0));
stack.shrink(1);
});
return InteractionResult.SUCCESS;
@@ -50,7 +52,7 @@ public abstract class InstructionBoundBlock extends Block implements EntityBlock
world.getBlockEntity(pos, getBlockEntityType()).ifPresent(be -> {
String name = MinionPersistentState.get(world.getServer()).getMinionData(be.getMinionUuid()).name();
player.displayClientMessage(Component.translatable("minions.reference.instruction.tooltip", name, be.getInstructionName()), true);
player.sendSystemMessage(Component.translatable("minions.reference.instruction.tooltip", be.getInstructionName(), name));
});
return InteractionResult.SUCCESS;
}
@@ -4,14 +4,15 @@ import io.github.skippyall.minions.listener.BlockEntityMinionListener;
import io.github.skippyall.minions.minion.MinionRuntime;
import io.github.skippyall.minions.minion.fakeplayer.MinionFakePlayer;
import io.github.skippyall.minions.program.instruction.ConfiguredInstruction;
import java.util.Optional;
import java.util.UUID;
import net.minecraft.core.BlockPos;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.entity.BlockEntityType;
import net.minecraft.world.level.block.state.BlockState;
import java.util.Optional;
import java.util.UUID;
public abstract class InstructionBoundBlockEntity<L extends BlockEntityMinionListener<?>> extends BlockEntity {
protected UUID minionUuid;
protected String instructionName = "";
@@ -27,7 +28,9 @@ public abstract class InstructionBoundBlockEntity<L extends BlockEntityMinionLis
public void removeListener() {
if(level instanceof ServerLevel serverWorld) {
L listener = getListener();
listener.remove(serverWorld.getServer());
if(listener != null) {
listener.remove(serverWorld.getServer());
}
}
}
@@ -3,7 +3,6 @@ package io.github.skippyall.minions.block.miniontrigger;
import com.mojang.serialization.MapCodec;
import eu.pb4.polymer.core.api.block.PolymerBlock;
import eu.pb4.polymer.core.api.utils.PolymerClientDecoded;
import eu.pb4.polymer.core.api.utils.PolymerKeepModel;
import eu.pb4.polymer.resourcepack.api.PolymerResourcePackUtils;
import eu.pb4.polymer.virtualentity.api.BlockWithElementHolder;
import eu.pb4.polymer.virtualentity.api.ElementHolder;
@@ -12,10 +11,11 @@ import io.github.skippyall.minions.Minions;
import io.github.skippyall.minions.block.instruction_bound.InstructionBoundBlock;
import io.github.skippyall.minions.polymer.VersionSync;
import io.github.skippyall.minions.registration.MinionBlocks;
import net.fabricmc.fabric.api.networking.v1.context.PacketContext;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.core.component.DataComponents;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.resources.Identifier;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.server.network.ServerGamePacketListenerImpl;
@@ -37,9 +37,8 @@ import net.minecraft.world.level.redstone.Orientation;
import net.minecraft.world.phys.shapes.CollisionContext;
import net.minecraft.world.phys.shapes.VoxelShape;
import org.jetbrains.annotations.Nullable;
import xyz.nucleoid.packettweaker.PacketContext;
public class MinionTriggerBlock extends InstructionBoundBlock implements PolymerBlock, PolymerKeepModel, PolymerClientDecoded, BlockWithElementHolder {
public class MinionTriggerBlock extends InstructionBoundBlock implements PolymerBlock, PolymerClientDecoded, BlockWithElementHolder {
public static final MapCodec<MinionTriggerBlock> CODEC = simpleCodec(MinionTriggerBlock::new);
public static final BooleanProperty POWERED = BooleanProperty.create("powered");
@@ -91,7 +90,7 @@ public class MinionTriggerBlock extends InstructionBoundBlock implements Polymer
}
@Override
protected int getAnalogOutputSignal(BlockState state, Level world, BlockPos pos) {
protected int getAnalogOutputSignal(BlockState state, Level world, BlockPos pos, Direction direction) {
return world.getBlockEntity(pos, MinionBlocks.MINION_TRIGGER_BE_TYPE).map(MinionTriggerBlockEntity::getComparatorOutput).orElse(0);
}
@@ -128,7 +127,7 @@ public class MinionTriggerBlock extends InstructionBoundBlock implements Polymer
}
};
ItemStack stack = new ItemStack(Items.BARRIER);
stack.set(DataComponents.ITEM_MODEL, ResourceLocation.fromNamespaceAndPath(Minions.MOD_ID, "minion_trigger_no_plate_" + (initialBlockState.getValue(MinionTriggerBlock.POWERED) ? "active" : "inactive")));
stack.set(DataComponents.ITEM_MODEL, Identifier.fromNamespaceAndPath(Minions.MOD_ID, "minion_trigger_no_plate_" + (initialBlockState.getValue(MinionTriggerBlock.POWERED) ? "active" : "inactive")));
ItemDisplayElement element = new ItemDisplayElement(stack);
element.setItemDisplayContext(ItemDisplayContext.NONE);
@@ -2,12 +2,13 @@ package io.github.skippyall.minions.block.miniontrigger;
import eu.pb4.polymer.core.api.item.PolymerBlockItem;
import eu.pb4.polymer.resourcepack.api.PolymerResourcePackUtils;
import net.minecraft.resources.ResourceLocation;
import net.fabricmc.fabric.api.networking.v1.context.PacketContext;
import net.minecraft.core.HolderLookup;
import net.minecraft.resources.Identifier;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.block.Block;
import org.jetbrains.annotations.Nullable;
import xyz.nucleoid.packettweaker.PacketContext;
public class MinionTriggerBlockItem extends PolymerBlockItem {
public MinionTriggerBlockItem(Block block, Properties settings, Item polymerItem) {
@@ -15,9 +16,9 @@ public class MinionTriggerBlockItem extends PolymerBlockItem {
}
@Override
public @Nullable ResourceLocation getPolymerItemModel(ItemStack stack, PacketContext context) {
public @Nullable Identifier getPolymerItemModel(ItemStack stack, PacketContext context, HolderLookup.Provider lookup) {
if(PolymerResourcePackUtils.hasMainPack(context)) {
return super.getPolymerItemModel(stack, context);
return super.getPolymerItemModel(stack, context, lookup);
} else {
return null;
}
@@ -11,10 +11,11 @@ import io.github.skippyall.minions.program.instruction.ConfiguredInstructionList
import io.github.skippyall.minions.registration.MinionBlocks;
import net.minecraft.core.BlockPos;
import net.minecraft.core.UUIDUtil;
import net.minecraft.resources.Identifier;
import net.minecraft.resources.ResourceKey;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.MinecraftServer;
import net.minecraft.world.level.Level;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
@@ -82,8 +83,8 @@ public class MinionTriggerMinionListener extends BlockEntityMinionInstructionLis
}
@Override
public Optional<ResourceLocation> getCodecId() {
return Optional.of(ResourceLocation.fromNamespaceAndPath(Minions.MOD_ID, "minion_trigger"));
public Optional<Identifier> getCodecId() {
return Optional.of(Identifier.fromNamespaceAndPath(Minions.MOD_ID, "minion_trigger"));
}
public void updateComparatorsIfLoaded(MinecraftServer server) {
@@ -2,7 +2,6 @@ package io.github.skippyall.minions.clipboard;
import com.mojang.serialization.MapCodec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import java.util.function.Consumer;
import net.minecraft.core.BlockPos;
import net.minecraft.core.component.DataComponentGetter;
import net.minecraft.network.chat.Component;
@@ -11,6 +10,8 @@ import net.minecraft.world.item.Item;
import net.minecraft.world.item.TooltipFlag;
import net.minecraft.world.level.Level;
import java.util.function.Consumer;
public record BlockPosClipboard(ResourceKey<Level> world, BlockPos pos) implements Clipboard {
public static final MapCodec<BlockPosClipboard> CODEC = RecordCodecBuilder.mapCodec(instance ->
instance.group(
@@ -3,9 +3,10 @@ package io.github.skippyall.minions.clipboard;
import com.mojang.serialization.Codec;
import com.mojang.serialization.MapCodec;
import io.github.skippyall.minions.registration.MinionRegistries;
import java.util.function.Function;
import net.minecraft.world.item.component.TooltipProvider;
import java.util.function.Function;
public interface Clipboard extends TooltipProvider {
Codec<Clipboard> CODEC = MinionRegistries.CLIPBOARD_TYPES.byNameCodec().dispatch(Clipboard::getCodec, Function.identity());
@@ -4,16 +4,17 @@ import eu.pb4.polymer.core.api.item.PolymerItem;
import io.github.skippyall.minions.minion.fakeplayer.MinionFakePlayer;
import io.github.skippyall.minions.registration.MinionComponentTypes;
import io.github.skippyall.minions.registration.MinionItems;
import net.fabricmc.fabric.api.networking.v1.context.PacketContext;
import net.minecraft.core.BlockPos;
import net.minecraft.core.HolderLookup;
import net.minecraft.core.component.DataComponents;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.resources.Identifier;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Items;
import net.minecraft.world.item.TooltipFlag;
import net.minecraft.world.level.Level;
import org.jetbrains.annotations.Nullable;
import xyz.nucleoid.packettweaker.PacketContext;
public class ClipboardItem extends Item implements PolymerItem {
public ClipboardItem(Properties settings) {
@@ -26,20 +27,20 @@ public class ClipboardItem extends Item implements PolymerItem {
}
@Override
public @Nullable ResourceLocation getPolymerItemModel(ItemStack stack, PacketContext context) {
public @Nullable Identifier getPolymerItemModel(ItemStack stack, PacketContext context, HolderLookup.Provider lookup) {
return null;
}
@Override
public ItemStack getPolymerItemStack(ItemStack itemStack, TooltipFlag tooltipType, PacketContext context) {
ItemStack stack = PolymerItem.super.getPolymerItemStack(itemStack, tooltipType, context);
public ItemStack getPolymerItemStack(ItemStack itemStack, TooltipFlag tooltipType, PacketContext context, HolderLookup.Provider lookup) {
ItemStack stack = PolymerItem.super.getPolymerItemStack(itemStack, tooltipType, context, lookup);
stack.set(DataComponents.ENCHANTMENT_GLINT_OVERRIDE, true);
return stack;
}
public static ItemStack createInstructionReference(MinionFakePlayer minion, String instructionName) {
ItemStack stack = new ItemStack(MinionItems.REFERENCE_ITEM);
stack.set(MinionComponentTypes.REFERENCE, new InstructionClipboard(minion.getUUID(), instructionName, minion.getGameProfile().getName()));
stack.set(MinionComponentTypes.REFERENCE, new InstructionClipboard(minion.getUUID(), instructionName, minion.getGameProfile().name()));
return stack;
}
@@ -3,14 +3,15 @@ package io.github.skippyall.minions.clipboard;
import com.mojang.serialization.Codec;
import com.mojang.serialization.MapCodec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import java.util.UUID;
import java.util.function.Consumer;
import net.minecraft.core.UUIDUtil;
import net.minecraft.core.component.DataComponentGetter;
import net.minecraft.network.chat.Component;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.TooltipFlag;
import java.util.UUID;
import java.util.function.Consumer;
public record InstructionClipboard(UUID selectedMinion, String selectedInstruction, String visualMinionName) implements Clipboard {
public static final MapCodec<InstructionClipboard> CODEC = RecordCodecBuilder.mapCodec(instance ->
instance.group(
@@ -6,10 +6,11 @@ import com.mojang.brigadier.exceptions.CommandSyntaxException;
import com.mojang.brigadier.suggestion.Suggestions;
import com.mojang.brigadier.suggestion.SuggestionsBuilder;
import io.github.skippyall.minions.docs.DocsManager;
import java.util.concurrent.CompletableFuture;
import net.minecraft.commands.CommandSourceStack;
import net.minecraft.commands.arguments.ResourceLocationArgument;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.commands.arguments.IdentifierArgument;
import net.minecraft.resources.Identifier;
import java.util.concurrent.CompletableFuture;
import static net.minecraft.commands.Commands.argument;
import static net.minecraft.commands.Commands.literal;
@@ -17,7 +18,7 @@ import static net.minecraft.commands.Commands.literal;
public class DocsSubcommand {
public static final LiteralArgumentBuilder<CommandSourceStack> DOCS = literal("docs")
.then(
argument("docName", ResourceLocationArgument.id())
argument("docName", IdentifierArgument.id())
.suggests(DocsSubcommand::getSuggestions)
.executes(DocsSubcommand::execute)
);
@@ -28,7 +29,7 @@ public class DocsSubcommand {
}
public static int execute(CommandContext<CommandSourceStack> context) throws CommandSyntaxException {
ResourceLocation id = ResourceLocationArgument.getId(context, "docName");
Identifier id = IdentifierArgument.getId(context, "docName");
DocsManager.showDocsEntry(context.getSource().getPlayerOrException(), id);
return 1;
}
@@ -4,10 +4,11 @@ import com.mojang.brigadier.builder.LiteralArgumentBuilder;
import com.mojang.brigadier.context.CommandContext;
import io.github.skippyall.minions.minion.MinionData;
import io.github.skippyall.minions.minion.MinionPersistentState;
import java.util.Collection;
import net.minecraft.commands.CommandSourceStack;
import net.minecraft.network.chat.Component;
import java.util.Collection;
import static net.minecraft.commands.Commands.literal;
public class ListSubcommand {
@@ -9,13 +9,14 @@ import io.github.skippyall.minions.minion.fakeplayer.MinionFakePlayer;
import net.minecraft.commands.CommandSourceStack;
import net.minecraft.commands.arguments.coordinates.Coordinates;
import net.minecraft.commands.arguments.coordinates.Vec3Argument;
import net.minecraft.server.permissions.Permissions;
import static net.minecraft.commands.Commands.argument;
import static net.minecraft.commands.Commands.literal;
public class SpawnSubcommand {
public static final LiteralArgumentBuilder<CommandSourceStack> SPAWN = literal("spawn")
.requires(source -> source.hasPermission(2))
.requires(source -> source.permissions().hasPermission(Permissions.COMMANDS_GAMEMASTER))
.then(argument("minion", StringArgumentType.word())
.suggests(MinionArgument.SUGGESTION_PROVIDER)
.then(argument("pos", Vec3Argument.vec3())
@@ -3,8 +3,6 @@ package io.github.skippyall.minions.command;
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
import com.mojang.brigadier.context.CommandContext;
import io.github.skippyall.minions.Minions;
import java.util.Collection;
import java.util.HashSet;
import net.minecraft.commands.CommandSourceStack;
import net.minecraft.commands.arguments.coordinates.BlockPosArgument;
import net.minecraft.core.BlockPos;
@@ -13,6 +11,9 @@ import net.minecraft.network.chat.Component;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.Blocks;
import java.util.Collection;
import java.util.HashSet;
import static net.minecraft.commands.Commands.argument;
import static net.minecraft.commands.Commands.literal;
@@ -4,11 +4,12 @@ import com.mojang.serialization.Codec;
import com.mojang.serialization.MapCodec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import io.github.skippyall.minions.registration.MinionRegistries;
import java.util.List;
import java.util.function.Function;
import net.minecraft.core.RegistryAccess;
import net.minecraft.server.dialog.body.DialogBody;
import java.util.List;
import java.util.function.Function;
public interface DocsEntry {
Codec<DocsEntry> CODEC = MinionRegistries.DOCS_ENTRY_TYPES.byNameCodec().dispatch(DocsEntry::getCodec, Function.identity());
@@ -7,7 +7,7 @@ import net.fabricmc.fabric.api.resource.SimpleResourceReloadListener;
import net.minecraft.core.Holder;
import net.minecraft.network.chat.ClickEvent;
import net.minecraft.network.chat.Component;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.resources.Identifier;
import net.minecraft.server.dialog.ActionButton;
import net.minecraft.server.dialog.CommonButtonData;
import net.minecraft.server.dialog.CommonDialogData;
@@ -30,15 +30,15 @@ import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executor;
public class DocsManager implements SimpleResourceReloadListener<Tuple<Map<ResourceLocation, DocsEntry>, DocsTree>> {
private static Map<ResourceLocation, DocsEntry> docs;
public class DocsManager implements SimpleResourceReloadListener<Tuple<Map<Identifier, DocsEntry>, DocsTree>> {
private static Map<Identifier, DocsEntry> docs;
private static DocsTree tree;
public static DocsTree getTree() {
return tree;
}
public static void showDocsEntry(ServerPlayer player, ResourceLocation id) {
public static void showDocsEntry(ServerPlayer player, Identifier id) {
DocsEntry entry = getDocsEntry(id);
if(entry == null) {
return;
@@ -48,11 +48,11 @@ public class DocsManager implements SimpleResourceReloadListener<Tuple<Map<Resou
if(tree != null) {
DocsTree.DocElement element = tree.getElement(id);
if (element.previous() != null) {
ResourceLocation previousId = element.previous().getId();
Identifier previousId = element.previous().getId();
buttons.add(getDialogButton(Component.literal("<- ").append(Component.translatable(getDocsEntry(previousId).getMetadata().titleKey())), previousId.toString()));
}
if (element.next() != null) {
ResourceLocation nextId = element.next().getId();
Identifier nextId = element.next().getId();
buttons.add(getDialogButton(Component.translatable(getDocsEntry(nextId).getMetadata().titleKey()).append(Component.literal(" ->")), nextId.toString()));
}
}
@@ -87,21 +87,21 @@ public class DocsManager implements SimpleResourceReloadListener<Tuple<Map<Resou
);
}
public static DocsEntry getDocsEntry(ResourceLocation id) {
public static DocsEntry getDocsEntry(Identifier id) {
return docs.get(id);
}
public static Collection<ResourceLocation> getDocsEntryIds() {
public static Collection<Identifier> getDocsEntryIds() {
return docs.keySet();
}
@Override
public CompletableFuture<Tuple<Map<ResourceLocation, DocsEntry>, DocsTree>> load(ResourceManager resourceManager, Executor executor) {
public CompletableFuture<Tuple<Map<Identifier, DocsEntry>, DocsTree>> load(ResourceManager resourceManager, Executor executor) {
return CompletableFuture.supplyAsync(() -> {
Map<ResourceLocation, Resource> resources = resourceManager.listResources("docs", id -> id.getNamespace().equals(Minions.MOD_ID) && id.getPath().endsWith(".json"));
Map<Identifier, Resource> resources = resourceManager.listResources("docs", id -> id.getNamespace().equals(Minions.MOD_ID) && id.getPath().endsWith(".json"));
final DocsTree.BranchElement[] root = {null};
Map<ResourceLocation, DocsEntry> docsEntries = new HashMap<>();
Map<Identifier, DocsEntry> docsEntries = new HashMap<>();
resources.forEach((id, resource) -> {
try(Reader reader = resource.openAsReader()) {
if(id.getPath().equals("docs/tree.json")) {
@@ -109,7 +109,7 @@ public class DocsManager implements SimpleResourceReloadListener<Tuple<Map<Resou
.ifSuccess(entry -> root[0] = entry.getFirst())
.ifError(error -> Minions.LOGGER.warn("Could not parse docs tree {}: {}", id, error.message()));
} else {
ResourceLocation docId = ResourceLocation.fromNamespaceAndPath(id.getNamespace(), id.getPath().substring("docs/".length(), id.getPath().length() - ".json".length()));
Identifier docId = Identifier.fromNamespaceAndPath(id.getNamespace(), id.getPath().substring("docs/".length(), id.getPath().length() - ".json".length()));
DocsEntry.CODEC.decode(JsonOps.INSTANCE, StrictJsonParser.parse(reader))
.ifSuccess(entry -> docsEntries.put(docId, entry.getFirst()))
.ifError(error -> Minions.LOGGER.warn("Could not parse docs entry {}: {}", id, error.message()));
@@ -128,7 +128,7 @@ public class DocsManager implements SimpleResourceReloadListener<Tuple<Map<Resou
}
@Override
public CompletableFuture<Void> apply(Tuple<Map<ResourceLocation, DocsEntry>, DocsTree> o, ResourceManager resourceManager, Executor executor) {
public CompletableFuture<Void> apply(Tuple<Map<Identifier, DocsEntry>, DocsTree> o, ResourceManager resourceManager, Executor executor) {
return CompletableFuture.supplyAsync(() -> {
docs = o.getA();
tree = o.getB();
@@ -137,7 +137,7 @@ public class DocsManager implements SimpleResourceReloadListener<Tuple<Map<Resou
}
@Override
public ResourceLocation getFabricId() {
return ResourceLocation.fromNamespaceAndPath(Minions.MOD_ID, "docs");
public Identifier getFabricId() {
return Identifier.fromNamespaceAndPath(Minions.MOD_ID, "docs");
}
}
@@ -2,15 +2,16 @@ package io.github.skippyall.minions.docs;
import com.mojang.datafixers.util.Either;
import com.mojang.serialization.Codec;
import net.minecraft.resources.Identifier;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import net.minecraft.resources.ResourceLocation;
public class DocsTree {
private final BranchElement root;
private final Map<ResourceLocation, DocElement> entries = new HashMap<>();
private final Map<Identifier, DocElement> entries = new HashMap<>();
public DocsTree(BranchElement root) {
this.root = root;
@@ -29,7 +30,7 @@ public class DocsTree {
return root;
}
public DocElement getElement(ResourceLocation id) {
public DocElement getElement(Identifier id) {
return entries.get(id);
}
@@ -54,15 +55,15 @@ public class DocsTree {
}
public static final class DocElement extends Element {
public static final Codec<DocElement> CODEC = ResourceLocation.CODEC.xmap(DocElement::new, DocElement::getId);
public static final Codec<DocElement> CODEC = Identifier.CODEC.xmap(DocElement::new, DocElement::getId);
private final ResourceLocation id;
private final Identifier id;
public DocElement(ResourceLocation element) {
public DocElement(Identifier element) {
this.id = element;
}
public ResourceLocation getId() {
public Identifier getId() {
return id;
}
}
@@ -4,26 +4,27 @@ import com.mojang.serialization.Codec;
import com.mojang.serialization.MapCodec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import io.github.skippyall.minions.gui.GuiDisplay;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import net.minecraft.core.RegistryAccess;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.core.registries.Registries;
import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.ComponentSerialization;
import net.minecraft.resources.Identifier;
import net.minecraft.resources.ResourceKey;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.dialog.body.DialogBody;
import net.minecraft.server.dialog.body.ItemBody;
import net.minecraft.server.dialog.body.PlainMessage;
import net.minecraft.world.item.Item;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
public record ReferenceEntry(Metadata metadata, ResourceKey<?> object, Component shortDescription, Component longDescription) implements DocsEntry {
private static final Codec<ResourceKey<?>> REGISTRY_KEY_CODEC = RecordCodecBuilder.create(instance ->
instance.group(
ResourceLocation.CODEC.fieldOf("registry").forGetter(ResourceKey::registry),
ResourceLocation.CODEC.fieldOf("value").forGetter(ResourceKey::location)
Identifier.CODEC.fieldOf("registry").forGetter(ResourceKey::registry),
Identifier.CODEC.fieldOf("value").forGetter(ResourceKey::identifier)
).apply(instance, (registry, value) -> ResourceKey.create(ResourceKey.createRegistryKey(registry), value))
);
@@ -46,9 +47,9 @@ public record ReferenceEntry(Metadata metadata, ResourceKey<?> object, Component
GuiDisplay display = getObjectDisplay(manager);
if(display != null) {
bodyElements.add(new ItemBody(display.createItemStack(), Optional.empty(), false, false, 16, 16));
bodyElements.add(new ItemBody(display.createItemStackTemplate(), Optional.empty(), false, false, 16, 16));
}
bodyElements.add(new PlainMessage(Component.translatable(object.location().toLanguageKey(object.registry().getPath())), 200));
bodyElements.add(new PlainMessage(Component.translatable(object.identifier().toLanguageKey(object.registry().getPath())), 200));
bodyElements.add(new PlainMessage(longDescription, 200));
return bodyElements;
@@ -59,15 +60,15 @@ public record ReferenceEntry(Metadata metadata, ResourceKey<?> object, Component
if(object.isFor(Registries.ITEM) || object.isFor(Registries.BLOCK)) {
Item item;
if(object.isFor(Registries.ITEM)) {
item = BuiltInRegistries.ITEM.getValue(object.location());
item = BuiltInRegistries.ITEM.getValue(object.identifier());
} else {
item = BuiltInRegistries.BLOCK.getValue(object.location()).asItem();
item = BuiltInRegistries.BLOCK.getValue(object.identifier()).asItem();
}
if(item != null) {
display = new GuiDisplay.ItemBased(item);
}
} else {
ResourceLocation displayId = object.location().withPrefix(object.registry().getPath() + "/");
Identifier displayId = object.identifier().withPrefix(object.registry().getPath() + "/");
display = GuiDisplay.getGuiDisplay(displayId, manager);
}
return display;
@@ -1,41 +1,54 @@
package io.github.skippyall.minions.gui;
import com.mojang.authlib.properties.PropertyMap;
import com.mojang.serialization.Codec;
import io.github.skippyall.minions.registration.MinionRegistries;
import io.github.skippyall.minions.util.TranslationUtil;
import it.unimi.dsi.fastutil.objects.ReferenceSortedSets;
import java.util.Optional;
import java.util.UUID;
import net.minecraft.ChatFormatting;
import net.minecraft.core.Registry;
import net.minecraft.core.RegistryAccess;
import net.minecraft.core.UUIDUtil;
import net.minecraft.core.component.DataComponentPatch;
import net.minecraft.core.component.DataComponentType;
import net.minecraft.core.component.DataComponents;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.network.chat.Component;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.resources.Identifier;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.ItemStackTemplate;
import net.minecraft.world.item.Items;
import net.minecraft.world.item.Rarity;
import net.minecraft.world.item.component.ResolvableProfile;
import net.minecraft.world.item.component.TooltipDisplay;
import java.util.LinkedHashSet;
import java.util.UUID;
public interface GuiDisplay {
Codec<GuiDisplay> CODEC = MinionRegistries.GUI_DISPLAY_TYPE.byNameCodec().dispatch(GuiDisplay::getCodec, codec -> codec.fieldOf("data"));
GuiDisplay DEFAULT_DISPLAY = new ItemBased(Items.BARRIER);
TooltipDisplay TOOLTIP_DISPLAY = createTooltipDisplay();
static GuiDisplay getGuiDisplay(ResourceLocation id, RegistryAccess manager) {
private static TooltipDisplay createTooltipDisplay() {
LinkedHashSet<DataComponentType<?>> set = new LinkedHashSet<>();
for(DataComponentType<?> type : BuiltInRegistries.DATA_COMPONENT_TYPE) {
if(type != DataComponents.LORE) {
set.add(type);
}
}
return new TooltipDisplay(false, set);
}
static GuiDisplay getGuiDisplay(Identifier id, RegistryAccess manager) {
return manager.lookup(MinionRegistries.GUI_DISPLAY).map(registry -> registry.getValue(id)).orElse(DEFAULT_DISPLAY);
}
static <T> GuiDisplay getGuiDisplayFor(Registry<T> registry, T element, RegistryAccess manager) {
ResourceLocation elementId = registry.getKey(element);
Identifier elementId = registry.getKey(element);
if(elementId == null) {
return DEFAULT_DISPLAY;
}
ResourceLocation displayId = elementId.withPrefix(registry.key().location().getPath() + "/");
Identifier displayId = elementId.withPrefix(registry.key().identifier().getPath() + "/");
return getGuiDisplay(displayId, manager);
}
@@ -50,24 +63,29 @@ public interface GuiDisplay {
return stack;
}
ItemStack createItemStack();
ItemStackTemplate createItemStackTemplate();
default ItemStack createItemStack() {
return createItemStackTemplate().create();
}
Codec<? extends GuiDisplay> getCodec();
class ModelBased implements GuiDisplay {
public static final Codec<ModelBased> CODEC = ResourceLocation.CODEC.xmap(ModelBased::new, display -> display.model);
public static final Codec<ModelBased> CODEC = Identifier.CODEC.xmap(ModelBased::new, display -> display.model);
private final ResourceLocation model;
private final Identifier model;
public ModelBased(ResourceLocation model) {
public ModelBased(Identifier model) {
this.model = model;
}
@Override
public ItemStack createItemStack() {
ItemStack stack = new ItemStack(Items.BARRIER);
stack.set(DataComponents.ITEM_MODEL, model);
return stack;
public ItemStackTemplate createItemStackTemplate() {
return new ItemStackTemplate(Items.BARRIER, DataComponentPatch.builder()
.set(DataComponents.ITEM_MODEL, model)
.build()
);
}
@Override
@@ -86,11 +104,11 @@ public interface GuiDisplay {
}
@Override
public ItemStack createItemStack() {
ItemStack stack = new ItemStack(item);
stack.set(DataComponents.TOOLTIP_DISPLAY, new TooltipDisplay(true, ReferenceSortedSets.emptySet()));
stack.set(DataComponents.RARITY, Rarity.COMMON);
return stack;
public ItemStackTemplate createItemStackTemplate() {
return new ItemStackTemplate(item, DataComponentPatch.builder()
.set(DataComponents.TOOLTIP_DISPLAY, TOOLTIP_DISPLAY)
.set(DataComponents.RARITY, Rarity.COMMON)
.build());
}
@Override
@@ -109,10 +127,11 @@ public interface GuiDisplay {
}
@Override
public ItemStack createItemStack() {
ItemStack stack = new ItemStack(Items.PLAYER_HEAD);
stack.set(DataComponents.PROFILE, new ResolvableProfile(Optional.empty(), Optional.of(uuid), new PropertyMap()));
return stack;
public ItemStackTemplate createItemStackTemplate() {
return new ItemStackTemplate(Items.PLAYER_HEAD, DataComponentPatch.builder()
.set(DataComponents.PROFILE, ResolvableProfile.createUnresolved(uuid))
.build()
);
}
@Override
@@ -122,17 +141,17 @@ public interface GuiDisplay {
}
class StackBased implements GuiDisplay {
public static final Codec<StackBased> CODEC = ItemStack.CODEC.xmap(StackBased::new, StackBased::createItemStack);
public static final Codec<StackBased> CODEC = ItemStackTemplate.CODEC.xmap(StackBased::new, StackBased::createItemStackTemplate);
private final ItemStack stack;
private final ItemStackTemplate template;
public StackBased(ItemStack stack) {
this.stack = stack;
public StackBased(ItemStackTemplate template) {
this.template = template;
}
@Override
public ItemStack createItemStack() {
return stack;
public ItemStackTemplate createItemStackTemplate() {
return template;
}
@Override
@@ -1,95 +0,0 @@
package io.github.skippyall.minions.gui;
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 java.util.Optional;
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;
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).thenAccept(skin -> {
MinionItem.setData(player.getServer(), getData().withSkin(skin), minionItem);
}));
if(MinionItem.getData(player.getServer(), minionItem) != null && MinionItem.getData(player.getServer(), minionItem).skin().isPresent()) {
builder.setComponent(DataComponents.PROFILE, new ResolvableProfile(Optional.empty(), Optional.empty(), 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.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.getServer(), name))
.thenAccept(name -> {
MinionItem.setData(player.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,65 +0,0 @@
package io.github.skippyall.minions.gui;
import net.minecraft.server.level.ServerPlayer;
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();
}
public void close() {
if(open) {
if(parent != null) {
parent.child = null;
parent.reopen();
}
closeNoOpen(parent == null);
}
}
private void closeNoOpen(boolean closeBacking) {
if(child != null) {
child.closeNoOpen(closeBacking);
}
if(parent != null) {
parent.child = null;
}
if(closeBacking) {
closeBacking();
}
open = false;
}
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()
}
@@ -2,13 +2,14 @@ package io.github.skippyall.minions.gui;
import eu.pb4.sgui.api.elements.GuiElementBuilder;
import eu.pb4.sgui.api.gui.SimpleGui;
import java.util.List;
import java.util.function.BiFunction;
import net.minecraft.core.IdMap;
import net.minecraft.network.chat.Component;
import net.minecraft.world.inventory.MenuType;
import net.minecraft.world.item.Items;
import java.util.List;
import java.util.function.BiFunction;
public class PaginatedList extends MinionsGui {
private int page = 0;
private SimpleGui gui;
@@ -26,13 +27,15 @@ public class PaginatedList extends MinionsGui {
@Override
protected void open() {
gui = new SimpleGui(MenuType.GENERIC_9x4, viewer, false) {
gui = new SimpleGui(MenuType.GENERIC_9x6, viewer, false) {
@Override
public void onClose() {
public void onPlayerClose(boolean success) {
onBackingClosed();
}
};
gui.setTitle(title);
gui.setSlot(8, backButton());
addItems();
gui.open();
}
@@ -51,12 +54,14 @@ public class PaginatedList extends MinionsGui {
}
private void addItems() {
for(int i = 27 * page; i < Math.min(27 * (page + 1), size); i++) {
gui.addSlot(display.apply(i, this));
int slot = 9;
for(int i = 36 * page; i < Math.min(36 * (page + 1), size); i++) {
gui.setSlot(slot, display.apply(i, this));
slot++;
}
if(page > 0) {
gui.setSlot(30, new GuiElementBuilder(Items.SPECTRAL_ARROW)
gui.setSlot(48, new GuiElementBuilder(Items.SPECTRAL_ARROW)
.setItemName(Component.translatable("book.page_button.previous"))
.setCallback(() -> {
page--;
@@ -64,11 +69,11 @@ public class PaginatedList extends MinionsGui {
})
);
} else {
gui.clearSlot(30);
gui.clearSlot(48);
}
if(27 * (page + 1) < size) {
gui.setSlot(32, new GuiElementBuilder(Items.ARROW)
gui.setSlot(50, new GuiElementBuilder(Items.ARROW)
.setItemName(Component.translatable("book.page_button.next"))
.setCallback(() -> {
page++;
@@ -76,7 +81,7 @@ public class PaginatedList extends MinionsGui {
})
);
} else {
gui.clearSlot(32);
gui.clearSlot(50);
}
}
}
@@ -6,15 +6,15 @@ import io.github.skippyall.minions.gui.Displayable;
import io.github.skippyall.minions.gui.GuiDisplay;
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.MenuType;
import net.minecraft.world.item.Items;
import org.jetbrains.annotations.Nullable;
import java.util.concurrent.CompletableFuture;
import java.util.function.BiFunction;
import java.util.function.Function;
import net.minecraft.network.chat.Component;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.inventory.MenuType;
import net.minecraft.world.item.Items;
public class ChoiceInput {
public static <T> BiFunction<ServerPlayer, T, CompletableFuture<T>> createDialogOpener(MenuType<?> screen, Component title, Function<T, GuiDisplay> displayFunction, T[] values, @Nullable T fallback) {
@@ -23,7 +23,7 @@ public class ChoiceInput {
SimpleGui gui = new SimpleGui(screen, player, false) {
@Override
public void onClose() {
public void onPlayerClose(boolean success) {
if(fallback == null) {
future.cancel(false);
} else {
@@ -53,7 +53,7 @@ public class ChoiceInput {
SimpleGui gui = new SimpleGui(MenuType.GENERIC_3x3, player, false) {
@Override
public void onClose() {
public void onPlayerClose(boolean success) {
future.cancel(false);
}
};
@@ -74,14 +74,14 @@ public class ChoiceInput {
return future;
}
public static CompletableFuture<Void> confirm(MinionsGui parent, Component title) {
CompletableFuture<Void> future = new CompletableFuture<>();
public static CompletableFuture<Boolean> confirm(MinionsGui parent, Component title) {
CompletableFuture<Boolean> future = new CompletableFuture<>();
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
public void onClose() {
future.cancel(false);
public void onPlayerClose(boolean success) {
future.complete(false);
onClose.run();
}
};
@@ -90,12 +90,18 @@ public class ChoiceInput {
gui.setSlot(3, new GuiElementBuilder(Items.REDSTONE_BLOCK)
.setName(Component.translatable("minions.gui.abort"))
.setCallback(() -> future.cancel(false))
.setCallback(() -> {
future.complete(false);
me.goBack();
})
);
gui.setSlot(5, new GuiElementBuilder(Items.EMERALD_BLOCK)
.setName(Component.translatable("minions.gui.confirm"))
.setCallback(() -> future.complete(null))
.setCallback(() -> {
future.complete(true);
me.goBack();
})
);
gui.open();
@@ -1,122 +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 java.util.concurrent.CompletableFuture;
import java.util.function.Function;
import net.minecraft.network.chat.Component;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.inventory.AnvilMenu;
import net.minecraft.world.item.Items;
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.handle((v, e) -> {
onClose.run();
return null;
});
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 onClose() {
if(!future.isDone() && !isConfirm) {
future.cancel(false);
}
}
public void onConfirm() {
if(result != null) {
result.ifSuccess(success -> {
isConfirm = true;
close();
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()
}
}
}
@@ -23,7 +23,6 @@ import org.jetbrains.annotations.Nullable;
public class ArgumentGui extends MinionsGui {
private final GuiContext.ValueSupplier context;
private final MinionFakePlayer minion;
private final ConfiguredInstruction<MinionRuntime> instruction;
private final Parameter<?> parameter;
@@ -34,7 +33,6 @@ public class ArgumentGui extends MinionsGui {
public ArgumentGui(MinionsGui parent, GuiContext.ValueSupplier context) {
super(parent);
minion = context.getMinion();
instruction = context.getInstruction();
this.parameter = context.getParameter();
this.context = context;
@@ -61,7 +59,7 @@ public class ArgumentGui extends MinionsGui {
protected void open() {
gui = new SimpleGui(MenuType.GENERIC_3x3, viewer, false) {
@Override
public void onClose() {
public void onPlayerClose(boolean success) {
onBackingClosed();
}
};
@@ -71,6 +69,8 @@ public class ArgumentGui extends MinionsGui {
Component.translatable(TranslationUtil.getTranslationKey(parameter.type(), MinionRegistries.VALUE_TYPES))
));
gui.setSlot(2, backButton());
updateTypeConfiguration();
updateArgumentConfiguration();
updateConverterConfiguration();
@@ -102,12 +102,7 @@ public class ArgumentGui extends MinionsGui {
.setName(Component.translatable("minions.gui.instruction.argument.configure.data"))
.addLoreLine(getArgument() != null ? getArgument().getDisplayText() : Component.translatable("minions.gui.not_set"))
.setCallback(() -> argumentType.openConfiguration(this, parameter.type(), getArgument())
.thenAccept(newArgument -> {
setArgument(newArgument);
if(child != null) {
child.close();
}
})
.thenAccept(this::setArgument)
)
);
}
@@ -149,7 +144,7 @@ public class ArgumentGui extends MinionsGui {
new GuiElementBuilder(GuiDisplay.getDisplayStackWithName(MinionRegistries.VALUE_SUPPLIER_TYPES, type, viewer.registryAccess()))
.setCallback(() -> {
setArgumentType(type);
me.close();
me.goBack();
})
);
}
@@ -13,6 +13,7 @@ import io.github.skippyall.minions.program.instruction.ConfiguredInstruction;
import io.github.skippyall.minions.program.instruction.ConfiguredInstructionListener;
import io.github.skippyall.minions.program.supplier.Parameter;
import net.minecraft.network.chat.Component;
import net.minecraft.network.protocol.game.ClientboundSoundEntityPacket;
import net.minecraft.sounds.SoundEvents;
import net.minecraft.sounds.SoundSource;
import net.minecraft.world.inventory.MenuType;
@@ -42,14 +43,14 @@ public class ConfigureInstructionGui extends MinionsGui implements ConfiguredIns
protected void open() {
gui = new SimpleGui(MenuType.GENERIC_9x3, viewer, false) {
@Override
public void onClose() {
public void onPlayerClose(boolean success) {
onBackingClosed();
}
};
gui.setTitle(Component.literal(name));
gui.setSlot(7, new GuiElementBuilder(Items.ANVIL)
gui.setSlot(6, new GuiElementBuilder(Items.ANVIL)
.setName(Component.translatable("minions.gui.instruction.configure.rename"))
.setCallback(() -> InstructionGui.inputInstructionName(this, context, name).thenAccept(newName -> {
minion.getInstructionManager().setInstructionName(name, newName);
@@ -57,15 +58,19 @@ public class ConfigureInstructionGui extends MinionsGui implements ConfiguredIns
}))
);
gui.setSlot(8, new GuiElementBuilder(Items.LAVA_BUCKET)
gui.setSlot(7, new GuiElementBuilder(Items.LAVA_BUCKET)
.setName(Component.translatable("minions.gui.instruction.configure.delete"))
.setCallback(() -> ChoiceInput.confirm(this, Component.translatable("minions.gui.instruction.configure.delete.confirm", name))
.thenAccept(v -> {
minion.getInstructionManager().removeInstruction(name);
close();
.thenAccept((confirmed) -> {
if(confirmed) {
minion.getInstructionManager().removeInstruction(name);
goBack();
}
}))
);
gui.setSlot(8, backButton());
updateSuppliers();
gui.setSlot(13, InstructionGui.createInstructionElement(instruction.getInstruction(), viewer.registryAccess()));
@@ -75,7 +80,7 @@ public class ConfigureInstructionGui extends MinionsGui implements ConfiguredIns
.addLoreLine(Component.translatable("minions.gui.instruction.configure.copy.description"))
.setCallback(() -> {
viewer.getInventory().placeItemBackInInventory(ClipboardItem.createInstructionReference(minion, name), true);
viewer.playNotifySound(SoundEvents.NOTE_BLOCK_CHIME.value(), SoundSource.BLOCKS, 1, 1);
viewer.connection.send(new ClientboundSoundEntityPacket(SoundEvents.NOTE_BLOCK_CHIME, SoundSource.BLOCKS, viewer, 1, 1, 0));
})
);
@@ -44,7 +44,7 @@ public class ConverterGui extends MinionsGui {
protected void open() {
gui = new SimpleGui(MenuType.GENERIC_3x3, viewer, false) {
@Override
public void onClose() {
public void onPlayerClose(boolean success) {
onBackingClosed();
}
};
@@ -53,15 +53,11 @@ public class ConverterGui extends MinionsGui {
updateTypeDisplay();
updateConverterDisplay();
gui.setSlot(8, backButton());
gui.open();
}
@Override
protected void reopen() {
gui.open();
}
private void updateTypeDisplay() {
gui.setSlot(3, new GuiElementBuilder(GuiDisplay.getDisplayStackWithName(MinionRegistries.VALUE_CONVERTER_TYPES, valueConverterType, viewer.registryAccess()))
.setCallback(this::configureType)
@@ -106,7 +102,7 @@ public class ConverterGui extends MinionsGui {
GuiDisplay.getDisplayStackWithName(MinionRegistries.VALUE_CONVERTER_TYPES, type, viewer.registryAccess())
).setCallback(() -> {
setType(type);
me.close();
me.goBack();
})
);
}
@@ -114,12 +110,7 @@ public class ConverterGui extends MinionsGui {
private void configureData() {
if(valueConverterType != null) {
valueConverterType.configure(this, from, to, converter)
.thenAccept(newConverter -> {
setConverter(newConverter);
if(child != null) {
child.close();
}
});
.thenAccept(this::setConverter);
}
}
@@ -34,7 +34,7 @@ public class ConverterListGui extends MinionsGui {
protected void open() {
gui = new SimpleGui(MenuType.GENERIC_9x3, viewer, false) {
@Override
public void onClose() {
public void onPlayerClose(boolean success) {
onBackingClosed();
}
};
@@ -61,6 +61,8 @@ public class ConverterListGui extends MinionsGui {
})
);
gui.setSlot(8, backButton());
gui.open();
}
@@ -18,30 +18,31 @@ import io.github.skippyall.minions.program.supplier.ValueSupplier;
import io.github.skippyall.minions.registration.MinionComponentTypes;
import io.github.skippyall.minions.registration.MinionRegistries;
import io.github.skippyall.minions.util.TranslationUtil;
import org.jetbrains.annotations.Nullable;
import java.util.NoSuchElementException;
import java.util.concurrent.CompletableFuture;
import net.minecraft.core.RegistryAccess;
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 org.jetbrains.annotations.Nullable;
import java.util.NoSuchElementException;
import java.util.concurrent.CompletableFuture;
public class InstructionGui {
public static MinionsGui openInstructionMainMenu(MinionsGui parent, GuiContext.Minion context) {
return new SimpleMinionsGui(parent, (onClose, me) -> {
ServerPlayer player = parent.getViewer();
public static void openInstructionMainMenu(MinionsGui parent, GuiContext.Minion context) {
new SimpleMinionsGui(parent, (onClose, me) -> {
ServerPlayer player = parent.viewer;
SimpleGui gui = new SimpleGui(MenuType.GENERIC_3x3, player, false) {
@Override
public void onClose() {
public void onPlayerClose(boolean success) {
onClose.run();
}
};
gui.setTitle(Component.translatable("minions.gui.instruction.title"));
gui.setSlot(2, me.backButton());
gui.setSlot(3, new GuiElementBuilder()
.setItem(Items.BOOK)
.setName(Component.translatable("minions.gui.instruction.list"))
@@ -60,7 +61,7 @@ public class InstructionGui {
public static void createNewInstruction(MinionsGui parent, GuiContext.Minion context) {
MinionFakePlayer minion = context.getMinion();
ServerPlayer viewer = parent.getViewer();
ServerPlayer viewer = parent.viewer;
selectInstructionModuleMenu(parent, context).thenAccept(instructionType ->
inputInstructionName(parent, context, "Instruction").thenAccept(name -> {
if (!minion.isRemoved() && !minion.hasDisconnected()) {
@@ -72,7 +73,7 @@ public class InstructionGui {
}
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)) {
return new Result.Error<>(Component.translatable("minions.gui.instruction.name_already_used"));
}
@@ -91,7 +92,7 @@ public class InstructionGui {
public static CompletableFuture<InstructionType<MinionRuntime>> selectInstructionModuleMenu(MinionsGui parent, GuiContext.Minion context) {
MinionFakePlayer minion = context.getMinion();
ServerPlayer viewer = parent.getViewer();
ServerPlayer viewer = parent.viewer;
if (minion.getModuleInventory().getModules().isEmpty()) {
viewer.sendSystemMessage(Component.translatable("minions.gui.instruction.no_modules"));
@@ -101,9 +102,9 @@ public class InstructionGui {
CompletableFuture<InstructionType<MinionRuntime>> future = new CompletableFuture<>();
new SimpleMinionsGui(parent, (closeHandler, me) -> {
SimpleGui gui = new SimpleGui(MenuType.GENERIC_9x3, viewer, false) {
SimpleGui gui = new SimpleGui(MenuType.GENERIC_9x4, viewer, false) {
@Override
public void onClose() {
public void onPlayerClose(boolean success) {
if (!future.isDone()) {
future.cancel(false);
}
@@ -112,11 +113,13 @@ public class InstructionGui {
};
gui.setTitle(Component.translatable("minions.gui.instruction.select_instruction"));
gui.setSlot(8, me.backButton());
for (int i = 0; i < minion.getModuleInventory().getContainerSize(); i++) {
ItemStack moduleItem = minion.getModuleInventory().getItem(i);
MinionModule module = moduleItem.get(MinionComponentTypes.MODULE);
if (module != null && !module.instructions().isEmpty()) {
gui.addSlot(new GuiElementBuilder(moduleItem)
gui.setSlot(i + 9, new GuiElementBuilder(moduleItem)
.setCallback(() -> selectInstructionMenu(parent, context, module)
.thenApply(future::complete)
)
@@ -134,9 +137,9 @@ public class InstructionGui {
CompletableFuture<InstructionType<MinionRuntime>> future = new CompletableFuture<>();
new SimpleMinionsGui(parent, (closeHandler, me) -> {
SimpleGui gui = new SimpleGui(MenuType.GENERIC_9x3, parent.getViewer(), false) {
SimpleGui gui = new SimpleGui(MenuType.GENERIC_9x4, parent.viewer, false) {
@Override
public void onClose() {
public void onPlayerClose(boolean success) {
if (!future.isDone()) {
future.cancel(false);
}
@@ -145,10 +148,13 @@ public class InstructionGui {
};
gui.setTitle(Component.translatable("minions.gui.instruction.select_instruction"));
gui.setSlot(8, me.backButton());
int slot = 9;
for (InstructionType<MinionRuntime> instructionType : module.instructions()) {
gui.addSlot(createInstructionElement(instructionType, parent.getViewer().registryAccess())
gui.setSlot(slot, createInstructionElement(instructionType, parent.viewer.registryAccess())
.setCallback(() -> future.complete(instructionType))
);
slot++;
}
gui.open();
@@ -33,19 +33,16 @@ public class InstructionListGui extends MinionsGui implements MinionListener {
@Override
protected void open() {
minion.addMinionListener(this);
gui = new SimpleGui(MenuType.GENERIC_9x3, viewer, false) {
gui = new SimpleGui(MenuType.GENERIC_9x4, viewer, false) {
@Override
public void onClose() {
public void onPlayerClose(boolean success) {
onBackingClosed();
}
};
gui.setTitle(Component.translatable("minions.gui.instruction.title"));
resetInstructionList();
gui.open();
}
@Override
protected void reopen() {
gui.setSlot(8, backButton());
resetInstructionList();
gui.open();
}
@@ -56,7 +53,7 @@ public class InstructionListGui extends MinionsGui implements MinionListener {
}
private void resetInstructionList() {
int i = 0;
int i = 9;
for (String instructionName : minion.getInstructionManager().getInstructionNames()) {
ConfiguredInstruction<MinionRuntime> instruction = minion.getInstructionManager().getInstruction(instructionName);
gui.setSlot(i, new GuiElementBuilder(GuiDisplay.getGuiDisplayFor(MinionRegistries.INSTRUCTION_TYPES, instruction.getInstruction(), viewer.registryAccess()).createItemStack())
@@ -23,7 +23,7 @@ public class GuiContextImpl implements GuiContext {
private final MinionFakePlayer minion;
public MinionImpl(GuiContext context, MinionFakePlayer minion) {
super(context);
super(context instanceof DelegatingGuiContextImpl<?> impl ? impl.context : context);
this.minion = minion;
}
@@ -38,7 +38,7 @@ public class GuiContextImpl implements GuiContext {
private String name;
public InstructionImpl(GuiContext.Minion context, ConfiguredInstruction<MinionRuntime> instruction, String name) {
super(context);
super(context instanceof DelegatingMinionImpl<?> impl ? impl.context : context);
this.instruction = instruction;
this.name = name;
}
@@ -63,7 +63,7 @@ public class GuiContextImpl implements GuiContext {
private final Parameter<?> parameter;
public ValueSupplierImpl(GuiContext.Instruction context, Parameter<?> parameter) {
super(context);
super(context instanceof DelegatingInstructionImpl<?> impl ? impl.context : context);
this.parameter = parameter;
}
@@ -31,7 +31,7 @@ public class MinionGui extends MinionsGui implements MinionListener {
protected void open() {
gui = new SimpleGui(MenuType.GENERIC_3x3, viewer, false) {
@Override
public void onClose() {
public void onPlayerClose(boolean success) {
onBackingClosed();
}
};
@@ -65,11 +65,6 @@ public class MinionGui extends MinionsGui implements MinionListener {
gui.open();
}
@Override
protected void reopen() {
gui.open();
}
@Override
protected void closeBacking() {
gui.close();
@@ -29,7 +29,7 @@ public class MinionInventoryGui extends MinionsGui {
protected void open() {
gui = new SimpleGui(MenuType.GENERIC_9x6, viewer, false) {
@Override
public void onClose() {
public void onPlayerClose(boolean success) {
onBackingClosed();
}
};
@@ -45,18 +45,20 @@ public class MinionInventoryGui extends MinionsGui {
gui.setSlot(5, new ItemStack(Items.LEATHER_BOOTS));
gui.setSlot(6, new ItemStack(Items.SHIELD));
gui.setSlotRedirect(2 + 9, new ArmorSlot(minion.getInventory(), minion, EquipmentSlot.HEAD, EquipmentSlot.HEAD.getIndex(Inventory.INVENTORY_SIZE), 0, 0, null));
gui.setSlotRedirect(3 + 9, new ArmorSlot(minion.getInventory(), minion, EquipmentSlot.CHEST, EquipmentSlot.CHEST.getIndex(Inventory.INVENTORY_SIZE), 0, 0, null));
gui.setSlotRedirect(4 + 9, new ArmorSlot(minion.getInventory(), minion, EquipmentSlot.LEGS, EquipmentSlot.LEGS.getIndex(Inventory.INVENTORY_SIZE), 0, 0, null));
gui.setSlotRedirect(5 + 9, new ArmorSlot(minion.getInventory(), minion, EquipmentSlot.FEET, EquipmentSlot.FEET.getIndex(Inventory.INVENTORY_SIZE), 0, 0, null));
gui.setSlotRedirect(6 + 9, new Slot(minion.getInventory(), Inventory.SLOT_OFFHAND, 0, 0));
gui.setSlot(8, backButton());
gui.setSlot(2 + 9, new ArmorSlot(minion.getInventory(), minion, EquipmentSlot.HEAD, EquipmentSlot.HEAD.getIndex(Inventory.INVENTORY_SIZE), 0, 0, null));
gui.setSlot(3 + 9, new ArmorSlot(minion.getInventory(), minion, EquipmentSlot.CHEST, EquipmentSlot.CHEST.getIndex(Inventory.INVENTORY_SIZE), 0, 0, null));
gui.setSlot(4 + 9, new ArmorSlot(minion.getInventory(), minion, EquipmentSlot.LEGS, EquipmentSlot.LEGS.getIndex(Inventory.INVENTORY_SIZE), 0, 0, null));
gui.setSlot(5 + 9, new ArmorSlot(minion.getInventory(), minion, EquipmentSlot.FEET, EquipmentSlot.FEET.getIndex(Inventory.INVENTORY_SIZE), 0, 0, null));
gui.setSlot(6 + 9, new Slot(minion.getInventory(), Inventory.SLOT_OFFHAND, 0, 0));
for (int i = Inventory.SELECTION_SIZE; i < Inventory.INVENTORY_SIZE; i++) {
gui.setSlotRedirect(i + 9, new Slot(minion.getInventory(), i, 0, 0));
gui.setSlot(i + 9, new Slot(minion.getInventory(), i, 0, 0));
}
for (int i = 0; i < Inventory.SELECTION_SIZE; i++) {
gui.setSlotRedirect(i + 45, new Slot(minion.getInventory(), i, 0, 0));
gui.setSlot(i + 45, new Slot(minion.getInventory(), i, 0, 0));
}
gui.open();
}
@@ -1,15 +1,15 @@
package io.github.skippyall.minions.gui.minion;
import eu.pb4.sgui.api.gui.GuiInterface;
import eu.pb4.sgui.api.gui.GuiLike;
import io.github.skippyall.minions.gui.MinionsGui;
import java.util.function.BiFunction;
public class SimpleMinionsGui extends MinionsGui {
private GuiInterface gui;
private final BiFunction<Runnable, SimpleMinionsGui, GuiInterface> guiFactory;
private GuiLike gui;
private final BiFunction<Runnable, SimpleMinionsGui, GuiLike> guiFactory;
public SimpleMinionsGui(MinionsGui parent, BiFunction<Runnable, SimpleMinionsGui, GuiInterface> guiFactory) {
public SimpleMinionsGui(MinionsGui parent, BiFunction<Runnable, SimpleMinionsGui, GuiLike> guiFactory) {
super(parent);
this.guiFactory = guiFactory;
open();
@@ -1,13 +1,15 @@
package io.github.skippyall.minions.listener;
import com.mojang.serialization.Codec;
import com.mojang.serialization.MapCodec;
import net.minecraft.core.Registry;
import net.minecraft.resources.Identifier;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArraySet;
import net.minecraft.core.Registry;
import net.minecraft.resources.ResourceLocation;
public class SerializableListenerManager<T extends SerializableListenerManager.SerializableListener> extends ListenerManager<T> {
public SerializableListenerManager() {
@@ -20,7 +22,7 @@ public class SerializableListenerManager<T extends SerializableListenerManager.S
public static <T extends SerializableListener> Codec<SerializableListenerManager<T>> getCodec(Registry<Codec<? extends T>> registry) {
return registry.byNameCodec().<T>dispatch(
listener -> listener.getCodecId().map(registry::getValue).orElse(Codec.unit(null)),
listener -> listener.getCodecId().map(registry::getValue).orElse(MapCodec.unitCodec(null)),
codec -> codec.fieldOf("data")
).listOf().xmap(
list -> new SerializableListenerManager<>(new CopyOnWriteArraySet<>(list)),
@@ -37,7 +39,7 @@ public class SerializableListenerManager<T extends SerializableListenerManager.S
}
public interface SerializableListener {
default Optional<ResourceLocation> getCodecId() {
default Optional<Identifier> getCodecId() {
return Optional.empty();
}
}
@@ -2,10 +2,11 @@ package io.github.skippyall.minions.minion;
import com.mojang.serialization.Codec;
import io.github.skippyall.minions.registration.MinionRegistries;
import net.minecraft.resources.Identifier;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import net.minecraft.resources.ResourceLocation;
public class MinionConfig {
public static final Codec<MinionConfig> CODEC = Codec.<Option<?>, Object>dispatchedMap(
@@ -43,11 +44,11 @@ public class MinionConfig {
return Objects.hashCode(values);
}
public static Option<Boolean> booleanOption(ResourceLocation key, boolean defaultValue) {
public static Option<Boolean> booleanOption(Identifier key, boolean defaultValue) {
return new Option<>(key, defaultValue, Codec.BOOL);
}
public record Option<T>(ResourceLocation key, T defaultValue, Codec<T> codec) {
public record Option<T>(Identifier key, T defaultValue, Codec<T> codec) {
@Override
public boolean equals(Object o) {
if (!(o instanceof Option<?> option)) return false;
@@ -1,13 +1,14 @@
package io.github.skippyall.minions.minion;
import eu.pb4.polymer.core.api.item.PolymerItem;
import eu.pb4.polymer.core.api.item.PolymerItemUtils;
import io.github.skippyall.minions.gui.MinionLookGui;
import io.github.skippyall.minions.minion.fakeplayer.MinionFakePlayer;
import io.github.skippyall.minions.registration.MinionComponentTypes;
import net.fabricmc.fabric.api.networking.v1.context.PacketContext;
import net.minecraft.core.HolderLookup;
import net.minecraft.core.component.DataComponents;
import net.minecraft.network.chat.Component;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.resources.Identifier;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer;
@@ -23,7 +24,6 @@ import net.minecraft.world.item.context.UseOnContext;
import net.minecraft.world.level.Level;
import net.minecraft.world.phys.Vec2;
import org.jetbrains.annotations.Nullable;
import xyz.nucleoid.packettweaker.PacketContext;
import java.util.function.Consumer;
@@ -33,7 +33,7 @@ public class MinionItem extends Item implements PolymerItem {
}
@Override
public @Nullable ResourceLocation getPolymerItemModel(ItemStack stack, PacketContext context) {
public @Nullable Identifier getPolymerItemModel(ItemStack stack, PacketContext context, HolderLookup.Provider lookup) {
return null;
}
@@ -43,25 +43,25 @@ public class MinionItem extends Item implements PolymerItem {
}
@Override
public ItemStack getPolymerItemStack(ItemStack stack, TooltipFlag tooltipType, PacketContext player) {
ItemStack out = PolymerItemUtils.createItemStack(stack, tooltipType, player);
public ItemStack getPolymerItemStack(ItemStack stack, TooltipFlag tooltipType, PacketContext player, HolderLookup.Provider lookup) {
ItemStack out = PolymerItem.super.getPolymerItemStack(stack, tooltipType, player, lookup);
out.set(DataComponents.ENCHANTMENT_GLINT_OVERRIDE, true);
return out;
}
@Override
public void appendHoverText(ItemStack stack, TooltipContext context, TooltipDisplay component, Consumer<Component> tooltip, TooltipFlag type) {
MinionData data = null /*getData(stack)*/;
if(data != null) {
tooltip.accept(Component.translatable("minions.minion_item.tooltip", data.name()));
}
//MinionData data = getData(stack);
//if(data != null) {
// tooltip.accept(Component.translatable("minions.minion_item.tooltip", data.name()));
//}
}
@Override
public InteractionResult use(Level world, Player user, InteractionHand hand) {
if(user instanceof ServerPlayer serverPlayer) {
ItemStack stack = user.getItemInHand(hand);
MinionLookGui.open(serverPlayer, stack);
new MinionLookGui(serverPlayer, stack);
return InteractionResult.SUCCESS;
}
@@ -70,7 +70,7 @@ public class MinionItem extends Item implements PolymerItem {
@Override
public InteractionResult useOn(UseOnContext context) {
if(!context.getLevel().isClientSide) {
if(!context.getLevel().isClientSide()) {
MinionData data = getDataOrDefault(context.getLevel().getServer(), context.getItemInHand());
MinionFakePlayer.spawnMinion(data, (ServerLevel) context.getLevel(), context.getClickedPos().getCenter().add(0,0.5,0), new Vec2(0, 0));
}
@@ -1,6 +1,8 @@
package io.github.skippyall.minions.minion;
import com.mojang.serialization.Codec;
import io.github.skippyall.minions.Minions;
import net.minecraft.resources.Identifier;
import net.minecraft.server.MinecraftServer;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.saveddata.SavedData;
@@ -14,7 +16,12 @@ import java.util.UUID;
public class MinionPersistentState extends SavedData {
public static final Codec<MinionPersistentState> CODEC = MinionData.CODEC.listOf().xmap(MinionPersistentState::new, MinionPersistentState::getMinionDataList);
public static SavedDataType<MinionPersistentState> TYPE = new SavedDataType<>("minion", MinionPersistentState::new, MinionPersistentState.CODEC, null);
public static SavedDataType<MinionPersistentState> TYPE = new SavedDataType<>(
Identifier.fromNamespaceAndPath(Minions.MOD_ID, "minion"),
MinionPersistentState::new,
MinionPersistentState.CODEC,
null
);
private final Map<UUID, MinionData> minionData = new HashMap<>();
@@ -22,10 +22,7 @@ public class MinionProfileUtils {
uuidMinion = UUID.randomUUID();
}
GameProfile newProfile = new GameProfile(uuidMinion, username);
if (skin != null) {
newProfile.getProperties().putAll(skin);
}
GameProfile newProfile = new GameProfile(uuidMinion, username, skin != null ? skin : PropertyMap.EMPTY);
LOGGER.info("Minion Profile: {}", newProfile);
return newProfile;
}
@@ -8,13 +8,14 @@ import io.github.skippyall.minions.program.instruction.ConfiguredInstruction;
import io.github.skippyall.minions.program.instruction.InstructionType;
import io.github.skippyall.minions.program.supplier.ValueSupplierType;
import io.github.skippyall.minions.registration.MinionRegistries;
import net.minecraft.core.Registry;
import net.minecraft.world.level.storage.ValueInput;
import net.minecraft.world.level.storage.ValueOutput;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import net.minecraft.core.Registry;
import net.minecraft.world.level.storage.ValueInput;
import net.minecraft.world.level.storage.ValueOutput;
public class MinionRuntime implements InstructionRuntime<MinionRuntime> {
private final MinionFakePlayer minion;
@@ -115,7 +116,7 @@ public class MinionRuntime implements InstructionRuntime<MinionRuntime> {
for (ValueInput inner : list) {
Optional<String> name = inner.getString("name");
if(name.isEmpty()) {
Minions.LOGGER.error("Tried deserializing configured instruction without a name of minion \"{}\":", minion.getGameProfile().getName());
Minions.LOGGER.error("Tried deserializing configured instruction without a name of minion \"{}\":", minion.getGameProfile().name());
continue;
}
@@ -123,7 +124,7 @@ public class MinionRuntime implements InstructionRuntime<MinionRuntime> {
ConfiguredInstruction<MinionRuntime> instruction = ConfiguredInstruction.load(inner, this);
configuredInstructions.put(name.get(), instruction);
} catch (Exception e) {
Minions.LOGGER.error("Could not deserialize configured instruction \"{}\" of minion \"{}\":", name.get(), minion.getGameProfile().getName(), e);
Minions.LOGGER.error("Could not deserialize configured instruction \"{}\" of minion \"{}\":", name.get(), minion.getGameProfile().name(), e);
}
}
}
@@ -3,10 +3,6 @@ package io.github.skippyall.minions.minion.fakeplayer;
import io.github.skippyall.minions.mixins.EntityAccessor;
import java.util.EnumMap;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import net.minecraft.commands.arguments.EntityAnchorArgument;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
@@ -18,11 +14,11 @@ import net.minecraft.util.Mth;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.InteractionResult;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.animal.horse.AbstractHorse;
import net.minecraft.world.entity.animal.equine.AbstractHorse;
import net.minecraft.world.entity.decoration.ItemFrame;
import net.minecraft.world.entity.player.Inventory;
import net.minecraft.world.entity.vehicle.Boat;
import net.minecraft.world.entity.vehicle.Minecart;
import net.minecraft.world.entity.vehicle.boat.Boat;
import net.minecraft.world.entity.vehicle.minecart.Minecart;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.phys.BlockHitResult;
@@ -31,6 +27,11 @@ import net.minecraft.world.phys.HitResult;
import net.minecraft.world.phys.Vec2;
import net.minecraft.world.phys.Vec3;
import java.util.EnumMap;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class EntityPlayerActionPack
{
private final MinionFakePlayer player;
@@ -215,7 +216,7 @@ public class EntityPlayerActionPack
if (closest instanceof AbstractHorse && onlyRideables)
((AbstractHorse) closest).mobInteract(player, InteractionHand.MAIN_HAND);
else
player.startRiding(closest, !onlyRideables);
player.startRiding(closest, !onlyRideables, true);
return this;
}
public EntityPlayerActionPack dismount()
@@ -352,13 +353,13 @@ public class EntityPlayerActionPack
boolean handWasEmpty = player.getItemInHand(hand).isEmpty();
boolean itemFrameEmpty = (entity instanceof ItemFrame) && ((ItemFrame) entity).getItem().isEmpty();
Vec3 relativeHitPos = entityHit.getLocation().subtract(entity.getX(), entity.getY(), entity.getZ());
if (entity.interactAt(player, relativeHitPos, hand).consumesAction())
if (entity.interact(player, hand, relativeHitPos).consumesAction())
{
ap.itemUseCooldown = 3;
return true;
}
// fix for SS itemframe always returns CONSUME even if no action is performed
if (player.interactOn(entity, hand).consumesAction() && !(handWasEmpty && itemFrameEmpty))
if (player.interactOn(entity, hand, relativeHitPos).consumesAction() && !(handWasEmpty && itemFrameEmpty))
{
ap.itemUseCooldown = 3;
return true;
@@ -485,7 +486,8 @@ public class EntityPlayerActionPack
{
if (action.limit == 1)
{
if (player.onGround()) player.jumpFromGround(); // onGround
if (player.onGround()) player.jumpFromGround();
else if (!player.onClimbable()) player.tryToStartFallFlying();
}
else
{
@@ -1,11 +1,14 @@
//code from https://github.com/gnembon/fabric-carpet
package io.github.skippyall.minions.minion.fakeplayer;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.embedded.EmbeddedChannel;
import net.minecraft.network.Connection;
import net.minecraft.network.PacketListener;
import net.minecraft.network.ProtocolInfo;
import net.minecraft.network.protocol.Packet;
import net.minecraft.network.protocol.PacketFlow;
import org.jspecify.annotations.Nullable;
public class FakeClientConnection extends Connection {
public FakeClientConnection(PacketFlow p)
@@ -16,6 +19,11 @@ public class FakeClientConnection extends Connection {
((ClientConnectionInterface)this).setChannel(new EmbeddedChannel());
}
@Override
public void send(Packet<?> packet, @Nullable ChannelFutureListener listener, boolean flush) {
}
@Override
public void setReadOnly()
{
@@ -3,6 +3,7 @@ package io.github.skippyall.minions.minion.fakeplayer;
import com.mojang.authlib.GameProfile;
import com.mojang.authlib.properties.PropertyMap;
import io.github.skippyall.minions.Minions;
import io.github.skippyall.minions.gui.minion.MinionGui;
import io.github.skippyall.minions.listener.SerializableListenerManager;
import io.github.skippyall.minions.minion.MinionData;
@@ -15,6 +16,7 @@ import io.github.skippyall.minions.module.ModuleInventory;
import io.github.skippyall.minions.registration.MinionConfigOptions;
import io.github.skippyall.minions.registration.MinionItems;
import io.github.skippyall.minions.registration.SpecialAbilities;
import net.fabricmc.fabric.impl.networking.context.PacketContextImpl;
import net.minecraft.core.BlockPos;
import net.minecraft.network.DisconnectionDetails;
import net.minecraft.network.chat.Component;
@@ -29,6 +31,7 @@ import net.minecraft.server.level.ClientInformation;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.server.network.CommonListenerCookie;
import net.minecraft.util.ProblemReporter;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.InteractionResult;
import net.minecraft.world.damagesource.DamageSource;
@@ -37,18 +40,20 @@ import net.minecraft.world.entity.EquipmentSlot;
import net.minecraft.world.entity.ai.attributes.Attributes;
import net.minecraft.world.entity.item.ItemEntity;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.entity.vehicle.AbstractBoat;
import net.minecraft.world.entity.vehicle.boat.AbstractBoat;
import net.minecraft.world.food.FoodData;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.GameType;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.portal.TeleportTransition;
import net.minecraft.world.level.storage.TagValueInput;
import net.minecraft.world.level.storage.ValueInput;
import net.minecraft.world.level.storage.ValueOutput;
import net.minecraft.world.phys.Vec2;
import net.minecraft.world.phys.Vec3;
import org.jetbrains.annotations.Nullable;
import java.util.Optional;
import java.util.Set;
import java.util.function.Consumer;
@@ -82,7 +87,17 @@ public class MinionFakePlayer extends ServerPlayer {
if(pos != null && rot != null) {
instance.fixStartingPosition = () -> instance.snapTo(pos.x, pos.y, pos.z, rot.x, rot.y);
}
server.getPlayerList().placeNewPlayer(new FakeClientConnection(PacketFlow.SERVERBOUND), instance, new CommonListenerCookie(profile, 0, instance.clientInformation(), false));
FakeClientConnection connection = new FakeClientConnection(PacketFlow.SERVERBOUND);
//noinspection UnstableApiUsage
connection.getPacketContext().set(PacketContextImpl.REGISTRY_ACCESS, server.registryAccess());
//noinspection UnstableApiUsage
connection.getPacketContext().set(PacketContextImpl.SERVER_INSTANCE, server);
//noinspection UnstableApiUsage
connection.getPacketContext().set(PacketContextImpl.GAME_PROFILE, profile);
server.getPlayerList().placeNewPlayer(connection, instance, new CommonListenerCookie(profile, 0, instance.clientInformation(), false));
loadPlayerData(instance);
instance.stopRiding(); // otherwise the created fake player will be on the vehicle
System.out.println(instance.position());
if(pos != null && rot != null) {
instance.teleportTo(level, pos.x, pos.y, pos.z, Set.of(), rot.x, rot.y, true);
@@ -102,6 +117,19 @@ public class MinionFakePlayer extends ServerPlayer {
instance.listeners().forEach(listener -> listener.onMinionSpawn(instance));
}
private static void loadPlayerData(MinionFakePlayer player)
{
try (ProblemReporter.ScopedCollector scopedCollector = new ProblemReporter.ScopedCollector(player.problemPath(), Minions.LOGGER))
{
Optional<ValueInput> optional = player.level().getServer().getPlayerList().loadPlayerData(player.nameAndId()).map((compoundTag) -> TagValueInput.create(scopedCollector, player.registryAccess(), compoundTag));
optional.ifPresent( valueInput -> {
player.load(valueInput);
player.loadAndSpawnEnderPearls(valueInput);
player.loadAndSpawnParentVehicle(valueInput);
});
}
}
public static MinionFakePlayer respawnFake(MinecraftServer server, ServerLevel level, GameProfile profile, ClientInformation cli)
{
return new MinionFakePlayer(server, level, profile, cli);
@@ -153,19 +181,18 @@ public class MinionFakePlayer extends ServerPlayer {
return canSpawnMobs();
}
public MinecraftServer getServer() {
return level().getServer();
}
@Override
public InteractionResult interact(Player player, InteractionHand hand) {
public InteractionResult interact(Player player, InteractionHand hand, Vec3 location) {
if(player instanceof ServerPlayer spe) {
new MinionGui(spe, this);
}
return InteractionResult.CONSUME;
}
@Override
public InteractionResult interactAt(Player player, Vec3 hitPos, InteractionHand hand) {
return interact(player, hand);
}
@Override
public void onEquipItem(final EquipmentSlot slot, final ItemStack previous, final ItemStack stack)
{
@@ -213,8 +240,8 @@ public class MinionFakePlayer extends ServerPlayer {
}
@Override
public boolean startRiding(Entity entityToRide, boolean force) {
if (super.startRiding(entityToRide, force)) {
public boolean startRiding(Entity entityToRide, boolean force, boolean sendEventAndTriggers) {
if (super.startRiding(entityToRide, force, sendEventAndTriggers)) {
// from ClientPacketListener.handleSetEntityPassengersPacket
if (entityToRide instanceof AbstractBoat) {
this.yRotO = entityToRide.getYRot();
@@ -4,13 +4,13 @@ package io.github.skippyall.minions.minion.fakeplayer;
import net.minecraft.network.Connection;
import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.contents.TranslatableContents;
import net.minecraft.network.protocol.Packet;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.server.network.CommonListenerCookie;
import net.minecraft.server.network.ServerGamePacketListenerImpl;
import net.minecraft.world.entity.PositionMoveRotation;
import net.minecraft.world.entity.Relative;
import java.util.Set;
public class NetHandlerPlayServerFake extends ServerGamePacketListenerImpl
@@ -20,11 +20,6 @@ public class NetHandlerPlayServerFake extends ServerGamePacketListenerImpl
super(minecraftServer, connection, serverPlayer, i);
}
@Override
public void send(final Packet<?> packetIn)
{
}
@Override
public void disconnect(Component message)
{
@@ -1,8 +1,6 @@
//code from https://github.com/gnembon/fabric-carpet
package io.github.skippyall.minions.minion.fakeplayer;
import java.util.Optional;
import java.util.function.Predicate;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.level.ClipContext;
import net.minecraft.world.level.Level;
@@ -12,6 +10,9 @@ import net.minecraft.world.phys.EntityHitResult;
import net.minecraft.world.phys.HitResult;
import net.minecraft.world.phys.Vec3;
import java.util.Optional;
import java.util.function.Predicate;
public class Tracer
{
public static HitResult rayTrace(Entity source, float partialTicks, double reach, boolean fluids)
@@ -8,7 +8,7 @@ import io.github.skippyall.minions.program.supplier.Parameter;
import io.github.skippyall.minions.program.supplier.ParameterValueList;
import io.github.skippyall.minions.registration.ValueTypes;
import net.minecraft.world.inventory.AbstractContainerMenu;
import net.minecraft.world.inventory.ClickType;
import net.minecraft.world.inventory.ContainerInput;
import net.minecraft.world.inventory.Slot;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.storage.ValueInput;
@@ -93,7 +93,7 @@ public class SwapItemExecution implements InstructionExecution<MinionRuntime> {
AbstractContainerMenu screenHandler = getScreen(minion, screen);
ItemStack previousCursor = screenHandler.getCarried();
screenHandler.setCarried(cursor);
screenHandler.clicked(slotIndex, 0, ClickType.SWAP, minion);
screenHandler.clicked(slotIndex, 0, ContainerInput.SWAP, minion);
cursor = screenHandler.getCarried();
screenHandler.setCarried(previousCursor);
}
@@ -3,9 +3,10 @@ package io.github.skippyall.minions.minion.program.instruction.move;
import com.mojang.serialization.Codec;
import io.github.skippyall.minions.gui.Displayable;
import io.github.skippyall.minions.gui.GuiDisplay;
import java.util.UUID;
import net.minecraft.util.StringRepresentable;
import java.util.UUID;
public enum TurnDirection implements StringRepresentable, Displayable {
LEFT("left", -1, 0),
UP("up", 0, -1),
@@ -16,15 +16,15 @@ import io.github.skippyall.minions.registration.MinionComponentTypes;
import io.github.skippyall.minions.registration.MinionItems;
import io.github.skippyall.minions.registration.ValueSuppliers;
import io.github.skippyall.minions.registration.ValueTypes;
import org.jetbrains.annotations.Nullable;
import java.util.concurrent.CompletableFuture;
import net.minecraft.core.BlockPos;
import net.minecraft.network.chat.Component;
import net.minecraft.resources.ResourceKey;
import net.minecraft.world.inventory.MenuType;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.Level;
import org.jetbrains.annotations.Nullable;
import java.util.concurrent.CompletableFuture;
public class AnalogInputSupplier implements ValueSupplier<Long, MinionRuntime> {
public static final Codec<AnalogInputSupplier> CODEC = RecordCodecBuilder.create(instance ->
@@ -63,7 +63,7 @@ public class AnalogInputSupplier implements ValueSupplier<Long, MinionRuntime> {
@Override
public Component getDisplayText() {
return Component.translatable("value_supplier.minions.analog_input.display", analogInputPos.toShortString(), analogInputWorld.location().toString());
return Component.translatable("value_supplier.minions.analog_input.display", analogInputPos.toShortString(), analogInputWorld.identifier().toString());
}
public static class AnalogInputSupplierType extends ValueSupplierType<MinionRuntime> {
@@ -79,19 +79,21 @@ public class AnalogInputSupplier implements ValueSupplier<Long, MinionRuntime> {
public <T> CompletableFuture<ValueSupplier<?, MinionRuntime>> openConfiguration(MinionsGui parent, ValueType<T> valueType, @Nullable ValueSupplier<?, MinionRuntime> previous) {
CompletableFuture<ValueSupplier<?, MinionRuntime>> future = new CompletableFuture<>();
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
public void onClose() {
public void onPlayerClose(boolean success) {
onClose.run();
}
};
gui.setTitle(Component.translatable("value_supplier.minions.analog_input"));
gui.setSlot(2, me.backButton());
gui.setSlot(4, new GuiElementBuilder(MinionItems.REFERENCE_ITEM)
.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) {
future.complete(new AnalogInputSupplier(pos.world(), pos.pos()));
me.goBack();
}
})
.setItemName(Component.translatable("value_supplier.minions.analog_input.config.click_with_reference"))
@@ -1,20 +1,19 @@
package io.github.skippyall.minions.minion.skin;
import com.google.common.collect.ImmutableMultimap;
import com.mojang.authlib.GameProfile;
import com.mojang.authlib.properties.Property;
import com.mojang.authlib.properties.PropertyMap;
import io.github.skippyall.minions.Minions;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import io.github.skippyall.minions.gui.MinionsGui;
import net.fabricmc.fabric.api.entity.FakePlayer;
import net.minecraft.core.Holder;
import net.minecraft.core.registries.Registries;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.Tag;
import net.minecraft.network.chat.Component;
import net.minecraft.resources.Identifier;
import net.minecraft.resources.ResourceKey;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.dialog.ActionButton;
import net.minecraft.server.dialog.CommonButtonData;
import net.minecraft.server.dialog.CommonDialogData;
@@ -24,20 +23,26 @@ import net.minecraft.server.dialog.Input;
import net.minecraft.server.dialog.NoticeDialog;
import net.minecraft.server.dialog.action.CustomAll;
import net.minecraft.server.dialog.input.TextInput;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.item.component.ResolvableProfile;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
public class Base64SkinProvider implements SkinProvider {
public static final ResourceKey<Dialog> DIALOG = ResourceKey.create(Registries.DIALOG, ResourceLocation.fromNamespaceAndPath(Minions.MOD_ID, "base_64_input"));
public static final ResourceLocation CUSTOM_DIALOG_ACTION = ResourceLocation.fromNamespaceAndPath(Minions.MOD_ID, "base_64_submit");
public static final ResourceKey<Dialog> DIALOG = ResourceKey.create(Registries.DIALOG, Identifier.fromNamespaceAndPath(Minions.MOD_ID, "base_64_input"));
public static final Identifier CUSTOM_DIALOG_ACTION = Identifier.fromNamespaceAndPath(Minions.MOD_ID, "base_64_submit");
private static long dialogIdCounter = 0;
private static Map<Long, CompletableFuture<Optional<PropertyMap>>> futures = new HashMap<>();
private static Map<Long, CompletableFuture<ResolvableProfile>> futures = new HashMap<>();
@Override
public CompletableFuture<Optional<PropertyMap>> openSkinMenu(ServerPlayer player) {
public CompletableFuture<ResolvableProfile> openSkinMenu(MinionsGui parent) {
dialogIdCounter++;
player.openDialog(getDialog());
CompletableFuture<Optional<PropertyMap>> future = new CompletableFuture<>();
parent.viewer.openDialog(getDialog());
CompletableFuture<ResolvableProfile> future = new CompletableFuture<>();
futures.put(dialogIdCounter, future);
return future;
}
@@ -48,10 +53,11 @@ public class Base64SkinProvider implements SkinProvider {
Optional<String> base64 = compound.getString("base_64");
if(id.isPresent() && base64.isPresent() && !base64.get().isBlank()) {
if(futures.containsKey(id.get())) {
PropertyMap map = new PropertyMap();
map.put("textures", new Property("textures", base64.get().strip()));
PropertyMap map = new PropertyMap(ImmutableMultimap.of(
"textures", new Property("textures", base64.get().strip())
));
futures.get(id.get()).complete(Optional.of(map));
futures.get(id.get()).complete(ResolvableProfile.createResolved(new GameProfile(FakePlayer.DEFAULT_UUID, "", map)));
futures.remove(id.get());
}
}
@@ -1,20 +1,17 @@
package io.github.skippyall.minions.minion.skin;
import com.mojang.authlib.GameProfile;
import com.mojang.authlib.properties.PropertyMap;
import io.github.skippyall.minions.gui.MinionsGui;
import io.github.skippyall.minions.gui.input.TextInput;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import net.minecraft.network.chat.Component;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.level.block.entity.SkullBlockEntity;
import net.minecraft.world.item.component.ResolvableProfile;
import java.util.concurrent.CompletableFuture;
public class NameSkinProvider implements SkinProvider {
@Override
public CompletableFuture<Optional<PropertyMap>> openSkinMenu(ServerPlayer player) {
return TextInput.inputString(player, Component.translatable("minions.gui.look.skin.name.title"), "")
.thenCompose(SkullBlockEntity::fetchGameProfile)
.thenApply(gameProfile -> gameProfile.map(GameProfile::getProperties));
public CompletableFuture<ResolvableProfile> openSkinMenu(MinionsGui parent) {
return TextInput.inputStringFuture(parent, Component.translatable("minions.gui.look.skin.name.title"), "")
.thenApply(name -> name != null ? ResolvableProfile.createUnresolved(name) : null);
}
@Override
@@ -1,13 +1,13 @@
package io.github.skippyall.minions.minion.skin;
import com.mojang.authlib.properties.PropertyMap;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import io.github.skippyall.minions.gui.MinionsGui;
import net.minecraft.network.chat.Component;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.item.component.ResolvableProfile;
import java.util.concurrent.CompletableFuture;
public interface SkinProvider {
CompletableFuture<Optional<PropertyMap>> openSkinMenu(ServerPlayer player);
CompletableFuture<ResolvableProfile> openSkinMenu(MinionsGui parent);
Component getDisplayName();
}
@@ -1,21 +1,17 @@
package io.github.skippyall.minions.minion.skin;
import com.mojang.authlib.GameProfile;
import com.mojang.authlib.properties.PropertyMap;
import io.github.skippyall.minions.gui.MinionsGui;
import io.github.skippyall.minions.gui.input.TextInput;
import java.util.Optional;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;
import net.minecraft.network.chat.Component;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.level.block.entity.SkullBlockEntity;
import net.minecraft.world.item.component.ResolvableProfile;
import java.util.concurrent.CompletableFuture;
public class UUIDSkinProvider implements SkinProvider {
@Override
public CompletableFuture<Optional<PropertyMap>> openSkinMenu(ServerPlayer player) {
return TextInput.inputString(player, Component.translatable("minions.gui.look.skin.uuid.title"), "")
.thenCompose(uuidString -> SkullBlockEntity.fetchGameProfile(UUID.fromString(uuidString)))
.thenApply(gameProfile -> gameProfile.map(GameProfile::getProperties));
public CompletableFuture<ResolvableProfile> openSkinMenu(MinionsGui parent) {
return TextInput.inputStringFuture(parent, Component.translatable("minions.gui.look.skin.uuid.title"), "")
.thenApply(name -> name != null ? ResolvableProfile.createUnresolved(name) : null);
}
@Override
@@ -1,8 +1,9 @@
package io.github.skippyall.minions.mixinhelper;
import java.util.function.Predicate;
import net.minecraft.world.entity.Entity;
import java.util.function.Predicate;
public class EntityViewMixinHelper {
public static final ThreadLocal<Predicate<Entity>> ADDITIONAL_PREDICATE = ThreadLocal.withInitial(() -> entity -> true);
}
@@ -1,10 +1,10 @@
package io.github.skippyall.minions.mixins;
import net.minecraft.world.entity.Entity;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Invoker;
import java.util.stream.Stream;
import net.minecraft.world.entity.Entity;
@Mixin(Entity.class)
public interface EntityAccessor {
@@ -12,5 +12,5 @@ public interface EntityAccessor {
boolean minions$canAddPassenger(Entity other);
@Invoker("getIndirectPassengersStream")
Stream<Entity> minions$streamIntoPassengers();
Stream<Entity> minions$getIndirectPassengersStream();
}
@@ -1,14 +1,14 @@
package io.github.skippyall.minions.mixins;
import io.github.skippyall.minions.mixinhelper.EntityViewMixinHelper;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.level.EntityGetter;
import org.jetbrains.annotations.Nullable;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.ModifyArg;
import java.util.function.Predicate;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.level.EntityGetter;
@Mixin(EntityGetter.class)
public interface EntityGetterMixin {
@@ -22,6 +22,6 @@ public abstract class EntityMixin {
@Inject(method = "isLocalInstanceAuthoritative", at = @At("HEAD"), cancellable = true)
private void isFakePlayer(CallbackInfoReturnable<Boolean> cir)
{
if (getControllingPassenger() instanceof MinionFakePlayer) cir.setReturnValue(!level.isClientSide);
if (getControllingPassenger() instanceof MinionFakePlayer) cir.setReturnValue(!level.isClientSide());
}
}
@@ -5,7 +5,7 @@ import io.github.skippyall.minions.minion.fakeplayer.MinionFakePlayer;
import io.github.skippyall.minions.minion.skin.Base64SkinProvider;
import io.github.skippyall.minions.registration.MinionConfigOptions;
import net.minecraft.nbt.Tag;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.resources.Identifier;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.level.ServerPlayer;
import org.spongepowered.asm.mixin.Mixin;
@@ -29,7 +29,7 @@ public class MinecraftServerMixin {
}
@Inject(method = "handleCustomClickAction", at = @At("HEAD"), cancellable = true)
private void onCustomClickAction(ResourceLocation id, Optional<Tag> payload, CallbackInfo ci) {
private void onCustomClickAction(Identifier id, Optional<Tag> payload, CallbackInfo ci) {
if(id.equals(Base64SkinProvider.CUSTOM_DIALOG_ACTION)) {
Base64SkinProvider.onCustomDialogAction(payload);
ci.cancel();
@@ -18,23 +18,20 @@ import net.minecraft.server.level.ServerPlayer;
import net.minecraft.server.network.CommonListenerCookie;
import net.minecraft.server.network.ServerGamePacketListenerImpl;
import net.minecraft.server.players.PlayerList;
import net.minecraft.util.ProblemReporter;
import net.minecraft.world.level.storage.ValueInput;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
@Mixin(PlayerList.class)
public class PlayerListMixin {
@Inject(method = "load", at = @At(value = "RETURN", shift = At.Shift.BEFORE))
private void fixStartingPos(ServerPlayer player, ProblemReporter errorReporter, CallbackInfoReturnable<Optional<ValueInput>> cir)
@Inject(method = "placeNewPlayer", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerPlayer;level()Lnet/minecraft/server/level/ServerLevel;"))
private void fixStartingPos(Connection connection, ServerPlayer player, CommonListenerCookie cookie, CallbackInfo ci)
{
if (player instanceof MinionFakePlayer)
{
@@ -16,7 +16,7 @@ public abstract class PlayerMixin {
* To make sure player attacks are able to knockback fake players
*/
@ModifyExpressionValue(
method = "attack",
method = "causeExtraKnockback",
at = @At(
value = "FIELD",
target = "Lnet/minecraft/world/entity/Entity;hurtMarked:Z",
@@ -1,3 +1,4 @@
//code from https://github.com/gnembon/fabric-carpet
package io.github.skippyall.minions.mixins;
import com.llamalad7.mixinextras.injector.ModifyReturnValue;
@@ -22,7 +23,7 @@ public abstract class TickRateManagerMixin {
return !isActualPlayer(entity) && // not carrying players
((EntityAccessor) entity)
.minions$streamIntoPassengers()
.minions$getIndirectPassengersStream()
.noneMatch(TickRateManagerMixin::isActualPlayer);
}
@@ -18,9 +18,9 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
@Mixin(value = DistanceManager.FixedPlayerDistanceChunkTracker.class)
public abstract class DistanceManager$FixedPlayerDistanceChunkTrackerMixin extends ChunkTrackerMixin implements ChunkLevelManager$DistanceFromNearestPlayerTrackerAccessor {
@Final
@Shadow
DistanceManager field_17462;
@Final
DistanceManager this$0;
@Shadow
@Final
@@ -40,7 +40,7 @@ public abstract class DistanceManager$FixedPlayerDistanceChunkTrackerMixin exten
@Override
public boolean minions$isRealPlayerInChunk(long chunkPos) {
ObjectSet<ServerPlayer> players = ((ChunkLevelManagerAccessor)field_17462).minions$getPlayers(chunkPos);
ObjectSet<ServerPlayer> players = ((ChunkLevelManagerAccessor)this$0).minions$getPlayers(chunkPos);
boolean contains = false;
if(players != null) {
contains = players.stream().anyMatch(player -> {
@@ -56,14 +56,14 @@ public abstract class DistanceManager$FixedPlayerDistanceChunkTrackerMixin exten
@Inject(method = "runAllUpdates", at = @At("HEAD"))
public void minions$sync(CallbackInfo info) {
if (minions$target) {
((ChunkLevelManagerAccessor)field_17462).minions$getMinionless().runAllUpdates();
((ChunkLevelManagerAccessor)this$0).minions$getMinionless().runAllUpdates();
}
}
@Override
public void minions$updateLevel(long chunkPos, int distance, boolean decrease, CallbackInfo info) {
if (minions$target && (distance == Integer.MAX_VALUE || minions$isRealPlayerInChunk(chunkPos))) {
((ChunkLevelManagerAccessor)field_17462).minions$getMinionless().update(chunkPos, distance, decrease);
((ChunkLevelManagerAccessor)this$0).minions$getMinionless().update(chunkPos, distance, decrease);
}
}
@@ -5,6 +5,10 @@ import io.github.skippyall.minions.mixinhelper.antimobcap.ChunkLevelManager$Dist
import io.github.skippyall.minions.mixinhelper.antimobcap.ChunkLevelManagerAccessor;
import it.unimi.dsi.fastutil.longs.Long2ObjectMap;
import it.unimi.dsi.fastutil.objects.ObjectSet;
import net.minecraft.core.SectionPos;
import net.minecraft.server.level.DistanceManager;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.level.TicketStorage;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
@@ -14,10 +18,6 @@ import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import java.util.concurrent.Executor;
import net.minecraft.core.SectionPos;
import net.minecraft.server.level.DistanceManager;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.level.TicketStorage;
@Mixin(DistanceManager.class)
public class DistanceManagerMixin implements ChunkLevelManagerAccessor {
@@ -10,7 +10,7 @@ import org.spongepowered.asm.mixin.injection.ModifyArg;
@Mixin(Grave.class)
public class GraveMixin {
@ModifyArg(method = "createBlock", at = @At(value = "INVOKE", target = "Leu/pb4/graves/grave/Grave;<init>(JLcom/mojang/authlib/GameProfile;BLnet/minecraft/world/entity/HumanoidArm;Lnet/minecraft/core/BlockPos;Lnet/minecraft/resources/ResourceLocation;Leu/pb4/graves/grave/GraveType;JJILnet/minecraft/network/chat/Component;Ljava/util/Collection;Ljava/util/Collection;ZI)V"))
@ModifyArg(method = "createBlock", at = @At(value = "INVOKE", target = "Leu/pb4/graves/grave/Grave;<init>(JLcom/mojang/authlib/GameProfile;BLnet/minecraft/world/entity/HumanoidArm;Lnet/minecraft/core/BlockPos;Lnet/minecraft/resources/Identifier;Leu/pb4/graves/grave/GraveType;JJILnet/minecraft/network/chat/Component;Ljava/util/Collection;Ljava/util/Collection;ZI)V"))
private static boolean createGrave(boolean profile, @Local(argsOnly = true) ServerPlayer player) {
if(player instanceof MinionFakePlayer) {
return false;
@@ -4,9 +4,6 @@ import io.github.skippyall.minions.minion.MinionRuntime;
import io.github.skippyall.minions.minion.fakeplayer.MinionFakePlayer;
import io.github.skippyall.minions.program.instruction.InstructionType;
import io.github.skippyall.minions.registration.MinionComponentTypes;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
import net.minecraft.network.chat.Component;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.ContainerHelper;
@@ -16,6 +13,10 @@ import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.storage.ValueInput;
import net.minecraft.world.level.storage.ValueOutput;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
public class ModuleInventory extends SimpleContainer {
private final Set<MinionModule> modules = new HashSet<>();
private final Set<InstructionType<MinionRuntime>> instructions = new HashSet<>();
@@ -3,18 +3,18 @@ package io.github.skippyall.minions.polymer;
import eu.pb4.polymer.networking.api.PolymerNetworking;
import eu.pb4.polymer.networking.api.server.PolymerServerNetworking;
import io.github.skippyall.minions.Minions;
import net.fabricmc.fabric.api.networking.v1.context.PacketContext;
import net.minecraft.network.codec.StreamCodec;
import net.minecraft.network.protocol.common.custom.CustomPacketPayload;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.resources.Identifier;
import net.minecraft.server.network.ServerGamePacketListenerImpl;
import xyz.nucleoid.packettweaker.PacketContext;
public class VersionSync {
public static final int NETWORK_VERSION = 1;
public static boolean isOnClient(PacketContext context) {
if(context.getPlayer() != null) {
return isOnClient(context.getPlayer().connection);
if(context != null && context.get(PacketContext.CONNECTION).getPacketListener() instanceof ServerGamePacketListenerImpl gamePacketListener) {
return isOnClient(gamePacketListener);
}
return false;
}
@@ -25,7 +25,7 @@ public class VersionSync {
public static class VersionSyncPayload implements CustomPacketPayload {
public static final CustomPacketPayload.Type<VersionSyncPayload> PACKET_ID = new CustomPacketPayload.Type<>(ResourceLocation.fromNamespaceAndPath(Minions.MOD_ID, "version_sync"));
public static final CustomPacketPayload.Type<VersionSyncPayload> PACKET_ID = new CustomPacketPayload.Type<>(Identifier.fromNamespaceAndPath(Minions.MOD_ID, "version_sync"));
@Override
public Type<? extends CustomPacketPayload> type() {
@@ -34,6 +34,6 @@ public class VersionSync {
}
public static void register() {
PolymerNetworking.registerS2CVersioned(VersionSyncPayload.PACKET_ID, NETWORK_VERSION, StreamCodec.unit(null));
PolymerNetworking.registerClientboundVersioned(VersionSyncPayload.PACKET_ID, NETWORK_VERSION, StreamCodec.unit(null));
}
}
@@ -3,10 +3,10 @@ package io.github.skippyall.minions.program.consumer;
import com.mojang.serialization.Codec;
import io.github.skippyall.minions.program.InstructionRuntime;
import io.github.skippyall.minions.program.value.ValueType;
import net.minecraft.server.level.ServerPlayer;
import org.jetbrains.annotations.Nullable;
import java.util.concurrent.CompletableFuture;
import net.minecraft.server.level.ServerPlayer;
public abstract class ValueConsumerType<R extends InstructionRuntime<R>> {
public abstract <T> Codec<? extends ValueConsumer<T,R>> getCodec(ValueType<T> type);
@@ -9,10 +9,10 @@ import io.github.skippyall.minions.program.value.ValueType;
import io.github.skippyall.minions.registration.MinionRegistries;
import io.github.skippyall.minions.registration.ValueConverters;
import io.github.skippyall.minions.util.TranslationUtil;
import net.minecraft.network.chat.Component;
import org.jetbrains.annotations.Nullable;
import java.util.concurrent.CompletableFuture;
import net.minecraft.network.chat.Component;
public class CastConverter<F,T> implements ValueConverter<F,T> {
private static final MapCodec<CastConverter<?,?>> CODEC = RecordCodecBuilder.mapCodec(instance -> instance.group(
@@ -4,13 +4,13 @@ import com.mojang.serialization.Codec;
import io.github.skippyall.minions.gui.input.Result;
import io.github.skippyall.minions.program.value.TypedValue;
import io.github.skippyall.minions.program.value.ValueType;
import net.minecraft.network.chat.Component;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.List;
import java.util.ListIterator;
import java.util.Objects;
import net.minecraft.network.chat.Component;
public class ConverterList {
public static final Codec<ConverterList> CODEC = ValueConverter.CODEC.listOf().xmap(ConverterList::new, l -> l.converters);
@@ -7,10 +7,10 @@ import io.github.skippyall.minions.program.value.ValueType;
import io.github.skippyall.minions.registration.MinionRegistries;
import io.github.skippyall.minions.registration.ValueConverters;
import io.github.skippyall.minions.registration.ValueTypes;
import net.minecraft.network.chat.Component;
import org.jetbrains.annotations.Nullable;
import java.util.concurrent.CompletableFuture;
import net.minecraft.network.chat.Component;
public class EqualityConverter<F> implements ValueConverter<F, Boolean> {
public static final MapCodec<EqualityConverter<?>> CODEC = MinionRegistries.VALUE_TYPES.byNameCodec().dispatchMap(
@@ -3,7 +3,6 @@ package io.github.skippyall.minions.program.instruction;
import io.github.skippyall.minions.program.InstructionRuntime;
import io.github.skippyall.minions.program.consumer.ValueConsumerList;
import io.github.skippyall.minions.program.supplier.ParameterValueList;
import io.github.skippyall.minions.program.supplier.ValueSupplierList;
import net.minecraft.world.level.storage.ValueInput;
import net.minecraft.world.level.storage.ValueOutput;
@@ -3,10 +3,11 @@ package io.github.skippyall.minions.program.instruction;
import io.github.skippyall.minions.program.InstructionRuntime;
import io.github.skippyall.minions.program.supplier.Parameter;
import io.github.skippyall.minions.program.supplier.ParameterValueList;
import net.minecraft.world.level.storage.ValueInput;
import java.util.Collection;
import java.util.List;
import java.util.function.Supplier;
import net.minecraft.world.level.storage.ValueInput;
/**
* Defines the semantics of an instruction and creates {@link InstructionExecution}
@@ -9,6 +9,7 @@ import io.github.skippyall.minions.program.conversion.Casts;
import io.github.skippyall.minions.program.conversion.ConverterList;
import io.github.skippyall.minions.program.instruction.InstructionType;
import io.github.skippyall.minions.program.value.TypedValue;
import net.minecraft.network.chat.Component;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
@@ -17,7 +18,6 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Consumer;
import net.minecraft.network.chat.Component;
public class ValueSupplierList<R extends InstructionRuntime<R>> {
private final Map<Parameter<?>, ValueSupplierEntry<?,R>> arguments = new HashMap<>();
@@ -2,10 +2,11 @@ package io.github.skippyall.minions.program.value;
import com.mojang.serialization.Codec;
import io.github.skippyall.minions.gui.MinionsGui;
import net.minecraft.network.chat.Component;
import java.util.concurrent.CompletableFuture;
import java.util.function.BiFunction;
import java.util.function.Function;
import net.minecraft.network.chat.Component;
public record SimpleValueType<T>(Codec<T> codec, T defaultValue, Function<Object, T> checkedCast, BiFunction<MinionsGui, T, CompletableFuture<T>> valueDialogOpener, Function<T, Component> textDisplay) implements ValueType<T> {
@Override
@@ -2,10 +2,10 @@ package io.github.skippyall.minions.program.value;
import com.mojang.serialization.Codec;
import io.github.skippyall.minions.gui.MinionsGui;
import net.minecraft.network.chat.Component;
import org.jetbrains.annotations.Nullable;
import java.util.concurrent.CompletableFuture;
import net.minecraft.network.chat.Component;
public interface ValueType<T> {
CompletableFuture<T> openValueDialog(MinionsGui gui, T previousValue);
@@ -6,11 +6,11 @@ import io.github.skippyall.minions.clipboard.BlockPosClipboard;
import io.github.skippyall.minions.clipboard.Clipboard;
import io.github.skippyall.minions.clipboard.InstructionClipboard;
import net.minecraft.core.Registry;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.resources.Identifier;
public class ClipboardTypes {
private static void register(String id, MapCodec<? extends Clipboard> codec) {
Registry.register(MinionRegistries.CLIPBOARD_TYPES, ResourceLocation.fromNamespaceAndPath(Minions.MOD_ID, id), codec);
Registry.register(MinionRegistries.CLIPBOARD_TYPES, Identifier.fromNamespaceAndPath(Minions.MOD_ID, id), codec);
}
static void register() {
@@ -3,10 +3,10 @@ package io.github.skippyall.minions.registration;
import io.github.skippyall.minions.Minions;
import io.github.skippyall.minions.docs.ReferenceEntry;
import net.minecraft.core.Registry;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.resources.Identifier;
public class DocsEntryTypes {
public static void register() {
Registry.register(MinionRegistries.DOCS_ENTRY_TYPES, ResourceLocation.fromNamespaceAndPath(Minions.MOD_ID, "reference_entry"), ReferenceEntry.CODEC);
Registry.register(MinionRegistries.DOCS_ENTRY_TYPES, Identifier.fromNamespaceAndPath(Minions.MOD_ID, "reference_entry"), ReferenceEntry.CODEC);
}
}
@@ -3,13 +3,13 @@ package io.github.skippyall.minions.registration;
import io.github.skippyall.minions.Minions;
import io.github.skippyall.minions.gui.GuiDisplay;
import net.minecraft.core.Registry;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.resources.Identifier;
public class GuiDisplayTypes {
static void register() {
Registry.register(MinionRegistries.GUI_DISPLAY_TYPE, ResourceLocation.fromNamespaceAndPath(Minions.MOD_ID, "item"), GuiDisplay.ItemBased.CODEC);
Registry.register(MinionRegistries.GUI_DISPLAY_TYPE, ResourceLocation.fromNamespaceAndPath(Minions.MOD_ID, "model"), GuiDisplay.ModelBased.CODEC);
Registry.register(MinionRegistries.GUI_DISPLAY_TYPE, ResourceLocation.fromNamespaceAndPath(Minions.MOD_ID, "head"), GuiDisplay.HeadBased.CODEC);
Registry.register(MinionRegistries.GUI_DISPLAY_TYPE, ResourceLocation.fromNamespaceAndPath(Minions.MOD_ID, "stack"), GuiDisplay.StackBased.CODEC);
Registry.register(MinionRegistries.GUI_DISPLAY_TYPE, Identifier.fromNamespaceAndPath(Minions.MOD_ID, "item"), GuiDisplay.ItemBased.CODEC);
Registry.register(MinionRegistries.GUI_DISPLAY_TYPE, Identifier.fromNamespaceAndPath(Minions.MOD_ID, "model"), GuiDisplay.ModelBased.CODEC);
Registry.register(MinionRegistries.GUI_DISPLAY_TYPE, Identifier.fromNamespaceAndPath(Minions.MOD_ID, "head"), GuiDisplay.HeadBased.CODEC);
Registry.register(MinionRegistries.GUI_DISPLAY_TYPE, Identifier.fromNamespaceAndPath(Minions.MOD_ID, "stack"), GuiDisplay.StackBased.CODEC);
}
}
@@ -13,11 +13,12 @@ import io.github.skippyall.minions.minion.program.instruction.move.WalkExecution
import io.github.skippyall.minions.program.instruction.InstructionExecution;
import io.github.skippyall.minions.program.instruction.InstructionType;
import io.github.skippyall.minions.program.supplier.Parameter;
import net.minecraft.core.Registry;
import net.minecraft.resources.Identifier;
import java.util.Collection;
import java.util.List;
import java.util.function.Supplier;
import net.minecraft.core.Registry;
import net.minecraft.resources.ResourceLocation;
public class Instructions {
public static final InstructionType<MinionRuntime> WALK = register(
@@ -64,7 +65,7 @@ public class Instructions {
);
private static InstructionType<MinionRuntime> register(String id, Supplier<InstructionExecution<MinionRuntime>> factory, Collection<Parameter<?>> parameters, Collection<Parameter<?>> returnParameters) {
ResourceLocation identifier = ResourceLocation.fromNamespaceAndPath(Minions.MOD_ID, id);
Identifier identifier = Identifier.fromNamespaceAndPath(Minions.MOD_ID, id);
return Registry.register(MinionRegistries.INSTRUCTION_TYPES, identifier, new InstructionType<>(factory, parameters, returnParameters));
}
@@ -9,15 +9,15 @@ import net.fabricmc.fabric.api.object.builder.v1.block.entity.FabricBlockEntityT
import net.minecraft.core.Registry;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.core.registries.Registries;
import net.minecraft.resources.Identifier;
import net.minecraft.resources.ResourceKey;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.level.block.SoundType;
import net.minecraft.world.level.block.entity.BlockEntityType;
import net.minecraft.world.level.block.state.BlockBehaviour;
import net.minecraft.world.level.material.PushReaction;
public class MinionBlocks {
public static final ResourceLocation MINION_TRIGGER_ID = ResourceLocation.fromNamespaceAndPath(Minions.MOD_ID, "minion_trigger");
public static final Identifier MINION_TRIGGER_ID = Identifier.fromNamespaceAndPath(Minions.MOD_ID, "minion_trigger");
public static final MinionTriggerBlock MINION_TRIGGER_BLOCK = Registry.register(
BuiltInRegistries.BLOCK,
MINION_TRIGGER_ID,
@@ -36,7 +36,7 @@ public class MinionBlocks {
FabricBlockEntityTypeBuilder.create(MinionTriggerBlockEntity::new, MINION_TRIGGER_BLOCK).build()
);
public static final ResourceLocation ANALOG_INPUT_BLOCK_ID = ResourceLocation.fromNamespaceAndPath(Minions.MOD_ID, "analog_input");
public static final Identifier ANALOG_INPUT_BLOCK_ID = Identifier.fromNamespaceAndPath(Minions.MOD_ID, "analog_input");
public static final AnalogInputBlock ANALOG_INPUT_BLOCK = Registry.register(
BuiltInRegistries.BLOCK,
ANALOG_INPUT_BLOCK_ID,
@@ -4,12 +4,12 @@ import eu.pb4.polymer.core.api.other.PolymerComponent;
import io.github.skippyall.minions.Minions;
import io.github.skippyall.minions.clipboard.Clipboard;
import io.github.skippyall.minions.module.MinionModule;
import net.fabricmc.fabric.api.item.v1.ComponentTooltipAppenderRegistry;
import net.fabricmc.fabric.api.item.v1.ItemComponentTooltipProviderRegistry;
import net.minecraft.core.Registry;
import net.minecraft.core.UUIDUtil;
import net.minecraft.core.component.DataComponentType;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.resources.Identifier;
import java.util.UUID;
public class MinionComponentTypes {
@@ -18,12 +18,12 @@ public class MinionComponentTypes {
public static final DataComponentType<Clipboard> REFERENCE = register("reference", DataComponentType.<Clipboard>builder().persistent(Clipboard.CODEC).build());
private static <T extends DataComponentType<?>> T register(String name, T type) {
Registry.register(BuiltInRegistries.DATA_COMPONENT_TYPE, ResourceLocation.fromNamespaceAndPath(Minions.MOD_ID, name), type);
Registry.register(BuiltInRegistries.DATA_COMPONENT_TYPE, Identifier.fromNamespaceAndPath(Minions.MOD_ID, name), type);
PolymerComponent.registerDataComponent(type);
return type;
}
public static void register() {
ComponentTooltipAppenderRegistry.addFirst(MinionComponentTypes.REFERENCE);
ItemComponentTooltipProviderRegistry.addFirst(MinionComponentTypes.REFERENCE);
}
}
@@ -3,7 +3,7 @@ package io.github.skippyall.minions.registration;
import io.github.skippyall.minions.Minions;
import io.github.skippyall.minions.minion.MinionConfig;
import net.minecraft.core.Registry;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.resources.Identifier;
import static io.github.skippyall.minions.minion.MinionConfig.booleanOption;
@@ -20,8 +20,8 @@ public class MinionConfigOptions {
return Registry.register(MinionRegistries.MINION_CONFIG_OPTIONS, option.key(), option);
}
private static ResourceLocation id(String name) {
return ResourceLocation.fromNamespaceAndPath(Minions.MOD_ID, name);
private static Identifier id(String name) {
return Identifier.fromNamespaceAndPath(Minions.MOD_ID, name);
}
public static void register() {}
@@ -1,35 +1,37 @@
package io.github.skippyall.minions.registration;
import eu.pb4.polymer.core.api.item.PolymerItemGroupUtils;
import eu.pb4.polymer.core.api.item.PolymerCreativeModeTabUtils;
import io.github.skippyall.minions.Minions;
import net.fabricmc.fabric.api.itemgroup.v1.FabricItemGroup;
import net.fabricmc.fabric.api.creativetab.v1.FabricCreativeModeTab;
import net.minecraft.network.chat.Component;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.resources.Identifier;
import net.minecraft.world.item.CreativeModeTab;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack;
import java.util.ArrayList;
import java.util.List;
public class MinionCreativeTab {
public static CreativeModeTab group;
private static final List<ItemStack> items = new ArrayList<>();
private static final List<Item> items = new ArrayList<>();
public static void add(Item entry) {
items.add(entry.getDefaultInstance());
items.add(entry);
}
public static void collectEntries(CreativeModeTab.ItemDisplayParameters displayContext, CreativeModeTab.Output entries) {
entries.acceptAll(items);
for(Item item : items) {
entries.accept(item);
}
}
public static void registerGroup() {
group = FabricItemGroup.builder()
group = FabricCreativeModeTab.builder()
.title(Component.translatable("minions.generic.mod_name"))
.icon(MinionItems.MINION_ITEM::getDefaultInstance)
.displayItems(MinionCreativeTab::collectEntries)
.build();
PolymerItemGroupUtils.registerPolymerItemGroup(ResourceLocation.fromNamespaceAndPath(Minions.MOD_ID, "main"), group);
PolymerCreativeModeTabUtils.registerPolymerCreativeModeTab(Identifier.fromNamespaceAndPath(Minions.MOD_ID, "main"), group);
}
}
@@ -9,60 +9,61 @@ import io.github.skippyall.minions.minion.MinionRuntime;
import io.github.skippyall.minions.module.MinionModule;
import io.github.skippyall.minions.module.SpecialAbility;
import io.github.skippyall.minions.program.instruction.InstructionType;
import java.util.List;
import java.util.function.Function;
import net.minecraft.core.Registry;
import net.minecraft.core.component.DataComponents;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.core.registries.Registries;
import net.minecraft.resources.Identifier;
import net.minecraft.resources.ResourceKey;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.tags.TagKey;
import net.minecraft.world.damagesource.DamageType;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.Items;
import net.minecraft.world.item.component.DamageResistant;
import java.util.List;
import java.util.function.Function;
import static io.github.skippyall.minions.Minions.MOD_ID;
public class MinionItems {
public static final TagKey<DamageType> MINION_ITEM_RESISTS = TagKey.create(Registries.DAMAGE_TYPE, ResourceLocation.fromNamespaceAndPath(MOD_ID, "minion_item_resists"));
public static final TagKey<DamageType> MINION_ITEM_RESISTS = TagKey.create(Registries.DAMAGE_TYPE, Identifier.fromNamespaceAndPath(MOD_ID, "minion_item_resists"));
public static final MinionItem MINION_ITEM = registerItem(
ResourceLocation.fromNamespaceAndPath(MOD_ID, "minion"),
settings -> new MinionItem(settings.component(DataComponents.DAMAGE_RESISTANT, new DamageResistant(MINION_ITEM_RESISTS)))
Identifier.fromNamespaceAndPath(MOD_ID, "minion"),
settings -> new MinionItem(settings.delayedComponent(DataComponents.DAMAGE_RESISTANT, context -> new DamageResistant(context.getOrThrow(MINION_ITEM_RESISTS))))
);
public static final SimplePolymerItem BASIC_UPGRADE_BASE = registerItem(
ResourceLocation.fromNamespaceAndPath(MOD_ID, "basic_upgrade_base"),
Identifier.fromNamespaceAndPath(MOD_ID, "basic_upgrade_base"),
settings -> new SimplePolymerItem(settings, Items.NETHERITE_UPGRADE_SMITHING_TEMPLATE)
);
public static final SimplePolymerItem ADVANCED_UPGRADE_BASE = registerItem(
ResourceLocation.fromNamespaceAndPath(MOD_ID, "advanced_upgrade_base"),
Identifier.fromNamespaceAndPath(MOD_ID, "advanced_upgrade_base"),
settings -> new SimplePolymerItem(settings, Items.NETHERITE_UPGRADE_SMITHING_TEMPLATE)
);
public static final SimplePolymerItem MOVE_MODULE = registerModule(
ResourceLocation.fromNamespaceAndPath(MOD_ID, "move_module"),
Identifier.fromNamespaceAndPath(MOD_ID, "move_module"),
Items.IRON_BOOTS,
List.of(Instructions.WALK, Instructions.WALK_CONTINUOUS, Instructions.TURN, Instructions.TURN_VECTOR)
);
public static final SimplePolymerItem ATTACK_MODULE = registerModule(
ResourceLocation.fromNamespaceAndPath(MOD_ID, "attack_module"),
Identifier.fromNamespaceAndPath(MOD_ID, "attack_module"),
Items.IRON_PICKAXE,
List.of(Instructions.ATTACK, Instructions.MINE_BLOCK)
);
public static final SimplePolymerItem INTERACT_MODULE = registerModule(
ResourceLocation.fromNamespaceAndPath(MOD_ID, "interact_module"),
Identifier.fromNamespaceAndPath(MOD_ID, "interact_module"),
Items.LEVER,
List.of(Instructions.USE)
);
public static final SimplePolymerItem MOB_SPAWNING_MODULE = registerModule(
ResourceLocation.fromNamespaceAndPath(MOD_ID, "mob_spawning_module"),
Identifier.fromNamespaceAndPath(MOD_ID, "mob_spawning_module"),
Items.SPAWNER,
List.of(),
List.of(SpecialAbilities.MOB_SPAWNING)
@@ -75,9 +76,9 @@ public class MinionItems {
new Item.Properties().useBlockDescriptionPrefix()
);
public static final ClipboardItem REFERENCE_ITEM = registerItem(ResourceLocation.fromNamespaceAndPath(MOD_ID, "clipboard"), ClipboardItem::new);
public static final ClipboardItem REFERENCE_ITEM = registerItem(Identifier.fromNamespaceAndPath(MOD_ID, "clipboard"), ClipboardItem::new);
public static <T extends Item> T registerItem(ResourceLocation identifier, Function<Item.Properties, T> constructor, Item.Properties settings) {
public static <T extends Item> T registerItem(Identifier identifier, Function<Item.Properties, T> constructor, Item.Properties settings) {
T item = constructor.apply(settings.setId(ResourceKey.create(Registries.ITEM, identifier)));
MinionCreativeTab.add(item);
@@ -85,11 +86,11 @@ public class MinionItems {
return Registry.register(BuiltInRegistries.ITEM, identifier, item);
}
public static <T extends Item> T registerItem(ResourceLocation identifier, Function<Item.Properties, T> constructor) {
public static <T extends Item> T registerItem(Identifier identifier, Function<Item.Properties, T> constructor) {
return registerItem(identifier, constructor, new Item.Properties());
}
public static SimplePolymerItem registerModule(ResourceLocation identifier, Item vanillaItem, List<InstructionType<MinionRuntime>> instructionTypes, List<SpecialAbility> specialAbilities) {
public static SimplePolymerItem registerModule(Identifier identifier, Item vanillaItem, List<InstructionType<MinionRuntime>> instructionTypes, List<SpecialAbility> specialAbilities) {
return registerItem(
identifier,
settings -> new SimplePolymerItem(settings, vanillaItem),
@@ -97,7 +98,7 @@ public class MinionItems {
);
}
public static SimplePolymerItem registerModule(ResourceLocation identifier, Item vanillaItem, List<InstructionType<MinionRuntime>> instructionTypes) {
public static SimplePolymerItem registerModule(Identifier identifier, Item vanillaItem, List<InstructionType<MinionRuntime>> instructionTypes) {
return registerModule(
identifier,
vanillaItem,
@@ -3,10 +3,10 @@ package io.github.skippyall.minions.registration;
import io.github.skippyall.minions.Minions;
import io.github.skippyall.minions.block.miniontrigger.MinionTriggerMinionListener;
import net.minecraft.core.Registry;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.resources.Identifier;
public class MinionListeners {
public static void register() {
Registry.register(MinionRegistries.MINION_LISTENER_CODECS, ResourceLocation.fromNamespaceAndPath(Minions.MOD_ID, "minion_trigger"), MinionTriggerMinionListener.CODEC);
Registry.register(MinionRegistries.MINION_LISTENER_CODECS, Identifier.fromNamespaceAndPath(Minions.MOD_ID, "minion_trigger"), MinionTriggerMinionListener.CODEC);
}
}
@@ -22,8 +22,8 @@ import net.fabricmc.fabric.api.event.registry.DynamicRegistries;
import net.fabricmc.fabric.api.event.registry.FabricRegistryBuilder;
import net.fabricmc.fabric.api.event.registry.RegistryAttribute;
import net.minecraft.core.Registry;
import net.minecraft.resources.Identifier;
import net.minecraft.resources.ResourceKey;
import net.minecraft.resources.ResourceLocation;
public class MinionRegistries {
public static final Registry<ValueType<?>> VALUE_TYPES = registry("value_type");
@@ -45,11 +45,11 @@ public class MinionRegistries {
public static final ResourceKey<Registry<ReferenceEntry>> DOCS_ENTRY = key("docs_entry");
private static <T> Registry<T> registry(String id) {
return FabricRegistryBuilder.<T>createSimple(key(id)).attribute(RegistryAttribute.OPTIONAL).buildAndRegister();
return FabricRegistryBuilder.<T>create(key(id)).attribute(RegistryAttribute.OPTIONAL).buildAndRegister();
}
private static <T> ResourceKey<Registry<T>> key(String name) {
return ResourceKey.createRegistryKey(ResourceLocation.fromNamespaceAndPath(Minions.MOD_ID, name));
return ResourceKey.createRegistryKey(Identifier.fromNamespaceAndPath(Minions.MOD_ID, name));
}
public static void register() {
@@ -6,7 +6,7 @@ import io.github.skippyall.minions.minion.skin.NameSkinProvider;
import io.github.skippyall.minions.minion.skin.SkinProvider;
import io.github.skippyall.minions.minion.skin.UUIDSkinProvider;
import net.minecraft.core.Registry;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.resources.Identifier;
public class SkinProviders {
public static NameSkinProvider NAME = register(new NameSkinProvider(), "name");
@@ -14,7 +14,7 @@ public class SkinProviders {
public static Base64SkinProvider BASE64 = register(new Base64SkinProvider(), "base64");
public static <T extends SkinProvider> T register(T skinProvider, String path) {
return Registry.register(MinionRegistries.SKIN_PROVIDERS, ResourceLocation.fromNamespaceAndPath(Minions.MOD_ID, path), skinProvider);
return Registry.register(MinionRegistries.SKIN_PROVIDERS, Identifier.fromNamespaceAndPath(Minions.MOD_ID, path), skinProvider);
}
public static void register() {
@@ -4,13 +4,13 @@ import io.github.skippyall.minions.Minions;
import io.github.skippyall.minions.module.MobSpawningAbility;
import io.github.skippyall.minions.module.SpecialAbility;
import net.minecraft.core.Registry;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.resources.Identifier;
public class SpecialAbilities {
public static final MobSpawningAbility MOB_SPAWNING = register("mob_spawning", new MobSpawningAbility());
private static <T extends SpecialAbility> T register(String name, T type) {
Registry.register(MinionRegistries.SPECIAL_ABILITIES, ResourceLocation.fromNamespaceAndPath(Minions.MOD_ID, name), type);
Registry.register(MinionRegistries.SPECIAL_ABILITIES, Identifier.fromNamespaceAndPath(Minions.MOD_ID, name), type);
return type;
}
@@ -5,14 +5,14 @@ import io.github.skippyall.minions.program.conversion.CastConverter;
import io.github.skippyall.minions.program.conversion.EqualityConverter;
import io.github.skippyall.minions.program.conversion.ValueConverterType;
import net.minecraft.core.Registry;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.resources.Identifier;
public class ValueConverters {
public static final EqualityConverter.EqualityConverterType EQUALITY_CONVERTER = register("equality", new EqualityConverter.EqualityConverterType());
public static final CastConverter.Type CAST_CONVERTER = register("cast", new CastConverter.Type());
private static <T extends ValueConverterType<?>> T register(String name, T type) {
return Registry.register(MinionRegistries.VALUE_CONVERTER_TYPES, ResourceLocation.fromNamespaceAndPath(Minions.MOD_ID, name), type);
return Registry.register(MinionRegistries.VALUE_CONVERTER_TYPES, Identifier.fromNamespaceAndPath(Minions.MOD_ID, name), type);
}
public static void register() {}
@@ -6,14 +6,14 @@ import io.github.skippyall.minions.minion.program.supplier.AnalogInputSupplier;
import io.github.skippyall.minions.program.supplier.FixedValueSupplierType;
import io.github.skippyall.minions.program.supplier.ValueSupplierType;
import net.minecraft.core.Registry;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.resources.Identifier;
public class ValueSuppliers {
public static final FixedValueSupplierType<MinionRuntime> FIXED_VALUE_SUPPLIER_TYPE = register("fixed", new FixedValueSupplierType<>());
public static final AnalogInputSupplier.AnalogInputSupplierType ANALOG_INPUT = register("analog_input", new AnalogInputSupplier.AnalogInputSupplierType());
public static <T extends ValueSupplierType<MinionRuntime>> T register(String id, T type) {
return Registry.register(MinionRegistries.VALUE_SUPPLIER_TYPES, ResourceLocation.fromNamespaceAndPath(Minions.MOD_ID, id), type);
return Registry.register(MinionRegistries.VALUE_SUPPLIER_TYPES, Identifier.fromNamespaceAndPath(Minions.MOD_ID, id), type);
}
public static void register() {}
@@ -6,10 +6,11 @@ import io.github.skippyall.minions.gui.input.TextInput;
import io.github.skippyall.minions.minion.program.instruction.move.TurnDirection;
import io.github.skippyall.minions.program.value.SimpleValueType;
import io.github.skippyall.minions.program.value.ValueType;
import java.util.concurrent.CompletableFuture;
import net.minecraft.core.Registry;
import net.minecraft.network.chat.Component;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.resources.Identifier;
import java.util.concurrent.CompletableFuture;
public class ValueTypes {
public static ValueType<Long> LONG = register(
@@ -18,10 +19,10 @@ public class ValueTypes {
Codec.LONG,
0L,
o -> o instanceof Long l ? l : null,
(parent, oldValue) -> TextInput.inputLong(
(parent, oldValue) -> TextInput.inputLongFuture(
parent,
Component.literal("Integer"),
String.valueOf(oldValue)
oldValue
),
value -> Component.literal(value.toString())
)
@@ -33,10 +34,10 @@ public class ValueTypes {
Codec.DOUBLE,
0D,
o -> o instanceof Double d ? d : null,
(parent, oldValue) -> TextInput.inputDouble(
(parent, oldValue) -> TextInput.inputDoubleFuture(
parent,
Component.literal("Number"),
String.valueOf(oldValue)
oldValue
),
value -> Component.literal(value.toString())
)
@@ -60,11 +61,11 @@ public class ValueTypes {
Codec.STRING,
"",
o -> o instanceof String s ? s : null,
((parent, oldValue) -> TextInput.inputString(
((parent, oldValue) -> TextInput.inputStringFuture(
parent,
Component.literal("Text"),
oldValue)
),
oldValue
)),
value -> Component.literal("\"" + value + "\"")
)
);
@@ -85,7 +86,7 @@ public class ValueTypes {
String id,
T type
) {
ResourceLocation identifier = ResourceLocation.fromNamespaceAndPath(Minions.MOD_ID, id);
Identifier identifier = Identifier.fromNamespaceAndPath(Minions.MOD_ID, id);
Registry.register(
MinionRegistries.VALUE_TYPES,
identifier,
@@ -1,11 +1,11 @@
package io.github.skippyall.minions.util;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.resources.Identifier;
import net.minecraft.world.item.Item;
public class ModelIdUtil {
public static ResourceLocation getItemModelId(Item item) {
public static Identifier getItemModelId(Item item) {
return BuiltInRegistries.ITEM.getKey(item);
}
}

Some files were not shown because too many files have changed in this diff Show More