From: Joann Mõndresku Date: Sat, 11 May 2024 09:01:27 +0000 (+0300) Subject: Initial release X-Git-Url: https://git.based.quest/index.html?a=commitdiff_plain;h=61501eaedc0218e9a523c2039580d86082a26e40;p=reEgg.git Initial release --- 61501eaedc0218e9a523c2039580d86082a26e40 diff --git a/LICENSE.txt b/LICENSE.txt new file mode 100644 index 0000000..061d802 --- /dev/null +++ b/LICENSE.txt @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2024 cernodile.com + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..659f981 --- /dev/null +++ b/README.md @@ -0,0 +1,37 @@ +# reEgg +A server emulator for Auxbrain's Egg, Inc. mobile game, written in Python, for version 1.12.13. +This project was created for [Reverse Engineering a Mobile App Protobuf API](https://based.quest/reverse-engineering-a-mobile-app-protobuf-api/) blog posts on based.quest. + +## DISCLAIMER +The version of game chosen is deliberate to not affect the current live service. The game developer has had a history of having to +deal with cheaters and I do not wish to furthen the problem by attempting to reverse engineer their efforts against cheaters. +The project's scope is to educate people on how to reverse engineer APIs in order for digital preservation and archival of media. +As API servers shut down, many apps are immediately locked out from being useable or get heavily hindered in capabilities to do anything productive. + +## Setup +Get any webserver that supports reverse proxying. Point it to proxy http://127.0.0.1:5000/. Create self-signed CA and certificate for www.auxbrain.com and configure your chosen webserver to use it. +Once that is set up, install "protobuf" and "flask" with pip and run `flask run` on the command line. + +You will need a VPN app on your phone that can overwrite DNS records (such as AdAway) and root to perform SSL unpinning (Xposed Framework has modules for that). +You can also perform this without root by repacking the app with a modified manifest. + +Once you've setup redirection, install the self-signed CA to Android's CA store. + +## Configuration +You might want to check out `data/` directory and check for any epoch values. I am using 05/05/2024 as the default epoch for scheduling contracts for example. + +## Roadmap +- [ ] First contact + - [ ] Offer a valid backup + - [x] Respond with valid payload + - [x] Unlock Pro Permit +- [ ] Gift Calendar +- [ ] Periodicals + - [ ] Contracts + - [x] Your First Contract + - [x] Contract Scheduler + - [ ] Co-op with computer simulations + - [x] Events + - [x] Proof of Concept + - [x] Event Scheduler + diff --git a/app.py b/app.py new file mode 100644 index 0000000..157df32 --- /dev/null +++ b/app.py @@ -0,0 +1,67 @@ +############ +# Egg Inc v1.12.13 (Android Build 111121) server emulator +# Read the blog post at https://based.quest/reverse-engineering-a-mobile-app-protobuf-api/ +############ +import base64 +import time + +import ei_pb2 as EIProto + +from flask import Flask +from flask import request + +import contracts +import events + +upgrade_cache = {} + +app = Flask(__name__) +contracts.load_contracts() + +@app.route('/ei/', methods=['POST']) +def ei_routes(subpath): + print("REQ: /ei/" + subpath) + if subpath == "daily_gift_info": + print(request.form) + data = base64.b64decode(request.form["data"].replace(" ", "+")) + if subpath == "first_contact": + ContactReq = EIProto.EggIncFirstContactRequest() + ContactReq.ParseFromString(data) + ContactResp = EIProto.EggIncFirstContactResponse() + if ContactReq.user_id in upgrade_cache: + print("Found an unupgraded save - lets upgrade the permit level to Pro") + ContactResp.backup.CopyFrom(cache[ContactReq.user_id]) + del upgrade_cache[ContactReq.user_id] + return base64.b64encode(ContactResp.SerializeToString()) + elif subpath == "save_backup": + SaveBackup = EIProto.Backup() + SaveBackup.ParseFromString(bytes(data)) + if SaveBackup.game.permit_level == 0: + SaveBackup.game.permit_level = 1 + SaveBackup.force_backup = True + SaveBackup.force_offer_backup = True + upgrade_cache[SaveBackup.user_id] = SaveBackup + elif subpath == "get_periodicals": + PeriodicalResp = EIProto.PeriodicalsResponse() + for evt in events.get_active_events(): + e = PeriodicalResp.events.events.add() + e.CopyFrom(evt) + for contract in contracts.get_active_contracts(): + c = PeriodicalResp.contracts.contracts.add() + c.CopyFrom(contract) + return base64.b64encode(PeriodicalResp.SerializeToString()) + else: + print("DATA", base64.b64encode(data)) + return "" + +@app.route('/ei_data/', methods=['POST']) +def ei_data_rotues(subpath): + print("REQ /ei_data/" + subpath) + if subpath == "log_action": + data = base64.b64decode(request.form["data"]) + GenericAction = EIProto.GenericAction() + GenericAction.ParseFromString(data) + print(GenericAction) + else: + print(request.form) + return "" diff --git a/contracts.py b/contracts.py new file mode 100644 index 0000000..17d2bbf --- /dev/null +++ b/contracts.py @@ -0,0 +1,95 @@ +# contracts.py - Contract Definitions parser and provider +import ei_pb2 as EIProto +import json +import time + +# Keep a cache of all contracts +contract_epoch = int(time.time()) +global_contract_db = {"legacy": [], "normal": [], "permanent": []} + +def get_active_contracts(): + # TODO: Shift the epoch when a full run of leggacys is done. + # TODO: Don't iterate all the contracts, calculate where appropriate on starting index + # Return an array of Contract objects + list = [global_contract_db["permanent"][0]] + # Iterate leggacy + time_since_epoch = time.time() - contract_epoch + i = 0 + for contract in global_contract_db["legacy"]: + # Leggacy ones are active for a week, one per week + i += 1 + expiry_time = (604800 * i) - time_since_epoch + # It's expired, get the next one + if expiry_time < 0: + continue + # It's already next week's contract, don't process more + if expiry_time > 604800: + break + contract.expiration_time = expiry_time + list.append(contract) + # Add regular contracts here when implemented + # DESIGN QUESTION: Do we even *want* regular contracts? Could just run two "leggacy" branches in parallel. + return list + +def __convert_contract_to_proto(obj): + # Map values from JSON object to Protobuf object. + contract = EIProto.Contract() + contract.identifier = obj["id"] + contract.name = obj["name"] + contract.description = obj["description"] + contract.egg = EIProto.Egg.Value(obj["egg"]) + contract.minutes_per_token = obj["token_interval"] + contract.length_seconds = obj["duration"] + contract.coop_allowed = False + for goal_set_src in obj["goalsets"]: + goal_set = contract.goal_sets.add() + for goal_src in goal_set_src: + goal = goal_set.goals.add() + goal.type = EIProto.GoalType.EGGS_LAID + goal.target_amount = goal_src["deliver"] + goal.reward_type = EIProto.RewardType.Value(goal_src["reward_type"]) + if goal.reward_type == EIProto.RewardType.BOOST: + goal.reward_sub_type = goal_src["reward_str"] + goal.reward_amount = goal_src["reward_amt"] + return contract + +def load_contracts(): + with open("data/contracts.json", "r") as file: + obj = json.loads(file.read()) + contract_epoch = obj["epoch"] + time_since_epoch = time.time() - contract_epoch + i = 0 + for source in obj["legacy"]: + global_contract_db["legacy"].append(__convert_contract_to_proto(source)) + i += 1 + global_contract_db["legacy"][-1].expiration_time = (604800 * i) - time_since_epoch + print(f'Loaded in {len(global_contract_db["legacy"])} "Leggacy" contracts, {len(global_contract_db["normal"])} to-schedule contracts') + return + +# Add the permanent contract here as well +def create_perma_contract(): + obj = { + "id": "first-contract", + "name": "Your First Contract", + "description": "We heard you are open to contract work! Help fill this order from the local pharmacy!", + "egg": "MEDICAL", + "duration": 14400.0, + "token_interval": 5.0, + "goalsets": [ + [ + {"deliver": 100000.0, "reward_type": "GOLD", "reward_amt": 500}, + {"deliver": 5000000000.0, "reward_type": "PIGGY_FILL", "reward_amt": 10000} + ], + [ + {"deliver": 100000.0, "reward_type": "GOLD", "reward_amt": 192}, + {"deliver": 5000000000.0, "reward_type": "PIGGY_FILL", "reward_amt": 10000} + ] + ] + } + contract = __convert_contract_to_proto(obj) + # The permanent "first contract" is a special case where it should never expire and it should also not appear after 5000 Soul Eggs + contract.expiration_time = 100000000.0 + contract.max_soul_eggs = 5000.0 + return contract + +global_contract_db["permanent"].append(create_perma_contract()) diff --git a/data/README.txt b/data/README.txt new file mode 100644 index 0000000..3d03ec3 --- /dev/null +++ b/data/README.txt @@ -0,0 +1,3 @@ +Contracts sourced from https://eicoop-carpet.netlify.app/ + +For leggacy: Choose "Type: Leggacy" as filter, start going from Laurel vs Yanny as that's the first one with Standard/Elite diff --git a/data/contract-creator.py b/data/contract-creator.py new file mode 100755 index 0000000..19993b1 --- /dev/null +++ b/data/contract-creator.py @@ -0,0 +1,153 @@ +#!/bin/python +import json +import sys +sys.path.append("..") +import ei_pb2 as EIProto + +# [ +# {"deliver": 250000000000000000, "reward_type": "SOUL_EGGS", "reward_amt": 250000}, +# {"deliver": 500000000000000000, "reward_type": "EGGS_OF_PROPHECY", "reward_amt": 1} +# ], +# [ +# {"deliver": 50000000000000, "reward_type": "SOUL_EGGS", "reward_amt": 10000}, +# {"deliver": 1000000000000000, "reward_type": "EGGS_OF_PROPHECY", "reward_amt": 1} +# ] +# ] +# } +boost_defs = { +"Supreme tachyon prism": "tachyon_prism_orange_big", +"Legendary tachyon prism (1000x 10m)": "tachyon_prism_orange", +"Legendary boost beacon (500x 10m)": "boost_beacon_orange", +"Legendary soul beacon (50x 10m)": "soul_beacon_orange", +"Epic tachyon prism (100x 2hr)": "tachyon_prism_purple_big", +"Epic soul beacon (50x 30)": "soul_beacon_purple", +"Powerful tachyon prism (100x 20m)": "tachyon_prism_purple", +"Jimbo's best bird feed (50x 2hr)": "jimbos_orange_big", +"Jimbo's best bird feed (50x 10m)": "jimbos_orange", +"Large boost beacon (5x 1hr)": "boost_beacon_blue_big" +} + +obj = {"id": "", "name": "", "description": "", "duration": 0.0, "token_interval": 0.0, "egg": "", "goalsets": []} + +def ask_for_string(preprint): + while True: + print(preprint, end="") + x = input() + if len(x) > 0: + return x + +def ask_for_float(preprint): + while True: + print(preprint, end="") + x = input() + try: + val = float(x) + return val + except: + continue + +def ask_for_quantity(preprint): + while True: + print(preprint, end="") + x = input() + vals = x.split(" ") + if len(vals) == 2: + try: + val = int(vals[0]) + # why doesnt python have switch statements? + multip = vals[1] + if len(multip) != 1: + print("Your quantifier must be 1 letter in length") + continue + if multip.upper() == "M": + val *= 1000000 + elif multip.upper() == "B": + val *= 1000000000 + elif multip.upper() == "T": + val *= 1000000000000 + elif multip == "q": + val *= 1000000000000000 + elif multip == "Q": + val *= 1000000000000000000 + elif multip == 's': + val *= 1000000000000000000000 + elif multip == 'S': + val *= 1000000000000000000000000 + else: + print("Couldn't identify your quantifier") + continue + return val + except: + continue + else: + print("Please enter the value in following format: VALUE QUANTIFIER (Example: 10 q)") + +def parse_egg_type(preprint): + while True: + print(preprint, end="") + x = input() + if x == "?": + print(", ".join(EIProto.Egg.keys())) + else: + try: + egg_type = x.upper() + EIProto.Egg.Value(egg_type) + return egg_type + except: + continue + +def parse_reward_type(preprint): + while True: + print(preprint, end="") + x = input() + if x == "?": + print(", ".join(EIProto.RewardType.keys())) + else: + try: + reward_type = x.upper() + EIProto.RewardType.Value(reward_type) + return reward_type + except: + continue + +def parse_boost_type(preprint): + while True: + print(preprint, end="") + x = input() + if x == "?": + for a, b in list(boost_defs.items()): print(a + ": " + b) + else: + try: + boost_name = x.lower() + if boost_name not in boost_defs.values(): + continue + return boost_name + except: + continue + + +def create_goalset(type): + print("Creating a " + type + " goalset") + goal_amount = int(ask_for_float("How many goals: ")) + goals = [] + for i in range(0, goal_amount): + print("Goal " + str(i + 1) + "/" + str(goal_amount)) + goal = {"deliver": 0, "reward_type": "", "reward_str": "", "reward_amt": 0} + goal["deliver"] = ask_for_quantity("How many eggs to deliver? ") + goal["reward_type"] = parse_reward_type("Enter reward type - type '?' for reference: ") + if goal["reward_type"] == "BOOST": + goal["reward_str"] = parse_boost_type("Type in boost type - type '?' for reference: ") + goal["reward_amt"] = ask_for_float("How many rewarded? ") + goals.append(goal) + return goals + +obj["id"] = ask_for_string("Enter contract ID: ") +obj["name"] = ask_for_string("Enter contract name: ") +obj["description"] = ask_for_string("Enter contract description: ") +obj["duration"] = ask_for_float("How many minutes does the contract last: ") * 60.0 +obj["token_interval"] = ask_for_float("How many minutes to wait per reward token: ") +obj["egg"] = parse_egg_type("Enter egg type - type '?' if need reference: ") +obj["goalsets"].append(create_goalset("Elite")) +obj["goalsets"].append(create_goalset("Standard")) + +print(json.dumps(obj, indent='\t')) diff --git a/data/contracts.json b/data/contracts.json new file mode 100644 index 0000000..53e2930 --- /dev/null +++ b/data/contracts.json @@ -0,0 +1,116 @@ +{ + "epoch": 1714867200, + "legacy": [ + { + "id": "laurel-v-yanny", + "name": "LEGGACY: Laurel vs Yanny", + "description": "A Quantum rift is causing people to hear different words in a viral video. Scientists have a fix but they need your help.", + "duration": 345600.0, + "token_interval": 60.0, + "egg": "QUANTUM", + "goalsets": [ + [ + { + "deliver": 250000000000000000, + "reward_type": "SOUL_EGGS", + "reward_amt": 250000 + }, + { + "deliver": 500000000000000000, + "reward_type": "EGGS_OF_PROPHECY", + "reward_amt": 1 + } + ], + [ + { + "deliver": 50000000000000, + "reward_type": "SOUL_EGGS", + "reward_amt": 10000 + }, + { + "deliver": 1000000000000000, + "reward_type": "EGGS_OF_PROPHECY", + "reward_amt": 1 + } + ] + ] + }, + { + "id": "build-a-house", + "name": "LEGGACY: Home Renovations", + "description": "You've decided to build a new house! Why not make it yourself? You'll need a lot of eggs so get started!", + "duration": 864000.0, + "token_interval": 60.0, + "egg": "SUPER_MATERIAL", + "goalsets": [ + [ + { + "deliver": 5000000000000000, + "reward_type": "GOLD", + "reward_str": "", + "reward_amt": 10000.0 + }, + { + "deliver": 25000000000000000, + "reward_type": "BOOST", + "reward_str": "tachyon_prism_orange_big", + "reward_amt": 2.0 + }, + { + "deliver": 100000000000000000, + "reward_type": "EGGS_OF_PROPHECY", + "reward_str": "", + "reward_amt": 1.0 + } + ], + [ + { + "deliver": 50000000000000, + "reward_type": "GOLD", + "reward_str": "", + "reward_amt": 2500.0 + }, + { + "deliver": 250000000000000, + "reward_type": "PIGGY_MULTIPLIER", + "reward_str": "", + "reward_amt": 2.0 + }, + { + "deliver": 3000000000000000, + "reward_type": "EGGS_OF_PROPHECY", + "reward_str": "", + "reward_amt": 1.0 + } + ] + ] + }, + { + "id": "all-or-nothing", + "name": "LEGGACY: All or Nothing", + "description": "A mysterious investor is looking for a lot of edible eggs.\nBut he wants the full amount or nothing.", + "duration": 799980.0, + "token_interval": 60.0, + "egg": "EDIBLE", + "goalsets": [ + [ + { + "deliver": 250000000000000000, + "reward_type": "EGGS_OF_PROPHECY", + "reward_str": "", + "reward_amt": 1.0 + } + ], + [ + { + "deliver": 10000000000000000, + "reward_type": "EGGS_OF_PROPHECY", + "reward_str": "", + "reward_amt": 1.0 + } + ] + ] + } + ], + "normal": [] +} diff --git a/ei_pb2.py b/ei_pb2.py new file mode 100644 index 0000000..7150e9f --- /dev/null +++ b/ei_pb2.py @@ -0,0 +1,164 @@ +# -*- coding: utf-8 -*- +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: ei.proto +# Protobuf Python Version: 4.25.3 +"""Generated protocol buffer code.""" +from google.protobuf import descriptor as _descriptor +from google.protobuf import descriptor_pool as _descriptor_pool +from google.protobuf import symbol_database as _symbol_database +from google.protobuf.internal import builder as _builder +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + + + +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x08\x65i.proto\x12\x02\x65i\"\xaf&\n\x06\x42\x61\x63kup\x12\x0f\n\x07user_id\x18\x01 \x01(\t\x12\x11\n\tuser_name\x18\x02 \x01(\t\x12\x13\n\x0b\x61pprox_time\x18\x03 \x01(\x01\x12\x12\n\x07version\x18\x15 \x01(\r:\x01\x30\x12\x1a\n\x12\x66orce_offer_backup\x18\x14 \x01(\x08\x12\x14\n\x0c\x66orce_backup\x18\x16 \x01(\x08\x12%\n\x08settings\x18\x04 \x01(\x0b\x32\x13.ei.Backup.Settings\x12%\n\x08tutorial\x18\x05 \x01(\x0b\x32\x13.ei.Backup.Tutorial\x12\x1f\n\x05stats\x18\x06 \x01(\x0b\x32\x10.ei.Backup.Stats\x12\x1d\n\x04game\x18\x07 \x01(\x0b\x32\x0f.ei.Backup.Game\x12\"\n\x03sim\x18\x08 \x01(\x0b\x32\x15.ei.Backup.Simulation\x12$\n\x05\x66\x61rms\x18\x0c \x03(\x0b\x32\x15.ei.Backup.Simulation\x12#\n\x07mission\x18\t \x01(\x0b\x32\x12.ei.Backup.Mission\x12\x1d\n\x04misc\x18\n \x01(\x0b\x32\x0f.ei.Backup.Misc\x12\"\n\tcontracts\x18\r \x01(\x0b\x32\x0f.ei.MyContracts\x12\x10\n\x08\x63hecksum\x18\x64 \x01(\x04\x1a\xc5\x05\n\x08Settings\x12\x0b\n\x03sfx\x18\x01 \x01(\x08\x12\r\n\x05music\x18\x02 \x01(\x08\x12\x18\n\x10low_battery_mode\x18\x03 \x01(\x08\x12\x1c\n\x14low_performance_mode\x18\x04 \x01(\x08\x12\x1f\n\x17\x66orce_touch_chicken_btn\x18\t \x01(\x08\x12\x1d\n\x15notifications_queried\x18\x05 \x01(\x08\x12\x18\n\x10notifications_on\x18\x06 \x01(\x08\x12\x19\n\x11notify_daily_gift\x18\x0b \x01(\x08\x12\x15\n\rcoppa_queried\x18\x07 \x01(\x08\x12\x18\n\x10\x63oppa_restricted\x18\x08 \x01(\x08\x12\x1c\n\x14gdpr_consent_queried\x18\x0c \x01(\x08\x12\x1b\n\x13gdpr_age_restricted\x18\x10 \x01(\x08\x12\x1a\n\x12gdpr_consent_given\x18\r \x01(\x08\x12\x13\n\x0b\x61ge_queried\x18\x12 \x01(\x08\x12\x1d\n\x0e\x61ge_restricted\x18\x13 \x01(\x08:\x05\x66\x61lse\x12\'\n\x1f\x64\x61ta_collection_consent_queried\x18\x14 \x01(\x08\x12%\n\x1d\x64\x61ta_collection_consent_given\x18\x15 \x01(\x08\x12\x1c\n\x14last_day_age_queried\x18\x11 \x01(\r\x12\x1e\n\x10user_ads_enabled\x18\x0e \x01(\x08:\x04true\x12 \n\x12user_cloud_enabled\x18\x0f \x01(\x08:\x04true\x12$\n\x16user_analytics_enabled\x18\x16 \x01(\x08:\x04true\x12+\n\x1duser_personalized_ads_enabled\x18\x17 \x01(\x08:\x04true\x12\x17\n\x0flow_performance\x18\n \x01(\x08\x12\x18\n\x10last_backup_time\x18\x18 \x01(\x01\x1a\x88\x02\n\x08Tutorial\x12\x13\n\x0bintro_shown\x18\x01 \x01(\x08\x12\x1c\n\x14\x63lick_tutorial_shown\x18\x02 \x01(\x08\x12\x15\n\rbuy_hab_shown\x18\x03 \x01(\x08\x12\x1a\n\x12hire_vehicle_shown\x18\x04 \x01(\x08\x12\x13\n\x0bq_num_shown\x18\x05 \x01(\x08\x12\x13\n\x0bs_num_shown\x18\x06 \x01(\x08\x12\x1b\n\x13\x63ontracts_tab_shown\x18\x07 \x01(\x08\x12\x1b\n\x13\x63ontract_info_shown\x18\x08 \x01(\x08\x12\x17\n\x0fjoin_coop_shown\x18\t \x01(\x08\x12\x19\n\x11switch_farm_shown\x18\n \x01(\x08\x1a\xdd\x03\n\x05Stats\x12\x16\n\x0e\x65gg_totals_OLD\x18\x01 \x03(\x04\x12\x12\n\negg_totals\x18\x08 \x03(\x01\x12\x1f\n\x17unlimited_chickens_uses\x18\x07 \x01(\x04\x12\x13\n\x0brefill_uses\x18\x02 \x01(\x04\x12\x13\n\x0bwarp_1_uses\x18\x04 \x01(\x04\x12\x13\n\x0bwarp_8_uses\x18\x05 \x01(\x04\x12\x13\n\x0b\x62oosts_used\x18\r \x01(\x04\x12\x1a\n\x12video_doubler_uses\x18\x03 \x01(\x04\x12\x17\n\x0f\x64rone_takedowns\x18\x06 \x01(\x04\x12\x1d\n\x15\x64rone_takedowns_elite\x18\n \x01(\x04\x12\x15\n\rnum_prestiges\x18\t \x01(\x04\x12\x18\n\x10num_piggy_breaks\x18\x0b \x01(\x04\x12\x1b\n\x13iap_packs_purchased\x18\x0c \x01(\x04\x12\x12\n\npiggy_full\x18\x0e \x01(\x08\x12\x18\n\x10piggy_found_full\x18\x0f \x01(\x08\x12\"\n\x1atime_piggy_filled_realtime\x18\x10 \x01(\x01\x12 \n\x18time_piggy_full_gametime\x18\x11 \x01(\x01\x12\x1d\n\x15lost_piggy_increments\x18\x12 \x01(\x04\x1a\xf5\x08\n\x04Game\x12\x17\n\x0c\x63urrent_farm\x18\x16 \x01(\r:\x01\x30\x12 \n\x0fmax_egg_reached\x18\x01 \x01(\x0e\x32\x07.ei.Egg\x12\x1a\n\x12golden_eggs_earned\x18\x02 \x01(\x04\x12\x19\n\x11golden_eggs_spent\x18\x03 \x01(\x04\x12\x1d\n\x15uncliamed_golden_eggs\x18\x10 \x01(\x04\x12\x11\n\tsoul_eggs\x18\x04 \x01(\x04\x12\x1b\n\x13unclaimed_soul_eggs\x18\x11 \x01(\x04\x12\x13\n\x0bsoul_eggs_d\x18\" \x01(\x01\x12\x1d\n\x15unclaimed_soul_eggs_d\x18# \x01(\x01\x12\x18\n\x10\x65ggs_of_prophecy\x18\x17 \x01(\x04\x12\"\n\x1aunclaimed_eggs_of_prophecy\x18\x18 \x01(\x04\x12\x1c\n\x14prestige_cash_earned\x18\x05 \x01(\x01\x12 \n\x18prestige_soul_boost_cash\x18! \x01(\x01\x12\x1c\n\x14lifetime_cash_earned\x18\x06 \x01(\x01\x12\x12\n\npiggy_bank\x18\x07 \x01(\x04\x12\x1e\n\x16piggy_full_alert_shown\x18\x1f \x01(\x08\x12\x14\n\x0cpermit_level\x18\x08 \x01(\r\x12.\n\repic_research\x18\t \x03(\x0b\x32\x17.ei.Backup.ResearchItem\x12\x19\n\x11hyperloop_station\x18\x1d \x01(\x08\x12\x1c\n\x14next_daily_gift_time\x18\n \x01(\x01\x12%\n\x1dlast_daily_gift_collected_day\x18\x14 \x01(\r\x12!\n\x19num_daily_gifts_collected\x18\x1c \x01(\r\x12%\n\x04news\x18\x0b \x03(\x0b\x32\x17.ei.Backup.NewsHeadline\x12\x16\n\x0elast_news_time\x18\x0c \x01(\x01\x12\x1a\n\x12\x63urrent_multiplier\x18\r \x01(\x01\x12%\n\x1d\x63urrent_multiplier_expiration\x18\x0e \x01(\x01\x12\x30\n\x0c\x61\x63hievements\x18\x0f \x03(\x0b\x32\x1a.ei.Backup.AchievementInfo\x12\x1d\n\x15max_farm_size_reached\x18\x12 \x03(\x04\x12\x17\n\x0f\x65gg_medal_level\x18\x13 \x03(\r\x12\"\n\x1along_idle_notification_set\x18\x19 \x01(\x08\x12(\n long_idle_notification_threshold\x18\x1a \x01(\x01\x12\x18\n\x10long_idle_reward\x18\x1b \x01(\x01\x12%\n\x06\x62oosts\x18\x1e \x03(\x0b\x32\x15.ei.Backup.OwnedBoost\x12\"\n\x1atotal_time_cheats_detected\x18 \x01(\r\x12\x1d\n\x15\x66orce_elite_contracts\x18$ \x01(\x08\x12!\n\x19new_player_event_end_time\x18% \x01(\x01\x1a\xaf\x06\n\nSimulation\x12\x19\n\x08\x65gg_type\x18\x01 \x01(\x0e\x32\x07.ei.Egg\x12\x1f\n\tfarm_type\x18\x13 \x01(\x0e\x32\x0c.ei.FarmType\x12\x13\n\x0b\x63ontract_id\x18\x14 \x01(\t\x12\x13\n\x0b\x63\x61sh_earned\x18\x02 \x01(\x01\x12\x12\n\ncash_spent\x18\x03 \x01(\x01\x12\x16\n\x0eunclaimed_cash\x18\x04 \x01(\x01\x12\x16\n\x0elast_step_time\x18\x05 \x01(\x01\x12\x14\n\x0cnum_chickens\x18\x06 \x01(\x04\x12\x1e\n\x16num_chickens_unsettled\x18\x07 \x01(\x04\x12\x1c\n\x14num_chickens_running\x18\x08 \x01(\x04\x12\x11\n\teggs_laid\x18\t \x01(\x01\x12\x15\n\reggs_paid_for\x18\n \x01(\x01\x12\x13\n\x0bsilos_owned\x18\x0b \x01(\r\x12\x0c\n\x04habs\x18\x0c \x03(\r\x12\x16\n\x0ehab_population\x18\r \x03(\x04\x12\x1e\n\x16hab_population_indound\x18\x0e \x03(\x04\x12!\n\x19hab_incubator_popuplation\x18\x0f \x03(\x01\x12\x1b\n\x13hatchery_population\x18\x10 \x01(\x01\x12\x10\n\x08vehicles\x18\x11 \x03(\r\x12\x14\n\x0ctrain_length\x18\x15 \x03(\r\x12\x30\n\x0f\x63ommon_research\x18\x12 \x03(\x0b\x32\x17.ei.Backup.ResearchItem\x12-\n\ractive_boosts\x18\x16 \x03(\x0b\x32\x16.ei.Backup.ActiveBoost\x12\x1c\n\x14time_cheats_detected\x18\x17 \x01(\r\x12\x17\n\x0ftime_cheat_debt\x18\x18 \x01(\x01\x12\x1d\n\x15\x62oost_tokens_received\x18\x19 \x01(\r\x12\x1a\n\x12\x62oost_tokens_spent\x18\x1a \x01(\r\x12\x1a\n\x12\x62oost_tokens_given\x18\x1c \x01(\r\x12\x1e\n\x16unclaimed_boost_tokens\x18\x1b \x01(\r\x12\'\n\x1fgametime_until_next_boost_token\x18\x1d \x01(\x01\x1a\x7f\n\x07Mission\x12\x17\n\x0f\x63urrent_mission\x18\x01 \x01(\t\x12\x17\n\x0freference_value\x18\x02 \x01(\x01\x12\x18\n\x10\x63urrent_missions\x18\x04 \x03(\t\x12(\n\x08missions\x18\x03 \x03(\x0b\x32\x16.ei.Backup.MissionInfo\x1a\xa7\x04\n\x04Misc\x12\x1c\n\x14\x63hicken_btn_pref_big\x18\x01 \x01(\x08\x12\"\n\x1a\x66ree_hatchery_refill_given\x18\x02 \x01(\x08\x12\'\n\x15last_share_farm_value\x18\x03 \x01(\x01:\x08\x31\x30\x30\x30\x30\x30\x30\x30\x12-\n\x1blast_share_swarm_farm_value\x18\x04 \x01(\x01:\x08\x31\x30\x30\x30\x30\x30\x30\x30\x12\"\n\x15last_share_swarm_size\x18\x05 \x01(\x01:\x03\x31\x34\x30\x12)\n\x1dlast_prestige_alert_soul_eggs\x18\n \x01(\x04:\x02\x34\x35\x12\x13\n\x0b\x66riend_rank\x18\x06 \x01(\x04\x12\x17\n\x0f\x66riend_rank_pop\x18\x07 \x01(\x04\x12\x13\n\x0bglobal_rank\x18\x08 \x01(\x04\x12\x17\n\x0fglobal_rank_pop\x18\t \x01(\x04\x12\x14\n\x0ctrophy_alert\x18\x0b \x01(\x08\x12\x10\n\x08\x61r_alert\x18\x0c \x01(\x08\x12\x17\n\x0f\x63ontracts_alert\x18\r \x01(\x08\x12\x12\n\ncoop_alert\x18\x0e \x01(\x08\x12\x14\n\x0cswitch_alert\x18\x0f \x01(\x08\x12\x1d\n\x15\x65gg_of_prophecy_alert\x18\x10 \x01(\x08\x12\x19\n\x11\x62oost_token_alert\x18\x11 \x01(\x08\x12\x16\n\x0esoul_egg_alert\x18\x12 \x01(\x08\x12\x1d\n\x15\x62\x61\x63kup_reminder_alert\x18\x13 \x01(\x08\x1a)\n\x0cResearchItem\x12\n\n\x02id\x18\x01 \x01(\t\x12\r\n\x05level\x18\x02 \x01(\r\x1a(\n\x0cNewsHeadline\x12\n\n\x02id\x18\x01 \x01(\t\x12\x0c\n\x04read\x18\x02 \x01(\x08\x1a/\n\x0f\x41\x63hievementInfo\x12\n\n\x02id\x18\x01 \x01(\t\x12\x10\n\x08\x61\x63hieved\x18\x02 \x01(\x08\x1aP\n\x0b\x41\x63tiveBoost\x12\x10\n\x08\x62oost_id\x18\x01 \x01(\t\x12\x16\n\x0etime_remaining\x18\x02 \x01(\x01\x12\x17\n\x0freference_value\x18\x03 \x01(\x01\x1a-\n\nOwnedBoost\x12\x10\n\x08\x62oost_id\x18\x01 \x01(\t\x12\r\n\x05\x63ount\x18\x02 \x01(\r\x1a\x45\n\x0bMissionInfo\x12\n\n\x02id\x18\x01 \x01(\t\x12\x11\n\tcompleted\x18\x02 \x01(\x08\x12\x17\n\x0freference_value\x18\x03 \x01(\x01\"d\n\x19\x45ggIncFirstContactRequest\x12\x0f\n\x07user_id\x18\x01 \x01(\t\x12\x16\n\x0e\x63lient_version\x18\x02 \x01(\r\x12\x1e\n\x08platform\x18\x03 \x01(\x0e\x32\x0c.ei.Platform\"8\n\x1a\x45ggIncFirstContactResponse\x12\x1a\n\x06\x62\x61\x63kup\x18\x01 \x01(\x0b\x32\n.ei.Backup\"9\n\x0e\x45ggIncAdConfig\x12\'\n\x10network_priority\x18\x01 \x03(\x0e\x32\r.ei.AdNetwork\"A\n\rDailyGiftInfo\x12\x13\n\x0b\x63urrent_day\x18\x01 \x01(\r\x12\x1b\n\x13seconds_to_next_day\x18\x02 \x01(\x01\"\xc8\x01\n\x10SalesInfoRequest\x12\x0f\n\x07user_id\x18\x01 \x01(\t\x12\x12\n\npiggy_full\x18\x02 \x01(\x08\x12\x18\n\x10piggy_found_full\x18\x03 \x01(\x08\x12\x1d\n\x15seconds_full_realtime\x18\x04 \x01(\x01\x12\x1d\n\x15seconds_full_gametime\x18\x05 \x01(\x01\x12\x17\n\x0flost_increments\x18\x07 \x01(\r\x12\x1e\n\x16\x63urrent_client_version\x18\n \x01(\r\"g\n\x0cIAPSaleEntry\x12\x12\n\nproduct_id\x18\x01 \x01(\t\x12\x19\n\x11seconds_remaining\x18\x02 \x01(\x01\x12\x17\n\x0f\x64iscount_string\x18\x03 \x01(\t\x12\x0f\n\x07sale_id\x18\x04 \x01(\t\",\n\tSalesInfo\x12\x1f\n\x05sales\x18\x01 \x03(\x0b\x32\x10.ei.IAPSaleEntry\"p\n\x0b\x45ggIncEvent\x12\x12\n\nidentifier\x18\x01 \x01(\t\x12\x19\n\x11seconds_remaining\x18\x02 \x01(\x01\x12\x0c\n\x04type\x18\x03 \x01(\t\x12\x12\n\nmultiplier\x18\x04 \x01(\x01\x12\x10\n\x08subtitle\x18\x05 \x01(\t\"6\n\x13\x45ggIncCurrentEvents\x12\x1f\n\x06\x65vents\x18\x01 \x03(\x0b\x32\x0f.ei.EggIncEvent\"\xa9\x02\n\nDeviceInfo\x12\x11\n\tdevice_id\x18\x01 \x01(\t\x12\x16\n\x0e\x61\x64vertising_id\x18\r \x01(\t\x12\x10\n\x08platform\x18\x02 \x01(\t\x12\x13\n\x0b\x66orm_factor\x18\x03 \x01(\t\x12\x13\n\x0b\x64\x65vice_name\x18\x04 \x01(\t\x12\x18\n\x10platform_version\x18\x05 \x01(\t\x12\x16\n\x0elocale_country\x18\x06 \x01(\t\x12\x17\n\x0flocale_language\x18\x07 \x01(\t\x12\x12\n\ngpu_vendor\x18\x08 \x01(\t\x12\x11\n\tgpu_model\x18\t \x01(\t\x12\x15\n\rdevice_bucket\x18\n \x01(\t\x12\x14\n\x0cscreen_width\x18\x0b \x01(\r\x12\x15\n\rscreen_height\x18\x0c \x01(\r\"\xd5\x05\n\x07\x41ppInfo\x12\x13\n\x0bversion_str\x18\x01 \x01(\t\x12\x10\n\x08sessions\x18\x02 \x01(\r\x12\x15\n\rnum_prestiges\x18\x03 \x01(\r\x12\x11\n\tsoul_eggs\x18\x04 \x01(\x04\x12\x13\n\x0b\x63urrent_egg\x18\x05 \x01(\r\x12\x13\n\x0bgold_earned\x18\x06 \x01(\x04\x12\x12\n\ngold_spent\x18\x07 \x01(\x04\x12\x17\n\x0f\x63urrent_mission\x18\x08 \x01(\r\x12\x12\n\npiggy_size\x18\t \x01(\r\x12\x18\n\x10num_piggy_breaks\x18\n \x01(\x04\x12\x1d\n\x15verified_piggy_breaks\x18\x1d \x01(\x04\x12\x1b\n\x13iap_packs_purchased\x18\x0b \x01(\x04\x12\x14\n\x0cpermit_level\x18\x0c \x01(\r\x12\x1a\n\x12video_doubler_uses\x18\x0f \x01(\x04\x12\x17\n\x0f\x64rone_takedowns\x18\x12 \x01(\x04\x12\x1d\n\x15\x64rone_takedowns_elite\x18\x13 \x01(\x04\x12\x19\n\x11trophies_unlocked\x18\x14 \x01(\x08\x12\x11\n\tegg_level\x18\x15 \x01(\x02\x12\x17\n\x0fstruggle_factor\x18\x16 \x01(\x02\x12\x12\n\npiggy_full\x18\x17 \x01(\x08\x12\x18\n\x10piggy_found_full\x18\x18 \x01(\x08\x12 \n\x18time_piggy_full_realtime\x18\x19 \x01(\x01\x12 \n\x18time_piggy_full_gametime\x18\x1a \x01(\x01\x12\x1d\n\x15lost_piggy_increments\x18\x1b \x01(\x04\x12\x0f\n\x07sale_id\x18\x1c \x01(\t\x12\x1f\n\x17unlimited_chickens_uses\x18\r \x01(\x04\x12\x13\n\x0brefill_uses\x18\x0e \x01(\x04\x12\x17\n\x0fshort_warp_uses\x18\x10 \x01(\x04\x12\x16\n\x0elong_warp_uses\x18\x11 \x01(\x04\"0\n\x12\x41\x63tionKeyValuePair\x12\x0b\n\x03key\x18\x01 \x02(\t\x12\r\n\x05value\x18\x02 \x02(\t\"\xc2\x01\n\rGenericAction\x12\x0f\n\x07user_id\x18\x01 \x01(\t\x12\x16\n\x0e\x61\x64vertising_id\x18\x07 \x01(\t\x12\x13\n\x0b\x61pprox_time\x18\x02 \x01(\x02\x12\x13\n\x0b\x61\x63tion_name\x18\x03 \x01(\t\x12$\n\x04\x64\x61ta\x18\x04 \x03(\x0b\x32\x16.ei.ActionKeyValuePair\x12\x18\n\x03\x61pp\x18\x05 \x01(\x0b\x32\x0b.ei.AppInfo\x12\x1e\n\x06\x64\x65vice\x18\x06 \x01(\x0b\x32\x0e.ei.DeviceInfo\"\x7f\n\x15VerifyPurchaseRequest\x12\x0b\n\x03sku\x18\x01 \x01(\t\x12\x16\n\x0etransaction_id\x18\x02 \x01(\t\x12\x0f\n\x07receipt\x18\x03 \x01(\t\x12\x10\n\x08platform\x18\x04 \x01(\t\x12\x1e\n\x03log\x18\x05 \x01(\x0b\x32\x11.ei.GenericAction\";\n\x16VerifyPurchaseResponse\x12\x10\n\x08verified\x18\x01 \x01(\x08\x12\x0f\n\x07message\x18\x02 \x01(\t\"\xcd\x04\n\x08\x43ontract\x12\x12\n\nidentifier\x18\x01 \x01(\t\x12\x0c\n\x04name\x18\t \x01(\t\x12\x13\n\x0b\x64\x65scription\x18\n \x01(\t\x12\x14\n\x03\x65gg\x18\x02 \x01(\x0e\x32\x07.ei.Egg\x12 \n\x05goals\x18\x03 \x03(\x0b\x32\x11.ei.Contract.Goal\x12\'\n\tgoal_sets\x18\x10 \x03(\x0b\x32\x14.ei.Contract.GoalSet\x12\x14\n\x0c\x63oop_allowed\x18\x04 \x01(\x08\x12\x15\n\rmax_coop_size\x18\x05 \x01(\r\x12\x12\n\nmax_boosts\x18\x0c \x01(\r\x12\x1d\n\x11minutes_per_token\x18\x0f \x01(\x01:\x02\x36\x30\x12\x17\n\x0f\x65xpiration_time\x18\x06 \x01(\x01\x12\x16\n\x0elength_seconds\x18\x07 \x01(\x01\x12\x15\n\rmax_soul_eggs\x18\r \x01(\x01\x12\x1a\n\x12min_client_version\x18\x0e \x01(\r\x12\r\n\x05\x64\x65\x62ug\x18\x0b \x01(\x08\x1a\xa8\x01\n\x04Goal\x12\x1a\n\x04type\x18\x01 \x01(\x0e\x32\x0c.ei.GoalType\x12\x15\n\rtarget_amount\x18\x02 \x01(\x01\x12#\n\x0breward_type\x18\x03 \x01(\x0e\x32\x0e.ei.RewardType\x12\x17\n\x0freward_sub_type\x18\x04 \x01(\t\x12\x15\n\rreward_amount\x18\x05 \x01(\x01\x12\x18\n\x10target_soul_eggs\x18\x06 \x01(\x01\x1a+\n\x07GoalSet\x12 \n\x05goals\x18\x01 \x03(\x0b\x32\x11.ei.Contract.Goal\"=\n\x10\x43ontractsRequest\x12\x11\n\tsoul_eggs\x18\x01 \x01(\x01\x12\x16\n\x0e\x63lient_version\x18\x05 \x01(\r\"y\n\x11\x43ontractsResponse\x12\x1f\n\tcontracts\x18\x01 \x03(\x0b\x32\x0c.ei.Contract\x12\x17\n\x0fwarning_message\x18\x04 \x01(\t\x12\x13\n\x0bserver_time\x18\x02 \x01(\x01\x12\x15\n\x07max_eop\x18\x03 \x01(\r:\x04\x31\x30\x30\x30\"b\n\x19\x43ontractCoopStatusRequest\x12\x1b\n\x13\x63ontract_identifier\x18\x01 \x01(\t\x12\x17\n\x0f\x63oop_identifier\x18\x02 \x01(\t\x12\x0f\n\x07user_id\x18\x03 \x01(\t\"\xe6\x05\n\x1a\x43ontractCoopStatusResponse\x12\x1b\n\x13\x63ontract_identifier\x18\x01 \x01(\t\x12\x14\n\x0ctotal_amount\x18\x02 \x01(\x01\x12\x17\n\x0f\x63oop_identifier\x18\x03 \x01(\t\x12\x45\n\x0c\x63ontributors\x18\x04 \x03(\x0b\x32/.ei.ContractCoopStatusResponse.ContributionInfo\x12\x16\n\x0e\x61uto_generated\x18\x08 \x01(\x08\x12\x0e\n\x06public\x18\n \x01(\x08\x12\x12\n\ncreator_id\x18\t \x01(\t\x12\x19\n\x11seconds_remaining\x18\x05 \x01(\x01\x12\x1d\n\x15\x61ll_members_reporting\x18\x06 \x01(\x08\x12&\n\x1egrace_period_seconds_remaining\x18\x07 \x01(\x01\x12\x36\n\x05gifts\x18\x0b \x03(\x0b\x32\'.ei.ContractCoopStatusResponse.CoopGift\x1a\x9e\x02\n\x10\x43ontributionInfo\x12\x0f\n\x07user_id\x18\x01 \x01(\t\x12\x11\n\tuser_name\x18\x02 \x01(\t\x12\x1b\n\x13\x63ontribution_amount\x18\x03 \x01(\x01\x12\x19\n\x11\x63ontribution_rate\x18\x06 \x01(\x01\x12\x12\n\nsoul_power\x18\x0b \x01(\x01\x12\x13\n\x0brank_change\x18\x08 \x01(\x05\x12\x0e\n\x06\x61\x63tive\x18\x04 \x01(\x08\x12\x1b\n\x13time_cheat_detected\x18\x07 \x01(\x08\x12\x1e\n\x08platform\x18\x05 \x01(\x0e\x32\x0c.ei.Platform\x12\x0f\n\x07push_id\x18\t \x01(\t\x12\x11\n\tban_votes\x18\n \x01(\r\x12\x14\n\x0c\x62oost_tokens\x18\x0c \x01(\r\x1a>\n\x08\x43oopGift\x12\x0f\n\x07user_id\x18\x01 \x01(\t\x12\x11\n\tuser_name\x18\x03 \x01(\t\x12\x0e\n\x06\x61mount\x18\x02 \x01(\r\"\x9f\x03\n\rLocalContract\x12\x1e\n\x08\x63ontract\x18\x01 \x01(\x0b\x32\x0c.ei.Contract\x12\x17\n\x0f\x63oop_identifier\x18\x02 \x01(\t\x12\x10\n\x08\x61\x63\x63\x65pted\x18\x07 \x01(\x08\x12\x15\n\rtime_accepted\x18\x03 \x01(\x01\x12\x11\n\tcancelled\x18\x04 \x01(\x08\x12\x0b\n\x03new\x18\x08 \x01(\x08\x12\x1c\n\x14\x63oop_shared_end_time\x18\x05 \x01(\x01\x12\"\n\x1a\x63oop_grace_period_end_time\x18\t \x01(\x01\x12#\n\x1b\x63oop_contribution_finalized\x18\n \x01(\x08\x12\'\n\x1f\x63oop_last_uploaded_contribution\x18\x0b \x01(\x01\x12\x14\n\x0c\x63oop_user_id\x18\r \x01(\t\x12%\n\x1dlast_amount_when_reward_given\x18\x06 \x01(\x01\x12\x1a\n\x12num_goals_achieved\x18\x0e \x01(\r\x12\x13\n\x0b\x62oosts_used\x18\x0c \x01(\r\x12\x0e\n\x06league\x18\x0f \x01(\r\"\xb1\x01\n\x0bMyContracts\x12\x19\n\x11\x63ontract_ids_seen\x18\x03 \x03(\t\x12$\n\tcontracts\x18\x01 \x03(\x0b\x32\x11.ei.LocalContract\x12\"\n\x07\x61rchive\x18\x02 \x03(\x0b\x32\x11.ei.LocalContract\x12=\n\x15\x63urrent_coop_statuses\x18\x04 \x03(\x0b\x32\x1e.ei.ContractCoopStatusResponse\"p\n\x10QueryCoopRequest\x12\x1b\n\x13\x63ontract_identifier\x18\x01 \x01(\t\x12\x17\n\x0f\x63oop_identifier\x18\x02 \x01(\t\x12\x0e\n\x06league\x18\x04 \x01(\r\x12\x16\n\x0e\x63lient_version\x18\x03 \x01(\r\"[\n\x11QueryCoopResponse\x12\x0e\n\x06\x65xists\x18\x01 \x01(\x08\x12\x0c\n\x04\x66ull\x18\x02 \x01(\x08\x12\x18\n\x10\x64ifferent_league\x18\x04 \x01(\x08\x12\x0e\n\x06\x62\x61nned\x18\x03 \x01(\x08\"\xe4\x01\n\x11\x43reateCoopRequest\x12\x1b\n\x13\x63ontract_identifier\x18\x01 \x01(\t\x12\x17\n\x0f\x63oop_identifier\x18\x02 \x01(\t\x12\x19\n\x11seconds_remaining\x18\x03 \x01(\x01\x12\x0f\n\x07user_id\x18\x04 \x01(\t\x12\x11\n\tuser_name\x18\x05 \x01(\t\x12\x12\n\nsoul_power\x18\x08 \x01(\x01\x12\x0e\n\x06league\x18\t \x01(\r\x12\x1e\n\x08platform\x18\x06 \x01(\x0e\x32\x0c.ei.Platform\x12\x16\n\x0e\x63lient_version\x18\x07 \x01(\r\"6\n\x12\x43reateCoopResponse\x12\x0f\n\x07success\x18\x01 \x01(\x08\x12\x0f\n\x07message\x18\x02 \x01(\t\"\xc7\x01\n\x0fJoinCoopRequest\x12\x1b\n\x13\x63ontract_identifier\x18\x01 \x01(\t\x12\x17\n\x0f\x63oop_identifier\x18\x02 \x01(\t\x12\x0f\n\x07user_id\x18\x03 \x01(\t\x12\x11\n\tuser_name\x18\x04 \x01(\t\x12\x12\n\nsoul_power\x18\x08 \x01(\x01\x12\x0e\n\x06league\x18\t \x01(\r\x12\x1e\n\x08platform\x18\x05 \x01(\x0e\x32\x0c.ei.Platform\x12\x16\n\x0e\x63lient_version\x18\x07 \x01(\r\"x\n\x10JoinCoopResponse\x12\x0f\n\x07success\x18\x01 \x01(\x08\x12\x0f\n\x07message\x18\x02 \x01(\t\x12\x0e\n\x06\x62\x61nned\x18\x04 \x01(\x08\x12\x17\n\x0f\x63oop_identifier\x18\x05 \x01(\t\x12\x19\n\x11seconds_remaining\x18\x03 \x01(\x01\"\xcd\x01\n\x13\x41utoJoinCoopRequest\x12\x1b\n\x13\x63ontract_identifier\x18\x01 \x01(\t\x12\x0f\n\x07user_id\x18\x02 \x01(\t\x12\x11\n\tuser_name\x18\x03 \x01(\t\x12\x12\n\nsoul_power\x18\x04 \x01(\x01\x12\x0e\n\x06league\x18\x08 \x01(\r\x12\x19\n\x11seconds_remaining\x18\x05 \x01(\x01\x12\x1e\n\x08platform\x18\x06 \x01(\x0e\x32\x0c.ei.Platform\x12\x16\n\x0e\x63lient_version\x18\x07 \x01(\r\"\x98\x01\n\x1cUpdateCoopPermissionsRequest\x12\x1b\n\x13\x63ontract_identifier\x18\x01 \x01(\t\x12\x17\n\x0f\x63oop_identifier\x18\x02 \x01(\t\x12\x1a\n\x12requesting_user_id\x18\x03 \x01(\t\x12\x0e\n\x06public\x18\x04 \x01(\x08\x12\x16\n\x0e\x63lient_version\x18\x05 \x01(\r\"A\n\x1dUpdateCoopPermissionsResponse\x12\x0f\n\x07success\x18\x01 \x01(\x08\x12\x0f\n\x07message\x18\x02 \x01(\t\"{\n\x10LeaveCoopRequest\x12\x1b\n\x13\x63ontract_identifier\x18\x01 \x01(\t\x12\x17\n\x0f\x63oop_identifier\x18\x02 \x01(\t\x12\x19\n\x11player_identifier\x18\x03 \x01(\t\x12\x16\n\x0e\x63lient_version\x18\x07 \x01(\r\"\xca\x01\n\x15GiftPlayerCoopRequest\x12\x1b\n\x13\x63ontract_identifier\x18\x01 \x01(\t\x12\x17\n\x0f\x63oop_identifier\x18\x02 \x01(\t\x12\x19\n\x11player_identifier\x18\x03 \x01(\t\x12\x1a\n\x12requesting_user_id\x18\x04 \x01(\t\x12\x1c\n\x14requesting_user_name\x18\x06 \x01(\t\x12\x0e\n\x06\x61mount\x18\x05 \x01(\r\x12\x16\n\x0e\x63lient_version\x18\x07 \x01(\r\"\x9c\x01\n\x15KickPlayerCoopRequest\x12\x1b\n\x13\x63ontract_identifier\x18\x01 \x01(\t\x12\x17\n\x0f\x63oop_identifier\x18\x02 \x01(\t\x12\x19\n\x11player_identifier\x18\x03 \x01(\t\x12\x1a\n\x12requesting_user_id\x18\x04 \x01(\t\x12\x16\n\x0e\x63lient_version\x18\x07 \x01(\r\"\xe4\x01\n\x1f\x43ontractCoopStatusUpdateRequest\x12\x0f\n\x07user_id\x18\x01 \x01(\t\x12\x1b\n\x13\x63ontract_identifier\x18\x02 \x01(\t\x12\x17\n\x0f\x63oop_identifier\x18\x03 \x01(\t\x12\x14\n\x0cpush_user_id\x18\x08 \x01(\t\x12\x0e\n\x06\x61mount\x18\x04 \x01(\x01\x12\x0c\n\x04rate\x18\x05 \x01(\x01\x12\x1c\n\x14time_cheats_detected\x18\x06 \x01(\r\x12\x12\n\nsoul_power\x18\x07 \x01(\x01\x12\x14\n\x0c\x62oost_tokens\x18\t \x01(\r\"5\n ContractCoopStatusUpdateResponse\x12\x11\n\tfinalized\x18\x01 \x01(\x08\"R\n\x13UserDataInfoRequest\x12\x0f\n\x07user_id\x18\x01 \x01(\t\x12\x11\n\tdevice_id\x18\x02 \x01(\t\x12\x17\n\x0f\x62\x61\x63kup_checksum\x18\x03 \x01(\x04\"d\n\x14UserDataInfoResponse\x12\x17\n\x0f\x62\x61\x63kup_checksum\x18\x01 \x01(\x04\x12\x19\n\x11\x62\x61\x63kup_total_cash\x18\x02 \x01(\x01\x12\x18\n\x10\x63oop_memberships\x18\x03 \x03(\t\"V\n\x17\x43learAllUserDataRequest\x12\x0f\n\x07user_id\x18\x01 \x01(\t\x12\x11\n\tdevice_id\x18\x02 \x01(\t\x12\x17\n\x0f\x62\x61\x63kup_checksum\x18\x03 \x01(\x04\"r\n\nServerGift\x12\x0f\n\x07user_id\x18\x01 \x01(\t\x12#\n\x0breward_type\x18\x03 \x01(\x0e\x32\x0e.ei.RewardType\x12\x17\n\x0freward_sub_type\x18\x04 \x01(\t\x12\x15\n\rreward_amount\x18\x05 \x01(\x01\"\xa5\x01\n\x13PeriodicalsResponse\x12\x1c\n\x05sales\x18\x01 \x01(\x0b\x32\r.ei.SalesInfo\x12\'\n\x06\x65vents\x18\x02 \x01(\x0b\x32\x17.ei.EggIncCurrentEvents\x12(\n\tcontracts\x18\x03 \x01(\x0b\x32\x15.ei.ContractsResponse\x12\x1d\n\x05gifts\x18\x04 \x03(\x0b\x32\x0e.ei.ServerGift\"\xef\x01\n\x15GetPeriodicalsRequest\x12\x0f\n\x07user_id\x18\x01 \x01(\t\x12\x12\n\npiggy_full\x18\x02 \x01(\x08\x12\x18\n\x10piggy_found_full\x18\x03 \x01(\x08\x12\x1d\n\x15seconds_full_realtime\x18\x04 \x01(\x01\x12\x1d\n\x15seconds_full_gametime\x18\x05 \x01(\x01\x12\x17\n\x0flost_increments\x18\x07 \x01(\r\x12\x11\n\tsoul_eggs\x18\x08 \x01(\x01\x12\x1e\n\x16\x63urrent_client_version\x18\n \x01(\r\x12\r\n\x05\x64\x65\x62ug\x18\x0b \x01(\x08\"d\n\x14\x41\x64\x41ttributionRawData\x12\x14\n\x0c\x64\x65vice_ad_id\x18\x01 \x01(\t\x12\x0f\n\x07user_id\x18\x04 \x01(\t\x12\x12\n\nad_network\x18\x02 \x01(\t\x12\x11\n\tjson_data\x18\x03 \x01(\t\"\xb8\x01\n\x10\x41\x64\x41ttributionRow\x12\x0f\n\x07user_id\x18\x01 \x01(\t\x12\r\n\x05\x61\x64_id\x18\x02 \x01(\t\x12\x12\n\nad_network\x18\x03 \x01(\t\x12\x10\n\x08\x63\x61mpaign\x18\x04 \x01(\t\x12\x0f\n\x07keyword\x18\x05 \x01(\t\x12\r\n\x05\x65xtra\x18\x06 \x01(\t\x12\x12\n\nclick_date\x18\x07 \x01(\x02\x12\x15\n\rdownload_date\x18\x08 \x01(\x02\x12\x13\n\x0b\x61pprox_time\x18\t \x01(\x02\"\x8d\x03\n\x11\x41\x64\x41ttributionInfo\x12\x14\n\x0c\x64\x65vice_ad_id\x18\x01 \x01(\t\x12\x14\n\x0cnetwork_name\x18\x02 \x01(\t\x12\x13\n\x0b\x61ttribution\x18\x03 \x01(\x08\x12\x10\n\x08org_name\x18\x04 \x01(\t\x12\x0e\n\x06org_id\x18\x05 \x01(\t\x12\x15\n\rcampaign_name\x18\x06 \x01(\t\x12\x13\n\x0b\x63\x61mpaign_id\x18\x07 \x01(\t\x12\x12\n\nclick_date\x18\x08 \x01(\t\x12\x17\n\x0f\x63onversion_date\x18\t \x01(\t\x12\x17\n\x0f\x63onversion_type\x18\n \x01(\t\x12\x0b\n\x03geo\x18\x0b \x01(\t\x12\x14\n\x0c\x61\x64group_name\x18\x0c \x01(\t\x12\x12\n\nadgroup_id\x18\r \x01(\t\x12\x0f\n\x07keyword\x18\x0e \x01(\t\x12\x12\n\nkeyword_id\x18\x0f \x01(\t\x12\x15\n\rkeyword_extra\x18\x10 \x01(\t\x12\x18\n\x10\x63reativeset_name\x18\x11 \x01(\t\x12\x16\n\x0e\x63reativeset_id\x18\x12 \x01(\t*\x1e\n\x08Platform\x12\x07\n\x03IOS\x10\x01\x12\t\n\x05\x44ROID\x10\x02*)\n\x10\x44\x65viceFormFactor\x12\t\n\x05PHONE\x10\x01\x12\n\n\x06TABLET\x10\x02*k\n\tAdNetwork\x12\n\n\x06VUNGLE\x10\x00\x12\x0e\n\nCHARTBOOST\x10\x01\x12\r\n\tAD_COLONY\x10\x02\x12\x0c\n\x08HYPER_MX\x10\x03\x12\t\n\x05UNITY\x10\x04\x12\x0c\n\x08\x46\x41\x43\x45\x42OOK\x10\x05\x12\x0c\n\x08\x41PPLOVIN\x10\x06*\xee\x02\n\x03\x45gg\x12\n\n\x06\x45\x44IBLE\x10\x01\x12\r\n\tSUPERFOOD\x10\x02\x12\x0b\n\x07MEDICAL\x10\x03\x12\x0f\n\x0bROCKET_FUEL\x10\x04\x12\x12\n\x0eSUPER_MATERIAL\x10\x05\x12\n\n\x06\x46USION\x10\x06\x12\x0b\n\x07QUANTUM\x10\x07\x12\x0f\n\x0bIMMORTALITY\x10\x08\x12\x0b\n\x07TACHYON\x10\t\x12\x0c\n\x08GRAVITON\x10\n\x12\r\n\tDILITHIUM\x10\x0b\x12\x0b\n\x07PRODIGY\x10\x0c\x12\r\n\tTERRAFORM\x10\r\x12\x0e\n\nANTIMATTER\x10\x0e\x12\x0f\n\x0b\x44\x41RK_MATTER\x10\x0f\x12\x06\n\x02\x41I\x10\x10\x12\n\n\x06NEBULA\x10\x11\x12\x0c\n\x08UNIVERSE\x10\x12\x12\x11\n\rENLIGHTENMENT\x10\x13\x12\r\n\tCHOCOLATE\x10\x64\x12\n\n\x06\x45\x41STER\x10\x65\x12\x10\n\x0cWATERBALLOON\x10\x66\x12\x0c\n\x08\x46IREWORK\x10g\x12\x0b\n\x07PUMPKIN\x10h\x12\x0c\n\x07UNKNOWN\x10\xe8\x07*-\n\x08\x46\x61rmType\x12\t\n\x05\x45MPTY\x10\x01\x12\x08\n\x04HOME\x10\x02\x12\x0c\n\x08\x43ONTRACT\x10\x03*+\n\x08GoalType\x12\r\n\tEGGS_LAID\x10\x01\x12\x10\n\x0cUNKNOWN_GOAL\x10\x64*\xc9\x01\n\nRewardType\x12\x08\n\x04\x43\x41SH\x10\x01\x12\x08\n\x04GOLD\x10\x02\x12\r\n\tSOUL_EGGS\x10\x03\x12\x14\n\x10\x45GGS_OF_PROPHECY\x10\x04\x12\x16\n\x12\x45PIC_RESEARCH_ITEM\x10\x05\x12\x0e\n\nPIGGY_FILL\x10\x06\x12\x14\n\x10PIGGY_MULTIPLIER\x10\x07\x12\x14\n\x10PIGGY_LEVEL_BUMP\x10\x08\x12\t\n\x05\x42OOST\x10\t\x12\x0f\n\x0b\x42OOST_TOKEN\x10\n\x12\x12\n\x0eUNKNOWN_REWARD\x10\x64') + +_globals = globals() +_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) +_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'ei_pb2', _globals) +if _descriptor._USE_C_DESCRIPTORS == False: + DESCRIPTOR._options = None + _globals['_PLATFORM']._serialized_start=12938 + _globals['_PLATFORM']._serialized_end=12968 + _globals['_DEVICEFORMFACTOR']._serialized_start=12970 + _globals['_DEVICEFORMFACTOR']._serialized_end=13011 + _globals['_ADNETWORK']._serialized_start=13013 + _globals['_ADNETWORK']._serialized_end=13120 + _globals['_EGG']._serialized_start=13123 + _globals['_EGG']._serialized_end=13489 + _globals['_FARMTYPE']._serialized_start=13491 + _globals['_FARMTYPE']._serialized_end=13536 + _globals['_GOALTYPE']._serialized_start=13538 + _globals['_GOALTYPE']._serialized_end=13581 + _globals['_REWARDTYPE']._serialized_start=13584 + _globals['_REWARDTYPE']._serialized_end=13785 + _globals['_BACKUP']._serialized_start=17 + _globals['_BACKUP']._serialized_end=4928 + _globals['_BACKUP_SETTINGS']._serialized_start=493 + _globals['_BACKUP_SETTINGS']._serialized_end=1202 + _globals['_BACKUP_TUTORIAL']._serialized_start=1205 + _globals['_BACKUP_TUTORIAL']._serialized_end=1469 + _globals['_BACKUP_STATS']._serialized_start=1472 + _globals['_BACKUP_STATS']._serialized_end=1949 + _globals['_BACKUP_GAME']._serialized_start=1952 + _globals['_BACKUP_GAME']._serialized_end=3093 + _globals['_BACKUP_SIMULATION']._serialized_start=3096 + _globals['_BACKUP_SIMULATION']._serialized_end=3911 + _globals['_BACKUP_MISSION']._serialized_start=3913 + _globals['_BACKUP_MISSION']._serialized_end=4040 + _globals['_BACKUP_MISC']._serialized_start=4043 + _globals['_BACKUP_MISC']._serialized_end=4594 + _globals['_BACKUP_RESEARCHITEM']._serialized_start=4596 + _globals['_BACKUP_RESEARCHITEM']._serialized_end=4637 + _globals['_BACKUP_NEWSHEADLINE']._serialized_start=4639 + _globals['_BACKUP_NEWSHEADLINE']._serialized_end=4679 + _globals['_BACKUP_ACHIEVEMENTINFO']._serialized_start=4681 + _globals['_BACKUP_ACHIEVEMENTINFO']._serialized_end=4728 + _globals['_BACKUP_ACTIVEBOOST']._serialized_start=4730 + _globals['_BACKUP_ACTIVEBOOST']._serialized_end=4810 + _globals['_BACKUP_OWNEDBOOST']._serialized_start=4812 + _globals['_BACKUP_OWNEDBOOST']._serialized_end=4857 + _globals['_BACKUP_MISSIONINFO']._serialized_start=4859 + _globals['_BACKUP_MISSIONINFO']._serialized_end=4928 + _globals['_EGGINCFIRSTCONTACTREQUEST']._serialized_start=4930 + _globals['_EGGINCFIRSTCONTACTREQUEST']._serialized_end=5030 + _globals['_EGGINCFIRSTCONTACTRESPONSE']._serialized_start=5032 + _globals['_EGGINCFIRSTCONTACTRESPONSE']._serialized_end=5088 + _globals['_EGGINCADCONFIG']._serialized_start=5090 + _globals['_EGGINCADCONFIG']._serialized_end=5147 + _globals['_DAILYGIFTINFO']._serialized_start=5149 + _globals['_DAILYGIFTINFO']._serialized_end=5214 + _globals['_SALESINFOREQUEST']._serialized_start=5217 + _globals['_SALESINFOREQUEST']._serialized_end=5417 + _globals['_IAPSALEENTRY']._serialized_start=5419 + _globals['_IAPSALEENTRY']._serialized_end=5522 + _globals['_SALESINFO']._serialized_start=5524 + _globals['_SALESINFO']._serialized_end=5568 + _globals['_EGGINCEVENT']._serialized_start=5570 + _globals['_EGGINCEVENT']._serialized_end=5682 + _globals['_EGGINCCURRENTEVENTS']._serialized_start=5684 + _globals['_EGGINCCURRENTEVENTS']._serialized_end=5738 + _globals['_DEVICEINFO']._serialized_start=5741 + _globals['_DEVICEINFO']._serialized_end=6038 + _globals['_APPINFO']._serialized_start=6041 + _globals['_APPINFO']._serialized_end=6766 + _globals['_ACTIONKEYVALUEPAIR']._serialized_start=6768 + _globals['_ACTIONKEYVALUEPAIR']._serialized_end=6816 + _globals['_GENERICACTION']._serialized_start=6819 + _globals['_GENERICACTION']._serialized_end=7013 + _globals['_VERIFYPURCHASEREQUEST']._serialized_start=7015 + _globals['_VERIFYPURCHASEREQUEST']._serialized_end=7142 + _globals['_VERIFYPURCHASERESPONSE']._serialized_start=7144 + _globals['_VERIFYPURCHASERESPONSE']._serialized_end=7203 + _globals['_CONTRACT']._serialized_start=7206 + _globals['_CONTRACT']._serialized_end=7795 + _globals['_CONTRACT_GOAL']._serialized_start=7582 + _globals['_CONTRACT_GOAL']._serialized_end=7750 + _globals['_CONTRACT_GOALSET']._serialized_start=7752 + _globals['_CONTRACT_GOALSET']._serialized_end=7795 + _globals['_CONTRACTSREQUEST']._serialized_start=7797 + _globals['_CONTRACTSREQUEST']._serialized_end=7858 + _globals['_CONTRACTSRESPONSE']._serialized_start=7860 + _globals['_CONTRACTSRESPONSE']._serialized_end=7981 + _globals['_CONTRACTCOOPSTATUSREQUEST']._serialized_start=7983 + _globals['_CONTRACTCOOPSTATUSREQUEST']._serialized_end=8081 + _globals['_CONTRACTCOOPSTATUSRESPONSE']._serialized_start=8084 + _globals['_CONTRACTCOOPSTATUSRESPONSE']._serialized_end=8826 + _globals['_CONTRACTCOOPSTATUSRESPONSE_CONTRIBUTIONINFO']._serialized_start=8476 + _globals['_CONTRACTCOOPSTATUSRESPONSE_CONTRIBUTIONINFO']._serialized_end=8762 + _globals['_CONTRACTCOOPSTATUSRESPONSE_COOPGIFT']._serialized_start=8764 + _globals['_CONTRACTCOOPSTATUSRESPONSE_COOPGIFT']._serialized_end=8826 + _globals['_LOCALCONTRACT']._serialized_start=8829 + _globals['_LOCALCONTRACT']._serialized_end=9244 + _globals['_MYCONTRACTS']._serialized_start=9247 + _globals['_MYCONTRACTS']._serialized_end=9424 + _globals['_QUERYCOOPREQUEST']._serialized_start=9426 + _globals['_QUERYCOOPREQUEST']._serialized_end=9538 + _globals['_QUERYCOOPRESPONSE']._serialized_start=9540 + _globals['_QUERYCOOPRESPONSE']._serialized_end=9631 + _globals['_CREATECOOPREQUEST']._serialized_start=9634 + _globals['_CREATECOOPREQUEST']._serialized_end=9862 + _globals['_CREATECOOPRESPONSE']._serialized_start=9864 + _globals['_CREATECOOPRESPONSE']._serialized_end=9918 + _globals['_JOINCOOPREQUEST']._serialized_start=9921 + _globals['_JOINCOOPREQUEST']._serialized_end=10120 + _globals['_JOINCOOPRESPONSE']._serialized_start=10122 + _globals['_JOINCOOPRESPONSE']._serialized_end=10242 + _globals['_AUTOJOINCOOPREQUEST']._serialized_start=10245 + _globals['_AUTOJOINCOOPREQUEST']._serialized_end=10450 + _globals['_UPDATECOOPPERMISSIONSREQUEST']._serialized_start=10453 + _globals['_UPDATECOOPPERMISSIONSREQUEST']._serialized_end=10605 + _globals['_UPDATECOOPPERMISSIONSRESPONSE']._serialized_start=10607 + _globals['_UPDATECOOPPERMISSIONSRESPONSE']._serialized_end=10672 + _globals['_LEAVECOOPREQUEST']._serialized_start=10674 + _globals['_LEAVECOOPREQUEST']._serialized_end=10797 + _globals['_GIFTPLAYERCOOPREQUEST']._serialized_start=10800 + _globals['_GIFTPLAYERCOOPREQUEST']._serialized_end=11002 + _globals['_KICKPLAYERCOOPREQUEST']._serialized_start=11005 + _globals['_KICKPLAYERCOOPREQUEST']._serialized_end=11161 + _globals['_CONTRACTCOOPSTATUSUPDATEREQUEST']._serialized_start=11164 + _globals['_CONTRACTCOOPSTATUSUPDATEREQUEST']._serialized_end=11392 + _globals['_CONTRACTCOOPSTATUSUPDATERESPONSE']._serialized_start=11394 + _globals['_CONTRACTCOOPSTATUSUPDATERESPONSE']._serialized_end=11447 + _globals['_USERDATAINFOREQUEST']._serialized_start=11449 + _globals['_USERDATAINFOREQUEST']._serialized_end=11531 + _globals['_USERDATAINFORESPONSE']._serialized_start=11533 + _globals['_USERDATAINFORESPONSE']._serialized_end=11633 + _globals['_CLEARALLUSERDATAREQUEST']._serialized_start=11635 + _globals['_CLEARALLUSERDATAREQUEST']._serialized_end=11721 + _globals['_SERVERGIFT']._serialized_start=11723 + _globals['_SERVERGIFT']._serialized_end=11837 + _globals['_PERIODICALSRESPONSE']._serialized_start=11840 + _globals['_PERIODICALSRESPONSE']._serialized_end=12005 + _globals['_GETPERIODICALSREQUEST']._serialized_start=12008 + _globals['_GETPERIODICALSREQUEST']._serialized_end=12247 + _globals['_ADATTRIBUTIONRAWDATA']._serialized_start=12249 + _globals['_ADATTRIBUTIONRAWDATA']._serialized_end=12349 + _globals['_ADATTRIBUTIONROW']._serialized_start=12352 + _globals['_ADATTRIBUTIONROW']._serialized_end=12536 + _globals['_ADATTRIBUTIONINFO']._serialized_start=12539 + _globals['_ADATTRIBUTIONINFO']._serialized_end=12936 +# @@protoc_insertion_point(module_scope) diff --git a/events.py b/events.py new file mode 100644 index 0000000..50634dc --- /dev/null +++ b/events.py @@ -0,0 +1,92 @@ +# events.py - Event Scheduler for the server +import ei_pb2 as EIProto +import random +import datetime +import time + +### +# BEHAVIOR ANALYSIS: +# Every Sunday - Soul Eggs 2x/3x event +# They typically last 24 hours +# Multiple *can* occur at once, albeit rarely +# Some events are more common than others. +# Thank you https://wasmegg-carpet.netlify.app/events/ for providing a database of past events. +### +# Changes compared to original game: +# No piggy bank events - you can't crack one open anyway. +### +# We can however, just lazily apply a "pre-set" map of events. +# If it's multiple events, it's an array, else it's an EIProto.EggIncEvent +### + +event_calendar = [] +def create_event_proto(type, internal_name, subtitle, multiplier): + evt = EIProto.EggIncEvent() + evt.type = type + evt.multiplier = multiplier + evt.subtitle = subtitle + evt.identifier = internal_name + return evt + +event_calendar.append([ + create_event_proto("vehicle-sale", "VEHICLE SALE", "75% off all vehicles", 0.25), + create_event_proto("drone-boost", "GENEROUS DRONES", "5x drone rewards", 5.0) +]) +event_calendar.append(create_event_proto("epic-research-sale", "EPIC RESEARCH SALE", "30% off Epic Research Upgrades", 0.7)) +event_calendar.append(create_event_proto("research-sale", "RESEARCH SALE", "70% off Research Upgrades", 0.3)) +event_calendar.append(create_event_proto("hab-sale", "HAB SALE", "70% OFF HEN HOUSES!", 0.3)) +event_calendar.append(create_event_proto("boost-sale", "BOOST SALE", "30% OFF BOOSTS!", 0.7)) +event_calendar.append(create_event_proto("earnings-boost", "CASH BOOST", "3x EARNINGS!", 3.0)) +event_calendar.append(create_event_proto("gift-boost", "GENEROUS GIFTS", "4x GIFTS!", 4.0)) +event_calendar.append(create_event_proto("boost-duration", "BOOST TIME+", "DOUBLE BOOST TIME", 2.0)) +event_calendar.append(create_event_proto("hab-sale", "HAB SALE", "70% OFF HEN HOUSES!", 0.3)) +event_calendar.append(create_event_proto("vehicle-sale", "VEHICLE SALE", "75% off all vehicles", 0.25)) +event_calendar.append(create_event_proto("drone-boost", "GENEROUS DRONES", "5x drone rewards", 5.0)) +event_calendar.append(create_event_proto("research-sale", "RESEARCH SALE", "70% off Research Upgrades", 0.3)) +event_calendar.append(create_event_proto("boost-sale", "BOOST SALE", "30% OFF BOOSTS!", 0.7)) +event_calendar.append(create_event_proto("earnings-boost", "CASH BOOST", "3x EARNINGS!", 3.0)) +event_calendar.append(create_event_proto("hab-sale", "HAB SALE", "70% OFF HEN HOUSES!", 0.3)) +event_calendar.append(create_event_proto("boost-duration", "BOOST TIME+", "DOUBLE BOOST TIME", 2.0)) +event_calendar.append(create_event_proto("gift-boost", "GENEROUS GIFTS", "4x GIFTS!", 4.0)) +event_calendar.append(create_event_proto("epic-research-sale", "EPIC RESEARCH SALE", "30% off Epic Research Upgrades", 0.7)) +event_calendar.append(create_event_proto("vehicle-sale", "VEHICLE SALE", "75% off all vehicles", 0.25)) +event_calendar.append(create_event_proto("drone-boost", "GENEROUS DRONES", "5x drone rewards", 5.0)) +event_calendar.append(create_event_proto("boost-duration", "BOOST TIME+", "DOUBLE BOOST TIME", 2.0)) +event_calendar.append(create_event_proto("research-sale", "RESEARCH SALE", "70% off Research Upgrades", 0.3)) +event_calendar.append(create_event_proto("earnings-boost", "CASH BOOST", "3x EARNINGS!", 3.0)) +event_calendar.append(create_event_proto("hab-sale", "HAB SALE", "70% OFF HEN HOUSES!", 0.3)) +event_calendar.append(create_event_proto("gift-boost", "GENEROUS GIFTS", "4x GIFTS!", 4.0)) +event_calendar.append(create_event_proto("vehicle-sale", "VEHICLE SALE", "75% off all vehicles", 0.25)) +event_calendar.append(create_event_proto("drone-boost", "GENEROUS DRONES", "5x drone rewards", 5.0)) +event_calendar.append(create_event_proto("earnings-boost", "CASH BOOST", "3x EARNINGS!", 3.0)) +event_calendar.append(create_event_proto("epic-research-sale", "EPIC RESEARCH SALE", "30% off Epic Research Upgrades", 0.7)) +event_calendar.append(create_event_proto("boost-duration", "BOOST TIME+", "DOUBLE BOOST TIME", 2.0)) +event_calendar.append(create_event_proto("hab-sale", "HAB SALE", "70% OFF HEN HOUSES!", 0.3)) + +triple_prestige_event = create_event_proto("prestige-boost", "PRESTIGE BOOST", "TRIPLE PRESTIGE!", 3.0) +double_prestige_event = create_event_proto("prestige-boost", "PRESTIGE BOOST", "DOUBLE PRESTIGE!", 2.0) + +def get_active_events(): + date = datetime.datetime.today() + delta = (datetime.datetime.combine(date + datetime.timedelta(days=1), datetime.time.min) - date).seconds + cur_day = date.day + res = [] + # it's a sunday, we have a fixed prestige event + if date.isoweekday() == 7: + # create a seed based off year and week to determine if we should use triple or double prestige this week + iso_calendar = date.isocalendar() + seed = int(str(iso_calendar.year) + str(iso_calendar.week)) + srng = random.Random(seed) + # 50/50 chance of it being either + if srng.random() < 0.5: + res.append(double_prestige_event) + else: + res.append(triple_prestige_event) + if type(event_calendar[cur_day]) is list: + res = event_calendar[cur_day] + else: + res.append(event_calendar[cur_day]) + # Apply duration deltas + for event in res: + event.seconds_remaining = delta + return res diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..ae97318 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,9 @@ +blinker==1.8.2 +click==8.1.7 +Flask==3.0.0 +google==3.0.0 +itsdangerous==2.2.0 +Jinja2==3.1.4 +MarkupSafe==2.1.5 +protobuf==4.24.4 +Werkzeug==3.0.3