simply put it, i'm trying to make a cloak item where if the user wears it they become fully invis, no fire damage visible, no armor/item (if possible) and the playername/player itself too. lastly i'd want to make it so when someone else sleeps in a bed, the invis player is visible and the sleeping player is in a spectator type pov untill they wake up
#need help making a cloak item
299 messages · Page 1 of 1 (latest)
ok, so thats your goal, what blocker are you running into? what are you stuck on and unable to figure out? we may be able to help guide you through whatever it is
the mixin process to make the player invisible
EntityRendererDispatcher#shouldRender calls the renderer's shouldRender method. EntityRenderer#shouldRender calls the entity's shouldrender method. OtherClientPlayerEntity does do some overriding here but Entity can be used to return false conditionally
PlayerEntityRenderer has shouldRenderFeatures which shouldnt be an issue but if you find that armor is rendering and such, thats why
now to translate that into code lmao
good luck. if you run into any more blockers let me know
i've heard something about a multibugger or something (im working in 1.19.2)
no idea what a multibugger is. can you describe it?
*multiBufferSource
in what context do you need that
ngl got no idea what i'm doin ```java
@Mixin({PlayerEntity.class})
public abstract class LivingEntityRendererMixin<T extends LivingEntity, M extends EntityModel<T>> {
@Shadow public abstract Iterable<ItemStack> getArmorItems();
private void render(T livingEntity, float yaw, float tickDelta, EntityPose poseStack, int light, CallbackInfo ci) {
if (livingEntity instanceof PlayerEntity player) {
ArrayList<ItemStack> items = Lists.newArrayList(this.getArmorItems());
if (items.contains(ModItems.CLOAK)) {
ci.cancel();
}
}
}
}```
all methods you put into a mixin class are copied into the target class[es]
@Mixin({PlayerEntity.class})
the mixin annotation indicates what class your changes are being made to
@Shadow lets you declare a field or method that exists in the target class so you can call it from your mixin code
looks like you are a bit confused so lets break it down into pieces
what class are you trying to change?
i guess just the general renderer that is supposed to show the player, if player is on fire, and the shadow of the player
ok, so lets start with the first thing, preventing the player from rendering.
for this, i have said that Entity#shouldRender is called. so lets say you want to modify the Entity class. your @Mixin annotation should have Entity.class in it
right,
next, lets fix the name and such of your class. for this, i would recommend either the target class name with Mixin suffix, or a purposeful name.
examples:
EntityMixin
InvisibilityCloakEntityMixin
since Entity is the base class (no parents), you dont need to extend anything
@Mixin({Entity.class})
public abstract class InvisibilityCloakEntityMixin { <-?
yep
now, the next step is to figure out what method you want to change.
inside of a Mixin class you can annotate your methods to tell the mixin processor how and where you want to call that method.
which method do you want your code to interact with/be called from/modify
i assume the default render class?
(side note) playStepSound sounds like it'd be cool to overwrite with it aswell
i found should render
public boolean shouldRender(double cameraX, double cameraY, double cameraZ) {
double d = this.getX() - cameraX;
double e = this.getY() - cameraY;
double f = this.getZ() - cameraZ;
double g = d * d + e * e + f * f;
return this.shouldRender(g);
}
public boolean shouldRender(double distance) {
double d = this.getBoundingBox().getAverageSideLength();
if (Double.isNaN(d)) {
d = (double)1.0F;
}
d *= (double)64.0F * renderDistanceMultiplier;
return distance < d * d;
} ```
ok, so the first one is called from the render dispatcher, the 2nd is called from the first. the 2nd is overridden in a child class so the first is probably what you want to change.
so, method will be shouldRender with the proper arguments. are you using IntelliJ with the MinecraftDevelopment plugin?
i should yeah
ok good
so now its time to figure out how you want to modify the method. that will determine which annotation you use
so with the following information, how would you modify the method?
your running code is running inside the entity that it wants to render
you can modify variables, method calls, return values, arguments, etc
public boolean shouldRender(double cameraX, double cameraY, double cameraZ) {
double d = this.getX() - cameraX;
double e = this.getY() - cameraY;
double f = this.getZ() - cameraZ;
double g = d * d + e * e + f * f;
return this.shouldRender(g);
}
i want to (while the entity is wearing the cloak) make it invisible (and if possible) only visible at like the corner of someone's screen
ok, lets do the "no render" part first, and deal with the FoV and frustum thing later
so, you are wanting to tell the game that it should not render conditionally, so you want to change the return value of the method based on some if statement(s) ?
gotta check that the chestplate slot (or helmet not quite sure which one to pick yet, i was thinking of maybe using trinkets for this) holds the cloak item
alright, so i would use a @ModifyReturnValue annotation here.
that tells Mixin that you want to change the return value of the method (really just describes itself)
each mixin method annotation has at a minimum a method parameter, telling it which method to put code in and an at parameter, telling it where to put code inside the method
so an example might be
@ModifyReturnValue(method="getName", at=@At("RETURN")) which would modify the return value of the getName method for every place that method returns something
the @At("RETURN") there is shorthand for @At(value="RETURN")
the longer form is used when you need to tell the @At more info such as when you want to put code anytime the method invokes (calls) a specific method
alright
so it kinda looks like this rn? ```java
@Mixin({Entity.class})
public abstract class InvisibilityCloakEntityMixin {
@ModifyReturnValue(method="shouldRender", at=@At("RETURN"))
@Shadow public abstract double getX();
@Shadow public abstract double getY();
@Shadow public abstract double getZ();
@Shadow
public static double getRenderDistanceMultiplier() {
return 0;
}
@Shadow public abstract Box getBoundingBox();
public boolean shouldRender(double cameraX, double cameraY, double cameraZ) {
double d = this.getX() - cameraX;
double e = this.getY() - cameraY;
double f = this.getZ() - cameraZ;
double g = d * d + e * e + f * f;
return this.shouldRender(g);
}
private boolean shouldRender(double distance) {
double d = this.getBoundingBox().getAverageSideLength();
if (Double.isNaN(d)) {
d = (double)1.0F;
}
d *= (double)64.0F * getRenderDistanceMultiplier();
return distance < d * d;
}
}```
alright, you dont need to put those methods in the mixin, but since you are going to modify them you need to know what they are, thats all. you can remove everything after @ModifyReturnValue(method="shouldRender", at=@At("RETURN")) before the last }
you should also let mcdev autocomplete the shouldRender in the method to select the one that takes 3 doubles
turns into this
yep good
the next step is to make the method that does the checking and returns the new return value. Mixin methods are primarily private (with some special exceptions for interfaces and parent mixin classes)
the @ModifyReturnValue expects to annotate a method that returns the same type as the method you are modifying. it also expects that method to take the original return value as a parameter.
so you need a method that:
is private
returns a boolean
takes in the original boolean as an argument
your method should fallback on returning the original boolean if you are not handling it (such as if they are not wearing the cloak)
i brought back the shadow, because i find it easier if i can just get the armor items and loop through that. ```java
@Shadow
public abstract Iterable<ItemStack> getArmorItems();
ArrayList<ItemStack> items = Lists.newArrayList(this.getArmorItems());
private boolean shouldRender(boolean og) {
return items.contains(ModItems.CLOAK);
}```
this is the cloak item class btw, it's literally nothign
so, Entity doesnt have a getArmorItems method, so you cant shadow it
you also should not just add a list of items to the class
hm, thats in Entity?
ye
interesting, must have been removed later
they prob thought, let's make it more annoying!
or it got name changed/redundant
lol, more like "Entity is a base class and not all entities have equipment, fireballs for example have no equipment"
welp; it makes it easier in this instance ig
your code should look something like
Iterator<ItemStack> itemIterator = getArmorItems().iterator();
while (itemIterator.hasNext()) {
ItemStack stack = itemIterator.next();
// YOUR CHECK HERE
}
you dont want to be building a list object every render frame
error, hasNext shouldn't be there for some reason
did you get the first line?
yes
can you show the whole method
(that should all be in your annotated method
private boolean shouldRender(boolean og) {
Iterator<ItemStack> itemIterator = getArmorItems().iterator();
while (itemIterator.hasNext()) {
...
well now it works lmfao
@Shadow public abstract Iterable<ItemStack> getArmorItems();
private boolean shouldRender(boolean og) {
Iterator<ItemStack> itemIterator = getArmorItems().iterator();
while (itemIterator.hasNext()) {
if (itemIterator.equals(ModItems.CLOAK)) {
return false;
}
}
return true;
}```
that's it kinda looks rn
instead of return true besure to return the original return value
coz og can also be false?
yep
right, that's now done
and other mods might be doing the same thing and you want to return their value if so
alright, now to make your item equippable 😛
i guess holding it in your hand should still work for testing
@ModifyReturnValue(method="shouldRender(DDD)Z", at=@At("RETURN")); this line still gives me an error of sorts
show the whole class. i expect that annotation is not right above the method
@ModifyReturnValue(...)
private boolean shouldRender(boolean og) {
...
import com.llamalad7.mixinextras.injector.ModifyReturnValue;
import com.zrollus.bd.item.ModItems;
import net.minecraft.entity.Entity;
import net.minecraft.item.ItemStack;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import java.util.Iterator;
@Mixin({Entity.class})
public abstract class InvisibilityCloakEntityMixin {
@ModifyReturnValue(method="shouldRender(DDD)Z", at=@At("RETURN"));
@Shadow public abstract Iterable<ItemStack> getArmorItems();
private boolean shouldRender(boolean og) {
Iterator<ItemStack> itemIterator = getArmorItems().iterator();
while (itemIterator.hasNext()) {
if (itemIterator.equals(ModItems.CLOAK)) {
return false;
}
}
return og;
}
}
the annotation is annotating the method to tell mixin that your "shouldRender" method is to be interacted with a specific way
the shadow can go above that
shadow is above it rn
yeah, swap the locationsof the @ModifyReturnValue line and the @Shadow line
no ;
that'd be it lol
used to always having a ;
public static final Item CLOAK = registerItem("cloak", new ArmorItem(cloakMaterial, EquipmentSlot.HEAD, new Item.Settings().group(ModItemGroup.BuildersDelight).fireproof())); <- this is btw how i'm registering the item
ah ok, so you arent using your cloak class at all anyway
not yet because i haven't (till now) found a reason to use it
since technically it doesn't seem required for what i'm trying to achieve
btw do i have to call the mixin at all or does it sorta start automatically
the mixin class needs to be pointed to in the mixin json file
mixin itself will read the json, load your mixin class, read the annotations and modify the target class according to the annotations you wrote
why do i have the slight feeling the game is not able to load into a world now?
coz its trying but crashing
whats the crash message
not a crash message, more just it's frozen
oh...just to check, did you update your mixin json to remove the old name and make sure the new name was there?
also the console should be showing what its doing
i would suggest once you get it tested you move that to the client section rather than the mixins section
if it does end up crashing again i shall say, (Example mixin got broke for some reason)
it repeats to just freeze when entering a world
aka when the client is supposed to see the world
[17:26:21] [Server thread/INFO] (Minecraft) Player698[local:E:7709087c] logged in with entity id 69 at (43.0886720511649, 56.0, -77.80153982327381)
[17:26:21] [Server thread/INFO] (Minecraft) Player698 joined the game
[17:26:21] [Render thread/INFO] (Minecraft) Loaded 0 advancements
last msgs in logs
i have a feeling i know whats going on. did you move the mixin to client?
yes
cool
in the shouldRender mixin method, at the top, add the following check:
if (!((Entity)(Object)this instanceof OtherClientPlayerEntity)) return og;
basically, only check inventories of other players
like so?
yeah
it was probably constantly looping over all inventories of all entities
you could alternatively set it to PlayerEntity instead of OtherClientPlayerEntity to test third person if you dont have another player to test with lol
(personally, i would probably handle it via status effect, but i dont know if those are synced to other clients without checking)
what is the yellow its giving for itemIterator?
oh, you didnt set the itemstack
...
ItemStack stack = itemIterator.next();
so the iterator never progresses so the while loop is infinite
i put that in the loop but not in the if right?
Iterator<ItemStack> itemIterator = getArmorItems().iterator();
while (itemIterator.hasNext()) {
ItemStack stack = itemIterator.next();
// YOUR CHECK HERE
}
the stack is what you should be checking against your item
stack.getItem().equals or stack.isOf
woo!
i have to eat dinner, but now im curious how either A trinkets could be involved and/or B, the vision thing would work.
the only dependancy i've used ever is gecko
-
move the check into some helper method that can check tinkers and inventory slots. the trinket slot would need to be synced to other players, not sure if they are.
move the mixin into EntityRenderer
target EntityRenderer#shouldRender
there should be a check in there for leashed or visible entities. you can use WrapOperation on the frustum.isVisible call to adjust some things there if needed, too
the Frustum is used to determine if something is in the FoV of the player.
some of the methods in Frustum are private, but you can do your own check there with intersectAab. it should return FrustumIntersection.INTERSECT (-1) if the entity is only partiall in "view" but not fully encompassed in the visible space
if you want to do that, you can use an invoker mixin in the Frustum class to let you call the method by casting
you can assume i'm probably gonna need that step by step like a kaupenjoe tutorial
(currently just trying to check for the item)
-# Lin is goat
having trouble with checking for the trinket slot
you added trinket as a dependency in your build.gradle?
yes, i have trinkets in the game, the issue is checking for the item,
remind me again what mc version you are using
current attempt
1.19.2
private boolean isEquipped = false;
private void IsEquipped(Iterator<ItemStack> itemIterator) {
while (itemIterator.hasNext()) {
ItemStack stack = itemIterator.next();
if (stack.getItem().equals(ModItems.CLOAK)) {
this.isEquipped = true;
} else {
isEquipped = false;
}
}
}``` i did add this
first thing to be careful of is the casting.
instead of the iterator, you should take in the entity
in the IsEquipped?
yeah
ok? brings me to ask why
your isEquipped method should check if the item is equipped, right?
you dont need to iterate the trinket slots manually
aight, so like this?
boolean hasTrinketEquipped = TrinketsApi.getTrinketComponent()
.map(component->component.isEquipped(stack->stack.isOf(YOURITEM)))
.orElse(false);
something like that should work for the trinkets
it gets the Optional from trinkets
then it uses Optional's map (which will map the contained value if its not null/empty) to check if one of the trinket slots has it equipped
then it gets the value if it has one or returns false
put that in the if or is it literally just another bool that we can return
if you want to check player equipment slots also, you can do that if trinkets returns false, for example
ugh ok, 1 sec that should be an easy fix but i want to make sure trinkets didnt account for it
thing is, the thing you said is in their docs, but somewhat they said nuh uh
you may need to add cardinal components to your build.gradle, as well
oh yeh, that's a mod i know from doctor4t's mods
gotta make sure that's version 5.1.0
5.1.0 is for 1.19.3
i would not develop against something that says its not for the version you are developing on
ok, would 5.2.2 work?
then how tf do the mods (quilted fabric api) work with them
that are on 1.19.2
eg, befoul
again, not saying it wont work, i am saying that issues may come up because they didnt release that version for 1.19.2 so players wont be using the newer versions
develop against what players will be using
it should
i added it
and the error just despawned coz of it
@Mixin({Entity.class})
public abstract class InvisibilityCloakEntityMixin {
private boolean isEquipped = false;
private void IsEquipped(Entity entity) {
boolean hasTrinketEquipped = TrinketsApi.getTrinketComponent((LivingEntity)entity)
.map(component->component.isEquipped(stack->stack.isOf(ModItems.CLOAK)))
.orElse(false);
if (!hasTrinketEquipped) {
Iterator<ItemStack> itemIterator = getArmorItems().iterator();
while (itemIterator.hasNext()) {
ItemStack stack = itemIterator.next();
if (stack.getItem().equals(ModItems.CLOAK)) {
this.isEquipped = true;
} else {
isEquipped = false;
}
}
}
else {
isEquipped = true;
}
}
@Shadow public abstract Iterable<ItemStack> getArmorItems();
@ModifyReturnValue(method="shouldRender(DDD)Z", at=@At("RETURN"))
private boolean shouldRender(boolean og) {
if (!((Entity)(Object)this instanceof PlayerEntity)) return og;
Iterator<ItemStack> itemIterator = getArmorItems().iterator();
return !isEquipped;
}
}```
this is what it looks like
you can make IsEquipped take in a LivingEntity and do the cast from the mixin
@Mixin({Entity.class})
public abstract class InvisibilityCloakEntityMixin {
private boolean IsEquipped(PlayerEntity entity) {
boolean hasTrinketEquipped = TrinketsApi.getTrinketComponent(entity)
.map(component->component.isEquipped(stack->stack.isOf(ModItems.CLOAK)))
.orElse(false);
if (hasTrinketEquipped) return true;
Iterator<ItemStack> itemIterator = getArmorItems().iterator();
while (itemIterator.hasNext()) {
ItemStack stack = itemIterator.next();
if (stack.getItem().equals(ModItems.CLOAK)) {
return true;
}
}
return false;
}
@Shadow public abstract Iterable<ItemStack> getArmorItems();
@ModifyReturnValue(method="shouldRender(DDD)Z", at=@At("RETURN"))
private boolean shouldRender(boolean og) {
if (!((Entity)(Object)this instanceof PlayerEntity playerEntity)) return og;
return isEquipped(playerEntity)?false:og;
}
}
something like this
you can check the logic and see if it makes sense
!isEquipped && og means:
if it is not equipped, and it was originally supposed to render, then render
if it was not equipped and original supposed to not render, dont render
if it was equipped, do not render
true && true = true
false && false = false
false && true = false
that seems to be saying that the wrong fabric api is being pulled in
huh...
might be in mixture with cardinal components
even tho it's just doing this, i might have to downgrade the loader
cardinal components is doing it
you need to filter fabric stuff from them
modImplementation(cardinalcomponentsstuff) {
exclude group: "net.fabricmc.fabric-api"
})
you might also need to exclude the group net.fabricmc since they are doing the same thing for loader 
fabric 0.58.0+1.19
is that the right fabric api for your version of mc?
it's the one it auto selects
what autoselects?
oh, you are developing for 1.19 not 1.19.2?
mc is also running 1.19....
and somehow it works in a 1.19.2 modpack
minecraft_version=1.19.2
yarn_mappings=1.19.2+build.28
loader_version=0.16.9
# Fabric API
fabric_version=0.77.0+1.19.2
vs
minecraft_version=1.19
yarn_mappings=1.19+build.4
loader_version=0.16.9
# Fabric API
fabric_version=0.58.0+1.19
the problem is when you start trying to mix and match versions of things you run into issues
some stuff works, some doesnt, and its a toss up whether your mod will even compile let alone run
the problem is that cardinal components is pulling in a specific version of a submodule of fabric api and its newer than yours
welp, that works now
im afraid of how difficult the ^^ is gonna be
lol
in this instances its basically "the visible area of the camera"
There is a debug renderer that visualizes frustum pretty well
still dunno the how, but i assume there's docs for it
declaration: package: net.minecraft.client.render, class: Frustum
don't close this yet, it's like 9pm, been working on this stuff since the morning and i've got school tomorrow, so will prob ask help tomorrow evenin
resending as a note move the mixin into EntityRenderer target EntityRenderer#shouldRender there should be a check in there for leashed or visible entities. you can use WrapOperation on the frustum.isVisible call to adjust some things there if needed, too the Frustum is used to determine if something is in the FoV of the player. some of the methods in Frustum are private, but you can do your own check there with intersectAab. it should return FrustumIntersection.INTERSECT (-1) if the entity is only partiall in "view" but not fully encompassed in the visible space if you want to do that, you can use an invoker mixin in the Frustum class to let you call the method by casting
why does it need to be entityrenderer actually, we're technically only checking the player
inside the renderer's check is where the frustum is checked for entity culling. we can use the frustum passed into that check for our own (reverse) culling check
will i need to use this? or the actual frustum doc
im assuming the actual doc coz of IsVisible
or this
ngl shi makes no sense at all, even with the docs
thinking about it, it might just make more sense to calculate the difference in rotation angle from the camera and angle to the player and depending on FOV make them visible
(if you dont want to deal with an accessor to get the frustum's intersects to calculate the intersection with the player bounding box
would you mind, like quickly, (like before) helping with the code
reaction the realest thing ever
kind reminder as even if you say that stuff im just mouth gaping wide open atm
i assume you were inspired by charter by arathain
yes
and im pretty sure the version thats public is open source
so go ahead and take a look
i dont know if they had that feature pre rewrite
i checked, doesn't have those items
ah
it's the 0.0.1 beta hence i wanted to make it for myself, (privatised mod not to upset the csmp peeps)
at first i thought it'd be fairly easy, up until i realised it aint
from what i know most the csmp mods are pretty unoptimized
so they probably just reversed the culling render effect with some slighty inaccurate values
advice from the fabric gods tells me to use enderman logic
boolean isPlayerStaring(PlayerEntity player) {
ItemStack itemStack = (ItemStack)player.getInventory().armor.get(3);
if (itemStack.isOf(Blocks.CARVED_PUMPKIN.asItem())) {
return false;
} else {
Vec3d vec3d = player.getRotationVec(1.0F).normalize();
Vec3d vec3d2 = new Vec3d(this.getX() - player.getX(), this.getEyeY() - player.getEyeY(), this.getZ() - player.getZ());
double d = vec3d2.length();
vec3d2 = vec3d2.normalize();
double e = vec3d.dotProduct(vec3d2);
return e > (double)1.0F - 0.025 / d ? player.canSee(this) : false;
}
}```
Player#canSee was just mentioned in another channel
indeed, but im in rendering channel for this atm
Oops lol
ngl, i launched 2 mc clients at once nearly killed my pc lmao
so euhm, i kinda accidentally made everyone invis, (oopsies)
quick problem check? ```java
@Mixin({Entity.class})
public abstract class InvisibilityCloakEntityMixin {
private boolean IsEquipped(PlayerEntity entity) {
boolean hasTrinketEquipped = TrinketsApi.getTrinketComponent(entity)
.map(component->component.isEquipped(stack->stack.isOf(ModItems.CLOAK)))
.orElse(false);
if (hasTrinketEquipped) return true;
Iterator<ItemStack> itemIterator = getArmorItems().iterator();
while (itemIterator.hasNext()) {
ItemStack stack = itemIterator.next();
if (stack.getItem().equals(ModItems.CLOAK)) {
return true;
}
}
return false;
}
boolean isPlayerStaring(PlayerEntity player) {
Vec3d vec3d = player.getRotationVec(1.0F).normalize();
Vec3d vec3d2 = new Vec3d(this.getX() - player.getX(), this.getEyeY() - player.getEyeY(), this.getZ() - player.getZ());
double d = vec3d2.length();
vec3d2 = vec3d2.normalize();
double e = vec3d.dotProduct(vec3d2);
return e > (double)1.0F - 0.025 / d ? player.canSee((Entity)(Object)this) : false;
}
@Shadow public abstract Iterable<ItemStack> getArmorItems();
@Shadow public abstract double getX();
@Shadow public abstract double getEyeY();
@Shadow public abstract double getZ();
@ModifyReturnValue(method="shouldRender(DDD)Z", at=@At("RETURN"))
private boolean shouldRender(boolean og) {
if (!((Entity)(Object)this instanceof OtherClientPlayerEntity playerEntity)) return og;
return !IsEquipped(playerEntity) && isPlayerStaring(playerEntity) && og;
}
}```
That would make sense
i had !isPlayerStaring, maybe i should make it an or stateent or smth?
or add an if
Currently, you only render if the player is looking exactly at the entity
yes, i am trying to make it so it's not onscreen, so isseen is prob better
Later on, you may want to look into submixin or instance of checks to ensure you only affect things that can wear your cloak
could you link to the msg you saw it in
I'm not sure I understand
this
the thing is, i think i'll need a different class because it needs to check it from every (other player) pov
unless that already does it here
Wouldn't you be doing it only for the clients player?
the thing already gets from other pov
OtherClientPlayerEntity
this means it gets it from other clients and only renders on other clients
so i just need to calculate if it sees another player, and you can say frustum all you want, idk how to use it