Skip to content

Commit

Permalink
✨ travelling merchant spawning logic wip
Browse files Browse the repository at this point in the history
  • Loading branch information
LocusAzzurro committed May 30, 2024
1 parent 99775d6 commit 19ccba9
Show file tree
Hide file tree
Showing 8 changed files with 194 additions and 4 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
package com.voxelutopia.ultramarine.client.integration.jei;

import com.voxelutopia.ultramarine.Ultramarine;
import com.voxelutopia.ultramarine.data.recipe.WoodworkingRecipe;
import com.voxelutopia.ultramarine.data.registry.BlockRegistry;
import mezz.jei.api.constants.VanillaTypes;
import mezz.jei.api.gui.builder.IRecipeLayoutBuilder;
import mezz.jei.api.gui.drawable.IDrawable;
import mezz.jei.api.helpers.IGuiHelper;
import mezz.jei.api.recipe.IFocusGroup;
import mezz.jei.api.recipe.RecipeIngredientRole;
import mezz.jei.api.recipe.RecipeType;
import mezz.jei.api.recipe.category.IRecipeCategory;
import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.TranslatableComponent;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.item.ItemStack;

public class CustomWanderingTraderCategory implements IRecipeCategory<CustomWanderingTraderWrapper> {

public static final ResourceLocation UID = new ResourceLocation(Ultramarine.MOD_ID, "custom_wandering_trader");

public static final RecipeType<CustomWanderingTraderWrapper> CUSTOM_WANDERING_TRADER_WRAPPER_RECIPE_TYPE =
new RecipeType<>(UID, CustomWanderingTraderWrapper.class);

public static final int WIDTH = 82;
public static final int HEIGHT = 34;

private final IDrawable background;
private final IDrawable icon;
private final Component localizedName;

public CustomWanderingTraderCategory(IGuiHelper guiHelper) {
background = guiHelper.createDrawable(UltramarinePlugin.JEI_GUI_VANILLA, 0, 220, WIDTH, HEIGHT);
icon = guiHelper.createDrawableIngredient(VanillaTypes.ITEM_STACK, new ItemStack(BlockRegistry.TEAHOUSE_FLAG.get()));
localizedName = new TranslatableComponent("gui.jei.category.custom_wandering_trader");
}

@Override
public Component getTitle() {
return localizedName;
}

@Override
public IDrawable getBackground() {
return background;
}

@Override
public IDrawable getIcon() {
return icon;
}

@SuppressWarnings("removal")
@Override
public ResourceLocation getUid() {
return UID;
}

@SuppressWarnings("removal")
@Override
public Class<? extends CustomWanderingTraderWrapper> getRecipeClass() {
return CustomWanderingTraderWrapper.class;
}

@Override
public RecipeType<CustomWanderingTraderWrapper> getRecipeType() {
return CUSTOM_WANDERING_TRADER_WRAPPER_RECIPE_TYPE;
}

@Override
public void setRecipe(IRecipeLayoutBuilder builder, CustomWanderingTraderWrapper recipe, IFocusGroup focuses) {
builder.addSlot(RecipeIngredientRole.INPUT, 1, 9).addItemStack(recipe.getInput());
builder.addSlot(RecipeIngredientRole.OUTPUT, 61, 9).addItemStack(recipe.getOutput());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package com.voxelutopia.ultramarine.client.integration.jei;

import mezz.jei.api.recipe.category.extensions.IRecipeCategoryExtension;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.crafting.Ingredient;
import net.minecraft.world.item.trading.MerchantOffer;

public class CustomWanderingTraderWrapper implements IRecipeCategoryExtension {

private ItemStack input;
private ItemStack output;

public CustomWanderingTraderWrapper(MerchantOffer offer){
this.input = offer.getBaseCostA();
this.output = offer.getResult();
}

public ItemStack getInput() {
return input;
}

public ItemStack getOutput() {
return output;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import com.voxelutopia.ultramarine.data.recipe.WoodworkingRecipe;
import com.voxelutopia.ultramarine.data.registry.BlockRegistry;
import com.voxelutopia.ultramarine.data.registry.RecipeTypeRegistry;
import com.voxelutopia.ultramarine.world.entity.CustomWanderingTrader;
import mezz.jei.api.IModPlugin;
import mezz.jei.api.JeiPlugin;
import mezz.jei.api.helpers.IGuiHelper;
Expand Down Expand Up @@ -43,6 +44,7 @@ public void registerCategories(IRecipeCategoryRegistration registration) {
registration.addRecipeCategories(new WoodworkingRecipeCategory(guiHelper));
registration.addRecipeCategories(new CompositeSmeltingRecipeCategory(guiHelper));
registration.addRecipeCategories(new ChiselTableRecipeCategory(guiHelper));
registration.addRecipeCategories(new CustomWanderingTraderCategory(guiHelper));
}

@Override
Expand All @@ -55,13 +57,16 @@ public void registerRecipes(IRecipeRegistration registration) {
registration.addRecipes(CompositeSmeltingRecipeCategory.COMPOSITE_SMELTING_RECIPE_TYPE, compositeSmeltingRecipes);
List<ChiselTableRecipe> chiselTableRecipes = recipeManager.getAllRecipesFor(RecipeTypeRegistry.CHISEL_TABLE.get());
registration.addRecipes(ChiselTableRecipeCategory.CHISEL_TABLE_RECIPE_TYPE, chiselTableRecipes);
List<CustomWanderingTraderWrapper> customWanderingTraderTrades = CustomWanderingTrader.getTradeOptions().stream().map(CustomWanderingTraderWrapper::new).toList();
registration.addRecipes(CustomWanderingTraderCategory.CUSTOM_WANDERING_TRADER_WRAPPER_RECIPE_TYPE, customWanderingTraderTrades);
}

@Override
public void registerRecipeCatalysts(IRecipeCatalystRegistration registration) {
registration.addRecipeCatalyst(new ItemStack(BlockRegistry.WOODWORKING_WORKBENCH.get()), WoodworkingRecipeCategory.WOODWORKING_RECIPE_TYPE);
registration.addRecipeCatalyst(new ItemStack(BlockRegistry.BRICK_KILN.get()), CompositeSmeltingRecipeCategory.COMPOSITE_SMELTING_RECIPE_TYPE);
registration.addRecipeCatalyst(new ItemStack(BlockRegistry.CHISEL_TABLE.get()), ChiselTableRecipeCategory.CHISEL_TABLE_RECIPE_TYPE);
registration.addRecipeCatalyst(new ItemStack(BlockRegistry.TEAHOUSE_FLAG.get()), CustomWanderingTraderCategory.CUSTOM_WANDERING_TRADER_WRAPPER_RECIPE_TYPE);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,13 @@ public class PoiTypeRegistry {

public static final RegistryObject<PoiType> COOKING_POI = POI_TYPES.register("cooking_poi",
() -> new PoiType("cooking_poi", PoiType.getBlockStates(BlockRegistry.FOOD_HAMPER.get()), 1, 1));
public static final RegistryObject<PoiType> TRADE_POI = POI_TYPES.register("trade_poi",
() -> new PoiType("trade_poi", PoiType.getBlockStates(BlockRegistry.TEAHOUSE_FLAG.get()), 1, 5));

public static void registerPOI (){
try {
ObfuscationReflectionHelper.findMethod(PoiType.class, "registerBlockStates", PoiType.class).invoke(null, COOKING_POI.get());
ObfuscationReflectionHelper.findMethod(PoiType.class, "registerBlockStates", PoiType.class).invoke(null, TRADE_POI.get());
} catch (InvocationTargetException | IllegalAccessException e) {
e.printStackTrace();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,30 +2,41 @@

import com.voxelutopia.ultramarine.Ultramarine;
import com.voxelutopia.ultramarine.data.ModBlockTags;
import com.voxelutopia.ultramarine.data.registry.BlockRegistry;
import com.voxelutopia.ultramarine.data.registry.ItemRegistry;
import com.voxelutopia.ultramarine.data.registry.VillagerProfessionRegistry;
import com.voxelutopia.ultramarine.world.block.ChiselTableMedium;
import com.voxelutopia.ultramarine.data.registry.*;
import com.voxelutopia.ultramarine.world.block.DecorativeBlock;
import com.voxelutopia.ultramarine.world.block.SnowRoofRidge;
import com.voxelutopia.ultramarine.world.feature.ModPlacedFeatures;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Holder;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.network.chat.Component;
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.entity.EntityType;
import net.minecraft.world.entity.MobSpawnType;
import net.minecraft.world.entity.SpawnPlacements;
import net.minecraft.world.entity.ai.village.poi.PoiManager;
import net.minecraft.world.entity.item.ItemEntity;
import net.minecraft.world.entity.npc.VillagerProfession;
import net.minecraft.world.entity.npc.VillagerTrades;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Items;
import net.minecraft.world.item.trading.MerchantOffer;
import net.minecraft.world.level.*;
import net.minecraft.world.level.biome.Biomes;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.levelgen.GenerationStep;
import net.minecraft.world.level.levelgen.Heightmap;
import net.minecraft.world.level.levelgen.placement.PlacedFeature;
import net.minecraft.world.level.storage.ServerLevelData;
import net.minecraftforge.common.Tags;
import net.minecraftforge.event.TickEvent;
import net.minecraftforge.event.entity.item.ItemExpireEvent;
import net.minecraftforge.event.entity.living.LivingSpawnEvent;
import net.minecraftforge.event.entity.player.PlayerEvent;
import net.minecraftforge.event.village.VillagerTradesEvent;
import net.minecraftforge.event.village.WandererTradesEvent;
Expand All @@ -35,7 +46,10 @@
import net.minecraftforge.fml.common.Mod;
import org.slf4j.Logger;

import javax.annotation.Nullable;
import java.util.List;
import java.util.Optional;
import java.util.Random;

@Mod.EventBusSubscriber
public class CommonEventHandler {
Expand Down Expand Up @@ -98,6 +112,66 @@ public static void roofSnowFall(BlockEvent.NeighborNotifyEvent event){
}
}

//@SubscribeEvent
public static void accelerateTraderTick(TickEvent.WorldTickEvent event){
if (!event.world.isClientSide() && event.phase == TickEvent.Phase.START){
ServerLevel world = (ServerLevel) event.world;
ServerLevelData levelData = (ServerLevelData) world.getLevelData();
if (world.getGameTime() % 600 == 0){
ServerPlayer player = world.getRandomPlayer();
if (player != null){
EntityType.WANDERING_TRADER.spawn(world, (CompoundTag)null, (Component)null, (Player)null, player.blockPosition(), MobSpawnType.EVENT, false, false);
}
}
}
}

@SubscribeEvent
public static void travellingMerchantSpawn(LivingSpawnEvent.SpecialSpawn event){
if (!event.getWorld().isClientSide()){
ServerLevel world = ((ServerLevelAccessor) event.getWorld()).getLevel();
if (event.getEntityLiving().getType().equals(EntityType.WANDERING_TRADER) && event.getSpawnReason() == MobSpawnType.EVENT){
ServerPlayer player = world.getRandomPlayer();
if (player != null) {
BlockPos blockpos = player.blockPosition();
PoiManager poiManager = world.getPoiManager();
Optional<BlockPos> poiPos = poiManager.find(PoiTypeRegistry.TRADE_POI.get().getPredicate(), (pos) -> true, blockpos, 16, PoiManager.Occupancy.ANY);
poiPos.ifPresent(pos -> {

BlockPos potentialSpawn = null;

for(int i = 0; i < 10; ++i) {
int j = pos.getX() + world.random.nextInt(4 * 2) - 4;
int k = pos.getZ() + world.random.nextInt(4 * 2) - 4;
int l = ((LevelReader) world).getHeight(Heightmap.Types.WORLD_SURFACE, j, k);
BlockPos rolledPos = new BlockPos(j, l, k);
if (NaturalSpawner.isSpawnPositionOk(SpawnPlacements.Type.ON_GROUND, world, rolledPos, EntityType.WANDERING_TRADER)) {
potentialSpawn = rolledPos;
break;
}
}

if (potentialSpawn != null) {

boolean hasSpaceAtSpawn = true;
for (BlockPos blockPos : BlockPos.betweenClosed(potentialSpawn, potentialSpawn.offset(1, 2, 1))) {
if (!((BlockGetter) world).getBlockState(blockPos).getCollisionShape(world, blockPos).isEmpty()) {
hasSpaceAtSpawn = false;
break;
}
}

if (hasSpaceAtSpawn && !world.getBiome(pos).is(Biomes.THE_VOID)) {
EntityTypeRegistry.CUSTOM_WANDERING_TRADER.get().spawn(
world, null, null, null, potentialSpawn.above().above(), MobSpawnType.EVENT, false, false);
}
}
});
}
}
}
}

@SubscribeEvent
public static void villagerTradesHandler(VillagerTradesEvent event){
VillagerProfession profession = event.getType();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.voxelutopia.ultramarine.world.entity;

import com.google.common.collect.ImmutableList;
import com.voxelutopia.ultramarine.data.registry.ItemRegistry;
import net.minecraft.network.protocol.Packet;
import net.minecraft.world.entity.EntityType;
Expand Down Expand Up @@ -44,6 +45,10 @@ public static AttributeSupplier.Builder setCustomAttributes(){
.add(Attributes.FOLLOW_RANGE, 32d);
}

public static List<MerchantOffer> getTradeOptions() {
return ImmutableList.copyOf(TRADE_OPTIONS);
}

@Override
public Packet<?> getAddEntityPacket() {
return NetworkHooks.getEntitySpawningPacket(this);
Expand Down
1 change: 1 addition & 0 deletions src/main/resources/assets/ultramarine/lang/en_us.json
Original file line number Diff line number Diff line change
Expand Up @@ -619,6 +619,7 @@
"gui.jei.category.woodworking": "Woodworking",
"gui.jei.category.composite_smelting": "Composite Smelting",
"gui.jei.category.chisel_table": "Chisel Table",
"gui.jei.category.custom_wandering_trader": "Custom Wandering Trader",

"__EOF__": ""
}
1 change: 1 addition & 0 deletions src/main/resources/assets/ultramarine/lang/zh_cn.json
Original file line number Diff line number Diff line change
Expand Up @@ -618,6 +618,7 @@
"gui.jei.category.woodworking": "木工桌",
"gui.jei.category.composite_smelting": "复合烧炼",
"gui.jei.category.chisel_table": "雕刻桌",
"gui.jei.category.custom_wandering_trader": "行商",

"__EOF__": ""
}

0 comments on commit 19ccba9

Please sign in to comment.