Compare commits

...

3 commits

Author SHA1 Message Date
moehreag a1801635b3 begin adding basic player events
All checks were successful
Publish to snapshot maven / build (push) Successful in 1m2s
2024-06-15 23:52:38 +02:00
moehreag 7f3510f227 update to 1.21 2024-06-15 21:24:44 +02:00
moehreag b0b2555ebf improve build
- publish all modules
- add test mods to general runtime classpath

- fix issues with keybindings being registered before the game is initialized
2024-06-13 19:30:16 +02:00
19 changed files with 141 additions and 25 deletions

View file

@ -19,6 +19,6 @@ jobs:
- name: Build
run: |
chmod +x ./gradlew
./gradlew :publishMavenJavaPublicationToFrogMCSnapshotsMavenRepository \
./gradlew publishMavenJavaPublicationToFrogMCSnapshotsMavenRepository \
-PFrogMCSnapshotsMavenUsername=${{ secrets.MAVEN_PUSH_USER }} \
-PFrogMCSnapshotsMavenPassword=${{ secrets.MAVEN_PUSH_TOKEN }} --stacktrace

View file

@ -35,7 +35,7 @@ allprojects {
phytotelma {
loader(rootProject.libs.versions.frogloader)
minecraft(rootProject.libs.versions.minecraft)
minecraft(rootProject.libs.versions.minecraft, provider { "1.20.6" }) // since parchment isn't published for 1.21 yet
}
tasks.processResources {
@ -94,7 +94,14 @@ allprojects {
evaluationDependsOnChildren()
// TODO: add testmods of libraries to general client runtime classpath
tasks.runClient {
classpath(sourceSets.test.get().runtimeClasspath)
project.subprojects.filter {
it.projectDir.resolve("src/main/resources/frog.mod.toml").exists()
}.forEach {
classpath(it.sourceSets.test.get().output)
}
}
dependencies {
project.subprojects.filter {

View file

@ -1,7 +1,7 @@
[versions]
minecraft = "1.20.6"
minecraft = "1.21"
frogloader = "0.0.1-SNAPSHOT"
phytotelma = "0.0.1-alpha.4"
phytotelma = "0.0.1-alpha.9"
lombok = "8.6"

View file

@ -5,7 +5,7 @@ import dev.frogmc.froglib.events.api.types.ClientTickEvent;
import dev.frogmc.froglib.events.api.types.ServerStartupEvent;
import dev.frogmc.froglib.events.api.types.ServerTickEvent;
public class Events {
public final class LifecycleEvents {
public static final Event<ClientStartupEvent> CLIENT_STARTUP = Event.of(ClientStartupEvent.class);
public static final Event<ServerStartupEvent> SERVER_STARTUP = Event.of(ServerStartupEvent.class);

View file

@ -1,6 +1,6 @@
package dev.frogmc.froglib.events.impl.mixin;
import dev.frogmc.froglib.events.api.Events;
import dev.frogmc.froglib.events.api.LifecycleEvents;
import net.minecraft.server.MinecraftServer;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
@ -12,11 +12,11 @@ public abstract class MinecraftServerMixin {
@Inject(method = "runServer", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/MinecraftServer;tickServer(Ljava/util/function/BooleanSupplier;)V"))
private void preServerTick(CallbackInfo ci) {
Events.PRE_SERVER_TICK.invoker().onTick((MinecraftServer) (Object) this);
LifecycleEvents.PRE_SERVER_TICK.invoker().onTick((MinecraftServer) (Object) this);
}
@Inject(method = "runServer", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/MinecraftServer;tickServer(Ljava/util/function/BooleanSupplier;)V", shift = At.Shift.AFTER))
private void postServerTick(CallbackInfo ci) {
Events.POST_SERVER_TICK.invoker().onTick((MinecraftServer) (Object) this);
LifecycleEvents.POST_SERVER_TICK.invoker().onTick((MinecraftServer) (Object) this);
}
}

View file

@ -1,6 +1,6 @@
package dev.frogmc.froglib.events.impl.mixin.client;
import dev.frogmc.froglib.events.api.Events;
import dev.frogmc.froglib.events.api.LifecycleEvents;
import net.minecraft.client.Minecraft;
import net.minecraft.client.main.GameConfig;
import org.spongepowered.asm.mixin.Mixin;
@ -13,16 +13,16 @@ public abstract class MinecraftMixin {
@Inject(method = "<init>", at = @At("TAIL"))
private void postClientInit(GameConfig gameConfig, CallbackInfo ci) {
Events.CLIENT_STARTUP.invoker().onClientInit((Minecraft) (Object) this, gameConfig);
LifecycleEvents.CLIENT_STARTUP.invoker().onClientInit((Minecraft) (Object) this, gameConfig);
}
@Inject(method = "tick", at = @At("HEAD"))
private void preClientTick(CallbackInfo ci) {
Events.PRE_CLIENT_TICK.invoker().onTick((Minecraft) (Object) this);
LifecycleEvents.PRE_CLIENT_TICK.invoker().onTick((Minecraft) (Object) this);
}
@Inject(method = "tick", at = @At("TAIL"))
private void postClientTick(CallbackInfo ci) {
Events.POST_CLIENT_TICK.invoker().onTick((Minecraft) (Object) this);
LifecycleEvents.POST_CLIENT_TICK.invoker().onTick((Minecraft) (Object) this);
}
}

View file

@ -1,6 +1,6 @@
package dev.frogmc.froglib.events.impl.mixin.server;
import dev.frogmc.froglib.events.api.Events;
import dev.frogmc.froglib.events.api.LifecycleEvents;
import net.minecraft.server.dedicated.DedicatedServer;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
@ -12,6 +12,6 @@ public abstract class DedicatedServerMixin {
@Inject(method = "initServer", at = @At(value = "INVOKE", target = "Lorg/slf4j/Logger;info(Ljava/lang/String;)V", ordinal = 0))
private void initializeServer(CallbackInfoReturnable<Boolean> cir) {
Events.SERVER_STARTUP.invoker().onServerInit((DedicatedServer) (Object) this);
LifecycleEvents.SERVER_STARTUP.invoker().onServerInit((DedicatedServer) (Object) this);
}
}

View file

@ -1,6 +1,6 @@
package dev.frogmc.froglib.keybinds.impl;
import dev.frogmc.froglib.events.api.Events;
import dev.frogmc.froglib.events.api.LifecycleEvents;
import dev.frogmc.froglib.keybinds.api.KeyListener;
import dev.frogmc.froglib.keybinds.api.KeyMappings;
import net.minecraft.client.KeyMapping;
@ -15,14 +15,23 @@ public class KeyMappingsImpl implements KeyMappings {
}
public void registerKey(KeyMapping mapping){
// TODO maybe synchronize?
Runnable register = () -> {
synchronized (Minecraft.getInstance().options) {
Minecraft.getInstance().options.keyMappings = ArrayUtils.add(Minecraft.getInstance().options.keyMappings, mapping);
}
};
//noinspection ConstantValue (This inspection is just wrong)
if (Minecraft.getInstance() != null && Minecraft.getInstance().options != null) {
register.run();
} else {
LifecycleEvents.CLIENT_STARTUP.register((client, config) -> register.run());
}
}
@Override
public void registerKeyWithListener(KeyMapping mapping, KeyListener listener) {
registerKey(mapping);
Events.POST_CLIENT_TICK.register(c -> {
LifecycleEvents.POST_CLIENT_TICK.register(c -> {
while (mapping.consumeClick()){
listener.onPress(mapping);
}

View file

View file

@ -0,0 +1,17 @@
package dev.frogmc.froglib.player.api;
import java.util.function.BiConsumer;
import dev.frogmc.froglib.events.api.Event;
import dev.frogmc.froglib.player.api.types.StopSleepEvent;
import net.minecraft.core.BlockPos;
import net.minecraft.world.damagesource.DamageSource;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.player.Player;
public final class PlayerEvents {
public static final Event<BiConsumer<Player, DamageSource>> DEATH = Event.biConsumer();
public static final Event<BiConsumer<Player, Entity>> ATTACK = Event.biConsumer();
public static final Event<BiConsumer<Player, BlockPos>> START_SLEEP = Event.biConsumer();
public static final Event<StopSleepEvent> STOP_SLEEP = Event.of(StopSleepEvent.class);
}

View file

@ -0,0 +1,7 @@
package dev.frogmc.froglib.player.api.types;
import net.minecraft.world.entity.player.Player;
public interface StopSleepEvent {
void onSleepStop(Player player, boolean wakeImmediately, boolean updateLevelForSleepingPlayers);
}

View file

@ -0,0 +1,38 @@
package dev.frogmc.froglib.player.impl.mixin;
import com.mojang.datafixers.util.Either;
import dev.frogmc.froglib.player.api.PlayerEvents;
import net.minecraft.core.BlockPos;
import net.minecraft.util.Unit;
import net.minecraft.world.damagesource.DamageSource;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.player.Player;
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.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
@Mixin(Player.class)
public class PlayerMixin {
@Inject(method = "die", at = @At("TAIL"))
private void onDeath(DamageSource cause, CallbackInfo ci) {
PlayerEvents.DEATH.invoker().accept((Player) (Object) this, cause);
}
@Inject(method = "attack", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/Entity;hurt(Lnet/minecraft/world/damagesource/DamageSource;F)Z"))
private void onAttack(Entity target, CallbackInfo ci){
PlayerEvents.ATTACK.invoker().accept((Player) (Object) this, target);
}
@Inject(method = "startSleepInBed", at = @At("TAIL"))
private void onStartSleep(BlockPos bedPos, CallbackInfoReturnable<Either<Player.BedSleepingProblem, Unit>> cir) {
PlayerEvents.START_SLEEP.invoker().accept((Player) (Object) this, bedPos);
}
@Inject(method = "stopSleepInBed", at = @At("TAIL"))
private void onStopSleep(boolean wakeImmediately, boolean updateLevelForSleepingPlayers, CallbackInfo ci) {
PlayerEvents.STOP_SLEEP.invoker().onSleepStop((Player) (Object) this, wakeImmediately, updateLevelForSleepingPlayers);
}
}

View file

@ -0,0 +1,19 @@
[frog]
format_version = "1.0.0"
[frog.mod]
id = "froglib_player"
name = "FrogLib Player"
version = "$version"
license = "Apache-2.0"
credits = [
{ name = "FrogMC Team", roles = ["author"] }
]
[frog.dependencies]
depends = [
{ id = "minecraft", versions = "~$game_version", name = "Minecraft" }
]
[frog.extensions]
mixin = "froglib.player.mixins.json"

View file

@ -0,0 +1,17 @@
{
"required": true,
"minVersion": "0.8",
"package": "dev.frogmc.froglib.player.impl.mixin",
"compatibilityLevel": "JAVA_21",
"mixins": [
"PlayerMixin"
],
"server": [
],
"client": [
],
"injectors": {
"defaultRequire": 1
}
}

View file

@ -4,7 +4,7 @@ import java.util.Collection;
import dev.frogmc.froglib.events.api.Event;
public class RegistryEvents {
public final class RegistryEvents {
public static final Event<BlockRegistration> BLOCK_REGISTRATION = Event.of(list -> () -> list.stream().map(BlockRegistration::register).flatMap(Collection::stream).toList());
public static final Event<ItemRegistration> ITEM_REGISTRATION = Event.of(list -> () -> list.stream().map(ItemRegistration::register).flatMap(Collection::stream).toList());
}

View file

@ -9,7 +9,7 @@ import net.minecraft.world.level.block.StainedGlassBlock;
import net.minecraft.world.level.block.state.BlockBehaviour;
public class BlockTestBlocks {
public static final ResourceLocation loc = new ResourceLocation("froglib_block_test", "testblock");
public static final ResourceLocation loc = ResourceLocation.fromNamespaceAndPath("froglib_block_test", "testblock");
public static final Block b = new StainedGlassBlock(DyeColor.MAGENTA, BlockBehaviour.Properties.of());
public static final Item bItem = new BlockItem(b, new Item.Properties());
}

View file

@ -1,14 +1,14 @@
package dev.frogmc.froglib.resources.impl;
import dev.frogmc.froglib.entrypoints.api.ClientExtension;
import dev.frogmc.froglib.events.api.Events;
import dev.frogmc.froglib.events.api.LifecycleEvents;
import dev.frogmc.frogloader.api.mod.ModProperties;
import net.minecraft.server.packs.resources.ReloadableResourceManager;
public class ResourceLoaderClient implements ClientExtension {
@Override
public void onClientInit(ModProperties mod) {
Events.CLIENT_STARTUP.register((m, c) ->
LifecycleEvents.CLIENT_STARTUP.register((m, c) ->
((ReloadableResourceManager) m.getResourceManager()).registerReloadListener(new ResourceLoaderReloadListener()));
}
}

View file

@ -1,14 +1,14 @@
package dev.frogmc.froglib.resources.impl;
import dev.frogmc.froglib.entrypoints.api.ServerExtension;
import dev.frogmc.froglib.events.api.Events;
import dev.frogmc.froglib.events.api.LifecycleEvents;
import dev.frogmc.frogloader.api.mod.ModProperties;
import net.minecraft.server.packs.resources.ReloadableResourceManager;
public class ResourceLoaderServer implements ServerExtension {
@Override
public void onServerInit(ModProperties mod) {
Events.SERVER_STARTUP.register(server ->
LifecycleEvents.SERVER_STARTUP.register(server ->
((ReloadableResourceManager)server.getResourceManager()).registerReloadListener(new ResourceLoaderReloadListener()));
}
}

View file

@ -25,3 +25,5 @@ include("library:resourceloader")
findProject(":library:resourceloader")?.name = "resourceloader"
include("library:registries")
findProject(":library:registries")?.name = "registries"
include("library:player")
findProject(":library:player")?.name = "player"