From 132991733ea1452650a9aac46b3f7477659ff4e6 Mon Sep 17 00:00:00 2001 From: William Blake Galbreath Date: Sat, 11 May 2019 01:31:50 -0500 Subject: [PATCH] Villager shops --- .../net/minecraft/server/EntityTypes.java | 7 + .../server/EntityVillagerAbstract.java | 1 + .../minecraft/server/EntityVillagerShop.java | 227 ++++++++++++++++++ .../minecraft/server/NavigationAbstract.java | 2 + .../entity/CraftAbstractVillager.java | 2 +- 5 files changed, 238 insertions(+), 1 deletion(-) create mode 100644 src/main/java/net/minecraft/server/EntityVillagerShop.java diff --git a/src/main/java/net/minecraft/server/EntityTypes.java b/src/main/java/net/minecraft/server/EntityTypes.java index 4979f77b7..475c3ec63 100644 --- a/src/main/java/net/minecraft/server/EntityTypes.java +++ b/src/main/java/net/minecraft/server/EntityTypes.java @@ -118,6 +118,7 @@ public class EntityTypes { public static final EntityTypes LIGHTNING_BOLT = a("lightning_bolt", EntityTypes.a.a(EnumCreatureType.MISC).b().a(0.0F, 0.0F)); public static final EntityTypes PLAYER = a("player", EntityTypes.a.a(EnumCreatureType.MISC).b().a().a(0.6F, 1.8F)); public static final EntityTypes FISHING_BOBBER = a("fishing_bobber", EntityTypes.a.a(EnumCreatureType.MISC).b().a().a(0.25F, 0.25F)); + public static final EntityTypes VILLAGER_SHOP = register("villager_shop", "villager", EntityTypes.a.a(EntityVillagerShop::new, EnumCreatureType.CREATURE).a(0.6F, 1.95F)); private final EntityTypes.b aZ; private final EnumCreatureType ba; private final boolean bb; @@ -138,6 +139,12 @@ public class EntityTypes { } // Purpur start + private static EntityTypes register(String name, String extendFrom, EntityTypes.a entitytypes_a) { + Map> dataTypes = (Map>) DataConverterRegistry.a().getSchema(DataFixUtils.makeKey(SharedConstants.a().getWorldVersion())).findChoiceType(DataConverterTypes.o).types(); // entity_tree + dataTypes.put("minecraft:" + name, dataTypes.get("minecraft:" + extendFrom)); + return a(name, entitytypes_a); + } + public static EntityTypes getFromKey(MinecraftKey key) { return IRegistry.ENTITY_TYPE.get(key); } diff --git a/src/main/java/net/minecraft/server/EntityVillagerAbstract.java b/src/main/java/net/minecraft/server/EntityVillagerAbstract.java index d78528696..8c75daee2 100644 --- a/src/main/java/net/minecraft/server/EntityVillagerAbstract.java +++ b/src/main/java/net/minecraft/server/EntityVillagerAbstract.java @@ -68,6 +68,7 @@ public abstract class EntityVillagerAbstract extends EntityAgeable implements NP return this.tradingPlayer; } + public boolean hasTrader() { return dY(); } // Purpur - OBFHELPER public boolean dY() { return this.tradingPlayer != null; } diff --git a/src/main/java/net/minecraft/server/EntityVillagerShop.java b/src/main/java/net/minecraft/server/EntityVillagerShop.java new file mode 100644 index 000000000..eb7213217 --- /dev/null +++ b/src/main/java/net/minecraft/server/EntityVillagerShop.java @@ -0,0 +1,227 @@ +package net.minecraft.server; + +import com.mojang.datafixers.Dynamic; + +import javax.annotation.Nullable; +import java.util.EnumSet; + +public class EntityVillagerShop extends EntityVillagerAbstract { + private static final DataWatcherObject VILLAGER_DATA = DataWatcher.a(EntityVillagerShop.class, DataWatcherRegistry.q); + + private BlockPosition home; + + public EntityVillagerShop(EntityTypes entitytypes, World world) { + this(EntityTypes.VILLAGER, world, VillagerType.PLAINS); + } + + public EntityVillagerShop(EntityTypes entitytypes, World world, VillagerType villagertype) { + super(entitytypes, world); + setCanPickupLoot(false); + setVillagerData(getVillagerData().withType(villagertype).withProfession(VillagerProfession.NONE)); + } + + @Override + public void setPosition(double x, double y, double z) { + super.setPosition(x, y, z); + if (home == null) { + home = new BlockPosition(x, y, z); + } + } + + @Override + public boolean isTypeNotPersistent(double d) { + return false; // don't despawn + } + + @Override + protected void initDatawatcher() { + super.initDatawatcher(); + this.datawatcher.register(VILLAGER_DATA, new VillagerData(VillagerType.PLAINS, VillagerProfession.NONE, 1)); + } + + public void setVillagerData(VillagerData villagerdata) { + datawatcher.set(VILLAGER_DATA, villagerdata); + } + + public VillagerData getVillagerData() { + return datawatcher.get(VILLAGER_DATA); + } + + @Override + protected void initAttributes() { + super.initAttributes(); + this.getAttributeInstance(GenericAttributes.MOVEMENT_SPEED).setValue(0.5D); + this.getAttributeInstance(GenericAttributes.FOLLOW_RANGE).setValue(48.0D); + } + + @Override + protected void initPathfinder() { + this.goalSelector.a(0, new PathfinderGoalFloat(this)); + this.goalSelector.a(1, new PathfinderGoalTradeWithPlayer(this)); + this.goalSelector.a(1, new PathfinderGoalLookAtTradingPlayer(this)); + this.goalSelector.a(2, new WanderCloseToHome(this, 16.0D, 0.35D)); + this.goalSelector.a(9, new PathfinderGoalInteract(this, EntityHuman.class, 3.0F, 1.0F)); + this.goalSelector.a(10, new PathfinderGoalLookAtPlayer(this, EntityInsentient.class, 8.0F)); + } + + @Override + public void b(NBTTagCompound nbttagcompound) { // write/save + super.b(nbttagcompound); + nbttagcompound.set("VillagerData", getVillagerData().a(DynamicOpsNBT.a)); + } + + @Override + public void a(NBTTagCompound nbttagcompound) { // read/load + super.a(nbttagcompound); + if (nbttagcompound.hasKeyOfType("VillagerData", 10)) { + setVillagerData(new VillagerData(new Dynamic<>(DynamicOpsNBT.a, nbttagcompound.get("VillagerData")))); + } + setCanPickupLoot(false); + } + + @Override + public int dV() { // getExp + return 0; + } + + @Override + public boolean ea() { // showProfessionProgressBar + return false; + } + + @Override + public boolean a(EntityHuman entityhuman, EnumHand enumhand) { // processInteract + ItemStack itemstack = entityhuman.b(enumhand); + if (itemstack.getItem() == Items.NAME_TAG) { + itemstack.a(entityhuman, this, enumhand); + return true; + } + if (itemstack.getItem() != Items.VILLAGER_SPAWN_EGG && this.isAlive() && !this.dY() && !this.isSleeping()) { + if (enumhand == EnumHand.MAIN_HAND) { + entityhuman.a(StatisticList.TALKED_TO_VILLAGER); + } + //if (!getOffers().isEmpty()) { + setTradingPlayer(entityhuman); + openTrade(entityhuman, getScoreboardDisplayName(), getVillagerData().getLevel()); + return true; + //} + } + return super.a(entityhuman, enumhand); + } + + @Nullable + @Override + protected SoundEffect getSoundAmbient() { + return isSleeping() ? null : (hasTrader() ? SoundEffects.ENTITY_VILLAGER_TRADE : SoundEffects.ENTITY_VILLAGER_AMBIENT); + } + + @Override + protected SoundEffect getSoundHurt(DamageSource damagesource) { + return SoundEffects.ENTITY_VILLAGER_HURT; + } + + @Override + protected SoundEffect getSoundDeath() { + return SoundEffects.ENTITY_VILLAGER_DEATH; + } + + @Override + public void e(BlockPosition blockposition) { // sleepInBed + super.e(blockposition); + } + + @Override + protected void ef() { // setupTradeOffers + // do not do anything + } + + @Override + protected void a(MerchantRecipeList list, VillagerTrades.IMerchantRecipeOption[] option, int size) { // addTradeOffers + // do not do anything + } + + @Override + protected void b(MerchantRecipe merchantrecipe) { // processRecipeRewards + // do nothing + } + + @Override + protected void a(EntityItem entityitem) { // updateEquipmentIfNeeded + // do not pick up items + } + + @Override + public boolean a_(int i, ItemStack itemstack) { // setItem + return false; // do not set items in own inventory + } + + @Override + public void setLastDamager(@Nullable EntityLiving entityliving) { + if (isAlive() && entityliving instanceof EntityHuman) { + world.broadcastEntityEffect(this, (byte) 13); // mad particles + } + super.setLastDamager(entityliving); + } + + @Override + public void die(DamageSource damagesource) { + super.die(damagesource); + } + + @Override + public EntityVillagerShop createChild(EntityAgeable entityageable) { + return null; // shop workers don't breed + } + + @Override + public GroupDataEntity prepare(GeneratorAccess generatoraccess, DifficultyDamageScaler difficultydamagescaler, EnumMobSpawn enummobspawn, @Nullable GroupDataEntity groupdataentity, @Nullable NBTTagCompound nbttagcompound) { + if (enummobspawn == EnumMobSpawn.BREEDING) { + setVillagerData(getVillagerData().withProfession(VillagerProfession.NONE)); + } + if (enummobspawn == EnumMobSpawn.COMMAND || enummobspawn == EnumMobSpawn.SPAWN_EGG || enummobspawn == EnumMobSpawn.SPAWNER) { + setVillagerData(getVillagerData().withType(VillagerType.a(generatoraccess.getBiome(new BlockPosition(this))))); + } + return super.prepare(generatoraccess, difficultydamagescaler, enummobspawn, groupdataentity, nbttagcompound); + } + + public void setHome(BlockPosition homePos) { + this.home = homePos; + } + + public BlockPosition getHome() { + return home; + } + + static class WanderCloseToHome extends PathfinderGoal { + final EntityVillagerShop villager; + final double range; + final double speed; + + private WanderCloseToHome(EntityVillagerShop villager, double range, double speed) { + this.villager = villager; + this.range = range; + this.speed = speed; + this.a(EnumSet.of(Type.MOVE)); + } + + @Override + public boolean a() { // shouldExecute + return villager.navigation.hasNoPath(); + } + + @Override + public void e() { // tick + if (!villager.navigation.hasNoPath()) { + return; // already on a path + } + BlockPosition home = villager.getHome(); + if (!home.a(villager.ch(), range)) { + Vec3D direction = new Vec3D(home).add(-villager.locX, -villager.locY, -villager.locZ).d(); // normalize + Vec3D target = direction.a(10.0D).add(villager.locX, villager.locY, villager.locZ); // scale + villager.navigation.setDestination(target.x, target.y, target.z, speed); + } else { + villager.navigation.setDestination(home.getX(), home.getY(), home.getZ(), speed); + } + } + } +} diff --git a/src/main/java/net/minecraft/server/NavigationAbstract.java b/src/main/java/net/minecraft/server/NavigationAbstract.java index 1bf7ead71..46a6511f7 100644 --- a/src/main/java/net/minecraft/server/NavigationAbstract.java +++ b/src/main/java/net/minecraft/server/NavigationAbstract.java @@ -125,6 +125,7 @@ public abstract class NavigationAbstract { } } + public boolean setDestination(double x, double y, double z, double speed) { return a(x, y, z, speed); } // Purpur - OBFHELPER public boolean a(double d0, double d1, double d2, double d3) { return this.a(this.a(d0, d1, d2), d3); } @@ -258,6 +259,7 @@ public abstract class NavigationAbstract { } + public boolean hasNoPath() { return n(); } // Purpur - OBFHELPER public boolean n() { return this.c == null || this.c.b(); } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftAbstractVillager.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftAbstractVillager.java index 18520fec0..307331e37 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftAbstractVillager.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftAbstractVillager.java @@ -20,7 +20,7 @@ public class CraftAbstractVillager extends CraftAgeable implements AbstractVilla @Override public EntityVillagerAbstract getHandle() { - return (EntityVillager) entity; + return (EntityVillagerAbstract) entity; // Purpur } @Override -- 2.20.1