Jump to content


  • Posts

  • Joined

  • Last visited

  • Days Won


Posts posted by Alpvax

  1. 56 minutes ago, Tavi007 said:
    Set<String> modFolderList = Sets.newHashSet();
    for (final String modFolder : modFolderList)//loop over supported mods 
        Set<String> mobFileList = Sets.newHashSet();
        for (final String mobFile : mobFileList)//loop over supported mobs (not listed mobs will use 'empty' as default)


    You create a new (empty) set, then loop through it. Twice.

    Neither of your loops will do anything, as they are both always going to be empty when the loop is run.


    58 minutes ago, Tavi007 said:

    My folder hierarchy looks like this: data/entities/<supported mod>/<mobs from mod>, where <supported mod> should be the mod id. For the vanilla mobs, this will be named 'minecraft'.

    I would suggest including your modid in the path, to stop there being conflicts.

    I would also not limit it to "supported" mods. That way support for third party mods can be added by datapacks (or even included in those mods if your mod becomes popular enough).

    I would recommend using a path such as data/<datapackid>/<your mod id>/entities/<modid>/<mobname>.json

    That would mean that your zombie definition would be at data/<your mod id>/<your mod id>/entities/minecraft/zombie.json

    It means your modid is duplicated, but there is no risk of another mod using the entities path and causing your mod to crash.

  2. As the Optional annotation has now disappeared in favour of capabilities, there is now no way to add optional features to non-TileEntity blocks.

    An example use case would be proper fluid handling for vanilla cauldrons, or handling of different blocks' "heat" values.


    It would have to return a function (BlockState, IWorldReader) -> custom capability instance. And couldn't be cached without more work. The capability would also not be able to be serialisable to NBT (obviously non-TEs don't have NBT).


    It would effectively be a mapping of blockstate -> capability.

    If we restricted it to readonly capabilities there would be no issues with modders caching the capability and modifying something they shouldn't, but it would for example allow extraction from cauldrons, but not insertion.

    The optimum solution would be for the capabilities to be cached when first accessed (Probably by calling World/Chunk#getBlockCapability(Capability, BlockPos)) which would then be returned every time afterwards (until the position was unloaded).


    It would allow ModB to support ModA's X system, without having to inherit from an API which may not exist at runtime.


    This post is intended as the starting point of a discussion, if it is an idea that no-one is interested in, that is fine.

    The alternative is to just ship ModA's API with ModB, or at least the interfaces you are implementing in your block, but that has no way of adding capabilities to blocks which you don't own (e.g. vanilla cauldrons, torches).

    • Like 1
  3. 5 minutes ago, BlockyPenguin said:

    If we go one step further, how do they get it so you can step between dimensions without a loading screen or even a lag spike?

    Because the chunk in the other dimension is already loaded, just like when you move from one chunk to the next in the same dimension, or use the teleport command to move to a loaded chunk.

    • Like 1
  4. On 5/20/2020 at 8:13 AM, diesieben07 said:

    There is no reason to use the marker. It does not save you from accessing client only code.

    I understand that (I also understand how to use DistExecutor, and use it when I need to call client side methods).

    My question is is it safe for me to use it as a marker, just something to double check when I'm calling my methods so I know not to call them from the wrong side. Or would javadoc be better?

    Apologies for somewhat hijacking the thread, I won't reply again.

  5. I have a follow up question:

    I have a world capability, and one of the method returns is Optional (or could be @Nullable).

    The LazyOptional#map argument is a NonNullFunction, and ideally I would return empty from the calling function rather than null.


    public Optional<INetworkNode> getNode(BlockPos pos) {
        return Optional.ofNullable(nodes.get(pos));
    //Utility class (I'm happy to change the return type to LazyOptional)
    public <T> Optional<T> ifNetworkNode(Function<INetworkNode, T> callback, BlockPos pos) {
        return getWorld().getCapability(Capabilities.NETWORK_CAPABILITY).map(graph ->
                .orElse(null) //<-- How can I unbox this Optional and return (Lazy)Optional.empty from the method instead of null?


    Am I doing something wrong? Have I missed something obvious again?


    EDIT: yes I was. I just needed to call orElseThrow on the LazyOptional

    return getWorld().getCapability(Capabilities.NETWORK_GRAPH_CAPABILITY).map(graph ->
        ).orElseThrow(() -> new NullPointerException("World %s did not have network capability attached"));


  6. On 5/17/2020 at 7:08 PM, imacatlolol said:

    OnlyIn does literally nothing for modders. It's an internal marker for Forge/FML only, so modders shouldn't use it.

    How true is this? Does it do nothing, or are the methods stripped during build/run? I have used it in the past as a marker for methods which I know must only be used on the client. Does this have a functional use or is it safe to use as a marker?

  7. 1 hour ago, Draco18s said:

    Why would you need to?

    Because many of the vanilla methods which I'm overriding have return values...


    I'm dropping this thread now, Lex answered my question, and it seems you're never going to understand what I was attempting to achieve Draco.

  8. 1 hour ago, Draco18s said:

    But what if it doesn't HAVE a value?

    But I know it does, because I just called isPresent. I would expect it to return null/throw an NPE (either would be acceptable).


    1 hour ago, Draco18s said:
    val = orElse(null)
    if(val != null) { /*code*/ }


    is functionally equivalent to


    ifPresent(val -> { /*code*/ } );

    Except that you cannot return anything from the second approach, which was the entire reasoning behind this query.

  9. 19 hours ago, LexManos said:

    Its exactly as useful as the normal Java Optional.

    Except the normal optional also has the value() method public, saving the orElse call.


    19 hours ago, LexManos said:

    Your examples are also pretty bad. The way you would want to do it is like:

    cap.map(e -> e.amount() * e.amountMultiplier()).orElse(0)

    Yes, the example was in fact bad, and that was helpful, thank you. I didn't even thing of doing all the processing inside the Map function, I have always tried to make them as simple as possible.

  10. 2 hours ago, Novârch said:

    LazyOptional.ifPresent(props -> {}) is what you want, props will be an instance of your capability. Here's an example of how I use it.


    2 hours ago, Draco18s said:

    ifPresent() takes a lambda operator. Anything that would go inside your if(val != null) block goes directly into that lambda.

    Yes, I am aware of that method. But you cannot return a value from it. (scope is now lambda scope).

    I was also asking about the isPresent method, not ifPresent.

  11. Is it just me, or is the LazyOptional very awkward to use?

    The isPresent() function seems virtually useless, what does it offer over doing .orElse(null), followed by a null check, because you cannot get the value without using orElse anyway?


    It seems that there is no easy way to return a value from a capability that may not be present. For example:

    interface CapabilitySample {
      int amount();
      int amountMultiplier();
    //In another class:
    public int getAmount(ICapabilityProvider obj) {
    	LazyOptional<CapabilitySample> cap = obj.getCapability(Capability_Instance);
      //************** Option 1 **************
        // Works if you only need a single method from the capability
        return cap.map(CapabilitySample::amount).orElse(0);
        //But what if you need multiple methods? The following (mapping the capability twice) seems like a bad idea:
        return cap.map(CapabilitySample::amount).orElse(0) * cap.map(CapabilitySample::amountMultiplier).orElse(1);
      //************** Option 2 **************
        if (cap.isPresent()) {
            //How do I return cap.amount() from here? There is no way to retrieve the cap.value().
            //Do I really have to do the following?
            CapabilitySample value = cap.orElseThrow(()-> new Exception("Pointless exception which can never happen!"));
            return value.amount() * value.amountModifier();
        } else {
            return 0;
      //************** Option 3 **************
        //Requires an entire implementation to be written with dummy methods!
        CapabilitySample value = cap.orElse(dummyCapabilitySample);
        return return value.amount() * value.amountModifier();


    Am I missing something, or is this a big oversight? Am I using capabilities wrong? Am I not supposed to return values from them, and just go all-in functional?


    As an unrelated aside, I also find the capability default implementation factory impossible to use, because invariably I want to use the object I am attaching to to set up the capability.

  12. RegistryObject.of(resourceLocation-of-entitytype, ForgeRegistries.ENTITY);

    If you change it to receive a Supplier<? extends EntityType<? extends LivingEntity>> instead of having to be a RegistryObject, then you could pass in the vanilla types as () -> VANILLA_TYPE.


    You could change your existing method to create the registry object or supplier and pass it into the other method.

  13. On 4/16/2020 at 7:57 PM, Naxehr said:

    I'm not even getting my code to run. i see its protected, which makes sense why its giving me an error when i try to call the setpose function.

    when i try to call it directly from the other script.

    		if (KeyBindings.crawl.isPressed()) {
    			if (player.getItemStackFromSlot(EquipmentSlotType.LEGS).getItem() == iteminit.parkour_knee_guard) {

    What other script?

    Did you look at my code?

    You need to use Reflection, or an access transformer to set the pose.

    You need to set the pose on the server (you need to send a packet when the button is pressed/released).

    On 4/16/2020 at 4:36 PM, Alpvax said:

    You have set the player's pose at the end of every tick,

    Which means you need to keep track of which players should be prone, and set the pose of each of them in a PlayerTickEvent.

  14. 4 minutes ago, DarkAssassin said:

    public void tick(BlockState state, World worldIn, BlockPos pos, Random random) {
              if (!worldIn.isRemote) {
                 if (worldIn.isBlockPowered(pos)) {
                    AbstractSpawner.isActivated  = true;
                AbstractSpawner.isActivated =false;     


    You probably need to call super#tick at some point.

  15. 6 minutes ago, KidKoderMod033109 said:

    I used this line, but for CapabilityAllergies::new  IntelliJ said that IAllergies was a functional interface.

    My mistake, I didn't have access to the code at the time.

    It should be either .orElseGet(CapabilityAllergies::new) or .orElse(new CapabilityAllergies()).

    The difference is that the first option will not create a new instance unless it is required, whereas the second will regardless. (Which you use will probably only result in a minor performance difference).

  • Create New...

Important Information

By using this site, you agree to our Terms of Use.