void THDRegisterCudaStream(cudaStream_t stream) { streamIdMap.emplace(stream, nextStreamId++); }
namespace pyston { using namespace pyston::assembler; // TODO not right place for this... int64_t ICInvalidator::version() { return cur_version; } void ICInvalidator::addDependent(ICSlotInfo* entry_info) { dependents.insert(entry_info); } void ICInvalidator::invalidateAll() { cur_version++; for (std::unordered_set<ICSlotInfo*>::iterator it = dependents.begin(), end = dependents.end(); it != end; ++it) { (*it)->clear(); } dependents.clear(); } void ICSlotInfo::clear() { ic->clear(this); } ICSlotRewrite::ICSlotRewrite(ICInfo* ic, const char* debug_name) : ic(ic), debug_name(debug_name) { buf = (uint8_t*)malloc(ic->getSlotSize()); assembler = new Assembler(buf, ic->getSlotSize()); assembler->nop(); if (VERBOSITY()) printf("starting %s icentry\n", debug_name); } ICSlotRewrite::~ICSlotRewrite() { delete assembler; free(buf); } void ICSlotRewrite::commit(uint64_t decision_path, CommitHook *hook) { bool still_valid = true; for (int i = 0; i < dependencies.size(); i++) { int orig_version = dependencies[i].second; ICInvalidator *invalidator = dependencies[i].first; if (orig_version != invalidator->version()) { still_valid = false; break; } } if (!still_valid) { if (VERBOSITY()) printf("not committing %s icentry since a dependency got updated before commit\n", debug_name); return; } ICSlotInfo *ic_entry = ic->pickEntryForRewrite(decision_path, debug_name); if (ic_entry == NULL) return; for (int i = 0; i < dependencies.size(); i++) { ICInvalidator *invalidator = dependencies[i].first; invalidator->addDependent(ic_entry); } uint8_t* slot_start = (uint8_t*)ic->start_addr + ic_entry->idx * ic->getSlotSize(); uint8_t* continue_point = (uint8_t*)ic->continue_addr; hook->finishAssembly(continue_point - slot_start); assert(assembler->isExactlyFull()); //if (VERBOSITY()) printf("Commiting to %p-%p\n", start, start + ic->slot_size); memcpy(slot_start, buf, ic->getSlotSize()); llvm::sys::Memory::InvalidateInstructionCache(slot_start, ic->getSlotSize()); } void ICSlotRewrite::addDependenceOn(ICInvalidator &invalidator) { dependencies.push_back(std::make_pair(&invalidator, invalidator.version())); } int ICSlotRewrite::getSlotSize() { return ic->getSlotSize(); } int ICSlotRewrite::getFuncStackSize() { return ic->stack_info.stack_size; } int ICSlotRewrite::getScratchRbpOffset() { assert(ic->stack_info.has_scratch); assert(ic->stack_info.scratch_bytes); return ic->stack_info.scratch_rbp_offset; } int ICSlotRewrite::getScratchBytes() { assert(ic->stack_info.has_scratch); assert(ic->stack_info.scratch_bytes); return ic->stack_info.scratch_bytes; } assembler::GenericRegister ICSlotRewrite::returnRegister() { return ic->return_register; } ICSlotRewrite* ICInfo::startRewrite(const char* debug_name) { return new ICSlotRewrite(this, debug_name); } ICSlotInfo* ICInfo::pickEntryForRewrite(uint64_t decision_path, const char* debug_name) { for (int i = 0; i < getNumSlots(); i++) { SlotInfo &sinfo = slots[i]; if (!sinfo.is_patched) { if (VERBOSITY()) { printf("committing %s icentry to unused slot %d at %p\n", debug_name, i, start_addr); } sinfo.is_patched = true; sinfo.decision_path = decision_path; return &sinfo.entry; } } for (int i = 0; i < getNumSlots(); i++) { SlotInfo &sinfo = slots[i]; if (sinfo.is_patched && sinfo.decision_path != decision_path) { continue; } if (VERBOSITY()) { printf("committing %s icentry to in-use slot %d at %p\n", debug_name, i, start_addr); } sinfo.is_patched = true; sinfo.decision_path = decision_path; return &sinfo.entry; } if (VERBOSITY()) printf("not committing %s icentry since it is not compatible (%lx)\n", debug_name, decision_path); return NULL; } ICInfo::ICInfo(void* start_addr, void* continue_addr, StackInfo stack_info, int num_slots, int slot_size, llvm::CallingConv::ID calling_conv, const std::unordered_set<int> &live_outs, assembler::GenericRegister return_register) : stack_info(stack_info), num_slots(num_slots), slot_size(slot_size), calling_conv(calling_conv), live_outs(live_outs.begin(), live_outs.end()), return_register(return_register), start_addr(start_addr), continue_addr(continue_addr) { for (int i = 0; i < num_slots; i++) { slots.push_back(SlotInfo(this, i)); } } static std::unordered_map<void*, ICInfo*> ics_by_return_addr; void registerCompiledPatchpoint(uint8_t* start_addr, PatchpointSetupInfo* pp, StackInfo stack_info, std::unordered_set<int> live_outs) { int size = pp->totalSize(); uint8_t* end_addr = start_addr + size; void* slowpath_addr = end_addr; uint8_t* rtn_addr; assembler::GenericRegister return_register; assert(pp->getCallingConvention() == llvm::CallingConv::C || pp->getCallingConvention() == llvm::CallingConv::PreserveAll); if (pp->hasReturnValue()) { static const int DWARF_RAX = 0; // It's possible that the return value doesn't get used, in which case // we can avoid copying back into RAX at the end if (live_outs.count(DWARF_RAX)) { live_outs.erase(DWARF_RAX); } // TODO we only need to do this if 0 was in live_outs, since if it wasn't, that indicates // the return value won't be used and we can optimize based on that. return_register = assembler::RAX; } if (pp->getCallingConvention() != llvm::CallingConv::C) { uint8_t* slowpath_start = start_addr + pp->num_slots * pp->slot_size; rtn_addr = initializePatchpoint2(start_addr, slowpath_start, (uint8_t*)end_addr, stack_info, live_outs); } else { //for (int regnum : live_outs) { //// LLVM has a bug where it incorrectly determines the set of liveouts; //// so far it only seems to add additional ones to the set, which should //// hopefully be safe. //// Otherwise, I'd like to test here that it's only the registers //// that we'd expect to be saved... //ASSERT(regnum == 0 || regnum == 3 || regnum == 6 || regnum == 12 || regnum == 13 || regnum == 14 || regnum == 15 || regnum == 7, "%d", regnum); //} initializePatchpoint(start_addr, size); rtn_addr = end_addr; } // we can let the user just slide down the nop section, but instead // emit jumps to the end. // Not sure if this is worth it or not? for (int i = 0; i < pp->num_slots; i++) { uint8_t* start = start_addr + i * pp->slot_size; //std::unique_ptr<MCWriter> writer(createMCWriter(start, pp->slot_size * (pp->num_slots - i), 0)); //writer->emitNop(); //writer->emitGuardFalse(); std::unique_ptr<Assembler> writer(new Assembler(start, pp->slot_size)); writer->nop(); //writer->trap(); writer->jmp(JumpDestination::fromStart(pp->slot_size * (pp->num_slots - i))); } ics_by_return_addr[rtn_addr] = new ICInfo(start_addr, end_addr, stack_info, pp->num_slots, pp->slot_size, pp->getCallingConvention(), live_outs, return_register); } ICInfo* getICInfo(void* rtn_addr) { std::unordered_map<void*, ICInfo*>::iterator it = ics_by_return_addr.find(rtn_addr); if (it == ics_by_return_addr.end()) return NULL; return it->second; } void ICInfo::clear(ICSlotInfo* icentry) { assert(icentry); uint8_t* start = (uint8_t*)start_addr + icentry->idx * getSlotSize(); if (VERBOSITY()) printf("clearing patchpoint %p, slot at %p\n", start_addr, start); std::unique_ptr<Assembler> writer(new Assembler(start, getSlotSize())); writer->nop(); writer->jmp(JumpDestination::fromStart(getSlotSize())); //std::unique_ptr<MCWriter> writer(createMCWriter(start, getSlotSize(), 0)); //writer->emitNop(); //writer->emitGuardFalse(); //writer->endWithSlowpath(); llvm::sys::Memory::InvalidateInstructionCache(start, getSlotSize()); } }
Obj * get(const Util::StringIdentifier & id)const{ const auto it = map_idToObj.find(id); return it==map_idToObj.end() ? nullptr : it->second.get(); }
bool is_member(std::string name) { return stringTextureMap.find(name) != std::end(name); }
inline const int index(const W& word) { return (word_idx.find(word) == word_idx.end()) ? 0 : word_idx[word]; }
void BakerCLI::bakeFile(QUrl inputUrl, const QString& outputPath, const QString& type) { // if the URL doesn't have a scheme, assume it is a local file if (inputUrl.scheme() != "http" && inputUrl.scheme() != "https" && inputUrl.scheme() != "ftp" && inputUrl.scheme() != "file") { inputUrl = QUrl::fromLocalFile(inputUrl.toString()); } qDebug() << "Baking file type: " << type; static const QString MODEL_EXTENSION { "fbx" }; static const QString SCRIPT_EXTENSION { "js" }; // check what kind of baker we should be creating bool isFBX = type == MODEL_EXTENSION; bool isScript = type == SCRIPT_EXTENSION; // If the type doesn't match the above, we assume we have a texture, and the type specified is the // texture usage type (albedo, cubemap, normals, etc.) auto url = inputUrl.toDisplayString(); auto idx = url.lastIndexOf('.'); auto extension = idx >= 0 ? url.mid(idx + 1).toLower() : ""; bool isSupportedImage = QImageReader::supportedImageFormats().contains(extension.toLatin1()); _outputPath = outputPath; // create our appropiate baker if (isFBX) { _baker = std::unique_ptr<Baker> { new FBXBaker(inputUrl, []() -> QThread* { return Oven::instance().getNextWorkerThread(); }, outputPath) }; _baker->moveToThread(Oven::instance().getNextWorkerThread()); } else if (isScript) { _baker = std::unique_ptr<Baker> { new JSBaker(inputUrl, outputPath) }; _baker->moveToThread(Oven::instance().getNextWorkerThread()); } else if (isSupportedImage) { static const std::unordered_map<QString, image::TextureUsage::Type> STRING_TO_TEXTURE_USAGE_TYPE_MAP { { "default", image::TextureUsage::DEFAULT_TEXTURE }, { "strict", image::TextureUsage::STRICT_TEXTURE }, { "albedo", image::TextureUsage::ALBEDO_TEXTURE }, { "normal", image::TextureUsage::NORMAL_TEXTURE }, { "bump", image::TextureUsage::BUMP_TEXTURE }, { "specular", image::TextureUsage::SPECULAR_TEXTURE }, { "metallic", image::TextureUsage::METALLIC_TEXTURE }, { "roughness", image::TextureUsage::ROUGHNESS_TEXTURE }, { "gloss", image::TextureUsage::GLOSS_TEXTURE }, { "emissive", image::TextureUsage::EMISSIVE_TEXTURE }, { "cube", image::TextureUsage::CUBE_TEXTURE }, { "occlusion", image::TextureUsage::OCCLUSION_TEXTURE }, { "scattering", image::TextureUsage::SCATTERING_TEXTURE }, { "lightmap", image::TextureUsage::LIGHTMAP_TEXTURE }, }; auto it = STRING_TO_TEXTURE_USAGE_TYPE_MAP.find(type); if (it == STRING_TO_TEXTURE_USAGE_TYPE_MAP.end()) { qCDebug(model_baking) << "Unknown texture usage type:" << type; QCoreApplication::exit(OVEN_STATUS_CODE_FAIL); } _baker = std::unique_ptr<Baker> { new TextureBaker(inputUrl, it->second, outputPath) }; _baker->moveToThread(Oven::instance().getNextWorkerThread()); } else { qCDebug(model_baking) << "Failed to determine baker type for file" << inputUrl; QCoreApplication::exit(OVEN_STATUS_CODE_FAIL); return; } // invoke the bake method on the baker thread QMetaObject::invokeMethod(_baker.get(), "bake"); // make sure we hear about the results of this baker when it is done connect(_baker.get(), &Baker::finished, this, &BakerCLI::handleFinishedBaker); }
intptr_t CustomMemFree(void* allocator, void* pointer) { intptr_t retval = g_origMemFree(allocator, pointer); /*if (pointer != nullptr && *g_unsafePointerLoc) { size_t allocSize = 0; if (g_unsafeStack.size() == 0) { { std::unique_lock<std::mutex> lock(g_allocMutex); auto it = g_allocData.find(pointer); if (it != g_allocData.end()) { allocSize = it->second; g_allocData.erase(it); } } if (**(void***)g_unsafePointerLoc >= pointer && **(void***)g_unsafePointerLoc < ((char*)pointer + allocSize)) { std::vector<uintptr_t> stackList(96); uintptr_t* stack = (uintptr_t*)_AddressOfReturnAddress(); for (int i = 0; i < stackList.size(); i++) { stackList[i] = stack[i]; } g_unsafeStack = stackList; } } }*/ if (/*!g_didLevelFree && */pointer != nullptr) { //std::unique_lock<std::mutex> lock(g_allocMutex); EnterCriticalSection(&g_allocCS); uintptr_t ptr = (uintptr_t)pointer; auto it = g_allocData.find(ptr); if (it != g_allocData.end()) { size_t allocSize = it->second; g_allocStuff.erase({ ptr, allocSize }); if (allocSize >= 8) { if (*(uintptr_t*)ptr == 0x141826A10) { uintptr_t* stack = (uintptr_t*)_AddressOfReturnAddress(); stack += (32 / 8); std::array<uintptr_t, 16> stacky; memcpy(stacky.data(), stack, 16 * 8); { g_freeThings.insert({ ptr, { allocSize, stacky } }); } } } /*static char* location = hook::pattern("4C 8D 0D ? ? ? ? 48 89 01 4C 89 81 80 00 00").count(1).get(0).get<char>(3); static char** g_collectionRoot = (char**)(location + *(int32_t*)location + 4); for (int i = 0; i < 0x950; i++) { if (g_collectionRoot[i]) { void* baad = *(void**)(g_collectionRoot[i] + 32); if (baad >= pointer && baad < ((char*)pointer + allocSize)) { atArray<char>* array = (atArray<char>*)(g_collectionRoot[i] + 128); trace("freed collection %s (%p-%p)\n", &array->Get(0), pointer, allocSize + (char*)pointer); uintptr_t* stack = (uintptr_t*)_AddressOfReturnAddress(); stack += (32 / 8); for (int i = 0; i < 16; i++) { trace("stack: %p\n", stack[i]); } } } }*/ /*if (g_inLevelFree) { if (allocSize != -1) { int stackIdx = g_stackIdx++; std::vector<uintptr_t> stackList(96); uintptr_t* stack = (uintptr_t*)_AddressOfReturnAddress(); for (int i = 0; i < stackList.size(); i++) { stackList[i] = stack[i]; } g_stacks[stackIdx] = stackList; trace("level free: %p-%p - stack idx: %d\n", pointer, (char*)pointer + allocSize, stackIdx); } }*/ g_allocData.erase(it); } LeaveCriticalSection(&g_allocCS); } return retval; }
void UpdateAI(uint32 diff) override { //Check if we have a target if (!UpdateVictim()) { //No target so we'll use this section to do our random wispers instance wide //WisperTimer if (WisperTimer <= diff) { Map* map = me->GetMap(); if (!map->IsDungeon()) return; //Play random sound to the zone Map::PlayerList const &PlayerList = map->GetPlayers(); if (!PlayerList.isEmpty()) { for (Map::PlayerList::const_iterator itr = PlayerList.begin(); itr != PlayerList.end(); ++itr) { if (Player* pPlr = itr->GetSource()) pPlr->PlayDirectSound(RANDOM_SOUND_WHISPER, pPlr); } } //One random wisper every 90 - 300 seconds WisperTimer = urand(90000, 300000); } else WisperTimer -= diff; return; } me->SetTarget(ObjectGuid::Empty); uint32 currentPhase = instance->GetData(DATA_CTHUN_PHASE); if (currentPhase == PHASE_CTHUN_STOMACH || currentPhase == PHASE_CTHUN_WEAK) { // EyeTentacleTimer if (EyeTentacleTimer <= diff) { //Spawn the 8 Eye Tentacles in the corret spots SpawnEyeTentacle(0, 20); //south SpawnEyeTentacle(10, 10); //south west SpawnEyeTentacle(20, 0); //west SpawnEyeTentacle(10, -10); //north west SpawnEyeTentacle(0, -20); //north SpawnEyeTentacle(-10, -10); //north east SpawnEyeTentacle(-20, 0); // east SpawnEyeTentacle(-10, 10); // south east EyeTentacleTimer = 30000; // every 30sec in phase 2 } else EyeTentacleTimer -= diff; } switch (currentPhase) { //Transition phase case PHASE_CTHUN_TRANSITION: //PhaseTimer if (PhaseTimer <= diff) { //Switch instance->SetData(DATA_CTHUN_PHASE, PHASE_CTHUN_STOMACH); //Switch to c'thun model me->InterruptNonMeleeSpells(false); DoCast(me, SPELL_TRANSFORM, false); me->SetFullHealth(); me->SetVisible(true); me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_NON_ATTACKABLE); //Emerging phase //AttackStart(ObjectAccessor::GetUnit(*me, HoldpPlayer)); DoZoneInCombat(); //Place all units in threat list on outside of stomach Stomach_Map.clear(); for (std::list<HostileReference*>::const_iterator i = me->getThreatManager().getThreatList().begin(); i != me->getThreatManager().getThreatList().end(); ++i) Stomach_Map[(*i)->getUnitGuid()] = false; //Outside stomach //Spawn 2 flesh tentacles FleshTentaclesKilled = 0; //Spawn flesh tentacle for (uint8 i = 0; i < 2; i++) { Creature* spawned = me->SummonCreature(NPC_FLESH_TENTACLE, FleshTentaclePos[i], TEMPSUMMON_CORPSE_DESPAWN); if (!spawned) ++FleshTentaclesKilled; } PhaseTimer = 0; } else PhaseTimer -= diff; break; //Body Phase case PHASE_CTHUN_STOMACH: //Remove Target field me->SetTarget(ObjectGuid::Empty); //Weaken if (FleshTentaclesKilled > 1) { instance->SetData(DATA_CTHUN_PHASE, PHASE_CTHUN_WEAK); Talk(EMOTE_WEAKENED); PhaseTimer = 45000; DoCast(me, SPELL_PURPLE_COLORATION, true); std::unordered_map<ObjectGuid, bool>::iterator i = Stomach_Map.begin(); //Kick all players out of stomach while (i != Stomach_Map.end()) { //Check for valid player Unit* unit = ObjectAccessor::GetUnit(*me, i->first); //Only move units in stomach if (unit && i->second == true) { //Teleport each player out DoTeleportPlayer(unit, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ() + 10, float(rand32() % 6)); //Cast knockback on them DoCast(unit, SPELL_EXIT_STOMACH_KNOCKBACK, true); //Remove the acid debuff unit->RemoveAurasDueToSpell(SPELL_DIGESTIVE_ACID); i->second = false; } ++i; } return; } //Stomach acid if (StomachAcidTimer <= diff) { //Apply aura to all players in stomach std::unordered_map<ObjectGuid, bool>::iterator i = Stomach_Map.begin(); while (i != Stomach_Map.end()) { //Check for valid player Unit* unit = ObjectAccessor::GetUnit(*me, i->first); //Only apply to units in stomach if (unit && i->second == true) { //Cast digestive acid on them DoCast(unit, SPELL_DIGESTIVE_ACID, true); //Check if player should be kicked from stomach if (unit->IsWithinDist3d(&KickPos, 15.0f)) { //Teleport each player out DoTeleportPlayer(unit, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ() + 10, float(rand32() % 6)); //Cast knockback on them DoCast(unit, SPELL_EXIT_STOMACH_KNOCKBACK, true); //Remove the acid debuff unit->RemoveAurasDueToSpell(SPELL_DIGESTIVE_ACID); i->second = false; } } ++i; } StomachAcidTimer = 4000; } else StomachAcidTimer -= diff; //Stomach Enter Timer if (StomachEnterTimer <= diff) { if (Unit* target = SelectRandomNotStomach()) { //Set target in stomach Stomach_Map[target->GetGUID()] = true; target->InterruptNonMeleeSpells(false); target->CastSpell(target, SPELL_MOUTH_TENTACLE, true, NULL, NULL, me->GetGUID()); StomachEnterTarget = target->GetGUID(); StomachEnterVisTimer = 3800; } StomachEnterTimer = 13800; } else StomachEnterTimer -= diff; if (StomachEnterVisTimer && StomachEnterTarget) { if (StomachEnterVisTimer <= diff) { //Check for valid player Unit* unit = ObjectAccessor::GetUnit(*me, StomachEnterTarget); if (unit) { DoTeleportPlayer(unit, STOMACH_X, STOMACH_Y, STOMACH_Z, STOMACH_O); } StomachEnterTarget.Clear(); StomachEnterVisTimer = 0; } else StomachEnterVisTimer -= diff; } //GientClawTentacleTimer if (GiantClawTentacleTimer <= diff) { if (Unit* target = SelectRandomNotStomach()) { //Spawn claw tentacle on the random target if (Creature* spawned = me->SummonCreature(NPC_GIANT_CLAW_TENTACLE, *target, TEMPSUMMON_CORPSE_DESPAWN, 500)) if (spawned->AI()) spawned->AI()->AttackStart(target); } //One giant claw tentacle every minute GiantClawTentacleTimer = 60000; } else GiantClawTentacleTimer -= diff; //GiantEyeTentacleTimer if (GiantEyeTentacleTimer <= diff) { if (Unit* target = SelectRandomNotStomach()) { //Spawn claw tentacle on the random target if (Creature* spawned = me->SummonCreature(NPC_GIANT_EYE_TENTACLE, *target, TEMPSUMMON_CORPSE_DESPAWN, 500)) if (spawned->AI()) spawned->AI()->AttackStart(target); } //One giant eye tentacle every minute GiantEyeTentacleTimer = 60000; } else GiantEyeTentacleTimer -= diff; break; //Weakened state case PHASE_CTHUN_WEAK: //PhaseTimer if (PhaseTimer <= diff) { //Switch instance->SetData(DATA_CTHUN_PHASE, PHASE_CTHUN_STOMACH); //Remove purple coloration me->RemoveAurasDueToSpell(SPELL_PURPLE_COLORATION); //Spawn 2 flesh tentacles FleshTentaclesKilled = 0; //Spawn flesh tentacle for (uint8 i = 0; i < 2; i++) { Creature* spawned = me->SummonCreature(NPC_FLESH_TENTACLE, FleshTentaclePos[i], TEMPSUMMON_CORPSE_DESPAWN); if (!spawned) ++FleshTentaclesKilled; } PhaseTimer = 0; } else PhaseTimer -= diff; break; } }
std::string convert_talk_topic( talk_topic_enum const old_value ) { static const std::unordered_map<talk_topic_enum, std::string> talk_topic_enum_mapping = { { // This macro creates the appropriate new names (as string) for each enum value, so one does not // have to repeat so much (e.g. 'WRAP(TALK_ARSONIST)' instead of '{ TALK_ARSONIST, "TALK_ARSONIST" }') // It also ensures that each name is exactly as the name of the enum value. #define WRAP(value) { value, #value } WRAP(TALK_NONE), WRAP(TALK_DONE), WRAP(TALK_GUARD), WRAP(TALK_MISSION_LIST), WRAP(TALK_MISSION_LIST_ASSIGNED), WRAP(TALK_MISSION_DESCRIBE), WRAP(TALK_MISSION_OFFER), WRAP(TALK_MISSION_ACCEPTED), WRAP(TALK_MISSION_REJECTED), WRAP(TALK_MISSION_ADVICE), WRAP(TALK_MISSION_INQUIRE), WRAP(TALK_MISSION_SUCCESS), WRAP(TALK_MISSION_SUCCESS_LIE), WRAP(TALK_MISSION_FAILURE), WRAP(TALK_MISSION_REWARD), WRAP(TALK_EVAC_MERCHANT), WRAP(TALK_EVAC_MERCHANT_NEW), WRAP(TALK_EVAC_MERCHANT_PLANS), WRAP(TALK_EVAC_MERCHANT_PLANS2), WRAP(TALK_EVAC_MERCHANT_PLANS3), WRAP(TALK_EVAC_MERCHANT_WORLD), WRAP(TALK_EVAC_MERCHANT_HORDES), WRAP(TALK_EVAC_MERCHANT_PRIME_LOOT), WRAP(TALK_EVAC_MERCHANT_ASK_JOIN), WRAP(TALK_EVAC_MERCHANT_NO), WRAP(TALK_EVAC_MERCHANT_HELL_NO), WRAP(TALK_FREE_MERCHANT_STOCKS), WRAP(TALK_FREE_MERCHANT_STOCKS_NEW), WRAP(TALK_FREE_MERCHANT_STOCKS_WHY), WRAP(TALK_FREE_MERCHANT_STOCKS_ALL), WRAP(TALK_FREE_MERCHANT_STOCKS_JERKY), WRAP(TALK_FREE_MERCHANT_STOCKS_CORNMEAL), WRAP(TALK_FREE_MERCHANT_STOCKS_FLOUR), WRAP(TALK_FREE_MERCHANT_STOCKS_SUGAR), WRAP(TALK_FREE_MERCHANT_STOCKS_WINE), WRAP(TALK_FREE_MERCHANT_STOCKS_BEER), WRAP(TALK_FREE_MERCHANT_STOCKS_SMMEAT), WRAP(TALK_FREE_MERCHANT_STOCKS_SMFISH), WRAP(TALK_FREE_MERCHANT_STOCKS_OIL), WRAP(TALK_FREE_MERCHANT_STOCKS_DELIVERED), WRAP(TALK_EVAC_GUARD1), WRAP(TALK_EVAC_GUARD1_PLACE), WRAP(TALK_EVAC_GUARD1_GOVERNMENT), WRAP(TALK_EVAC_GUARD1_TRADE), WRAP(TALK_EVAC_GUARD1_JOIN), WRAP(TALK_EVAC_GUARD1_JOIN2), WRAP(TALK_EVAC_GUARD1_JOIN3), WRAP(TALK_EVAC_GUARD1_ATTITUDE), WRAP(TALK_EVAC_GUARD1_JOB), WRAP(TALK_EVAC_GUARD1_OLDGUARD), WRAP(TALK_EVAC_GUARD1_BYE), WRAP(TALK_EVAC_GUARD2), WRAP(TALK_EVAC_GUARD2_NEW), WRAP(TALK_EVAC_GUARD2_RULES), WRAP(TALK_EVAC_GUARD2_RULES_BASEMENT), WRAP(TALK_EVAC_GUARD2_WHO), WRAP(TALK_EVAC_GUARD2_TRADE), WRAP(TALK_EVAC_GUARD3), WRAP(TALK_EVAC_GUARD3_NEW), WRAP(TALK_EVAC_GUARD3_RULES), WRAP(TALK_EVAC_GUARD3_HIDE1), WRAP(TALK_EVAC_GUARD3_HIDE2), WRAP(TALK_EVAC_GUARD3_WASTE), WRAP(TALK_EVAC_GUARD3_DEAD), WRAP(TALK_EVAC_GUARD3_HOSTILE), WRAP(TALK_EVAC_GUARD3_INSULT), WRAP(TALK_EVAC_HUNTER), WRAP(TALK_EVAC_HUNTER_SMELL), WRAP(TALK_EVAC_HUNTER_DO), WRAP(TALK_EVAC_HUNTER_LIFE), WRAP(TALK_EVAC_HUNTER_HUNT), WRAP(TALK_EVAC_HUNTER_SALE), WRAP(TALK_EVAC_HUNTER_ADVICE), WRAP(TALK_EVAC_HUNTER_BYE), WRAP(TALK_OLD_GUARD_REP), WRAP(TALK_OLD_GUARD_REP_NEW), WRAP(TALK_OLD_GUARD_REP_NEW_DOING), WRAP(TALK_OLD_GUARD_REP_NEW_DOWNSIDE), WRAP(TALK_OLD_GUARD_REP_WORLD), WRAP(TALK_OLD_GUARD_REP_WORLD_2NDFLEET), WRAP(TALK_OLD_GUARD_REP_WORLD_FOOTHOLDS), WRAP(TALK_OLD_GUARD_REP_ASK_JOIN), WRAP(TALK_ARSONIST), WRAP(TALK_ARSONIST_NEW), WRAP(TALK_ARSONIST_DOING), WRAP(TALK_ARSONIST_DOING_REBAR), WRAP(TALK_ARSONIST_WORLD), WRAP(TALK_ARSONIST_WORLD_OPTIMISTIC), WRAP(TALK_ARSONIST_JOIN), WRAP(TALK_ARSONIST_MUTATION), WRAP(TALK_ARSONIST_MUTATION_INSULT), WRAP(TALK_SCAVENGER_MERC), WRAP(TALK_SCAVENGER_MERC_NEW), WRAP(TALK_SCAVENGER_MERC_TIPS), WRAP(TALK_SCAVENGER_MERC_HIRE), WRAP(TALK_SCAVENGER_MERC_HIRE_SUCCESS), WRAP(TALK_SHELTER), WRAP(TALK_SHELTER_PLANS), WRAP(TALK_SHARE_EQUIPMENT), WRAP(TALK_GIVE_EQUIPMENT), WRAP(TALK_DENY_EQUIPMENT), WRAP(TALK_TRAIN), WRAP(TALK_TRAIN_START), WRAP(TALK_TRAIN_FORCE), WRAP(TALK_SUGGEST_FOLLOW), WRAP(TALK_AGREE_FOLLOW), WRAP(TALK_DENY_FOLLOW), WRAP(TALK_SHOPKEEP), WRAP(TALK_LEADER), WRAP(TALK_LEAVE), WRAP(TALK_PLAYER_LEADS), WRAP(TALK_LEADER_STAYS), WRAP(TALK_HOW_MUCH_FURTHER), WRAP(TALK_FRIEND), WRAP(TALK_FRIEND_GUARD), WRAP(TALK_DENY_GUARD), WRAP(TALK_DENY_TRAIN), WRAP(TALK_DENY_PERSONAL), WRAP(TALK_FRIEND_UNCOMFORTABLE), WRAP(TALK_COMBAT_COMMANDS), WRAP(TALK_COMBAT_ENGAGEMENT), WRAP(TALK_STRANGER_NEUTRAL), WRAP(TALK_STRANGER_WARY), WRAP(TALK_STRANGER_SCARED), WRAP(TALK_STRANGER_FRIENDLY), WRAP(TALK_STRANGER_AGGRESSIVE), WRAP(TALK_MUG), WRAP(TALK_DESCRIBE_MISSION), WRAP(TALK_WEAPON_DROPPED), WRAP(TALK_DEMAND_LEAVE), WRAP(TALK_SIZE_UP), WRAP(TALK_LOOK_AT), WRAP(TALK_OPINION) } }; #undef WRAP auto const iter = talk_topic_enum_mapping.find( old_value ); if( iter == talk_topic_enum_mapping.end() ) { debugmsg( "could not convert %d to new talk topic string", static_cast<int>( old_value ) ); return "TALK_NONE"; } return iter->second; }
static void DeinitLevel() { static bool initedLateHook = false; if (!initedLateHook) { // late hook to prevent scenario manager from reinitializing on map load - it messes things up, a lot, and I doubt custom maps use scenarios anyway. :) hook::put<uint16_t>(hook::pattern("83 F9 04 0F 85 F9 00 00 00").count(1).get(0).get<void>(3), 0xE990); // shutdown hook::put<uint16_t>(hook::pattern("83 F9 02 0F 85 C6 01 00 00").count(1).get(0).get<void>(3), 0xE990); // init // don't load mounted ped (personality) metadata anymore (temp dbg-y?) hook::nop(hook::pattern("48 8B DA 83 E9 14 74 5B").count(1).get(0).get<void>(0x72 - 12), 5); // recreate interior proxy pool sanely //char* poolFn = hook::get_pattern<char>("41 0F B7 C6 4D 89 73 E8 41 8B F6 66 89 44 24 28", -0x23); //poolFn += 0xD4; //hook::nop(poolFn, 44); //hook::jump(poolFn, ClearInteriorProxyPool); initedLateHook = true; } // stuff g_inLevelFree = true; g_deinitLevel(); shutdownModelInfo(1); initModelInfo(1); initStreamingInterface(); //g_loadClipSets(); // extra content manager shutdown session removes these, and we want these before init session, so we scan them right here, right now. // TEMP REMOVE extraContentMgr__doScanInt(*g_extraContentMgr); extraContentMgr__doScanPost(*g_extraContentMgr, false, false); //shutdownPhysics(1); //initPhysics(1); // unknown value in the bounds streaming module, doesn't get cleared on 'after map loaded' shutdown int colCrashOffset = *hook::get_pattern<int>("0F B7 83 ? ? 00 00 BA FF 1F 00 00 66 33 C1 66", 3); int colCrashCountMax = (colCrashOffset - 464) / 4; *(uint32_t*)(g_boundsStreamingModule + colCrashOffset) = 0; // bounds streaming module, 'has preloading bounds completed' value *(uint8_t*)(g_boundsStreamingModule + 255) = 0; // clear the 'loaded cache hashes' list //*g_cacheArray = atArray<allocWrap<uint32_t>>(16); g_cacheArray->ClearCount(); // free one CScene list of all the bad influences from the last session ClearInteriorProxyList(g_sceneLinkedList); // also clear the interior proxy pool out, as it might contain garbage references to static bounds, still (*g_interiorProxyPool)->Clear(); // and some global vehicle audio entity also houses... interior proxies. *g_vehicleReflEntityArray = atArray<CInteriorProxy*>(); // clear interior proxies from render phases for (auto& pair : g_renderPhases) { CRenderPhaseScanned* renderPhase = pair.second; if (renderPhase->portalScanner) { trace("clearing %s interior proxy (was %p)\n", pair.first.c_str(), renderPhase->portalScanner->interiorProxy); renderPhase->portalScanner->interiorProxy = nullptr; } } g_inLevelFree = false; if (!g_didLevelFree) { for (auto& stack : g_stacks) { FILE* f = fopen(va("D:\\dev\\stacks\\%p.txt", ((stack.first / 256) * 256)), "a"); if (f) { fprintf(f, "--- %p ---\n", stack.first); for (auto& entry : stack.second) { fprintf(f, "%p\n", entry); } fprintf(f, "--- --- ---\n"); fclose(f); } } g_stackIdx = 0; g_stacks.clear(); g_didLevelFree = true; } }
std::unordered_set<TileID, TileID::Hash> AnnotationManager::addTileFeature(const uint32_t annotationID, const AnnotationSegments& segments, const std::vector<std::vector<vec2<double>>>& projectedFeature, const AnnotationType& type, const StyleProperties& styleProperties, const std::unordered_map<std::string, std::string>& featureProperties, const std::string layerId, const uint8_t maxZoom) { assert(type != AnnotationType::Any); // track the annotation global ID and its original geometry auto anno_it = annotations.emplace(annotationID, std::make_unique<Annotation>(type, layerId, segments, styleProperties)); std::unordered_set<TileID, TileID::Hash> affectedTiles; if (type == AnnotationType::Shape) { orderedShapeAnnotations.push_back(annotationID); using namespace mapbox::util::geojsonvt; const double z2 = 1 << maxZoom; const double baseTolerance = 3; const double extent = 4096; const double tolerance = baseTolerance / (z2 * extent); ProjectedGeometryContainer rings; std::vector<LonLat> points; for (size_t i = 0; i < segments[0].size(); ++i) { // first segment for now (no holes) const double constraintedLatitude = ::fmin(::fmax(segments[0][i].latitude, -util::LATITUDE_MAX), util::LATITUDE_MAX); points.push_back(LonLat(segments[0][i].longitude, constraintedLatitude)); } ProjectedFeatureType featureType; if (styleProperties.is<FillProperties>()) { featureType = ProjectedFeatureType::Polygon; if (points.front().lon != points.back().lon || points.front().lat != points.back().lat) { points.push_back(LonLat(points.front().lon, points.front().lat)); } } else { featureType = ProjectedFeatureType::LineString; } ProjectedGeometryContainer ring = Convert::project(points, tolerance); rings.members.push_back(ring); std::vector<ProjectedFeature> features; Tags tags; tags.insert(featureProperties.begin(), featureProperties.end()); features.push_back(Convert::create(tags, featureType, rings)); shapeTilers.emplace(annotationID, std::make_unique<GeoJSONVT>(features, maxZoom, 4, 100, 10)); } else { // side length of map at max zoom double z2 = 1 << maxZoom; const double extent = 4096; uint32_t x = 0; uint32_t y = 0; for (int8_t z = maxZoom; z >= 0; z--) { std::unordered_map<TileID, GeometryCollection, TileID::Hash> featureTiles; if (type == AnnotationType::Point) { auto& pp = projectedFeature[0][0]; x = pp.x * z2; y = pp.y * z2; const Coordinate coordinate(extent * (pp.x * z2 - x), extent * (pp.y * z2 - y)); GeometryCollection geometries = {{ {{ coordinate }} }}; featureTiles.emplace(TileID(z, x, y, z), geometries); } else { for (size_t l = 0; l < projectedFeature.size(); ++l) { for (size_t p = 0; p < projectedFeature[l].size(); ++p) { auto& pp = projectedFeature[l][p]; x = pp.x * z2; y = pp.y * z2; const Coordinate coordinate(extent * (pp.x * z2 - x), extent * (pp.y * z2 - y)); auto tile_it = featureTiles.find(TileID(z, x, y, z)); if (tile_it != featureTiles.end()) { GeometryCollection& geometries = featureTiles.find(TileID(z, x, y, z))->second; if (!geometries.empty()) { geometries.back().push_back(coordinate); } else { geometries.push_back({{ coordinate }}); } } else { GeometryCollection geometries = {{ {{ coordinate }} }}; featureTiles.emplace(TileID(z, x, y, z), geometries); } } } } for (auto& featureTile : featureTiles) { // determine feature type FeatureType featureType; if (type == AnnotationType::Point) { featureType = FeatureType::Point; } else if (styleProperties.is<LineProperties>()) { featureType = FeatureType::LineString; } else if (styleProperties.is<FillProperties>()) { featureType = FeatureType::Polygon; } else { throw std::runtime_error("Invalid feature type"); } // create tile feature auto feature = std::make_shared<const LiveTileFeature>( featureType, featureTile.second, featureProperties ); // check for tile & create if necessary auto tile_pos = tiles.emplace(featureTile.first, std::make_pair(std::unordered_set<uint32_t>({ annotationID }), std::make_unique<LiveTile>())); // check for annotation layer & create if necessary util::ptr<LiveTileLayer> layer; std::string layerID = ""; if (type == AnnotationType::Point) { layerID = PointLayerID; } else { layerID = ShapeLayerID + "." + util::toString(annotationID); } if (tile_pos.second || tile_pos.first->second.second->getMutableLayer(layerID) == nullptr) { layer = std::make_shared<LiveTileLayer>(); tile_pos.first->second.second->addLayer(layerID, layer); } else { layer = tile_pos.first->second.second->getMutableLayer(layerID); // associate annotation with tile tile_pos.first->second.first.insert(annotationID); } // add feature to layer layer->addFeature(feature); // Record annotation association with tile and tile feature. This is used to determine stale tiles, // as well as to remove the feature from the tile upon annotation deletion. anno_it.first->second->tilePointFeatures.emplace(featureTile.first, std::weak_ptr<const LiveTileFeature>(feature)); // track affected tile affectedTiles.insert(featureTile.first); } // get ready for the next-lower zoom number z2 /= 2; x /= 2; y /= 2; } } return affectedTiles; }
tweener_t get_tweener(std::wstring name) { std::transform(name.begin(), name.end(), name.begin(), std::tolower); if(name == L"linear") return [](double t, double b, double c, double d) { return ease_none(t, b, c, d, std::vector<double>()); }; std::vector<double> params; static const boost::wregex expr(L"(?<NAME>\\w*)(:(?<V0>\\d+\\.?\\d?))?(:(?<V1>\\d+\\.?\\d?))?"); // boost::regex has no repeated captures? boost::wsmatch what; if(boost::regex_match(name, what, expr)) { name = what["NAME"].str(); if(what["V0"].matched) params.push_back(boost::lexical_cast<double>(what["V0"].str())); if(what["V1"].matched) params.push_back(boost::lexical_cast<double>(what["V1"].str())); } typedef std::function<double(double, double, double, double, const std::vector<double>&)> tween_t; static const std::unordered_map<std::wstring, tween_t> tweens = boost::assign::map_list_of (L"", ease_none ) (L"linear", ease_none ) (L"easenone", ease_none ) (L"easeinquad", ease_in_quad ) (L"easeoutquad", ease_out_quad ) (L"easeinoutquad", ease_in_out_quad ) (L"easeoutinquad", ease_out_in_quad ) (L"easeincubic", ease_in_cubic ) (L"easeoutcubic", ease_out_cubic ) (L"easeinoutcubic", ease_in_out_cubic ) (L"easeoutincubic", ease_out_in_cubic ) (L"easeinquart", ease_in_quart ) (L"easeoutquart", ease_out_quart ) (L"easeinoutquart", ease_in_out_quart ) (L"easeoutinquart", ease_out_in_quart ) (L"easeinquint", ease_in_quint ) (L"easeoutquint", ease_out_quint ) (L"easeinoutquint", ease_in_out_quint ) (L"easeoutinquint", ease_out_in_quint ) (L"easeinsine", ease_in_sine ) (L"easeoutsine", ease_out_sine ) (L"easeinoutsine", ease_in_out_sine ) (L"easeoutinsine", ease_out_in_sine ) (L"easeinexpo", ease_in_expo ) (L"easeoutexpo", ease_out_expo ) (L"easeinoutexpo", ease_in_out_expo ) (L"easeoutinexpo", ease_out_in_expo ) (L"easeincirc", ease_in_circ ) (L"easeoutcirc", ease_out_circ ) (L"easeinoutcirc", ease_in_out_circ ) (L"easeoutincirc", ease_out_in_circ ) (L"easeinelastic", ease_in_elastic ) (L"easeoutelastic", ease_out_elastic ) (L"easeinoutelastic", ease_in_out_elastic) (L"easeoutinelastic", ease_out_in_elastic) (L"easeinback", ease_in_back ) (L"easeoutback", ease_out_back ) (L"easeinoutback", ease_in_out_back ) (L"easeoutintback", ease_out_int_back ) (L"easeoutbounce", ease_out_bounce ) (L"easeinbounce", ease_in_bounce ) (L"easeinoutbounce", ease_in_out_bounce ) (L"easeoutinbounce", ease_out_in_bounce ); auto it = tweens.find(name); if(it == tweens.end()) it = tweens.find(L"linear"); return [=](double t, double b, double c, double d) { return it->second(t, b, c, d, params); }; };
namespace VM { #define COLLISION_PADDING 0.1f std::vector<Script> scripts; std::unordered_map<std::string, scriptID> loadedScripts; ScriptStack::ScriptStack() : tail(0) { stack = new unsigned char[ptr_max]; clear(); } ScriptStack::~ScriptStack() { delete [] stack; } void ScriptStack::push(unsigned char* data, ptr size) { assert ( (tail+size) < ptr_max); memcpy(stack + tail, data, size); tail += size; } unsigned char* ScriptStack::get(ptr index) { assert( index < tail ); return &stack[index]; } void ScriptStack::clear() { tail = 0; memset(stack, 0xCD, ptr_max); } // FUNCTIONS //////////////////////////////////////////////////////////////////////// scriptID AddScript(const Script& script) { scriptID scriptid = scripts.size(); scripts.push_back(Script()); Script& newScript = scripts.back(); CopyScript(newScript, script); return scriptid; } //////////////////////////////////////////////////////////////////////////////////////// const Script& GetScript(scriptID id) { return scripts[id]; } //////////////////////////////////////////////////////////////////////////////////////// scriptID LoadCompiledScript(const std::string& scriptFile) { std::unordered_map<std::string, scriptID>::iterator scriptIter = loadedScripts.find(scriptFile); if (scriptIter != loadedScripts.end()) { return loadedScripts[scriptFile]; } std::fstream file; size_t dataSize; unsigned char code; unsigned char data[256]; file.open(scriptFile, std::ios::in | std::ios::binary); scriptID newscriptID = scripts.size(); scripts.push_back(Script()); Script& newScript = scripts.back(); size_t scriptSize; file.read((char*)&scriptSize, sizeof(size_t)); newScript.reserve(scriptSize); for(size_t i = 0; i < scriptSize; ++i) { file.read((char*) &dataSize, sizeof(size_t)); file.read((char*) &code, sizeof(unsigned char)); file.read((char*) data, sizeof(unsigned char) * dataSize); newScript.push_back( Instruction(code, &data[0], dataSize) ); } loadedScripts[scriptFile] = newscriptID; return newscriptID; } ///////////////////////////////////////////////////////////////////////////////////// void SaveCompiledScript(const std::string& scriptFile, scriptID id) { std::fstream file; file.open(scriptFile, std::ios::out | std::ios::binary); Script script = scripts[id]; Script::const_iterator it = script.begin(); Script::const_iterator end = script.end(); size_t scriptSize = script.size(); file.write((char*)&scriptSize, sizeof(size_t)); size_t dataSize; unsigned char code; const unsigned char* data; for(; it!= end; ++it) { dataSize = it->GetDataSize(); code = it->GetCode(); data = it->GetData(); file.write((char*)&dataSize, sizeof(size_t)); file.write((char*)&code, sizeof(unsigned char)); file.write((char*)data, sizeof(unsigned char) * dataSize); } file.close(); } ///////////////////////////////////////////////////////////////////////////////////// void CopyScript(Script& dst, const Script& source) { dst.resize(source.size()); for(size_t i = 0; i < source.size(); ++i) { dst[i] = source[i]; } } // EXECUTE ///////////////////////////////////////////////////////////////////////////// Actor* GetActor(unsigned char* data) { return (Actor*)*(unsigned int*)data; } const unsigned char* DataAtOffset(const unsigned char* data, ptr offset) { return data + offset * ptr_size; } void Execute(scriptID id) { ScriptStack scriptState; Execute(id, scriptState); } ///////////////////////////////////////////////////////////////////////////////////// void Execute(scriptID id, ScriptStack& scriptState) { Script script = scripts[id]; Script::const_iterator ins = script.begin(); Script::const_iterator end = script.end(); for (; ins != end; ++ins) { switch(ins->GetCode()) { ///////////////////////////////////////////////////////////////////////////// case op_noop: break; case op_push: { const unsigned char* data = ins->GetData(); ptr size = *(ptr*)data; // SIZE MISMATCH, fix it ppeas Phil unsigned char* value = (unsigned char*)DataAtOffset(data, 1); scriptState.push(value, size); } break; ///////////////////////////////////////////////////////////////////////////// case op_end: return; break; ///////////////////////////////////////////////////////////////////////////// case op_forceout: { // figure out our overlap and how much we have. const unsigned char* data = ins->GetData(); Actor* target = GetActor(scriptState.get(*data)); Actor* source = GetActor( scriptState.get(*DataAtOffset(data, 1)) ); const Box* sourceBox = source->GetCollision(); const Box* targetBox = target->GetCollision(); if ( !BoxesIntersect(sourceBox, targetBox) ) { return; } float x1, x2, x3, x4, y1, y2, y3, y4; x1 = sourceBox->GetUpperLeft().x; x2 = targetBox->GetUpperRight().x; x3 = sourceBox->GetUpperRight().x; x4 = targetBox->GetUpperLeft().x; y1 = sourceBox->GetLowerLeft().y; y2 = targetBox->GetUpperLeft().y; y3 = sourceBox->GetUpperLeft().y; y4 = targetBox->GetLowerLeft().y; float bottomOverlap = y1-y2+COLLISION_PADDING; float topOverlap = y3-y4-COLLISION_PADDING; float leftOverlap = x1-x2-COLLISION_PADDING; float rightOverlap = x3-x4+COLLISION_PADDING; float moveY = abs(topOverlap) > abs(bottomOverlap) ? bottomOverlap : topOverlap; float moveX = abs(leftOverlap) > abs(rightOverlap) ? rightOverlap : leftOverlap; Vector2 moveFirst, moveSecond; if (abs(moveX) < abs(moveY)) { moveFirst.x = moveX; moveSecond.y = moveY; } else { moveFirst.y = moveY; moveSecond.x = moveX; } target->Move(moveFirst); if ( BoxesIntersect(sourceBox, targetBox) ) { target->Move(moveSecond); } } break; ///////////////////////////////////////////////////////////////////////////// case op_playanim: { const unsigned char* data = ins->GetData(); Actor* target = GetActor(scriptState.get(*data)); unsigned char animName = (unsigned char)*( DataAtOffset(data, 1) ); target->GetAnimComponent()->PlayAnim((char*)scriptState.get(animName)); } break; ///////////////////////////////////////////////////////////////////////////// case op_kill: const unsigned char* data = ins->GetData(); Actor* target = (Actor*) scriptState.get(*(unsigned int*)data); target->MarkForCleanup(); break; } // end switch(instruction) } // end for } // end Execute } // end namespace
void OnlineFileRequestImpl::removeObserver(FileRequest* req) { observers.erase(req); }
EXPORT_CDECL(bool) RegisterDataProvider(LPCWSTR name, IDataProvider *provider) { sDataProviders.emplace(name, provider); return true; }
bool OnlineFileRequestImpl::hasObservers() const { return !observers.empty(); }
/// Check whether the given subsystem is running or not bool is_running(const std::string &sub) noexcept { return subsystems.count(sub) > 0; }
bool TestHelpers::check_empty_map(const std::unordered_map<std::string,int64_t> & m) { return m.empty(); }
namespace pyston { static uint64_t next_stack_addr = 0x4270000000L; static std::deque<uint64_t> available_addrs; // There should be a better way of getting this: #define PAGE_SIZE 4096 #define INITIAL_STACK_SIZE (8 * PAGE_SIZE) #define STACK_REDZONE_SIZE PAGE_SIZE #define MAX_STACK_SIZE (4 * 1024 * 1024) static std::unordered_map<void*, BoxedGenerator*> s_generator_map; static_assert(THREADING_USE_GIL, "have to make the generator map thread safe!"); class RegisterHelper { private: void* frame_addr; public: RegisterHelper(BoxedGenerator* generator, void* frame_addr) : frame_addr(frame_addr) { s_generator_map[frame_addr] = generator; } ~RegisterHelper() { assert(s_generator_map.count(frame_addr)); s_generator_map.erase(frame_addr); } }; static void freeGeneratorStack(BoxedGenerator* g) { if (g->stack_begin == NULL) return; available_addrs.push_back((uint64_t)g->stack_begin); // Limit the number of generator stacks we keep around: if (available_addrs.size() > 5) { uint64_t addr = available_addrs.front(); available_addrs.pop_front(); int r = munmap((void*)(addr - MAX_STACK_SIZE), MAX_STACK_SIZE); assert(r == 0); } g->stack_begin = NULL; } Context* getReturnContextForGeneratorFrame(void* frame_addr) { BoxedGenerator* generator = s_generator_map[frame_addr]; assert(generator); return generator->returnContext; } void generatorEntry(BoxedGenerator* g) { { assert(g->cls == generator_cls); assert(g->function->cls == function_cls); threading::pushGenerator(g, g->stack_begin, g->returnContext); try { RegisterHelper context_registerer(g, __builtin_frame_address(0)); // call body of the generator BoxedFunctionBase* func = g->function; Box** args = g->args ? &g->args->elts[0] : nullptr; callCLFunc(func->f, nullptr, func->f->numReceivedArgs(), func->closure, g, func->globals, g->arg1, g->arg2, g->arg3, args); } catch (ExcInfo e) { // unhandled exception: propagate the exception to the caller g->exception = e; } // we returned from the body of the generator. next/send/throw will notify the caller g->entryExited = true; threading::popGenerator(); } swapContext(&g->context, g->returnContext, 0); } Box* generatorIter(Box* s) { return s; } // called from both generatorHasNext and generatorSend/generatorNext (but only if generatorHasNext hasn't been called) static void generatorSendInternal(BoxedGenerator* self, Box* v) { STAT_TIMER(t0, "us_timer_generator_switching", 0); if (self->running) raiseExcHelper(ValueError, "generator already executing"); // check if the generator already exited if (self->entryExited) { freeGeneratorStack(self); raiseExcHelper(StopIteration, (const char*)nullptr); } self->returnValue = v; self->running = true; #if STAT_TIMERS if (!self->prev_stack) self->prev_stack = StatTimer::createStack(self->my_timer); else self->prev_stack = StatTimer::swapStack(self->prev_stack); #endif swapContext(&self->returnContext, self->context, (intptr_t)self); #if STAT_TIMERS self->prev_stack = StatTimer::swapStack(self->prev_stack); if (self->entryExited) { assert(self->prev_stack == &self->my_timer); assert(self->my_timer.isPaused()); } #endif self->running = false; // propagate exception to the caller if (self->exception.type) { assert(self->entryExited); freeGeneratorStack(self); // don't raise StopIteration exceptions because those are handled specially. if (!self->exception.matches(StopIteration)) throw self->exception; return; } if (self->entryExited) { freeGeneratorStack(self); // Reset the current exception. // We could directly create the StopIteration exception but we delay creating it because often the caller is not // interested in the exception (=generatorHasnext). If we really need it we will create it inside generatorSend. self->exception = ExcInfo(NULL, NULL, NULL); return; } } Box* generatorSend(Box* s, Box* v) { assert(s->cls == generator_cls); BoxedGenerator* self = static_cast<BoxedGenerator*>(s); if (self->iterated_from__hasnext__) Py_FatalError(".throw called on generator last advanced with __hasnext__"); generatorSendInternal(self, v); // throw StopIteration if the generator exited if (self->entryExited) { // But we can't just create a new exc because the generator may have exited because of an explicit // 'raise StopIterationSubClass, "test"' statement and we can't replace it with the generic StopIteration // exception. // That's why we set inside 'generatorSendInternal()' 'self->exception' to the raised StopIteration exception or // create a new one if the generator exited implicit. // CPython raises the custom exception just once, on the next generator 'next' it will we a normal StopIteration // exc. assert(self->exception.type == NULL || self->exception.matches(StopIteration)); ExcInfo old_exc = self->exception; // Clear the exception for GC purposes: self->exception = ExcInfo(nullptr, nullptr, nullptr); if (old_exc.type == NULL) raiseExcHelper(StopIteration, (const char*)nullptr); throw old_exc; } return self->returnValue; } Box* generatorThrow(Box* s, BoxedClass* exc_cls, Box* exc_val = nullptr, Box** args = nullptr) { assert(s->cls == generator_cls); BoxedGenerator* self = static_cast<BoxedGenerator*>(s); if (self->iterated_from__hasnext__) Py_FatalError(".throw called on generator last advanced with __hasnext__"); // don't overwrite self->exception if the generator already exited // because it will contain the StopIteration exception to throw. if (!self->entryExited) { Box* exc_tb = args ? nullptr : args[0]; if (!exc_val) exc_val = None; if (!exc_tb) exc_tb = None; self->exception = excInfoForRaise(exc_cls, exc_val, exc_tb); } return generatorSend(self, None); } Box* generatorClose(Box* s) { assert(s->cls == generator_cls); BoxedGenerator* self = static_cast<BoxedGenerator*>(s); // check if the generator already exited if (self->entryExited) return None; return generatorThrow(self, GeneratorExit, nullptr, nullptr); } Box* generatorNext(Box* s) { assert(s->cls == generator_cls); BoxedGenerator* self = static_cast<BoxedGenerator*>(s); if (self->iterated_from__hasnext__) { self->iterated_from__hasnext__ = false; return self->returnValue; } return generatorSend(s, None); } i1 generatorHasnextUnboxed(Box* s) { assert(s->cls == generator_cls); BoxedGenerator* self = static_cast<BoxedGenerator*>(s); if (!self->iterated_from__hasnext__) { generatorSendInternal(self, None); self->iterated_from__hasnext__ = true; } return !self->entryExited; } Box* generatorHasnext(Box* s) { return boxBool(generatorHasnextUnboxed(s)); } extern "C" Box* yield(BoxedGenerator* obj, Box* value) { STAT_TIMER(t0, "us_timer_generator_switching", 0); assert(obj->cls == generator_cls); BoxedGenerator* self = static_cast<BoxedGenerator*>(obj); self->returnValue = value; threading::popGenerator(); swapContext(&self->context, self->returnContext, 0); threading::pushGenerator(obj, obj->stack_begin, obj->returnContext); // if the generator receives a exception from the caller we have to throw it if (self->exception.type) { ExcInfo e = self->exception; self->exception = ExcInfo(NULL, NULL, NULL); throw e; } return self->returnValue; } extern "C" BoxedGenerator* createGenerator(BoxedFunctionBase* function, Box* arg1, Box* arg2, Box* arg3, Box** args) { assert(function); assert(function->cls == function_cls); return new BoxedGenerator(function, arg1, arg2, arg3, args); } #if STAT_TIMERS static uint64_t* generator_timer_counter = Stats::getStatCounter("us_timer_generator_toplevel"); #endif extern "C" BoxedGenerator::BoxedGenerator(BoxedFunctionBase* function, Box* arg1, Box* arg2, Box* arg3, Box** args) : function(function), arg1(arg1), arg2(arg2), arg3(arg3), args(nullptr), entryExited(false), running(false), returnValue(nullptr), exception(nullptr, nullptr, nullptr), context(nullptr), returnContext(nullptr) #if STAT_TIMERS , prev_stack(NULL), my_timer(generator_timer_counter, 0, true) #endif { int numArgs = function->f->numReceivedArgs(); if (numArgs > 3) { numArgs -= 3; this->args = new (numArgs) GCdArray(); memcpy(&this->args->elts[0], args, numArgs * sizeof(Box*)); } static StatCounter generator_stack_reused("generator_stack_reused"); static StatCounter generator_stack_created("generator_stack_created"); void* initial_stack_limit; if (available_addrs.size() == 0) { generator_stack_created.log(); uint64_t stack_low = next_stack_addr; uint64_t stack_high = stack_low + MAX_STACK_SIZE; next_stack_addr = stack_high; #if STACK_GROWS_DOWN this->stack_begin = (void*)stack_high; initial_stack_limit = (void*)(stack_high - INITIAL_STACK_SIZE); void* p = mmap(initial_stack_limit, INITIAL_STACK_SIZE, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_FIXED | MAP_ANONYMOUS | MAP_GROWSDOWN, -1, 0); ASSERT(p == initial_stack_limit, "%p %s", p, strerror(errno)); // Create an inaccessible redzone so that the generator stack won't grow indefinitely. // Looks like it throws a SIGBUS if we reach the redzone; it's unclear if that's better // or worse than being able to consume all available memory. void* p2 = mmap((void*)stack_low, STACK_REDZONE_SIZE, PROT_NONE, MAP_PRIVATE | MAP_FIXED | MAP_ANONYMOUS, -1, 0); assert(p2 == (void*)stack_low); // Interestingly, it seems like MAP_GROWSDOWN will leave a page-size gap between the redzone and the growable // region. if (VERBOSITY() >= 1) { printf("Created new generator stack, starts at %p, currently extends to %p\n", (void*)stack_high, initial_stack_limit); printf("Created a redzone from %p-%p\n", (void*)stack_low, (void*)(stack_low + STACK_REDZONE_SIZE)); } #else #error "implement me" #endif // we're registering memory that isn't in the gc heap here, // which may sound wrong. Generators, however, can represent // a larger tax on system resources than just their GC // allocation, so we try to encode that here as additional gc // heap pressure. gc::registerGCManagedBytes(INITIAL_STACK_SIZE); } else { generator_stack_reused.log(); #if STACK_GROWS_DOWN uint64_t stack_high = available_addrs.back(); this->stack_begin = (void*)stack_high; initial_stack_limit = (void*)(stack_high - INITIAL_STACK_SIZE); available_addrs.pop_back(); #else #error "implement me" #endif } assert(((intptr_t)stack_begin & (~(intptr_t)(0xF))) == (intptr_t)stack_begin && "stack must be aligned"); context = makeContext(stack_begin, (void (*)(intptr_t))generatorEntry); } extern "C" void generatorGCHandler(GCVisitor* v, Box* b) { boxGCHandler(v, b); BoxedGenerator* g = (BoxedGenerator*)b; v->visit(g->function); int num_args = g->function->f->numReceivedArgs(); if (num_args >= 1) v->visit(g->arg1); if (num_args >= 2) v->visit(g->arg2); if (num_args >= 3) v->visit(g->arg3); if (g->args) v->visit(g->args); if (num_args > 3) v->visitPotentialRange(reinterpret_cast<void* const*>(&g->args->elts[0]), reinterpret_cast<void* const*>(&g->args->elts[num_args - 3])); if (g->returnValue) v->visit(g->returnValue); if (g->exception.type) v->visit(g->exception.type); if (g->exception.value) v->visit(g->exception.value); if (g->exception.traceback) v->visit(g->exception.traceback); if (g->running) { v->visitPotentialRange((void**)&g->returnContext, ((void**)&g->returnContext) + sizeof(g->returnContext) / sizeof(void*)); } else { // g->context is always set for a running generator, but we can trigger a GC while constructing // a generator in which case we can see a NULL context if (g->context) { #if STACK_GROWS_DOWN v->visitPotentialRange((void**)g->context, (void**)g->stack_begin); #endif } } } Box* generatorName(Box* _self, void* context) { assert(isSubclass(_self->cls, generator_cls)); BoxedGenerator* self = static_cast<BoxedGenerator*>(_self); return boxString(self->function->f->source->getName()); } void generatorDestructor(Box* b) { assert(isSubclass(b->cls, generator_cls)); BoxedGenerator* self = static_cast<BoxedGenerator*>(b); freeGeneratorStack(self); } void setupGenerator() { generator_cls = BoxedHeapClass::create(type_cls, object_cls, &generatorGCHandler, 0, offsetof(BoxedGenerator, weakreflist), sizeof(BoxedGenerator), false, "generator"); generator_cls->simple_destructor = generatorDestructor; generator_cls->giveAttr("__iter__", new BoxedFunction(boxRTFunction((void*)generatorIter, typeFromClass(generator_cls), 1))); generator_cls->giveAttr("close", new BoxedFunction(boxRTFunction((void*)generatorClose, UNKNOWN, 1))); generator_cls->giveAttr("next", new BoxedFunction(boxRTFunction((void*)generatorNext, UNKNOWN, 1))); CLFunction* hasnext = boxRTFunction((void*)generatorHasnextUnboxed, BOOL, 1); addRTFunction(hasnext, (void*)generatorHasnext, BOXED_BOOL); generator_cls->giveAttr("__hasnext__", new BoxedFunction(hasnext)); generator_cls->giveAttr("send", new BoxedFunction(boxRTFunction((void*)generatorSend, UNKNOWN, 2))); auto gthrow = new BoxedFunction(boxRTFunction((void*)generatorThrow, UNKNOWN, 4, 2, false, false), { NULL, NULL }); generator_cls->giveAttr("throw", gthrow); generator_cls->giveAttr("__name__", new (pyston_getset_cls) BoxedGetsetDescriptor(generatorName, NULL, NULL)); generator_cls->freeze(); } }
inline const int index(const W& word) const { auto finder = word_idx.find(word); return (finder == word_idx.end()) ? 0 : finder->second; }
~RegisterHelper() { assert(s_generator_map.count(frame_addr)); s_generator_map.erase(frame_addr); }
void mission::clear_all() { world_missions.clear(); }
/// Close all open sockets static void CleanupSockets() { for (auto sock : open_sockets) closesocket(sock.second.socket_fd); open_sockets.clear(); }
Util::StringIdentifier getId(Obj * obj)const{ const auto it = map_objToId.find(obj); return it==map_objToId.end() ? Util::StringIdentifier() : it->second; }
void add(int number) { if(hashmap.find(number)==hashmap.end()) hashmap[number] = 0; hashmap[number] += 1; }
void remove(std::string name) { auto pos = stringTextureMap.find(name); stringTextureMap.remove(pos); }
void CarbonRouterInstanceBase::addStartupOpts( std::unordered_map<std::string, std::string> additionalOpts) { additionalStartupOpts_.insert(additionalOpts.begin(), additionalOpts.end()); }
namespace GameEngine{ //Initialise static attributes to null{0} btDynamicsWorld* PhysicsEngine::_world = 0; btDefaultCollisionConfiguration* PhysicsEngine::_config = 0; btCollisionDispatcher* PhysicsEngine::_dispatcher = 0; btBroadphaseInterface* PhysicsEngine::_broadphase = 0; btSequentialImpulseConstraintSolver* PhysicsEngine::_solver = 0; std::list<btRigidBody*> PhysicsEngine::_rigidBodies = std::list<btRigidBody*>(); std::unordered_map<Entity*, std::set<Entity*>> contacts; bool HandleContacts(btManifoldPoint& point, btCollisionObject* body0, btCollisionObject* body1){ //Get the 2 entities involved by accessing the user pointer of the bodies in contact Entity* entity0 = (Entity*)body0->getUserPointer(); Entity* entity1 = (Entity*)body1->getUserPointer(); // check if entity0 is already in map auto found = contacts.find(entity0); if(found != contacts.end()){ //Entity in map. Add entity2 to the set mapped to it //Sets don't allow duplicates, so value won't be added if it already exists found->second.insert(entity1); }else{ //entity1 not in map. Create new set and add entity1 std::set<Entity*> set; set.insert(entity1); //add entity0 mapped to the new set in the contacts map contacts[entity0] = set; } return true; } bool PhysicsEngine::initialise(){ _config = new btDefaultCollisionConfiguration(); _dispatcher = new btCollisionDispatcher(_config); _broadphase = new btAxisSweep3(btVector3(-1000, -1000, -1000), btVector3(1000, 1000, 1000)); _solver = new btSequentialImpulseConstraintSolver(); _world = new btDiscreteDynamicsWorld(_dispatcher, _broadphase, _solver, _config); //set the collision processed callback gContactProcessedCallback = (ContactProcessedCallback)HandleContacts; //could check everything's ok but just return true for now return true; } bool PhysicsEngine::update(float deltaTime){ _world->stepSimulation(deltaTime, 60); //iterate across the contacts map for(auto contactsIter = contacts.begin(); contactsIter!=contacts.end(); ++contactsIter){ //get the entity key from teh current entry in the map Entity* collider0 = contactsIter->first; //get the set of colliders from the current entry in the map std::set<Entity*>& set = contactsIter->second; //iterate thru all the entities in the set for(auto entityIter = set.begin(); entityIter!=set.end(); ++entityIter){ // get the other colider from the iterator Entity* collider1 = *entityIter; //create 2 messages - one for collider and one for the entity being hit Message msg1(collider0, "COLLISION", collider1); Message msg2(collider1, "COLLISION", collider0); //dispatch teh messages MessageHandler::sendMessage(msg1); MessageHandler::sendMessage(msg2); } } //empty the contacts map ready for next time contacts.clear(); //for now return true; } void PhysicsEngine::shutdown(){ //remove all rigid bodies for(auto iter = _rigidBodies.begin(); iter != _rigidBodies.end(); ++iter){ //remove from world simulation _world->removeRigidBody(*iter); //delete from memory delete *iter; //set pointer to null{0} *iter = 0; } //now empty the list _rigidBodies.clear(); //start deleting the physics components delete _world; _world = 0; delete _solver; _solver = 0; delete _dispatcher; _dispatcher = 0; delete _broadphase; _broadphase = 0; delete _config; _config = 0; //Physics now shutdown } //creates and registers a new square rigidbody - assumes position is set btRigidBody* PhysicsEngine::createBoxRigidBody(Entity* entity, const vector3df& scale, float mass){ //create rigidbody's transform using entity's position btTransform transform; transform.setIdentity(); vector3df pos = entity->getNode()->getPosition(); transform.setOrigin(btVector3(pos.X, pos.Y, pos.Z)); //create the motionState of the object btDefaultMotionState* motionState = new btDefaultMotionState(transform); //create the bounding volume btVector3 halfExtents(scale.X*0.5f, scale.Y*0.5f, scale.Z*0.5f); btCollisionShape* shape = new btBoxShape(halfExtents); //create intertia info for the shape btVector3 localinertia; shape->calculateLocalInertia(mass, localinertia); //now create the rigidBody btRigidBody* rigidBody = new btRigidBody(mass, motionState, shape, localinertia); //add a pointer to rigidBody pointing to associated Entity rigidBody->setUserPointer(entity); //add the rigidBody to the world _world->addRigidBody(rigidBody); //and add to the list of rigidBodies _rigidBodies.push_back(rigidBody); //finally return created body return rigidBody; } //creates and registers a new sphere - assumes position already set btRigidBody* PhysicsEngine::createSphereRigidBody(Entity* entity, float radius, float mass){ //create rigidbody's transform using entity's position btTransform transform; transform.setIdentity(); vector3df pos = entity->getNode()->getPosition(); transform.setOrigin(btVector3(pos.X, pos.Y, pos.Z)); //create the motionState of the object btDefaultMotionState* motionState = new btDefaultMotionState(transform); //create the bounding volume btCollisionShape* shape = new btSphereShape(radius); //create intertia info for the shape btVector3 localinertia; shape->calculateLocalInertia(mass, localinertia); //now create the rigidBody btRigidBody* rigidBody = new btRigidBody(mass, motionState, shape, localinertia); //add a pointer to rigidBody pointing to associated Entity rigidBody->setUserPointer(entity); //add the rigidBody to the world _world->addRigidBody(rigidBody); //and add to the list of rigidBodies _rigidBodies.push_back(rigidBody); //finally return created body return rigidBody; } bool PhysicsEngine::removeRigidBody(btRigidBody* body){ _rigidBodies.remove(body); _world->removeRigidBody(body); return true; } }
ICInfo* getICInfo(void* rtn_addr) { std::unordered_map<void*, ICInfo*>::iterator it = ics_by_return_addr.find(rtn_addr); if (it == ics_by_return_addr.end()) return NULL; return it->second; }