#need help making a cloak item

299 messages · Page 1 of 1 (latest)

visual mountain
#

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

forest bone
#

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

visual mountain
#

the mixin process to make the player invisible

forest bone
#

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

visual mountain
#

now to translate that into code lmao

forest bone
#

good luck. if you run into any more blockers let me know

visual mountain
#

i've heard something about a multibugger or something (im working in 1.19.2)

forest bone
#

no idea what a multibugger is. can you describe it?

visual mountain
#

*multiBufferSource

forest bone
#

in what context do you need that

visual mountain
#

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();
        }
    }
}

}```

forest bone
#

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?

visual mountain
#

i guess just the general renderer that is supposed to show the player, if player is on fire, and the shadow of the player

forest bone
#

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

visual mountain
#

right,

forest bone
#

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

visual mountain
#

@Mixin({Entity.class})
public abstract class InvisibilityCloakEntityMixin { <-?

forest bone
#

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

visual mountain
#

i assume the default render class?

forest bone
#

nope, not class

#

we are within the Entity class

#

what method in the Entity class

visual mountain
#

(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;
    } ```
forest bone
#

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?

visual mountain
#

i should yeah

forest bone
#

ok good

visual mountain
forest bone
#

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);
}
visual mountain
#

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

forest bone
#

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) ?

visual mountain
#

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

forest bone
#

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

visual mountain
#

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;
}

}```

forest bone
#

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

visual mountain
#

turns into this

forest bone
#

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)

visual mountain
#

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

forest bone
#

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

visual mountain
#

this is in the entity class

#

but i hear what ya sayin

forest bone
#

hm, thats in Entity?

visual mountain
#

ye

forest bone
#

interesting, must have been removed later

visual mountain
#

they prob thought, let's make it more annoying!

#

or it got name changed/redundant

forest bone
#

lol, more like "Entity is a base class and not all entities have equipment, fireballs for example have no equipment"

visual mountain
#

welp; it makes it easier in this instance ig

forest bone
#

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

visual mountain
#

error, hasNext shouldn't be there for some reason

forest bone
#

did you get the first line?

visual mountain
#

yes

forest bone
#

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()) {
...
visual mountain
#

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

forest bone
#

instead of return true besure to return the original return value

visual mountain
#

coz og can also be false?

forest bone
#

yep

visual mountain
#

right, that's now done

forest bone
#

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

visual mountain
#

@ModifyReturnValue(method="shouldRender(DDD)Z", at=@At("RETURN")); this line still gives me an error of sorts

forest bone
#

show the whole class. i expect that annotation is not right above the method

#
@ModifyReturnValue(...)
private boolean shouldRender(boolean og) {
...
visual mountain
#

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;
    }
}
forest bone
#

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

visual mountain
#

shadow is above it rn

forest bone
#

yeah, swap the locationsof the @ModifyReturnValue line and the @Shadow line

visual mountain
forest bone
#

no ;

visual mountain
#

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

forest bone
#

ah ok, so you arent using your cloak class at all anyway

visual mountain
#

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

forest bone
#

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

visual mountain
#

why do i have the slight feeling the game is not able to load into a world now?

#

coz its trying but crashing

forest bone
#

whats the crash message

visual mountain
#

not a crash message, more just it's frozen

forest bone
#

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

visual mountain
#

it said failed after force closing the game

forest bone
#

i would suggest once you get it tested you move that to the client section rather than the mixins section

visual mountain
#

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

forest bone
#

i have a feeling i know whats going on. did you move the mixin to client?

visual mountain
#

yes

forest bone
#

cool

visual mountain
forest bone
#

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

visual mountain
#

like so?

forest bone
#

yeah

visual mountain
#

it was probably constantly looping over all inventories of all entities

forest bone
#

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)

visual mountain
#

i'll try playerEntity coz it's faster

#

i won't try it because issue returns

forest bone
#

what is the yellow its giving for itemIterator?

visual mountain
#

freeze happens for both players once they're close to eachother

forest bone
#

oh, you didnt set the itemstack

visual mountain
#

...

forest bone
#

ItemStack stack = itemIterator.next();

#

so the iterator never progresses so the while loop is infinite

visual mountain
#

i put that in the loop but not in the if right?

forest bone
#
  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

visual mountain
#

alr, testin

#

that works!

forest bone
#

woo!

visual mountain
#

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

forest bone
#
  1. 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

visual mountain
#

you can assume i'm probably gonna need that step by step like a kaupenjoe tutorial

visual mountain
#

(currently just trying to check for the item)

visual mountain
#

having trouble with checking for the trinket slot

forest bone
#

you added trinket as a dependency in your build.gradle?

visual mountain
#

yes, i have trinkets in the game, the issue is checking for the item,

forest bone
#

remind me again what mc version you are using

visual mountain
#

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
forest bone
#

first thing to be careful of is the casting.

#

instead of the iterator, you should take in the entity

visual mountain
#

in the IsEquipped?

forest bone
#

yeah

visual mountain
#

ok? brings me to ask why

forest bone
#

your isEquipped method should check if the item is equipped, right?
you dont need to iterate the trinket slots manually

visual mountain
#

aight, so like this?

forest bone
#
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

visual mountain
#

put that in the if or is it literally just another bool that we can return

forest bone
#

if you want to check player equipment slots also, you can do that if trinkets returns false, for example

visual mountain
forest bone
#

where is that?

#

(in the code i posted)

visual mountain
forest bone
#

you didnt pass it an entity

#

and that should be inside a method

visual mountain
#

error persists

#

(has to be living entity)

forest bone
#

ugh ok, 1 sec that should be an easy fix but i want to make sure trinkets didnt account for it

visual mountain
#

thing is, the thing you said is in their docs, but somewhat they said nuh uh

forest bone
#

you may need to add cardinal components to your build.gradle, as well

visual mountain
#

oh yeh, that's a mod i know from doctor4t's mods

#

gotta make sure that's version 5.1.0

forest bone
#

5.1.0 is for 1.19.3

visual mountain
#

it works on 1.19.2

#

for some reason

forest bone
#

i would not develop against something that says its not for the version you are developing on

visual mountain
#

ok, would 5.2.2 work?

forest bone
#

nope

#

(thats even higher...)

visual mountain
#

then how tf do the mods (quilted fabric api) work with them

#

that are on 1.19.2

#

eg, befoul

forest bone
#

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

visual mountain
#

5.0.2 also exists in one of the mods

#

that would work right?

forest bone
#

it should

visual mountain
#

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

forest bone
#

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

visual mountain
#

last line IsEquipped but yes

#

trust?

forest bone
#

you can check the logic and see if it makes sense

visual mountain
#

doesn't make sense imo

#

but it does

forest bone
#

!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

visual mountain
#

so simplify good

#

error

forest bone
#

that seems to be saying that the wrong fabric api is being pulled in

visual mountain
#

huh...

#

might be in mixture with cardinal components

#

even tho it's just doing this, i might have to downgrade the loader

forest bone
#

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 concern

visual mountain
forest bone
#

can you show the rest of the error?

#

(or the latest.log from the run/logs folder)

visual mountain
forest bone
#

fabric 0.58.0+1.19

is that the right fabric api for your version of mc?

visual mountain
#

it's the one it auto selects

forest bone
#

what autoselects?

visual mountain
forest bone
#

oh, you are developing for 1.19 not 1.19.2?

visual mountain
#

well

#

lets say i forgot to update api

#

lmao

forest bone
#

mc is also running 1.19....

visual mountain
#

and somehow it works in a 1.19.2 modpack

forest bone
#
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

visual mountain
#

true

#

cardinal is very dependant on correct version

forest bone
#

the problem is that cardinal components is pulling in a specific version of a submodule of fabric api and its newer than yours

visual mountain
#

welp, that works now

visual mountain
forest bone
#

lol

visual mountain
#

coz idek what the heck frustum is

#

and how the hecc to implement

forest bone
#

in this instances its basically "the visible area of the camera"

strong notch
#

There is a debug renderer that visualizes frustum pretty well

visual mountain
#

still dunno the how, but i assume there's docs for it

#

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

visual mountain
#

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

forest bone
#

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

visual mountain
#

will i need to use this? or the actual frustum doc

#

im assuming the actual doc coz of IsVisible

#

or this

visual mountain
#

ngl shi makes no sense at all, even with the docs

forest bone
#

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

visual mountain
#

would you mind, like quickly, (like before) helping with the code

#

reaction the realest thing ever

visual mountain
#

kind reminder as even if you say that stuff im just mouth gaping wide open atm

harsh panther
visual mountain
#

yes

harsh panther
#

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

visual mountain
#

i checked, doesn't have those items

harsh panther
#

ah

visual mountain
#

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

harsh panther
#

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

visual mountain
#

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;
        }
    }```
strong notch
#

Player#canSee was just mentioned in another channel

visual mountain
#

indeed, but im in rendering channel for this atm

visual mountain
#

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;
}

}```

visual mountain
#

i had !isPlayerStaring, maybe i should make it an or stateent or smth?

#

or add an if

strong notch
visual mountain
#

yes, i am trying to make it so it's not onscreen, so isseen is prob better

strong notch
visual mountain
#

could you link to the msg you saw it in

strong notch
visual mountain
#

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

strong notch
visual mountain
#

the thing already gets from other pov

#

OtherClientPlayerEntity

#

this means it gets it from other clients and only renders on other clients

visual mountain
#

so i just need to calculate if it sees another player, and you can say frustum all you want, idk how to use it

harsh panther
#

frustum is the culling method minecraft uses to hide entities outside of players fov

#

thats as far as my knowledge goes tho

#

i assume it uses like an fov variable

#

so you could probably make a mixin with the reverse effect of the culling

#

but like minus the fov by a bit