Jump to content

desht

Members
  • Posts

    244
  • Joined

  • Last visited

  • Days Won

    13

Everything posted by desht

  1. In your build.gradle: minecraft { ... mappings = snapshot_20170103 ... } Or whatever's current for 1.11.2 - see http://export.mcpbot.bspk.rs/. There isn't a "stable" mapping for 1.11.2 yet.
  2. If this is 1.11, I can see a problem immediately - null is never a valid value for an ItemStack. Use ItemStack.EMPTY. Also, what's with the func_190916_E() and func_190901_a() calls? There are deobfuscated names for both of those: ItemStack#getCount() and Slot#onTake().
  3. This thread may also provide some information (and links to my code): I do something similar, where my tile entity can hold a camouflage upgrade item, and the block will render using that upgrade item's saved block state.
  4. means you've tried to operate upon a 0-sized inventory, which obviously won't work too well. Remember that NBTTagCompound#getInteger() returns 0 if the tag isn't present; you need to validate that and supply sensible defaults.
  5. Your readFromNBT() method calls inventory.deserializeNBT(), but your inventory field is still null at that point. You need to initialise that to a valid ItemStackHandler object, either in your constructor, or where the field is declared. Remember that your tile entity objects will also be created when any chunk containing it is loaded, not just when you explicitly create them from your block class.
  6. Actually, Enum#valueOf() will throw an IllegalArgumentException if the string isn't known. Checking for null won't help; you need to wrap the call in a try/catch block.
  7. Yep, very true. The one thing Bukkit still has over Forge, then, is the version-transparent API (e.g. the 1.10 -> 1.11 ItemStack changes would be a non-issue for plugin devs). Out of interest, what are your thoughts on Sponge (on top of Forge) as a server-side plugin API?
  8. Let me offer my perspective as a former Bukkit plugin dev, and now (relative newbie) Forge dev... The big difference back when Bukkit/CraftBukkit appeared was that modding your client back in 2011 was a considerably tougher affair than it is today. Coupled with the fact that there weren't many mods around then (the original Industrial Craft was announced in Feb 2011), the client modding scene was a little... specialist. On the other hand, CraftBukkit was a pretty much drop-in replacement for the vanilla server, and it meant your players could just connect with their vanilla client - no hard-to-install client mods needed, no battling item ID conflicts or manually inserting classes into the client JAR. Perfect for running big multiplayer servers; you got protection plugins to combat griefing, mini-games, RPG plugins - there's quite a bit you can do without adding custom items. And as Animefan8888 alluded to, it did allow sort-of-custom items with a little server-side trickery - as it happens, I created a fairly extensive custom item framework myself: https://dev.bukkit.org/projects/sensible-toolbox Things have changed though, for two big reasons: 1) Forge is here to stay, and it's a very capable system; as far as I can tell there's nothing Bukkit can do these days that Forge can't, and 2) it's really really easy these days to download a modpack and just start playing. Of course, actually modding for Forge is still a lot harder than for Bukkit - you need to understand the client/server separation, you need to understand models & textures (and possibly some OpenGL), you need to peer inside the vanilla code on a fairly regular basis, and you need to accept that there will be pain when a major new MC release comes out (something Bukkit makes 99% transparent). But that's for developers to worry about; players mostly need not care. tl;dr When Bukkit came out, it was the obvious choice for a multiplayer server. Nowadays, not so much - Bukkit (and its derivatives) are mostly around because of inertia these days.
  9. From looking at the call hierarchy of the break & harvest events (it's PlayerEvent.HarvestCheck BTW), I'm not so sure about that... When you receive a BlockEvent.BreakEvent, a HarvestCheck has already been fired - the BreakEvent constructor calls ForgeHooks.canHarvestBlock() , which fires the HarvestEvent. But more importantly, using event.setCanHarvest(false) in a HarvestCheck handler doesn't stop the block being broken, it just stops anything dropping from it. Specifically, Block#removedByPlayer() still gets called, which by default sets the block to AIR, but Block#harvestBlock() does not get called. On the other hand, canceling a BlockEvent.BreakEvent does stop the block from being broken. I'm looking at PlayerInteractionManager#tryHarvestBlock(BlockPos pos) for this information, for the record.
  10. Yep. Block is a singleton class, remember - it represents a template of all blocks of that type.
  11. If you want to prevent a specific chest from being broken (whose position you know), you could just subscribe to BlockEvent.BreakEvent and cancel it as necessary.
  12. You're not returning the item stack with the NBT which you set up (and that part looks ok). Instead you're returning an arraylist with a brand new ItemStack which has no NBT data at all: return Lists.newArrayList(new ItemStack(this, 1, meta)); Also, why are you making getItemDropped() return null? Looks unnecessary, especially as you've overridden getDrops(), which is what primarily calls getItemDropped() in the default Block#getDrops() implementation. (and any particular reason you've made getDrops() final?)
  13. Because you'll end up iterating multiple times up a column of blocks if you have 2 blocks with the same (X,Z) in the list of affected blocks. Waste of CPU cycles. No you wouldn't. By storing Y values you don't iterate over the columns. Looking at the OP's code, the intention appears to be to iterate upward from each affected block to max world height, turning every block into a falling block; presumably the intention is for underground explosions to cause cave-ins. So upwards iteration is in fact required. What should be avoided is doing that iteration more than once for each column of blocks.
  14. Is your current code the same code that you last posted? Because as I and other have pointed out, it's wrong. (And spawning falling blocks via Bukkit ends up calling the same internal server code to create entities; the only difference is that Bukkit adds another layer of abstraction. So it's highly unlikely that Forge is failing to do something that Bukkit can do).
  15. Because you'll end up iterating multiple times up a column of blocks if you have 2 blocks with the same (X,Z) in the list of affected blocks. Waste of CPU cycles.
  16. Hence using a Set<Pair> - just store one instance of each (X,Z) pair. But you're right - you'd need to store a Y-value as well; so perhaps a Map<Pair<Integer,Integer>, Integer> would be better, where the key is (X,Z) and the value is Y. As for which Y-value, that's up to the mod developer; the smallest Y would be a reasonable choice.
  17. That wont work because theny position is not identifable. Explain please? Seems totally workable to me.
  18. Yep. Hence why I suggested a Set<Pair<Integer,Integer>> as the appropriate data structure here; a unique set of (x,z) positions from which columns can be traced vertically upwards. OP needs to be paying attention
  19. TNT radius is 6.9, according to the official Wiki. Now consider a couple of hundred TNT under some amplified biome, or mesa, or extreme hills... that could easily be millions of blocks. (And it will be your problem if & when your publicly released mod gets fingered as a server killer ) Mitigation might be not to create falling blocks immediately, but add them to a queue of limited (tunable) size. Then pull a certain (tunable) number from the queue every tick, validate that the block hasn't already changed in the intervening ticks since they were added, and then create the falling block. And if the queue is full, just don't add them. A queue of Pair<BlockPos,IBlockState> should work here (remembering that IBlockState object can be validly and cheaply compared with ==).
  20. Cool. You'll also want to consider what happens if someone sets off multiple explosions down at bedrock level (the amount of scanning for blocks and more so the number of entities being rapidly created will make your server cry).
  21. Firstly, "isn't working" isn't very helpful. I'll assume you mean that it just doesn't spawn a falling block rather than it fails with an exception etc. The explosion event is fired before any blocks are actually destroyed, so if you want to spawn a falling block, it's up to you to set the block being replaced with air. Also, if there's a block underneath, you might want to add a small amount to the falling block's Y co-ord so it isn't considered on the ground (or it will immediately turn back into a real block). You may also want to give newly spawned falling blocks an initial velocity (based on their position and proximity to the explosion centre) so they fly outwards. Also, a map of Block->BlockPos makes no sense at all. Block is a singleton class; you'll just end up with one element for each type of block affected. And I don't follow what your getBlocksToFall() method is doing - why not just iterate over event.getAffectedBlockPositions() directly? Update: OK, I understand what you need better now. I'd suggest just converting the list of affected locations to a Set<Pair<Integer,Integer>>, where the two ints are the X & Z positions of the affected blocks. Then for each element, you can iterate upward to world height and convert blocks to falling blocks. If you work upwards, you shouldn't need to worry about the block underneath being solid. (Also, be sure to test what happens with tile entity blocks, with or without held items).
  22. How about having two ItemHandler objects: a private one (not exposed via capabilities), and a public one (exposed so that hoppers etc. can extract). The private item handler just allows items to be inserted normally, and that's what your machine would use to put items into it; a simple ItemStackHandler might suffice. The public handler would be a custom IItemHandler implementation which delegates everything to the private handler, with the exception of inserting items, which you make a no-op. And in your GUI, connect any Slots as needed to the public item handler to prevent manual insertion of items.
  23. MutableBlockPos might be of benefit where you find yourself creating many BlockPos objects - avoiding unnecessary object creation overhead is always good. For example, if you're using a BlockPos to process many blocks, you might do: BlockPos pos = startPos; for (int i = 0; i < MAX_BLOCKS; i++) { processBlockAt(world, pos); pos = pos.offset(directionToScan); } But that creates MAX_BLOCKS short-lived BlockPos objects (BlockPos#offset() creates a new BlockPos object each time). Using MutableBlockPos: MutableBlockPos pos = new MutableBlockPos(startPos); for (int i = 0; i < MAX_BLOCKS; i++) { processBlockAt(world, pos); pos.move(directionToScan); } ...and that's MAX_BLOCKS-1 short-lived objects you didn't need to create. Of course, the official Java docs state: -- https://docs.oracle.com/javase/tutorial/essential/concurrency/immutable.html
  24. I just got bitten by this while getting rid of ITileEntityProvider too, and I suspect I know what happened to Raycoms. I implemented hasTileEntity() and getTileEntity(), using @Override of course, and restarted my dev world, only to find my item routers no longer had tile entities at all. A bit of debugging showed that hasTileEntity() wasn't even being called. A little more investigation with my IDE shows that there are two hasTileEntity() methods: hasTileEntity() , and hasTileEntity(IBlockState state) . Of course, I'd overridden the no-args one, which is wrong. You need to override hasTileEntity(IBlockState state) . Getting it wrong is a subtle error, since your IDE won't flag this as an error at all. The code is syntactically fine, just incorrect. Once I fixed that, my item routers had tile entities again, but since the world had been restarted using the wrong code, the game - as you rightly noted - treated the blocks as having no tile entity, and removed any saved data for those from the world. After fixing the code, loading up another dev world that I previously made worked fine - all TE data was intact. Moral of this story: override hasTileEntity(IBlockState state) , not hasTileEntity() . That no-args version appears to be only called by TileEntityHopper, and just calls hasTileEntity(getDefaultState()) . Yucky.
  25. Gravel doesn't tick randomly, so that shouldn't be an issue. As @trollworkout mentioned, unsupported gravel appears regularly in the Nether, and stays where it is until it gets a block physics update, then cascading physics updates bring the whole lot down. But I agree - use a custom ChunkProvider here; it'll solve both the falling block problem and the likely performance problems. Shouldn't be necessary (as you yourself stated in your first post). As long as the gravel is pre-generated, it won't fall until it gets a physics update by a neighbouring block being changed. At that point, the falling gravel itself causes a physics update, and any neighbouring gravel will fall, and so on.
×
×
  • Create New...

Important Information

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