BlockyPenguin Posted March 21, 2021 Posted March 21, 2021 (edited) So I have made a capability for chunks, and it has a float field in it. I would like the float to tick up by 0.1 every x amount of ticks (configurable by user). How would I go about doing this? Thanks! Edited March 21, 2021 by BlockyPenguin Quote Today (22/10/20) I reached 100 posts! I'm probably more excited than I should be for something so realistically minor...
BlockyPenguin Posted March 21, 2021 Author Posted March 21, 2021 17 minutes ago, diesieben07 said: Is it a requirement that it only ticks when the chunk is loaded? Preferably, yes. Quote Today (22/10/20) I reached 100 posts! I'm probably more excited than I should be for something so realistically minor...
BlockyPenguin Posted March 21, 2021 Author Posted March 21, 2021 1 hour ago, diesieben07 said: Option 1: Use Chunk#getInhabitedTime, it increases every tick, but only if there are actual players nearby (not spectators) or if the chunk is force loaded. This might be enough for your needs. Option 2: If that does not work for you, use WorldTickEvent, check that you are on the server and then use something similar to ServerChunkProvider#tickChunks to update all loaded chunks. Thanks, I think I'll use Chunk#getInhabitedTime. Where should I put my code though? Is there an event or something? Quote Today (22/10/20) I reached 100 posts! I'm probably more excited than I should be for something so realistically minor...
BlockyPenguin Posted March 21, 2021 Author Posted March 21, 2021 2 hours ago, diesieben07 said: Wherever you would normally access the float value in your capability, use getInhabitedTime. So, my capability has a getter for the float, yes, but how would I get the instance of Chunk? Quote Today (22/10/20) I reached 100 posts! I'm probably more excited than I should be for something so realistically minor...
BlockyPenguin Posted March 21, 2021 Author Posted March 21, 2021 (edited) So this is my capability: public class RiftCapability implements IRift { private boolean isRift; private float riftActivityPercent; public RiftCapability() { this.isRift = Rifts.RAND.nextInt(100) < 5; this.riftActivityPercent = isRift ? Utils.randomFloatBounds(0.15f) : 0.0f; } public RiftCapability(boolean isRift, float riftActivityPercent) { this.isRift = isRift; this.riftActivityPercent = riftActivityPercent; } @Override public boolean isRift() { return isRift; } @Override public float getRiftActivityPercent() { return riftActivityPercent; } @Override public void setRiftActivityPercent(float riftActivityPercent) { if(riftActivityPercent < 0 || riftActivityPercent > 1) throw new IndexOutOfBoundsException("Rift Activity Percent cannot be less than 0 or greater than 1!"); else this.riftActivityPercent = riftActivityPercent; } @Override public void openRift() { this.isRift = true; } @Override public void closeRift() { this.isRift = false; } @Override public void riftEvent() { //TODO: Fire a rift event. } } This is my provider: public class RiftCapabilityProvider implements ICapabilitySerializable<INBT> { @CapabilityInject(IRift.class) public static final Capability<IRift> RIFT_CAPABILITY = null; private LazyOptional<IRift> instance = LazyOptional.of(RIFT_CAPABILITY::getDefaultInstance); @Override public <T> LazyOptional<T> getCapability(Capability<T> cap, Direction side) { return cap == RIFT_CAPABILITY ? instance.cast() : LazyOptional.empty(); } @Override public INBT serializeNBT() { return RIFT_CAPABILITY.getStorage().writeNBT( RIFT_CAPABILITY, instance.orElseThrow(() -> new IllegalArgumentException("LazyOptional must not be empty!")), null ); } @Override public void deserializeNBT(INBT nbt) { RIFT_CAPABILITY.getStorage().readNBT( RIFT_CAPABILITY, instance.orElseThrow(() -> new IllegalArgumentException("LazyOptional must not be empty!")), null, nbt ); } } And I attach it like so: public static void attachRiftCapability(AttachCapabilitiesEvent<Chunk> event) { World world = event.getObject().getWorld(); if(!world.isRemote) event.addCapability(new ResourceLocation(Rifts.MODID, "rift_capability"), new RiftCapabilityProvider()); } Does this help? Edited March 21, 2021 by BlockyPenguin Quote Today (22/10/20) I reached 100 posts! I'm probably more excited than I should be for something so realistically minor...
BlockyPenguin Posted March 21, 2021 Author Posted March 21, 2021 9 minutes ago, diesieben07 said: You don't need the float value anymore, you can calculate it from the inhabited time. Oh, ok... but my question still remains as to how to get the inhabited time. Quote Today (22/10/20) I reached 100 posts! I'm probably more excited than I should be for something so realistically minor...
BlockyPenguin Posted March 21, 2021 Author Posted March 21, 2021 1 hour ago, diesieben07 said: Call Chunk#getInhabitedTime... Yes, but how do I get the instance of Chunk? That's what's confusing me... Quote Today (22/10/20) I reached 100 posts! I'm probably more excited than I should be for something so realistically minor...
BlockyPenguin Posted March 21, 2021 Author Posted March 21, 2021 1 hour ago, diesieben07 said: Well, which chunk do you want? Every loaded chunk, I guess... Quote Today (22/10/20) I reached 100 posts! I'm probably more excited than I should be for something so realistically minor...
BlockyPenguin Posted March 21, 2021 Author Posted March 21, 2021 Just now, diesieben07 said: Why? What for? Okay, I'm thinking we're not quite on the same page here, so I'll start again: I've made a capability for chunks, which contains a float value. I would like the float to increase by 0.1 every x amount of time. My thought is that if I get all the loaded chunks, I can iterate over them and increase this value. As to how I would implement a timer without a tick() method, I am at a loss, but one problem at a time. Quote Today (22/10/20) I reached 100 posts! I'm probably more excited than I should be for something so realistically minor...
BlockyPenguin Posted March 21, 2021 Author Posted March 21, 2021 18 minutes ago, diesieben07 said: I suggested using getInhabitedTime instead of this float value. Minecraft already increments getInhabitedTime for you. But wouldn't it be incremented at a different rate? I think I forgot to mention as well, that I have the float set to a random value between 0.0 and 0.2 in the capability's default implementation's constructor. Quote Today (22/10/20) I reached 100 posts! I'm probably more excited than I should be for something so realistically minor...
BlockyPenguin Posted March 21, 2021 Author Posted March 21, 2021 6 minutes ago, diesieben07 said: Yes, but that is easily adjusted for. Say in your config you say "increment it by 3 every tick", then just take the inhabited time and multiply it by 3 - done. So every chunk starts out with a random value? If you want to avoid ticking still, you can base this random value on the chunk's coordinates (Use something like MathHelper.getSeed, which is what Minecraft uses for the random block rendering offset). Then to get the "final value" just take this "random start value" and add the inhabited time multiplied whatever the config says. Okay... so how would i get the chunk then? Would it help if i uploaded my code to github? Quote Today (22/10/20) I reached 100 posts! I'm probably more excited than I should be for something so realistically minor...
BlockyPenguin Posted March 21, 2021 Author Posted March 21, 2021 6 minutes ago, diesieben07 said: Dude. You don't need to get the chunk. Minecraft updates the data for you. You don't need a capability. You don't need to store anything. Whenever you need the data, you can just calculate it. Okay, so, let's say that I want to get this data when an item is right clicked, it would be something like this, right? @Override public ActionResult<ItemStack> onItemRightClick(World world, PlayerEntity player, Hand hand) { ItemStack stack = player.getHeldItem(hand); Chunk c = (Chunk)world.getChunk(player.getPosition()); c.getInhabitedTime(); return ActionResult.resultSuccess(stack); } But MathHelper.getSeed doesn't seem to exist... Quote Today (22/10/20) I reached 100 posts! I'm probably more excited than I should be for something so realistically minor...
BlockyPenguin Posted March 22, 2021 Author Posted March 22, 2021 4 minutes ago, diesieben07 said: Why this cast? Because World#getChunk() returns an IChunk. 5 minutes ago, diesieben07 said: Its getCoordinateRandom if you're not on mojang mappings yet. Ah, thanks. TBH, I'm a little concerned about changing over to Mojang mappings, I know there are a few legality issues still. What would be the right place to ask about this? Quote Today (22/10/20) I reached 100 posts! I'm probably more excited than I should be for something so realistically minor...
BlockyPenguin Posted March 22, 2021 Author Posted March 22, 2021 2 minutes ago, diesieben07 said: The Forge discord. Okay, thanks 2 minutes ago, diesieben07 said: No... it doesn't? At least not all of its versions. And those that return an IChunk do not always return a Chunk. Blindly casting is almost always a bad idea. Here is the source code of World#getChunk: default IChunk getChunk(BlockPos pos) { return this.getChunk(pos.getX() >> 4, pos.getZ() >> 4); } So what do you suggest I do then? Quote Today (22/10/20) I reached 100 posts! I'm probably more excited than I should be for something so realistically minor...
BlockyPenguin Posted March 22, 2021 Author Posted March 22, 2021 2 hours ago, diesieben07 said: That's IWorldReader#getChunk, not World#getChunk. That's strange, because I'm definitely calling it on a World object, unless World implements IWorldReader. 2 hours ago, diesieben07 said: Use instanceof. So this is what I've got: @Override public ActionResult<ItemStack> onItemRightClick(World world, PlayerEntity player, Hand hand) { IChunk ichunk = world.getChunk(player.getPosition()); if(ichunk instanceof Chunk) { Chunk chunk = (Chunk)ichunk; long seed = MathHelper.getCoordinateRandom(player.getPosition().getX(), player.getPosition().getY(), player.getPosition().getZ()); seed += chunk.getInhabitedTime() * Config.RIFT_MULTIPLICATION_FACTOR.get(); player.sendStatusMessage(new StringTextComponent(seed + ""), false); } return ActionResult.resultSuccess(player.getHeldItem(hand)); } But how would I turn that into value between 0 and 1? or at least 0 and 100, or some other easily measurable number. Then I've also got to worry about the boolean dictating whether or not a chunk is a rift or not. Quote Today (22/10/20) I reached 100 posts! I'm probably more excited than I should be for something so realistically minor...
BlockyPenguin Posted March 22, 2021 Author Posted March 22, 2021 15 minutes ago, diesieben07 said: You need to use the chunk position here, not the player position. Otherwise it will be different depending on where you are in the chunk. Also, you probably don't want to actually use getCoordinateRandom, but some other method to get some pseudo-random data. You could for example use a Random instance and use setSeed() and then call nextFloat. Okay, so what would I set the seed to? I already have a public static final Random instance in my main class, would that do the job? Quote Today (22/10/20) I reached 100 posts! I'm probably more excited than I should be for something so realistically minor...
Draco18s Posted March 22, 2021 Posted March 22, 2021 3 hours ago, BlockyPenguin said: unless World implements IWorldReader *Cough* It does. Quote Apparently I'm a complete and utter jerk and come to this forum just like to make fun of people, be confrontational, and make your personal life miserable. If you think this is the case, JUST REPORT ME. Otherwise you're just going to get reported when you reply to my posts and point it out, because odds are, I was trying to be nice. Exception: If you do not understand Java, I WILL NOT HELP YOU and your thread will get locked. DO NOT PM ME WITH PROBLEMS. No help will be given.
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.