#Trading with non-villager mobs (specifically vanilla mobs)
128 messages ยท Page 1 of 1 (latest)
Yes, it would be possible. I would recommend using the UseEntityCallback or whatever fapi calls it
all implementations of createScreenHandlerFactory online seem to be for blocks is there any page on doing for whatever?
public static void registerEvokerInteractions() {
UseEntityCallback.EVENT.register((player, world, hand, entity, hitResult) -> {
if (
!player.isSpectator()
&& entity.getType().equals(EntityType.EVOKER)
&& player.hasStatusEffect(ModEffects.HERO_OF_THE_PILLAGE)
) {
if (!world.isClient) {
NamedScreenHandlerFactory screenHandlerFactory = //createScreenHandlerFactoryImplementation();
}
}
return ActionResult.SUCCESS;
});
}
this is what i have so far
there is MerchantScreenHandler, which you can turn into a NamedScreenHandlerFactory using SimpleNamedScreenHandlerFactory, this is how vanilla does it.
vanilla example for villager:
player.openHandledScreen(
new SimpleNamedScreenHandlerFactory((syncId, playerInventory, playerx) -> new MerchantScreenHandler(syncId, playerInventory, this), name)
);
(this is at Merchant#sendOffers(), if you want to see more of how vanilla does it)
can I use the screenhandlercontext to get the recipemanager
@jagged torrent What version are you working with? Because I'm making something similar for 1.21.4 and already have everything but the actual trades working (it had the trading screen before but I changed it, it should be pretty easy to add trades back tho)
1.20.1
so far this is what I came up with
but it returns an Optional<Optional<EnchantmentConversionRecipe>
should I just use a series of .get()'s to extract the recipe from the optional?
that seems risky
but I dont see another way with my setup
Optional<Optional<EnchantmentConversionRecipe>> recipe = context.get((world, pos) -> world.getRecipeManager().getFirstMatch(EnchantmentConversionRecipe.Type.INSTANCE, this.input, world));
this.result.setStack(0, new ItemStack(recipe.get().get().getOutput()));
``` this seems cursed
context.get(
(world, pos) -> world.getRecipeManager()
.getFirstMatch(
RecipeType.BLASTING,
this.input,
world
)
)
.flatMap(Function.identity())
.map(recipe -> recipe.getOutput())
.ifPresentOrElse(
stack -> this.result.setStack(0, stack),
() -> this.result.setStack(0, ItemStack.EMPTY)
);
``` try something like this?
is this for the message above the message above?
ok
im getting red for the setStack method
oops
fixed ๐
had to shim it to get the compiler to stop screaming at me
var stack = context.get(
(world, pos) -> world.getRecipeManager()
.getFirstMatch(
RecipeType.BLASTING,
this.input,
world
)
)
.flatMap(Function.identity())
.map(recipe -> recipe.getOutput())
.orElse(ItemStack.EMPTY);
this.result.setStack(0, stack);
``` something like this might also work, if you like it better?
it looks nice but im still not sure how to use enchanted books in recipes
yes
so both result and input?
yes
concerning ๐
:)! ! !! !
I haven't done this in a minute.
o
what does your matcher look like rn?
๐
it's okay
I meant the one in your recipe?
if there is one in that version?
Recipe#matches
I dont have a matcher in my recipe class
okay
describe a recipe to me? EnchantedBook{SHARPNESS:5} -> EnchantedBook{CUSTOM:5}?
something like that
okay
exactly liek that
var enchantment = Enchantments.AQUA_AFFINITY;
var enchantmentResult = Enchantments.BINDING_CURSE;
var stack = Items.DIAMOND_HELMET.getDefaultStack();
int level = EnchantmentHelper.getLevel(enchantment, stack);
if (level > 0) {
var map = EnchantmentHelper.get(stack);
map.remove(enchantment);
map.put(enchantmentResult, 1);
EnchantmentHelper.set(map, stack);
}
something like that?
or what is something else the problem?
what does that do
if the stack has AQUA_AFFINITY, it replaces AQUA_AFFINITY with BINDING_CURSE on the stack
sorry that is not what I am trying to do
well it could work
but the input can only accept singular enchantment enchanted books
so it could replace the enchantment with the modded one
on a book
does that work
I'm not sure I understand what the poblem is?
the code I've provided is an example
it should work with all items
?
but isnt that hardcoded
it doesn't have to be though
it's up to you to un hardcode it
it's hardcoded to make it easy to understand
if there is something you don't understand about how, I'd be glad to help with that
so I am using slots and an update function in a screenhandler to handle the crafting
in the update function is where the recipe would go
how would I create a list of enchantments match another list of enchantments without using traditional recipes
because you cant use a normal json file right
and I dont want it to replace what is in the input
I want a new book in the output
so I already cleared the input in my code
using slots
I am just missing a version of this that works for enchantments
so I can make a list of "recipes"
without having to use a switch statement ๐
for each enchantment pair
that is my problem
idk
can I use a json file
If you want to
Maps are a basic programming concept, there's plenty of info on them.
this is my solution to the problem
private void updateResult() {
ItemStack inputStack = this.input.getStack(0);
ItemStack outputStack = new ItemStack(Items.ENCHANTED_BOOK);
if (inputStack.isEmpty()) {
this.result.setStack(0, ItemStack.EMPTY);
} else {
NbtList nbtList = inputStack.getEnchantments();
for (int i = 0; i < nbtList.size(); i++) {
NbtCompound nbtCompound = nbtList.getCompound(i);
Identifier inputEnchantment = EnchantmentHelper.getIdFromNbt(nbtCompound);
int level = EnchantmentHelper.getLevelFromNbt(nbtCompound);
Enchantment outputEnchantment;
if (inputEnchantment != null && inputEnchantment.equals(Registries.ENCHANTMENT.getId(Enchantments.SHARPNESS))) {
float chance = random.nextFloat();
if (chance < 0.1) {
outputEnchantment = ModEnchants.BLEEDING;
} else {
outputEnchantment = ModEnchants.DULLNESS;
}
} else {
outputEnchantment = this.alternativeEnchantMap.get(inputEnchantment);
}
EnchantedBookItem.addEnchantment(outputStack, new EnchantmentLevelEntry(outputEnchantment, level));
}
this.result.setStack(0, outputStack);
}
this.sendContentUpdates();
}
I just iterate over the enchantments and apply them to a map
then apply the new enchants to a book
sharpness gets special treatment with randomness
but I think im done
here is my above definition of the map
of course I do not like this solution because this looks longer than it needs to be
but im forced to use identifiers with "getStuffFromNbt"
so this is valid?
player.openHandledScreen(
new SimpleNamedScreenHandlerFactory((syncId, playerInventory, playerx) ->
new EvokerScreenHandler(
syncId,
playerInventory,
ScreenHandlerContext.create(world, entity.getBlockPos())
), entity.getDisplayName())
);
inside of useEntityCallback implementation event register
btw my screen does not appear when this is called
no crashing just no response
You've made the screen, but you haven't set the screen for the player
oh
I thought that's what openScreenHandler did
I looked on the documentation for what I need to do
how do I set the screen aswell?
Oh I'm blind I didn't see the first line
Are you checking logical side properly?
like checking for client
I check if the world is not client before openHandledScreen
still no screen