Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Some random and minor 0.6 refactors #296

Merged
merged 9 commits into from
Jun 23, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,9 @@ repositories {
}
}

loom {
splitEnvironmentSourceSets()
}

dependencies {
minecraft "com.mojang:minecraft:${project.minecraft_version}"
Expand All @@ -86,7 +89,7 @@ dependencies {

modApi include('xyz.nucleoid:server-translations-api:2.3.0+1.20.5-rc2')
modApi include('xyz.nucleoid:packet-tweaker:0.5.1+1.20.6')
modApi include('xyz.nucleoid:fantasy:0.6.0+1.20.6')
modApi include('xyz.nucleoid:fantasy:0.6.2+1.20.6')
modApi include('xyz.nucleoid:more-codecs:0.3.3+1.20.2')
modApi include('xyz.nucleoid:stimuli:0.4.11+1.20.6')
modApi include('xyz.nucleoid:map-templates:0.1.9+1.20.4')
Expand All @@ -110,6 +113,7 @@ dependencies {
modCompileOnly("dev.emi:trinkets:3.7.1")

testmodImplementation sourceSets.main.output
testmodImplementation sourceSets.client.output
}

processResources {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package xyz.nucleoid.plasmid.mixin.game.space;
package xyz.nucleoid.plasmid.client.mixin.game.space;

import com.llamalad7.mixinextras.injector.ModifyExpressionValue;
import net.minecraft.server.integrated.IntegratedPlayerManager;
Expand Down
12 changes: 12 additions & 0 deletions src/client/resources/plasmid.client.mixins.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"required": true,
"minVersion": "0.8",
"package": "xyz.nucleoid.plasmid.client.mixin",
"compatibilityLevel": "JAVA_17",
"client": [
"game.space.IntegratedPlayerManagerMixin"
],
"injectors": {
"defaultRequire": 1
}
}
8 changes: 2 additions & 6 deletions src/main/java/xyz/nucleoid/plasmid/command/GameCommand.java
Original file line number Diff line number Diff line change
Expand Up @@ -142,12 +142,8 @@ private static int openAnonymousGame(CommandContext<ServerCommandSource> context
protected static int openAnonymousGame(CommandContext<ServerCommandSource> context, boolean test) throws CommandSyntaxException {
try {
var configNbt = NbtCompoundArgumentType.getNbtCompound(context, "game_config_nbt");
var result = GameConfig.DIRECT_CODEC.parse(context.getSource().getRegistryManager().getOps(NbtOps.INSTANCE), configNbt);
if (result.error().isPresent()) {
throw MALFORMED_CONFIG.create(result.error().get());
}

var game = result.result().get();
var game = GameConfig.DIRECT_CODEC.parse(context.getSource().getRegistryManager().getOps(NbtOps.INSTANCE), configNbt)
.getOrThrow(MALFORMED_CONFIG::create);
return openGame(context, RegistryEntry.of(game), test);
} catch (CommandSyntaxException e) {
throw e;
Expand Down
20 changes: 20 additions & 0 deletions src/main/java/xyz/nucleoid/plasmid/game/GameAttachment.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package xyz.nucleoid.plasmid.game;

import net.minecraft.util.Identifier;

public class GameAttachment<T> {
private final Identifier id;

private GameAttachment(Identifier id) {
this.id = id;
}

public static <T> GameAttachment<T> create(Identifier id) {
return new GameAttachment<>(id);
}

@Override
public String toString() {
return this.id.toString();
}
}
18 changes: 18 additions & 0 deletions src/main/java/xyz/nucleoid/plasmid/game/GameAttachmentHolder.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package xyz.nucleoid.plasmid.game;

import org.jetbrains.annotations.Nullable;

public interface GameAttachmentHolder {
@Nullable
<T> T getAttachment(GameAttachment<? extends T> attachment);

default <T> T getAttachmentOrThrow(GameAttachment<? extends T> attachment) {
T value = this.getAttachment(attachment);
if (value == null) {
throw new IllegalArgumentException("Missing attachment " + attachment + " on " + this);
}
return value;
}

<T> void setAttachment(GameAttachment<? super T> attachment, @Nullable T value);
}
6 changes: 1 addition & 5 deletions src/main/java/xyz/nucleoid/plasmid/game/GameSpace.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
* @see GameType
* @see GameActivity
*/
public interface GameSpace {
public interface GameSpace extends GameAttachmentHolder {
/**
* @return the host server of this {@link GameSpace}
*/
Expand Down Expand Up @@ -109,8 +109,4 @@ public interface GameSpace {
* @return true if this GameSpace is closed, false otherwise
*/
boolean isClosed();

@Nullable
<T> T getAttachment(String key);
void setAttachment(String key, @Nullable Object obj);
}
14 changes: 7 additions & 7 deletions src/main/java/xyz/nucleoid/plasmid/game/GameType.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package xyz.nucleoid.plasmid.game;

import com.mojang.serialization.Codec;
import com.mojang.serialization.MapCodec;
import net.minecraft.text.Text;
import net.minecraft.util.Identifier;
import net.minecraft.util.Util;
Expand All @@ -24,10 +24,10 @@ public final class GameType<C> {
public static final TinyRegistry<GameType<?>> REGISTRY = TinyRegistry.create();

private final Identifier id;
private final Codec<C> configCodec;
private final MapCodec<C> configCodec;
private final Open<C> open;

private GameType(Identifier id, Codec<C> configCodec, Open<C> open) {
private GameType(Identifier id, MapCodec<C> configCodec, Open<C> open) {
this.id = id;
this.configCodec = configCodec;
this.open = open;
Expand All @@ -37,14 +37,14 @@ private GameType(Identifier id, Codec<C> configCodec, Open<C> open) {
* Registers a new {@link GameType} with the given id, codec to parse a config, and function to set up the game.
*
* @param identifier a unique identifier to register this game type with
* @param configCodec a {@link Codec} that can deserialize
* @param configCodec a {@link MapCodec} that can deserialize
* @param open a function that describes how the game should be set up, given a configuration
* @param <C> the type of config that should be loadedS
* @return the registered {@link GameType} instance
* @see Codec
* @see MapCodec
* @see com.mojang.serialization.codecs.RecordCodecBuilder
*/
public static <C> GameType<C> register(Identifier identifier, Codec<C> configCodec, Open<C> open) {
public static <C> GameType<C> register(Identifier identifier, MapCodec<C> configCodec, Open<C> open) {
var type = new GameType<>(identifier, configCodec, open);
REGISTRY.register(identifier, type);
return type;
Expand All @@ -58,7 +58,7 @@ public Identifier id() {
return this.id;
}

public Codec<C> configCodec() {
public MapCodec<C> configCodec() {
return this.configCodec;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package xyz.nucleoid.plasmid.game.composite;

import com.mojang.serialization.Codec;
import com.mojang.serialization.MapCodec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import net.minecraft.registry.RegistryCodecs;
import net.minecraft.registry.entry.RegistryEntry;
Expand All @@ -11,7 +11,7 @@
import xyz.nucleoid.plasmid.game.config.GameConfigs;

public record RandomGameConfig(RegistryEntryList<GameConfig<?>> games) {
public static final Codec<RandomGameConfig> CODEC = RecordCodecBuilder.create(i -> i.group(
public static final MapCodec<RandomGameConfig> CODEC = RecordCodecBuilder.mapCodec(i -> i.group(
RegistryCodecs.entryList(GameConfigs.REGISTRY_KEY).fieldOf("games").forGetter(config -> config.games)
).apply(i, RandomGameConfig::new));

Expand Down
116 changes: 39 additions & 77 deletions src/main/java/xyz/nucleoid/plasmid/game/config/GameConfig.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package xyz.nucleoid.plasmid.game.config;

import com.mojang.datafixers.util.Pair;
import com.mojang.serialization.*;
import com.mojang.serialization.Codec;
import com.mojang.serialization.MapCodec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import net.minecraft.item.ItemStack;
import net.minecraft.item.Items;
Expand All @@ -22,8 +22,6 @@
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.function.Function;
import java.util.stream.Stream;

public record GameConfig<C>(
GameType<C> type,
Expand All @@ -34,7 +32,7 @@ public record GameConfig<C>(
CustomValuesConfig custom,
C config
) {
public static final Codec<GameConfig<?>> DIRECT_CODEC = new ConfigCodec().codec();
public static final Codec<GameConfig<?>> DIRECT_CODEC = GameType.REGISTRY.dispatch(GameConfig::type, GameConfig::createTypedCodec);
public static final Codec<RegistryEntry<GameConfig<?>>> CODEC = RegistryElementCodec.of(GameConfigs.REGISTRY_KEY, DIRECT_CODEC);

public GameOpenProcedure openProcedure(MinecraftServer server) {
Expand Down Expand Up @@ -105,80 +103,44 @@ private static boolean hasTranslationFor(String translationKey) {
return language.serverTranslations().contains(translationKey);
}

static final class ConfigCodec extends MapCodec<GameConfig<?>> {
@Override
public <T> Stream<T> keys(DynamicOps<T> ops) {
return Stream.concat(Stream.of(ops.createString("type"), ops.createString("config")), Metadata.MAP_CODEC.keys(ops));
}

@Override
public <T> DataResult<GameConfig<?>> decode(DynamicOps<T> ops, MapLike<T> input) {
var typeResult = GameType.REGISTRY.decode(ops, input.get("type")).map(Pair::getFirst);

return typeResult.flatMap(type -> {
return Metadata.MAP_CODEC.decode(ops, input).flatMap(metadata -> {
return this.decodeConfig(ops, input, type.configCodec()).map(config -> {
return this.createConfigUnchecked(type, metadata, config);
});
});
});
}

private <T> DataResult<?> decodeConfig(DynamicOps<T> ops, MapLike<T> input, Codec<?> configCodec) {
if (configCodec instanceof MapCodecCodec<?> mapCodec) {
return mapCodec.codec().decode(ops, input).map(Function.identity());
} else {
return configCodec.decode(ops, input.get("config")).map(Pair::getFirst);
}
}

@SuppressWarnings("unchecked")
private <C> GameConfig<C> createConfigUnchecked(GameType<C> type, Metadata metadata, Object config) {
return new GameConfig<>(
type,
metadata.name.orElse(null), metadata.shortName.orElse(null), metadata.description.orElse(null),
metadata.icon, metadata.custom,
(C) config
);
}

@Override
public <T> RecordBuilder<T> encode(GameConfig<?> game, DynamicOps<T> ops, RecordBuilder<T> prefix) {
return this.encodeUnchecked(game, ops, prefix);
}

private <T, C> RecordBuilder<T> encodeUnchecked(GameConfig<C> game, DynamicOps<T> ops, RecordBuilder<T> prefix) {
var codec = game.type.configCodec();
if (codec instanceof MapCodecCodec<C> mapCodec) {
prefix = mapCodec.codec().encode(game.config, ops, prefix);
} else {
prefix.add("config", codec.encodeStart(ops, game.config));
}

prefix.add("type", GameType.REGISTRY.encodeStart(ops, game.type));

var metadata = new Metadata(
Optional.ofNullable(game.name), Optional.ofNullable(game.shortName), Optional.ofNullable(game.description),
game.icon, game.custom
);
prefix = Metadata.MAP_CODEC.encode(metadata, ops, prefix);

return prefix;
}
private static <C> MapCodec<GameConfig<C>> createTypedCodec(GameType<C> type) {
return RecordCodecBuilder.mapCodec(i -> i.group(
type.configCodec().forGetter(GameConfig::config),
Metadata.MAP_CODEC.forGetter(Metadata::from)
).apply(i, (config, metadata) -> new GameConfig<>(
type,
metadata.name.orElse(null),
metadata.shortName.orElse(null),
metadata.description.orElse(null),
metadata.icon,
metadata.custom,
config
)));
}

static final record Metadata(
Optional<Text> name, Optional<Text> shortName, Optional<List<Text>> description,
ItemStack icon, CustomValuesConfig custom
private record Metadata(
Optional<Text> name,
Optional<Text> shortName,
Optional<List<Text>> description,
ItemStack icon,
CustomValuesConfig custom
) {
static final MapCodec<Metadata> MAP_CODEC = RecordCodecBuilder.mapCodec(instance -> {
return instance.group(
PlasmidCodecs.TEXT.optionalFieldOf("name").forGetter(Metadata::name),
PlasmidCodecs.TEXT.optionalFieldOf("short_name").forGetter(Metadata::shortName),
MoreCodecs.listOrUnit(PlasmidCodecs.TEXT).optionalFieldOf("description").forGetter(Metadata::description),
MoreCodecs.ITEM_STACK.optionalFieldOf("icon", new ItemStack(Items.GRASS_BLOCK)).forGetter(Metadata::icon),
CustomValuesConfig.CODEC.fieldOf("custom").orElseGet(CustomValuesConfig::empty).forGetter(Metadata::custom)
).apply(instance, Metadata::new);
});
static final MapCodec<Metadata> MAP_CODEC = RecordCodecBuilder.mapCodec(i -> i.group(
PlasmidCodecs.TEXT.optionalFieldOf("name").forGetter(Metadata::name),
PlasmidCodecs.TEXT.optionalFieldOf("short_name").forGetter(Metadata::shortName),
MoreCodecs.listOrUnit(PlasmidCodecs.TEXT).optionalFieldOf("description").forGetter(Metadata::description),
MoreCodecs.ITEM_STACK.optionalFieldOf("icon", new ItemStack(Items.GRASS_BLOCK)).forGetter(Metadata::icon),
CustomValuesConfig.CODEC.fieldOf("custom").orElseGet(CustomValuesConfig::empty).forGetter(Metadata::custom)
).apply(i, Metadata::new));

public static Metadata from(GameConfig<?> game) {
return new Metadata(
Optional.ofNullable(game.name),
Optional.ofNullable(game.shortName),
Optional.ofNullable(game.description),
game.icon,
game.custom
);
}
}
}
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
package xyz.nucleoid.plasmid.game.manager;

import com.google.common.collect.Lists;
import it.unimi.dsi.fastutil.objects.Reference2ObjectOpenHashMap;
import me.lucko.fabric.api.permissions.v0.Permissions;
import net.minecraft.registry.RegistryKey;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.text.Text;
import net.minecraft.util.Formatting;
import net.minecraft.world.World;
import org.jetbrains.annotations.Nullable;
import xyz.nucleoid.fantasy.RuntimeWorldHandle;
import xyz.nucleoid.plasmid.Plasmid;
import xyz.nucleoid.plasmid.event.GameEvents;
Expand All @@ -19,7 +21,6 @@
import xyz.nucleoid.plasmid.game.player.PlayerOfferResult;

import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Consumer;

Expand All @@ -40,7 +41,7 @@ public final class ManagedGameSpace implements GameSpace {
private boolean closed;

private final GameSpaceStatistics statistics = new GameSpaceStatistics();
private final Map<String, Object> attachments = new HashMap<>();
private final Map<GameAttachment<?>, Object> attachments = new Reference2ObjectOpenHashMap<>();

ManagedGameSpace(MinecraftServer server, GameSpaceManager manager, GameSpaceMetadata metadata) {
this.server = server;
Expand Down Expand Up @@ -171,18 +172,20 @@ public GameSpaceStatistics getStatistics() {
public boolean isClosed() {
return this.closed;
}

@Override
public <T> T getAttachment(String key) {
//noinspection unchecked
return (T) this.attachments.get(key);
@Nullable
@SuppressWarnings("unchecked")
public <T> T getAttachment(GameAttachment<? extends T> attachment) {
return (T) this.attachments.get(attachment);
}

@Override
public void setAttachment(String key, Object obj) {
if (obj == null) {
this.attachments.remove(key);
public <T> void setAttachment(GameAttachment<? super T> attachment, @Nullable T value) {
if (value == null) {
this.attachments.remove(attachment);
} else {
this.attachments.put(key, obj);
this.attachments.put(attachment, value);
}
}

Expand Down
Loading
Loading