├── Files └── EventAssets │ └── pop_up_1920x1235_welcome.png ├── Logic ├── Classes │ ├── LogicDataTables.py │ ├── LogicOfferBundle.py │ ├── LogicClientAvatar.py │ ├── LogicConfData.py │ ├── LogicDataSlot.py │ ├── LogicDailyData.py │ └── LogicClientHome.py ├── Player.py ├── Device.py └── Entry │ ├── CooldownEntry.py │ ├── AdStatus.py │ ├── RelaseEntry.py │ ├── EventSlot.py │ ├── IntValueEntry.py │ └── EventData.py ├── Packets ├── Messages │ ├── Server │ │ ├── Home │ │ │ ├── KeepAliveOkMessage.py │ │ │ ├── PlayerJWTokenMessage.py │ │ │ ├── OwnHomeDataMessage.py │ │ │ ├── LobbyInfoMessage.py │ │ │ ├── SeasonRewardsMessage.py │ │ │ ├── LeaderboardMessage.py │ │ │ └── PlayerProfileMessage.py │ │ ├── Battle │ │ │ ├── MatchMakingCancelledMessage.py │ │ │ ├── UdpConnectionInfoMessage.py │ │ │ ├── VisionUpdateMessage.py │ │ │ ├── MatchMakingStatusMessage.py │ │ │ ├── StartLoadingMessage.py │ │ │ └── BattleEndMessage.py │ │ ├── Login │ │ │ ├── ServerHelloMessage.py │ │ │ ├── CryptoErrorMessage.py │ │ │ └── LoginOkMessage.py │ │ └── Alliance │ │ │ ├── MyAllianceMessage.py │ │ │ ├── AllianceWarMessage.py │ │ │ └── AllianceDataMessage.py │ └── Client │ │ ├── Gameroom │ │ ├── TeamLeaveMessage.py │ │ ├── TeamMemberStatusMessage.py │ │ ├── TeamSetLocationMessage.py │ │ ├── TeamSetMemberReadyMessage.py │ │ ├── TeamSetEventMessage.py │ │ ├── TeamChangeMemberSettingsMessage.py │ │ └── TeamCreateMessage.py │ │ ├── Home │ │ ├── UdpCheckConnectionMessage.py │ │ ├── PlayerStatusMessage.py │ │ ├── ClientCapabilitiesMessage.py │ │ ├── ReportUserMessage.py │ │ ├── AnalyticEventMessage.py │ │ ├── KeepAliveMessage.py │ │ ├── GetSeasonRewardsMessage.py │ │ ├── AskPlayerJWTokenMessage.py │ │ ├── GetPlayerProfileMessage.py │ │ └── GetLeaderboardMessage.py │ │ ├── Login │ │ ├── AuthenticationCheckMessage.py │ │ ├── ResetAccountMessage.py │ │ ├── AccountSwitchedMessage.py │ │ ├── SetDeviceTokenMessage.py │ │ ├── ClientCryptoErrorMessage.py │ │ ├── CreateAccountMessage.py │ │ ├── UnlockAccountMessage.py │ │ ├── LoginUsingSessionMessage.py │ │ ├── ClientHelloMessage.py │ │ └── LoginMessage.py │ │ ├── Billing │ │ ├── BillingCancelledByClientMessage.py │ │ ├── KunlunBillingRequestMessage.py │ │ ├── TencentBillingRequestMessage.py │ │ ├── AppleBillingRequestMessage.py │ │ ├── GoogleBillingRequestMessage.py │ │ └── CafeBazaarBillingRequestMessage.py │ │ ├── Alliance │ │ ├── ReportAllianceStreamMessage.py │ │ └── AskForAllianceDataMessage.py │ │ └── Battle │ │ ├── GoHomeMessage.py │ │ ├── CancelMatchMakingMessage.py │ │ ├── GoHomeFromOfflinePractiseMessage.py │ │ ├── MatchmakeRequestMessage.py │ │ └── AskForBattleEndMessage.py └── LogicLaserFactory.py ├── README.md ├── Utility ├── Utils.py └── ByteStream.py └── main.py /Files/EventAssets/pop_up_1920x1235_welcome.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IsaaSooBarr/Project-LaserScratch/HEAD/Files/EventAssets/pop_up_1920x1235_welcome.png -------------------------------------------------------------------------------- /Logic/Classes/LogicDataTables.py: -------------------------------------------------------------------------------- 1 | from Logic.Helpers.GlobalID import GlobalID 2 | 3 | 4 | class LogicDataTables: 5 | def getDataById(self, globalId): 6 | GlobalID.getClassID(globalId) -------------------------------------------------------------------------------- /Logic/Player.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | class Players: 4 | ClientDict = {} 5 | Major = 0 6 | Minor = 0 7 | Revision = 0 8 | BattleTick = 0 9 | 10 | 11 | def __init__(self, device): 12 | self.device = device 13 | -------------------------------------------------------------------------------- /Logic/Device.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | class Device: 4 | AndroidID = None 5 | DeviveModel = None 6 | OpenUDID = None 7 | OSVersion = None 8 | isAndroid = False 9 | Language = None 10 | 11 | 12 | def __init__(self, socket): 13 | self.socket = socket 14 | 15 | 16 | def SendData(self, data): 17 | self.socket.send(data) -------------------------------------------------------------------------------- /Logic/Entry/CooldownEntry.py: -------------------------------------------------------------------------------- 1 | from Utility.ByteStream import Writer 2 | 3 | 4 | class CooldownEntry(Writer): 5 | def encode(self): 6 | self.writeVInt(0) # Count 7 | for x in range(0): 8 | self.writeVInt(0) 9 | self.writeDataReference(0, 0) 10 | self.writeVInt(0) -------------------------------------------------------------------------------- /Logic/Entry/AdStatus.py: -------------------------------------------------------------------------------- 1 | from Utility.ByteStream import Writer 2 | 3 | 4 | class AdStatus(Writer): 5 | def encode(self): 6 | self.writeVInt(0) # Count 7 | for x in range(0): 8 | self.writeVInt(0) 9 | self.writeVInt(0) # Used Daily Ads 10 | self.writeVInt(5) # Maximum Daily Ads -------------------------------------------------------------------------------- /Logic/Entry/RelaseEntry.py: -------------------------------------------------------------------------------- 1 | from Utility.ByteStream import Writer 2 | 3 | 4 | class RelaseEntry(Writer): 5 | def encode(self): 6 | self.writeVInt(0) # Count 7 | for x in range(0): 8 | self.writeDataReference(16, 0) # Locked Item 9 | self.writeInt(0) # Locked Timer 10 | self.writeInt(-1) -------------------------------------------------------------------------------- /Packets/Messages/Server/Home/KeepAliveOkMessage.py: -------------------------------------------------------------------------------- 1 | from Utility.ByteStream import Writer 2 | 3 | 4 | class KeepAliveOkMessage(Writer): 5 | def __init__(self, client, player): 6 | super().__init__(client) 7 | self.id = 20108 8 | self.client = client 9 | self.player = player 10 | 11 | 12 | def encode(self): 13 | pass 14 | -------------------------------------------------------------------------------- /Packets/Messages/Server/Battle/MatchMakingCancelledMessage.py: -------------------------------------------------------------------------------- 1 | from Utility.ByteStream import Writer 2 | 3 | 4 | class MatchMakingCancelledMessage(Writer): 5 | def __init__(self, client, player): 6 | super().__init__(client) 7 | self.id = 20406 8 | self.client = client 9 | self.player = player 10 | 11 | 12 | def encode(self): 13 | pass 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /Packets/Messages/Server/Home/PlayerJWTokenMessage.py: -------------------------------------------------------------------------------- 1 | from Utility.ByteStream import Writer 2 | 3 | 4 | class PlayerJWTokenMessage(Writer): 5 | def __init__(self, client, player): 6 | super().__init__(client) 7 | self.id = 23774 8 | self.client = client 9 | self.player = player 10 | 11 | 12 | def encode(self): 13 | self.writeString("") # JSON Web Token 14 | -------------------------------------------------------------------------------- /Packets/Messages/Client/Gameroom/TeamLeaveMessage.py: -------------------------------------------------------------------------------- 1 | from Utility.ByteStream import Reader 2 | 3 | 4 | class TeamLeaveMessage(Reader): 5 | def __init__(self, client, player, initial_bytes): 6 | super().__init__(initial_bytes) 7 | self.player = player 8 | self.client = client 9 | 10 | 11 | def decode(self): 12 | pass 13 | 14 | 15 | def process(self): 16 | pass -------------------------------------------------------------------------------- /Packets/Messages/Client/Home/UdpCheckConnectionMessage.py: -------------------------------------------------------------------------------- 1 | from Utility.ByteStream import Reader 2 | 3 | 4 | class UdpCheckConnectionMessage(Reader): 5 | def __init__(self, client, player, initial_bytes): 6 | super().__init__(initial_bytes) 7 | self.player = player 8 | self.client = client 9 | 10 | 11 | def decode(self): 12 | pass 13 | 14 | 15 | def process(self): 16 | pass -------------------------------------------------------------------------------- /Packets/Messages/Server/Login/ServerHelloMessage.py: -------------------------------------------------------------------------------- 1 | from Utility.ByteStream import Writer 2 | 3 | 4 | class ServerHelloMessage(Writer): 5 | def __init__(self, client, player): 6 | super().__init__(client) 7 | self.id = 20100 8 | self.client = client 9 | self.player = player 10 | 11 | 12 | def encode(self): 13 | self.writeInt(24) 14 | self.writeBytes(b'') 15 | -------------------------------------------------------------------------------- /Packets/Messages/Client/Login/AuthenticationCheckMessage.py: -------------------------------------------------------------------------------- 1 | from Utility.ByteStream import Reader 2 | 3 | 4 | class AuthenticationCheckMessage(Reader): 5 | def __init__(self, client, player, initial_bytes): 6 | super().__init__(initial_bytes) 7 | self.player = player 8 | self.client = client 9 | 10 | 11 | def decode(self): 12 | pass 13 | 14 | 15 | def process(self): 16 | pass -------------------------------------------------------------------------------- /Packets/Messages/Client/Home/PlayerStatusMessage.py: -------------------------------------------------------------------------------- 1 | from Utility.ByteStream import Reader 2 | 3 | 4 | class PlayerStatusMessage(Reader): 5 | def __init__(self, client, player, initial_bytes): 6 | super().__init__(initial_bytes) 7 | self.player = player 8 | self.client = client 9 | 10 | 11 | def decode(self): 12 | self.Status = self.readVInt() 13 | 14 | 15 | def process(self): 16 | pass -------------------------------------------------------------------------------- /Packets/Messages/Client/Home/ClientCapabilitiesMessage.py: -------------------------------------------------------------------------------- 1 | from Utility.ByteStream import Reader 2 | 3 | 4 | class ClientCapabilitiesMessage(Reader): 5 | def __init__(self, client, player, initial_bytes): 6 | super().__init__(initial_bytes) 7 | self.player = player 8 | self.client = client 9 | 10 | 11 | def decode(self): 12 | self.Ping = self.readVInt() 13 | 14 | 15 | def process(self): 16 | pass -------------------------------------------------------------------------------- /Packets/Messages/Client/Login/ResetAccountMessage.py: -------------------------------------------------------------------------------- 1 | from Utility.ByteStream import Reader 2 | 3 | 4 | class ResetAccountMessage(Reader): 5 | def __init__(self, client, player, initial_bytes): 6 | super().__init__(initial_bytes) 7 | self.player = player 8 | self.client = client 9 | 10 | 11 | def decode(self): 12 | self.AccountPreset = self.readInt() 13 | 14 | 15 | def process(self): 16 | pass -------------------------------------------------------------------------------- /Packets/Messages/Client/Gameroom/TeamMemberStatusMessage.py: -------------------------------------------------------------------------------- 1 | from Utility.ByteStream import Reader 2 | 3 | 4 | class TeamMemberStatusMessage(Reader): 5 | def __init__(self, client, player, initial_bytes): 6 | super().__init__(initial_bytes) 7 | self.player = player 8 | self.client = client 9 | 10 | 11 | def decode(self): 12 | self.Status = self.readVInt() 13 | 14 | 15 | def process(self): 16 | pass 17 | 18 | -------------------------------------------------------------------------------- /Packets/Messages/Client/Billing/BillingCancelledByClientMessage.py: -------------------------------------------------------------------------------- 1 | from Utility.ByteStream import Reader 2 | 3 | 4 | class BillingCancelledByClientMessage(Reader): 5 | def __init__(self, client, player, initial_bytes): 6 | super().__init__(initial_bytes) 7 | self.player = player 8 | self.client = client 9 | 10 | 11 | def decode(self): 12 | self.readInt() 13 | 14 | 15 | def process(self): 16 | pass -------------------------------------------------------------------------------- /Packets/Messages/Client/Home/ReportUserMessage.py: -------------------------------------------------------------------------------- 1 | from Utility.ByteStream import Reader 2 | 3 | 4 | class ReportUserMessage(Reader): 5 | def __init__(self, client, player, initial_bytes): 6 | super().__init__(initial_bytes) 7 | self.player = player 8 | self.client = client 9 | 10 | 11 | def decode(self): 12 | self.readInt() 13 | self.ReportedAvatarId = self.readLong() 14 | 15 | 16 | def process(self): 17 | pass -------------------------------------------------------------------------------- /Packets/Messages/Client/Gameroom/TeamSetLocationMessage.py: -------------------------------------------------------------------------------- 1 | from Utility.ByteStream import Reader 2 | 3 | 4 | class TeamSetLocationMessage(Reader): 5 | def __init__(self, client, player, initial_bytes): 6 | super().__init__(initial_bytes) 7 | self.player = player 8 | self.client = client 9 | 10 | 11 | def decode(self): 12 | self.LocationID = self.readDataReference()[1] 13 | 14 | 15 | def process(self): 16 | pass -------------------------------------------------------------------------------- /Packets/Messages/Server/Login/CryptoErrorMessage.py: -------------------------------------------------------------------------------- 1 | from Utility.ByteStream import Writer 2 | 3 | 4 | class CryptoErrorMessage(Writer): 5 | def __init__(self, client, player, CryptoError): 6 | super().__init__(client) 7 | self.id = 29997 8 | self.client = client 9 | self.player = player 10 | self.CryptoError = CryptoError 11 | 12 | 13 | def encode(self): 14 | self.writeVInt(self.CryptoError) # Crypto Error -------------------------------------------------------------------------------- /Packets/Messages/Client/Gameroom/TeamSetMemberReadyMessage.py: -------------------------------------------------------------------------------- 1 | from Utility.ByteStream import Reader 2 | 3 | 4 | class TeamSetMemberReadyMessage(Reader): 5 | def __init__(self, client, player, initial_bytes): 6 | super().__init__(initial_bytes) 7 | self.player = player 8 | self.client = client 9 | 10 | 11 | def decode(self): 12 | self.readBoolean() 13 | self.readVInt() 14 | 15 | 16 | def process(self): 17 | pass -------------------------------------------------------------------------------- /Packets/Messages/Client/Gameroom/TeamSetEventMessage.py: -------------------------------------------------------------------------------- 1 | from Utility.ByteStream import Reader 2 | 3 | 4 | class TeamSetEventMessage(Reader): 5 | def __init__(self, client, player, initial_bytes): 6 | super().__init__(initial_bytes) 7 | self.player = player 8 | self.client = client 9 | 10 | 11 | def decode(self): 12 | self.EventSlot = self.readVInt() 13 | self.readVInt() 14 | 15 | 16 | def process(self): 17 | pass -------------------------------------------------------------------------------- /Packets/Messages/Client/Alliance/ReportAllianceStreamMessage.py: -------------------------------------------------------------------------------- 1 | from Utility.ByteStream import Reader 2 | 3 | 4 | class ReportAllianceStreamMessage(Reader): 5 | def __init__(self, client, player, initial_bytes): 6 | super().__init__(initial_bytes) 7 | self.player = player 8 | self.client = client 9 | 10 | 11 | def decode(self): 12 | self.Id = self.readLong() 13 | self.ReportedAvatarId = self.readLong() 14 | 15 | 16 | def process(self): 17 | pass -------------------------------------------------------------------------------- /Packets/Messages/Client/Gameroom/TeamChangeMemberSettingsMessage.py: -------------------------------------------------------------------------------- 1 | from Utility.ByteStream import Reader 2 | 3 | 4 | class TeamChangeMemberSettingsMessage(Reader): 5 | def __init__(self, client, player, initial_bytes): 6 | super().__init__(initial_bytes) 7 | self.player = player 8 | self.client = client 9 | 10 | 11 | def decode(self): 12 | self.readVInt() 13 | self.BrawlerID = self.readDataReference()[1] 14 | 15 | 16 | def process(self): 17 | pass -------------------------------------------------------------------------------- /Logic/Entry/EventSlot.py: -------------------------------------------------------------------------------- 1 | from Utility.ByteStream import Writer 2 | 3 | 4 | class EventSlot(Writer): 5 | def encode(self): 6 | self.writeVInt(7) # Event Slots Count 7 | self.writeVInt(1) # Gem Grab 8 | self.writeVInt(2) # Showdown 9 | self.writeVInt(3) # Daily Events 10 | self.writeVInt(4) # Special Events 11 | self.writeVInt(5) # Duo Showdown 12 | self.writeVInt(6) # Special Events (Duo Showdown) 13 | self.writeVInt(7) # Ticketed Events -------------------------------------------------------------------------------- /Packets/Messages/Client/Login/AccountSwitchedMessage.py: -------------------------------------------------------------------------------- 1 | from Utility.ByteStream import Reader 2 | 3 | 4 | class AccountSwitchedMessage(Reader): 5 | def __init__(self, client, player, initial_bytes): 6 | super().__init__(initial_bytes) 7 | self.player = player 8 | self.client = client 9 | 10 | 11 | def decode(self): 12 | self.SwitchedToAccountId = self.readLong() 13 | self.readByte() 14 | self.readString() 15 | 16 | 17 | def process(self): 18 | pass -------------------------------------------------------------------------------- /Packets/Messages/Client/Login/SetDeviceTokenMessage.py: -------------------------------------------------------------------------------- 1 | from Utility.ByteStream import Reader 2 | 3 | 4 | class SetDeviceTokenMessage(Reader): 5 | def __init__(self, client, player, initial_bytes): 6 | super().__init__(initial_bytes) 7 | self.player = player 8 | self.client = client 9 | 10 | 11 | def decode(self): 12 | #self.DeviceToken = self.readBytes() 13 | #self.AntihackFlags = self.readInt() 14 | pass 15 | 16 | 17 | def process(self): 18 | pass -------------------------------------------------------------------------------- /Packets/Messages/Client/Gameroom/TeamCreateMessage.py: -------------------------------------------------------------------------------- 1 | from Utility.ByteStream import Reader 2 | 3 | 4 | class TeamCreateMessage(Reader): 5 | def __init__(self, client, player, initial_bytes): 6 | super().__init__(initial_bytes) 7 | self.player = player 8 | self.client = client 9 | 10 | 11 | def decode(self): 12 | self.EventSlot = self.readVInt() 13 | self.readVInt() 14 | self.readVInt() 15 | self.readBoolean() 16 | 17 | 18 | def process(self): 19 | pass -------------------------------------------------------------------------------- /Packets/Messages/Client/Home/AnalyticEventMessage.py: -------------------------------------------------------------------------------- 1 | from Utility.ByteStream import Reader 2 | 3 | 4 | class AnalyticEventMessage(Reader): 5 | def __init__(self, client, player, initial_bytes): 6 | super().__init__(initial_bytes) 7 | self.player = player 8 | self.client = client 9 | 10 | 11 | def decode(self): 12 | self.Type = self.readStringReference() 13 | self.Event = self.readString() 14 | 15 | 16 | def process(self): 17 | print("[INFO] " + self.Type + " " + self.Event) -------------------------------------------------------------------------------- /Packets/Messages/Client/Home/KeepAliveMessage.py: -------------------------------------------------------------------------------- 1 | from Packets.Messages.Server.Home.KeepAliveOkMessage import KeepAliveOkMessage 2 | from Utility.ByteStream import Reader 3 | 4 | 5 | class KeepAliveMessage(Reader): 6 | def __init__(self, client, player, initial_bytes): 7 | super().__init__(initial_bytes) 8 | self.player = player 9 | self.client = client 10 | 11 | 12 | def decode(self): 13 | pass 14 | 15 | 16 | def process(self): 17 | KeepAliveOkMessage(self.client, self.player).send() -------------------------------------------------------------------------------- /Packets/Messages/Server/Battle/UdpConnectionInfoMessage.py: -------------------------------------------------------------------------------- 1 | from Utility.ByteStream import Writer 2 | 3 | 4 | class UdpConnectionInfoMessage(Writer): 5 | def __init__(self, client, player): 6 | super().__init__(client) 7 | self.id = 24112 8 | self.client = client 9 | self.player = player 10 | 11 | 12 | def encode(self): 13 | self.writeVInt(9339) # Server Port 14 | self.writeString("10.0.0.169") # Server Host 15 | self.writeBytes(b'') 16 | self.writeBytes(b'') -------------------------------------------------------------------------------- /Packets/Messages/Client/Home/GetSeasonRewardsMessage.py: -------------------------------------------------------------------------------- 1 | from Packets.Messages.Server.Home.SeasonRewardsMessage import SeasonRewardsMessage 2 | from Utility.ByteStream import Reader 3 | 4 | 5 | class GetSeasonRewardsMessage(Reader): 6 | def __init__(self, client, player, initial_bytes): 7 | super().__init__(initial_bytes) 8 | self.player = player 9 | self.client = client 10 | 11 | 12 | def decode(self): 13 | pass 14 | 15 | 16 | def process(self): 17 | SeasonRewardsMessage(self.client, self.player).send() -------------------------------------------------------------------------------- /Packets/Messages/Client/Home/AskPlayerJWTokenMessage.py: -------------------------------------------------------------------------------- 1 | from Packets.Messages.Server.Home.PlayerJWTokenMessage import PlayerJWTokenMessage 2 | from Utility.ByteStream import Reader 3 | 4 | 5 | class AskPlayerJWTokenMessage(Reader): 6 | def __init__(self, client, player, initial_bytes): 7 | super().__init__(initial_bytes) 8 | self.player = player 9 | self.client = client 10 | 11 | 12 | def decode(self): 13 | pass 14 | 15 | 16 | def process(self): 17 | PlayerJWTokenMessage(self.client, self.player).send() -------------------------------------------------------------------------------- /Packets/Messages/Client/Battle/GoHomeMessage.py: -------------------------------------------------------------------------------- 1 | from Packets.Messages.Server.Home.OwnHomeDataMessage import OwnHomeDataMessage 2 | from Utility.ByteStream import Reader 3 | 4 | 5 | class GoHomeMessage(Reader): 6 | def __init__(self, client, player, initial_bytes): 7 | super().__init__(initial_bytes) 8 | self.player = player 9 | self.client = client 10 | 11 | 12 | def decode(self): 13 | self.ClearActiveBattle = self.readBoolean() 14 | 15 | 16 | def process(self): 17 | OwnHomeDataMessage(self.client, self.player).send() -------------------------------------------------------------------------------- /Packets/Messages/Client/Battle/CancelMatchMakingMessage.py: -------------------------------------------------------------------------------- 1 | from Packets.Messages.Server.Battle.MatchMakingCancelledMessage import MatchMakingCancelledMessage 2 | from Utility.ByteStream import Reader 3 | 4 | 5 | class CancelMatchMakingMessage(Reader): 6 | def __init__(self, client, player, initial_bytes): 7 | super().__init__(initial_bytes) 8 | self.player = player 9 | self.client = client 10 | 11 | 12 | def decode(self): 13 | pass 14 | 15 | 16 | def process(self): 17 | MatchMakingCancelledMessage(self.client, self.player).send() -------------------------------------------------------------------------------- /Packets/Messages/Client/Login/ClientCryptoErrorMessage.py: -------------------------------------------------------------------------------- 1 | from Packets.Messages.Server.Login.CryptoErrorMessage import CryptoErrorMessage 2 | from Utility.ByteStream import Reader 3 | 4 | 5 | class ClientCryptoErrorMessage(Reader): 6 | def __init__(self, client, player, initial_bytes): 7 | super().__init__(initial_bytes) 8 | self.player = player 9 | self.client = client 10 | 11 | 12 | def decode(self): 13 | self.CryptoError = self.readInt() 14 | 15 | 16 | def process(self): 17 | CryptoErrorMessage(self.client, self.player, self.CryptoError).send() 18 | -------------------------------------------------------------------------------- /Packets/Messages/Client/Battle/GoHomeFromOfflinePractiseMessage.py: -------------------------------------------------------------------------------- 1 | from Packets.Messages.Server.Home.OwnHomeDataMessage import OwnHomeDataMessage 2 | from Utility.ByteStream import Reader 3 | 4 | 5 | class GoHomeFromOfflinePractiseMessage(Reader): 6 | def __init__(self, client, player, initial_bytes): 7 | super().__init__(initial_bytes) 8 | self.player = player 9 | self.client = client 10 | 11 | 12 | def decode(self): 13 | self.ClearActiveBattle = self.readBoolean() 14 | 15 | 16 | def process(self): 17 | OwnHomeDataMessage(self.client, self.player).send() -------------------------------------------------------------------------------- /Packets/Messages/Server/Battle/VisionUpdateMessage.py: -------------------------------------------------------------------------------- 1 | from Utility.ByteStream import Writer 2 | 3 | 4 | class VisionUpdateMessage(Writer): 5 | def __init__(self, client, player): 6 | super().__init__(client) 7 | self.id = 24109 8 | self.client = client 9 | self.player = player 10 | 11 | 12 | def encode(self): 13 | self.writeVInt(self.player.BattleTick) # Battle Tick 14 | self.writeVInt(int(self.player.BattleTick / 10)) 15 | self.writeVInt(0) 16 | self.writeVInt(0) # Spectates 17 | self.writeBoolean(False) # Brawl TV Battle -------------------------------------------------------------------------------- /Packets/Messages/Client/Login/CreateAccountMessage.py: -------------------------------------------------------------------------------- 1 | from Utility.ByteStream import Reader 2 | 3 | 4 | class CreateAccountMessage(Reader): 5 | def __init__(self, client, player, initial_bytes): 6 | super().__init__(initial_bytes) 7 | self.player = player 8 | self.client = client 9 | 10 | 11 | def decode(self): 12 | self.DeviceId = self.readString() 13 | self.FacebookId = self.readString() 14 | self.GameCenterId = self.readString() 15 | self.TwitterId = self.readString() 16 | self.Email = self.readString() 17 | 18 | 19 | def process(self): 20 | pass -------------------------------------------------------------------------------- /Packets/Messages/Client/Billing/KunlunBillingRequestMessage.py: -------------------------------------------------------------------------------- 1 | from Utility.ByteStream import Reader 2 | 3 | 4 | class KunlunBillingRequestMessage(Reader): 5 | def __init__(self, client, player, initial_bytes): 6 | super().__init__(initial_bytes) 7 | self.player = player 8 | self.client = client 9 | 10 | 11 | def decode(self): 12 | self.TID = self.readStringReference() 13 | self.ProdId = self.readStringReference() 14 | self.PurchaseToken = self.readStringReference() 15 | self.Price = self.readStringReference() 16 | 17 | 18 | def process(self): 19 | pass -------------------------------------------------------------------------------- /Packets/Messages/Client/Billing/TencentBillingRequestMessage.py: -------------------------------------------------------------------------------- 1 | from Utility.ByteStream import Reader 2 | 3 | 4 | class TencentBillingRequestMessage(Reader): 5 | def __init__(self, client, player, initial_bytes): 6 | super().__init__(initial_bytes) 7 | self.player = player 8 | self.client = client 9 | 10 | 11 | def decode(self): 12 | self.OriginalJSON = self.readStringReference() 13 | self.Signature = self.readStringReference() 14 | self.ProdId = self.readStringReference() 15 | self.Price = self.readStringReference() 16 | 17 | 18 | def process(self): 19 | pass -------------------------------------------------------------------------------- /Packets/Messages/Client/Billing/AppleBillingRequestMessage.py: -------------------------------------------------------------------------------- 1 | from Utility.ByteStream import Reader 2 | 3 | 4 | class AppleBillingRequestMessage(Reader): 5 | def __init__(self, client, player, initial_bytes): 6 | super().__init__(initial_bytes) 7 | self.player = player 8 | self.client = client 9 | 10 | 11 | def decode(self): 12 | self.TID = self.readString() 13 | self.ProdId = self.readString() 14 | self.CurrencyCode = self.readString() 15 | self.Price = self.readString() 16 | #self.ReceiptDataLength = self.readBytes() 17 | 18 | 19 | def process(self): 20 | pass -------------------------------------------------------------------------------- /Packets/Messages/Server/Battle/MatchMakingStatusMessage.py: -------------------------------------------------------------------------------- 1 | from Utility.ByteStream import Writer 2 | 3 | 4 | class MatchMakingStatusMessage(Writer): 5 | def __init__(self, client, player): 6 | super().__init__(client) 7 | self.id = 20405 8 | self.player = player 9 | 10 | 11 | def encode(self): 12 | self.writeInt(60) # Matchmake Timer 13 | self.writeInt(1) # Current Players in Matchmake 14 | self.writeInt(1) # Maximum Players in Matchmake 15 | self.writeInt(1) # Play Again Accepted Players 16 | self.writeInt(0) # Play Again Maximum Players 17 | self.writeBoolean(True) # Matchmake Timer Enabled State -------------------------------------------------------------------------------- /Packets/Messages/Client/Login/UnlockAccountMessage.py: -------------------------------------------------------------------------------- 1 | from Utility.ByteStream import Reader 2 | 3 | 4 | class UnlockAccountMessage(Reader): 5 | def __init__(self, client, player, initial_bytes): 6 | super().__init__(initial_bytes) 7 | self.player = player 8 | self.client = client 9 | 10 | 11 | def decode(self): 12 | self.AccountID = self.readLong() 13 | self.PassToken = self.readString() 14 | self.UnlockCode = self.readString() 15 | self.SupercellIDToken = self.readString() 16 | 17 | 18 | def process(self): 19 | self.HighID = self.AccountID[0] 20 | self.LowID = self.AccountID[1] -------------------------------------------------------------------------------- /Packets/Messages/Server/Home/OwnHomeDataMessage.py: -------------------------------------------------------------------------------- 1 | from Logic.Classes.LogicClientHome import LogicClientHome 2 | from Logic.Classes.LogicClientAvatar import LogicClientAvatar 3 | from Utility.ByteStream import Writer 4 | from Utility.Utils import Utils 5 | 6 | 7 | class OwnHomeDataMessage(Writer): 8 | def __init__(self, client, player): 9 | super().__init__(client) 10 | self.id = 24101 11 | self.client = client 12 | self.player = player 13 | 14 | 15 | def encode(self): 16 | LogicClientHome.encode(self) 17 | LogicClientAvatar.encode(self) 18 | self.writeVInt(Utils.getCurrentTimeInSecondsSinceEpoch(self)) # Current Time 19 | -------------------------------------------------------------------------------- /Packets/Messages/Client/Home/GetPlayerProfileMessage.py: -------------------------------------------------------------------------------- 1 | from Packets.Messages.Server.Home.PlayerProfileMessage import PlayerProfileMessage 2 | from Utility.ByteStream import Reader 3 | 4 | 5 | class GetPlayerProfileMessage(Reader): 6 | def __init__(self, client, player, initial_bytes): 7 | super().__init__(initial_bytes) 8 | self.player = player 9 | self.client = client 10 | 11 | 12 | def decode(self): 13 | self.PlayerID = self.readLong() 14 | 15 | 16 | def process(self): 17 | self.HighID = self.PlayerID[0] 18 | self.LowID = self.PlayerID[1] 19 | PlayerProfileMessage(self.client, self.player, self.HighID, self.LowID).send() 20 | -------------------------------------------------------------------------------- /Packets/Messages/Client/Billing/GoogleBillingRequestMessage.py: -------------------------------------------------------------------------------- 1 | from Utility.ByteStream import Reader 2 | 3 | 4 | class GoogleBillingRequestMessage(Reader): 5 | def __init__(self, client, player, initial_bytes): 6 | super().__init__(initial_bytes) 7 | self.player = player 8 | self.client = client 9 | 10 | 11 | def decode(self): 12 | self.TID = self.readString() 13 | self.ProdId = self.readString() 14 | self.CurrencyCode = self.readString() 15 | self.Price = self.readString() 16 | self.PurchaseData = self.readString() 17 | self.Signature = self.readString() 18 | 19 | 20 | def process(self): 21 | pass -------------------------------------------------------------------------------- /Packets/Messages/Client/Home/GetLeaderboardMessage.py: -------------------------------------------------------------------------------- 1 | from Packets.Messages.Server.Home.LeaderboardMessage import LeaderboardMessage 2 | from Utility.ByteStream import Reader 3 | 4 | 5 | class GetLeaderboardMessage(Reader): 6 | def __init__(self, client, player, initial_bytes): 7 | super().__init__(initial_bytes) 8 | self.player = player 9 | self.client = client 10 | 11 | 12 | def decode(self): 13 | self.isLocal = self.readBoolean() 14 | self.Type = self.readVInt() 15 | self.BralwerID = self.readDataReference()[1] 16 | 17 | 18 | def process(self): 19 | LeaderboardMessage(self.client, self.player, self.isLocal, self.Type, self.BralwerID).send() -------------------------------------------------------------------------------- /Packets/Messages/Client/Billing/CafeBazaarBillingRequestMessage.py: -------------------------------------------------------------------------------- 1 | from Utility.ByteStream import Reader 2 | 3 | 4 | class CafeBazaarBillingRequestMessage(Reader): 5 | def __init__(self, client, player, initial_bytes): 6 | super().__init__(initial_bytes) 7 | self.player = player 8 | self.client = client 9 | 10 | 11 | def decode(self): 12 | self.TID = self.readString() 13 | self.ProdId = self.readString() 14 | self.CurrencyCode = self.readString() 15 | self.Price = self.readString() 16 | self.PurchaseData = self.readString() 17 | self.Signature = self.readString() 18 | 19 | 20 | def process(self): 21 | pass -------------------------------------------------------------------------------- /Packets/Messages/Client/Alliance/AskForAllianceDataMessage.py: -------------------------------------------------------------------------------- 1 | from Packets.Messages.Server.Alliance.AllianceDataMessage import AllianceDataMessage 2 | from Utility.ByteStream import Reader 3 | 4 | 5 | class AskForAllianceDataMessage(Reader): 6 | def __init__(self, client, player, initial_bytes): 7 | super().__init__(initial_bytes) 8 | self.player = player 9 | self.client = client 10 | 11 | 12 | def decode(self): 13 | self.AllianceID = self.readLong() 14 | self.readBoolean() 15 | 16 | 17 | def process(self): 18 | self.HighID = self.AllianceID[0] 19 | self.LowID = self.AllianceID[1] 20 | AllianceDataMessage(self.client, self.player, self.HighID, self.LowID).send() -------------------------------------------------------------------------------- /Packets/Messages/Client/Login/LoginUsingSessionMessage.py: -------------------------------------------------------------------------------- 1 | from Utility.ByteStream import Reader 2 | 3 | 4 | class LoginUsingSessionMessage(Reader): 5 | def __init__(self, client, player, initial_bytes): 6 | super().__init__(initial_bytes) 7 | self.player = player 8 | self.client = client 9 | 10 | 11 | def decode(self): 12 | self.AccountIdHigherInt = self.readInt() 13 | self.AccountIdLowerInt = self.readInt() 14 | self.SessionKey = self.readString() 15 | self.FacebookAccessToken = self.readString() 16 | self.Source = self.readString() 17 | self.DeviceIdentifier = self.readString() 18 | self.DeviceToken = self.readString() 19 | 20 | 21 | def process(self): 22 | pass -------------------------------------------------------------------------------- /Packets/Messages/Client/Battle/MatchmakeRequestMessage.py: -------------------------------------------------------------------------------- 1 | from Packets.Messages.Server.Battle.MatchMakingStatusMessage import MatchMakingStatusMessage 2 | from Utility.ByteStream import Reader 3 | import time 4 | 5 | 6 | class MatchmakeRequestMessage(Reader): 7 | def __init__(self, client, player, initial_bytes): 8 | super().__init__(initial_bytes) 9 | self.player = player 10 | self.client = client 11 | 12 | 13 | def decode(self): 14 | self.readDataReference()[1] # Selected Brawler 15 | self.readVInt() # Event Index 16 | self.readVInt() # Event Index 17 | self.readVInt() # Highstakes Index 18 | self.readVInt() 19 | 20 | 21 | def process(self): 22 | MatchMakingStatusMessage(self.client, self.player).send() -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

Laser Scratch

2 | 3 | Brawl Stars open source server for v20! 4 | 5 | 6 | ![ScreenShot](https://cdn.discordapp.com/attachments/914412016100315187/915434728625152030/Screenshot_20211130-235016.png) 7 | 8 | 9 | ## Implemented Features 10 | - Battle End 11 | - Leaderboard 12 | - Player Profile 13 | - Lobby Info 14 | - Menu Notifications 15 | - Club Wars 16 | 17 | 18 | ## Important Notes 19 | - Python 3.7 is the minimum requirement to run the server. 20 | - This server was made ONLY for testing purposes. If you aren't a coder, don't try to use it. 21 | - Missing features should be added in future. 22 | - The server doesn't have his own client yet. A custom client will be available soon. 23 | 24 | 25 | ## Authors 26 | 👤 **Isadora** 27 | * Github: [@Isaa](https://github.com/IsaaSooBarr) 28 | 29 | 30 | Contributors: 31 | - PhoenixFire 32 | - Crazor 33 | - BreadDev 34 | - XshadowX 35 | - Peter 36 | - Peka 37 | - eesdf 38 | -------------------------------------------------------------------------------- /Packets/Messages/Server/Alliance/MyAllianceMessage.py: -------------------------------------------------------------------------------- 1 | from Utility.ByteStream import Writer 2 | 3 | 4 | class MyAllianceMessage(Writer): 5 | def __init__(self, client, player): 6 | super().__init__(client) 7 | self.id = 24399 8 | self.client = client 9 | self.player = player 10 | 11 | 12 | def encode(self): 13 | self.writeVInt(1) 14 | self.writeBoolean(True) # Joined In a Club 15 | self.writeDataReference(25, 1) # Club Role 16 | # Club Header Entry 17 | self.writeLong(0, 1) # Club ID 18 | self.writeString("Club") # Club Name 19 | self.writeDataReference(8, 0) # Club Badge 20 | self.writeVInt(1) # Club Type 21 | self.writeVInt(1) # Club Members 22 | self.writeVInt(0) # Club Trophies 23 | self.writeVInt(0) # Club Required Trophies 24 | self.writeDataReference(0, -1) 25 | self.writeString("BR") # Club Region 26 | self.writeVInt(1) # Club Online Members 27 | # Club Header Entry End -------------------------------------------------------------------------------- /Packets/Messages/Server/Home/LobbyInfoMessage.py: -------------------------------------------------------------------------------- 1 | from Utility.ByteStream import Writer 2 | from Utility.Utils import Utils 3 | 4 | 5 | class LobbyInfoMessage(Writer): 6 | def __init__(self, client, player, count): 7 | super().__init__(client) 8 | self.id = 23457 9 | self.client = client 10 | self.player = player 11 | self.count = count 12 | 13 | 14 | def encode(self): 15 | self.writeVInt(self.count) # Players Online 16 | self.writeString(f"Project LaserScratch (v1.1.1)\nVersion: {self.player.Major}.{self.player.Minor}.{self.player.Revision}\n{Utils.getLobbyInfoCurrentDate(self)}") 17 | 18 | 19 | # Lobby Info Entry Array 20 | self.writeVInt(0) # Events Count 21 | for x in range(0): 22 | self.writeVInt(0) # Event Index 23 | self.writeVInt(0) # Pvp Battle 24 | self.writeVInt(0) # Pvp Matchmake 25 | self.writeVInt(0) # Co-op Battle 26 | self.writeVInt(0) # Co-op Matchmake 27 | # Lobby Info Entry Array End 28 | 29 | -------------------------------------------------------------------------------- /Logic/Classes/LogicOfferBundle.py: -------------------------------------------------------------------------------- 1 | from Utility.ByteStream import Writer 2 | from Utility.Utils import Utils 3 | 4 | 5 | class LogicOfferBundle(Writer): 6 | def encode(self): 7 | self.writeVInt(0) # Shop Offers Count 8 | for x in range(0): 9 | self.writeVInt(0) # Offer Items Count 10 | for x in range(0): 11 | self.writeVInt(0) # Offer Item ID 12 | self.writeVInt(0) # Offer Amount 13 | self.writeDataReference(16, 0) # Offer Character 14 | self.writeVInt(0) # Offer Item Extra Data 15 | self.writeVInt(0) # Offer Resource Type 16 | self.writeVInt(0) # Offer Cost 17 | self.writeVInt(0) # Offer Timer 18 | self.writeVInt(0) # Offer New Tag State 19 | self.writeVInt(0) # Offer Bundle Percentage Value 20 | self.writeBoolean(False) # Offer Purchased 21 | self.writeVInt(0) 22 | self.writeBoolean(False) # Daily Deals Offer 23 | self.writeVInt(0) # Offer Original Cost 24 | self.ChronosTextEntry(2, "") # Offer Text Entry 25 | self.writeBoolean(False) -------------------------------------------------------------------------------- /Logic/Entry/IntValueEntry.py: -------------------------------------------------------------------------------- 1 | from Utility.ByteStream import Writer 2 | 3 | 4 | class IntValueEntryLogicDailyData(Writer): 5 | def encode(self): 6 | self.writeVInt(9) # Home Events Count 7 | self.writeLong(1, False) # Daily Created Club State 8 | self.writeLong(2, False) # Daily Changed Location State 9 | self.writeLong(3, 0) # Tokens Gained 10 | self.writeLong(4, 0) # Trophies Gained 11 | self.writeLong(5, 0) # Star Tokens Gained 12 | self.writeLong(6, False) # Demo Account State 13 | self.writeLong(7, False) # Do Not Disturb State 14 | self.writeLong(8, 0) # Star Points Gained 15 | self.writeLong(9, False) # Star Points Enabled State 16 | 17 | 18 | class IntValueEntryLogicConfData(Writer): 19 | def encode(self): 20 | self.writeVInt(6) # Home Events Count 21 | self.writeLong(1, 41000000) # Menu Theme 22 | self.writeLong(3, 3) # Level Required For Unlock Friendly Games 23 | self.writeLong(5, False) # Temporarily Disable Shop 24 | self.writeLong(6, False) # Temporarily Disable Brawl Boxes 25 | self.writeLong(14, False) # Double Token Weekend 26 | self.writeLong(15, True) # Disable Content Creator Boost -------------------------------------------------------------------------------- /Packets/Messages/Client/Login/ClientHelloMessage.py: -------------------------------------------------------------------------------- 1 | from Packets.Messages.Server.Login.ServerHelloMessage import ServerHelloMessage 2 | from Utility.ByteStream import Reader 3 | 4 | 5 | class ClientHelloMessage(Reader): 6 | def __init__(self, client, player, initial_bytes): 7 | super().__init__(initial_bytes) 8 | self.player = player 9 | self.client = client 10 | 11 | 12 | def decode(self): 13 | self.Protocol = self.readInt() 14 | self.KeyVersion = self.readInt() 15 | self.Major = self.readInt() 16 | self.Minor = self.readInt() 17 | self.Build = self.readInt() 18 | self.ContentHash = self.readString() 19 | self.DeviceType = self.readInt() 20 | self.AppStore = self.readInt() 21 | print("Protocol:", self.Protocol) 22 | print("Key Version:", self.KeyVersion) 23 | print("Client Major:", self.Major) 24 | print("Client Minor:", self.Minor) 25 | print("Client Build:", self.Build) 26 | print("Content Hash:", self.ContentHash) 27 | print("Device Type:", self.DeviceType) 28 | print("App Store Type:", self.AppStore) 29 | 30 | 31 | def process(self): 32 | ServerHelloMessage(self.client, self.player).send() -------------------------------------------------------------------------------- /Packets/Messages/Server/Alliance/AllianceWarMessage.py: -------------------------------------------------------------------------------- 1 | from Utility.ByteStream import Writer 2 | 3 | 4 | class AllianceWarMessage(Writer): 5 | def __init__(self, client, player): 6 | super().__init__(client) 7 | self.id = 24776 8 | self.client = client 9 | self.player = player 10 | 11 | 12 | def encode(self): 13 | self.writeLong(0, 1) # Player ID 14 | self.writeVInt(1) # Your Club Faction 15 | 16 | 17 | # Club War Events Array 18 | self.writeVInt(1) # Count 19 | for x in range(1): 20 | self.writeVInt(0) 21 | self.writeVInt(0) # Event Column Index 22 | self.writeVInt(0) # Event Row Index 23 | self.writeVInt(1) # Club Faction 24 | self.writeDataReference(15, 0) # War Location ID 25 | self.writeVInt(1) # War Node State 26 | self.writeVInt(0) # War Node State Time Left 27 | self.writeVInt(9) # Faction Score 28 | self.writeArrayVInt([]) 29 | # Club War Events Array End 30 | 31 | 32 | # Club War Factions Array 33 | self.writeVInt(1) # Count 34 | for x in range(1): 35 | self.writeVInt(1) # Club Faction 36 | self.writeVInt(1) # Faction Score 37 | # Club War Factions Array End -------------------------------------------------------------------------------- /Packets/Messages/Server/Home/SeasonRewardsMessage.py: -------------------------------------------------------------------------------- 1 | from Utility.ByteStream import Writer 2 | 3 | 4 | class SeasonRewardsMessage(Writer): 5 | def __init__(self, client, player): 6 | super().__init__(client) 7 | self.id = 24123 8 | self.client = client 9 | self.player = player 10 | 11 | 12 | def encode(self): 13 | StarPointsTrophiesStart = [550,600,650,700,750,800,850,900,950,1000,1050,1100,1150,1200,1250,1300,1350,1400] 14 | StarPointsTrophiesEnd = [599,649,699,749,799,849,899,949,999,1049,1099,1149,1199,1249,1299,1349,1399,-1] 15 | StarPointsSeasonRewardAmount = [70,120,160,200,220,240,260,280,300,320,340,360,380,400,420,440,460,480] 16 | StarPointsTrophiesInReset = [525,550,575,600,625,650,675,700,725,750,775,800,825,850,875,900,925,950] 17 | self.writeVInt(len(StarPointsTrophiesStart)) # Index Count 18 | for StarPointsIndex in range(len(StarPointsTrophiesStart)): 19 | self.writeVInt(StarPointsTrophiesStart[StarPointsIndex]) # Minimum Trophies Index For Season Reward 20 | self.writeVInt(StarPointsTrophiesEnd[StarPointsIndex]) # Maximum Trophies Index For Season Reward 21 | self.writeVInt(StarPointsSeasonRewardAmount[StarPointsIndex]) # Season Star Points Reward Amount 22 | self.writeVInt(StarPointsTrophiesInReset[StarPointsIndex]) # Trophies After Season End -------------------------------------------------------------------------------- /Utility/Utils.py: -------------------------------------------------------------------------------- 1 | from datetime import datetime 2 | import string 3 | import random 4 | import time 5 | import numpy as np 6 | 7 | 8 | class Utils: 9 | connected_clients = {"ClientsCount": 0, "Clients": {}} 10 | 11 | 12 | def getLogicDataTable(self, GlobalID): 13 | return (GlobalID / 1000000 + (GlobalID >> 31)) - (GlobalID * 1125899907 >> 63) 14 | 15 | 16 | def getCurrentDate(self): 17 | result = time.localtime(int(time.time())) 18 | return (result.tm_year * 1000 + result.tm_yday) 19 | 20 | 21 | def getTimeForNextDay(self): 22 | result = time.localtime(int(time.time())) 23 | return (86400 - (result.tm_sec + (result.tm_min * 60) + (result.tm_hour * 3600))) 24 | 25 | 26 | def getCurrentTimeInSecondsSinceEpoch(self): 27 | result = int(time.time()) 28 | return result 29 | 30 | 31 | def getLobbyInfoCurrentDate(self): 32 | result = datetime.utcnow().strftime("%a %b %d %H:%M:%S UTC %Y") 33 | return result 34 | 35 | 36 | def getAccountCreatedDate(self): 37 | result = int(time.time()) 38 | return (result * 1000) 39 | 40 | 41 | def getServerTime(self): 42 | result = int(time.time() * 1000) 43 | return result 44 | 45 | 46 | def getBattleTime(self): 47 | result = int(time.time()) 48 | return result 49 | 50 | 51 | def EventTimer(self): 52 | result = time.localtime(int(time.time())) 53 | return (86400 - (result.tm_sec + (result.tm_min * 60) + (result.tm_hour * 3600))) 54 | -------------------------------------------------------------------------------- /Packets/Messages/Server/Alliance/AllianceDataMessage.py: -------------------------------------------------------------------------------- 1 | from Utility.ByteStream import Writer 2 | 3 | 4 | class AllianceDataMessage(Writer): 5 | def __init__(self, client, player, HighID, LowID): 6 | super().__init__(client) 7 | self.id = 24301 8 | self.client = client 9 | self.player = player 10 | self.HighID = HighID 11 | self.LowID = LowID 12 | 13 | 14 | def encode(self): 15 | self.writeBoolean(False) 16 | # Club Full Entry 17 | # Club Header Entry 18 | self.writeLong(self.HighID, self.LowID) # Club ID 19 | self.writeString("Club") # Club Name 20 | self.writeDataReference(8, 0) # Club Badge 21 | self.writeVInt(1) # Club Type 22 | self.writeVInt(1) # Club Members 23 | self.writeVInt(0) # Club Trophies 24 | self.writeVInt(0) # Club Required Trophies 25 | self.writeDataReference(0, -1) 26 | self.writeString("BR") # Club Region 27 | self.writeVInt(1) # Club Online Members 28 | # Club Header Entry End 29 | self.writeString("Club Description") # Club Description 30 | 31 | 32 | # Club Members Array 33 | self.writeVInt(1) # Club Members Count 34 | for x in range(1): 35 | self.writeLong(0, 1) # Player ID 36 | self.writeVInt(1) # Player Club Role 37 | self.writeVInt(0) # Player Trophies 38 | self.writeVInt(8) # Player Status 39 | self.writeVInt(0) # Player Status Timer 40 | self.writeBoolean(False) 41 | # Player Display Data 42 | self.writeString("Brawler") # Player Name 43 | self.writeVInt(100) 44 | self.writeVInt(28000000) # Player Profile Icon 45 | self.writeVInt(43000000) # Player Name Color 46 | # Player Display Data End 47 | # Club Members Array End 48 | # Club Full Entry End -------------------------------------------------------------------------------- /Packets/Messages/Server/Home/LeaderboardMessage.py: -------------------------------------------------------------------------------- 1 | from Utility.ByteStream import Writer 2 | 3 | 4 | class LeaderboardMessage(Writer): 5 | def __init__(self, client, player, isLocal, Type, BralwerID): 6 | super().__init__(client) 7 | self.id = 24403 8 | self.client = client 9 | self.player = player 10 | self.isLocal = isLocal 11 | self.Type = Type 12 | self.BralwerID = BralwerID 13 | 14 | 15 | def encode(self): 16 | self.writeVInt(self.Type) 17 | self.writeDataReference(16, self.BralwerID) 18 | self.writeString("BR") if self.isLocal == True else self.writeString() 19 | 20 | 21 | # Leaderboard Entry Array 22 | self.writeVInt(1) # Leaderboard Entry Count 23 | for x in range(1): 24 | self.writeLogicLong(0, 1) # Target ID 25 | self.writeVInt(0) 26 | self.writeVInt(0) # Target Trophies 27 | # Leaderboard Player Entry 28 | self.writeBoolean(True) # Leaderboard Player Entry 29 | self.writeString("Club") # Club Name 30 | # Player Display Data 31 | self.writeString("Brawler") # Player Name 32 | self.writeVInt(100) 33 | self.writeVInt(28000000) # Player Profile Icon 34 | self.writeVInt(43000000) # Player Name Color 35 | # Player Display Data End 36 | # Leaderboard Player Entry End 37 | # Leaderboard Alliance Entry 38 | self.writeBoolean(True) # Leaderboard Alliance Entry 39 | self.writeString("Club") # Club Name 40 | self.writeVInt(1) # Club Members Count 41 | self.writeDataReference(8, 0) # Club Badge 42 | # Leaderboard Alliance Entry End 43 | # Leaderboard Entry Array End 44 | 45 | 46 | self.writeVInt(0) 47 | self.writeVInt(1) # Leaderboard Entry Count 48 | self.writeVInt(0) 49 | self.writeVInt(0) # Leaderboard Global Region 50 | self.writeString("BR") # Leaderboard Local Region -------------------------------------------------------------------------------- /Packets/Messages/Server/Login/LoginOkMessage.py: -------------------------------------------------------------------------------- 1 | from Utility.ByteStream import Writer 2 | 3 | 4 | class LoginOkMessage(Writer): 5 | def __init__(self, client, player): 6 | super().__init__(client) 7 | self.id = 20104 8 | self.client = client 9 | self.player = player 10 | 11 | 12 | def encode(self): 13 | self.writeLong(0, 1) # Account ID 14 | self.writeLong(0, 1) # Home ID 15 | self.writeString("") # Pass Token 16 | self.writeString() # Facebook ID 17 | self.writeString() # Gamecenter ID 18 | self.writeInt(self.player.Major) # Server Major Version 19 | self.writeInt(self.player.Revision) # Server Build Version 20 | self.writeInt(self.player.Minor) # Content Version 21 | self.writeString("dev") # Environment 22 | self.writeInt(0) # Session Count 23 | self.writeInt(0) # Play Time Seconds 24 | self.writeInt(0) # Days Since Started Playing 25 | self.writeString("103121310241222") # Facebook Application ID 26 | self.writeString("") # Server Time 27 | self.writeString("") # Account Created Date 28 | self.writeInt(0) # Startup Cooldown 29 | self.writeString() # Google Service ID 30 | self.writeString("BR") # Login Country 31 | self.writeString() # Kunlun ID 32 | self.writeInt(2) # Tier 33 | self.writeString("") 34 | self.writeInt(2) # Url Entry Array Count 35 | self.writeString("https://game-assets.brawlstarsgame.com") 36 | self.writeString("http://a678dbc1c015a893c9fd-4e8cc3b1ad3a3c940c504815caefa967.r87.cf2.rackcdn.com") 37 | self.writeInt(2) # Url Entry Array Count 38 | self.writeString("https://raw.githubusercontent.com/IsaaSooBarr/Project-LaserScratch/main/Files/EventAssets/") # Event Assets 39 | self.writeString("https://24b999e6da07674e22b0-8209975788a0f2469e68e84405ae4fcf.ssl.cf2.rackcdn.com/event-assets") 40 | self.writeVInt(0) # Seconds Until Account Deletion 41 | self.writeCompressedString(b'') # Supercell ID Token 42 | self.writeBoolean(True,False) # Double Boolean 43 | self.writeString("") 44 | -------------------------------------------------------------------------------- /Packets/Messages/Server/Battle/StartLoadingMessage.py: -------------------------------------------------------------------------------- 1 | from Utility.ByteStream import Writer 2 | 3 | 4 | class StartLoadingMessage(Writer): 5 | def __init__(self, client, player): 6 | super().__init__(client) 7 | self.id = 20559 8 | self.client = client 9 | self.player = player 10 | 11 | 12 | def encode(self): 13 | self.writeInt(1) # Game Mode Total Players 14 | self.writeInt(0) 15 | self.writeInt(0) 16 | 17 | 18 | # Logic Player Array 19 | self.writeInt(1) # Players Count 20 | 21 | 22 | self.writeLong(0, 1) # Player ID 23 | self.writeVInt(1) # Player Index 24 | self.writeVInt(0) # Player Team 25 | self.writeVInt(0) 26 | self.writeInt(1000000) # ??? 27 | self.writeDataReference(16, 0) # Player Brawler 28 | self.writeDataReference(29, 0) # Player Skin 29 | # Logic Hero Upgrades Array 30 | self.writeBoolean(True) # Hero Upgrades 31 | self.writeVInt(0) # Brawler Power Level 32 | self.writeDataReference(23, -1) # Brawler Star Power 33 | # Logic Hero Upgrades Array End 34 | # Player Display Data 35 | self.writeString("Icaro") # Player Name 36 | self.writeVInt(100) 37 | self.writeVInt(28000000) # Player Profile Icon 38 | self.writeVInt(43000000) # Player Name Color 39 | # Player Display Data End 40 | # Logic Player Array End 41 | 42 | 43 | # Logic Vector Array 44 | self.writeInt(0) # Array 45 | for x in range(0): 46 | self.writeInt(0) 47 | self.writeInt(0) 48 | # Logic Vector Array End 49 | 50 | 51 | self.writeInt(0) # Count 52 | 53 | 54 | self.writeInt(1413965001) # Unknown 55 | self.writeVInt(1) 56 | self.writeVInt(1) # Map Blocks 57 | self.writeVInt(1) # Joystick Mode 58 | self.writeBoolean(True) # Battle Hints 59 | self.writeVInt(0) 60 | self.writeVInt(0) 61 | self.writeDataReference(15, 0) # Location ID 62 | -------------------------------------------------------------------------------- /Logic/Classes/LogicClientAvatar.py: -------------------------------------------------------------------------------- 1 | from Logic.Classes.LogicDataSlot import LogicDataSlotHeroOrItemUnlocked 2 | from Logic.Classes.LogicDataSlot import LogicDataSlotHeroScore 3 | from Logic.Classes.LogicDataSlot import LogicDataSlotHeroHighestScore 4 | from Logic.Classes.LogicDataSlot import LogicDataSlotResourceCount 5 | from Logic.Classes.LogicDataSlot import LogicDataSlotHeroPower 6 | from Logic.Classes.LogicDataSlot import LogicDataSlotHeroLevel 7 | from Logic.Classes.LogicDataSlot import LogicDataSlotCardCount 8 | from Logic.Classes.LogicDataSlot import LogicDataSlotHeroSeenState 9 | from Utility.ByteStream import Writer 10 | 11 | 12 | class LogicClientAvatar(Writer): 13 | def encode(self): 14 | self.writeLogicLong(0, 1) # Account ID 15 | self.writeLogicLong(0, 0) 16 | self.writeLogicLong(0, 0) 17 | self.writeStringReference("Brawler") # Player Name 18 | self.writeBoolean(True) # Registered Name State 19 | self.writeInt(-1) 20 | self.writeVInt(8) # Commodity Count 21 | 22 | 23 | # Unlocked Brawlers and Resources Array 24 | LogicDataSlotHeroOrItemUnlocked.encode(self) 25 | # Unlocked Brawlers and Resources Array End 26 | 27 | 28 | # Brawlers Trophies Array 29 | LogicDataSlotHeroScore.encode(self) 30 | # Brawlers Trophies Array End 31 | 32 | 33 | # Brawlers Highest Trophies Array 34 | LogicDataSlotHeroHighestScore.encode(self) 35 | # Brawlers Highest Trophies Array End 36 | 37 | 38 | # Highest Resources Amount Array 39 | LogicDataSlotResourceCount.encode(self) 40 | # Highest Resources Amount Array End 41 | 42 | 43 | # Brawlers Power Points Array 44 | LogicDataSlotHeroPower.encode(self) 45 | # Brawlers Power Points Array End 46 | 47 | 48 | # Brawlers Power Level Array 49 | LogicDataSlotHeroLevel.encode(self) 50 | # Brawlers Power Level Array End 51 | 52 | 53 | # Brawlers Star Powers Array 54 | LogicDataSlotCardCount.encode(self) 55 | # Brawlers Star Powers Array End 56 | 57 | 58 | # Brawlers Seem State Array 59 | LogicDataSlotHeroSeenState.encode(self) 60 | # Brawlers Seem State Array End 61 | 62 | 63 | self.writeVInt(0) # Player Gems 64 | self.writeVInt(0) # Player Free Gems 65 | self.writeVInt(1) # Player Experience Level 66 | self.writeVInt(100) 67 | self.writeVInt(0) # Cumulative Purchased Gems 68 | self.writeVInt(0) # Battles Count 69 | self.writeVInt(0) # Win Count 70 | self.writeVInt(0) # Lose Count 71 | self.writeVInt(0) # Win/Loose Streak 72 | self.writeVInt(0) # Npc Win Count 73 | self.writeVInt(0) # Npc Lose Count 74 | self.writeVInt(2) # Tutorial State -------------------------------------------------------------------------------- /Logic/Classes/LogicConfData.py: -------------------------------------------------------------------------------- 1 | from Logic.Entry.EventSlot import EventSlot 2 | from Logic.Entry.EventData import EventDataActiveEvent 3 | from Logic.Entry.EventData import EventDataUpcomingEvent 4 | from Logic.Entry.RelaseEntry import RelaseEntry 5 | from Logic.Entry.IntValueEntry import IntValueEntryLogicConfData 6 | from Utility.ByteStream import Writer 7 | from Utility.Utils import Utils 8 | 9 | 10 | class LogicConfData(Writer): 11 | def encode(self): 12 | self.writeVInt(Utils.getCurrentDate(self)) # Current Year and Day 13 | self.writeVInt(100) # Brawl Box Tokens 14 | self.writeVInt(10) # Shop Brawl Box Cost 15 | self.writeVInt(30) # Shop Big Box Cost 16 | self.writeVInt(3) # Shop Big Box Multipler 17 | self.writeVInt(80) # Shop Megabox Cost 18 | self.writeVInt(10) # Shop Megabox Multipler 19 | self.writeVInt(50) # Shop Token Doubler Cost 20 | self.writeVInt(1000) # Shop Token Doubler Amount 21 | self.writeVInt(550) # Minimum Brawler Trophies For Season Reset 22 | self.writeVInt(50) # Brawler Trophy Loss Percentage In Season Reset 23 | self.writeVInt(999900) # Token Limit Amount 24 | self.writeArrayVInt([0,30,80,170,350,0]) # Boxes With Guaranteed Brawlers Cost 25 | 26 | 27 | # Event Slots Array 28 | EventSlot.encode(self) 29 | # Event Slots Array End 30 | 31 | 32 | # Event Slots Data Array 33 | EventDataActiveEvent.encode(self) 34 | # Event Slots Data Array End 35 | 36 | 37 | # Upcoming Event Slots Data Array 38 | EventDataUpcomingEvent.encode(self) 39 | # Upcoming Event Slots Data Array End 40 | 41 | 42 | self.writeArrayVInt([20,35,75,140,290,480,800,1250]) # Brawler Coins Upgrade Cost 43 | self.writeArrayVInt([1,2,3,4,5,10,15,20]) # Highstakes Rewards 44 | self.writeArrayVInt([10,30,80]) # Event Tickets Cost 45 | self.writeArrayVInt([6,20,60]) # Event Tickets Amount 46 | self.writeArrayVInt([20,50,140,280]) # Coin Packs Cost 47 | self.writeArrayVInt([150,400,1200,2600]) # Coin Packs Amount 48 | self.writeVInt(0) # Coin Packs State 49 | self.writeVInt(200) # Maximun Battle Tokens 50 | self.writeVInt(20) # Tokens Gained In Refresh 51 | self.writeVInt(8640) # Tokens Refresh Timer 52 | self.writeVInt(10) # Big Box Star Tokens 53 | self.writeVInt(5) 54 | self.writeBoolean(False,False,False) # Unlocked Event Slots State 55 | self.writeVInt(50) 56 | self.writeVInt(604800) 57 | self.writeBoolean(True) # Shop Boxes Enabled State 58 | 59 | 60 | # Locked For Chronos Array 61 | RelaseEntry.encode(self) 62 | # Locked For Chronos Array End 63 | 64 | 65 | # Home Events Array 66 | IntValueEntryLogicConfData.encode(self) 67 | # Home Events Array End -------------------------------------------------------------------------------- /Logic/Classes/LogicDataSlot.py: -------------------------------------------------------------------------------- 1 | from Utility.ByteStream import Writer 2 | 3 | 4 | class LogicDataSlotHeroOrItemUnlocked(Writer): 5 | def encode(self): 6 | self.writeVInt(1 + 7) # Items Count 7 | for x in range(1): 8 | self.writeDataReference(23, x) # Item ID 9 | self.writeVInt(1) # Item Data 10 | self.writeDataReference(5, 1) # Resource ID 11 | self.writeVInt(0) # Tokens Amount 12 | self.writeDataReference(5, 5) # Resource ID 13 | self.writeVInt(0) # Chips Amount 14 | self.writeDataReference(5, 6) # Resource ID 15 | self.writeVInt(0) # Elixir Amount 16 | self.writeDataReference(5, 7) # Resource ID 17 | self.writeVInt(0) # Upgrade Tokens Amount 18 | self.writeDataReference(5, 8) # Resource ID 19 | self.writeVInt(0) # Coins Amount 20 | self.writeDataReference(5, 9) # Resource ID 21 | self.writeVInt(0) # Star Tokens Amount 22 | self.writeDataReference(5, 10) # Resource ID 23 | self.writeVInt(0) # Star Points Amount 24 | 25 | 26 | class LogicDataSlotHeroScore(Writer): 27 | def encode(self): 28 | self.writeVInt(0) # Brawlers Count 29 | for x in range(0): 30 | self.writeDataReference(16, 0) # Brawler ID 31 | self.writeVInt(0) # Brawler Trophies 32 | 33 | 34 | class LogicDataSlotHeroHighestScore(Writer): 35 | def encode(self): 36 | self.writeVInt(0) # Brawlers Count 37 | for x in range(0): 38 | self.writeDataReference(16, 0) # Brawler ID 39 | self.writeVInt(0) # Brawler Highest Trophies 40 | 41 | 42 | class LogicDataSlotResourceCount(Writer): 43 | def encode(self): 44 | self.writeVInt(0) # Resources Count 45 | for x in range(0): 46 | self.writeDataReference(5, 0) # Resource ID 47 | self.writeVInt(0) # Resource Amount 48 | 49 | 50 | class LogicDataSlotHeroPower(Writer): 51 | def encode(self): 52 | self.writeVInt(0) # Brawlers Count 53 | for x in range(0): 54 | self.writeDataReference(16, 0) # Brawler ID 55 | self.writeVInt(0) # Brawler Power Points Amount 56 | 57 | 58 | class LogicDataSlotHeroLevel(Writer): 59 | def encode(self): 60 | self.writeVInt(0) # Brawlers Count 61 | for x in range(0): 62 | self.writeDataReference(16, 0) # Brawler ID 63 | self.writeVInt(0) # Brawler Power Level 64 | 65 | 66 | class LogicDataSlotCardCount(Writer): 67 | def encode(self): 68 | self.writeVInt(0) # Items Count 69 | for x in range(0): 70 | self.writeDataReference(23, 0) # Item ID 71 | self.writeVInt(0) # Item Data 72 | 73 | 74 | class LogicDataSlotHeroSeenState(Writer): 75 | def encode(self): 76 | self.writeVInt(0) # Brawlers Count 77 | for x in range(0): 78 | self.writeDataReference(16, 0) # Brawler ID 79 | self.writeVInt(0) # Brawler Seem State -------------------------------------------------------------------------------- /Packets/Messages/Server/Home/PlayerProfileMessage.py: -------------------------------------------------------------------------------- 1 | from Utility.ByteStream import Writer 2 | 3 | 4 | class PlayerProfileMessage(Writer): 5 | def __init__(self, client, player, HighID, LowID): 6 | super().__init__(client) 7 | self.id = 24113 8 | self.client = client 9 | self.player = player 10 | self.HighID = HighID 11 | self.LowID = LowID 12 | 13 | 14 | def encode(self): 15 | # Player Profile 16 | self.writeLogicLong(self.HighID, self.LowID) # Player ID 17 | self.writeDataReference(0, -1) 18 | 19 | 20 | # Hero Entry Array 21 | self.writeVInt(1) # Brawlers Count 22 | for x in range(1): 23 | self.writeDataReference(16, x) # Brawler ID 24 | self.writeDataReference(29, -1) # Skin ID 25 | self.writeVInt(0) # Brawler Trophies 26 | self.writeVInt(0) # Brawler Trophies for Rank 27 | self.writeVInt(1) # Brawler Power Level 28 | # Hero Entry Array End 29 | 30 | 31 | # Stats Entry Array 32 | self.writeVInt(11) # Stats Count 33 | self.writeVInt(1) # Stats Index 34 | self.writeVInt(0) # 3 vs 3 Victories 35 | self.writeVInt(2) # Stats Index 36 | self.writeVInt(0) # Player Experience Points 37 | self.writeVInt(3) # Stats Index 38 | self.writeVInt(0) # Player Trophies 39 | self.writeVInt(4) # Stats Index 40 | self.writeVInt(0) # Player Highest Trophies 41 | self.writeVInt(5) # Stats Index 42 | self.writeVInt(1) # Unlocked Brawlers 43 | self.writeVInt(6) # Stats Index 44 | self.writeVInt(0) # Unknown 45 | self.writeVInt(7) # Stats Index 46 | self.writeVInt(28000000) # Player Profile Icon 47 | self.writeVInt(8) # Stats Index 48 | self.writeVInt(0) # Solo Victories 49 | self.writeVInt(9) # Stats Index 50 | self.writeVInt(0) # Best Robo Rumble Time 51 | self.writeVInt(10) # Stats Index 52 | self.writeVInt(0) # Best Time As Big Brawler 53 | self.writeVInt(11) # Stats Index 54 | self.writeVInt(0) # Duo Victories 55 | # Stats Entry Array End 56 | 57 | 58 | # Player Display Data 59 | self.writeString("Brawler") # Player Name 60 | self.writeVInt(100) 61 | self.writeVInt(28000000) # Player Profile Icon 62 | self.writeVInt(43000000) # Player Name Color 63 | # Player Display Data End 64 | # Player Profile End 65 | 66 | 67 | # Club Header Entry Array 68 | self.writeBoolean(True) # Joined In a Club 69 | self.writeLong(0, 1) # Club ID 70 | self.writeString("Club") # Club Name 71 | self.writeDataReference(8, 0) # Club Badge 72 | self.writeVInt(1) # Club Type 73 | self.writeVInt(1) # Club Members 74 | self.writeVInt(0) # Club Trophies 75 | self.writeVInt(0) # Club Required Trophies 76 | self.writeDataReference(0, 0) 77 | self.writeString("BR") # Club Region 78 | self.writeVInt(1) # Club Online Members 79 | # Club Header Entry Array End 80 | 81 | 82 | self.writeDataReference(25, 1) # Club Role -------------------------------------------------------------------------------- /Logic/Classes/LogicDailyData.py: -------------------------------------------------------------------------------- 1 | from Logic.Classes.LogicOfferBundle import LogicOfferBundle 2 | from Logic.Entry.AdStatus import AdStatus 3 | from Logic.Entry.IntValueEntry import IntValueEntryLogicDailyData 4 | from Logic.Entry.CooldownEntry import CooldownEntry 5 | from Utility.ByteStream import Writer 6 | from Utility.Utils import Utils 7 | 8 | 9 | class LogicDailyData(Writer): 10 | def encode(self): 11 | self.writeVInt(Utils.getCurrentDate(self)) # Current Year and Day 12 | self.writeVInt(Utils.getTimeForNextDay(self)) # Time Remaining For Next Day 13 | self.writeVInt(0) # Player Trophies 14 | self.writeVInt(0) # Player Highest Trophies 15 | self.writeVInt(0) # Player Daily Highest Trophies 16 | self.writeVInt(1) # Collected Trophy Road Reward 17 | self.writeVInt(0) # Player Experience Points 18 | self.writeDataReference(28, 0) # Player Profile Icon 19 | self.writeDataReference(43, 0) # Player Name Color 20 | self.writeArrayVInt([]) # Played Game Modes 21 | 22 | 23 | # Selected Skins Array 24 | SelectedSkins = [] 25 | self.writeVInt(len(SelectedSkins)) # Skins Count 26 | for i in range(len(SelectedSkins)): 27 | self.writeDataReference(29, i) # Selected Skin 28 | # Selected Skins Array End 29 | 30 | 31 | # Unlocked Skins Array 32 | UnlockedSkins = [] 33 | self.writeVInt(len(UnlockedSkins)) # Skins Count 34 | for i in range(len(UnlockedSkins)): 35 | self.writeDataReference(29, i) # Unlocked Skin 36 | # Unlocked Skins Array End 37 | 38 | 39 | self.writeVInt(0) # Leaderboard Region 40 | self.writeVInt(0) # Player Highest League Trophies 41 | self.writeVInt(0) # Tokens Used In Battles 42 | self.writeBoolean(False) # Token Limit Reached State 43 | self.writeVInt(1) # Control Mode 44 | self.writeBoolean(True) # Battle Hints 45 | self.writeVInt(0) # Tokens Remaining From Token Doubler 46 | self.writeVInt(0) # Season End Timer 47 | self.writeBoolean(False, False, False, True) # Shop Exclusive Offer and Token Doubler State 48 | self.writeVInt(0) # Token Doubler Seem State 49 | self.writeVInt(0) # Event Tickets Seem State 50 | self.writeVInt(0) # Coin Packs Seem State 51 | self.writeVInt(0) # Change Name Cost 52 | self.writeVInt(0) # Timer For the Next Name Change 53 | 54 | 55 | # Shop Offers Array 56 | LogicOfferBundle.encode(self) 57 | # Shop Offers Array End 58 | 59 | 60 | # Brawl Box Ad Status Array 61 | AdStatus.encode(self) 62 | # Brawl Box Ad Status Array End 63 | 64 | 65 | self.writeVInt(0) # Available Tokens From Battles 66 | self.writeVInt(0) # Timer For New Tokens 67 | self.writeArrayVInt([]) # Event Tickets Purchased Index 68 | self.writeVInt(0) # Player Event Tickets 69 | self.writeVInt(0) 70 | self.writeDataReference(16, 0) # Selected Brawler 71 | self.writeString("BR") # Player Location 72 | self.writeString() # Supported Content Creator 73 | 74 | 75 | # Home Events Array 76 | IntValueEntryLogicDailyData.encode(self) 77 | # Home Events Array End 78 | 79 | 80 | # Cooldown Entry Array 81 | CooldownEntry.encode(self) 82 | # Cooldown Entry Array End -------------------------------------------------------------------------------- /main.py: -------------------------------------------------------------------------------- 1 | import logging 2 | import socket 3 | import time 4 | import os 5 | from threading import * 6 | from Logic.Device import Device 7 | from Logic.Player import Players 8 | from Utility.Utils import Utils 9 | from Packets.LogicLaserFactory import AvailablePackets 10 | from Packets.Messages.Server.Home.LobbyInfoMessage import LobbyInfoMessage 11 | 12 | 13 | def _(*args): 14 | print('[INFO]', end=' ') 15 | for arg in args: 16 | print(arg, end=' ') 17 | print() 18 | 19 | 20 | 21 | class Server: 22 | Clients = {"ClientCounts": 0, "Clients": {}} 23 | ThreadCount = 0 24 | 25 | 26 | def __init__(self, ip: str, port: int): 27 | self.server = socket.socket() 28 | self.port = port 29 | self.ip = ip 30 | 31 | 32 | def start(self): 33 | self.server.bind((self.ip, self.port)) 34 | _(f'Server started! Ip: {self.ip}, Port: {self.port}') 35 | while True: 36 | self.server.listen() 37 | client, address = self.server.accept() 38 | _(f'New connection! Ip: {address[0]}') 39 | ClientThread(client, address).start() 40 | Utils.connected_clients['ClientsCount'] += 1 41 | 42 | 43 | class ClientThread(Thread): 44 | def __init__(self, client, address): 45 | super().__init__() 46 | self.client = client 47 | self.address = address 48 | self.device = Device(self.client) 49 | self.player = Players(self.device) 50 | 51 | 52 | def recvall(self, length: int): 53 | data = b'' 54 | while len(data) < length: 55 | s = self.client.recv(length) 56 | if not s: 57 | print("Receive Error!") 58 | break 59 | data += s 60 | return data 61 | 62 | 63 | def run(self): 64 | LastPacketRecived = time.time() 65 | try: 66 | while True: 67 | header = self.client.recv(7) 68 | if len(header) > 0: 69 | LastPacketRecived = time.time() 70 | PacketID = int.from_bytes(header[:2], 'big') 71 | PacketLenght = int.from_bytes(header[2:5], 'big') 72 | PacketData = self.recvall(PacketLenght) 73 | LobbyInfoMessage(self.client, self.player, Utils.connected_clients['ClientsCount']).send() 74 | if PacketID in AvailablePackets: 75 | PacketName = AvailablePackets[PacketID].__name__ 76 | _(f'Packet {PacketID}: {PacketName} was received!') 77 | message = AvailablePackets[PacketID](self.client, self.player, PacketData) 78 | message.decode() 79 | message.process() 80 | if PacketID == 10101: 81 | Server.Clients["Clients"][str(self.player.low_id)] = {"SocketInfo": self.client} 82 | Server.Clients["ClientCounts"] = Server.ThreadCount 83 | self.player.ClientDict = Server.Clients 84 | else: 85 | _(f'Packet {PacketID} is not handled!') 86 | if time.time() - LastPacketRecived > 10: 87 | print(f"[INFO] Ip: {self.address[0]} disconnected!") 88 | self.client.close() 89 | break 90 | except ConnectionAbortedError: 91 | print(f"[INFO] Ip: {self.address[0]} disconnected!") 92 | self.client.close() 93 | except ConnectionResetError: 94 | print(f"[INFO] Ip: {self.address[0]} disconnected!") 95 | self.client.close() 96 | except TimeoutError: 97 | print(f"[INFO] Ip: {self.address[0]} disconnected!") 98 | self.client.close() 99 | 100 | 101 | if __name__ == '__main__': 102 | server = Server('0.0.0.0', 9339) 103 | server.start() -------------------------------------------------------------------------------- /Packets/Messages/Client/Login/LoginMessage.py: -------------------------------------------------------------------------------- 1 | from Packets.Messages.Server.Login.LoginOkMessage import LoginOkMessage 2 | from Packets.Messages.Server.Home.OwnHomeDataMessage import OwnHomeDataMessage 3 | from Packets.Messages.Server.Alliance.MyAllianceMessage import MyAllianceMessage 4 | from Packets.Messages.Server.Alliance.AllianceWarMessage import AllianceWarMessage 5 | from Utility.ByteStream import Reader 6 | 7 | 8 | class LoginMessage(Reader): 9 | def __init__(self, client, player, initial_bytes): 10 | super().__init__(initial_bytes) 11 | self.player = player 12 | self.client = client 13 | 14 | 15 | def decode(self): 16 | self.player.high_id = self.readInt() 17 | self.player.low_id = self.readInt() 18 | self.player.token = self.readString() 19 | self.player.Major = self.readInt() 20 | self.player.Revision = self.readInt() 21 | self.player.Minor = self.readInt() 22 | self.FingerprintSHA = self.readString() 23 | Unknown1 = self.readString() 24 | self.DeviceID = self.readString() 25 | Unknown2 = self.readString() 26 | self.Device = self.readString() 27 | self.PreferredLanguage = self.readDataReference()[1] 28 | self.PreferredDeviceLanguage = self.readString() 29 | self.DeviceUUID = self.readString() 30 | self.OSVersion = self.readString() 31 | self.isAndroid = self.readBoolean() 32 | Unknown3 = self.readStringReference() 33 | self.AndroidID = self.readStringReference() 34 | Unknown4 = self.readStringReference() 35 | self.isAdvertisingEnabled = self.readBoolean() 36 | Unknown5 = self.readString() 37 | Unknown6 = self.readInt() 38 | self.AppStore = self.readVInt() 39 | Unknown7 = self.readStringReference() 40 | Unknown8 = self.readStringReference() 41 | self.AppVersion = self.readStringReference() 42 | Unknown9 = self.readStringReference() 43 | Unknown10 = self.readStringReference() 44 | self.TencentPlatform = self.readVInt() 45 | Unknown11 = self.readStringReference() 46 | Unknown12 = self.readStringReference() 47 | Unknown13 = self.readStringReference() 48 | print("Account HighID:", self.player.high_id) 49 | print("Account LowID:", self.player.low_id) 50 | print("Pass Token:", self.player.token) 51 | print("Client Major:", self.player.Major) 52 | print("Client Content:", self.player.Revision) 53 | print("Client Build:", self.player.Minor) 54 | print("Resource SHA:", self.FingerprintSHA) 55 | print("Unknown:", Unknown1) 56 | print("Device ID:", self.DeviceID) 57 | print("Unknown:", Unknown2) 58 | print("Device Model:", self.Device) 59 | print("App Language:", self.PreferredLanguage) 60 | print("Device Language:", self.PreferredDeviceLanguage) 61 | print("Device UUID:", self.DeviceUUID) 62 | print("OS Version:", self.OSVersion) 63 | print("isAndroid:", self.isAndroid) 64 | print("Unknown:", Unknown3) 65 | print("Android ID:", self.AndroidID) 66 | print("Unknown:", Unknown4) 67 | print("Advertising Enabled:", self.isAdvertisingEnabled) 68 | print("Unknown:", Unknown5) 69 | print("Unknown:", Unknown6) 70 | print("App Store Type:", self.AppStore) 71 | print("Unknown:", Unknown7) 72 | print("Unknown:", Unknown8) 73 | print("App Version:", self.AppVersion) 74 | print("Unknown:", Unknown9) 75 | print("Unknown:", Unknown10) 76 | print("Tencent Platform:", self.TencentPlatform) 77 | print("Unknown:", Unknown11) 78 | print("Unknown:", Unknown12) 79 | print("Unknown:", Unknown13) 80 | 81 | 82 | def process(self): 83 | LoginOkMessage(self.client, self.player).send() 84 | OwnHomeDataMessage(self.client, self.player).send() 85 | MyAllianceMessage(self.client, self.player).send() 86 | AllianceWarMessage(self.client, self.player).send() -------------------------------------------------------------------------------- /Packets/Messages/Server/Battle/BattleEndMessage.py: -------------------------------------------------------------------------------- 1 | from Utility.ByteStream import Writer 2 | 3 | 4 | class BattleEndMessage(Writer): 5 | def __init__(self, client, player, Type): 6 | super().__init__(client) 7 | self.id = 23456 8 | self.client = client 9 | self.player = player 10 | self.Type = Type 11 | 12 | 13 | def encode(self): 14 | self.writeVInt(self.Type) # Battle End Game Mode 15 | self.writeVInt(self.player.BattleResult) # Battle Result 16 | self.writeVInt(0) # Tokens Gained 17 | self.writeVInt(0) # Trophies Result 18 | self.writeVInt(0) # Doubled Tokens 19 | self.writeVInt(0) # Double Token Weekend 20 | self.writeVInt(0) # Token Doubler Remaining 21 | self.writeVInt(0) # Ticketed Events Extra Data 22 | self.writeBoolean(False,False,False,False,False,False) # Battle End Type 23 | 24 | 25 | # Player Entry Array 26 | self.writeVInt(self.player.BattlePlayers) # Battle Players 27 | self.writeBoolean(True,False,False) # Team And Star Player Type 28 | self.writeDataReference(16, self.player.BrawlerID) # Player Brawler 29 | self.writeDataReference(29, self.player.SkinID) # Player Skin 30 | self.writeVInt(0) # Brawler Trophies 31 | self.writeVInt(1) # Brawler Power Level 32 | self.writeBoolean(True) # IsPlayer Array 33 | self.writeLong(0, 1) # Player ID 34 | # Player Display Data 35 | self.writeString("Icaro") # Player Name 36 | self.writeVInt(100) 37 | self.writeVInt(28000000) # Player Profile Icon 38 | self.writeVInt(43000000) # Player Name Color 39 | # Player Display Data End 40 | 41 | 42 | BotName = [self.player.Bot1Name, self.player.Bot2Name, self.player.Bot3Name, self.player.Bot4Name, self.player.Bot5Name, self.player.Bot6Name, self.player.Bot7Name, self.player.Bot8Name, self.player.Bot9Name] 43 | BotTeam = [self.player.Bot1Team, self.player.Bot2Team, self.player.Bot3Team, self.player.Bot4Team, self.player.Bot5Team, self.player.Bot6Team, self.player.Bot7Team, self.player.Bot8Team, self.player.Bot9Team] 44 | BotBrawler = [self.player.Bot1Brawler, self.player.Bot2Brawler, self.player.Bot3Brawler, self.player.Bot4Brawler, self.player.Bot5Brawler, self.player.Bot6Brawler, self.player.Bot7Brawler, self.player.Bot8Brawler, self.player.Bot9Brawler] 45 | for PlayerIndex in range(self.player.BattlePlayers - 1): 46 | if self.player.PlayerTeam == 0: 47 | if BotTeam[PlayerIndex] == 0: 48 | self.writeBoolean(False,False,False) # Team And Star Player Type 49 | else: 50 | self.writeBoolean(False,True,False) # Team And Star Player Type 51 | else: 52 | if BotTeam[PlayerIndex] == 0: 53 | self.writeBoolean(False,True,False) # Team And Star Player Type 54 | else: 55 | self.writeBoolean(False,False,False) # Team And Star Player Type 56 | self.writeDataReference(16, BotBrawler[PlayerIndex]) # Player Brawler 57 | self.writeDataReference(29, -1) # Player Skin 58 | self.writeVInt(0) # Brawler Trophies 59 | self.writeVInt(1) # Brawler Power Level 60 | self.writeBoolean(False) # IsPlayer Array 61 | # Player Display Data 62 | self.writeString(BotName[PlayerIndex]) # Player Name 63 | self.writeVInt(100) 64 | self.writeVInt(28000000) # Player Profile Icon 65 | self.writeVInt(43000000) # Player Name Color 66 | # Player Display Data End 67 | # Player Entry Array End 68 | 69 | 70 | # Experience Entry Array 71 | self.writeVInt(2) # Count 72 | self.writeVInt(0) # Normal Experience ID 73 | self.writeVInt(0) # Normal Experience Gained 74 | self.writeVInt(8) # Star Player Experience ID 75 | self.writeVInt(0) # Star Player Experience Gained 76 | # Experience Entry Array End 77 | 78 | 79 | # Milestone Rewards Array 80 | self.writeVInt(0) # Milestones Count 81 | for x in range(0): 82 | self.writeDataReference(39, 0) # Milestones Index 83 | # Milestone Rewards Array End 84 | 85 | 86 | # Milestone Progress Array 87 | self.writeVInt(2) # Count 88 | self.writeVInt(1) # Milestone ID 89 | self.writeVInt(0) # Brawler Trophies 90 | self.writeVInt(0) # Brawler Highest Trophies 91 | self.writeVInt(5) # Milestone ID 92 | self.writeVInt(0) # Player Experience Points 93 | self.writeVInt(0) # Player Experience Points 94 | # Milestone Progress Array End 95 | 96 | 97 | self.writeDataReference(28, 0) # Player Profile Icon 98 | 99 | 100 | self.writeBoolean(False) # Play Again -------------------------------------------------------------------------------- /Packets/LogicLaserFactory.py: -------------------------------------------------------------------------------- 1 | from Packets.Messages.Client.Home.AskPlayerJWTokenMessage import AskPlayerJWTokenMessage 2 | from Packets.Messages.Client.Login.ClientCryptoErrorMessage import ClientCryptoErrorMessage 3 | from Packets.Messages.Client.Login.ClientHelloMessage import ClientHelloMessage 4 | from Packets.Messages.Client.Login.LoginMessage import LoginMessage 5 | from Packets.Messages.Client.Login.LoginUsingSessionMessage import LoginUsingSessionMessage 6 | from Packets.Messages.Client.Login.CreateAccountMessage import CreateAccountMessage 7 | from Packets.Messages.Client.Home.ClientCapabilitiesMessage import ClientCapabilitiesMessage 8 | from Packets.Messages.Client.Home.KeepAliveMessage import KeepAliveMessage 9 | from Packets.Messages.Client.Home.UdpCheckConnectionMessage import UdpCheckConnectionMessage 10 | from Packets.Messages.Client.Home.AnalyticEventMessage import AnalyticEventMessage 11 | from Packets.Messages.Client.Login.AuthenticationCheckMessage import AuthenticationCheckMessage 12 | from Packets.Messages.Client.Login.SetDeviceTokenMessage import SetDeviceTokenMessage 13 | from Packets.Messages.Client.Login.ResetAccountMessage import ResetAccountMessage 14 | from Packets.Messages.Client.Battle.GoHomeMessage import GoHomeMessage 15 | from Packets.Messages.Client.Home.ReportUserMessage import ReportUserMessage 16 | from Packets.Messages.Client.Login.AccountSwitchedMessage import AccountSwitchedMessage 17 | from Packets.Messages.Client.Alliance.ReportAllianceStreamMessage import ReportAllianceStreamMessage 18 | from Packets.Messages.Client.Login.UnlockAccountMessage import UnlockAccountMessage 19 | from Packets.Messages.Client.Billing.AppleBillingRequestMessage import AppleBillingRequestMessage 20 | from Packets.Messages.Client.Billing.GoogleBillingRequestMessage import GoogleBillingRequestMessage 21 | from Packets.Messages.Client.Billing.TencentBillingRequestMessage import TencentBillingRequestMessage 22 | from Packets.Messages.Client.Billing.CafeBazaarBillingRequestMessage import CafeBazaarBillingRequestMessage 23 | from Packets.Messages.Client.Billing.KunlunBillingRequestMessage import KunlunBillingRequestMessage 24 | from Packets.Messages.Client.Billing.BillingCancelledByClientMessage import BillingCancelledByClientMessage 25 | ### TODO ### 26 | from Packets.Messages.Client.Battle.MatchmakeRequestMessage import MatchmakeRequestMessage 27 | from Packets.Messages.Client.Battle.CancelMatchMakingMessage import CancelMatchMakingMessage 28 | from Packets.Messages.Client.Battle.GoHomeFromOfflinePractiseMessage import GoHomeFromOfflinePractiseMessage 29 | from Packets.Messages.Client.Battle.AskForBattleEndMessage import AskForBattleEndMessage 30 | from Packets.Messages.Client.Home.GetPlayerProfileMessage import GetPlayerProfileMessage 31 | from Packets.Messages.Client.Home.GetSeasonRewardsMessage import GetSeasonRewardsMessage 32 | from Packets.Messages.Client.Alliance.AskForAllianceDataMessage import AskForAllianceDataMessage 33 | from Packets.Messages.Client.Gameroom.TeamCreateMessage import TeamCreateMessage 34 | from Packets.Messages.Client.Gameroom.TeamLeaveMessage import TeamLeaveMessage 35 | from Packets.Messages.Client.Gameroom.TeamChangeMemberSettingsMessage import TeamChangeMemberSettingsMessage 36 | from Packets.Messages.Client.Gameroom.TeamSetMemberReadyMessage import TeamSetMemberReadyMessage 37 | from Packets.Messages.Client.Gameroom.TeamMemberStatusMessage import TeamMemberStatusMessage 38 | from Packets.Messages.Client.Gameroom.TeamSetEventMessage import TeamSetEventMessage 39 | from Packets.Messages.Client.Gameroom.TeamSetLocationMessage import TeamSetLocationMessage 40 | from Packets.Messages.Client.Home.PlayerStatusMessage import PlayerStatusMessage 41 | from Packets.Messages.Client.Home.GetLeaderboardMessage import GetLeaderboardMessage 42 | 43 | 44 | AvailablePackets = { 45 | 10055: AskPlayerJWTokenMessage, 46 | 10099: ClientCryptoErrorMessage, 47 | 10100: ClientHelloMessage, 48 | 10101: LoginMessage, 49 | 10102: LoginUsingSessionMessage, 50 | 10103: CreateAccountMessage, 51 | 10107: ClientCapabilitiesMessage, 52 | 10108: KeepAliveMessage, 53 | 10109: UdpCheckConnectionMessage, 54 | 10110: AnalyticEventMessage, 55 | 10112: AuthenticationCheckMessage, 56 | 10113: SetDeviceTokenMessage, 57 | 10116: ResetAccountMessage, 58 | 10117: ReportUserMessage, 59 | 10118: AccountSwitchedMessage, 60 | 10119: ReportAllianceStreamMessage, 61 | 10121: UnlockAccountMessage, 62 | 10150: AppleBillingRequestMessage, 63 | 10151: GoogleBillingRequestMessage, 64 | 10152: TencentBillingRequestMessage, 65 | 10153: CafeBazaarBillingRequestMessage, 66 | 10159: KunlunBillingRequestMessage, 67 | 10160: BillingCancelledByClientMessage, 68 | ### TODO ### 69 | 14101: GoHomeMessage, 70 | 14103: MatchmakeRequestMessage, 71 | 14106: CancelMatchMakingMessage, 72 | 14109: GoHomeFromOfflinePractiseMessage, 73 | 14110: AskForBattleEndMessage, 74 | 14113: GetPlayerProfileMessage, 75 | 14277: GetSeasonRewardsMessage, 76 | 14302: AskForAllianceDataMessage, 77 | 14350: TeamCreateMessage, 78 | 14353: TeamLeaveMessage, 79 | 14354: TeamChangeMemberSettingsMessage, 80 | 14355: TeamSetMemberReadyMessage, 81 | 14361: TeamMemberStatusMessage, 82 | 14362: TeamSetEventMessage, 83 | 14363: TeamSetLocationMessage, 84 | 14366: PlayerStatusMessage, 85 | 14403: GetLeaderboardMessage, 86 | } 87 | -------------------------------------------------------------------------------- /Logic/Entry/EventData.py: -------------------------------------------------------------------------------- 1 | from Utility.ByteStream import Writer 2 | from Utility.Utils import Utils 3 | 4 | 5 | class EventSlots: 6 | EventsData = [ 7 | { 8 | 'EventIndex': 1, 9 | 'NewEventReward': 10, 10 | 'LocationID': 7, 11 | 'MapStatus': 2, 12 | 'TextEntry': None, 13 | 'Modifiers': [] 14 | }, 15 | 16 | 17 | 18 | { 19 | 'EventIndex': 2, 20 | 'NewEventReward': 10, 21 | 'LocationID': 13, 22 | 'MapStatus': 2, 23 | 'TextEntry': None, 24 | 'Modifiers': [] 25 | }, 26 | 27 | 28 | 29 | { 30 | 'EventIndex': 3, 31 | 'NewEventReward': 10, 32 | 'LocationID': 24, 33 | 'MapStatus': 2, 34 | 'TextEntry': None, 35 | 'Modifiers': [] 36 | }, 37 | 38 | 39 | 40 | { 41 | 'EventIndex': 4, 42 | 'NewEventReward': 10, 43 | 'LocationID': 5, 44 | 'MapStatus': 2, 45 | 'TextEntry': None, 46 | 'Modifiers': [] 47 | }, 48 | 49 | 50 | 51 | { 52 | 'EventIndex': 5, 53 | 'NewEventReward': 0, 54 | 'LocationID': 34, 55 | 'MapStatus': 0, 56 | 'TextEntry': None, 57 | 'Modifiers': [] 58 | }, 59 | 60 | 61 | 62 | 63 | { 64 | 'EventIndex': 7, 65 | 'NewEventReward': 2, 66 | 'LocationID': 21, 67 | 'MapStatus': 2, 68 | 'TextEntry': "TID_WEEKEND_EVENT", 69 | 'Modifiers': [] 70 | } 71 | ] 72 | 73 | 74 | ComingUpEventsData = [ 75 | { 76 | 'EventIndex': 1, 77 | 'NewEventReward': 10, 78 | 'LocationID': 7, 79 | 'MapStatus': 2, 80 | 'TextEntry': None, 81 | 'Modifiers': [] 82 | }, 83 | 84 | 85 | 86 | { 87 | 'EventIndex': 2, 88 | 'NewEventReward': 10, 89 | 'LocationID': 13, 90 | 'MapStatus': 2, 91 | 'TextEntry': None, 92 | 'Modifiers': [] 93 | }, 94 | 95 | 96 | 97 | { 98 | 'EventIndex': 3, 99 | 'NewEventReward': 10, 100 | 'LocationID': 24, 101 | 'MapStatus': 2, 102 | 'TextEntry': None, 103 | 'Modifiers': [] 104 | }, 105 | 106 | 107 | 108 | { 109 | 'EventIndex': 4, 110 | 'NewEventReward': 10, 111 | 'LocationID': 5, 112 | 'MapStatus': 2, 113 | 'TextEntry': None, 114 | 'Modifiers': [] 115 | }, 116 | 117 | 118 | 119 | { 120 | 'EventIndex': 5, 121 | 'NewEventReward': 0, 122 | 'LocationID': 34, 123 | 'MapStatus': 0, 124 | 'TextEntry': None, 125 | 'Modifiers': [] 126 | }, 127 | 128 | 129 | 130 | 131 | { 132 | 'EventIndex': 7, 133 | 'NewEventReward': 2, 134 | 'LocationID': 21, 135 | 'MapStatus': 2, 136 | 'TextEntry': "TID_WEEKEND_EVENT", 137 | 'Modifiers': [] 138 | } 139 | ] 140 | 141 | 142 | class EventDataActiveEvent(Writer): 143 | def encode(self): 144 | EventsCount = len(EventSlots.EventsData) 145 | self.writeVInt(EventsCount) # Event Slots Count 146 | for map in EventSlots.EventsData: 147 | self.writeVInt(0) 148 | self.writeVInt(map['EventIndex']) # Event ID 149 | self.writeVInt(0) # New Event Timer 150 | self.writeVInt(Utils.EventTimer(self)) # Event Timer 151 | self.writeVInt(map['NewEventReward']) # New Event Reward Amount 152 | self.writeDataReference(15, map['LocationID']) # Location ID 153 | self.writeVInt(map['MapStatus']) # Event Status 154 | self.writeString(map['TextEntry']) # Event Text Entry 155 | self.writeVInt(0) # Boxes Purchased 156 | self.writeArrayVInt(map['Modifiers']) # Event Mofifiers 157 | self.writeVInt(0) # Ticketed Events Difficulty 158 | 159 | 160 | class EventDataUpcomingEvent(Writer): 161 | def encode(self): 162 | EventsCount = len(EventSlots.ComingUpEventsData) 163 | self.writeVInt(EventsCount) # Event Slots Count 164 | for map in EventSlots.ComingUpEventsData: 165 | self.writeVInt(0) 166 | self.writeVInt(map['EventIndex']) # Event ID 167 | self.writeVInt(Utils.EventTimer(self)) # New Event Timer 168 | self.writeVInt(Utils.EventTimer(self)) # Event Timer 169 | self.writeVInt(map['NewEventReward']) # New Event Reward Amount 170 | self.writeDataReference(15, map['LocationID']) # Location ID 171 | self.writeVInt(map['MapStatus']) # Event Status 172 | self.writeString(map['TextEntry']) # Event Text Entry 173 | self.writeVInt(0) # Boxes Purchased 174 | self.writeArrayVInt(map['Modifiers']) # Event Mofifiers 175 | self.writeVInt(0) # Ticketed Events Difficulty -------------------------------------------------------------------------------- /Packets/Messages/Client/Battle/AskForBattleEndMessage.py: -------------------------------------------------------------------------------- 1 | from Packets.Messages.Server.Battle.BattleEndMessage import BattleEndMessage 2 | from Utility.ByteStream import Reader 3 | 4 | 5 | class AskForBattleEndMessage(Reader): 6 | def __init__(self, client, player, initial_bytes): 7 | super().__init__(initial_bytes) 8 | self.player = player 9 | self.client = client 10 | 11 | 12 | def decode(self): 13 | self.player.BattleResult = self.readVInt() 14 | self.readVInt() 15 | self.player.Rank = self.readVInt() 16 | self.Map = self.readDataReference()[1] # Locations CsvID 17 | self.BattlePlayers = self.readVInt() # Battle End Players 18 | 19 | 20 | self.player.BrawlerID = self.readDataReference()[1] 21 | self.player.SkinID = self.readDataReference()[1] 22 | self.PlayerTeam = self.readVInt() 23 | self.IsPlayer = self.readBoolean() 24 | self.PlayerName = self.readString() 25 | 26 | 27 | self.Bot1Brawler = self.readDataReference()[1] 28 | self.Bot1Skin = self.readDataReference()[1] 29 | self.Bot1Team = self.readVInt() 30 | self.Bot1IsPlayer = self.readBoolean() 31 | self.Bot1Name = self.readString() 32 | 33 | 34 | self.Bot2Brawler = self.readDataReference()[1] 35 | self.Bot2Skin = self.readDataReference()[1] 36 | self.Bot2Team = self.readVInt() 37 | self.Bot2IsPlayer = self.readBoolean() 38 | self.Bot2Name = self.readString() 39 | 40 | 41 | self.Bot3Brawler = self.readDataReference()[1] 42 | self.Bot3Skin = self.readDataReference()[1] 43 | self.Bot3Team = self.readVInt() 44 | self.Bot3IsPlayer = self.readBoolean() 45 | self.Bot3Name = self.readString() 46 | 47 | 48 | self.Bot4Brawler = self.readDataReference()[1] 49 | self.Bot4Skin = self.readDataReference()[1] 50 | self.Bot4Team = self.readVInt() 51 | self.Bot4IsPlayer = self.readBoolean() 52 | self.Bot4Name = self.readString() 53 | 54 | 55 | self.Bot5Brawler = self.readDataReference()[1] 56 | self.Bot5Skin = self.readDataReference()[1] 57 | self.Bot5Team = self.readVInt() 58 | self.Bot5IsPlayer = self.readBoolean() 59 | self.Bot5Name = self.readString() 60 | 61 | 62 | self.Bot6Brawler = self.readDataReference()[1] 63 | self.Bot6Skin = self.readDataReference()[1] 64 | self.Bot6Team = self.readVInt() 65 | self.Bot6IsPlayer = self.readBoolean() 66 | self.Bot6Name = self.readString() 67 | 68 | 69 | self.Bot7Brawler = self.readDataReference()[1] 70 | self.Bot7Skin = self.readDataReference()[1] 71 | self.Bot7Team = self.readVInt() 72 | self.Bot7IsPlayer = self.readBoolean() 73 | self.Bot7Name = self.readString() 74 | 75 | 76 | self.Bot8Brawler = self.readDataReference()[1] 77 | self.Bot8Skin = self.readDataReference()[1] 78 | self.Bot8Team = self.readVInt() 79 | self.Bot8IsPlayer = self.readBoolean() 80 | self.Bot8Name = self.readString() 81 | 82 | 83 | self.Bot9Brawler = self.readDataReference()[1] 84 | self.Bot9Skin = self.readDataReference()[1] 85 | self.Bot9Team = self.readVInt() 86 | self.Bot9IsPlayer = self.readBoolean() 87 | self.Bot9Name = self.readString() 88 | 89 | 90 | def process(self): 91 | self.player.Bot1Name = self.Bot1Name 92 | self.player.Bot2Name = self.Bot2Name 93 | self.player.Bot3Name = self.Bot3Name 94 | self.player.Bot4Name = self.Bot4Name 95 | self.player.Bot5Name = self.Bot5Name 96 | self.player.Bot6Name = self.Bot6Name 97 | self.player.Bot7Name = self.Bot7Name 98 | self.player.Bot8Name = self.Bot8Name 99 | self.player.Bot9Name = self.Bot9Name 100 | self.player.Bot1Brawler = self.Bot1Brawler 101 | self.player.Bot2Brawler = self.Bot2Brawler 102 | self.player.Bot3Brawler = self.Bot3Brawler 103 | self.player.Bot4Brawler = self.Bot4Brawler 104 | self.player.Bot5Brawler = self.Bot5Brawler 105 | self.player.Bot6Brawler = self.Bot6Brawler 106 | self.player.Bot7Brawler = self.Bot7Brawler 107 | self.player.Bot8Brawler = self.Bot8Brawler 108 | self.player.Bot9Brawler = self.Bot9Brawler 109 | self.player.PlayerTeam = self.PlayerTeam 110 | self.player.Bot1Team = self.Bot1Team 111 | self.player.Bot2Team = self.Bot2Team 112 | self.player.Bot3Team = self.Bot3Team 113 | self.player.Bot4Team = self.Bot4Team 114 | self.player.Bot5Team = self.Bot5Team 115 | self.player.Bot6Team = self.Bot6Team 116 | self.player.Bot7Team = self.Bot7Team 117 | self.player.Bot8Team = self.Bot8Team 118 | self.player.Bot9Team = self.Bot9Team 119 | self.player.BattlePlayers = self.BattlePlayers 120 | if self.BattlePlayers == 10 and self.Bot1Team == 0: 121 | self.Type = 5 122 | elif self.BattlePlayers == 10: 123 | self.Type = 2 124 | elif self.BattlePlayers == 3 and self.Map in [27, 29, 39, 68]: 125 | self.Type = 3 126 | elif self.BattlePlayers == 3 and self.Map in [57, 67, 133, 269]: 127 | self.Type = 6 128 | elif self.BattlePlayers == 6 and self.Map in [21, 30, 65, 66, 119, 120]: 129 | self.Type = 4 130 | else: 131 | self.Type = 1 132 | BattleEndMessage(self.client, self.player, self.Type).send() -------------------------------------------------------------------------------- /Utility/ByteStream.py: -------------------------------------------------------------------------------- 1 | from io import BufferedReader, BytesIO 2 | import zlib 3 | 4 | 5 | class Writer: 6 | def __init__(self, client, endian: str = 'big'): 7 | self.client = client 8 | self.endian = endian 9 | self.buffer = b'' 10 | 11 | 12 | def writeInt(self, data: int, length: int = 4): 13 | if data > 0: 14 | self.buffer += data.to_bytes(length, 'big', signed=False) 15 | else: 16 | self.buffer += data.to_bytes(length, 'big', signed=True) 17 | 18 | 19 | def writeInt8(self, data): 20 | self.writeInt(data, 1) 21 | 22 | 23 | def writeInt16(self, data): 24 | self.writeInt(data, 2) 25 | 26 | 27 | def writeInt24(self, data): 28 | self.writeInt(data, 3) 29 | 30 | 31 | def writeIntLE(self, data, length=4): 32 | self.buffer += data.to_bytes(length, 'little') 33 | 34 | 35 | def writeLong(self, high, low): 36 | self.buffer += high.to_bytes(4, 'big') + low.to_bytes(4, 'big') 37 | 38 | 39 | def writeUInteger(self, data: int, length: int = 1): 40 | self.buffer += data.to_bytes(length, 'big', signed=False) 41 | 42 | 43 | def writeUInt8(self, integer: int): 44 | self.writeUInteger(integer) 45 | 46 | 47 | def writeVInt(self, data, rotate: bool = True): 48 | final = b'' 49 | if data == 0: 50 | self.writeByte(0) 51 | elif data < 0: 52 | self.writeVInt((2147483648 * 2) + data) 53 | else: 54 | data = (data << 1) ^ (data >> 31) 55 | while data: 56 | b = data & 0x7f 57 | 58 | if data >= 0x80: 59 | b |= 0x80 60 | if rotate: 61 | rotate = False 62 | lsb = b & 0x1 63 | msb = (b & 0x80) >> 7 64 | b >>= 1 65 | b = b & ~0xC0 66 | b = b | (msb << 7) | (lsb << 6) 67 | 68 | final += b.to_bytes(1, 'big') 69 | data >>= 7 70 | self.buffer += final 71 | 72 | 73 | def writeArrayVInt(self, arraydata): 74 | self.writeVInt(len(arraydata)) 75 | for i in arraydata: 76 | self.writeVInt(i) 77 | 78 | 79 | def writeLogicLong(self, high, low): 80 | self.writeVInt(high) 81 | self.writeVInt(low) 82 | 83 | 84 | def writeDataReference(self, ClassID, InstanceID=0): 85 | if ClassID >= 1 and InstanceID >= 0: 86 | self.writeVInt(ClassID) 87 | self.writeVInt(InstanceID) 88 | else: 89 | self.writeVInt(0) 90 | 91 | 92 | def writeBoolean(self, *args): 93 | boolean = 0 94 | i = 0 95 | for value in args: 96 | if value: 97 | boolean |= 1 << i 98 | i += 1 99 | self.writeByte(boolean) 100 | 101 | 102 | def writeString(self, string = None): 103 | if string is None: 104 | self.writeInt((2 ** 32) - 1) 105 | else: 106 | if type(string) == bytes: 107 | encoded = string 108 | else: 109 | encoded = string.encode('utf-8') 110 | self.writeInt(len(encoded)) 111 | self.buffer += encoded 112 | 113 | 114 | def writeStringReference(self, string = None): 115 | if string is None: 116 | self.writeInt((2 ** 32) - 1) 117 | else: 118 | if type(string) == bytes: 119 | encoded = string 120 | else: 121 | encoded = string.encode('utf-8') 122 | self.writeInt(len(encoded)) 123 | self.buffer += encoded 124 | 125 | 126 | def writeCompressedString(self, data: bytes): 127 | compressed = zlib.compress(data) 128 | self.writeInt(len(compressed) + 4) 129 | self.writeIntLE(len(data)) 130 | self.buffer += compressed 131 | 132 | 133 | def writeByte(self, data): 134 | if data > 255: 135 | self.buffer += data.to_bytes(2, 'big', signed=False) 136 | elif data > 127: 137 | self.buffer += data.to_bytes(1, 'big', signed=False) 138 | else: 139 | self.buffer += data.to_bytes(1, 'big', signed=True) 140 | 141 | 142 | def writeHexa(self, data): 143 | if data: 144 | if data.startswith('0x'): 145 | data = data[2:] 146 | self.buffer += bytes.fromhex(''.join(data.split()).replace('-', '')) 147 | 148 | 149 | def size(self): 150 | return len(self.buffer) 151 | 152 | 153 | def getRaw(self): 154 | return self.buffer 155 | 156 | 157 | def writeBytes(self, data): 158 | self.buffer += data 159 | 160 | 161 | def ChronosTextEntry(self, TextType, TextEntry): 162 | self.writeInt(TextType) 163 | self.writeStringReference(TextEntry) 164 | 165 | 166 | def ChronosFileEntry(self, FilePath, FileSHA): 167 | self.writeStringReference(FilePath) 168 | self.writeStringReference(FileSHA) 169 | 170 | 171 | def send(self): 172 | self.encode() 173 | packet = self.buffer 174 | self.buffer = self.id.to_bytes(2, 'big', signed=True) 175 | self.writeInt24(len(packet)) 176 | if hasattr(self, 'version'): 177 | self.writeInt16(self.version) 178 | else: 179 | self.writeInt16(0) 180 | self.buffer += packet + b'\xff\xff\x00\x00\x00\x00\x00' 181 | self.client.send(self.buffer) 182 | print(f'[INFO] Packet {self.id}: {self.__class__.__name__} was sent!') 183 | 184 | 185 | class Reader(BufferedReader): 186 | def __init__(self, header_bytes): 187 | super().__init__(BytesIO(header_bytes)) 188 | self.bytes_of_packets = header_bytes 189 | 190 | 191 | def readInt(self): 192 | return int.from_bytes(self.read(4), "big") 193 | 194 | 195 | def readInt8(self): 196 | return int.from_bytes(self.read(1), "big") 197 | 198 | 199 | def readInt16(self): 200 | return int.from_bytes(self.read(2), "big") 201 | 202 | 203 | def readInt24(self): 204 | return int.from_bytes(self.read(3), "big") 205 | 206 | 207 | def readIntLE(self): 208 | return int.from_bytes(self.read(4), "little") 209 | 210 | 211 | def readLong(self): 212 | high = self.readInt() 213 | low = self.readInt() 214 | return high, low 215 | 216 | 217 | def readUInteger(self, length: int = 1, endian: str = 'big'): 218 | result = 0 219 | i = 0 220 | for x in range(length): 221 | byte = self.bytes_of_packets[i] 222 | bit_padding = x * 8 223 | if endian == 'big': 224 | bit_padding = (8 * (length - 1)) - bit_padding 225 | result |= byte << bit_padding 226 | i += 1 227 | return result 228 | 229 | 230 | def readUInt8(self): 231 | return self.readUInteger() 232 | 233 | 234 | def readVInt(self): 235 | n = self.readVarInt(True) 236 | return (n >> 1) ^ (-(n & 1)) 237 | 238 | 239 | def readLogicLong(self): 240 | high = self.readVInt() 241 | low = self.readVInt() 242 | return high, low 243 | 244 | 245 | def readDataReference(self): 246 | ClassID = self.readVInt() 247 | if ClassID != 0: 248 | InstanceID = self.readVInt() 249 | else: 250 | InstanceID = -1 251 | return ClassID, InstanceID 252 | 253 | 254 | def readBoolean(self): 255 | result = bool.from_bytes(bytes=self.read(1), byteorder='big', signed=False) 256 | if result == True: 257 | return True 258 | else: 259 | return False 260 | 261 | 262 | def readString(self): 263 | lenght = self.readInt() 264 | if lenght == pow(2, 32) - 1: 265 | return b"" 266 | else: 267 | try: 268 | decoded = self.read(lenght) 269 | except MemoryError: 270 | raise IndexError("String out of range.") 271 | else: 272 | return decoded.decode('utf-8') 273 | 274 | 275 | def readStringReference(self): 276 | return self.readString() 277 | 278 | 279 | def readCompressedString(self): 280 | self.readInt() 281 | data_length = self.readIntLE() 282 | compressed = self.readBytes(data_length) 283 | return zlib.decompress(compressed) 284 | 285 | 286 | def readByte(self): 287 | return int.from_bytes(self.read(1), "big") 288 | 289 | 290 | def readBytes(self, length): 291 | return self.read(length) 292 | 293 | 294 | def readShort(self, length=2): 295 | return int.from_bytes(self.read(length), "big") 296 | 297 | 298 | def readVarInt(self, rotate: bool = True): 299 | result = 0 300 | shift = 0 301 | while True: 302 | byte = self.readByte() 303 | if rotate and shift == 0: 304 | seventh = (byte & 0x40) >> 6 305 | msb = (byte & 0x80) >> 7 306 | n = byte << 1 307 | n = n & ~0x181 308 | byte = n | (msb << 7) | seventh 309 | result |= (byte & 0x7f) << shift 310 | shift += 7 311 | if not (byte & 0x80): 312 | break 313 | return result 314 | 315 | 316 | def peekInt(self, length=4): 317 | return int.from_bytes(self.peek(length)[:length], "big") -------------------------------------------------------------------------------- /Logic/Classes/LogicClientHome.py: -------------------------------------------------------------------------------- 1 | from Logic.Classes.LogicDailyData import LogicDailyData 2 | from Logic.Classes.LogicConfData import LogicConfData 3 | from Utility.ByteStream import Writer 4 | 5 | 6 | class LogicClientHome(Writer): 7 | def encode(self): 8 | LogicDailyData.encode(self) 9 | LogicConfData.encode(self) 10 | self.writeLong(0, 1) # Home ID 11 | 12 | 13 | self.writeVInt(16) # Notification Factory 14 | 15 | 16 | # New Brawler Ranks Notification 17 | self.writeVInt(78) # Notification ID 18 | self.writeInt(0) # Notification Index 19 | self.writeBoolean(True) # Notification Read 20 | self.writeInt(0) # Notification Time Ago 21 | self.writeString() # Notification Message Entry 22 | self.writeVInt(400) # Star Points Gained 23 | self.writeVInt(50) # Tokens Gained 24 | # New Brawler Ranks Notification End 25 | 26 | 27 | # Season End Notification 28 | self.writeVInt(79) # Notification ID 29 | self.writeInt(1) # Notification Index 30 | self.writeBoolean(True) # Notification Read 31 | self.writeInt(0) # Notification Time Ago 32 | self.writeString() # Notification Message Entry 33 | self.writeVInt(28) # Brawlers Count 34 | for x in range(28): 35 | self.writeVInt(16000000 + x) # Brawler ID 36 | self.writeVInt(1400) # Brawler Trophies 37 | self.writeVInt(450) # Brawler Trophy Loss 38 | self.writeVInt(480) # Star Points Gained 39 | # Season End Notification End 40 | 41 | 42 | # Star Points Migration Notification 43 | self.writeVInt(80) # Notification ID 44 | self.writeInt(2) # Notification Index 45 | self.writeBoolean(True) # Notification Read 46 | self.writeInt(0) # Notification Time Ago 47 | self.writeString() # Notification Message Entry 48 | self.writeVInt(8000) # Star Points Gained 49 | # Star Points Migration Notification End 50 | 51 | 52 | # Custom Support Message Notification 53 | self.writeVInt(81) # Notification ID 54 | self.writeInt(3) # Notification Index 55 | self.writeBoolean(True) # Notification Read 56 | self.writeInt(0) # Notification Time Ago 57 | self.writeString("Hacc") # Notification Message Entry 58 | self.writeVInt(0) 59 | # Custom Support Message Notification End 60 | 61 | 62 | # Club Mail Notification 63 | self.writeVInt(82) # Notification ID 64 | self.writeInt(4) # Notification Index 65 | self.writeBoolean(True) # Notification Read 66 | self.writeInt(0) # Notification Time Ago 67 | self.writeString("Hacc") # Message Entry 68 | # Player Display Data 69 | self.writeString("Brawler") # Player Name 70 | self.writeVInt(100) 71 | self.writeVInt(28000000) # Player Profile Icon 72 | self.writeVInt(43000000) # Player Name Color 73 | # Player Display Data End 74 | # Club Mail Notification End 75 | 76 | 77 | # Promo Popup Notification 78 | self.writeVInt(83) # Notification ID 79 | self.writeInt(5) # Notification Index 80 | self.writeBoolean(False) # Notification Read 81 | self.writeInt(0) # Notification Time Ago 82 | self.writeString() # Notification Message Entry 83 | self.ChronosTextEntry(0, "Welcome to LaserScratch!") # Primary Text Entry 84 | self.ChronosTextEntry(0, "Check GitHub for more info and updates!") # Secondary Text Entry 85 | self.ChronosTextEntry(0, "View More") # Button Text Entry 86 | self.ChronosFileEntry("pop_up_1920x1235_welcome.png", "6bb3b752a80107a14671c7bdebe0a1b662448d0c") # Notification Banner Data 87 | self.writeStringReference("brawlstars://extlink?page=https%3A%2F%2Fgithub.com%2FIcaro072%2FProject-LaserScratch") # Notification Event 88 | self.writeVInt(0) 89 | # Promo Popup Notification End 90 | 91 | 92 | # Star Power Donated Notification 93 | self.writeVInt(84) # Notification ID 94 | self.writeInt(6) # Notification Index 95 | self.writeBoolean(True) # Notification Read 96 | self.writeInt(0) # Notification Time Ago 97 | self.writeString() # Notification Message Entry 98 | self.writeVInt(0) 99 | self.writeVInt(23000000 + 76) # Star Power Donated 100 | # Star Power Donated Notification End 101 | 102 | 103 | # Gems Refunded Notification 104 | self.writeVInt(85) # Notification ID 105 | self.writeInt(7) # Notification Index 106 | self.writeBoolean(True) # Notification Read 107 | self.writeInt(0) # Notification Time Ago 108 | self.writeString() # Notification Message Entry 109 | self.writeVInt(0) # Revoke Type 110 | self.writeVInt(0) # Gems Revoked 111 | self.writeLong(0, 1) # Player ID 112 | self.writeVInt(0) 113 | self.writeString("") # Offer Purchased Timestamp 114 | # Gems Refunded Notification End 115 | 116 | 117 | # News Notification 118 | self.writeVInt(87) # Notification ID 119 | self.writeInt(8) # Notification Index 120 | self.writeBoolean(True) # Notification Read 121 | self.writeInt(0) # Notification Time Ago 122 | self.writeString() # Notification Message Entry 123 | self.writeStringReference() 124 | # News Notification End 125 | 126 | 127 | # Token Doubler Donated Notification 128 | self.writeVInt(88) # Notification ID 129 | self.writeInt(9) # Notification Index 130 | self.writeBoolean(True) # Notification Read 131 | self.writeInt(0) # Notification Time Ago 132 | self.writeString() # Notification Message Entry 133 | self.writeVInt(0) 134 | self.writeVInt(0) # Token Doublers Donated 135 | # Token Doubler Donated Notification End 136 | 137 | 138 | # Gems Donated Notification 139 | self.writeVInt(89) # Notification ID 140 | self.writeInt(10) # Notification Index 141 | self.writeBoolean(True) # Notification Read 142 | self.writeInt(0) # Notification Time Ago 143 | self.writeString() # Notification Message Entry 144 | self.writeVInt(0) 145 | self.writeVInt(0) # Gems Donated 146 | # Gems Donated Notification End 147 | 148 | 149 | # Resource Donated Notification 150 | self.writeVInt(90) # Notification ID 151 | self.writeInt(11) # Notification Index 152 | self.writeBoolean(True) # Notification Read 153 | self.writeInt(0) # Notification Time Ago 154 | self.writeString() # Notification Message Entry 155 | self.writeVInt(0) 156 | self.writeVInt(5000000 + 1) # Resource ID 157 | self.writeVInt(0) # Resource Donated 158 | # Resource Donated Notification End 159 | 160 | 161 | # Tickets Donated Notification 162 | self.writeVInt(91) # Notification ID 163 | self.writeInt(12) # Notification Index 164 | self.writeBoolean(True) # Notification Read 165 | self.writeInt(0) # Notification Time Ago 166 | self.writeString() # Notification Message Entry 167 | self.writeVInt(0) 168 | self.writeVInt(0) # Token Doublers Donated 169 | # Tickets Donated Notification End 170 | 171 | 172 | # Brawler Power Points Donated Notification 173 | self.writeVInt(92) # Notification ID 174 | self.writeInt(13) # Notification Index 175 | self.writeBoolean(True) # Notification Read 176 | self.writeInt(0) # Notification Time Ago 177 | self.writeString() # Notification Message Entry 178 | self.writeVInt(0) 179 | self.writeVInt(16000000 + 0) # Brawler ID 180 | self.writeVInt(0) # Power Points Donated 181 | # Brawler Power Points Donated Notification End 182 | 183 | 184 | # Brawler Donated Notification 185 | self.writeVInt(93) # Notification ID 186 | self.writeInt(14) # Notification Index 187 | self.writeBoolean(True) # Notification Read 188 | self.writeInt(0) # Notification Time Ago 189 | self.writeString() # Notification Message Entry 190 | self.writeVInt(0) 191 | self.writeVInt(16000000 + 0) # Brawler Donated 192 | # Brawler Donated Notification End 193 | 194 | 195 | # Skin Donated Notification 196 | self.writeVInt(94) # Notification ID 197 | self.writeInt(15) # Notification Index 198 | self.writeBoolean(True) # Notification Read 199 | self.writeInt(0) # Notification Time Ago 200 | self.writeString() # Notification Message Entry 201 | self.writeVInt(29000000 + 2) # Skin Donated 202 | # Skin Donated Notification End 203 | 204 | 205 | self.writeVInt(-1) 206 | self.writeBoolean(False) 207 | 208 | 209 | # Gatcha Drop Array 210 | self.writeVInt(0) # Count 211 | for x in range(0): 212 | self.writeVInt(0) 213 | self.writeDataReference(16, -1) 214 | self.writeVInt(0) 215 | self.writeDataReference(29, -1) 216 | self.writeDataReference(23, -1) 217 | self.writeVInt(0) 218 | # Gatcha Drop Array End --------------------------------------------------------------------------------