I am trying to replace villager trading with bartering, as with piglins. I was trying to use entityJS entity modification event .canPickupLoot to enable them to pick up emeralds, and then I believe I could use onItemPickUp to create the bartering functionality. However, it seems villagers already have canpPickUpLoot set to true, for breeding and farming I suppose. I can't figure out how to modify this to allow them to also pick up emeralds. Does anyone have a suggestion / workaround?
#Trying to replicate bartering using entityJS
60 messages · Page 1 of 1 (latest)
Once your ticket has been resolved, please close it with </ticket close:1054771505520717835> command!
Specifically, I want emeralds thrown on the ground near a villager to disappear one at a time and then drop a specified loot table a few seconds later, which can depend on the villagers profession
did u ever make progress on this
this will need special handling because the modifyEntity event only modifies methods that arent explicitly overridden by the entity top level class, in this case, Villager.
it is still possible through the .aiStep() to replicate how minecraft detects bounding box interaction with an item entity and then remove one from that entity stack and place it in the villagers mainhand. you would then through persistent data keep track of how long the villager is holding onto the emerald in its mainhanditem slot and remove it after a bit, popping a random item from a selection. for reference this is the java method for how they detect item entities touching the mob java for(ItemEntity itementity : this.level().getEntitiesOfClass(ItemEntity.class, this.getBoundingBox().inflate((double)vec3i.getX(), (double)vec3i.getY(), (double)vec3i.getZ()))) { if (!itementity.isRemoved() && !itementity.getItem().isEmpty() && !itementity.hasPickUpDelay() && this.wantsToPickUp(itementity.getItem())) { this.pickUpItem(itementity); } }
this would translate to something like this where you would call the function inside your aiStep callback ```js
let ItemEntity = Java.loadClass("net.minecraft.world.entity.item.ItemEntity")
/**
*
- @param {Internal.LivingEntity} entity
*/
function hasItemNearby(entity) {
for (let e of entity.level.getEntitiesOfClass(ItemEntity, entity.getBoundingBox().inflate(1, 0, 1))) {
let/**@type {Internal.ItemEntity} */ itementity = e
if (!itementity.isRemoved() && !itementity.getItem().isEmpty() && !itementity.hasPickUpDelay()) {
if (entity.mainHandItem.id == "minecraft:air") {
entity.setItemInHand("main_hand", itementity.getItem())
itementity.item.count--
}
}
}
}```
Oh I was trying to do this without that part, instead having a player give an enderman an item directly and have them look at it for a sec then throw something
I'll update my progress here I guess lol
Actually maybe I will...
without which part, entityjs dependency? cause its possible without it, or are you talking about on right click or something because this logic would still apply, just without the for loop of entities
I meant without them finding the item and picking up, but I decided to still do that in another way
its a bit diff for endermen, so far I just have them picking up the block item
Paste version of enderBartering.js from @celest wyvern
very cool
Do you know how I can disable endermen teleporting/placing a block temporarily?
I am just going to double check it still has the block and within range for now :P
you can try something like this ```js
mob.goalSelector.runningGoals.forEach(g => {
if (g.goal.class instanceof Java.loadClass("net.minecraft.world.entity.monster.EnderMan$EndermanTakeBlockGoal")) {
g.goal.stop()
}
})
there is another example of this in example scripts for controlling tamed mob goals [here](<https://discord.com/channels/303440391124942858/1360058916666605628>)
Thanks!
What about for teleporting? It's not a goal, so I'd think I should listen to the forge EntityTeleportEvent and check if it has the data for being mid-barter then cancel
But it maybe doable in EntityJS I am not familiar enough
Seems pretty “in character” for an endermen to just teleport away in the middle of a deal.
True... but not intuitive to gameplay 
I like to think they're fairly calm and reasonable when not angered
this works
the forge event would be a good place to start
oh nice
can't get that class load instanceof check to work 😭 I am just gonna compare strings 🥹
yeah looks like the class has no visibility modifier so maybe rhino just cant see it or compare it
what I have now, I bet the AI isn't super efficient and it still ends up placing block sometimes so I added a check if it still has the block before throwing reward
Works pretty good though
Paste version of enderBarteringServer.js, enderBarteringStartup.js from @celest wyvern
and fake loot table lmao
How did you do the fake loot table? Are you actually pulling the barter trades from it or is it just for display only
I posted the code above lol ^ I have an object that it actually picks a random item from, but I also made it generate a loot table object for chest loot and create the data in high priority data events, it's just for display but it matches
I don't think I can roll a loot table and get the item entity of it? Since loot tables can drop multiple stacks
Ah gotcha
I'd want it looked over first cus this is the first time I've done anything with entityjs, it may have some glaring issues I don't want others to deal with
Liopyu giving me a "lgtm" or some constructive criticism lol
I mean I have quite a few scripts with more "advanced" contents I should post
fair enough
oh i was just happy someone was actively working on their script and figuring entityjs stuff out instead of asking me to write them scripts 
if you wanted to actually use the loot table then you can use the /loot command. would be all the same though ```js
mob.server.runCommandSilent(loot spawn ${x} ${y} ${z} loot kubejs:enderman_bartering_loot_table)
doesn't give a entity stack since it can output multiple, then I can't apply motion without some questionable antics >_>
hmm, yeah youd have to do it the official way with loot params
let ServerLevel = Java.loadClass("net.minecraft.server.level.ServerLevel")
let LootBuilder = Java.loadClass("net.minecraft.world.level.storage.loot.LootParams$Builder")
let LootContextParams = Java.loadClass("net.minecraft.world.level.storage.loot.parameters.LootContextParams")
let ItemEntity = Java.loadClass("net.minecraft.world.entity.item.ItemEntity")
/**
*
* @param {ResourceLocation_} lootTableId
* @param {Internal.PathfinderMob} entity
* @returns {Internal.ObjectArrayList<Internal.ItemStack>}
*/
function getLootFromTable(lootTableId, entity) {
let level = entity.level
let server = level.getServer()
if (server == null) return []
let table = server.getLootData().getLootTable(lootTableId)
if (table == null) return []
let paramSet = table.getParamSet()
let builder = new LootBuilder(level)
let required = paramSet.getRequired()
if (required.contains(LootContextParams.THIS_ENTITY)) builder = builder.withParameter(LootContextParams.THIS_ENTITY, entity)
if (required.contains(LootContextParams.ORIGIN)) builder = builder.withParameter(LootContextParams.ORIGIN, entity.position())
let params = builder.create(paramSet)
let items = table.getRandomItems(params)
return items
}
// example usage of loot func
ItemEvents.rightClicked(event => {
let { level, entity } = event
let loot = getLootFromTable("minecraft:chests/ancient_city", entity)
loot.forEach(item => {
let itemEntity = new ItemEntity(level, entity.x, entity.y, entity.z, item)
itemEntity.setPickUpDelay(20)
itemEntity.spawn()
})
})```
this way you would be able to set the motion for each of the items you get from the official loot table
@naive kiln if you were also interested in this
Ouh wow
this was basically pulled from the official PiglinAi code and how they do it
Very interesting
||just with a lot of reflection||
That is impressive and very useful, thanks @earnest crag
np, that being said there isnt much of a difference since people will probably not change your modpack's loot tables, it is a good example though
also is this ticket finished? if so then
Please close your ticket (with </ticket close:1054771505520717835> or the button atop this thread) once you resolved your issue!
This also helps others that would like to help out, as they don't have to look into this thread to check if it has been resolved by now.
Do you have any other questions regarding your issue? Feel free to ask!
Note: You should create a new post for unrelated issues.

Lol
oh the op isnt even active in it
Not even our ticket I took it over 
Fucking hilarious
imma go ahead and close it though, thank you all for your contributions