
Everything posted by bajtix
-
[1.16.4] How to prevent hoppers/other similar item extractors from accessing my container
I forgot to do it! Thanks for the help everyone!
-
[1.16.4] How to prevent hoppers/other similar item extractors from accessing my container
If I return the empty LazyOptional, hoppers still can steal items out of it. The same happens if I don't override it.
-
[1.16.4] How to prevent hoppers/other similar item extractors from accessing my container
Could you please explain how do I do that? I have this: @Override public <T> LazyOptional<T> getCapability(@Nonnull Capability<T> cap, @Nonnull Direction side) { if(cap == CapabilityItemHandler.ITEM_HANDLER_CAPABILITY) { return itemHandler.cast(); } return super.getCapability(cap, side); } private IItemHandlerModifiable createHandler() { return new InvWrapper(this); } @Override public void remove() { super.remove(); if(itemHandler != null) { itemHandler.invalidate(); } } What should I do now? I tried to make the getCapability to return null, but it crashed. (I'm sorry, I'm still a begginer)
-
[1.16.4] How to prevent hoppers/other similar item extractors from accessing my container
I know that it has something to do with getCapability function in the container class, but I am not sure what it should return for the hoppers to be unable to access it. I've seen a similar topic for 1.12, but how do I make it work with 1.16?
-
[1.16.4] Send new TileEntity NBT to the server
If I understand correctly, the last parameter of the registerMessage() function is the method that handles the data, right? I'm not sure if I understood the documentation.
-
[1.16.4] Send new TileEntity NBT to the server
Okay, I think It might work now, but I still have no idea when to register them. Should it be done from the main mod class or is there a registry event for that? also, how do I make it actually handle it? I may be not experienced enough to understand it, but I don't think that just putting a "handle()" method will work.
-
[1.16.4] Send new TileEntity NBT to the server
INSTANCE.registerMessage(0, CSendNBTPacket.class ,CSendNBTPacket::encode, CSendNBTPacket::decode, CSendNBTPacket::ctx); public class CSendNBTPacket { public PacketBuffer encode(CSendNBTPacket packet) { return null; } public CSendNBTPacket decode(PacketBuffer buffer) { } public Supplier<NetworkEvent.Context> ctx() { return null; } } What am I doing wrong here? (ignoring the "return null;" part)
-
[1.16.4] Send new TileEntity NBT to the server
So.. how do I exactly handle it? And register it? I don't understand the docs, especially the "Registering Packets". I understand that the packet class should have functions for encoding and decoding the packets, but I don't really know how they should work.
-
[1.16.4] Send new TileEntity NBT to the server
I saw how it is made for the CommandBlockScreen, but I am not sure how to handle these packets. Also, the button just sends a TextField to the server, and it is checked again there - I just need to send two integers. I tried implementing it with SimpleChannels, but I saw that Minecraft uses a custom packet.
-
[1.16.4] Send new TileEntity NBT to the server
I am trying to send a NBT update to the client when a GUI button is clicked. I tried just setting the value, but it looks like it is only set for the client TileEntity, and not the server one. How can I send the value to the server? I've seen that Minecraft uses a custom packet for that, but I have no idea how to use them, and I don't understand the documetion.
-
[1.16.4] Register recipe type - cannot join server
Thank you! I somehow overlooked that in my code and spent a few hours searching for the solution.
-
[1.16.4] Register recipe type - cannot join server
I'm posting this in a different thread, because it is a little different then just creating a recipe. So I managed to make my custom recipe work, but it only works for singleplayer. When I try to join a server, the client throws Internal Exception: io.netty.handler.codec.EncoderException: java.lang.NullPointerException I am registering the recipe here: @SubscribeEvent public static void onRecipeRegistry(final RegistryEvent.Register<IRecipeSerializer<?>> recipeRegistryEvent) { LOGGER.info("Recipe registry!"); SpecialRecipeSerializer<MusicCloningRecipe> musicCloningRecipe = (SpecialRecipeSerializer<MusicCloningRecipe>) new SpecialRecipeSerializer<>(MusicCloningRecipe::new).setRegistryName("crafting_special_musiccloning"); recipeRegistryEvent.getRegistry().register( musicCloningRecipe ); } And it is kept here: @ObjectHolder("musicblock") class Recipes { public static final SpecialRecipeSerializer<MusicCloningRecipe> CRAFTING_SPECIAL_MUSICCLONING = null; } The recipe code: package xyz.bajtix.musicblock; import net.minecraft.inventory.CraftingInventory; import net.minecraft.item.ItemStack; import net.minecraft.item.Items; import net.minecraft.item.WrittenBookItem; import net.minecraft.item.crafting.IRecipeSerializer; import net.minecraft.item.crafting.SpecialRecipe; import net.minecraft.nbt.CompoundNBT; import net.minecraft.util.NonNullList; import net.minecraft.util.ResourceLocation; import net.minecraft.world.World; public class MusicCloningRecipe extends SpecialRecipe { public MusicCloningRecipe(ResourceLocation idIn) { super(idIn); } public boolean matches(CraftingInventory inv, World worldIn) { int i = 0; boolean oneHasData = false; for(int j = 0; j < inv.getSizeInventory(); ++j) { if(inv.getStackInSlot(j).getItem() == ItemList.musicBlock) { i++; if(inv.getStackInSlot(j).hasTag() && inv.getStackInSlot(j).getTag().contains("music")) oneHasData = !oneHasData; } } return i == 2 && oneHasData; } /** * Returns an Item that is the result of this recipe * * @param inv */ @Override public ItemStack getCraftingResult(CraftingInventory inv) { int i = 0; CompoundNBT data = null; for(int j = 0; j < inv.getSizeInventory(); ++j) { if(inv.getStackInSlot(j).getItem() == ItemList.musicBlock) { i++; if(inv.getStackInSlot(j).hasTag() && inv.getStackInSlot(j).getTag().contains("music")) data = inv.getStackInSlot(j).getTag(); } } if(data == null) return null; ItemStack stack = new ItemStack(ItemList.musicBlock,1,data); stack.setTag(data); return stack; } @Override public NonNullList<ItemStack> getRemainingItems(CraftingInventory inv) { NonNullList<ItemStack> itemlist = NonNullList.withSize(inv.getSizeInventory(), ItemStack.EMPTY); for(int i = 0; i < itemlist.size(); ++i) { ItemStack itemstack = inv.getStackInSlot(i); if (itemstack.hasContainerItem()) { itemlist.set(i, itemstack.getContainerItem()); } else if (itemstack.getItem() == ItemList.musicBlock) { ItemStack itemstack1 = itemstack.copy(); itemstack1.setCount(1); itemlist.set(i, itemstack1); break; } } return itemlist; } /** * Used to determine if this recipe can fit in a grid of the given width/height * * @param width * @param height */ @Override public boolean canFit(int width, int height) { return width >= 2 && height >= 2; } @Override public IRecipeSerializer<?> getSerializer() { return null; } } And it is registered in an @OjectHolder class Could someone please tell me what am I doing wrong? I couldn't really find a good documentation for it.
-
[1.16.4] How to copy NBT between recipe ingredients and result?
So I managed to make it work, but it only works for singleplayer. When I try to join a server, the client throws Internal Exception: io.netty.handler.codec.EncoderException: java.lang.NullPointerException I am registering the recipe here: @SubscribeEvent public static void onRecipeRegistry(final RegistryEvent.Register<IRecipeSerializer<?>> recipeRegistryEvent) { LOGGER.info("Recipe registry!"); SpecialRecipeSerializer<MusicCloningRecipe> musicCloningRecipe = (SpecialRecipeSerializer<MusicCloningRecipe>) new SpecialRecipeSerializer<>(MusicCloningRecipe::new).setRegistryName("crafting_special_musiccloning"); recipeRegistryEvent.getRegistry().register( musicCloningRecipe ); } And it is kept here: @ObjectHolder("musicblock") class Recipes { public static final SpecialRecipeSerializer<MusicCloningRecipe> CRAFTING_SPECIAL_MUSICCLONING = null; } Could someone please tell me what am I doing wrong? I couldn't really find a good documentation for it.
-
[SOLVED] [1.16.4] Send chat message from remote world
I managed to resolve the issue now, with the debugger. The problem was that altough the method PlayerEntity#sendMessage with null as the sender ID works just fine on singleplayer server, but when run on a remote server throws an exception. The solution that worked was just giving the player's UUID as the senderID. Thanks for the help!
-
[SOLVED] [1.16.4] Send chat message from remote world
After rebooting my PC and reinstalling gradle it finally worked, so maybe it was some problem with an application already using the port? I have no idea, but now the server runs. I was also able to use the debugger; The function runs and the player is not null, everything looks like it should work but the chat message still isn't sent.
-
[SOLVED] [1.16.4] Send chat message from remote world
The client runs, the server doesn't.
-
[SOLVED] [1.16.4] Send chat message from remote world
But basically the same thing happens when using the run configuration. The only difference is that it prints Disconnected from the target VM, address: '127.0.0.1:53952', transport: 'socket' at the end. I am tried reinstalling gradle, but it is still the same.
-
[SOLVED] [1.16.4] Send chat message from remote world
This is the log afer running the runServer configuration with --debug and --stacktrace I tried uploading it here, but it threw an error and pastebin didn't work either, so I put it here https://filebin.net/m6dldvc1g31tfukx/gradleLog.txt?t=ufc9r7pm
-
[SOLVED] [1.16.4] Send chat message from remote world
If I am understanding it correctly, the IDE still needs to run gradle to compile it and run the server. I used genIntellijRuns and I am using the runServer, but it always throws this error. The client works just fine.
-
[SOLVED] [1.16.4] Send chat message from remote world
I'm trying to run the debugger on the server, but for some reason the gradlew runServer fails. It throws the error: 22:55:00.259 [ERROR] [org.gradle.internal.buildevents.BuildExceptionReporter] * Exception is: 22:55:00.259 [ERROR] [org.gradle.internal.buildevents.BuildExceptionReporter] org.gradle.launcher.daemon.client.DaemonConnectionException: Could not dispatch a message to the daemon. 22:55:00.259 [ERROR] [org.gradle.internal.buildevents.BuildExceptionReporter] at org.gradle.launcher.daemon.client.DaemonClientConnection.dispatch(DaemonClientConnection.java:68) 22:55:00.260 [ERROR] [org.gradle.internal.buildevents.BuildExceptionReporter] at org.gradle.launcher.daemon.client.DaemonClientConnection.dispatch(DaemonClientConnection.java:35) 22:55:00.260 [ERROR] [org.gradle.internal.buildevents.BuildExceptionReporter] at org.gradle.launcher.daemon.client.DaemonClientInputForwarder$ForwardTextStreamToConnection.endOfStream(DaemonClientInputForwarder.java:78) 22:55:00.260 [ERROR] [org.gradle.internal.buildevents.BuildExceptionReporter] at org.gradle.launcher.daemon.client.InputForwarder$1.run(InputForwarder.java:95) 22:55:00.260 [ERROR] [org.gradle.internal.buildevents.BuildExceptionReporter] at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:63) 22:55:00.260 [ERROR] [org.gradle.internal.buildevents.BuildExceptionReporter] at org.gradle.internal.concurrent.ManagedExecutorImpl$1.run(ManagedExecutorImpl.java:46) 22:55:00.260 [ERROR] [org.gradle.internal.buildevents.BuildExceptionReporter] at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) 22:55:00.260 [ERROR] [org.gradle.internal.buildevents.BuildExceptionReporter] at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) 22:55:00.260 [ERROR] [org.gradle.internal.buildevents.BuildExceptionReporter] at org.gradle.internal.concurrent.ThreadFactoryImpl$ManagedThreadRunnable.run(ThreadFactoryImpl.java:55) 22:55:00.260 [ERROR] [org.gradle.internal.buildevents.BuildExceptionReporter] at java.lang.Thread.run(Thread.java:748) 22:55:00.260 [ERROR] [org.gradle.internal.buildevents.BuildExceptionReporter] Caused by: org.gradle.internal.remote.internal.MessageIOException: Could not write '/127.0.0.1:49937'. 22:55:00.260 [ERROR] [org.gradle.internal.buildevents.BuildExceptionReporter] at org.gradle.internal.remote.internal.inet.SocketConnection.flush(SocketConnection.java:135) 22:55:00.260 [ERROR] [org.gradle.internal.buildevents.BuildExceptionReporter] at org.gradle.launcher.daemon.client.DaemonClientConnection.dispatch(DaemonClientConnection.java:59) 22:55:00.260 [ERROR] [org.gradle.internal.buildevents.BuildExceptionReporter] ... 9 more 22:55:00.260 [ERROR] [org.gradle.internal.buildevents.BuildExceptionReporter] Caused by: java.io.IOException: Istniej╣ce po│╣czenie zosta│o gwa│townie zamkniŕte przez zdalnego hosta //this translates to: an existing connection was forcibly closed by the remote host 22:55:00.260 [ERROR] [org.gradle.internal.buildevents.BuildExceptionReporter] at sun.nio.ch.SocketDispatcher.write0(Native Method) 22:55:00.260 [ERROR] [org.gradle.internal.buildevents.BuildExceptionReporter] at sun.nio.ch.SocketDispatcher.write(SocketDispatcher.java:51) 22:55:00.260 [ERROR] [org.gradle.internal.buildevents.BuildExceptionReporter] at sun.nio.ch.IOUtil.writeFromNativeBuffer(IOUtil.java:93) 22:55:00.260 [ERROR] [org.gradle.internal.buildevents.BuildExceptionReporter] at sun.nio.ch.IOUtil.write(IOUtil.java:51) 22:55:00.260 [ERROR] [org.gradle.internal.buildevents.BuildExceptionReporter] at sun.nio.ch.SocketChannelImpl.write(SocketChannelImpl.java:471) 22:55:00.260 [ERROR] [org.gradle.internal.buildevents.BuildExceptionReporter] at org.gradle.internal.remote.internal.inet.SocketConnection$SocketOutputStream.writeWithNonBlockingRetry(SocketConnection.java:273) 22:55:00.260 [ERROR] [org.gradle.internal.buildevents.BuildExceptionReporter] at org.gradle.internal.remote.internal.inet.SocketConnection$SocketOutputStream.writeBufferToChannel(SocketConnection.java:261) 22:55:00.260 [ERROR] [org.gradle.internal.buildevents.BuildExceptionReporter] at org.gradle.internal.remote.internal.inet.SocketConnection$SocketOutputStream.flush(SocketConnection.java:255) 22:55:00.260 [ERROR] [org.gradle.internal.buildevents.BuildExceptionReporter] at org.gradle.internal.remote.internal.inet.SocketConnection.flush(SocketConnection.java:133) 22:55:00.260 [ERROR] [org.gradle.internal.buildevents.BuildExceptionReporter] ... 10 more 22:55:00.260 [ERROR] [org.gradle.internal.buildevents.BuildExceptionReporter] 22:55:00.260 [ERROR] [org.gradle.internal.buildevents.BuildExceptionReporter] 22:55:00.260 [ERROR] [org.gradle.internal.buildevents.BuildExceptionReporter] * Get more help at https://help.gradle.org
-
[SOLVED] [1.16.4] Send chat message from remote world
Im pretty sure it is, as all the other things in that function work just fine.
-
[SOLVED] [1.16.4] Send chat message from remote world
Here it is. I'm pretty sure it is terrible, I am still working on it. Also, I have no idea how the client-server sync code works and I still can't understand it. package xyz.bajtix.musicblock; import net.minecraft.block.BlockState; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.nbt.CompoundNBT; import net.minecraft.nbt.INBT; import net.minecraft.nbt.ListNBT; import net.minecraft.network.NetworkManager; import net.minecraft.network.play.server.SUpdateTileEntityPacket; import net.minecraft.particles.IParticleData; import net.minecraft.particles.ParticleTypes; import net.minecraft.state.properties.NoteBlockInstrument; import net.minecraft.tileentity.ITickableTileEntity; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.SoundCategory; import net.minecraft.util.math.BlockPos; import net.minecraft.util.text.StringTextComponent; import net.minecraft.util.text.TranslationTextComponent; import net.minecraftforge.common.util.INBTSerializable; import javax.annotation.Nullable; import java.util.ArrayList; import java.util.HashMap; import java.util.Map; public class MusicBlockTileEntity extends TileEntity implements ITickableTileEntity { public MusicBlockTileEntity() { super(TEList.MUSIC_BLOCK); if(recorded == null) recorded = new HashMap<Integer, ArrayList<Note>>(); } public class Note implements INBTSerializable { public float frequency; public NoteBlockInstrument instrument; public Note(float frequency, NoteBlockInstrument instrument) { this.frequency = frequency; this.instrument = instrument; } @Override public CompoundNBT serializeNBT() { CompoundNBT nbt = new CompoundNBT(); nbt.putFloat("f",frequency); nbt.putString("i",instrument.name()); return nbt; } @Override public void deserializeNBT(INBT nbt) { CompoundNBT bnbt = (CompoundNBT)nbt; frequency = bnbt.getFloat("f"); String iname = bnbt.getString("i"); instrument = NoteBlockInstrument.valueOf(iname); } } private Map<Integer, ArrayList<Note>> recorded; private int tick = 0; private PlayerEntity lastPlayerRecord; private int state = 2; // Play = 0; Record = 1; Idle = 2 /** * Song volume (pretty sure it can be max. 3) */ public float volume = 3; /** * Song author */ public String author = "anonymous"; /** * Song name (defaults to the key specified in lang file as <code>msg.unnamed</code>) */ public String songName = new TranslationTextComponent("msg.unnamed").getString(); /** * Adds a note to the recording, with current tick * @param frequency The pitch of the sound * @param instrument Note Block Instrument to play this note */ public void addNote(float frequency, NoteBlockInstrument instrument) { if(state == 1){ if(!recorded.containsKey(tick)){ ArrayList<Note> notes = new ArrayList<>(); notes.add(new Note(frequency,instrument)); recorded.put(tick, notes); return; } else{ recorded.get(tick).add(new Note(frequency,instrument)); } } } /** * Force adds a note, even if it is not recording, to the given tick * @param frequency The pitch of the sound * @param instrument Note Block Instrument to play this note * @param tick The tick of this note */ public void addNote(float frequency, NoteBlockInstrument instrument, int tick) { if(!recorded.containsKey(tick)){ ArrayList<Note> notes = new ArrayList<>(); notes.add(new Note(frequency,instrument)); recorded.put(tick, notes); return; } else{ recorded.get(tick).add(new Note(frequency,instrument)); } } /** * Clears the recorded song data */ public void clearRecording() { recorded.clear(); } /** * Get the full recording * @return the recording, <code>Map<[Integer]Tick, [Note]Note></code> */ public Map<Integer, ArrayList<Note>> getRecorded() { return recorded; } /** * Set the recorded Map. Please do not use this method, unless you know what you are doing * @param recorded The <code>Map< tick[Integer],note[Note] ></code> */ public void setRecorded(Map<Integer, ArrayList<Note>> recorded) { this.recorded = recorded; } /** * The amount of entries in the recorded music * @return the amount of entries in the dictionary */ public int getNoteAmount() { return recorded.size(); } /** * Get notes at tick * @param tick Tick to get the notes at * @return The note array list */ public ArrayList<Note> getNotes(int tick) { if(recorded.containsKey(tick)) return recorded.get(tick); else return null; } /** * Overwrite notes at a given tick * @param notes The note array to be put * @param tick The tick in which to overwrite */ public void setNotes(ArrayList<Note> notes, int tick) { if(tick > 6000 ) return; recorded.put(tick,notes); } /** * Get the current state * @return the state variable */ public int getState() { return state; } /** * Get the current tick * @return the tick variable */ public int getTick() { return tick; } /** * Sets the current tick * @param s the tick value */ public void setTick(int s) { tick = s; } //TODO: Cleanup this function @Override public void tick() { if(state == 2) return; if(state == 1) { BlockPos chunkPos = world.getChunk(pos).getPos().asBlockPos(); for (int i = 0; i < 48; i++) { world.addParticle(ParticleTypes.FLAME, chunkPos.getX() + i - 16, pos.getY() + .5d, chunkPos.getZ() - 16, 0, 0.5d, 0); } for (int i = 0; i < 48; i++) { world.addParticle(ParticleTypes.FLAME, chunkPos.getX() + i - 16, pos.getY() + .5d, chunkPos.getZ() + 32, 0, 0.5d, 0); } for (int i = 0; i < 48; i++) { world.addParticle(ParticleTypes.FLAME, chunkPos.getX() - 16, pos.getY() + .5d, chunkPos.getZ() + i - 16, 0, 0.5d, 0); } for (int i = 0; i < 48; i++) { world.addParticle(ParticleTypes.FLAME, chunkPos.getX() + 32, pos.getY() + .5d, chunkPos.getZ() + i - 16, 0, 0.5d, 0); } } if(state == 0) { if(recorded.containsKey(tick)) { for(Note n : recorded.get(tick)) { world.playSound((PlayerEntity) null, pos, n.instrument.getSound(), SoundCategory.RECORDS, volume, n.frequency); } } /*if(tick % 60 == 0) world.notifyBlockUpdate(pos,world.getBlockState(pos),world.getBlockState(pos),2);*/ } tick++; if(tick > 6000) { if(state == 0) { state = 2; tick = 0; } else if(state == 1) { record(lastPlayerRecord,null); } } } /** * Toggles playing the recorded audio * @param announce Should it write "Now playing.." message to nearby players? */ public void play(boolean announce) { if(state == 0 || state == 3) { state = 2; tick = 0; } else { state = 0; tick = 0; if(announce) { for (PlayerEntity p : world.getPlayers()) { if (p.getDistanceSq(pos.getX(), pos.getY(), pos.getZ()) < 80) p.sendMessage(new StringTextComponent(new TranslationTextComponent("msg.nowplaying").getString() + " '" + songName + "' " + new TranslationTextComponent("msg.by").getString() + " " + author), null); } } } } /** * * @param playerEntity The player who toggled recording * @param author If player entity is null, this will be the song's author * @return The final state of the musicbox */ public int record(@Nullable PlayerEntity playerEntity,@Nullable String author) { if(playerEntity != null) lastPlayerRecord = playerEntity; if(recorded.size() > 0 && state != 3 && state != 1) { state = 3; if(playerEntity != null) lastPlayerRecord = playerEntity; playerEntity.sendMessage(new TranslationTextComponent("msg.overwrite"),null); return state; } if(state == 1) { if(playerEntity != null) playerEntity.sendMessage(new TranslationTextComponent("msg.recsave"),null); state = 2; world.setBlockState(pos,world.getBlockState(pos).with(MusicBlock.RECORDING,false)); if(playerEntity != null) { lastPlayerRecord = playerEntity; this.author = playerEntity.getDisplayName().getString(); } else { this.author = author; } markDirty(); } else { if(playerEntity != null) playerEntity.sendMessage(new TranslationTextComponent("msg.recstart"), null); recorded.clear(); state = 1; tick = 0; world.setBlockState(pos, world.getBlockState(pos).with(MusicBlock.RECORDING, true)); } return state; } /** * This function returns song data as NBT * @return The song data as ListNBT */ public ListNBT getSongDataNBT() { ListNBT musicData = new ListNBT(); for(Map.Entry k : recorded.entrySet()) { CompoundNBT mtickData = new CompoundNBT(); int tick = (Integer)k.getKey(); mtickData.putInt("tick",tick); ArrayList<Note> notes = (ArrayList<Note>)k.getValue(); ListNBT notesNbt = new ListNBT(); for(Note n : notes) { notesNbt.add(n.serializeNBT()); } mtickData.put("notes",notesNbt); musicData.add(mtickData); } return musicData; } /** * Don't touch, this is used by minecraft to write NBT. Use <code>getSongDataNBT()</code> and the other methods to retrieve the info you want */ @Override public CompoundNBT write(CompoundNBT compound) { compound = super.write(compound); compound.put("noteData", getSongDataNBT()); compound.putString("author",author); compound.putString("name",songName); return compound; } /** * Don't touch, this is used by minecraft to read NBT. Use <code>applyNBTSettings()</code> */ @Override public void read(BlockState state, CompoundNBT nbt) { super.read(state,nbt); this.state = 2; ListNBT musicData = (ListNBT)nbt.get("noteData"); HashMap<Integer,ArrayList<Note>> r = new HashMap<>(); System.out.println("Loading note recording:"); if(musicData == null || musicData.size() < 1) return; for(INBT k : musicData) { int tick = ((CompoundNBT)k).getInt("tick"); ListNBT notesNbt = (ListNBT)((CompoundNBT)k).get("notes"); ArrayList<Note> notes = new ArrayList<>(); if(notesNbt.size() < 1) continue; for(INBT n : notesNbt) { Note note = new Note(0,null); note.deserializeNBT(n); notes.add(note); } r.put(tick,notes); } tick = 0; author = nbt.getString("author"); songName = nbt.getString("name"); this.recorded = r; System.out.println("Finished loading notes, final size:" + recorded.size()); } /** * Imports provided parameters as the current NBT * @param musicData the song data * @param author the author * @param songName the song name */ public void applyNBTSettings(ListNBT musicData, String author, String songName) { HashMap<Integer,ArrayList<Note>> r = new HashMap<>(); System.out.println("Loading note recording:"); this.author = author; if(musicData == null || musicData.size() < 1) return; for(INBT k : musicData) { int tick = ((CompoundNBT)k).getInt("tick"); ListNBT notesNbt = (ListNBT)((CompoundNBT)k).get("notes"); ArrayList<Note> notes = new ArrayList<>(); if(notesNbt.size() < 1) continue; for(INBT n : notesNbt) { Note note = new Note(0,null); note.deserializeNBT(n); notes.add(note); } r.put(tick,notes); } tick = 0; this.recorded = r; this.songName = songName; } @Override public CompoundNBT getUpdateTag() { CompoundNBT nbt = super.getUpdateTag(); if(nbt == null) return null; nbt.putString("author",author); nbt.putString("name",songName); nbt.putInt("state",state); nbt.putInt("tick",tick); nbt.put("noteData",getSongDataNBT()); return nbt; } @Nullable @Override public SUpdateTileEntityPacket getUpdatePacket() { CompoundNBT nbt = super.getUpdateTag(); if(nbt == null) return new SUpdateTileEntityPacket(getPos(),-1,nbt); nbt.putString("author",author); nbt.putString("name",songName); nbt.putInt("state",state); nbt.putInt("tick",tick); nbt.put("noteData",getSongDataNBT()); System.out.println("Sending data : Tick:" + tick + "; State: " + state); return new SUpdateTileEntityPacket(getPos(),-1,nbt); } @Override public void onDataPacket(NetworkManager net, SUpdateTileEntityPacket pkt) { CompoundNBT tag = pkt.getNbtCompound(); if(tag == null) return; if(!tag.contains("author")) return; if(!tag.contains("name")) return; if(!tag.contains("noteData")) return; if(!tag.contains("state")) return; if(!tag.contains("tick")) return; applyNBTSettings((ListNBT) tag.get("noteData"),tag.getString("author"),tag.getString("name")); state = tag.getInt("state"); tick = tag.getInt("tick"); System.out.println("Aquired data from server: Tick:" + tick + "; State: " + state); } @Override public void handleUpdateTag(BlockState bs, CompoundNBT tag) { if(tag == null) return; if(!tag.contains("author")) return; if(!tag.contains("name")) return; if(!tag.contains("noteData")) return; if(!tag.contains("state")) return; if(!tag.contains("tick")) return; applyNBTSettings((ListNBT) tag.get("noteData"),tag.getString("author"),tag.getString("name")); state = tag.getInt("state"); tick = tag.getInt("tick"); } }
-
[SOLVED] [1.16.4] Send chat message from remote world
I may be doing something wrong, but I am trying to send a chat message to a player from a remote world. Basically, i detect click on a block @Override public ActionResultType onBlockActivated(BlockState state, World worldIn, BlockPos pos, PlayerEntity player, Hand handIn, BlockRayTraceResult hit) { if (worldIn.isRemote) return ActionResultType.SUCCESS; ((MusicBlockTileEntity)worldIn.getTileEntity(pos)).record(player,null); return ActionResultType.SUCCESS; } and then, if the world is remote i call a function on a tile entity. The function contains a code that should send a message to a player. In singleplayer it works, but on a server the message doesn't show up. I'm pretty sure I'm doing something wrong but I don't know what.
-
[1.16.4] How to copy NBT between recipe ingredients and result?
Thanks, I'll take a look
-
[1.16.4] How to copy NBT between recipe ingredients and result?
I saw a post covering this topic, but it was for 1.12 and I was unable to do something like this in 1.16. I may not be understanding something here, could anyone please explain how should I go about implementing such thing for 1.16?
IPS spam blocked by CleanTalk.