MAP_CHUNKのpacketを改変して、Y-61にある草ブロックを石にしたい
import:
ch.njol.skript.Skript
org.bukkit.Bukkit
org.bukkit.plugin.Plugin
com.comphenix.protocol.events.PacketListener
com.comphenix.protocol.events.ListeningWhitelist
com.comphenix.protocol.events.ListenerPriority
com.comphenix.protocol.events.ListenerOptions
com.comphenix.protocol.events.PacketAdapter
com.comphenix.protocol.events.PacketEvent
com.comphenix.protocol.events.PacketContainer
com.comphenix.protocol.ProtocolLibrary
com.comphenix.protocol.PacketType
com.comphenix.protocol.injector.GamePhase
com.comphenix.protocol.reflect.StructureModifier
java.lang.Override
java.util.ArrayList
java.lang.System
preimport:
jp.nlaocs.BlockPackets
public class BlockPackets extends PacketAdapter:
public BlockPackets():
super[Plugin, ListenerPriority, PacketType[]](Skript.getInstance(), ListenerPriority.NORMAL, [PacketType.Play.Server.MAP_CHUNK as PacketType])
@Override
public void onPacketSending(PacketEvent event):
set {_packet} to {_event}.getPacket()
broadcast "&aPacket: %{_packet}%"
on load:
set {blockpacketlistener} to new BlockPackets()
ProtocolLibrary.getProtocolManager().addPacketListener({blockpacketlistener})
on unload:
ProtocolLibrary.getProtocolManager().removePacketListener({blockpacketlistener})
clear {blockpacketlistener}
import:
ch.njol.skript.Skript
org.bukkit.Bukkit
org.bukkit.plugin.Plugin
com.comphenix.protocol.events.PacketListener
com.comphenix.protocol.events.ListeningWhitelist
com.comphenix.protocol.events.ListenerPriority
com.comphenix.protocol.events.ListenerOptions
com.comphenix.protocol.events.PacketAdapter
com.comphenix.protocol.events.PacketEvent
com.comphenix.protocol.events.PacketContainer
com.comphenix.protocol.ProtocolLibrary
com.comphenix.protocol.PacketType
com.comphenix.protocol.injector.GamePhase
com.comphenix.protocol.reflect.StructureModifier
java.lang.Override
java.util.ArrayList
java.lang.System
preimport:
jp.nlaocs.BlockPackets
public class BlockPackets extends PacketAdapter:
public BlockPackets():
super[Plugin, ListenerPriority, PacketType[]](Skript.getInstance(), ListenerPriority.NORMAL, [PacketType.Play.Server.MAP_CHUNK as PacketType])
@Override
public void onPacketSending(PacketEvent event):
set {_packet} to {_event}.getPacket()
broadcast "&aPacket: %{_packet}%"
on load:
set {blockpacketlistener} to new BlockPackets()
ProtocolLibrary.getProtocolManager().addPacketListener({blockpacketlistener})
on unload:
ProtocolLibrary.getProtocolManager().removePacketListener({blockpacketlistener})
clear {blockpacketlistener}


25 Replies
PacketContainerからチャンクのブロック、その座標を抽出する方法がわからないです
若干近づいたかも

このlongと思われる型の数値をどうすればブロックになるのでしょうか…
@egge
?
助けてください
もうマイクラなんて長いこと触ってないからできるかわからんけど
だいたい分かったけど
手動で計算するのはめんどいから
一回SimpleBitStorageにしまいこんで
全部getで取得

heightmapには256個のentryがあってそれぞれのエントリのビット長がceil(log2(height+1))
heightはワールドの最大の高さ

そのままデータ入ってるわけじゃないから
その意味不明なlong値から高さ取るためには

これしないと無理
heightmapの次に送られるchunk formatのbyte arrayは
ここに書いてある通り
ワールドの高さによって
public SimpleBitStorage(int p_184724_, int p_184725_, @Nullable long[] p_184726_) {
Validate.inclusiveBetween(1L, 32L, (long)p_184724_);
this.size = p_184725_;
this.bits = p_184724_;
this.mask = (1L << p_184724_) - 1L;
this.valuesPerLong = (char)(64 / p_184724_);
int i = 3 * (this.valuesPerLong - 1);
this.divideMul = MAGIC[i + 0];
this.divideAdd = MAGIC[i + 1];
this.divideShift = MAGIC[i + 2];
int j = (p_184725_ + this.valuesPerLong - 1) / this.valuesPerLong;
if (p_184726_ != null) {
if (p_184726_.length != j) {
throw new SimpleBitStorage.InitializationException("Invalid length given for storage, got: " + p_184726_.length + " but expected: " + j);
}
this.data = p_184726_;
} else {
this.data = new long[j];
}
}
---> SimpleBitStorage(bitLength, sizeOfData, dataArray)
public SimpleBitStorage(int p_184724_, int p_184725_, @Nullable long[] p_184726_) {
Validate.inclusiveBetween(1L, 32L, (long)p_184724_);
this.size = p_184725_;
this.bits = p_184724_;
this.mask = (1L << p_184724_) - 1L;
this.valuesPerLong = (char)(64 / p_184724_);
int i = 3 * (this.valuesPerLong - 1);
this.divideMul = MAGIC[i + 0];
this.divideAdd = MAGIC[i + 1];
this.divideShift = MAGIC[i + 2];
int j = (p_184725_ + this.valuesPerLong - 1) / this.valuesPerLong;
if (p_184726_ != null) {
if (p_184726_.length != j) {
throw new SimpleBitStorage.InitializationException("Invalid length given for storage, got: " + p_184726_.length + " but expected: " + j);
}
this.data = p_184726_;
} else {
this.data = new long[j];
}
}
---> SimpleBitStorage(bitLength, sizeOfData, dataArray)

したのchunk sectionの数が変わる
16^3毎にデータ送るからデフォルトの高さ384の場合384/16=24
常にchunk formatは
2bytes block count
16^3(4096)entries palette
4^3(64)entries palette
のデータを持ってる
データは下から上に向かって
送られてくる
heightmapとこのバイト配列でもいいけど

下に丁寧にブロックごとのデータをまとめたものがあるから
こっち使ったほうが楽だとおもいます。
これについていうと、これはheightmapの値でブロックではない。
うわ
召喚されてる
ブロックのデータは下のbyte arrayに入ってて

ブロックの数が最初にきて
そのあとにブロックの
idが並ぶ
palette =
4bytes block length
array of block ids
上のpaletteに送られてくるのがブロックで下はtile entityだったわ
結局paletteを覗いていくしかない
import:
com.comphenix.protocol.events.PacketListener
com.comphenix.protocol.events.ListeningWhitelist
com.comphenix.protocol.PacketType
com.comphenix.protocol.ProtocolLibrary
com.comphenix.protocol.utility.MinecraftReflection
com.comphenix.protocol.wrappers.BukkitConverters
ch.njol.skript.Skript
net.minecraft.network.PacketDataSerializer
io.netty.buffer.Unpooled
java.util.Arrays
function packet_sending(proxy: object, e: object):
#set {_levelChunk} to {_e}.getPacket().getSpecificModifier(MinecraftReflection.getLevelChunkPacketDataClass()).read(0)
set {_levelChunk} to {_e}.getPacket().getLevelChunkData().read(0)
set {_buf} to new PacketDataSerializer(Unpooled.wrappedBuffer({_levelChunk}.getBuffer()))
loop 30 times:
set {_bc} to {_buf}.readShort()
#if {_buf}.writerIndex() is {_buf}.readerIndex():
if {_bc} is 0:
stop loop
broadcast "%loop-number% BC %{_bc}%"
#-----BLOCK
set {_bpe} to {_buf}.readUnsignedByte()
broadcast "%loop-number% BLOCK_BPE %{_bpe}%"
if {_bpe} is 0:
set {_eid} to {_buf}.m()
broadcast "%loop-number% BLOCK_Single %{_eid}%"
else if {_bpe} <= 8:
set {_pdata} to {_buf}.c()
broadcast "%loop-number% BLOCK_Indirect %{_pdata}%"
set {_da} to {_buf}.d()
broadcast "%loop-number% BLOCK_DataArray %Arrays.asList({_da}).size()%"
#-----BIOME
set {_bpe} to {_buf}.readUnsignedByte()
broadcast "%loop-number% BIOME_BPE %{_bpe}%"
if {_bpe} is 0:
set {_eid} to {_buf}.m()
broadcast "%loop-number% BIOME_Single %{_eid}%"
else if {_bpe} <= 3:
set {_pdata} to {_buf}.c()
broadcast "%loop-number% BIOME_Indirect %{_pdata}%"
set {_da} to {_buf}.d()
broadcast "%loop-number% BIOME_DataArray %{_da}%"
broadcast "%{_buf}.readerIndex()% %{_buf}.writerIndex()%"
import:
com.comphenix.protocol.events.PacketListener
com.comphenix.protocol.events.ListeningWhitelist
com.comphenix.protocol.PacketType
com.comphenix.protocol.ProtocolLibrary
com.comphenix.protocol.utility.MinecraftReflection
com.comphenix.protocol.wrappers.BukkitConverters
ch.njol.skript.Skript
net.minecraft.network.PacketDataSerializer
io.netty.buffer.Unpooled
java.util.Arrays
function packet_sending(proxy: object, e: object):
#set {_levelChunk} to {_e}.getPacket().getSpecificModifier(MinecraftReflection.getLevelChunkPacketDataClass()).read(0)
set {_levelChunk} to {_e}.getPacket().getLevelChunkData().read(0)
set {_buf} to new PacketDataSerializer(Unpooled.wrappedBuffer({_levelChunk}.getBuffer()))
loop 30 times:
set {_bc} to {_buf}.readShort()
#if {_buf}.writerIndex() is {_buf}.readerIndex():
if {_bc} is 0:
stop loop
broadcast "%loop-number% BC %{_bc}%"
#-----BLOCK
set {_bpe} to {_buf}.readUnsignedByte()
broadcast "%loop-number% BLOCK_BPE %{_bpe}%"
if {_bpe} is 0:
set {_eid} to {_buf}.m()
broadcast "%loop-number% BLOCK_Single %{_eid}%"
else if {_bpe} <= 8:
set {_pdata} to {_buf}.c()
broadcast "%loop-number% BLOCK_Indirect %{_pdata}%"
set {_da} to {_buf}.d()
broadcast "%loop-number% BLOCK_DataArray %Arrays.asList({_da}).size()%"
#-----BIOME
set {_bpe} to {_buf}.readUnsignedByte()
broadcast "%loop-number% BIOME_BPE %{_bpe}%"
if {_bpe} is 0:
set {_eid} to {_buf}.m()
broadcast "%loop-number% BIOME_Single %{_eid}%"
else if {_bpe} <= 3:
set {_pdata} to {_buf}.c()
broadcast "%loop-number% BIOME_Indirect %{_pdata}%"
set {_da} to {_buf}.d()
broadcast "%loop-number% BIOME_DataArray %{_da}%"
broadcast "%{_buf}.readerIndex()% %{_buf}.writerIndex()%"
function packet_receiving(proxy: object, e: object):
broadcast "receive %{_e}%"
function sending_wl() :: object:
return ListeningWhitelist.newBuilder().normal().types(PacketType.Play.Server.MAP_CHUNK).build()
function receiving_wl() :: object:
return ListeningWhitelist.EMPTY_WHITELIST
function plugin() :: object:
return Skript.getInstance()
command /test:
trigger:
if {proxy} is set:
ProtocolLibrary.getProtocolManager().removePacketListener({proxy})
set {_funcs::onPacketSending} to function reference "packet_sending"
set {_funcs::onPacketReceiving} to function reference "packet_receiving"
set {_funcs::getSendingWhitelist} to function reference "sending_wl"
set {_funcs::getReceivingWhitelist} to function reference "receiving_wl"
set {_funcs::getPlugin} to function reference "plugin"
set {proxy} to proxy of PacketListener from {_funcs::*}
ProtocolLibrary.getProtocolManager().addPacketListener({proxy})
function packet_receiving(proxy: object, e: object):
broadcast "receive %{_e}%"
function sending_wl() :: object:
return ListeningWhitelist.newBuilder().normal().types(PacketType.Play.Server.MAP_CHUNK).build()
function receiving_wl() :: object:
return ListeningWhitelist.EMPTY_WHITELIST
function plugin() :: object:
return Skript.getInstance()
command /test:
trigger:
if {proxy} is set:
ProtocolLibrary.getProtocolManager().removePacketListener({proxy})
set {_funcs::onPacketSending} to function reference "packet_sending"
set {_funcs::onPacketReceiving} to function reference "packet_receiving"
set {_funcs::getSendingWhitelist} to function reference "sending_wl"
set {_funcs::getReceivingWhitelist} to function reference "receiving_wl"
set {_funcs::getPlugin} to function reference "plugin"
set {proxy} to proxy of PacketListener from {_funcs::*}
ProtocolLibrary.getProtocolManager().addPacketListener({proxy})


bpe = 4-8 indirectの場合はpalettのインデックスを示す
bpe = 15の場合はData ArrayにブロックのIDが入る
bpe = 0 Empty
{_bid} = block id
ここで草ブロックか判定して
いじれば完了
あとは頑張ってね
import:
com.comphenix.protocol.events.PacketListener
com.comphenix.protocol.events.ListeningWhitelist
com.comphenix.protocol.PacketType
com.comphenix.protocol.ProtocolLibrary
com.comphenix.protocol.utility.MinecraftReflection
com.comphenix.protocol.wrappers.BukkitConverters
ch.njol.skript.Skript
net.minecraft.network.PacketDataSerializer
io.netty.buffer.Unpooled
java.util.Arrays
java.util.BitSet
function packet_sending(proxy: object, e: object):
set {_levelChunk} to {_e}.getPacket().getLevelChunkData().read(0)
set {_buf} to new PacketDataSerializer(Unpooled.wrappedBuffer({_levelChunk}.getBuffer()))
loop 1 times:
set {_bc} to {_buf}.readShort()
if {_bc} is 0:
stop loop
set {_bpe} to {_buf}.readUnsignedByte()
if {_bpe} is 0:
set {_eid} to {_buf}.m()
else if {_bpe} <= 8:
set {_pdata} to {_buf}.c()
set {_da} to {_buf}.d()
set {_bs} to BitSet.valueOf({_da})
if {_bpe} is not 0:
loop {_bs}.size() / {_bpe} times:
set {_from} to ((loop-number-2) - 1) * {_bpe}
set {_to} to loop-number-2 * {_bpe} - 1
set {_bs2} to {_bs}.get({_from}, {_to})
set {_v} to {_bs2}.toLongArray()[0]
if {_v} is none:
set {_v} to 0
if {_bpe} <= 8:
set {_bid} to {_pdata}[{_v}]
else if {_bpe} is 15
set {_bid} to {_v}
#ここから処理を書く
set {_bpe} to {_buf}.readUnsignedByte()
if {_bpe} is 0:
set {_eid} to {_buf}.m()
else if {_bpe} <= 3:
set {_pdata} to {_buf}.c()
set {_da} to {_buf}.d()
import:
com.comphenix.protocol.events.PacketListener
com.comphenix.protocol.events.ListeningWhitelist
com.comphenix.protocol.PacketType
com.comphenix.protocol.ProtocolLibrary
com.comphenix.protocol.utility.MinecraftReflection
com.comphenix.protocol.wrappers.BukkitConverters
ch.njol.skript.Skript
net.minecraft.network.PacketDataSerializer
io.netty.buffer.Unpooled
java.util.Arrays
java.util.BitSet
function packet_sending(proxy: object, e: object):
set {_levelChunk} to {_e}.getPacket().getLevelChunkData().read(0)
set {_buf} to new PacketDataSerializer(Unpooled.wrappedBuffer({_levelChunk}.getBuffer()))
loop 1 times:
set {_bc} to {_buf}.readShort()
if {_bc} is 0:
stop loop
set {_bpe} to {_buf}.readUnsignedByte()
if {_bpe} is 0:
set {_eid} to {_buf}.m()
else if {_bpe} <= 8:
set {_pdata} to {_buf}.c()
set {_da} to {_buf}.d()
set {_bs} to BitSet.valueOf({_da})
if {_bpe} is not 0:
loop {_bs}.size() / {_bpe} times:
set {_from} to ((loop-number-2) - 1) * {_bpe}
set {_to} to loop-number-2 * {_bpe} - 1
set {_bs2} to {_bs}.get({_from}, {_to})
set {_v} to {_bs2}.toLongArray()[0]
if {_v} is none:
set {_v} to 0
if {_bpe} <= 8:
set {_bid} to {_pdata}[{_v}]
else if {_bpe} is 15
set {_bid} to {_v}
#ここから処理を書く
set {_bpe} to {_buf}.readUnsignedByte()
if {_bpe} is 0:
set {_eid} to {_buf}.m()
else if {_bpe} <= 3:
set {_pdata} to {_buf}.c()
set {_da} to {_buf}.d()
function packet_receiving(proxy: object, e: object):
broadcast "receive %{_e}%"
function sending_wl() :: object:
return ListeningWhitelist.newBuilder().normal().types(PacketType.Play.Server.MAP_CHUNK).build()
function receiving_wl() :: object:
return ListeningWhitelist.EMPTY_WHITELIST
function plugin() :: object:
return Skript.getInstance()
command /test:
trigger:
if {proxy} is set:
ProtocolLibrary.getProtocolManager().removePacketListener({proxy})
set {_funcs::onPacketSending} to function reference "packet_sending"
set {_funcs::onPacketReceiving} to function reference "packet_receiving"
set {_funcs::getSendingWhitelist} to function reference "sending_wl"
set {_funcs::getReceivingWhitelist} to function reference "receiving_wl"
set {_funcs::getPlugin} to function reference "plugin"
set {proxy} to proxy of PacketListener from {_funcs::*}
ProtocolLibrary.getProtocolManager().addPacketListener({proxy})
function packet_receiving(proxy: object, e: object):
broadcast "receive %{_e}%"
function sending_wl() :: object:
return ListeningWhitelist.newBuilder().normal().types(PacketType.Play.Server.MAP_CHUNK).build()
function receiving_wl() :: object:
return ListeningWhitelist.EMPTY_WHITELIST
function plugin() :: object:
return Skript.getInstance()
command /test:
trigger:
if {proxy} is set:
ProtocolLibrary.getProtocolManager().removePacketListener({proxy})
set {_funcs::onPacketSending} to function reference "packet_sending"
set {_funcs::onPacketReceiving} to function reference "packet_receiving"
set {_funcs::getSendingWhitelist} to function reference "sending_wl"
set {_funcs::getReceivingWhitelist} to function reference "receiving_wl"
set {_funcs::getPlugin} to function reference "plugin"
set {proxy} to proxy of PacketListener from {_funcs::*}
ProtocolLibrary.getProtocolManager().addPacketListener({proxy})
ありがとうございます
いろいろ試してみます!