Jump to content

Alpvax

Members
  • Posts

    297
  • Joined

  • Last visited

  • Days Won

    3

Everything posted by Alpvax

  1. 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. 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).
  3. I'm not exactly sure that is true, but the chunk is already loaded, so the modder can always cancel the loading screen themselves if that is not the case.
  4. 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.
  5. 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.
  6. 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. //Capability.class 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 -> graph.getNode(pos) .map(callback) .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 -> graph.getNode(getPos()).map(callback) ).orElseThrow(() -> new NullPointerException("World %s did not have network capability attached"));
  7. 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?
  8. Look into multipart blockstate json files on the minecraft wiki, they do (almost) everything forge blockstates used to do (forge blockstates no longer exist).
  9. 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.
  10. But I know it does, because I just called isPresent. I would expect it to return null/throw an NPE (either would be acceptable). Except that you cannot return anything from the second approach, which was the entire reasoning behind this query.
  11. Yes, but I'm about to use the value, so it will be calculated anyway. Either way, the issue is solved, thanks.
  12. Except the normal optional also has the value() method public, saving the orElse call. 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.
  13. 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.
  14. 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.
  15. Yes, but with that approach being a supplier, I am correct in thinking that it won't? Would using the delegate fix it, or is a RegistryObject the correct approach?
  16. The only thing I am unsure of with that approach (dieseiben could probably clarify) is whether that continues to work if someone replaces the vanilla entity type.
  17. 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.
  18. 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). Which means you need to keep track of which players should be prone, and set the pose of each of them in a PlayerTickEvent.
  19. Probably true, but as the initial code created a new capability if there wasn't an existing one, I repeated that functionality.
  20. So is there a recommendation for most cases, or does it not really matter?
  21. You probably need to call super#tick at some point.
  22. 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.