Skip to content

Commit

Permalink
Merge pull request #22 from valoeghese/tsuchimikado_motoharu
Browse files Browse the repository at this point in the history
chunk gen events
  • Loading branch information
valoeghese authored Oct 11, 2020
2 parents 12356bf + 8ad6517 commit 501960d
Show file tree
Hide file tree
Showing 13 changed files with 226 additions and 15 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@
import net.minecraft.item.ItemStack;
import net.minecraft.server.network.ServerPlayerEntity;

/**
* @author B0undaryBreaker
*/
@Mixin(InventoryChangedCriterion.class)
public class MixinInventoryChangedCriterion {
@Inject(method = "trigger(Lnet/minecraft/server/network/ServerPlayerEntity;Lnet/minecraft/entity/player/PlayerInventory;Lnet/minecraft/item/ItemStack;III)V", at = @At("HEAD"))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@
import net.minecraft.item.ItemStack;
import net.minecraft.server.network.ServerPlayerEntity;

/**
* @author B0undaryBreaker
*/
@Mixin(ItemDurabilityChangedCriterion.class)
public class MixinItemDurabilityChangedCriterion {
@Inject(method = "trigger", at = @At("HEAD"))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@
import net.minecraft.entity.damage.DamageSource;
import net.minecraft.server.network.ServerPlayerEntity;

/**
* @author B0undaryBreaker
*/
@Mixin(OnKilledCriterion.class)
public class MixinOnKilledCriterion {
@Inject(method = "trigger", at = @At("HEAD"))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@
import net.minecraft.entity.damage.DamageSource;
import net.minecraft.server.network.ServerPlayerEntity;

/**
* @author b0undary
*/
@Mixin(PlayerHurtEntityCriterion.class)
public class MixinPlayerHurtEntityCriterion {
@Inject(method = "trigger", at = @At("HEAD"))
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,24 @@
package io.github.fabriccommunity.events.mixin.spawn;

import java.util.Random;

import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.Redirect;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;

import io.github.fabriccommunity.events.impl.EntitySpawnImpl;
import io.github.fabriccommunity.events.world.WorldGenEvents;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityType;
import net.minecraft.server.world.ServerWorld;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.ServerWorldAccess;
import net.minecraft.world.SpawnHelper;
import net.minecraft.world.WorldView;
import net.minecraft.world.biome.Biome;

/**
* @author Valoeghese
Expand All @@ -30,4 +40,14 @@ private static void entitySpawnEventNatural(ServerWorld self, Entity entity) {
private static void entitySpawnEventChunk(ServerWorldAccess self, Entity entity) {
EntitySpawnImpl.spawnEntityV(self, entity);
}

@Inject(at = @At("RETURN"), method = "populateEntities")
private static void onPopulateEntities(ServerWorldAccess world, Biome biome, int chunkX, int chunkZ, Random random, CallbackInfo info) {
WorldGenEvents.POPULATE_ENTITIES.invoker().onPopulateEntities(world, biome, chunkX, chunkZ, random, MixinSpawnHelper::getEntitySpawnPos);
}

@Shadow
private static BlockPos getEntitySpawnPos(WorldView world, EntityType<?> entityType, int x, int z) {
throw new RuntimeException("Mixin getEntitySpawnPos failed to apply!");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package io.github.fabriccommunity.events.mixin.world;

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 io.github.fabriccommunity.events.world.WorldGenEvents;
import net.minecraft.world.ChunkRegion;
import net.minecraft.world.gen.StructureAccessor;
import net.minecraft.world.gen.chunk.ChunkGenerator;

/**
* @author Valoeghese
*/
@Mixin(ChunkGenerator.class)
public class MixinChunkGenerator {
@Inject(at = @At("HEAD"), method = "generateFeatures", cancellable = true)
private void onStartGenerateFeatures(ChunkRegion region, StructureAccessor accessor, CallbackInfo info) {
if (WorldGenEvents.GENERATE_FEATURES_START.invoker().onStartGenerateFeatures((ChunkGenerator) (Object) this, region, accessor)) {
info.cancel();
}
}

@Inject(at = @At("RETURN"), method = "generateFeatures")
private void onEndGenerateFeatures(ChunkRegion region, StructureAccessor accessor, CallbackInfo info) {
WorldGenEvents.GENERATE_FEATURES_END.invoker().onEndGenerateFeatures((ChunkGenerator) (Object) this, region, accessor);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,10 @@ public class PlayerAdvancementEvents {
*/
public static final Event<ItemDurabilityChanged> ITEM_DURABILITY_CHANGED_WILDCARD = EventFactory.createArrayBacked(ItemDurabilityChanged.class,
listeners -> (player, stack, damage) -> {
for (ItemDurabilityChanged listener : listeners) {
listener.onItemDurabilityChange(player, stack, damage);
}
});
for (ItemDurabilityChanged listener : listeners) {
listener.onItemDurabilityChange(player, stack, damage);
}
});

/**
* An event run when the durability of a stack of <item> is changed.
Expand All @@ -58,10 +58,10 @@ public static Event<ItemDurabilityChanged> itemDurabilityChanged(Item item) {
*/
public static final Event<PlayerHurtEntity> PLAYER_HURT_ENTITY_WILDCARD = EventFactory.createArrayBacked(PlayerHurtEntity.class,
listeners -> (attacker, victim, source, dealt, taken, blocked) -> {
for (PlayerHurtEntity listener : listeners) {
listener.onPlayerHurtEntity(attacker, victim, source, dealt, taken, blocked);
}
});
for (PlayerHurtEntity listener : listeners) {
listener.onPlayerHurtEntity(attacker, victim, source, dealt, taken, blocked);
}
});

/**
* An event run when a player hurts a specific type of entity.
Expand All @@ -77,10 +77,10 @@ public static Event<PlayerHurtEntity> playerHurtEntity(EntityType<?> type) {
*/
public static final Event<PlayerKilledEntity> PLAYER_KILLED_ENTITY_WILDCARD = EventFactory.createArrayBacked(PlayerKilledEntity.class,
listeners -> (killer, victim, source) -> {
for (PlayerKilledEntity listener : listeners) {
listener.onPlayerKillEntity(killer, victim, source);
}
});
for (PlayerKilledEntity listener : listeners) {
listener.onPlayerKillEntity(killer, victim, source);
}
});

/**
* An event run when a play kills a specific type of entity.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package io.github.fabriccommunity.events.util;

import net.minecraft.entity.EntityType;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.WorldView;

/**
* Used by {@link WorldGenEvents.POPULATE_ENTITIES} as an accessible way to get the entity spawn pos for given x/z coordinates.
* @author Valoeghese
*/
@FunctionalInterface
public interface SpawnPosGetter {
BlockPos getEntitySpawnPos(WorldView world, EntityType<?> entityType, int x, int z);
}
Original file line number Diff line number Diff line change
@@ -1,13 +1,19 @@
package io.github.fabriccommunity.events.world;

import java.util.Random;
import java.util.concurrent.atomic.AtomicReference;

import io.github.fabriccommunity.events.util.SpawnPosGetter;
import net.fabricmc.fabric.api.event.Event;
import net.fabricmc.fabric.api.event.EventFactory;
import net.minecraft.util.ActionResult;
import net.minecraft.util.registry.Registry;
import net.minecraft.world.ChunkRegion;
import net.minecraft.world.ServerWorldAccess;
import net.minecraft.world.biome.Biome;
import net.minecraft.world.biome.source.BiomeSource;
import net.minecraft.world.gen.StructureAccessor;
import net.minecraft.world.gen.chunk.ChunkGenerator;

/**
* A collection of events pertaining to world generation.
Expand All @@ -28,8 +34,39 @@ public final class WorldGenEvents {
return ActionResult.PASS;
});

/**
* Called on feature placement to allow for mods to modify the chunk without using mojang's "features", or even replace chunk feature population, among various other things.
*/
public static final Event<GenerateFeaturesStart> GENERATE_FEATURES_START = EventFactory.createArrayBacked(GenerateFeaturesStart.class, listeners -> (generator, region, structures) -> {
for (GenerateFeaturesStart listener : listeners) {
if (listener.onStartGenerateFeatures(generator, region, structures)) {
return true;
}
}

return false;
});

/**
* Called at the end of biome placement to allow for mods to edit the biome to be placed.
*/
public static final Event<GenerateFeaturesEnd> GENERATE_FEATURES_END = EventFactory.createArrayBacked(GenerateFeaturesEnd.class, listeners -> (generator, region, structures) -> {
for (GenerateFeaturesEnd listener : listeners) {
listener.onEndGenerateFeatures(generator, region, structures);
}
});

/**
* Called on chunk generation entity population to allow for mods to spawn entities with their own logic.
*/
public static final Event<PopulateEntities> POPULATE_ENTITIES = EventFactory.createArrayBacked(PopulateEntities.class, listeners -> (world, biome, chunkX, chunkZ, random, spawnPosGetter) -> {
for (PopulateEntities listener : listeners) {
listener.onPopulateEntities(world, biome, chunkX, chunkZ, random, spawnPosGetter);
}
});

/**
* Called on feature placement to allow for mods to modify the chunk without using mojang's "features", among various other things.
* @author Valoeghese
*/
@FunctionalInterface
Expand All @@ -51,4 +88,33 @@ public interface BiomePlacement {
*/
ActionResult onBiomePlace(BiomeSource source, Registry<Biome> registry, final Biome original, AtomicReference<Biome> biome, int genX, int genZ);
}

/**
* Called on feature placement to allow for mods to modify the chunk without using mojang's "features", or even replace chunk feature population, among various other things.
* @return true to cancel further event processing and not place features through vanilla's method. false to pass on to further event processing.
* @author Valoeghese
*/
@FunctionalInterface
public interface GenerateFeaturesStart {
boolean onStartGenerateFeatures(ChunkGenerator generator, ChunkRegion region, StructureAccessor accessor);
}

/**
* Called on feature placement to allow for mods to modify the chunk without using mojang's "features", among various other things.
* @author Valoeghese
*/
@FunctionalInterface
public interface GenerateFeaturesEnd {
void onEndGenerateFeatures(ChunkGenerator generator, ChunkRegion region, StructureAccessor accessor);
}

/**
* Called on chunk generation entity population to allow for mods to spawn entities with their own logic.
* @param spawnPosGetter a function used by vanilla to get the spawn block pos for the given x/z coordinates.
* @author Valoeghese
*/
@FunctionalInterface
public interface PopulateEntities {
void onPopulateEntities(ServerWorldAccess world, Biome biome, int chunkX, int chunkZ, Random random, SpawnPosGetter spawnPosGetter);
}
}
6 changes: 4 additions & 2 deletions src/main/resources/fabric.mod.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,10 @@
"name": "Too Many Events",
"description": "More events for modders to use",
"authors": [
"Valoeghese",
"HalfOf2"
"b0undary",
"HalfOf2",
"LeoCTH",
"Valoeghese"
],

"license": "MIT",
Expand Down
3 changes: 2 additions & 1 deletion src/main/resources/toomanyevents.mixins.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@
"spawn.MixinEntityType",
"spawn.MixinMobSpawnerLogic",
"spawn.MixinSpawnHelper",
"spawn.MixinSummonCommand"
"spawn.MixinSummonCommand",
"world.MixinChunkGenerator"
],
"client": [
"client.MixinBackgroundRenderer",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
package io.github.fabriccommunity.events.test;

import io.github.fabriccommunity.events.world.WorldGenEvents;
import net.fabricmc.api.ModInitializer;
import net.minecraft.block.Blocks;
import net.minecraft.entity.EntityType;
import net.minecraft.entity.SpawnReason;
import net.minecraft.entity.passive.VillagerEntity;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.biome.Biome;

public class ChunkGenTest implements ModInitializer {
public static final boolean ENABLED = true;

@Override
public void onInitialize() {
if (ENABLED) {
WorldGenEvents.GENERATE_FEATURES_START.register((generator, region, structures) -> {
if (random(region.getCenterChunkX(), region.getCenterChunkZ(), (int) region.getSeed(), 0b111) == 0) {
return true; // cancel further event processing
}

return false;
});

WorldGenEvents.GENERATE_FEATURES_END.register((generator, region, structures) -> {
int x = region.getCenterChunkX() * 16;
int z = region.getCenterChunkZ() * 16;
BlockPos.Mutable e = new BlockPos.Mutable(x, 0, z);

for (int y = 128; y >= 32; --y) {
e.setY(y);
region.setBlockState(e, Blocks.AIR.getDefaultState(), 3);
}
});

WorldGenEvents.POPULATE_ENTITIES.register((world, biome, chunkX, chunkZ, random, spawnPosGetter) -> {
if (biome.getCategory() != Biome.Category.OCEAN) {
int target = random.nextInt(3);

for (int i = 0; i < target; ++i) {
int ex = (chunkX << 4) + random.nextInt(16);
int ez = (chunkZ << 4) + random.nextInt(16);

VillagerEntity villager = EntityType.VILLAGER.create(world.toServerWorld());
BlockPos pos = spawnPosGetter.getEntitySpawnPos(world, villager.getType(), ex, ez);
villager.refreshPositionAndAngles(pos, random.nextFloat() * 360.0f, 0.0f);
villager.headYaw = villager.yaw;
villager.bodyYaw = villager.yaw;
villager.initialize(world, world.getLocalDifficulty(pos), SpawnReason.STRUCTURE, null, null);
world.spawnEntityAndPassengers(villager);
}
}
});
}
}

private static int random(int x, int y, int seed, int mask) {
seed = 375462423 * seed + 672456235;
seed += x;
seed = 375462423 * seed + 672456235;
seed += y;
seed = 375462423 * seed + 672456235;
return seed & mask;
}
}
1 change: 1 addition & 0 deletions src/test/resources/fabric.mod.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
"main": [
"io.github.fabriccommunity.events.test.BiomePlacementTest",
"io.github.fabriccommunity.events.test.BlockPlaceTest",
"io.github.fabriccommunity.events.test.ChunkGenTest",
"io.github.fabriccommunity.events.test.FoodTest",
"io.github.fabriccommunity.events.test.EntitySpawnTest",
"io.github.fabriccommunity.events.test.PlayerInteractionTest",
Expand Down

0 comments on commit 501960d

Please sign in to comment.