712 lines
18 KiB
Elixir
712 lines
18 KiB
Elixir
defmodule Odinsea.Shop.Packets do
|
|
@moduledoc """
|
|
Cash Shop and MTS packet builders.
|
|
|
|
Ported from Java tools.packet.MTSCSPacket
|
|
"""
|
|
|
|
alias Odinsea.Net.Packet.Out
|
|
alias Odinsea.Net.Opcodes
|
|
alias Odinsea.Shop.CashItem
|
|
|
|
# Cash shop operation codes for responses
|
|
@cs_success 0x00
|
|
@cs_fail 0x01
|
|
|
|
# ==============================================================================
|
|
# Cash Shop Entry/Setup Packets
|
|
# ==============================================================================
|
|
|
|
@doc """
|
|
Sets up the cash shop for a player.
|
|
Sent when player enters the cash shop.
|
|
"""
|
|
def set_cash_shop(character) do
|
|
Out.new(Opcodes.lp_set_cash_shop())
|
|
|> encode_cash_shop_info(character)
|
|
|> Out.to_data()
|
|
end
|
|
|
|
@doc """
|
|
Encodes the full cash shop info structure.
|
|
"""
|
|
defp encode_cash_shop_info(packet, character) do
|
|
# Best items (featured items)
|
|
best_items = Odinsea.Shop.CashItemFactory.get_best_items()
|
|
|
|
packet
|
|
# encodeStock
|
|
|> encode_stock()
|
|
# encodeCategory
|
|
|> encode_categories()
|
|
# encodeBest
|
|
|> encode_best_items(best_items)
|
|
# encodeGateway
|
|
|> encode_gateway()
|
|
# encodeLimitGoods
|
|
|> encode_limit_goods()
|
|
# encodeZeroGoods
|
|
|> encode_zero_goods()
|
|
# encodeCategoryInfo
|
|
|> encode_category_info()
|
|
# Character info
|
|
|> encode_character_cash_info(character)
|
|
end
|
|
|
|
defp encode_stock(packet) do
|
|
# Stock counts - simplified, no limited stock items
|
|
Out.encode_short(packet, 0)
|
|
end
|
|
|
|
defp encode_categories(packet) do
|
|
categories = Odinsea.Shop.CashItemFactory.get_categories()
|
|
|
|
packet
|
|
|> Out.encode_short(length(categories))
|
|
|> then(fn pkt ->
|
|
Enum.reduce(categories, pkt, fn cat, p ->
|
|
p
|
|
|> Out.encode_byte(cat.category)
|
|
|> Out.encode_byte(cat.sub_category)
|
|
|> Out.encode_byte(cat.discount_rate)
|
|
end)
|
|
end)
|
|
end
|
|
|
|
defp encode_best_items(packet, items) do
|
|
# Best items for each category/gender combination
|
|
packet
|
|
|> Out.encode_short(5) # Category count
|
|
|> Out.encode_short(2) # Gender count (male/female)
|
|
|> Out.encode_short(1) # Items per cell
|
|
|> then(fn pkt ->
|
|
Enum.reduce(0..4, pkt, fn _i, p1 ->
|
|
Enum.reduce(0..1, p1, fn _j, p2 ->
|
|
# Featured item for this category/gender
|
|
item_sn = Enum.random(items) || 0
|
|
p2
|
|
|> Out.encode_int(item_sn)
|
|
|> Out.encode_short(10000) # Category SN
|
|
end)
|
|
end)
|
|
end)
|
|
end
|
|
|
|
defp encode_gateway(packet) do
|
|
# Gateway info - empty for now
|
|
Out.encode_byte(packet, 0)
|
|
end
|
|
|
|
defp encode_limit_goods(packet) do
|
|
# Limited goods - empty
|
|
Out.encode_short(packet, 0)
|
|
end
|
|
|
|
defp encode_zero_goods(packet) do
|
|
# Zero goods - empty
|
|
Out.encode_short(packet, 0)
|
|
end
|
|
|
|
defp encode_category_info(packet) do
|
|
# Category parent info
|
|
Out.encode_byte(packet, 0)
|
|
end
|
|
|
|
defp encode_character_cash_info(packet, character) do
|
|
packet
|
|
|> Out.encode_int(character.nx_cash || 0)
|
|
|> Out.encode_int(character.maple_points || 0)
|
|
|> Out.encode_int(character.id)
|
|
# Gift token - not implemented
|
|
|> Out.encode_int(0)
|
|
end
|
|
|
|
@doc """
|
|
Enables cash shop usage.
|
|
"""
|
|
def enable_cs_use(socket) do
|
|
packet =
|
|
Out.new(Opcodes.lp_cash_shop_update())
|
|
|> encode_cs_update()
|
|
|> Out.to_data()
|
|
|
|
:gen_tcp.send(socket, packet)
|
|
end
|
|
|
|
defp encode_cs_update(packet) do
|
|
# Flag indicating update type
|
|
Out.encode_byte(packet, @cs_success)
|
|
end
|
|
|
|
@doc """
|
|
Sends the player's cash inventory.
|
|
"""
|
|
def get_cs_inventory(socket, character) do
|
|
cash_items = character.cash_inventory || []
|
|
|
|
packet =
|
|
Out.new(Opcodes.lp_cash_shop_update())
|
|
|> Out.encode_byte(0x4A) # Operation code for inventory
|
|
|> encode_cash_items(cash_items)
|
|
|> Out.to_data()
|
|
|
|
:gen_tcp.send(socket, packet)
|
|
end
|
|
|
|
defp encode_cash_items(packet, items) do
|
|
packet
|
|
|> Out.encode_short(length(items))
|
|
|> then(fn pkt ->
|
|
Enum.reduce(items, pkt, fn item, p ->
|
|
encode_cash_item(p, item)
|
|
end)
|
|
end)
|
|
end
|
|
|
|
defp encode_cash_item(packet, item) do
|
|
packet
|
|
|> Out.encode_long(item.unique_id)
|
|
|> Out.encode_int(item.item_id)
|
|
|> Out.encode_int(item.sn || 0)
|
|
|> Out.encode_short(item.quantity)
|
|
|> Out.encode_string(item.gift_from || "")
|
|
|> Out.encode_long(item.expiration || -1)
|
|
end
|
|
|
|
@doc """
|
|
Shows NX and Maple Point balances.
|
|
"""
|
|
def show_nx_maple_tokens(socket, character) do
|
|
packet =
|
|
Out.new(Opcodes.lp_cash_shop_update())
|
|
|> Out.encode_byte(0x3D) # Operation code for balance
|
|
|> Out.encode_int(character.nx_cash || 0)
|
|
|> Out.encode_int(character.maple_points || 0)
|
|
|> Out.to_data()
|
|
|
|
:gen_tcp.send(socket, packet)
|
|
end
|
|
|
|
# ==============================================================================
|
|
# Purchase Response Packets
|
|
# ==============================================================================
|
|
|
|
@doc """
|
|
Shows a successfully purchased cash item.
|
|
"""
|
|
def show_bought_cs_item(socket, item, sn, account_id) do
|
|
packet =
|
|
Out.new(Opcodes.lp_cash_shop_update())
|
|
|> Out.encode_byte(0x53) # Bought item operation
|
|
|> Out.encode_int(account_id)
|
|
|> encode_bought_item(item, sn)
|
|
|> Out.to_data()
|
|
|
|
:gen_tcp.send(socket, packet)
|
|
end
|
|
|
|
defp encode_bought_item(packet, item, sn) do
|
|
packet
|
|
|> Out.encode_long(item.unique_id)
|
|
|> Out.encode_int(item.item_id)
|
|
|> Out.encode_int(sn)
|
|
|> Out.encode_short(item.quantity)
|
|
|> Out.encode_string(item.gift_from || "")
|
|
|> Out.encode_long(item.expiration || -1)
|
|
end
|
|
|
|
@doc """
|
|
Shows a successfully purchased package.
|
|
"""
|
|
def show_bought_cs_package(socket, items, account_id) do
|
|
packet =
|
|
Out.new(Opcodes.lp_cash_shop_update())
|
|
|> Out.encode_byte(0x5D) # Package operation
|
|
|> Out.encode_int(account_id)
|
|
|> Out.encode_short(length(items))
|
|
|> then(fn pkt ->
|
|
Enum.reduce(items, pkt, fn item, p ->
|
|
encode_bought_item(p, item, item.sn)
|
|
end)
|
|
end)
|
|
|> Out.to_data()
|
|
|
|
:gen_tcp.send(socket, packet)
|
|
end
|
|
|
|
@doc """
|
|
Shows a successfully purchased quest item.
|
|
"""
|
|
def show_bought_cs_quest_item(socket, item, position) do
|
|
packet =
|
|
Out.new(Opcodes.lp_cash_shop_update())
|
|
|> Out.encode_byte(0x73) # Quest item operation
|
|
|> Out.encode_int(item.price)
|
|
|> Out.encode_short(item.count)
|
|
|> Out.encode_short(position)
|
|
|> Out.encode_int(item.item_id)
|
|
|> Out.to_data()
|
|
|
|
:gen_tcp.send(socket, packet)
|
|
end
|
|
|
|
@doc """
|
|
Confirms item moved from cash inventory to regular inventory.
|
|
"""
|
|
def confirm_from_cs_inventory(socket, item, position) do
|
|
packet =
|
|
Out.new(Opcodes.lp_cash_shop_update())
|
|
|> Out.encode_byte(0x69) # From CS inventory
|
|
|> Out.encode_byte(Odinsea.Game.InventoryType.get_type(
|
|
Odinsea.Game.InventoryType.from_item_id(item.item_id)
|
|
))
|
|
|> Out.encode_short(position)
|
|
|> Out.to_data()
|
|
|
|
:gen_tcp.send(socket, packet)
|
|
end
|
|
|
|
@doc """
|
|
Confirms item moved to cash inventory.
|
|
"""
|
|
def confirm_to_cs_inventory(socket, item, account_id) do
|
|
packet =
|
|
Out.new(Opcodes.lp_cash_shop_update())
|
|
|> Out.encode_byte(0x5F) # To CS inventory
|
|
|> Out.encode_int(account_id)
|
|
|> encode_cash_item_single(item)
|
|
|> Out.to_data()
|
|
|
|
:gen_tcp.send(socket, packet)
|
|
end
|
|
|
|
defp encode_cash_item_single(packet, item) do
|
|
packet
|
|
|> Out.encode_long(item.unique_id)
|
|
|> Out.encode_int(item.item_id)
|
|
|> Out.encode_int(item.sn || 0)
|
|
|> Out.encode_short(item.quantity)
|
|
|> Out.encode_string(item.gift_from || "")
|
|
end
|
|
|
|
# ==============================================================================
|
|
# Gift Packets
|
|
# ==============================================================================
|
|
|
|
@doc """
|
|
Sends gift confirmation.
|
|
"""
|
|
def send_gift(socket, price, item_id, count, partner) do
|
|
packet =
|
|
Out.new(Opcodes.lp_cash_shop_update())
|
|
|> Out.encode_byte(0x5B) # Gift sent operation
|
|
|> Out.encode_int(price)
|
|
|> Out.encode_int(item_id)
|
|
|> Out.encode_short(count)
|
|
|> Out.encode_string(partner)
|
|
|> Out.to_data()
|
|
|
|
:gen_tcp.send(socket, packet)
|
|
end
|
|
|
|
@doc """
|
|
Gets gifts for the player.
|
|
"""
|
|
def get_cs_gifts(socket, gifts) do
|
|
packet =
|
|
Out.new(Opcodes.lp_cash_shop_update())
|
|
|> Out.encode_byte(0x48) # Gifts operation
|
|
|> Out.encode_short(length(gifts))
|
|
|> then(fn pkt ->
|
|
Enum.reduce(gifts, pkt, fn {item, msg}, p ->
|
|
p
|
|
|> Out.encode_int(item.sn)
|
|
|> Out.encode_string(item.gift_from)
|
|
|> Out.encode_string(msg)
|
|
|> encode_cash_item_single(item)
|
|
end)
|
|
end)
|
|
|> Out.to_data()
|
|
|
|
:gen_tcp.send(socket, packet)
|
|
end
|
|
|
|
# ==============================================================================
|
|
# Wishlist Packets
|
|
# ==============================================================================
|
|
|
|
@doc """
|
|
Sends the wishlist to the player.
|
|
"""
|
|
def send_wishlist(socket, _character, wishlist) do
|
|
packet =
|
|
Out.new(Opcodes.lp_cash_shop_update())
|
|
|> Out.encode_byte(0x4D) # Wishlist operation
|
|
|> then(fn pkt ->
|
|
Enum.reduce(wishlist, pkt, fn sn, p ->
|
|
Out.encode_int(p, sn)
|
|
end)
|
|
end)
|
|
|> Out.to_data()
|
|
|
|
:gen_tcp.send(socket, packet)
|
|
end
|
|
|
|
# ==============================================================================
|
|
# Coupon Packets
|
|
# ==============================================================================
|
|
|
|
@doc """
|
|
Shows coupon redemption result.
|
|
"""
|
|
def show_coupon_redeemed(socket, items, maple_points, mesos, client_state) do
|
|
packet =
|
|
Out.new(Opcodes.lp_cash_shop_update())
|
|
|> Out.encode_byte(0x4B) # Coupon operation
|
|
|> Out.encode_byte(if safe_map_size(items) > 0, do: 1, else: 0)
|
|
|> Out.encode_int(safe_map_size(items))
|
|
|> then(fn pkt ->
|
|
Enum.reduce(items, pkt, fn {_sn, item}, p ->
|
|
encode_coupon_item(p, item, client_state)
|
|
end)
|
|
end)
|
|
|> Out.encode_int(mesos)
|
|
|> Out.encode_int(maple_points)
|
|
|> Out.to_data()
|
|
|
|
:gen_tcp.send(socket, packet)
|
|
end
|
|
|
|
defp encode_coupon_item(packet, item, _client_state) do
|
|
packet
|
|
|> Out.encode_int(item.sn)
|
|
|> Out.encode_byte(0) # Unknown
|
|
|> Out.encode_int(item.item_id)
|
|
|> Out.encode_int(item.count)
|
|
end
|
|
|
|
@doc """
|
|
Redeem response (simplified).
|
|
"""
|
|
def redeem_response(socket) do
|
|
packet =
|
|
Out.new(Opcodes.lp_cash_shop_update())
|
|
|> Out.encode_byte(0xA1) # Redeem response
|
|
|> Out.encode_int(0)
|
|
|> Out.encode_int(0)
|
|
|> Out.encode_int(0)
|
|
|> Out.to_data()
|
|
|
|
:gen_tcp.send(socket, packet)
|
|
end
|
|
|
|
# ==============================================================================
|
|
# Error Packets
|
|
# ==============================================================================
|
|
|
|
@doc """
|
|
Sends a cash shop failure code.
|
|
"""
|
|
def send_cs_fail(socket, code) do
|
|
packet =
|
|
Out.new(Opcodes.lp_cash_shop_update())
|
|
|> Out.encode_byte(0x49) # Fail operation
|
|
|> Out.encode_byte(code)
|
|
|> Out.to_data()
|
|
|
|
:gen_tcp.send(socket, packet)
|
|
end
|
|
|
|
@doc """
|
|
Notifies that a cash item has expired.
|
|
"""
|
|
def cash_item_expired(socket, unique_id) do
|
|
packet =
|
|
Out.new(Opcodes.lp_cash_shop_update())
|
|
|> Out.encode_byte(0x4E) # Expired operation
|
|
|> Out.encode_long(unique_id)
|
|
|> Out.to_data()
|
|
|
|
:gen_tcp.send(socket, packet)
|
|
end
|
|
|
|
# ==============================================================================
|
|
# MTS Packets
|
|
# ==============================================================================
|
|
|
|
@doc """
|
|
Starts the MTS for a player.
|
|
"""
|
|
def start_mts(character) do
|
|
Out.new(Opcodes.lp_set_mts_opened())
|
|
|> encode_mts_info(character)
|
|
|> Out.to_data()
|
|
end
|
|
|
|
defp encode_mts_info(packet, character) do
|
|
packet
|
|
|> encode_mts_tax_rates()
|
|
|> encode_character_mts_info(character)
|
|
end
|
|
|
|
defp encode_mts_tax_rates(packet) do
|
|
# Tax rates for different price ranges
|
|
packet
|
|
|> Out.encode_int(5) # Number of brackets
|
|
# Bracket 1: 0-5000000
|
|
|> Out.encode_int(0)
|
|
|> Out.encode_int(5_000_000)
|
|
|> Out.encode_int(10) # 10% tax
|
|
# Bracket 2: 5000000-10000000
|
|
|> Out.encode_int(5_000_001)
|
|
|> Out.encode_int(10_000_000)
|
|
|> Out.encode_int(9)
|
|
# Bracket 3: 10000000-50000000
|
|
|> Out.encode_int(10_000_001)
|
|
|> Out.encode_int(50_000_000)
|
|
|> Out.encode_int(8)
|
|
# Bracket 4: 50000000-100000000
|
|
|> Out.encode_int(50_000_001)
|
|
|> Out.encode_int(100_000_000)
|
|
|> Out.encode_int(7)
|
|
# Bracket 5: 100000000+
|
|
|> Out.encode_int(100_000_001)
|
|
|> Out.encode_int(999_999_999)
|
|
|> Out.encode_int(6)
|
|
end
|
|
|
|
defp encode_character_mts_info(packet, character) do
|
|
packet
|
|
|> Out.encode_int(character.nx_cash || 0)
|
|
|> Out.encode_int(character.maple_points || 0)
|
|
|> Out.encode_int(character.id)
|
|
end
|
|
|
|
@doc """
|
|
Shows MTS cash balance.
|
|
"""
|
|
def show_mts_cash(socket, character) do
|
|
packet =
|
|
Out.new(Opcodes.lp_mts_operation())
|
|
|> Out.encode_byte(0x17) # Show cash
|
|
|> Out.encode_int(character.nx_cash || 0)
|
|
|> Out.encode_int(character.maple_points || 0)
|
|
|> Out.to_data()
|
|
|
|
:gen_tcp.send(socket, packet)
|
|
end
|
|
|
|
@doc """
|
|
Sends current MTS listings.
|
|
"""
|
|
def send_current_mts(socket, cart) do
|
|
items = Odinsea.Shop.MTS.get_current_mts(cart)
|
|
|
|
packet =
|
|
Out.new(Opcodes.lp_mts_operation())
|
|
|> Out.encode_byte(0x16) # Current MTS
|
|
|> Out.encode_int(length(items))
|
|
|> Out.encode_int(0) # Total count (for pagination)
|
|
|> Out.encode_int(cart.page)
|
|
|> Out.encode_int(cart.tab)
|
|
|> then(fn pkt ->
|
|
Enum.reduce(items, pkt, fn item, p ->
|
|
encode_mts_item(p, item)
|
|
end)
|
|
end)
|
|
|> Out.to_data()
|
|
|
|
:gen_tcp.send(socket, packet)
|
|
end
|
|
|
|
@doc """
|
|
Sends "not yet sold" listings.
|
|
"""
|
|
def send_not_yet_sold(socket, cart) do
|
|
items = Odinsea.Shop.MTS.get_not_yet_sold(cart.character_id)
|
|
|
|
packet =
|
|
Out.new(Opcodes.lp_mts_operation())
|
|
|> Out.encode_byte(0x18) # Not yet sold
|
|
|> Out.encode_int(length(items))
|
|
|> then(fn pkt ->
|
|
Enum.reduce(items, pkt, fn item, p ->
|
|
encode_mts_item(p, item)
|
|
end)
|
|
end)
|
|
|> Out.to_data()
|
|
|
|
:gen_tcp.send(socket, packet)
|
|
end
|
|
|
|
@doc """
|
|
Sends transfer inventory.
|
|
"""
|
|
def send_transfer(socket, cart, changed \\ false) do
|
|
items = Odinsea.Shop.MTS.get_transfer(cart.character_id)
|
|
|
|
packet =
|
|
Out.new(Opcodes.lp_mts_operation())
|
|
|> Out.encode_byte(0x19) # Transfer
|
|
|> Out.encode_byte(if changed, do: 1, else: 0)
|
|
|> Out.encode_int(length(items))
|
|
|> then(fn pkt ->
|
|
Enum.reduce(items, pkt, fn item, p ->
|
|
encode_mts_transfer_item(p, item)
|
|
end)
|
|
end)
|
|
|> Out.to_data()
|
|
|
|
:gen_tcp.send(socket, packet)
|
|
end
|
|
|
|
defp encode_mts_item(packet, item) do
|
|
packet
|
|
|> Out.encode_int(item.id)
|
|
|> Out.encode_int(item.item.item_id)
|
|
|> Out.encode_int(item.price)
|
|
|> Out.encode_int(item.price) # Current price (can change)
|
|
|> Out.encode_int(item.seller_id)
|
|
|> Out.encode_string(item.seller_name)
|
|
|> Out.encode_long(item.expiration)
|
|
|> encode_item_stats(item.item)
|
|
end
|
|
|
|
defp encode_mts_transfer_item(packet, item) do
|
|
packet
|
|
|> Out.encode_int(item.item_id)
|
|
|> Out.encode_short(item.quantity)
|
|
|> encode_item_stats(item)
|
|
end
|
|
|
|
defp encode_item_stats(packet, item) do
|
|
# Full item encoding with stats
|
|
# This is simplified - full version would encode equipment stats
|
|
packet
|
|
|> Out.encode_byte(0) # Has stats flag
|
|
end
|
|
|
|
@doc """
|
|
MTS wanted listing over.
|
|
"""
|
|
def get_mts_wanted_listing_over(socket, nx, maple_points) do
|
|
packet =
|
|
Out.new(Opcodes.lp_mts_operation())
|
|
|> Out.encode_byte(0x1A)
|
|
|> Out.encode_int(nx)
|
|
|> Out.encode_int(maple_points)
|
|
|> Out.to_data()
|
|
|
|
:gen_tcp.send(socket, packet)
|
|
end
|
|
|
|
@doc """
|
|
MTS confirm sell.
|
|
"""
|
|
def get_mts_confirm_sell(socket) do
|
|
packet =
|
|
Out.new(Opcodes.lp_mts_operation())
|
|
|> Out.encode_byte(0x02)
|
|
|> Out.to_data()
|
|
|
|
:gen_tcp.send(socket, packet)
|
|
end
|
|
|
|
@doc """
|
|
MTS fail sell.
|
|
"""
|
|
def get_mts_fail_sell(socket) do
|
|
packet =
|
|
Out.new(Opcodes.lp_mts_operation())
|
|
|> Out.encode_byte(0x03)
|
|
|> Out.encode_byte(0) # Error code
|
|
|> Out.to_data()
|
|
|
|
:gen_tcp.send(socket, packet)
|
|
end
|
|
|
|
@doc """
|
|
MTS confirm cancel.
|
|
"""
|
|
def get_mts_confirm_cancel(socket) do
|
|
packet =
|
|
Out.new(Opcodes.lp_mts_operation())
|
|
|> Out.encode_byte(0x08)
|
|
|> Out.to_data()
|
|
|
|
:gen_tcp.send(socket, packet)
|
|
end
|
|
|
|
@doc """
|
|
MTS fail cancel.
|
|
"""
|
|
def get_mts_fail_cancel(socket) do
|
|
packet =
|
|
Out.new(Opcodes.lp_mts_operation())
|
|
|> Out.encode_byte(0x09)
|
|
|> Out.to_data()
|
|
|
|
:gen_tcp.send(socket, packet)
|
|
end
|
|
|
|
@doc """
|
|
MTS confirm buy.
|
|
"""
|
|
def get_mts_confirm_buy(socket) do
|
|
packet =
|
|
Out.new(Opcodes.lp_mts_operation())
|
|
|> Out.encode_byte(0x0C)
|
|
|> Out.to_data()
|
|
|
|
:gen_tcp.send(socket, packet)
|
|
end
|
|
|
|
@doc """
|
|
MTS fail buy.
|
|
"""
|
|
def get_mts_fail_buy(socket) do
|
|
packet =
|
|
Out.new(Opcodes.lp_mts_operation())
|
|
|> Out.encode_byte(0x0D)
|
|
|> Out.encode_byte(0)
|
|
|> Out.to_data()
|
|
|
|
:gen_tcp.send(socket, packet)
|
|
end
|
|
|
|
@doc """
|
|
MTS confirm transfer.
|
|
"""
|
|
def get_mts_confirm_transfer(socket, inv_type, position) do
|
|
packet =
|
|
Out.new(Opcodes.lp_mts_operation())
|
|
|> Out.encode_byte(0x11)
|
|
|> Out.encode_byte(inv_type)
|
|
|> Out.encode_short(position)
|
|
|> Out.to_data()
|
|
|
|
:gen_tcp.send(socket, packet)
|
|
end
|
|
|
|
@doc """
|
|
Add to cart message.
|
|
"""
|
|
def add_to_cart_message(socket, failed, deleted) do
|
|
packet =
|
|
Out.new(Opcodes.lp_mts_operation())
|
|
|> Out.encode_byte(0x15)
|
|
|> Out.encode_byte(if failed, do: 0, else: 1)
|
|
|> Out.encode_byte(if deleted, do: 0, else: 1)
|
|
|> Out.to_data()
|
|
|
|
:gen_tcp.send(socket, packet)
|
|
end
|
|
|
|
# ==============================================================================
|
|
# Utility Functions
|
|
# ==============================================================================
|
|
|
|
defp safe_map_size(map) when is_map(map), do: Kernel.map_size(map)
|
|
defp safe_map_size(_), do: 0
|
|
end
|