2018-07-18 19:10:43 +02:00
package us.myles.ViaVersion.protocols.protocol1_13to1_12_2.packets ;
2017-12-12 00:39:34 +01:00
2018-12-15 12:13:05 +01:00
import com.github.steveice10.opennbt.conversion.ConverterRegistry ;
2018-06-13 22:12:43 +02:00
import com.github.steveice10.opennbt.tag.builtin.* ;
2018-07-02 16:36:03 +02:00
import com.google.common.base.Joiner ;
2018-01-07 17:22:54 +01:00
import com.google.common.base.Optional ;
2018-07-15 14:26:26 +02:00
import com.google.common.io.BaseEncoding ;
2017-12-12 00:39:34 +01:00
import us.myles.ViaVersion.api.PacketWrapper ;
2018-07-29 13:14:17 +02:00
import us.myles.ViaVersion.api.Via ;
2017-12-12 00:39:34 +01:00
import us.myles.ViaVersion.api.minecraft.item.Item ;
import us.myles.ViaVersion.api.protocol.Protocol ;
import us.myles.ViaVersion.api.remapper.PacketHandler ;
import us.myles.ViaVersion.api.remapper.PacketRemapper ;
import us.myles.ViaVersion.api.type.Type ;
import us.myles.ViaVersion.packets.State ;
2018-07-21 16:45:33 +02:00
import us.myles.ViaVersion.protocols.protocol1_13to1_12_2.ChatRewriter ;
2018-12-15 12:13:05 +01:00
import us.myles.ViaVersion.protocols.protocol1_13to1_12_2.data.BlockIdData ;
2018-07-18 19:10:43 +02:00
import us.myles.ViaVersion.protocols.protocol1_13to1_12_2.data.MappingData ;
import us.myles.ViaVersion.protocols.protocol1_13to1_12_2.data.SoundSource ;
import us.myles.ViaVersion.protocols.protocol1_13to1_12_2.data.SpawnEggRewriter ;
2017-12-12 00:39:34 +01:00
2018-07-02 16:36:03 +02:00
import java.nio.charset.StandardCharsets ;
import java.util.ArrayList ;
import java.util.List ;
2018-02-18 09:55:52 +01:00
2017-12-12 00:39:34 +01:00
public class InventoryPackets {
2017-12-13 22:52:24 +01:00
private static String NBT_TAG_NAME ;
2017-12-12 00:39:34 +01:00
public static void register ( Protocol protocol ) {
2017-12-13 22:52:24 +01:00
NBT_TAG_NAME = " ViaVersion| " + protocol . getClass ( ) . getSimpleName ( ) ;
2017-12-12 00:39:34 +01:00
/ *
Outgoing packets
* /
// Set slot packet
protocol . registerOutgoing ( State . PLAY , 0x16 , 0x17 , new PacketRemapper ( ) {
@Override
public void registerMap ( ) {
map ( Type . BYTE ) ; // 0 - Window ID
map ( Type . SHORT ) ; // 1 - Slot ID
2017-12-18 16:48:25 +01:00
map ( Type . ITEM , Type . FLAT_ITEM ) ; // 2 - Slot Value
2017-12-12 00:39:34 +01:00
handler ( new PacketHandler ( ) {
@Override
public void handle ( PacketWrapper wrapper ) throws Exception {
Item stack = wrapper . get ( Type . FLAT_ITEM , 0 ) ;
toClient ( stack ) ;
}
} ) ;
}
} ) ;
// Window items packet
protocol . registerOutgoing ( State . PLAY , 0x14 , 0x15 , new PacketRemapper ( ) {
@Override
public void registerMap ( ) {
map ( Type . UNSIGNED_BYTE ) ; // 0 - Window ID
2017-12-18 16:48:25 +01:00
map ( Type . ITEM_ARRAY , Type . FLAT_ITEM_ARRAY ) ; // 1 - Window Values
2017-12-12 00:39:34 +01:00
handler ( new PacketHandler ( ) {
@Override
public void handle ( PacketWrapper wrapper ) throws Exception {
Item [ ] stacks = wrapper . get ( Type . FLAT_ITEM_ARRAY , 0 ) ;
for ( Item stack : stacks )
toClient ( stack ) ;
}
} ) ;
}
} ) ;
2018-08-12 14:56:39 +02:00
// Window property
protocol . registerOutgoing ( State . PLAY , 0x15 , 0x16 , new PacketRemapper ( ) {
@Override
public void registerMap ( ) {
map ( Type . UNSIGNED_BYTE ) ; // Window id
map ( Type . SHORT ) ; // Property
map ( Type . SHORT ) ; // Value
handler ( new PacketHandler ( ) {
@Override
public void handle ( PacketWrapper wrapper ) throws Exception {
short property = wrapper . get ( Type . SHORT , 0 ) ;
if ( property > = 4 & & property < = 6 ) { // Enchantment id
wrapper . set ( Type . SHORT , 1 , ( short ) MappingData . enchantmentMappings . getNewEnchantment (
wrapper . get ( Type . SHORT , 1 )
) ) ;
}
}
} ) ;
}
} ) ;
2017-12-12 00:39:34 +01:00
// Plugin message Packet -> Trading
protocol . registerOutgoing ( State . PLAY , 0x18 , 0x19 , new PacketRemapper ( ) {
@Override
public void registerMap ( ) {
map ( Type . STRING ) ; // 0 - Channel
handler ( new PacketHandler ( ) {
@Override
public void handle ( PacketWrapper wrapper ) throws Exception {
2018-01-07 17:22:54 +01:00
String channel = wrapper . get ( Type . STRING , 0 ) ;
2018-01-07 17:28:50 +01:00
// Handle stopsound change TODO change location of this remap to other class?
2018-01-07 17:22:54 +01:00
if ( channel . equalsIgnoreCase ( " MC|StopSound " ) ) {
String originalSource = wrapper . read ( Type . STRING ) ;
String originalSound = wrapper . read ( Type . STRING ) ;
// Reset the packet
wrapper . clearPacket ( ) ;
2018-07-21 17:32:30 +02:00
wrapper . setId ( 0x4C ) ;
2018-01-07 17:22:54 +01:00
byte flags = 0 ;
wrapper . write ( Type . BYTE , flags ) ; // Placeholder
if ( ! originalSource . isEmpty ( ) ) {
flags | = 1 ;
Optional < SoundSource > finalSource = SoundSource . findBySource ( originalSource ) ;
if ( ! finalSource . isPresent ( ) ) {
2018-08-21 17:26:04 +02:00
if ( ! Via . getConfig ( ) . isSuppress1_13ConversionErrors ( ) | | Via . getManager ( ) . isDebug ( ) ) {
Via . getPlatform ( ) . getLogger ( ) . info ( " Could not handle unknown sound source " + originalSource + " falling back to default: master " ) ;
}
2018-01-07 17:22:54 +01:00
finalSource = Optional . of ( SoundSource . MASTER ) ;
2018-08-21 17:26:04 +02:00
2018-01-07 17:22:54 +01:00
}
wrapper . write ( Type . VAR_INT , finalSource . get ( ) . getId ( ) ) ;
}
if ( ! originalSound . isEmpty ( ) ) {
flags | = 2 ;
wrapper . write ( Type . STRING , originalSound ) ;
}
wrapper . set ( Type . BYTE , 0 , flags ) ; // Update flags
2018-06-22 14:19:57 +02:00
return ;
} else if ( channel . equalsIgnoreCase ( " MC|TrList " ) ) {
channel = " minecraft:trader_list " ;
2017-12-12 00:39:34 +01:00
wrapper . passthrough ( Type . INT ) ; // Passthrough Window ID
int size = wrapper . passthrough ( Type . UNSIGNED_BYTE ) ;
for ( int i = 0 ; i < size ; i + + ) {
2017-12-18 16:48:25 +01:00
// Input Item
2018-07-13 20:23:07 +02:00
Item input = wrapper . read ( Type . ITEM ) ;
2018-06-22 14:19:57 +02:00
InventoryPackets . toClient ( input ) ;
2018-07-13 20:23:07 +02:00
wrapper . write ( Type . FLAT_ITEM , input ) ;
2017-12-18 16:48:25 +01:00
// Output Item
2018-07-13 20:23:07 +02:00
Item output = wrapper . read ( Type . ITEM ) ;
2018-06-22 14:19:57 +02:00
InventoryPackets . toClient ( output ) ;
2018-07-13 20:23:07 +02:00
wrapper . write ( Type . FLAT_ITEM , output ) ;
2017-12-12 00:39:34 +01:00
boolean secondItem = wrapper . passthrough ( Type . BOOLEAN ) ; // Has second item
2017-12-18 16:48:25 +01:00
if ( secondItem ) {
// Second Item
2018-07-13 20:23:07 +02:00
Item second = wrapper . read ( Type . ITEM ) ;
2018-06-22 14:19:57 +02:00
InventoryPackets . toClient ( second ) ;
2018-07-13 20:23:07 +02:00
wrapper . write ( Type . FLAT_ITEM , second ) ;
2017-12-18 16:48:25 +01:00
}
2017-12-12 00:39:34 +01:00
wrapper . passthrough ( Type . BOOLEAN ) ; // Trade disabled
wrapper . passthrough ( Type . INT ) ; // Number of tools uses
wrapper . passthrough ( Type . INT ) ; // Maximum number of trade uses
}
2018-06-22 14:19:57 +02:00
} else {
2018-07-15 14:26:26 +02:00
channel = getNewPluginChannelId ( channel ) ;
2018-07-02 16:36:03 +02:00
if ( channel = = null ) {
wrapper . cancel ( ) ;
return ;
} else if ( channel . equals ( " minecraft:register " ) | | channel . equals ( " minecraft:unregister " ) ) {
String [ ] channels = new String ( wrapper . read ( Type . REMAINING_BYTES ) , StandardCharsets . UTF_8 ) . split ( " \ 0 " ) ;
List < String > rewrittenChannels = new ArrayList < > ( ) ;
for ( int i = 0 ; i < channels . length ; i + + ) {
2018-07-15 14:26:26 +02:00
String rewritten = getNewPluginChannelId ( channels [ i ] ) ;
2018-07-29 13:14:17 +02:00
if ( rewritten ! = null ) {
2018-07-02 16:36:03 +02:00
rewrittenChannels . add ( rewritten ) ;
2018-08-21 17:26:04 +02:00
} else if ( ! Via . getConfig ( ) . isSuppress1_13ConversionErrors ( ) | | Via . getManager ( ) . isDebug ( ) ) {
2018-07-29 13:14:17 +02:00
Via . getPlatform ( ) . getLogger ( ) . warning ( " Ignoring plugin channel in REGISTER: " + channels [ i ] ) ;
}
2018-07-02 16:36:03 +02:00
}
wrapper . write ( Type . REMAINING_BYTES , Joiner . on ( '\0' ) . join ( rewrittenChannels ) . getBytes ( StandardCharsets . UTF_8 ) ) ;
}
2017-12-12 00:39:34 +01:00
}
2018-06-22 14:19:57 +02:00
wrapper . set ( Type . STRING , 0 , channel ) ;
2017-12-12 00:39:34 +01:00
}
2018-07-02 16:36:03 +02:00
// TODO Fix trading GUI
2017-12-12 00:39:34 +01:00
} ) ;
}
} ) ;
// Entity Equipment Packet
2018-07-11 15:13:36 +02:00
protocol . registerOutgoing ( State . PLAY , 0x3F , 0x42 , new PacketRemapper ( ) {
2017-12-12 00:39:34 +01:00
@Override
public void registerMap ( ) {
map ( Type . VAR_INT ) ; // 0 - Entity ID
map ( Type . VAR_INT ) ; // 1 - Slot ID
2017-12-18 16:48:25 +01:00
map ( Type . ITEM , Type . FLAT_ITEM ) ; // 2 - Item
2017-12-12 00:39:34 +01:00
handler ( new PacketHandler ( ) {
@Override
public void handle ( PacketWrapper wrapper ) throws Exception {
Item stack = wrapper . get ( Type . FLAT_ITEM , 0 ) ;
toClient ( stack ) ;
}
} ) ;
}
} ) ;
/ *
Incoming packets
* /
// Click window packet
2018-07-14 12:53:31 +02:00
protocol . registerIncoming ( State . PLAY , 0x07 , 0x08 , new PacketRemapper ( ) {
2017-12-12 00:39:34 +01:00
@Override
public void registerMap ( ) {
map ( Type . UNSIGNED_BYTE ) ; // 0 - Window ID
map ( Type . SHORT ) ; // 1 - Slot
map ( Type . BYTE ) ; // 2 - Button
map ( Type . SHORT ) ; // 3 - Action number
map ( Type . VAR_INT ) ; // 4 - Mode
2017-12-18 16:48:25 +01:00
map ( Type . FLAT_ITEM , Type . ITEM ) ; // 5 - Clicked Item
2017-12-12 00:39:34 +01:00
handler ( new PacketHandler ( ) {
@Override
public void handle ( PacketWrapper wrapper ) throws Exception {
2018-01-04 15:41:10 +01:00
Item item = wrapper . get ( Type . ITEM , 0 ) ;
2017-12-13 22:52:24 +01:00
toServer ( item ) ;
2017-12-12 00:39:34 +01:00
}
} ) ;
}
}
) ;
2018-07-04 22:10:30 +02:00
// Plugin message
2018-07-11 14:47:13 +02:00
protocol . registerIncoming ( State . PLAY , 0x09 , 0x0A , new PacketRemapper ( ) {
2018-07-04 22:10:30 +02:00
@Override
public void registerMap ( ) {
map ( Type . STRING ) ; // Channel
handler ( new PacketHandler ( ) {
@Override
public void handle ( PacketWrapper wrapper ) throws Exception {
String channel = wrapper . get ( Type . STRING , 0 ) ;
2018-07-15 14:26:26 +02:00
channel = getOldPluginChannelId ( channel ) ;
2018-07-04 22:10:30 +02:00
if ( channel = = null ) {
wrapper . cancel ( ) ;
return ;
} else if ( channel . equals ( " REGISTER " ) | | channel . equals ( " UNREGISTER " ) ) {
String [ ] channels = new String ( wrapper . read ( Type . REMAINING_BYTES ) , StandardCharsets . UTF_8 ) . split ( " \ 0 " ) ;
List < String > rewrittenChannels = new ArrayList < > ( ) ;
for ( int i = 0 ; i < channels . length ; i + + ) {
2018-07-15 14:26:26 +02:00
String rewritten = getOldPluginChannelId ( channels [ i ] ) ;
2018-07-29 13:14:17 +02:00
if ( rewritten ! = null ) {
2018-07-04 22:10:30 +02:00
rewrittenChannels . add ( rewritten ) ;
2018-08-21 17:26:04 +02:00
} else if ( ! Via . getConfig ( ) . isSuppress1_13ConversionErrors ( ) | | Via . getManager ( ) . isDebug ( ) ) {
2018-07-29 13:14:17 +02:00
Via . getPlatform ( ) . getLogger ( ) . warning ( " Ignoring plugin channel in REGISTER: " + channels [ i ] ) ;
}
2018-07-04 22:10:30 +02:00
}
wrapper . write ( Type . REMAINING_BYTES , Joiner . on ( '\0' ) . join ( rewrittenChannels ) . getBytes ( StandardCharsets . UTF_8 ) ) ;
}
wrapper . set ( Type . STRING , 0 , channel ) ;
}
} ) ;
}
} ) ;
2017-12-12 00:39:34 +01:00
// Creative Inventory Action
2018-07-11 14:47:13 +02:00
protocol . registerIncoming ( State . PLAY , 0x1B , 0x24 , new PacketRemapper ( ) {
2017-12-12 00:39:34 +01:00
@Override
public void registerMap ( ) {
map ( Type . SHORT ) ; // 0 - Slot
2017-12-18 16:48:25 +01:00
map ( Type . FLAT_ITEM , Type . ITEM ) ; // 1 - Clicked Item
2017-12-12 00:39:34 +01:00
handler ( new PacketHandler ( ) {
@Override
public void handle ( PacketWrapper wrapper ) throws Exception {
2018-01-04 15:41:10 +01:00
Item item = wrapper . get ( Type . ITEM , 0 ) ;
2017-12-13 22:52:24 +01:00
toServer ( item ) ;
2017-12-12 00:39:34 +01:00
}
} ) ;
}
}
) ;
}
2018-04-08 17:02:46 +02:00
// TODO CLEANUP / SMARTER REWRITE SYSTEM
2018-07-02 16:36:03 +02:00
// TODO Rewrite identifiers
2017-12-12 00:39:34 +01:00
public static void toClient ( Item item ) {
if ( item = = null ) return ;
2018-03-20 18:21:37 +01:00
CompoundTag tag = item . getTag ( ) ;
2018-04-04 19:58:20 +02:00
// Save original id
int originalId = ( item . getId ( ) < < 16 | item . getData ( ) & 0xFFFF ) ;
2018-07-20 12:14:51 +02:00
int rawId = ( item . getId ( ) < < 4 | item . getData ( ) & 0xF ) ;
2018-07-17 22:40:39 +02:00
// NBT Additions
2018-03-20 18:21:37 +01:00
if ( isDamageable ( item . getId ( ) ) ) {
2018-07-17 22:40:39 +02:00
if ( tag = = null ) item . setTag ( tag = new CompoundTag ( " tag " ) ) ;
2018-03-20 18:21:37 +01:00
tag . put ( new IntTag ( " Damage " , item . getData ( ) ) ) ;
}
if ( item . getId ( ) = = 358 ) { // map
2018-07-17 22:40:39 +02:00
if ( tag = = null ) item . setTag ( tag = new CompoundTag ( " tag " ) ) ;
2018-03-20 18:21:37 +01:00
tag . put ( new IntTag ( " map " , item . getData ( ) ) ) ;
}
2018-04-04 19:58:20 +02:00
2018-07-17 22:40:39 +02:00
// NBT Changes
if ( tag ! = null ) {
// Invert shield color id
2018-07-18 20:23:46 +02:00
if ( item . getId ( ) = = 442 | | item . getId ( ) = = 425 ) {
2018-07-17 22:40:39 +02:00
if ( tag . get ( " BlockEntityTag " ) instanceof CompoundTag ) {
CompoundTag blockEntityTag = tag . get ( " BlockEntityTag " ) ;
if ( blockEntityTag . get ( " Base " ) instanceof IntTag ) {
IntTag base = blockEntityTag . get ( " Base " ) ;
base . setValue ( 15 - base . getValue ( ) ) ;
}
2018-07-18 20:23:46 +02:00
if ( blockEntityTag . get ( " Patterns " ) instanceof ListTag ) {
for ( Tag pattern : ( ListTag ) blockEntityTag . get ( " Patterns " ) ) {
if ( pattern instanceof CompoundTag ) {
IntTag c = ( ( CompoundTag ) pattern ) . get ( " Color " ) ;
c . setValue ( 15 - c . getValue ( ) ) ; // Invert color id
}
}
}
2018-03-20 18:21:37 +01:00
}
}
2018-07-17 22:40:39 +02:00
// Display Name now uses JSON
if ( tag . get ( " display " ) instanceof CompoundTag ) {
2018-07-21 16:45:33 +02:00
CompoundTag display = tag . get ( " display " ) ;
if ( display . get ( " Name " ) instanceof StringTag ) {
StringTag name = display . get ( " Name " ) ;
display . put ( new StringTag ( NBT_TAG_NAME + " |Name " , name . getValue ( ) ) ) ;
2018-07-17 22:40:39 +02:00
name . setValue (
2018-07-21 16:45:33 +02:00
ChatRewriter . legacyTextToJson (
2018-07-17 22:40:39 +02:00
name . getValue ( )
2018-06-13 22:12:43 +02:00
)
2018-07-17 22:40:39 +02:00
) ;
2018-06-13 22:12:43 +02:00
}
}
2018-07-17 22:40:39 +02:00
// ench is now Enchantments and now uses identifiers
if ( tag . get ( " ench " ) instanceof ListTag ) {
ListTag ench = tag . get ( " ench " ) ;
ListTag enchantments = new ListTag ( " Enchantments " , CompoundTag . class ) ;
for ( Tag enchEntry : ench ) {
if ( enchEntry instanceof CompoundTag ) {
CompoundTag enchantmentEntry = new CompoundTag ( " " ) ;
2018-07-20 20:54:52 +02:00
short oldId = ( ( Number ) ( ( CompoundTag ) enchEntry ) . get ( " id " ) . getValue ( ) ) . shortValue ( ) ;
2018-07-20 20:47:05 +02:00
String newId = MappingData . oldEnchantmentsIds . get ( oldId ) ;
2018-07-29 13:14:17 +02:00
if ( newId = = null ) {
newId = " viaversion:legacy/ " + oldId ;
2018-07-20 20:47:05 +02:00
}
enchantmentEntry . put ( new StringTag ( " id " , newId ) ) ;
2018-07-20 20:58:04 +02:00
enchantmentEntry . put ( new ShortTag ( " lvl " , ( ( Number ) ( ( CompoundTag ) enchEntry ) . get ( " lvl " ) . getValue ( ) ) . shortValue ( ) ) ) ;
2018-07-17 22:40:39 +02:00
enchantments . add ( enchantmentEntry ) ;
}
}
tag . remove ( " ench " ) ;
tag . put ( enchantments ) ;
}
2018-07-19 09:51:38 +02:00
if ( tag . get ( " StoredEnchantments " ) instanceof ListTag ) {
ListTag storedEnch = tag . get ( " StoredEnchantments " ) ;
ListTag newStoredEnch = new ListTag ( " StoredEnchantments " , CompoundTag . class ) ;
for ( Tag enchEntry : storedEnch ) {
if ( enchEntry instanceof CompoundTag ) {
CompoundTag enchantmentEntry = new CompoundTag ( " " ) ;
2018-07-20 20:54:52 +02:00
short oldId = ( ( Number ) ( ( CompoundTag ) enchEntry ) . get ( " id " ) . getValue ( ) ) . shortValue ( ) ;
2018-07-20 20:47:05 +02:00
String newId = MappingData . oldEnchantmentsIds . get ( oldId ) ;
if ( newId = = null ) {
2018-07-29 13:14:17 +02:00
newId = " viaversion:legacy/ " + oldId ;
2018-07-20 20:47:05 +02:00
}
2018-07-19 09:51:38 +02:00
enchantmentEntry . put ( new StringTag ( " id " ,
2018-07-20 20:47:05 +02:00
newId
2018-07-19 09:51:38 +02:00
) ) ;
2018-07-20 20:58:04 +02:00
enchantmentEntry . put ( new ShortTag ( " lvl " , ( ( Number ) ( ( CompoundTag ) enchEntry ) . get ( " lvl " ) . getValue ( ) ) . shortValue ( ) ) ) ;
2018-07-19 09:51:38 +02:00
newStoredEnch . add ( enchantmentEntry ) ;
}
}
tag . remove ( " StoredEnchantments " ) ;
tag . put ( newStoredEnch ) ;
}
2018-12-15 12:13:05 +01:00
if ( tag . get ( " CanPlaceOn " ) instanceof ListTag ) {
ListTag old = tag . get ( " CanPlaceOn " ) ;
ListTag newCanPlaceOn = new ListTag ( " CanPlaceOn " , StringTag . class ) ;
tag . put ( ConverterRegistry . convertToTag ( NBT_TAG_NAME + " |CanPlaceOn " , ConverterRegistry . convertToValue ( old ) ) ) ; // There will be data losing
for ( Tag oldTag : old ) {
Object value = oldTag . getValue ( ) ;
String [ ] newValues = BlockIdData . blockIdMapping . get ( value instanceof String
? ( ( String ) value ) . replace ( " minecraft: " , " " )
: null ) ;
if ( newValues ! = null ) {
for ( String newValue : newValues ) {
newCanPlaceOn . add ( new StringTag ( " " , newValue ) ) ;
}
} else {
newCanPlaceOn . add ( oldTag ) ;
}
}
tag . put ( newCanPlaceOn ) ;
}
if ( tag . get ( " CanDestroy " ) instanceof ListTag ) {
ListTag old = tag . get ( " CanDestroy " ) ;
ListTag newCanDestroy = new ListTag ( " CanDestroy " , StringTag . class ) ;
tag . put ( ConverterRegistry . convertToTag ( NBT_TAG_NAME + " |CanDestroy " , ConverterRegistry . convertToValue ( old ) ) ) ; // There will be data losing
for ( Tag oldTag : old ) {
Object value = oldTag . getValue ( ) ;
String [ ] newValues = BlockIdData . blockIdMapping . get ( value instanceof String
? ( ( String ) value ) . replace ( " minecraft: " , " " )
: null ) ;
if ( newValues ! = null ) {
for ( String newValue : newValues ) {
newCanDestroy . add ( new StringTag ( " " , newValue ) ) ;
}
} else {
newCanDestroy . add ( oldTag ) ;
}
}
tag . put ( newCanDestroy ) ;
}
2018-07-20 12:14:51 +02:00
// Handle SpawnEggs
if ( item . getId ( ) = = 383 ) {
if ( tag . get ( " EntityTag " ) instanceof CompoundTag ) {
CompoundTag entityTag = tag . get ( " EntityTag " ) ;
if ( entityTag . get ( " id " ) instanceof StringTag ) {
StringTag identifier = entityTag . get ( " id " ) ;
rawId = SpawnEggRewriter . getSpawnEggId ( identifier . getValue ( ) ) ;
if ( rawId = = - 1 ) {
rawId = 25100288 ; // Bat fallback
} else {
entityTag . remove ( " id " ) ;
if ( entityTag . isEmpty ( ) )
tag . remove ( " EntityTag " ) ;
}
} else {
// Fallback to bat
rawId = 25100288 ;
}
2018-04-08 17:02:46 +02:00
} else {
// Fallback to bat
rawId = 25100288 ;
}
2018-07-20 12:14:51 +02:00
}
if ( tag . isEmpty ( ) ) {
item . setTag ( tag = null ) ;
2018-04-08 17:02:46 +02:00
}
}
2018-04-04 19:58:20 +02:00
if ( ! MappingData . oldToNewItems . containsKey ( rawId ) ) {
2018-07-17 22:40:39 +02:00
if ( ! isDamageable ( item . getId ( ) ) & & item . getId ( ) ! = 358 ) { // Map
if ( tag = = null ) item . setTag ( tag = new CompoundTag ( " tag " ) ) ;
tag . put ( new IntTag ( NBT_TAG_NAME , originalId ) ) ; // Data will be lost, saving original id
}
if ( item . getId ( ) = = 31 & & item . getData ( ) = = 0 ) { // Shrub was removed
2018-07-17 22:51:31 +02:00
rawId = 32 < < 4 ; // Dead Bush
2018-07-17 22:40:39 +02:00
} else if ( MappingData . oldToNewItems . containsKey ( rawId & ~ 0xF ) ) {
2018-04-20 00:39:30 +02:00
rawId & = ~ 0xF ; // Remove data
2018-04-04 19:58:20 +02:00
} else {
2018-08-21 17:26:04 +02:00
if ( ! Via . getConfig ( ) . isSuppress1_13ConversionErrors ( ) | | Via . getManager ( ) . isDebug ( ) ) {
Via . getPlatform ( ) . getLogger ( ) . warning ( " Failed to get 1.13 item for " + item . getId ( ) ) ;
}
2018-04-04 19:58:20 +02:00
rawId = 16 ; // Stone
}
}
2017-12-12 00:39:34 +01:00
item . setId ( MappingData . oldToNewItems . get ( rawId ) . shortValue ( ) ) ;
item . setData ( ( short ) 0 ) ;
2017-12-13 22:52:24 +01:00
}
2018-07-29 13:14:17 +02:00
public static String getNewPluginChannelId ( String old ) {
switch ( old ) {
case " MC|TrList " :
return " minecraft:trader_list " ;
case " MC|Brand " :
return " minecraft:brand " ;
case " MC|BOpen " :
return " minecraft:book_open " ;
case " MC|DebugPath " :
return " minecraft:debug/paths " ;
case " MC|DebugNeighborsUpdate " :
return " minecraft:debug/neighbors_update " ;
case " REGISTER " :
return " minecraft:register " ;
case " UNREGISTER " :
return " minecraft:unregister " ;
case " BungeeCord " :
return " bungeecord:main " ;
case " WDL|INIT " :
return " wdl:init " ;
case " WDL|CONTROL " :
return " wdl:init " ;
case " WDL|REQUEST " :
return " wdl:request " ;
default :
2018-10-31 20:26:55 +01:00
return old . matches ( " ([0-9a-z_-]*:)?[0-9a-z_/.-]* " ) // Identifier regex
2018-07-29 13:14:17 +02:00
? old
: " viaversion:legacy/ " + BaseEncoding . base32 ( ) . lowerCase ( ) . withPadChar ( '-' ) . encode (
old . getBytes ( StandardCharsets . UTF_8 ) ) ;
}
}
2017-12-13 22:52:24 +01:00
public static void toServer ( Item item ) {
if ( item = = null ) return ;
2018-04-04 19:58:20 +02:00
2018-03-20 18:21:37 +01:00
Integer rawId = null ;
boolean gotRawIdFromTag = false ;
2018-04-04 19:58:20 +02:00
2018-03-20 18:21:37 +01:00
CompoundTag tag = item . getTag ( ) ;
2018-04-04 19:58:20 +02:00
2018-06-13 22:12:43 +02:00
// Use tag to get original ID and data
2018-03-20 18:21:37 +01:00
if ( tag ! = null ) {
2017-12-13 22:52:24 +01:00
// Check for valid tag
2018-06-13 22:12:43 +02:00
if ( tag . get ( NBT_TAG_NAME ) instanceof IntTag ) {
rawId = ( Integer ) tag . get ( NBT_TAG_NAME ) . getValue ( ) ;
// Remove the tag
tag . remove ( NBT_TAG_NAME ) ;
gotRawIdFromTag = true ;
2017-12-13 22:52:24 +01:00
}
}
2018-06-13 22:12:43 +02:00
2018-03-20 18:21:37 +01:00
if ( rawId = = null ) {
2018-07-17 22:40:39 +02:00
Integer oldId = MappingData . oldToNewItems . inverse ( ) . get ( ( int ) item . getId ( ) ) ;
2018-06-13 22:12:43 +02:00
if ( oldId ! = null ) {
// Handle spawn eggs
Optional < String > eggEntityId = SpawnEggRewriter . getEntityId ( oldId ) ;
if ( eggEntityId . isPresent ( ) ) {
rawId = 383 < < 16 ;
if ( tag = = null )
item . setTag ( tag = new CompoundTag ( " tag " ) ) ;
if ( ! tag . contains ( " EntityTag " ) ) {
CompoundTag entityTag = new CompoundTag ( " EntityTag " ) ;
entityTag . put ( new StringTag ( " id " , eggEntityId . get ( ) ) ) ;
tag . put ( entityTag ) ;
2018-04-20 00:39:30 +02:00
}
2018-06-13 22:12:43 +02:00
} else {
rawId = ( oldId > > 4 ) < < 16 | oldId & 0xF ;
2018-03-20 18:21:37 +01:00
}
2018-02-18 09:55:52 +01:00
}
}
2018-04-04 19:58:20 +02:00
2018-04-20 00:39:30 +02:00
if ( rawId = = null ) {
2018-08-21 17:26:04 +02:00
if ( ! Via . getConfig ( ) . isSuppress1_13ConversionErrors ( ) | | Via . getManager ( ) . isDebug ( ) ) {
Via . getPlatform ( ) . getLogger ( ) . warning ( " Failed to get 1.12 item for " + item . getId ( ) ) ;
}
2018-04-20 00:39:30 +02:00
rawId = 0x10000 ; // Stone
}
item . setId ( ( short ) ( rawId > > 16 ) ) ;
item . setData ( ( short ) ( rawId & 0xFFFF ) ) ;
2018-04-04 19:58:20 +02:00
2018-06-13 22:12:43 +02:00
// NBT changes
2018-04-20 00:39:30 +02:00
if ( tag ! = null ) {
if ( isDamageable ( item . getId ( ) ) ) {
if ( tag . get ( " Damage " ) instanceof IntTag ) {
if ( ! gotRawIdFromTag )
item . setData ( ( short ) ( int ) tag . get ( " Damage " ) . getValue ( ) ) ;
tag . remove ( " Damage " ) ;
2018-03-20 18:21:37 +01:00
}
2018-04-20 00:39:30 +02:00
}
2018-04-04 19:58:20 +02:00
2018-04-20 00:39:30 +02:00
if ( item . getId ( ) = = 358 ) { // map
if ( tag . get ( " map " ) instanceof IntTag ) {
if ( ! gotRawIdFromTag )
item . setData ( ( short ) ( int ) tag . get ( " map " ) . getValue ( ) ) ;
tag . remove ( " map " ) ;
2018-03-20 18:21:37 +01:00
}
2018-04-20 00:39:30 +02:00
}
2018-04-04 19:58:20 +02:00
2018-07-18 20:23:46 +02:00
if ( item . getId ( ) = = 442 | | item . getId ( ) = = 425 ) { // shield / banner
2018-04-20 00:39:30 +02:00
if ( tag . get ( " BlockEntityTag " ) instanceof CompoundTag ) {
CompoundTag blockEntityTag = tag . get ( " BlockEntityTag " ) ;
if ( blockEntityTag . get ( " Base " ) instanceof IntTag ) {
IntTag base = blockEntityTag . get ( " Base " ) ;
base . setValue ( 15 - base . getValue ( ) ) ; // invert color id
2018-03-20 18:21:37 +01:00
}
2018-07-18 20:23:46 +02:00
if ( blockEntityTag . get ( " Patterns " ) instanceof ListTag ) {
for ( Tag pattern : ( ListTag ) blockEntityTag . get ( " Patterns " ) ) {
if ( pattern instanceof CompoundTag ) {
IntTag c = ( ( CompoundTag ) pattern ) . get ( " Color " ) ;
c . setValue ( 15 - c . getValue ( ) ) ; // Invert color id
}
}
}
2018-03-20 18:21:37 +01:00
}
}
2018-06-13 22:12:43 +02:00
// Display Name now uses JSON
if ( tag . get ( " display " ) instanceof CompoundTag ) {
2018-07-21 16:45:33 +02:00
CompoundTag display = tag . get ( " display " ) ;
2018-06-13 22:12:43 +02:00
if ( ( ( CompoundTag ) tag . get ( " display " ) ) . get ( " Name " ) instanceof StringTag ) {
2018-07-21 16:45:33 +02:00
StringTag name = display . get ( " Name " ) ;
StringTag via = display . get ( NBT_TAG_NAME + " |Name " ) ;
2018-06-13 22:12:43 +02:00
name . setValue (
2018-07-21 16:45:33 +02:00
via ! = null ? via . getValue ( ) : ChatRewriter . jsonTextToLegacy (
2018-06-13 22:12:43 +02:00
name . getValue ( )
)
) ;
2018-07-21 16:45:33 +02:00
display . remove ( NBT_TAG_NAME + " |Name " ) ;
2018-06-13 22:12:43 +02:00
}
}
// ench is now Enchantments and now uses identifiers
if ( tag . get ( " Enchantments " ) instanceof ListTag ) {
ListTag enchantments = tag . get ( " Enchantments " ) ;
ListTag ench = new ListTag ( " ench " , CompoundTag . class ) ;
for ( Tag enchantmentEntry : enchantments ) {
if ( enchantmentEntry instanceof CompoundTag ) {
CompoundTag enchEntry = new CompoundTag ( " " ) ;
2018-07-20 20:47:05 +02:00
String newId = ( String ) ( ( CompoundTag ) enchantmentEntry ) . get ( " id " ) . getValue ( ) ;
Short oldId = MappingData . oldEnchantmentsIds . inverse ( ) . get ( newId ) ;
2018-07-29 13:14:17 +02:00
if ( oldId = = null & & newId . startsWith ( " viaversion:legacy/ " ) ) {
2018-07-20 20:47:05 +02:00
oldId = Short . valueOf ( newId . substring ( 18 ) ) ;
}
2018-06-13 22:12:43 +02:00
enchEntry . put (
new ShortTag (
" id " ,
2018-07-20 20:47:05 +02:00
oldId
2018-06-13 22:12:43 +02:00
)
) ;
enchEntry . put ( new ShortTag ( " lvl " , ( Short ) ( ( CompoundTag ) enchantmentEntry ) . get ( " lvl " ) . getValue ( ) ) ) ;
ench . add ( enchEntry ) ;
}
}
2019-01-23 17:03:10 +01:00
tag . remove ( " Enchantments " ) ;
2018-06-13 22:12:43 +02:00
tag . put ( ench ) ;
}
2018-07-19 09:51:38 +02:00
if ( tag . get ( " StoredEnchantments " ) instanceof ListTag ) {
ListTag storedEnch = tag . get ( " StoredEnchantments " ) ;
ListTag newStoredEnch = new ListTag ( " StoredEnchantments " , CompoundTag . class ) ;
for ( Tag enchantmentEntry : storedEnch ) {
if ( enchantmentEntry instanceof CompoundTag ) {
2018-07-29 13:14:17 +02:00
CompoundTag enchEntry = new CompoundTag ( " " ) ;
String newId = ( String ) ( ( CompoundTag ) enchantmentEntry ) . get ( " id " ) . getValue ( ) ;
2018-07-20 20:54:52 +02:00
Short oldId = MappingData . oldEnchantmentsIds . inverse ( ) . get ( newId ) ;
2018-07-29 13:14:17 +02:00
if ( oldId = = null & & newId . startsWith ( " viaversion:legacy/ " ) ) {
2018-07-20 20:54:52 +02:00
oldId = Short . valueOf ( newId . substring ( 18 ) ) ;
}
2018-07-19 09:51:38 +02:00
enchEntry . put (
new ShortTag (
" id " ,
2018-07-20 20:54:52 +02:00
oldId
2018-07-19 09:51:38 +02:00
)
) ;
enchEntry . put ( new ShortTag ( " lvl " , ( Short ) ( ( CompoundTag ) enchantmentEntry ) . get ( " lvl " ) . getValue ( ) ) ) ;
newStoredEnch . add ( enchEntry ) ;
}
}
tag . remove ( " StoredEnchantments " ) ;
tag . put ( newStoredEnch ) ;
}
2018-12-15 12:13:05 +01:00
if ( tag . get ( NBT_TAG_NAME + " |CanPlaceOn " ) instanceof ListTag ) {
tag . put ( ConverterRegistry . convertToTag (
" CanPlaceOn " ,
ConverterRegistry . convertToValue ( tag . get ( NBT_TAG_NAME + " |CanPlaceOn " ) )
) ) ;
tag . remove ( NBT_TAG_NAME + " |CanPlaceOn " ) ;
} else if ( tag . get ( " CanPlaceOn " ) instanceof ListTag ) {
ListTag old = tag . get ( " CanPlaceOn " ) ;
ListTag newCanPlaceOn = new ListTag ( " CanPlaceOn " , StringTag . class ) ;
for ( Tag oldTag : old ) {
Object value = oldTag . getValue ( ) ;
String [ ] newValues = BlockIdData . fallbackReverseMapping . get ( value instanceof String
? ( ( String ) value ) . replace ( " minecraft: " , " " )
: null ) ;
if ( newValues ! = null ) {
for ( String newValue : newValues ) {
newCanPlaceOn . add ( new StringTag ( " " , newValue ) ) ;
}
} else {
newCanPlaceOn . add ( oldTag ) ;
}
}
tag . put ( newCanPlaceOn ) ;
}
if ( tag . get ( NBT_TAG_NAME + " |CanDestroy " ) instanceof ListTag ) {
tag . put ( ConverterRegistry . convertToTag (
" CanDestroy " ,
ConverterRegistry . convertToValue ( tag . get ( NBT_TAG_NAME + " |CanDestroy " ) )
) ) ;
tag . remove ( NBT_TAG_NAME + " |CanDestroy " ) ;
} else if ( tag . get ( " CanDestroy " ) instanceof ListTag ) {
ListTag old = tag . get ( " CanDestroy " ) ;
ListTag newCanDestroy = new ListTag ( " CanDestroy " , StringTag . class ) ;
for ( Tag oldTag : old ) {
Object value = oldTag . getValue ( ) ;
String [ ] newValues = BlockIdData . fallbackReverseMapping . get ( value instanceof String
? ( ( String ) value ) . replace ( " minecraft: " , " " )
: null ) ;
if ( newValues ! = null ) {
for ( String newValue : newValues ) {
newCanDestroy . add ( new StringTag ( " " , newValue ) ) ;
}
} else {
newCanDestroy . add ( oldTag ) ;
}
}
tag . put ( newCanDestroy ) ;
}
2018-03-20 18:21:37 +01:00
}
}
2018-07-15 14:26:26 +02:00
public static String getOldPluginChannelId ( String newId ) {
2018-07-04 22:10:30 +02:00
switch ( newId ) {
case " minecraft:register " :
2018-07-15 14:26:26 +02:00
return " REGISTER " ;
2018-07-04 22:10:30 +02:00
case " minecraft:unregister " :
2018-07-15 14:26:26 +02:00
return " UNREGISTER " ;
2018-07-04 22:10:30 +02:00
case " minecraft:brand " :
2018-07-15 14:26:26 +02:00
return " MC|Brand " ;
case " bungeecord:main " :
return " BungeeCord " ;
2018-07-21 23:18:31 +02:00
case " wdl:init " :
return " WDL|INIT " ;
case " wdl:control " :
return " WDL|CONTROL " ;
case " wdl:request " :
return " WDL|REQUEST " ;
2018-07-04 22:10:30 +02:00
default :
2018-08-05 22:26:14 +02:00
return newId . startsWith ( " viaversion:legacy/ " ) // Our format :)
2018-07-15 14:26:26 +02:00
? new String ( BaseEncoding . base32 ( ) . lowerCase ( ) . withPadChar ( '-' ) . decode (
newId . substring ( 18 ) ) , StandardCharsets . UTF_8 )
2018-08-05 22:26:14 +02:00
: newId . startsWith ( " legacy: " )
? newId . substring ( 7 ) // Rewrite BungeeCord's format. It will only prevent kicks, plugins will still be broken because of case-sensitivity *plays sad violin*
: newId . startsWith ( " bungeecord:legacy/ " )
? newId . substring ( 18 )
2018-07-15 14:26:26 +02:00
: newId ;
2018-07-04 22:10:30 +02:00
}
}
2018-07-29 13:14:17 +02:00
public static boolean isDamageable ( int id ) {
return id > = 256 & & id < = 259 // iron shovel, pickaxe, axe, flint and steel
| | id = = 261 // bow
| | id > = 267 & & id < = 279 // iron sword, wooden+stone+diamond swords, shovels, pickaxes, axes
| | id > = 283 & & id < = 286 // gold sword, shovel, pickaxe, axe
| | id > = 290 & & id < = 294 // hoes
| | id > = 298 & & id < = 317 // armors
| | id = = 346 // fishing rod
| | id = = 359 // shears
| | id = = 398 // carrot on a stick
| | id = = 442 // shield
| | id = = 443 ; // elytra
}
2017-12-12 00:39:34 +01:00
}