Initial commit
This commit is contained in:
commit
0e7bfc1fe2
2837 changed files with 897984 additions and 0 deletions
3
README.txt
Normal file
3
README.txt
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
Toontown Online is a MMORPG created by Disney Interactive, shut down in 2013.
|
||||||
|
|
||||||
|
This is a collection of various source code for the game.
|
5
otp/.cvsignore
Normal file
5
otp/.cvsignore
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
.cvsignore
|
||||||
|
__init__.py
|
||||||
|
Makefile
|
||||||
|
pp.dep
|
||||||
|
built
|
11
otp/.project
Normal file
11
otp/.project
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<projectDescription>
|
||||||
|
<name>otp</name>
|
||||||
|
<comment></comment>
|
||||||
|
<projects>
|
||||||
|
</projects>
|
||||||
|
<buildSpec>
|
||||||
|
</buildSpec>
|
||||||
|
<natures>
|
||||||
|
</natures>
|
||||||
|
</projectDescription>
|
63
otp/Package.pp
Normal file
63
otp/Package.pp
Normal file
|
@ -0,0 +1,63 @@
|
||||||
|
//
|
||||||
|
// Package.pp
|
||||||
|
//
|
||||||
|
// This file defines certain configuration variables that are to be
|
||||||
|
// written into the various make scripts. It is processed by ppremake
|
||||||
|
// (along with the Sources.pp files in each of the various
|
||||||
|
// directories) to generate build scripts appropriate to each
|
||||||
|
// environment.
|
||||||
|
//
|
||||||
|
// This is the package-specific file, which should be at the top of
|
||||||
|
// every source hierarchy. It generally gets the ball rolling, and is
|
||||||
|
// responsible for explicitly including all of the relevent Config.pp
|
||||||
|
// files.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// What is the name and version of this source tree?
|
||||||
|
#if $[eq $[PACKAGE],]
|
||||||
|
#define PACKAGE otp
|
||||||
|
#define VERSION 0.80
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
// Where should we find the DIRECT source directory?
|
||||||
|
#if $[DIRECT_SOURCE]
|
||||||
|
#define DIRECT_SOURCE $[unixfilename $[DIRECT_SOURCE]]
|
||||||
|
#elif $[or $[CTPROJS],$[DIRECT]]
|
||||||
|
// If we are presently attached, use the environment variable.
|
||||||
|
#define DIRECT_SOURCE $[unixfilename $[DIRECT]]
|
||||||
|
#if $[eq $[DIRECT],]
|
||||||
|
#error You seem to be attached to some trees, but not DIRECT!
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
// Otherwise, if we are not attached, we guess that the source is a
|
||||||
|
// sibling directory to this source root.
|
||||||
|
#define DIRECT_SOURCE $[standardize $[TOPDIR]/../direct]
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Where should we install OTP?
|
||||||
|
#if $[OTP_INSTALL]
|
||||||
|
#define OTP_INSTALL $[unixfilename $[OTP_INSTALL]]
|
||||||
|
#elif $[CTPROJS]
|
||||||
|
#set OTP $[unixfilename $[OTP]]
|
||||||
|
#define OTP_INSTALL $[OTP]/built
|
||||||
|
#if $[eq $[OTP],]
|
||||||
|
#error You seem to be attached to some trees, but not OTP!
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
#defer OTP_INSTALL $[unixfilename $[INSTALL_DIR]]
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
// Also get the DIRECT Package file and everything that includes.
|
||||||
|
#if $[not $[isfile $[DIRECT_SOURCE]/Package.pp]]
|
||||||
|
#printvar DIRECT_SOURCE
|
||||||
|
#error DIRECT source directory not found from otp! Are you attached properly?
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include $[DIRECT_SOURCE]/Package.pp
|
||||||
|
|
||||||
|
// Define the inter-tree dependencies.
|
||||||
|
#define NEEDS_TREES direct $[NEEDS_TREES]
|
||||||
|
#define DEPENDABLE_HEADER_DIRS $[DEPENDABLE_HEADER_DIRS] $[DIRECT_INSTALL]/include
|
10
otp/Sources.pp
Normal file
10
otp/Sources.pp
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
// This is the toplevel directory for a package.
|
||||||
|
|
||||||
|
#define DIR_TYPE toplevel
|
||||||
|
|
||||||
|
#define REQUIRED_TREES dtool panda direct
|
||||||
|
|
||||||
|
#define EXTRA_DIST \
|
||||||
|
Sources.pp Config.pp Package.pp
|
||||||
|
|
||||||
|
#define PYTHON_PACKAGE 1
|
7
otp/metalibs/Sources.pp
Normal file
7
otp/metalibs/Sources.pp
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
// This is a group directory: a directory level above a number of
|
||||||
|
// source subdirectories.
|
||||||
|
|
||||||
|
#define DIR_TYPE group
|
||||||
|
|
||||||
|
// The metalibs directory always depends on the src directory.
|
||||||
|
#define DEPENDS src
|
2
otp/metalibs/otp/.cvsignore
Normal file
2
otp/metalibs/otp/.cvsignore
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
.cvsignore
|
||||||
|
Makefile
|
33
otp/metalibs/otp/Sources.pp
Normal file
33
otp/metalibs/otp/Sources.pp
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
// DIR_TYPE "metalib" indicates we are building a shared library that
|
||||||
|
// consists mostly of references to other shared libraries. Under
|
||||||
|
// Windows, this directly produces a DLL (as opposed to the regular
|
||||||
|
// src libraries, which don't produce anything but a pile of OBJ files
|
||||||
|
// under Windows).
|
||||||
|
|
||||||
|
#define DIR_TYPE metalib
|
||||||
|
#define BUILDING_DLL BUILDING_OTP
|
||||||
|
|
||||||
|
#define COMPONENT_LIBS \
|
||||||
|
otpbase settings nametag movement secure navigation
|
||||||
|
|
||||||
|
#define OTHER_LIBS direct panda pandaexpress dtoolconfig dtool \
|
||||||
|
express:c prc:c event:c pgraph:c pgraphnodes:c linmath:c gobj:c lerp:c \
|
||||||
|
char:c putil:c mathutil:c downloader:c mathutil:c chan:c \
|
||||||
|
pandabase:c recorder:c grutil:c chan:c collide:c device:c \
|
||||||
|
dgraph:c display:c gsgbase:c parametrics:c text:c pnmimage:c \
|
||||||
|
dtoolutil:c interrogatedb:c interval:c dtoolbase:c \
|
||||||
|
dconfig:c pipeline:c pstatclient:c cull:c pnmimagetypes:c \
|
||||||
|
tform:c audio:c pgui:c directbase:c dcparser:c showbase:c \
|
||||||
|
deadrec:c distributed:c motiontrail:c movies:c \
|
||||||
|
$[if $[HAVE_NET],net:c] $[if $[WANT_NATIVE_NET],nativenet:c]
|
||||||
|
|
||||||
|
#if $[HAVE_FREETYPE]
|
||||||
|
#define OTHER_LIBS $[OTHER_LIBS] pnmtext:c
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#begin metalib_target
|
||||||
|
#define TARGET otp
|
||||||
|
|
||||||
|
#define SOURCES otp.cxx
|
||||||
|
#end metalib_target
|
||||||
|
|
9
otp/metalibs/otp/otp.cxx
Normal file
9
otp/metalibs/otp/otp.cxx
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
// Filename: otp.cxx
|
||||||
|
// Created by: drose (18May00)
|
||||||
|
//
|
||||||
|
|
||||||
|
|
||||||
|
// This is a dummy file whose sole purpose is to give the compiler
|
||||||
|
// something to compile when making libtoontown.so in NO_DEFER mode,
|
||||||
|
// which generates an empty library that itself links with all the
|
||||||
|
// other shared libraries that make up libtoontown.
|
2
otp/src/.cvsignore
Normal file
2
otp/src/.cvsignore
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
.cvsignore
|
||||||
|
Makefile
|
4
otp/src/Sources.pp
Normal file
4
otp/src/Sources.pp
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
// This is a group directory: a directory level above a number of
|
||||||
|
// source subdirectories.
|
||||||
|
|
||||||
|
#define DIR_TYPE group
|
|
@ -0,0 +1,12 @@
|
||||||
|
[Add.Code]
|
||||||
|
DisneyOnlineGames.ocx=DisneyOnlineGames.ocx
|
||||||
|
DisneyOnlineGames.inf=DisneyOnlineGames.inf
|
||||||
|
|
||||||
|
[DisneyOnlineGames.ocx]
|
||||||
|
file=thiscab
|
||||||
|
clsid={3DCEC959-378A-4922-AD7E-FD5C925D927F}
|
||||||
|
RegisterServer=yes
|
||||||
|
FileVersion=7,6,6,1549
|
||||||
|
|
||||||
|
[DisneyOnlineGames.inf]
|
||||||
|
file=thiscab
|
BIN
otp/src/activex/DisneyOnlineGames/built/DisneyOnlineGames.ocx
Normal file
BIN
otp/src/activex/DisneyOnlineGames/built/DisneyOnlineGames.ocx
Normal file
Binary file not shown.
3
otp/src/activex/DisneyOnlineGames/built/buildCAB.cmd
Normal file
3
otp/src/activex/DisneyOnlineGames/built/buildCAB.cmd
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
signcode -spc \\sesrccdfile01\Verisign_Credentials\WaltDisneyCompany\mycredentials.spc -v \\sesrccdfile01\Verisign_Credentials\WaltDisneyCompany\myprivatekey.pvk -n "Disney Online Games ActiveX Control" -t http://timestamp.verisign.com/scripts/timstamp.dll DisneyOnlineGames.ocx
|
||||||
|
cabarc -s 6144 n DisneyOnlineGames.cab DisneyOnlineGames.ocx DisneyOnlineGames.inf
|
||||||
|
signcode -spc \\sesrccdfile01\Verisign_Credentials\WaltDisneyCompany\mycredentials.spc -v \\sesrccdfile01\Verisign_Credentials\WaltDisneyCompany\myprivatekey.pvk -n "Disney Online Games ActiveX Control" -t http://timestamp.verisign.com/scripts/timstamp.dll DisneyOnlineGames.cab
|
Binary file not shown.
BIN
otp/src/activex/DisneyOnlineGames/doc/Build-Instructions.doc
Normal file
BIN
otp/src/activex/DisneyOnlineGames/doc/Build-Instructions.doc
Normal file
Binary file not shown.
Binary file not shown.
BIN
otp/src/activex/DisneyOnlineGames/doc/FlowDiagram.vsd
Normal file
BIN
otp/src/activex/DisneyOnlineGames/doc/FlowDiagram.vsd
Normal file
Binary file not shown.
|
@ -0,0 +1,21 @@
|
||||||
|
Microsoft Visual Studio Solution File, Format Version 8.00
|
||||||
|
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DisneyOnlineGames", "DisneyOnlineGames.Visual Studio 2003.vcproj", "{230D7CA9-17C1-4FF6-92E0-E620C7314D77}"
|
||||||
|
ProjectSection(ProjectDependencies) = postProject
|
||||||
|
EndProjectSection
|
||||||
|
EndProject
|
||||||
|
Global
|
||||||
|
GlobalSection(SolutionConfiguration) = preSolution
|
||||||
|
Debug = Debug
|
||||||
|
Release = Release
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ProjectConfiguration) = postSolution
|
||||||
|
{230D7CA9-17C1-4FF6-92E0-E620C7314D77}.Debug.ActiveCfg = Debug|Win32
|
||||||
|
{230D7CA9-17C1-4FF6-92E0-E620C7314D77}.Debug.Build.0 = Debug|Win32
|
||||||
|
{230D7CA9-17C1-4FF6-92E0-E620C7314D77}.Release.ActiveCfg = Release|Win32
|
||||||
|
{230D7CA9-17C1-4FF6-92E0-E620C7314D77}.Release.Build.0 = Release|Win32
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ExtensibilityAddIns) = postSolution
|
||||||
|
EndGlobalSection
|
||||||
|
EndGlobal
|
|
@ -0,0 +1,235 @@
|
||||||
|
<?xml version="1.0" encoding="Windows-1252"?>
|
||||||
|
<VisualStudioProject
|
||||||
|
ProjectType="Visual C++"
|
||||||
|
Version="7.10"
|
||||||
|
Name="DisneyOnlineGames"
|
||||||
|
ProjectGUID="{230D7CA9-17C1-4FF6-92E0-E620C7314D77}"
|
||||||
|
Keyword="MFCActiveXProj">
|
||||||
|
<Platforms>
|
||||||
|
<Platform
|
||||||
|
Name="Win32"/>
|
||||||
|
</Platforms>
|
||||||
|
<Configurations>
|
||||||
|
<Configuration
|
||||||
|
Name="Debug|Win32"
|
||||||
|
OutputDirectory="Debug"
|
||||||
|
IntermediateDirectory="Debug"
|
||||||
|
ConfigurationType="2"
|
||||||
|
UseOfMFC="1"
|
||||||
|
CharacterSet="2">
|
||||||
|
<Tool
|
||||||
|
Name="VCCLCompilerTool"
|
||||||
|
Optimization="0"
|
||||||
|
PreprocessorDefinitions="WIN32;_WINDOWS;_DEBUG;_USRDLL"
|
||||||
|
MinimalRebuild="TRUE"
|
||||||
|
BasicRuntimeChecks="3"
|
||||||
|
RuntimeLibrary="1"
|
||||||
|
TreatWChar_tAsBuiltInType="TRUE"
|
||||||
|
UsePrecompiledHeader="3"
|
||||||
|
WarningLevel="3"
|
||||||
|
Detect64BitPortabilityProblems="TRUE"
|
||||||
|
DebugInformationFormat="4"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCCustomBuildTool"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCLinkerTool"
|
||||||
|
OutputFile="$(OutDir)/DisneyOnlineGames.ocx"
|
||||||
|
LinkIncremental="1"
|
||||||
|
ModuleDefinitionFile=".\DisneyOnlineGames.def"
|
||||||
|
GenerateDebugInformation="TRUE"
|
||||||
|
AssemblyDebug="1"
|
||||||
|
SubSystem="2"
|
||||||
|
ImportLibrary="$(OutDir)/DisneyOnlineGames.lib"
|
||||||
|
TargetMachine="1"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCMIDLTool"
|
||||||
|
PreprocessorDefinitions="_DEBUG"
|
||||||
|
MkTypLibCompatible="FALSE"
|
||||||
|
TypeLibraryName="$(IntDir)/$(ProjectName).tlb"
|
||||||
|
HeaderFileName="$(ProjectName)idl.h"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCPostBuildEventTool"
|
||||||
|
Description="Performing registration"
|
||||||
|
CommandLine="regsvr32 /s /c "$(TargetPath)""
|
||||||
|
ExcludedFromBuild="TRUE"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCPreBuildEventTool"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCPreLinkEventTool"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCResourceCompilerTool"
|
||||||
|
PreprocessorDefinitions="_DEBUG"
|
||||||
|
Culture="1033"
|
||||||
|
AdditionalIncludeDirectories="$(IntDir)"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCWebServiceProxyGeneratorTool"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCXMLDataGeneratorTool"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCWebDeploymentTool"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCManagedWrapperGeneratorTool"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
|
||||||
|
</Configuration>
|
||||||
|
<Configuration
|
||||||
|
Name="Release|Win32"
|
||||||
|
OutputDirectory="..\_copy-OCX_to---built---when_ready_to_have_signed"
|
||||||
|
IntermediateDirectory="Release"
|
||||||
|
ConfigurationType="2"
|
||||||
|
UseOfMFC="1"
|
||||||
|
CharacterSet="2"
|
||||||
|
WholeProgramOptimization="TRUE">
|
||||||
|
<Tool
|
||||||
|
Name="VCCLCompilerTool"
|
||||||
|
GlobalOptimizations="TRUE"
|
||||||
|
OptimizeForWindowsApplication="TRUE"
|
||||||
|
PreprocessorDefinitions="WIN32;_WINDOWS;NDEBUG;_USRDLL"
|
||||||
|
StringPooling="TRUE"
|
||||||
|
RuntimeLibrary="0"
|
||||||
|
EnableFunctionLevelLinking="TRUE"
|
||||||
|
TreatWChar_tAsBuiltInType="TRUE"
|
||||||
|
UsePrecompiledHeader="3"
|
||||||
|
WarningLevel="3"
|
||||||
|
Detect64BitPortabilityProblems="TRUE"
|
||||||
|
DebugInformationFormat="3"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCCustomBuildTool"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCLinkerTool"
|
||||||
|
OutputFile="$(OutDir)/DisneyOnlineGames.ocx"
|
||||||
|
LinkIncremental="1"
|
||||||
|
ModuleDefinitionFile=".\DisneyOnlineGames.def"
|
||||||
|
GenerateDebugInformation="FALSE"
|
||||||
|
SubSystem="2"
|
||||||
|
OptimizeReferences="2"
|
||||||
|
EnableCOMDATFolding="2"
|
||||||
|
OptimizeForWindows98="1"
|
||||||
|
ImportLibrary="$(IntDir)/DisneyOnlineGames.lib"
|
||||||
|
TargetMachine="1"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCMIDLTool"
|
||||||
|
PreprocessorDefinitions="NDEBUG"
|
||||||
|
MkTypLibCompatible="FALSE"
|
||||||
|
TypeLibraryName="$(IntDir)/$(ProjectName).tlb"
|
||||||
|
HeaderFileName="$(ProjectName)idl.h"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCPostBuildEventTool"
|
||||||
|
Description="Performing registration"
|
||||||
|
CommandLine="regsvr32 /s /c "$(TargetPath)""
|
||||||
|
ExcludedFromBuild="TRUE"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCPreBuildEventTool"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCPreLinkEventTool"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCResourceCompilerTool"
|
||||||
|
PreprocessorDefinitions="NDEBUG"
|
||||||
|
Culture="1033"
|
||||||
|
AdditionalIncludeDirectories="$(IntDir)"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCWebServiceProxyGeneratorTool"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCXMLDataGeneratorTool"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCWebDeploymentTool"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCManagedWrapperGeneratorTool"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
|
||||||
|
</Configuration>
|
||||||
|
</Configurations>
|
||||||
|
<References>
|
||||||
|
</References>
|
||||||
|
<Files>
|
||||||
|
<Filter
|
||||||
|
Name="Source Files"
|
||||||
|
Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"
|
||||||
|
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}">
|
||||||
|
<File
|
||||||
|
RelativePath=".\DisneyOnlineGames.cpp">
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\DisneyOnlineGames.def">
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\DisneyOnlineGames.idl">
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\DisneyOnlineGamesCtrl.cpp">
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\DisneyOnlineGamesPropPage.cpp">
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\EnvBlock.cpp">
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\RunPiratesOnline.cpp">
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\stdafx.cpp">
|
||||||
|
<FileConfiguration
|
||||||
|
Name="Debug|Win32">
|
||||||
|
<Tool
|
||||||
|
Name="VCCLCompilerTool"
|
||||||
|
UsePrecompiledHeader="1"/>
|
||||||
|
</FileConfiguration>
|
||||||
|
<FileConfiguration
|
||||||
|
Name="Release|Win32">
|
||||||
|
<Tool
|
||||||
|
Name="VCCLCompilerTool"
|
||||||
|
UsePrecompiledHeader="1"/>
|
||||||
|
</FileConfiguration>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\TopLevelWindowIterator.cpp">
|
||||||
|
</File>
|
||||||
|
</Filter>
|
||||||
|
<Filter
|
||||||
|
Name="Header Files"
|
||||||
|
Filter="h;hpp;hxx;hm;inl;inc;xsd"
|
||||||
|
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}">
|
||||||
|
<File
|
||||||
|
RelativePath=".\DisneyOnlineGames.h">
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\DisneyOnlineGamesCtrl.h">
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\DisneyOnlineGamesPropPage.h">
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\EnvBlock.h">
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\Resource.h">
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\RunPiratesOnline.h">
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\stdafx.h">
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\TopLevelWindowIterator.h">
|
||||||
|
</File>
|
||||||
|
</Filter>
|
||||||
|
<Filter
|
||||||
|
Name="Resource Files"
|
||||||
|
Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx"
|
||||||
|
UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}">
|
||||||
|
<File
|
||||||
|
RelativePath=".\DisneyOnlineGames.rc">
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\DisneyOnlineGamesCtrl.bmp">
|
||||||
|
</File>
|
||||||
|
</Filter>
|
||||||
|
</Files>
|
||||||
|
<Globals>
|
||||||
|
<Global
|
||||||
|
Name="RESOURCE_FILE"
|
||||||
|
Value="DisneyOnlineGames.rc"/>
|
||||||
|
</Globals>
|
||||||
|
</VisualStudioProject>
|
|
@ -0,0 +1,20 @@
|
||||||
|
|
||||||
|
Microsoft Visual Studio Solution File, Format Version 9.00
|
||||||
|
# Visual Studio 2005
|
||||||
|
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DisneyOnlineGames", "DisneyOnlineGames.Visual Studio 2005.vcproj", "{230D7CA9-17C1-4FF6-92E0-E620C7314D77}"
|
||||||
|
EndProject
|
||||||
|
Global
|
||||||
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
|
Debug|Win32 = Debug|Win32
|
||||||
|
Release|Win32 = Release|Win32
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||||
|
{230D7CA9-17C1-4FF6-92E0-E620C7314D77}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||||
|
{230D7CA9-17C1-4FF6-92E0-E620C7314D77}.Debug|Win32.Build.0 = Debug|Win32
|
||||||
|
{230D7CA9-17C1-4FF6-92E0-E620C7314D77}.Release|Win32.ActiveCfg = Release|Win32
|
||||||
|
{230D7CA9-17C1-4FF6-92E0-E620C7314D77}.Release|Win32.Build.0 = Release|Win32
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
|
HideSolutionNode = FALSE
|
||||||
|
EndGlobalSection
|
||||||
|
EndGlobal
|
|
@ -0,0 +1,327 @@
|
||||||
|
<?xml version="1.0" encoding="Windows-1252"?>
|
||||||
|
<VisualStudioProject
|
||||||
|
ProjectType="Visual C++"
|
||||||
|
Version="8.00"
|
||||||
|
Name="DisneyOnlineGames"
|
||||||
|
ProjectGUID="{230D7CA9-17C1-4FF6-92E0-E620C7314D77}"
|
||||||
|
RootNamespace="DisneyOnlineGames"
|
||||||
|
Keyword="MFCActiveXProj"
|
||||||
|
>
|
||||||
|
<Platforms>
|
||||||
|
<Platform
|
||||||
|
Name="Win32"
|
||||||
|
/>
|
||||||
|
</Platforms>
|
||||||
|
<ToolFiles>
|
||||||
|
</ToolFiles>
|
||||||
|
<Configurations>
|
||||||
|
<Configuration
|
||||||
|
Name="Debug|Win32"
|
||||||
|
OutputDirectory="Debug"
|
||||||
|
IntermediateDirectory="Debug"
|
||||||
|
ConfigurationType="2"
|
||||||
|
InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
|
||||||
|
UseOfMFC="1"
|
||||||
|
CharacterSet="2"
|
||||||
|
>
|
||||||
|
<Tool
|
||||||
|
Name="VCPreBuildEventTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCCustomBuildTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCXMLDataGeneratorTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCWebServiceProxyGeneratorTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCMIDLTool"
|
||||||
|
PreprocessorDefinitions="_DEBUG"
|
||||||
|
MkTypLibCompatible="false"
|
||||||
|
TypeLibraryName="$(IntDir)/$(ProjectName).tlb"
|
||||||
|
HeaderFileName="$(ProjectName)idl.h"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCCLCompilerTool"
|
||||||
|
Optimization="0"
|
||||||
|
PreprocessorDefinitions="WIN32;_WINDOWS;_DEBUG;_USRDLL"
|
||||||
|
MinimalRebuild="true"
|
||||||
|
BasicRuntimeChecks="3"
|
||||||
|
RuntimeLibrary="1"
|
||||||
|
TreatWChar_tAsBuiltInType="true"
|
||||||
|
UsePrecompiledHeader="2"
|
||||||
|
WarningLevel="3"
|
||||||
|
Detect64BitPortabilityProblems="true"
|
||||||
|
DebugInformationFormat="4"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCManagedResourceCompilerTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCResourceCompilerTool"
|
||||||
|
PreprocessorDefinitions="_DEBUG"
|
||||||
|
Culture="1033"
|
||||||
|
AdditionalIncludeDirectories="$(IntDir)"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCPreLinkEventTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCLinkerTool"
|
||||||
|
AdditionalDependencies="wininet.lib"
|
||||||
|
OutputFile="$(OutDir)/DisneyOnlineGames.ocx"
|
||||||
|
LinkIncremental="1"
|
||||||
|
ModuleDefinitionFile=".\DisneyOnlineGames.def"
|
||||||
|
GenerateDebugInformation="true"
|
||||||
|
AssemblyDebug="1"
|
||||||
|
SubSystem="2"
|
||||||
|
ImportLibrary="$(OutDir)/DisneyOnlineGames.lib"
|
||||||
|
TargetMachine="1"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCALinkTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCManifestTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCXDCMakeTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCBscMakeTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCFxCopTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCAppVerifierTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCWebDeploymentTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCPostBuildEventTool"
|
||||||
|
Description="Performing registration"
|
||||||
|
CommandLine="regsvr32 /s /c "$(TargetPath)""
|
||||||
|
ExcludedFromBuild="true"
|
||||||
|
/>
|
||||||
|
</Configuration>
|
||||||
|
<Configuration
|
||||||
|
Name="Release|Win32"
|
||||||
|
OutputDirectory="..\_copy-OCX_to---built---when_ready_to_have_signed"
|
||||||
|
IntermediateDirectory="Release"
|
||||||
|
ConfigurationType="2"
|
||||||
|
InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
|
||||||
|
UseOfMFC="1"
|
||||||
|
CharacterSet="2"
|
||||||
|
WholeProgramOptimization="1"
|
||||||
|
>
|
||||||
|
<Tool
|
||||||
|
Name="VCPreBuildEventTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCCustomBuildTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCXMLDataGeneratorTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCWebServiceProxyGeneratorTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCMIDLTool"
|
||||||
|
PreprocessorDefinitions="NDEBUG"
|
||||||
|
MkTypLibCompatible="false"
|
||||||
|
TypeLibraryName="$(IntDir)/$(ProjectName).tlb"
|
||||||
|
HeaderFileName="$(ProjectName)idl.h"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCCLCompilerTool"
|
||||||
|
PreprocessorDefinitions="WIN32;_WINDOWS;NDEBUG;_USRDLL"
|
||||||
|
StringPooling="true"
|
||||||
|
RuntimeLibrary="0"
|
||||||
|
EnableFunctionLevelLinking="true"
|
||||||
|
TreatWChar_tAsBuiltInType="true"
|
||||||
|
UsePrecompiledHeader="2"
|
||||||
|
WarningLevel="3"
|
||||||
|
Detect64BitPortabilityProblems="true"
|
||||||
|
DebugInformationFormat="3"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCManagedResourceCompilerTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCResourceCompilerTool"
|
||||||
|
PreprocessorDefinitions="NDEBUG"
|
||||||
|
Culture="1033"
|
||||||
|
AdditionalIncludeDirectories="$(IntDir)"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCPreLinkEventTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCLinkerTool"
|
||||||
|
AdditionalDependencies="wininet.lib"
|
||||||
|
OutputFile="$(OutDir)/DisneyOnlineGames.ocx"
|
||||||
|
LinkIncremental="1"
|
||||||
|
ModuleDefinitionFile=".\DisneyOnlineGames.def"
|
||||||
|
GenerateDebugInformation="false"
|
||||||
|
SubSystem="2"
|
||||||
|
OptimizeReferences="2"
|
||||||
|
EnableCOMDATFolding="2"
|
||||||
|
OptimizeForWindows98="1"
|
||||||
|
ImportLibrary="$(IntDir)/DisneyOnlineGames.lib"
|
||||||
|
TargetMachine="1"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCALinkTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCManifestTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCXDCMakeTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCBscMakeTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCFxCopTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCAppVerifierTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCWebDeploymentTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCPostBuildEventTool"
|
||||||
|
Description="Performing registration"
|
||||||
|
CommandLine="regsvr32 /s /c "$(TargetPath)""
|
||||||
|
ExcludedFromBuild="true"
|
||||||
|
/>
|
||||||
|
</Configuration>
|
||||||
|
</Configurations>
|
||||||
|
<References>
|
||||||
|
</References>
|
||||||
|
<Files>
|
||||||
|
<Filter
|
||||||
|
Name="Source Files"
|
||||||
|
Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"
|
||||||
|
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
|
||||||
|
>
|
||||||
|
<File
|
||||||
|
RelativePath=".\DisneyOnlineGames.cpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\DisneyOnlineGames.def"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\DisneyOnlineGames.idl"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\DisneyOnlineGamesCtrl.cpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\DisneyOnlineGamesPropPage.cpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\EnvBlock.cpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\RunPiratesOnline.cpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\stdafx.cpp"
|
||||||
|
>
|
||||||
|
<FileConfiguration
|
||||||
|
Name="Debug|Win32"
|
||||||
|
>
|
||||||
|
<Tool
|
||||||
|
Name="VCCLCompilerTool"
|
||||||
|
UsePrecompiledHeader="1"
|
||||||
|
/>
|
||||||
|
</FileConfiguration>
|
||||||
|
<FileConfiguration
|
||||||
|
Name="Release|Win32"
|
||||||
|
>
|
||||||
|
<Tool
|
||||||
|
Name="VCCLCompilerTool"
|
||||||
|
UsePrecompiledHeader="1"
|
||||||
|
/>
|
||||||
|
</FileConfiguration>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\TopLevelWindowIterator.cpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
</Filter>
|
||||||
|
<Filter
|
||||||
|
Name="Header Files"
|
||||||
|
Filter="h;hpp;hxx;hm;inl;inc;xsd"
|
||||||
|
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
|
||||||
|
>
|
||||||
|
<File
|
||||||
|
RelativePath=".\DisneyOnlineGames.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\DisneyOnlineGamesCtrl.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\DisneyOnlineGamesPropPage.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\EnvBlock.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\Resource.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\RunPiratesOnline.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\stdafx.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\TopLevelWindowIterator.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
</Filter>
|
||||||
|
<Filter
|
||||||
|
Name="Resource Files"
|
||||||
|
Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx"
|
||||||
|
UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
|
||||||
|
>
|
||||||
|
<File
|
||||||
|
RelativePath=".\DisneyOnlineGames.rc"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\DisneyOnlineGamesCtrl.bmp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
</Filter>
|
||||||
|
</Files>
|
||||||
|
<Globals>
|
||||||
|
<Global
|
||||||
|
Name="RESOURCE_FILE"
|
||||||
|
Value="DisneyOnlineGames.rc"
|
||||||
|
/>
|
||||||
|
</Globals>
|
||||||
|
</VisualStudioProject>
|
201
otp/src/activex/DisneyOnlineGames/src/DisneyOnlineGames.cpp
Normal file
201
otp/src/activex/DisneyOnlineGames/src/DisneyOnlineGames.cpp
Normal file
|
@ -0,0 +1,201 @@
|
||||||
|
#include "stdafx.h"
|
||||||
|
#include "DisneyOnlineGames.h"
|
||||||
|
#include "comcat.h"
|
||||||
|
#include "strsafe.h"
|
||||||
|
#include "objsafe.h"
|
||||||
|
|
||||||
|
#ifdef _DEBUG
|
||||||
|
#define new DEBUG_NEW
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// CLSID_SafeItem - Necessary for safe ActiveX control
|
||||||
|
// Taken from IMPLEMENT_OLECREATE_EX function in DisneyOnlineGamesCtrl.cpp
|
||||||
|
|
||||||
|
const CATID CLSID_SafeItem =
|
||||||
|
{ 0x3dcec959, 0x378a, 0x4922,{ 0xad, 0x7e, 0xfd, 0x5c, 0x92, 0x5d, 0x92, 0x7f}};
|
||||||
|
|
||||||
|
HRESULT CreateComponentCategory(CATID catid, WCHAR *catDescription)
|
||||||
|
{
|
||||||
|
ICatRegister *pcr = NULL ;
|
||||||
|
HRESULT hr = S_OK ;
|
||||||
|
|
||||||
|
hr = CoCreateInstance(CLSID_StdComponentCategoriesMgr,
|
||||||
|
NULL, CLSCTX_INPROC_SERVER, IID_ICatRegister, (void**)&pcr);
|
||||||
|
if (FAILED(hr))
|
||||||
|
return hr;
|
||||||
|
|
||||||
|
// Make sure the HKCR\Component Categories\{..catid...}
|
||||||
|
// key is registered.
|
||||||
|
CATEGORYINFO catinfo;
|
||||||
|
catinfo.catid = catid;
|
||||||
|
catinfo.lcid = 0x0409 ; // english
|
||||||
|
size_t len;
|
||||||
|
// Make sure the provided description is not too long.
|
||||||
|
// Only copy the first 127 characters if it is.
|
||||||
|
// The second parameter of StringCchLength is the maximum
|
||||||
|
// number of characters that may be read into catDescription.
|
||||||
|
// There must be room for a NULL-terminator. The third parameter
|
||||||
|
// contains the number of characters excluding the NULL-terminator.
|
||||||
|
hr = StringCchLengthW(catDescription, STRSAFE_MAX_CCH, &len);
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
if (len>127)
|
||||||
|
{
|
||||||
|
len = 127;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// TODO: Write an error handler;
|
||||||
|
}
|
||||||
|
// The second parameter of StringCchCopy is 128 because you need
|
||||||
|
// room for a NULL-terminator.
|
||||||
|
hr = StringCchCopyW(catinfo.szDescription, len + 1, catDescription);
|
||||||
|
// Make sure the description is null terminated.
|
||||||
|
catinfo.szDescription[len + 1] = '\0';
|
||||||
|
|
||||||
|
hr = pcr->RegisterCategories(1, &catinfo);
|
||||||
|
pcr->Release();
|
||||||
|
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// HRESULT RegisterCLSIDInCategory -
|
||||||
|
// Register your component categories information
|
||||||
|
|
||||||
|
HRESULT RegisterCLSIDInCategory(REFCLSID clsid, CATID catid)
|
||||||
|
{
|
||||||
|
// Register your component categories information.
|
||||||
|
ICatRegister *pcr = NULL ;
|
||||||
|
HRESULT hr = S_OK ;
|
||||||
|
hr = CoCreateInstance(CLSID_StdComponentCategoriesMgr,
|
||||||
|
NULL, CLSCTX_INPROC_SERVER, IID_ICatRegister, (void**)&pcr);
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
// Register this category as being "implemented" by the class.
|
||||||
|
CATID rgcatid[1] ;
|
||||||
|
rgcatid[0] = catid;
|
||||||
|
hr = pcr->RegisterClassImplCategories(clsid, 1, rgcatid);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pcr != NULL)
|
||||||
|
pcr->Release();
|
||||||
|
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// HRESULT UnRegisterCLSIDInCategory - Remove entries from the registry
|
||||||
|
|
||||||
|
HRESULT UnRegisterCLSIDInCategory(REFCLSID clsid, CATID catid)
|
||||||
|
{
|
||||||
|
ICatRegister *pcr = NULL ;
|
||||||
|
HRESULT hr = S_OK ;
|
||||||
|
|
||||||
|
hr = CoCreateInstance(CLSID_StdComponentCategoriesMgr,
|
||||||
|
NULL, CLSCTX_INPROC_SERVER, IID_ICatRegister, (void**)&pcr);
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
// Unregister this category as being "implemented" by the class.
|
||||||
|
CATID rgcatid[1] ;
|
||||||
|
rgcatid[0] = catid;
|
||||||
|
hr = pcr->UnRegisterClassImplCategories(clsid, 1, rgcatid);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pcr != NULL)
|
||||||
|
pcr->Release();
|
||||||
|
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
|
||||||
|
CDisneyOnlineGamesApp theApp;
|
||||||
|
|
||||||
|
const GUID CDECL BASED_CODE _tlid =
|
||||||
|
{ 0x5F6C8F0A, 0x6FE5, 0x4546, { 0x82, 0xF1, 0x9B, 0x50, 0x37, 0x3A, 0x8E, 0xBD } };
|
||||||
|
const WORD _wVerMajor = 3;
|
||||||
|
const WORD _wVerMinor = 1;
|
||||||
|
|
||||||
|
BOOL CDisneyOnlineGamesApp::InitInstance()
|
||||||
|
// DLL initialization
|
||||||
|
{
|
||||||
|
BOOL bInit = COleControlModule::InitInstance();
|
||||||
|
if (bInit)
|
||||||
|
{
|
||||||
|
// TODO: Add your own module initialization code here.
|
||||||
|
}
|
||||||
|
return bInit;
|
||||||
|
}
|
||||||
|
|
||||||
|
int CDisneyOnlineGamesApp::ExitInstance()
|
||||||
|
// DLL termination
|
||||||
|
{
|
||||||
|
// TODO: Add your own module termination code here.
|
||||||
|
return COleControlModule::ExitInstance();
|
||||||
|
}
|
||||||
|
|
||||||
|
STDAPI DllRegisterServer(void)
|
||||||
|
// Adds entries to the system registry
|
||||||
|
{
|
||||||
|
HRESULT hr; // HResult used by Safety Functions
|
||||||
|
|
||||||
|
AFX_MANAGE_STATE(_afxModuleAddrThis);
|
||||||
|
|
||||||
|
if (!AfxOleRegisterTypeLib(AfxGetInstanceHandle(), _tlid))
|
||||||
|
return ResultFromScode(SELFREG_E_TYPELIB);
|
||||||
|
|
||||||
|
if (!COleObjectFactoryEx::UpdateRegistryAll(TRUE))
|
||||||
|
return ResultFromScode(SELFREG_E_CLASS);
|
||||||
|
|
||||||
|
// Mark the control as safe for initializing.
|
||||||
|
|
||||||
|
hr = CreateComponentCategory(CATID_SafeForInitializing,
|
||||||
|
L"Controls safely initializable from persistent data!");
|
||||||
|
if (FAILED(hr))
|
||||||
|
return hr;
|
||||||
|
|
||||||
|
hr = RegisterCLSIDInCategory(CLSID_SafeItem,
|
||||||
|
CATID_SafeForInitializing);
|
||||||
|
if (FAILED(hr))
|
||||||
|
return hr;
|
||||||
|
|
||||||
|
// Mark the control as safe for scripting.
|
||||||
|
|
||||||
|
hr = CreateComponentCategory(CATID_SafeForScripting,
|
||||||
|
L"Controls safely scriptable!");
|
||||||
|
if (FAILED(hr))
|
||||||
|
return hr;
|
||||||
|
|
||||||
|
hr = RegisterCLSIDInCategory(CLSID_SafeItem,
|
||||||
|
CATID_SafeForScripting);
|
||||||
|
if (FAILED(hr))
|
||||||
|
return hr;
|
||||||
|
|
||||||
|
return NOERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
STDAPI DllUnregisterServer(void)
|
||||||
|
// Removes entries from the system registry
|
||||||
|
{
|
||||||
|
HRESULT hr; // HResult used by Safety Functions
|
||||||
|
|
||||||
|
AFX_MANAGE_STATE(_afxModuleAddrThis);
|
||||||
|
|
||||||
|
if (!AfxOleUnregisterTypeLib(_tlid, _wVerMajor, _wVerMinor))
|
||||||
|
return ResultFromScode(SELFREG_E_TYPELIB);
|
||||||
|
|
||||||
|
if (!COleObjectFactoryEx::UpdateRegistryAll(FALSE))
|
||||||
|
return ResultFromScode(SELFREG_E_CLASS);
|
||||||
|
|
||||||
|
// Remove entries from the registry.
|
||||||
|
|
||||||
|
hr=UnRegisterCLSIDInCategory(CLSID_SafeItem,
|
||||||
|
CATID_SafeForInitializing);
|
||||||
|
if (FAILED(hr))
|
||||||
|
return hr;
|
||||||
|
|
||||||
|
hr=UnRegisterCLSIDInCategory(CLSID_SafeItem,
|
||||||
|
CATID_SafeForScripting);
|
||||||
|
if (FAILED(hr))
|
||||||
|
return hr;
|
||||||
|
|
||||||
|
return NOERROR;
|
||||||
|
}
|
|
@ -0,0 +1,9 @@
|
||||||
|
; DisneyOnlineGames.def : Declares the module parameters.
|
||||||
|
|
||||||
|
LIBRARY "DisneyOnlineGames.OCX"
|
||||||
|
|
||||||
|
EXPORTS
|
||||||
|
DllCanUnloadNow PRIVATE
|
||||||
|
DllGetClassObject PRIVATE
|
||||||
|
DllRegisterServer PRIVATE
|
||||||
|
DllUnregisterServer PRIVATE
|
20
otp/src/activex/DisneyOnlineGames/src/DisneyOnlineGames.h
Normal file
20
otp/src/activex/DisneyOnlineGames/src/DisneyOnlineGames.h
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#if !defined( __AFXCTL_H__ )
|
||||||
|
#error "include 'afxctl.h' before including this file"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "resource.h" // main symbols
|
||||||
|
|
||||||
|
|
||||||
|
class CDisneyOnlineGamesApp : public COleControlModule
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
BOOL InitInstance();
|
||||||
|
int ExitInstance();
|
||||||
|
};
|
||||||
|
|
||||||
|
extern const GUID CDECL _tlid;
|
||||||
|
extern const WORD _wVerMajor;
|
||||||
|
extern const WORD _wVerMinor;
|
||||||
|
|
55
otp/src/activex/DisneyOnlineGames/src/DisneyOnlineGames.idl
Normal file
55
otp/src/activex/DisneyOnlineGames/src/DisneyOnlineGames.idl
Normal file
|
@ -0,0 +1,55 @@
|
||||||
|
// DisneyOnlineGames.idl : type library source for ActiveX Control project.
|
||||||
|
|
||||||
|
// This file will be processed by the MIDL compiler tool to
|
||||||
|
// produce the type library (DisneyOnlineGames.tlb) that will become a resource in
|
||||||
|
// DisneyOnlineGames.ocx.
|
||||||
|
|
||||||
|
#include <olectl.h>
|
||||||
|
#include <idispids.h>
|
||||||
|
|
||||||
|
[ uuid(5F6C8F0A-6FE5-4546-82F1-9B50373A8EBD), version(1.0),
|
||||||
|
helpfile("DisneyOnlineGames.hlp"),
|
||||||
|
helpstring("Disney Online Games ActiveX Control module"),
|
||||||
|
control ]
|
||||||
|
library DisneyOnlineGamesLib
|
||||||
|
{
|
||||||
|
importlib(STDOLE_TLB);
|
||||||
|
|
||||||
|
// Primary dispatch interface for CDisneyOnlineGamesCtrl
|
||||||
|
|
||||||
|
[ uuid(33BDF503-F6F7-456C-B3C9-F74F294C8EB7),
|
||||||
|
helpstring("Dispatch interface for Disney Online Games Control")]
|
||||||
|
dispinterface _DDisneyOnlineGames
|
||||||
|
{
|
||||||
|
properties:
|
||||||
|
[id(2), helpstring("property ModeId")] BSTR ModeId;
|
||||||
|
[id(9) , helpstring("property ResponseCode")] ULONG ResponseCode;
|
||||||
|
[id(10) , helpstring("property Token")] BSTR Token;
|
||||||
|
methods:
|
||||||
|
[id(5), helpstring("method runPiratesOnline")] void runPiratesOnline(void);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Event dispatch interface for CDisneyOnlineGamesCtrl
|
||||||
|
|
||||||
|
[ uuid(CAC95DCF-C37B-4173-901A-ED2D6EDC5177),
|
||||||
|
helpstring("Event interface for Disney Online Games Control") ]
|
||||||
|
dispinterface _DDisneyOnlineGamesEvents
|
||||||
|
{
|
||||||
|
properties:
|
||||||
|
// Event interface has no properties
|
||||||
|
|
||||||
|
methods:
|
||||||
|
[id(1)] void onRunPiratesOnlineComplete(void);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Class information for CDisneyOnlineGamesCtrl
|
||||||
|
|
||||||
|
[ uuid(3DCEC959-378A-4922-AD7E-FD5C925D927F),
|
||||||
|
helpstring("Disney Online Games Control"), control ]
|
||||||
|
coclass DisneyOnlineGames
|
||||||
|
{
|
||||||
|
[default] dispinterface _DDisneyOnlineGames;
|
||||||
|
[default, source] dispinterface _DDisneyOnlineGamesEvents;
|
||||||
|
};
|
||||||
|
|
||||||
|
};
|
159
otp/src/activex/DisneyOnlineGames/src/DisneyOnlineGames.rc
Normal file
159
otp/src/activex/DisneyOnlineGames/src/DisneyOnlineGames.rc
Normal file
|
@ -0,0 +1,159 @@
|
||||||
|
// Microsoft Visual C++ generated resource script.
|
||||||
|
//
|
||||||
|
#include "resource.h"
|
||||||
|
|
||||||
|
#define APSTUDIO_READONLY_SYMBOLS
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// Generated from the TEXTINCLUDE 2 resource.
|
||||||
|
//
|
||||||
|
#include "afxres.h"
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
#undef APSTUDIO_READONLY_SYMBOLS
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
// English (U.S.) resources
|
||||||
|
|
||||||
|
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
|
||||||
|
#ifdef _WIN32
|
||||||
|
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
|
||||||
|
#pragma code_page(1252)
|
||||||
|
#endif //_WIN32
|
||||||
|
|
||||||
|
#ifdef APSTUDIO_INVOKED
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// TEXTINCLUDE
|
||||||
|
//
|
||||||
|
|
||||||
|
1 TEXTINCLUDE
|
||||||
|
BEGIN
|
||||||
|
"resource.h\0"
|
||||||
|
END
|
||||||
|
|
||||||
|
2 TEXTINCLUDE
|
||||||
|
BEGIN
|
||||||
|
"#include ""afxres.h""\r\n"
|
||||||
|
"\0"
|
||||||
|
END
|
||||||
|
|
||||||
|
3 TEXTINCLUDE
|
||||||
|
BEGIN
|
||||||
|
"1 TYPELIB ""DisneyOnlineGames.tlb""\r\n"
|
||||||
|
"\0"
|
||||||
|
END
|
||||||
|
|
||||||
|
#endif // APSTUDIO_INVOKED
|
||||||
|
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// Version
|
||||||
|
//
|
||||||
|
|
||||||
|
VS_VERSION_INFO VERSIONINFO
|
||||||
|
FILEVERSION 7,6,6,1549
|
||||||
|
PRODUCTVERSION 3,0,1,5
|
||||||
|
FILEFLAGSMASK 0x3fL
|
||||||
|
#ifdef _DEBUG
|
||||||
|
FILEFLAGS 0x1L
|
||||||
|
#else
|
||||||
|
FILEFLAGS 0x0L
|
||||||
|
#endif
|
||||||
|
FILEOS 0x4L
|
||||||
|
FILETYPE 0x2L
|
||||||
|
FILESUBTYPE 0x0L
|
||||||
|
BEGIN
|
||||||
|
BLOCK "StringFileInfo"
|
||||||
|
BEGIN
|
||||||
|
BLOCK "040904e4"
|
||||||
|
BEGIN
|
||||||
|
VALUE "CompanyName", "Walt Disney Co."
|
||||||
|
VALUE "FileDescription", "Disney Online Games ActiveX Control"
|
||||||
|
VALUE "FileVersion", "7, 6, 6, 1549"
|
||||||
|
VALUE "InternalName", "DisneyOnlineGames.ocx"
|
||||||
|
VALUE "LegalCopyright", "Copyright © 2007 Walt Disney Co."
|
||||||
|
VALUE "OriginalFilename", "DisneyOnlineGames.ocx"
|
||||||
|
VALUE "ProductName", "DisneyOnlineGames"
|
||||||
|
VALUE "ProductVersion", "3, 0, 1, 5"
|
||||||
|
END
|
||||||
|
END
|
||||||
|
BLOCK "VarFileInfo"
|
||||||
|
BEGIN
|
||||||
|
VALUE "Translation", 0x409, 1252
|
||||||
|
END
|
||||||
|
END
|
||||||
|
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// Bitmap
|
||||||
|
//
|
||||||
|
|
||||||
|
IDB_DISNEYONLINEGAMES BITMAP "DisneyOnlineGamesCtrl.bmp"
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// Dialog
|
||||||
|
//
|
||||||
|
|
||||||
|
IDD_PROPPAGE_DISNEYONLINEGAMES DIALOG 0, 0, 250, 62
|
||||||
|
STYLE DS_SETFONT | WS_CHILD
|
||||||
|
FONT 8, "MS Sans Serif"
|
||||||
|
BEGIN
|
||||||
|
LTEXT "TODO: Place controls to manipulate properties of DisneyOnlineGames Control on this dialog.",
|
||||||
|
IDC_STATIC,7,25,229,16
|
||||||
|
END
|
||||||
|
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// DESIGNINFO
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifdef APSTUDIO_INVOKED
|
||||||
|
GUIDELINES DESIGNINFO
|
||||||
|
BEGIN
|
||||||
|
IDD_PROPPAGE_DISNEYONLINEGAMES, DIALOG
|
||||||
|
BEGIN
|
||||||
|
LEFTMARGIN, 7
|
||||||
|
RIGHTMARGIN, 243
|
||||||
|
TOPMARGIN, 7
|
||||||
|
BOTTOMMARGIN, 55
|
||||||
|
END
|
||||||
|
END
|
||||||
|
#endif // APSTUDIO_INVOKED
|
||||||
|
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// String Table
|
||||||
|
//
|
||||||
|
|
||||||
|
STRINGTABLE
|
||||||
|
BEGIN
|
||||||
|
IDS_DISNEYONLINEGAMES "Disney Online Games ActiveX Control"
|
||||||
|
IDS_DISNEYONLINEGAMES_PPG "Disney Online Games ActiveX Property Page"
|
||||||
|
END
|
||||||
|
|
||||||
|
STRINGTABLE
|
||||||
|
BEGIN
|
||||||
|
IDS_DISNEYONLINEGAMES_PPG_CAPTION "General"
|
||||||
|
END
|
||||||
|
|
||||||
|
#endif // English (U.S.) resources
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef APSTUDIO_INVOKED
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// Generated from the TEXTINCLUDE 3 resource.
|
||||||
|
//
|
||||||
|
1 TYPELIB "DisneyOnlineGames.tlb"
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
#endif // not APSTUDIO_INVOKED
|
||||||
|
|
BIN
otp/src/activex/DisneyOnlineGames/src/DisneyOnlineGamesCtrl.bmp
Normal file
BIN
otp/src/activex/DisneyOnlineGames/src/DisneyOnlineGamesCtrl.bmp
Normal file
Binary file not shown.
After Width: | Height: | Size: 246 B |
236
otp/src/activex/DisneyOnlineGames/src/DisneyOnlineGamesCtrl.cpp
Normal file
236
otp/src/activex/DisneyOnlineGames/src/DisneyOnlineGamesCtrl.cpp
Normal file
|
@ -0,0 +1,236 @@
|
||||||
|
#include "stdafx.h"
|
||||||
|
#include "DisneyOnlineGames.h"
|
||||||
|
#include "DisneyOnlineGamesCtrl.h"
|
||||||
|
#include "DisneyOnlineGamesPropPage.h"
|
||||||
|
|
||||||
|
#ifdef _DEBUG
|
||||||
|
#define new DEBUG_NEW
|
||||||
|
#endif
|
||||||
|
|
||||||
|
IMPLEMENT_DYNCREATE(CDisneyOnlineGamesCtrl, COleControl)
|
||||||
|
|
||||||
|
// Message map
|
||||||
|
|
||||||
|
BEGIN_MESSAGE_MAP(CDisneyOnlineGamesCtrl, COleControl)
|
||||||
|
ON_OLEVERB(AFX_IDS_VERB_EDIT, OnEdit)
|
||||||
|
ON_OLEVERB(AFX_IDS_VERB_PROPERTIES, OnProperties)
|
||||||
|
END_MESSAGE_MAP()
|
||||||
|
|
||||||
|
// Dispatch map
|
||||||
|
|
||||||
|
BEGIN_DISPATCH_MAP(CDisneyOnlineGamesCtrl, COleControl)
|
||||||
|
DISP_PROPERTY_NOTIFY_ID(CDisneyOnlineGamesCtrl, "ModeId", dispidModeId, m_ModeId, OnModeIdChanged, VT_BSTR)
|
||||||
|
DISP_FUNCTION_ID(CDisneyOnlineGamesCtrl, "runPiratesOnline", dispidrunPiratesOnline, exportedmethodrunPiratesOnline, VT_EMPTY, VTS_NONE)
|
||||||
|
DISP_PROPERTY_NOTIFY_ID(CDisneyOnlineGamesCtrl, "ResponseCode", dispidResponseCode, m_ResponseCode, OnResponseCodeChanged, VT_UI4)
|
||||||
|
DISP_PROPERTY_NOTIFY_ID(CDisneyOnlineGamesCtrl, "Token", dispidToken, m_Token, OnTokenChanged, VT_BSTR)
|
||||||
|
END_DISPATCH_MAP()
|
||||||
|
|
||||||
|
// Event map
|
||||||
|
|
||||||
|
BEGIN_EVENT_MAP(CDisneyOnlineGamesCtrl, COleControl)
|
||||||
|
EVENT_CUSTOM_ID("onRunPiratesOnlineComplete", eventidonRunPiratesOnlineComplete, Fire_onRunPiratesOnlineComplete, VTS_NONE)
|
||||||
|
END_EVENT_MAP()
|
||||||
|
|
||||||
|
// Property pages
|
||||||
|
|
||||||
|
// TODO: Add more property pages as needed. Remember to increase the count!
|
||||||
|
BEGIN_PROPPAGEIDS(CDisneyOnlineGamesCtrl, 1)
|
||||||
|
PROPPAGEID(CDisneyOnlineGamesPropPage::guid)
|
||||||
|
END_PROPPAGEIDS(CDisneyOnlineGamesCtrl)
|
||||||
|
|
||||||
|
// Initialize class factory and guid
|
||||||
|
|
||||||
|
IMPLEMENT_OLECREATE_EX(CDisneyOnlineGamesCtrl, "DISNEYONLINEGAMES.DisneyOnlineGamesCtrl.1",
|
||||||
|
0x3dcec959, 0x378a, 0x4922, 0xad, 0x7e, 0xfd, 0x5c, 0x92, 0x5d, 0x92, 0x7f)
|
||||||
|
|
||||||
|
// Type library ID and version
|
||||||
|
|
||||||
|
IMPLEMENT_OLETYPELIB(CDisneyOnlineGamesCtrl, _tlid, _wVerMajor, _wVerMinor)
|
||||||
|
|
||||||
|
// Interface IDs
|
||||||
|
|
||||||
|
const IID BASED_CODE IID_DDisneyOnlineGames =
|
||||||
|
{ 0x33BDF503, 0xF6F7, 0x456C, { 0xB3, 0xC9, 0xF7, 0x4F, 0x29, 0x4C, 0x8E, 0xB7 } };
|
||||||
|
const IID BASED_CODE IID_DDisneyOnlineGamesEvents =
|
||||||
|
{ 0xCAC95DCF, 0xC37B, 0x4173, { 0x90, 0x1A, 0xED, 0x2D, 0x6E, 0xDC, 0x51, 0x77 } };
|
||||||
|
|
||||||
|
// Control type information
|
||||||
|
|
||||||
|
static const DWORD BASED_CODE _dwDisneyOnlineGamesOleMisc =
|
||||||
|
OLEMISC_ALWAYSRUN |
|
||||||
|
OLEMISC_SETCLIENTSITEFIRST |
|
||||||
|
OLEMISC_INSIDEOUT |
|
||||||
|
OLEMISC_CANTLINKINSIDE |
|
||||||
|
OLEMISC_ACTIVATEWHENVISIBLE
|
||||||
|
;
|
||||||
|
|
||||||
|
IMPLEMENT_OLECTLTYPE(CDisneyOnlineGamesCtrl, IDS_DISNEYONLINEGAMES, _dwDisneyOnlineGamesOleMisc)
|
||||||
|
|
||||||
|
// CDisneyOnlineGamesCtrl::CDisneyOnlineGamesCtrlFactory::UpdateRegistry -
|
||||||
|
// Adds or removes system registry entries for CDisneyOnlineGamesCtrl
|
||||||
|
|
||||||
|
BOOL CDisneyOnlineGamesCtrl::CDisneyOnlineGamesCtrlFactory::UpdateRegistry(BOOL bRegister)
|
||||||
|
{
|
||||||
|
// TODO: Verify that your control follows apartment-model threading rules.
|
||||||
|
// Refer to MFC TechNote 64 for more information.
|
||||||
|
// If your control does not conform to the apartment-model rules, then
|
||||||
|
// you must modify the code below, changing the 6th parameter from
|
||||||
|
// afxRegInsertable | afxRegApartmentThreading to afxRegInsertable.
|
||||||
|
|
||||||
|
if (bRegister)
|
||||||
|
return AfxOleRegisterControlClass(
|
||||||
|
AfxGetInstanceHandle(),
|
||||||
|
m_clsid,
|
||||||
|
m_lpszProgID,
|
||||||
|
IDS_DISNEYONLINEGAMES,
|
||||||
|
IDB_DISNEYONLINEGAMES,
|
||||||
|
afxRegInsertable | afxRegApartmentThreading | afxRegFreeThreading,
|
||||||
|
_dwDisneyOnlineGamesOleMisc,
|
||||||
|
_tlid,
|
||||||
|
_wVerMajor,
|
||||||
|
_wVerMinor);
|
||||||
|
else
|
||||||
|
return AfxOleUnregisterClass(m_clsid, m_lpszProgID);
|
||||||
|
}
|
||||||
|
|
||||||
|
// CDisneyOnlineGamesCtrl::CDisneyOnlineGamesCtrl - Constructor
|
||||||
|
|
||||||
|
CDisneyOnlineGamesCtrl::CDisneyOnlineGamesCtrl()
|
||||||
|
{
|
||||||
|
InitializeIIDs(&IID_DDisneyOnlineGames, &IID_DDisneyOnlineGamesEvents);
|
||||||
|
}
|
||||||
|
|
||||||
|
// CDisneyOnlineGamesCtrl::~CDisneyOnlineGamesCtrl - Destructor
|
||||||
|
|
||||||
|
CDisneyOnlineGamesCtrl::~CDisneyOnlineGamesCtrl()
|
||||||
|
{
|
||||||
|
// TODO: Cleanup your control's instance data here.
|
||||||
|
}
|
||||||
|
|
||||||
|
// CDisneyOnlineGamesCtrl::OnDraw - Drawing function
|
||||||
|
|
||||||
|
void CDisneyOnlineGamesCtrl::OnDraw(
|
||||||
|
CDC* pdc, const CRect& rcBounds, const CRect& rcInvalid)
|
||||||
|
{
|
||||||
|
if (!pdc)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// CDisneyOnlineGamesCtrl::DoPropExchange - Persistence support
|
||||||
|
|
||||||
|
void CDisneyOnlineGamesCtrl::DoPropExchange(CPropExchange* pPX)
|
||||||
|
{
|
||||||
|
ExchangeVersion(pPX, MAKELONG(_wVerMinor, _wVerMajor));
|
||||||
|
COleControl::DoPropExchange(pPX);
|
||||||
|
|
||||||
|
// TODO: Call PX_ functions for each persistent custom property.
|
||||||
|
}
|
||||||
|
|
||||||
|
// CDisneyOnlineGamesCtrl::GetControlFlags -
|
||||||
|
// Flags to customize MFC's implementation of ActiveX controls.
|
||||||
|
//
|
||||||
|
DWORD CDisneyOnlineGamesCtrl::GetControlFlags()
|
||||||
|
{
|
||||||
|
DWORD dwFlags = COleControl::GetControlFlags();
|
||||||
|
return dwFlags;
|
||||||
|
}
|
||||||
|
|
||||||
|
// CDisneyOnlineGamesCtrl::OnResetState - Reset control to default state
|
||||||
|
|
||||||
|
void CDisneyOnlineGamesCtrl::OnResetState()
|
||||||
|
{
|
||||||
|
COleControl::OnResetState(); // Resets defaults found in DoPropExchange
|
||||||
|
|
||||||
|
// TODO: Reset any other control state here.
|
||||||
|
}
|
||||||
|
|
||||||
|
// CDisneyOnlineGamesCtrl message handlers
|
||||||
|
|
||||||
|
void CDisneyOnlineGamesCtrl::OnModeIdChanged(void)
|
||||||
|
{
|
||||||
|
AFX_MANAGE_STATE(AfxGetStaticModuleState());
|
||||||
|
|
||||||
|
// TODO: Add your property handler code here
|
||||||
|
|
||||||
|
SetModifiedFlag();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CDisneyOnlineGamesCtrl::exportedmethodrunPiratesOnline (void)
|
||||||
|
{
|
||||||
|
AFX_MANAGE_STATE(AfxGetStaticModuleState());
|
||||||
|
|
||||||
|
#if defined(_DEBUG_TOKEN_VALUE_)
|
||||||
|
{
|
||||||
|
// If the request to obtain the path to temporary directory failed
|
||||||
|
char szTempPath [MAX_PATH];
|
||||||
|
if (GetTempPath (MAX_PATH, szTempPath))
|
||||||
|
{
|
||||||
|
// If the request to obtain a unique temporary filename failed
|
||||||
|
char szInstallerFullPathname [MAX_PATH];
|
||||||
|
if (GetTempFileName (szTempPath, NULL, 0, szInstallerFullPathname))
|
||||||
|
{
|
||||||
|
// If the temporary file was not successfully opened for writing
|
||||||
|
HANDLE hFile;
|
||||||
|
if (INVALID_HANDLE_VALUE != (hFile = CreateFile (
|
||||||
|
szInstallerFullPathname,
|
||||||
|
GENERIC_WRITE,
|
||||||
|
0,
|
||||||
|
NULL,
|
||||||
|
CREATE_ALWAYS,
|
||||||
|
FILE_ATTRIBUTE_NORMAL,
|
||||||
|
NULL
|
||||||
|
)))
|
||||||
|
{
|
||||||
|
char szPrefix [] = "m_Token=\"";
|
||||||
|
char szSuffix [] = "\"";
|
||||||
|
char * pszBuf = (char *)malloc (lstrlen (szPrefix) + lstrlen (m_Token) + lstrlen (szSuffix) + 1);
|
||||||
|
strcpy (pszBuf, szPrefix);
|
||||||
|
strcat (pszBuf, m_Token);
|
||||||
|
strcat (pszBuf, szSuffix);
|
||||||
|
//
|
||||||
|
DWORD dwNumberOfBytesWritten;
|
||||||
|
WriteFile (hFile, pszBuf, lstrlen (pszBuf), &dwNumberOfBytesWritten, NULL);
|
||||||
|
//
|
||||||
|
CloseHandle (hFile);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
CRunPiratesOnline * pRunPiratesOnline = new CRunPiratesOnline ();
|
||||||
|
m_ResponseCode = pRunPiratesOnline->Run (atoi (m_ModeId), m_Token);
|
||||||
|
delete pRunPiratesOnline;
|
||||||
|
|
||||||
|
// If our attempt to run Pirates Online was successful
|
||||||
|
if (RESPONSE_CODE__SUCCESS == m_ResponseCode)
|
||||||
|
{
|
||||||
|
CTopLevelWindowIterator itlw (GetCurrentProcessId ());
|
||||||
|
for (HWND hWndTopLevelWindow = itlw.First(); hWndTopLevelWindow; hWndTopLevelWindow = itlw.Next())
|
||||||
|
{
|
||||||
|
// Minimize the top level window that was created by this process
|
||||||
|
::ShowWindow (hWndTopLevelWindow, SW_MINIMIZE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fire response to webpage
|
||||||
|
Fire_onRunPiratesOnlineComplete ();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CDisneyOnlineGamesCtrl::OnResponseCodeChanged(void)
|
||||||
|
{
|
||||||
|
AFX_MANAGE_STATE(AfxGetStaticModuleState());
|
||||||
|
|
||||||
|
// TODO: Add your property handler code here
|
||||||
|
|
||||||
|
SetModifiedFlag();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CDisneyOnlineGamesCtrl::OnTokenChanged(void)
|
||||||
|
{
|
||||||
|
AFX_MANAGE_STATE(AfxGetStaticModuleState());
|
||||||
|
|
||||||
|
// TODO: Add your property handler code here
|
||||||
|
|
||||||
|
SetModifiedFlag();
|
||||||
|
}
|
|
@ -0,0 +1,58 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
class CDisneyOnlineGamesCtrl : public COleControl
|
||||||
|
{
|
||||||
|
DECLARE_DYNCREATE(CDisneyOnlineGamesCtrl)
|
||||||
|
|
||||||
|
// Constructor
|
||||||
|
public:
|
||||||
|
CDisneyOnlineGamesCtrl();
|
||||||
|
|
||||||
|
// Overrides
|
||||||
|
public:
|
||||||
|
virtual void OnDraw(CDC* pdc, const CRect& rcBounds, const CRect& rcInvalid);
|
||||||
|
virtual void DoPropExchange(CPropExchange* pPX);
|
||||||
|
virtual void OnResetState();
|
||||||
|
virtual DWORD GetControlFlags();
|
||||||
|
|
||||||
|
// Implementation
|
||||||
|
protected:
|
||||||
|
~CDisneyOnlineGamesCtrl();
|
||||||
|
|
||||||
|
DECLARE_OLECREATE_EX(CDisneyOnlineGamesCtrl) // Class factory and guid
|
||||||
|
DECLARE_OLETYPELIB(CDisneyOnlineGamesCtrl) // GetTypeInfo
|
||||||
|
DECLARE_PROPPAGEIDS(CDisneyOnlineGamesCtrl) // Property page IDs
|
||||||
|
DECLARE_OLECTLTYPE(CDisneyOnlineGamesCtrl) // Type name and misc status
|
||||||
|
|
||||||
|
// Message maps
|
||||||
|
DECLARE_MESSAGE_MAP()
|
||||||
|
|
||||||
|
// Dispatch maps
|
||||||
|
DECLARE_DISPATCH_MAP()
|
||||||
|
|
||||||
|
// Event maps
|
||||||
|
DECLARE_EVENT_MAP()
|
||||||
|
|
||||||
|
// Dispatch and event IDs
|
||||||
|
public:
|
||||||
|
enum {
|
||||||
|
dispidToken = 10,
|
||||||
|
eventidonRunPiratesOnlineComplete = 1L,
|
||||||
|
dispidResponseCode = 9,
|
||||||
|
dispidrunPiratesOnline = 5L,
|
||||||
|
dispidModeId = 2,
|
||||||
|
};
|
||||||
|
protected:
|
||||||
|
void OnModeIdChanged(void);
|
||||||
|
CString m_ModeId;
|
||||||
|
void exportedmethodrunPiratesOnline(void);
|
||||||
|
void OnResponseCodeChanged(void);
|
||||||
|
ULONG m_ResponseCode;
|
||||||
|
void OnTokenChanged(void);
|
||||||
|
CString m_Token;
|
||||||
|
|
||||||
|
void Fire_onRunPiratesOnlineComplete(void)
|
||||||
|
{
|
||||||
|
FireEvent(eventidonRunPiratesOnlineComplete, EVENT_PARAM(VTS_NONE));
|
||||||
|
}
|
||||||
|
};
|
|
@ -0,0 +1,60 @@
|
||||||
|
#include "stdafx.h"
|
||||||
|
#include "DisneyOnlineGames.h"
|
||||||
|
#include "DisneyOnlineGamesPropPage.h"
|
||||||
|
|
||||||
|
#ifdef _DEBUG
|
||||||
|
#define new DEBUG_NEW
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
IMPLEMENT_DYNCREATE(CDisneyOnlineGamesPropPage, COlePropertyPage)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Message map
|
||||||
|
|
||||||
|
BEGIN_MESSAGE_MAP(CDisneyOnlineGamesPropPage, COlePropertyPage)
|
||||||
|
END_MESSAGE_MAP()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Initialize class factory and guid
|
||||||
|
|
||||||
|
IMPLEMENT_OLECREATE_EX(CDisneyOnlineGamesPropPage, "DISNEYONLINEGAMES.DisneyOnlineGamesPropPage.1",
|
||||||
|
0xe314aa7, 0x9a00, 0x4db3, 0xb0, 0x23, 0x7a, 0xda, 0x8d, 0xdf, 0x7d, 0x26)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// CDisneyOnlineGamesPropPage::CDisneyOnlineGamesPropPageFactory::UpdateRegistry -
|
||||||
|
// Adds or removes system registry entries for CDisneyOnlineGamesPropPage
|
||||||
|
|
||||||
|
BOOL CDisneyOnlineGamesPropPage::CDisneyOnlineGamesPropPageFactory::UpdateRegistry(BOOL bRegister)
|
||||||
|
{
|
||||||
|
if (bRegister)
|
||||||
|
return AfxOleRegisterPropertyPageClass(AfxGetInstanceHandle(),
|
||||||
|
m_clsid, IDS_DISNEYONLINEGAMES_PPG);
|
||||||
|
else
|
||||||
|
return AfxOleUnregisterClass(m_clsid, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// CDisneyOnlineGamesPropPage::CDisneyOnlineGamesPropPage - Constructor
|
||||||
|
|
||||||
|
CDisneyOnlineGamesPropPage::CDisneyOnlineGamesPropPage() :
|
||||||
|
COlePropertyPage(IDD, IDS_DISNEYONLINEGAMES_PPG_CAPTION)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// CDisneyOnlineGamesPropPage::DoDataExchange - Moves data between page and properties
|
||||||
|
|
||||||
|
void CDisneyOnlineGamesPropPage::DoDataExchange(CDataExchange* pDX)
|
||||||
|
{
|
||||||
|
DDP_PostProcessing(pDX);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// CDisneyOnlineGamesPropPage message handlers
|
|
@ -0,0 +1,23 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
class CDisneyOnlineGamesPropPage : public COlePropertyPage
|
||||||
|
{
|
||||||
|
DECLARE_DYNCREATE(CDisneyOnlineGamesPropPage)
|
||||||
|
DECLARE_OLECREATE_EX(CDisneyOnlineGamesPropPage)
|
||||||
|
|
||||||
|
// Constructor
|
||||||
|
public:
|
||||||
|
CDisneyOnlineGamesPropPage();
|
||||||
|
|
||||||
|
// Dialog Data
|
||||||
|
enum { IDD = IDD_PROPPAGE_DISNEYONLINEGAMES };
|
||||||
|
|
||||||
|
// Implementation
|
||||||
|
protected:
|
||||||
|
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
|
||||||
|
|
||||||
|
// Message maps
|
||||||
|
protected:
|
||||||
|
DECLARE_MESSAGE_MAP()
|
||||||
|
};
|
||||||
|
|
93
otp/src/activex/DisneyOnlineGames/src/DisneyOnlineGames_i.c
Normal file
93
otp/src/activex/DisneyOnlineGames/src/DisneyOnlineGames_i.c
Normal file
|
@ -0,0 +1,93 @@
|
||||||
|
|
||||||
|
|
||||||
|
/* this ALWAYS GENERATED file contains the IIDs and CLSIDs */
|
||||||
|
|
||||||
|
/* link this file in with the server and any clients */
|
||||||
|
|
||||||
|
|
||||||
|
/* File created by MIDL compiler version 6.00.0361 */
|
||||||
|
/* at Wed Jun 06 15:59:25 2007
|
||||||
|
*/
|
||||||
|
/* Compiler settings for .\DisneyOnlineGames.idl:
|
||||||
|
Oicf, W1, Zp8, env=Win32 (32b run)
|
||||||
|
protocol : dce , ms_ext, c_ext, robust
|
||||||
|
error checks: allocation ref bounds_check enum stub_data
|
||||||
|
VC __declspec() decoration level:
|
||||||
|
__declspec(uuid()), __declspec(selectany), __declspec(novtable)
|
||||||
|
DECLSPEC_UUID(), MIDL_INTERFACE()
|
||||||
|
*/
|
||||||
|
//@@MIDL_FILE_HEADING( )
|
||||||
|
|
||||||
|
#if !defined(_M_IA64) && !defined(_M_AMD64)
|
||||||
|
|
||||||
|
|
||||||
|
#pragma warning( disable: 4049 ) /* more than 64k source lines */
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C"{
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#include <rpc.h>
|
||||||
|
#include <rpcndr.h>
|
||||||
|
|
||||||
|
#ifdef _MIDL_USE_GUIDDEF_
|
||||||
|
|
||||||
|
#ifndef INITGUID
|
||||||
|
#define INITGUID
|
||||||
|
#include <guiddef.h>
|
||||||
|
#undef INITGUID
|
||||||
|
#else
|
||||||
|
#include <guiddef.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define MIDL_DEFINE_GUID(type,name,l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8) \
|
||||||
|
DEFINE_GUID(name,l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8)
|
||||||
|
|
||||||
|
#else // !_MIDL_USE_GUIDDEF_
|
||||||
|
|
||||||
|
#ifndef __IID_DEFINED__
|
||||||
|
#define __IID_DEFINED__
|
||||||
|
|
||||||
|
typedef struct _IID
|
||||||
|
{
|
||||||
|
unsigned long x;
|
||||||
|
unsigned short s1;
|
||||||
|
unsigned short s2;
|
||||||
|
unsigned char c[8];
|
||||||
|
} IID;
|
||||||
|
|
||||||
|
#endif // __IID_DEFINED__
|
||||||
|
|
||||||
|
#ifndef CLSID_DEFINED
|
||||||
|
#define CLSID_DEFINED
|
||||||
|
typedef IID CLSID;
|
||||||
|
#endif // CLSID_DEFINED
|
||||||
|
|
||||||
|
#define MIDL_DEFINE_GUID(type,name,l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8) \
|
||||||
|
const type name = {l,w1,w2,{b1,b2,b3,b4,b5,b6,b7,b8}}
|
||||||
|
|
||||||
|
#endif !_MIDL_USE_GUIDDEF_
|
||||||
|
|
||||||
|
MIDL_DEFINE_GUID(IID, LIBID_DisneyOnlineGamesLib,0x5F6C8F0A,0x6FE5,0x4546,0x82,0xF1,0x9B,0x50,0x37,0x3A,0x8E,0xBD);
|
||||||
|
|
||||||
|
|
||||||
|
MIDL_DEFINE_GUID(IID, DIID__DDisneyOnlineGames,0x33BDF503,0xF6F7,0x456C,0xB3,0xC9,0xF7,0x4F,0x29,0x4C,0x8E,0xB7);
|
||||||
|
|
||||||
|
|
||||||
|
MIDL_DEFINE_GUID(IID, DIID__DDisneyOnlineGamesEvents,0xCAC95DCF,0xC37B,0x4173,0x90,0x1A,0xED,0x2D,0x6E,0xDC,0x51,0x77);
|
||||||
|
|
||||||
|
|
||||||
|
MIDL_DEFINE_GUID(CLSID, CLSID_DisneyOnlineGames,0x3DCEC959,0x378A,0x4922,0xAD,0x7E,0xFD,0x5C,0x92,0x5D,0x92,0x7F);
|
||||||
|
|
||||||
|
#undef MIDL_DEFINE_GUID
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* !defined(_M_IA64) && !defined(_M_AMD64)*/
|
||||||
|
|
316
otp/src/activex/DisneyOnlineGames/src/DisneyOnlineGamesidl.h
Normal file
316
otp/src/activex/DisneyOnlineGames/src/DisneyOnlineGamesidl.h
Normal file
|
@ -0,0 +1,316 @@
|
||||||
|
|
||||||
|
|
||||||
|
/* this ALWAYS GENERATED file contains the definitions for the interfaces */
|
||||||
|
|
||||||
|
|
||||||
|
/* File created by MIDL compiler version 6.00.0361 */
|
||||||
|
/* at Wed Jun 06 15:59:25 2007
|
||||||
|
*/
|
||||||
|
/* Compiler settings for .\DisneyOnlineGames.idl:
|
||||||
|
Oicf, W1, Zp8, env=Win32 (32b run)
|
||||||
|
protocol : dce , ms_ext, c_ext, robust
|
||||||
|
error checks: allocation ref bounds_check enum stub_data
|
||||||
|
VC __declspec() decoration level:
|
||||||
|
__declspec(uuid()), __declspec(selectany), __declspec(novtable)
|
||||||
|
DECLSPEC_UUID(), MIDL_INTERFACE()
|
||||||
|
*/
|
||||||
|
//@@MIDL_FILE_HEADING( )
|
||||||
|
|
||||||
|
#pragma warning( disable: 4049 ) /* more than 64k source lines */
|
||||||
|
|
||||||
|
|
||||||
|
/* verify that the <rpcndr.h> version is high enough to compile this file*/
|
||||||
|
#ifndef __REQUIRED_RPCNDR_H_VERSION__
|
||||||
|
#define __REQUIRED_RPCNDR_H_VERSION__ 475
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "rpc.h"
|
||||||
|
#include "rpcndr.h"
|
||||||
|
|
||||||
|
#ifndef __RPCNDR_H_VERSION__
|
||||||
|
#error this stub requires an updated version of <rpcndr.h>
|
||||||
|
#endif // __RPCNDR_H_VERSION__
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef __DisneyOnlineGamesidl_h__
|
||||||
|
#define __DisneyOnlineGamesidl_h__
|
||||||
|
|
||||||
|
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||||
|
#pragma once
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Forward Declarations */
|
||||||
|
|
||||||
|
#ifndef ___DDisneyOnlineGames_FWD_DEFINED__
|
||||||
|
#define ___DDisneyOnlineGames_FWD_DEFINED__
|
||||||
|
typedef interface _DDisneyOnlineGames _DDisneyOnlineGames;
|
||||||
|
#endif /* ___DDisneyOnlineGames_FWD_DEFINED__ */
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef ___DDisneyOnlineGamesEvents_FWD_DEFINED__
|
||||||
|
#define ___DDisneyOnlineGamesEvents_FWD_DEFINED__
|
||||||
|
typedef interface _DDisneyOnlineGamesEvents _DDisneyOnlineGamesEvents;
|
||||||
|
#endif /* ___DDisneyOnlineGamesEvents_FWD_DEFINED__ */
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef __DisneyOnlineGames_FWD_DEFINED__
|
||||||
|
#define __DisneyOnlineGames_FWD_DEFINED__
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
typedef class DisneyOnlineGames DisneyOnlineGames;
|
||||||
|
#else
|
||||||
|
typedef struct DisneyOnlineGames DisneyOnlineGames;
|
||||||
|
#endif /* __cplusplus */
|
||||||
|
|
||||||
|
#endif /* __DisneyOnlineGames_FWD_DEFINED__ */
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C"{
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void * __RPC_USER MIDL_user_allocate(size_t);
|
||||||
|
void __RPC_USER MIDL_user_free( void * );
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef __DisneyOnlineGamesLib_LIBRARY_DEFINED__
|
||||||
|
#define __DisneyOnlineGamesLib_LIBRARY_DEFINED__
|
||||||
|
|
||||||
|
/* library DisneyOnlineGamesLib */
|
||||||
|
/* [control][helpstring][helpfile][version][uuid] */
|
||||||
|
|
||||||
|
|
||||||
|
EXTERN_C const IID LIBID_DisneyOnlineGamesLib;
|
||||||
|
|
||||||
|
#ifndef ___DDisneyOnlineGames_DISPINTERFACE_DEFINED__
|
||||||
|
#define ___DDisneyOnlineGames_DISPINTERFACE_DEFINED__
|
||||||
|
|
||||||
|
/* dispinterface _DDisneyOnlineGames */
|
||||||
|
/* [helpstring][uuid] */
|
||||||
|
|
||||||
|
|
||||||
|
EXTERN_C const IID DIID__DDisneyOnlineGames;
|
||||||
|
|
||||||
|
#if defined(__cplusplus) && !defined(CINTERFACE)
|
||||||
|
|
||||||
|
MIDL_INTERFACE("33BDF503-F6F7-456C-B3C9-F74F294C8EB7")
|
||||||
|
_DDisneyOnlineGames : public IDispatch
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
|
#else /* C style interface */
|
||||||
|
|
||||||
|
typedef struct _DDisneyOnlineGamesVtbl
|
||||||
|
{
|
||||||
|
BEGIN_INTERFACE
|
||||||
|
|
||||||
|
HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
|
||||||
|
_DDisneyOnlineGames * This,
|
||||||
|
/* [in] */ REFIID riid,
|
||||||
|
/* [iid_is][out] */ void **ppvObject);
|
||||||
|
|
||||||
|
ULONG ( STDMETHODCALLTYPE *AddRef )(
|
||||||
|
_DDisneyOnlineGames * This);
|
||||||
|
|
||||||
|
ULONG ( STDMETHODCALLTYPE *Release )(
|
||||||
|
_DDisneyOnlineGames * This);
|
||||||
|
|
||||||
|
HRESULT ( STDMETHODCALLTYPE *GetTypeInfoCount )(
|
||||||
|
_DDisneyOnlineGames * This,
|
||||||
|
/* [out] */ UINT *pctinfo);
|
||||||
|
|
||||||
|
HRESULT ( STDMETHODCALLTYPE *GetTypeInfo )(
|
||||||
|
_DDisneyOnlineGames * This,
|
||||||
|
/* [in] */ UINT iTInfo,
|
||||||
|
/* [in] */ LCID lcid,
|
||||||
|
/* [out] */ ITypeInfo **ppTInfo);
|
||||||
|
|
||||||
|
HRESULT ( STDMETHODCALLTYPE *GetIDsOfNames )(
|
||||||
|
_DDisneyOnlineGames * This,
|
||||||
|
/* [in] */ REFIID riid,
|
||||||
|
/* [size_is][in] */ LPOLESTR *rgszNames,
|
||||||
|
/* [in] */ UINT cNames,
|
||||||
|
/* [in] */ LCID lcid,
|
||||||
|
/* [size_is][out] */ DISPID *rgDispId);
|
||||||
|
|
||||||
|
/* [local] */ HRESULT ( STDMETHODCALLTYPE *Invoke )(
|
||||||
|
_DDisneyOnlineGames * This,
|
||||||
|
/* [in] */ DISPID dispIdMember,
|
||||||
|
/* [in] */ REFIID riid,
|
||||||
|
/* [in] */ LCID lcid,
|
||||||
|
/* [in] */ WORD wFlags,
|
||||||
|
/* [out][in] */ DISPPARAMS *pDispParams,
|
||||||
|
/* [out] */ VARIANT *pVarResult,
|
||||||
|
/* [out] */ EXCEPINFO *pExcepInfo,
|
||||||
|
/* [out] */ UINT *puArgErr);
|
||||||
|
|
||||||
|
END_INTERFACE
|
||||||
|
} _DDisneyOnlineGamesVtbl;
|
||||||
|
|
||||||
|
interface _DDisneyOnlineGames
|
||||||
|
{
|
||||||
|
CONST_VTBL struct _DDisneyOnlineGamesVtbl *lpVtbl;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef COBJMACROS
|
||||||
|
|
||||||
|
|
||||||
|
#define _DDisneyOnlineGames_QueryInterface(This,riid,ppvObject) \
|
||||||
|
(This)->lpVtbl -> QueryInterface(This,riid,ppvObject)
|
||||||
|
|
||||||
|
#define _DDisneyOnlineGames_AddRef(This) \
|
||||||
|
(This)->lpVtbl -> AddRef(This)
|
||||||
|
|
||||||
|
#define _DDisneyOnlineGames_Release(This) \
|
||||||
|
(This)->lpVtbl -> Release(This)
|
||||||
|
|
||||||
|
|
||||||
|
#define _DDisneyOnlineGames_GetTypeInfoCount(This,pctinfo) \
|
||||||
|
(This)->lpVtbl -> GetTypeInfoCount(This,pctinfo)
|
||||||
|
|
||||||
|
#define _DDisneyOnlineGames_GetTypeInfo(This,iTInfo,lcid,ppTInfo) \
|
||||||
|
(This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo)
|
||||||
|
|
||||||
|
#define _DDisneyOnlineGames_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) \
|
||||||
|
(This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId)
|
||||||
|
|
||||||
|
#define _DDisneyOnlineGames_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) \
|
||||||
|
(This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr)
|
||||||
|
|
||||||
|
#endif /* COBJMACROS */
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* C style interface */
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* ___DDisneyOnlineGames_DISPINTERFACE_DEFINED__ */
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef ___DDisneyOnlineGamesEvents_DISPINTERFACE_DEFINED__
|
||||||
|
#define ___DDisneyOnlineGamesEvents_DISPINTERFACE_DEFINED__
|
||||||
|
|
||||||
|
/* dispinterface _DDisneyOnlineGamesEvents */
|
||||||
|
/* [helpstring][uuid] */
|
||||||
|
|
||||||
|
|
||||||
|
EXTERN_C const IID DIID__DDisneyOnlineGamesEvents;
|
||||||
|
|
||||||
|
#if defined(__cplusplus) && !defined(CINTERFACE)
|
||||||
|
|
||||||
|
MIDL_INTERFACE("CAC95DCF-C37B-4173-901A-ED2D6EDC5177")
|
||||||
|
_DDisneyOnlineGamesEvents : public IDispatch
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
|
#else /* C style interface */
|
||||||
|
|
||||||
|
typedef struct _DDisneyOnlineGamesEventsVtbl
|
||||||
|
{
|
||||||
|
BEGIN_INTERFACE
|
||||||
|
|
||||||
|
HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
|
||||||
|
_DDisneyOnlineGamesEvents * This,
|
||||||
|
/* [in] */ REFIID riid,
|
||||||
|
/* [iid_is][out] */ void **ppvObject);
|
||||||
|
|
||||||
|
ULONG ( STDMETHODCALLTYPE *AddRef )(
|
||||||
|
_DDisneyOnlineGamesEvents * This);
|
||||||
|
|
||||||
|
ULONG ( STDMETHODCALLTYPE *Release )(
|
||||||
|
_DDisneyOnlineGamesEvents * This);
|
||||||
|
|
||||||
|
HRESULT ( STDMETHODCALLTYPE *GetTypeInfoCount )(
|
||||||
|
_DDisneyOnlineGamesEvents * This,
|
||||||
|
/* [out] */ UINT *pctinfo);
|
||||||
|
|
||||||
|
HRESULT ( STDMETHODCALLTYPE *GetTypeInfo )(
|
||||||
|
_DDisneyOnlineGamesEvents * This,
|
||||||
|
/* [in] */ UINT iTInfo,
|
||||||
|
/* [in] */ LCID lcid,
|
||||||
|
/* [out] */ ITypeInfo **ppTInfo);
|
||||||
|
|
||||||
|
HRESULT ( STDMETHODCALLTYPE *GetIDsOfNames )(
|
||||||
|
_DDisneyOnlineGamesEvents * This,
|
||||||
|
/* [in] */ REFIID riid,
|
||||||
|
/* [size_is][in] */ LPOLESTR *rgszNames,
|
||||||
|
/* [in] */ UINT cNames,
|
||||||
|
/* [in] */ LCID lcid,
|
||||||
|
/* [size_is][out] */ DISPID *rgDispId);
|
||||||
|
|
||||||
|
/* [local] */ HRESULT ( STDMETHODCALLTYPE *Invoke )(
|
||||||
|
_DDisneyOnlineGamesEvents * This,
|
||||||
|
/* [in] */ DISPID dispIdMember,
|
||||||
|
/* [in] */ REFIID riid,
|
||||||
|
/* [in] */ LCID lcid,
|
||||||
|
/* [in] */ WORD wFlags,
|
||||||
|
/* [out][in] */ DISPPARAMS *pDispParams,
|
||||||
|
/* [out] */ VARIANT *pVarResult,
|
||||||
|
/* [out] */ EXCEPINFO *pExcepInfo,
|
||||||
|
/* [out] */ UINT *puArgErr);
|
||||||
|
|
||||||
|
END_INTERFACE
|
||||||
|
} _DDisneyOnlineGamesEventsVtbl;
|
||||||
|
|
||||||
|
interface _DDisneyOnlineGamesEvents
|
||||||
|
{
|
||||||
|
CONST_VTBL struct _DDisneyOnlineGamesEventsVtbl *lpVtbl;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef COBJMACROS
|
||||||
|
|
||||||
|
|
||||||
|
#define _DDisneyOnlineGamesEvents_QueryInterface(This,riid,ppvObject) \
|
||||||
|
(This)->lpVtbl -> QueryInterface(This,riid,ppvObject)
|
||||||
|
|
||||||
|
#define _DDisneyOnlineGamesEvents_AddRef(This) \
|
||||||
|
(This)->lpVtbl -> AddRef(This)
|
||||||
|
|
||||||
|
#define _DDisneyOnlineGamesEvents_Release(This) \
|
||||||
|
(This)->lpVtbl -> Release(This)
|
||||||
|
|
||||||
|
|
||||||
|
#define _DDisneyOnlineGamesEvents_GetTypeInfoCount(This,pctinfo) \
|
||||||
|
(This)->lpVtbl -> GetTypeInfoCount(This,pctinfo)
|
||||||
|
|
||||||
|
#define _DDisneyOnlineGamesEvents_GetTypeInfo(This,iTInfo,lcid,ppTInfo) \
|
||||||
|
(This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo)
|
||||||
|
|
||||||
|
#define _DDisneyOnlineGamesEvents_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) \
|
||||||
|
(This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId)
|
||||||
|
|
||||||
|
#define _DDisneyOnlineGamesEvents_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) \
|
||||||
|
(This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr)
|
||||||
|
|
||||||
|
#endif /* COBJMACROS */
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* C style interface */
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* ___DDisneyOnlineGamesEvents_DISPINTERFACE_DEFINED__ */
|
||||||
|
|
||||||
|
|
||||||
|
EXTERN_C const CLSID CLSID_DisneyOnlineGames;
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
|
||||||
|
class DECLSPEC_UUID("3DCEC959-378A-4922-AD7E-FD5C925D927F")
|
||||||
|
DisneyOnlineGames;
|
||||||
|
#endif
|
||||||
|
#endif /* __DisneyOnlineGamesLib_LIBRARY_DEFINED__ */
|
||||||
|
|
||||||
|
/* Additional Prototypes for ALL interfaces */
|
||||||
|
|
||||||
|
/* end of Additional Prototypes */
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
94
otp/src/activex/DisneyOnlineGames/src/EnvBlock.cpp
Normal file
94
otp/src/activex/DisneyOnlineGames/src/EnvBlock.cpp
Normal file
|
@ -0,0 +1,94 @@
|
||||||
|
#include "stdafx.h"
|
||||||
|
|
||||||
|
void CEnvBlock::insert_env_block_key_value_pair (CString & strEnvForChildProcess,
|
||||||
|
int * pInsertIdx,
|
||||||
|
char * lpszVariable)
|
||||||
|
{
|
||||||
|
// Insert the next environment block key=value pair, accounting for the following facts:
|
||||||
|
// 1. There must be a terminating NULL byte ('\0') between each key=value pair
|
||||||
|
// 2. Two NULL bytes indicate environment block end
|
||||||
|
//---------------------------------------------------------------------------------------------
|
||||||
|
// In other words, an environment block consists of a null-terminated block of null-terminated
|
||||||
|
// strings (meaning there are two null bytes at the end of the block), where each string is of
|
||||||
|
// the form
|
||||||
|
// key=value
|
||||||
|
//---------------------------------------------------------------------------------------------
|
||||||
|
strEnvForChildProcess.Insert (*pInsertIdx, lpszVariable);
|
||||||
|
(*pInsertIdx) += (int)strlen (lpszVariable);
|
||||||
|
(*pInsertIdx)++;
|
||||||
|
strEnvForChildProcess.GetBufferSetLength (*pInsertIdx);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CEnvBlock::Create (const char * pszEnvKeyToAddToChildProcessEnvBlock,
|
||||||
|
CString & strEnvForChildProcess)
|
||||||
|
{
|
||||||
|
// Set environment key=value pair that the executable will look for
|
||||||
|
static const char szEnvKeyValuePairSeparator [] = "=";
|
||||||
|
CString strEnvKeyValuePairToAddToChildProcessEnvBlock;
|
||||||
|
strEnvKeyValuePairToAddToChildProcessEnvBlock.Format (
|
||||||
|
"%s%s%s",
|
||||||
|
pszEnvKeyToAddToChildProcessEnvBlock,
|
||||||
|
szEnvKeyValuePairSeparator,
|
||||||
|
m.pszToken);
|
||||||
|
// Ensure the string to hold the environment block for the child process is empty
|
||||||
|
strEnvForChildProcess.GetBufferSetLength (0);
|
||||||
|
// Initilize the child process environment block insert index
|
||||||
|
int InsertIdx = 0;
|
||||||
|
// Indicate that the key=value pair that the executable will look for has NOT yet been inserted
|
||||||
|
bool fAddedEnvKeyToChildProcessEnvBlock = false;
|
||||||
|
// If a pointer to the environment block for this process was returned
|
||||||
|
LPVOID lpvEnv;
|
||||||
|
if (lpvEnv = GetEnvironmentStrings ())
|
||||||
|
{
|
||||||
|
// Variable strings are separated by NULL byte, and the block is terminated by a NULL byte
|
||||||
|
LPTSTR lpszVariable;
|
||||||
|
for (lpszVariable = (LPTSTR)lpvEnv; *lpszVariable; lpszVariable += lstrlen (lpszVariable) + 1)
|
||||||
|
{
|
||||||
|
// If the key=value pair that the executable will look for has NOT yet been inserted
|
||||||
|
if (!fAddedEnvKeyToChildProcessEnvBlock)
|
||||||
|
{
|
||||||
|
// If the current key=value pair from this process' environment block is greater
|
||||||
|
// than the key=value pair that the executable will look for
|
||||||
|
//---------------------------------------------------------------------------------
|
||||||
|
// NOTE: All strings in the environment block must be sorted alphabetically by name.
|
||||||
|
// The sort is case-insensitive, Unicode order, without regard to locale.
|
||||||
|
// Because the equal sign is a separator, it must not be used in the name of
|
||||||
|
// an environment variable.
|
||||||
|
//---------------------------------------------------------------------------------
|
||||||
|
if (0 > strEnvKeyValuePairToAddToChildProcessEnvBlock.CompareNoCase (lpszVariable))
|
||||||
|
{
|
||||||
|
// Indicate that the key=value pair that the executable will look for has been
|
||||||
|
// inserted into the environment block for the child process
|
||||||
|
fAddedEnvKeyToChildProcessEnvBlock = true;
|
||||||
|
// Insert the next environment block key=value pair
|
||||||
|
insert_env_block_key_value_pair (
|
||||||
|
strEnvForChildProcess,
|
||||||
|
&InsertIdx,
|
||||||
|
strEnvKeyValuePairToAddToChildProcessEnvBlock.GetBuffer ());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Insert the next environment block key=value pair
|
||||||
|
insert_env_block_key_value_pair (
|
||||||
|
strEnvForChildProcess,
|
||||||
|
&InsertIdx,
|
||||||
|
lpszVariable);
|
||||||
|
}
|
||||||
|
// Free the environment block
|
||||||
|
FreeEnvironmentStrings ((LPTCH)lpvEnv);
|
||||||
|
}
|
||||||
|
// If the key=value pair that the executable will look for has NOT yet been inserted
|
||||||
|
if (!fAddedEnvKeyToChildProcessEnvBlock)
|
||||||
|
{
|
||||||
|
// Insert the next environment block key=value pair
|
||||||
|
insert_env_block_key_value_pair (
|
||||||
|
strEnvForChildProcess,
|
||||||
|
&InsertIdx,
|
||||||
|
strEnvKeyValuePairToAddToChildProcessEnvBlock.GetBuffer ());
|
||||||
|
}
|
||||||
|
// Insert the next environment block key=value pair
|
||||||
|
insert_env_block_key_value_pair (
|
||||||
|
strEnvForChildProcess,
|
||||||
|
&InsertIdx,
|
||||||
|
"\0");
|
||||||
|
}
|
||||||
|
|
23
otp/src/activex/DisneyOnlineGames/src/EnvBlock.h
Normal file
23
otp/src/activex/DisneyOnlineGames/src/EnvBlock.h
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
class CEnvBlock
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CEnvBlock (const char * pszToken)
|
||||||
|
{
|
||||||
|
memset (&m, 0, sizeof (m));
|
||||||
|
m.pszToken = pszToken;
|
||||||
|
}
|
||||||
|
~CEnvBlock (void)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
void Create (const char * pszEnvKeyToAddToChildProcessEnvBlock,
|
||||||
|
CString & strEnvForChildProcess);
|
||||||
|
private:
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
const char * pszToken;
|
||||||
|
} m;
|
||||||
|
private:
|
||||||
|
void insert_env_block_key_value_pair (CString & strEnvForChildProcess,
|
||||||
|
int * pInsertIdx,
|
||||||
|
char * lpszVariable);
|
||||||
|
};
|
877
otp/src/activex/DisneyOnlineGames/src/RunPiratesOnline.cpp
Normal file
877
otp/src/activex/DisneyOnlineGames/src/RunPiratesOnline.cpp
Normal file
|
@ -0,0 +1,877 @@
|
||||||
|
#include "stdafx.h"
|
||||||
|
|
||||||
|
static const char szEnvKeyToAddToChildProcessEnvBlock [] = "DisneyOnlineGamesToken";
|
||||||
|
static const char szInstallerCommandLineOptionPrefix [] = "/";
|
||||||
|
static const char szInstallerSilentRunModeOption [] = "S";
|
||||||
|
|
||||||
|
typedef struct _tag_MMOG_FLAVOR
|
||||||
|
{
|
||||||
|
const int mode;
|
||||||
|
const char * pszInstallerURL;
|
||||||
|
const char * pszLauncherCSIDL;
|
||||||
|
const char * pszLauncherPathname;
|
||||||
|
} MMOG_FLAVOR, *PMMOG_FLAVOR;
|
||||||
|
|
||||||
|
static const MMOG_FLAVOR gsc_mmogFlavor [] = {
|
||||||
|
{
|
||||||
|
// Development
|
||||||
|
1,
|
||||||
|
"http://build64.online.disney.com:3120/english/currentVersion/dev/PotC-setup_DEV.exe",
|
||||||
|
"PROGRAM_FILES",
|
||||||
|
"\\Disney\\Disney Online\\PiratesOnline_DEV\\Launcher1.exe",
|
||||||
|
}
|
||||||
|
,
|
||||||
|
{ // QA
|
||||||
|
2,
|
||||||
|
"http://pirate143b.starwave.com:1420/english/currentVersion/qa/PotC-setup_QA.exe",
|
||||||
|
"PROGRAM_FILES",
|
||||||
|
"\\Disney\\Disney Online\\PiratesOnline_QA\\Launcher1.exe",
|
||||||
|
}
|
||||||
|
,
|
||||||
|
{ // Test
|
||||||
|
3,
|
||||||
|
"http://download.test.piratesonline.com/english/currentVersion/PotC-setup_TEST.exe",
|
||||||
|
"PROGRAM_FILES",
|
||||||
|
"\\Disney\\Disney Online\\PiratesOnline_TEST\\Launcher1.exe",
|
||||||
|
}
|
||||||
|
,
|
||||||
|
{ // Live
|
||||||
|
4,
|
||||||
|
"http://download.piratesonline.com/english/currentVersion/PotC-setup.exe",
|
||||||
|
"PROGRAM_FILES",
|
||||||
|
"\\Disney\\Disney Online\\PiratesOnline\\Launcher1.exe",
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
static const char c_szFolderNameDelimiter_DOS [] = "\\";
|
||||||
|
static const char c_chFolderNameDelimiter_UNIX = '/';
|
||||||
|
|
||||||
|
#if defined(_DEBUG)
|
||||||
|
#define ODS(s) { printf (s); printf ("\r\n"); }
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static char *g_paszAcceptTypes [] = { "*/*", NULL };
|
||||||
|
|
||||||
|
#if defined(_DEBUG)
|
||||||
|
PSZ CRunPiratesOnline::get_http_specific_error_description (DWORD dwError)
|
||||||
|
{
|
||||||
|
switch (dwError)
|
||||||
|
{
|
||||||
|
case 12001:
|
||||||
|
return "Out of handles";
|
||||||
|
case 12002:
|
||||||
|
return "Timeout";
|
||||||
|
case 12004:
|
||||||
|
return "Internal Error";
|
||||||
|
case 12005:
|
||||||
|
return "Invalid URL";
|
||||||
|
case 12007:
|
||||||
|
return "Service Name Not Resolved";
|
||||||
|
case 12008:
|
||||||
|
return "Protocol Not Found";
|
||||||
|
case 12013:
|
||||||
|
return "Incorrect User Name";
|
||||||
|
case 12014:
|
||||||
|
return "Incorrect Password";
|
||||||
|
case 12015:
|
||||||
|
return "Login Failure";
|
||||||
|
case 12016:
|
||||||
|
return "Invalid Operation";
|
||||||
|
case 12017:
|
||||||
|
return "Operation Canceled";
|
||||||
|
case 12020:
|
||||||
|
return "Not Proxy Request";
|
||||||
|
case 12023:
|
||||||
|
return "No Direct Access";
|
||||||
|
case 12026:
|
||||||
|
return "Request Pending";
|
||||||
|
case 12027:
|
||||||
|
return "Incorrect Format";
|
||||||
|
case 12028:
|
||||||
|
return "Item not found";
|
||||||
|
case 12029:
|
||||||
|
return "Cannot connect";
|
||||||
|
case 12030:
|
||||||
|
return "Connection Aborted";
|
||||||
|
case 12031:
|
||||||
|
return "Connection Reset";
|
||||||
|
case 12033:
|
||||||
|
return "Invalid Proxy Request";
|
||||||
|
case 12034:
|
||||||
|
return "Need UI";
|
||||||
|
case 12035:
|
||||||
|
return "Sec Cert Date Invalid";
|
||||||
|
case 12038:
|
||||||
|
return "Sec Cert CN Invalid";
|
||||||
|
case 12044:
|
||||||
|
return "Client Auth Cert Needed";
|
||||||
|
case 12045:
|
||||||
|
return "Invalid CA Cert";
|
||||||
|
case 12046:
|
||||||
|
return "Client Auth Not Setup";
|
||||||
|
case 12150:
|
||||||
|
return "HTTP Header Not Found";
|
||||||
|
case 12152:
|
||||||
|
return "Invalid HTTP Server Response";
|
||||||
|
case 12153:
|
||||||
|
return "Invalid HTTP Header";
|
||||||
|
case 120154:
|
||||||
|
return "Invalid Query Request";
|
||||||
|
case 120156:
|
||||||
|
return "Redirect Failed";
|
||||||
|
case 120159:
|
||||||
|
return "TCP/IP not installed";
|
||||||
|
default:
|
||||||
|
return "Error";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
ENUM_RESPONSE_CODE CRunPiratesOnline::response_data_available_and_successfully_read (HINTERNET hRequest,
|
||||||
|
char * pszHttpResponseData,
|
||||||
|
DWORD dwNumHttpResponseDataBufferBytes,
|
||||||
|
DWORD * pdwNumBytesResponseDataRead)
|
||||||
|
{
|
||||||
|
// If we can NOT query the server to determine the amount of data available
|
||||||
|
DWORD dwNumberOfBytesAvailableToBeRead = 0;
|
||||||
|
if (!InternetQueryDataAvailable (
|
||||||
|
hRequest,
|
||||||
|
&dwNumberOfBytesAvailableToBeRead,
|
||||||
|
0,
|
||||||
|
0))
|
||||||
|
{
|
||||||
|
#if defined(_DEBUG)
|
||||||
|
{
|
||||||
|
DWORD dwLastError;
|
||||||
|
dwLastError = GetLastError ();
|
||||||
|
char szMsgBuf [1024];
|
||||||
|
wsprintf (
|
||||||
|
szMsgBuf,
|
||||||
|
"%s\t%s: %u=%s",
|
||||||
|
__FUNCTION__,
|
||||||
|
"ERROR: InternetQueryDataAvailable",
|
||||||
|
dwLastError,
|
||||||
|
get_http_specific_error_description (dwLastError));
|
||||||
|
ODS(szMsgBuf)
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return RESPONSE_CODE__CANNOT_QUERY_SERVER;
|
||||||
|
}
|
||||||
|
// If no data is available
|
||||||
|
if (0 == dwNumberOfBytesAvailableToBeRead)
|
||||||
|
{
|
||||||
|
#if defined(_DEBUG)
|
||||||
|
{
|
||||||
|
char szMsgBuf [1024];
|
||||||
|
wsprintf (
|
||||||
|
szMsgBuf,
|
||||||
|
"%s\t%s: Indicates that zero (0) bytes are available to be read",
|
||||||
|
__FUNCTION__,
|
||||||
|
"InternetQueryDataAvailable");
|
||||||
|
ODS(szMsgBuf)
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return RESPONSE_CODE__SUCCESS;
|
||||||
|
}
|
||||||
|
// If the number of bytes available to be read is more than the size of our in-memory buffer
|
||||||
|
if (dwNumberOfBytesAvailableToBeRead > dwNumHttpResponseDataBufferBytes)
|
||||||
|
{
|
||||||
|
// Clamp the number of bytes to be read to the size of our in-memory buffer
|
||||||
|
dwNumberOfBytesAvailableToBeRead = dwNumHttpResponseDataBufferBytes;
|
||||||
|
}
|
||||||
|
// If the number of bytes available to be read will require a read past the end of the content
|
||||||
|
if ((dwNumberOfBytesAvailableToBeRead + m.dwNumBytesResponseDataReadTotal) > m.dwContentLen)
|
||||||
|
{
|
||||||
|
// Clip the number of bytes to be read to ensure exactly m.dwContentLen bytes are read
|
||||||
|
dwNumberOfBytesAvailableToBeRead = m.dwContentLen - m.dwNumBytesResponseDataReadTotal;
|
||||||
|
}
|
||||||
|
// If we can NOT read data from the handle opened by function InternetOpenUrl
|
||||||
|
if (!InternetReadFile (
|
||||||
|
hRequest,
|
||||||
|
pszHttpResponseData,
|
||||||
|
dwNumberOfBytesAvailableToBeRead,
|
||||||
|
pdwNumBytesResponseDataRead))
|
||||||
|
{
|
||||||
|
#if defined(_DEBUG)
|
||||||
|
{
|
||||||
|
DWORD dwLastError;
|
||||||
|
dwLastError = GetLastError ();
|
||||||
|
char szMsgBuf [1024];
|
||||||
|
wsprintf (
|
||||||
|
szMsgBuf,
|
||||||
|
"%s\t%s: %u=%s",
|
||||||
|
__FUNCTION__,
|
||||||
|
"ERROR: InternetReadFile",
|
||||||
|
dwLastError,
|
||||||
|
get_http_specific_error_description (dwLastError));
|
||||||
|
ODS(szMsgBuf)
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return RESPONSE_CODE__INTERNET_READ_FAILURE;
|
||||||
|
}
|
||||||
|
// If the number of byte available to be read is NOT equal to the number of bytes read
|
||||||
|
if (dwNumberOfBytesAvailableToBeRead != *pdwNumBytesResponseDataRead)
|
||||||
|
{
|
||||||
|
#if defined(_DEBUG)
|
||||||
|
{
|
||||||
|
char szMsgBuf [1024];
|
||||||
|
wsprintf (
|
||||||
|
szMsgBuf,
|
||||||
|
"%s\t%s: The number of bytes available to be read = <%u>, but <%u> bytes were successfully read",
|
||||||
|
__FUNCTION__,
|
||||||
|
"ERROR: InternetReadFile",
|
||||||
|
dwNumberOfBytesAvailableToBeRead,
|
||||||
|
*pdwNumBytesResponseDataRead);
|
||||||
|
ODS(szMsgBuf)
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return RESPONSE_CODE__INVALID_NUMBER_OF_BYTES_READ;
|
||||||
|
}
|
||||||
|
#if defined(_DEBUG)
|
||||||
|
{
|
||||||
|
char szMsgBuf [1024];
|
||||||
|
wsprintf (
|
||||||
|
szMsgBuf,
|
||||||
|
"%s\tSuccessfully read <%d> bytes",
|
||||||
|
__FUNCTION__,
|
||||||
|
*pdwNumBytesResponseDataRead);
|
||||||
|
ODS(szMsgBuf)
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
// Indicate success
|
||||||
|
return RESPONSE_CODE__SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
ENUM_RESPONSE_CODE CRunPiratesOnline::download_installer (HANDLE hFile)
|
||||||
|
{
|
||||||
|
#if defined(_DEBUG)
|
||||||
|
{ char szMsgBuf [1024];wsprintf (szMsgBuf,"ENTER: "
|
||||||
|
"%s",__FUNCTION__);ODS(szMsgBuf)}
|
||||||
|
#endif
|
||||||
|
ENUM_RESPONSE_CODE enumResponseCode = RESPONSE_CODE__SUCCESS;
|
||||||
|
//
|
||||||
|
char hostnamebuf [512];
|
||||||
|
memset (hostnamebuf, 0, sizeof (hostnamebuf));
|
||||||
|
//
|
||||||
|
char urlstrbuf [1024];
|
||||||
|
//
|
||||||
|
URL_COMPONENTS url_comp;
|
||||||
|
memset (&url_comp, 0, sizeof (url_comp));
|
||||||
|
url_comp.dwStructSize = sizeof (url_comp);
|
||||||
|
url_comp.lpszHostName = hostnamebuf;
|
||||||
|
url_comp.dwHostNameLength = sizeof (hostnamebuf);
|
||||||
|
url_comp.lpszUrlPath = urlstrbuf;
|
||||||
|
url_comp.dwUrlPathLength = sizeof (urlstrbuf);
|
||||||
|
// If the source URL cannot be cracked into its component parts
|
||||||
|
#if defined(_DEBUG)
|
||||||
|
{ char szMsgBuf [1024];wsprintf (szMsgBuf,"%s"
|
||||||
|
" - about to call InternetCrackUrl",__FUNCTION__);ODS(szMsgBuf)}
|
||||||
|
#endif
|
||||||
|
if (!InternetCrackUrl (gsc_mmogFlavor[m.immogFlavorIdx].pszInstallerURL, 0, 0x0, &url_comp))
|
||||||
|
{
|
||||||
|
#if defined(_DEBUG)
|
||||||
|
{
|
||||||
|
DWORD dwLastError;
|
||||||
|
dwLastError = GetLastError ();
|
||||||
|
char szMsgBuf [1024];
|
||||||
|
wsprintf (
|
||||||
|
szMsgBuf,
|
||||||
|
"%s\t"
|
||||||
|
"%s: %u=%s",
|
||||||
|
__FUNCTION__,
|
||||||
|
"ERROR: InternetCrackUrl",
|
||||||
|
dwLastError,
|
||||||
|
get_http_specific_error_description (dwLastError));
|
||||||
|
ODS(szMsgBuf)
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
enumResponseCode = RESPONSE_CODE__CANNOT_CRACK_SOURCE_URL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if ((url_comp.nScheme != INTERNET_SCHEME_HTTP)
|
||||||
|
&&
|
||||||
|
(url_comp.nScheme != INTERNET_SCHEME_HTTPS)
|
||||||
|
)
|
||||||
|
{
|
||||||
|
#if defined(_DEBUG)
|
||||||
|
{
|
||||||
|
char szMsgBuf [1024];
|
||||||
|
wsprintf (
|
||||||
|
szMsgBuf,
|
||||||
|
"%s"
|
||||||
|
"\t"
|
||||||
|
"ERROR: Only HTTP and HTTPS are supported",
|
||||||
|
__FUNCTION__);
|
||||||
|
ODS(szMsgBuf)
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
enumResponseCode = RESPONSE_CODE__UNSUPPORTED_INTERNET_PROTOCOL_SCHEME;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialize the HttpOpenRequest bit flags
|
||||||
|
//
|
||||||
|
DWORD dwHttpOpenRequestBitFlags =
|
||||||
|
INTERNET_FLAG_RELOAD // 0x80000000 // retrieve the original item
|
||||||
|
|
|
||||||
|
INTERNET_FLAG_NO_CACHE_WRITE // 0x04000000 // don't write this item to the cache
|
||||||
|
|
|
||||||
|
INTERNET_FLAG_KEEP_CONNECTION // 0x00400000 // use keep-alive semantics
|
||||||
|
|
|
||||||
|
INTERNET_FLAG_PRAGMA_NOCACHE // 0x00000100 // asking wininet to add "pragma: no-cache"
|
||||||
|
;
|
||||||
|
|
||||||
|
// Set the server port number
|
||||||
|
//
|
||||||
|
if (INTERNET_SCHEME_HTTPS == url_comp.nScheme)
|
||||||
|
{
|
||||||
|
dwHttpOpenRequestBitFlags |= (
|
||||||
|
INTERNET_FLAG_SECURE // 0x00800000 // use PCT/SSL if applicable (HTTP)
|
||||||
|
|
|
||||||
|
INTERNET_FLAG_IGNORE_CERT_CN_INVALID // 0x00001000 // bad common name in X509 Cert.
|
||||||
|
|
|
||||||
|
INTERNET_FLAG_IGNORE_CERT_DATE_INVALID); // 0x00002000 // expired X509 Cert.
|
||||||
|
}
|
||||||
|
|
||||||
|
HINTERNET hSession;
|
||||||
|
HINTERNET hConnection = NULL;
|
||||||
|
HINTERNET hRequest = NULL;
|
||||||
|
//
|
||||||
|
#define MAX_HEADER_SIZE 8192
|
||||||
|
char * pRequestHdrBuf = new char [MAX_HEADER_SIZE];
|
||||||
|
DWORD dwBufLen = MAX_HEADER_SIZE;
|
||||||
|
//
|
||||||
|
DWORD HTTP_StatusCode = 0;
|
||||||
|
DWORD dwSizeOfStatusCode = sizeof (HTTP_StatusCode);
|
||||||
|
//
|
||||||
|
DWORD dwSizeOf_ContentLen = sizeof (m.dwContentLen);
|
||||||
|
|
||||||
|
// Initialize this apps use of the WinINet functions
|
||||||
|
#if defined(_DEBUG)
|
||||||
|
{ char szMsgBuf [1024];wsprintf (szMsgBuf,"%s"
|
||||||
|
" - about to call InternetOpen",__FUNCTION__);ODS(szMsgBuf)}
|
||||||
|
#endif
|
||||||
|
if (NULL == (hSession = InternetOpen (
|
||||||
|
"DisneyOnlineGames",
|
||||||
|
INTERNET_OPEN_TYPE_PRECONFIG,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
0)))
|
||||||
|
{
|
||||||
|
#if defined(_DEBUG)
|
||||||
|
{DWORD dwLastError;dwLastError = GetLastError ();char szMsgBuf [1024];wsprintf (szMsgBuf,"%s\t"
|
||||||
|
"%s: %u=%s",__FUNCTION__,"ERROR: InternetOpen",dwLastError,get_http_specific_error_description (dwLastError));ODS(szMsgBuf)}
|
||||||
|
#endif
|
||||||
|
enumResponseCode = RESPONSE_CODE__CANNOT_OPEN_SESSION;
|
||||||
|
}
|
||||||
|
// Open an HTTP session for the specified site
|
||||||
|
else
|
||||||
|
#if defined(_DEBUG)
|
||||||
|
{
|
||||||
|
{ char szMsgBuf [1024];wsprintf (szMsgBuf,"%s"
|
||||||
|
" - url_comp.lpszHostName=[%s]",__FUNCTION__,url_comp.lpszHostName);ODS(szMsgBuf)}
|
||||||
|
{ char szMsgBuf [1024];wsprintf (szMsgBuf,"%s"
|
||||||
|
" - url_comp.nPort=[%d]",__FUNCTION__,url_comp.nPort);ODS(szMsgBuf)}
|
||||||
|
{ char szMsgBuf [1024];wsprintf (szMsgBuf,"%s"
|
||||||
|
" - urlstrbuf=[%s]",__FUNCTION__,urlstrbuf);ODS(szMsgBuf)}
|
||||||
|
{ char szMsgBuf [1024];wsprintf (szMsgBuf,"%s"
|
||||||
|
" - about to call InternetConnect",__FUNCTION__);ODS(szMsgBuf)}
|
||||||
|
#endif
|
||||||
|
if (NULL == (hConnection = InternetConnect (
|
||||||
|
hSession,
|
||||||
|
url_comp.lpszHostName,
|
||||||
|
url_comp.nPort,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
INTERNET_SERVICE_HTTP,
|
||||||
|
INTERNET_FLAG_NO_CACHE_WRITE,
|
||||||
|
0)))
|
||||||
|
{
|
||||||
|
#if defined(_DEBUG)
|
||||||
|
{DWORD dwLastError;dwLastError = GetLastError ();char szMsgBuf [1024];wsprintf (szMsgBuf,"%s\t"
|
||||||
|
"%s: %u=%s",__FUNCTION__,"ERROR: InternetConnect",dwLastError,get_http_specific_error_description (dwLastError));ODS(szMsgBuf)}
|
||||||
|
#endif
|
||||||
|
enumResponseCode = RESPONSE_CODE__CANNOT_CONNECT;
|
||||||
|
}
|
||||||
|
// Open an HTTP request handle
|
||||||
|
else
|
||||||
|
#if defined(_DEBUG)
|
||||||
|
{
|
||||||
|
{ char szMsgBuf [1024];wsprintf (szMsgBuf,"%s"
|
||||||
|
" - about to call HttpOpenRequest",__FUNCTION__);ODS(szMsgBuf)}
|
||||||
|
#endif
|
||||||
|
if (NULL == (hRequest = HttpOpenRequest (
|
||||||
|
hConnection,
|
||||||
|
"GET",
|
||||||
|
url_comp.lpszUrlPath,
|
||||||
|
"HTTP/1.1",
|
||||||
|
NULL,
|
||||||
|
(LPCTSTR *)g_paszAcceptTypes,
|
||||||
|
dwHttpOpenRequestBitFlags,
|
||||||
|
0)))
|
||||||
|
{
|
||||||
|
#if defined(_DEBUG)
|
||||||
|
{DWORD dwLastError;dwLastError = GetLastError ();char szMsgBuf [1024];wsprintf (szMsgBuf,"%s\t"
|
||||||
|
"%s: %u=%s",__FUNCTION__,"ERROR: HttpOpenRequest",dwLastError,get_http_specific_error_description (dwLastError));ODS(szMsgBuf)}
|
||||||
|
#endif
|
||||||
|
enumResponseCode = RESPONSE_CODE__CANNOT_OPEN_REQUEST;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#if defined(_DEBUG)
|
||||||
|
{
|
||||||
|
{ char szMsgBuf [1024];wsprintf (szMsgBuf,"%s"
|
||||||
|
" - about to call HttpQueryInfo",__FUNCTION__);ODS(szMsgBuf)}
|
||||||
|
#endif
|
||||||
|
if (!HttpQueryInfo (
|
||||||
|
hRequest,
|
||||||
|
HTTP_QUERY_RAW_HEADERS_CRLF | HTTP_QUERY_FLAG_REQUEST_HEADERS,
|
||||||
|
(LPVOID)pRequestHdrBuf,
|
||||||
|
&dwBufLen,
|
||||||
|
0))
|
||||||
|
{
|
||||||
|
#if defined(_DEBUG)
|
||||||
|
{DWORD dwLastError;dwLastError = GetLastError ();char szMsgBuf [1024];wsprintf (szMsgBuf,"%s\t"
|
||||||
|
"%s: %u=%s",__FUNCTION__,"ERROR: HttpQueryInfo",dwLastError,get_http_specific_error_description (dwLastError));ODS(szMsgBuf)}
|
||||||
|
#endif
|
||||||
|
enumResponseCode = RESPONSE_CODE__CANNOT_OBTAIN_HEADERS_RETURNED_BY_SERVER;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#if defined(_DEBUG)
|
||||||
|
{
|
||||||
|
{ char szMsgBuf [1024];wsprintf (szMsgBuf,"%s"
|
||||||
|
" - about to call HttpSendRequest",__FUNCTION__);ODS(szMsgBuf)}
|
||||||
|
#endif
|
||||||
|
if (!HttpSendRequest (
|
||||||
|
hRequest,
|
||||||
|
NULL, // No extra headers
|
||||||
|
0, // No extra Header length
|
||||||
|
NULL, // Not sending a POST
|
||||||
|
0)) // Not sending a POST
|
||||||
|
{
|
||||||
|
#if defined(_DEBUG)
|
||||||
|
{DWORD dwLastError;dwLastError = GetLastError ();char szMsgBuf [1024];wsprintf (szMsgBuf,"%s\t"
|
||||||
|
"%s: %u=%s",__FUNCTION__,"ERROR: HttpQueryInfo",dwLastError,get_http_specific_error_description (dwLastError));ODS(szMsgBuf)}
|
||||||
|
#endif
|
||||||
|
enumResponseCode = RESPONSE_CODE__HTTP_SERVER_REQUEST_FAILURE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#if defined(_DEBUG)
|
||||||
|
{
|
||||||
|
{ char szMsgBuf [1024];wsprintf (szMsgBuf,"%s"
|
||||||
|
" - about to call HttpQueryInfo",__FUNCTION__);ODS(szMsgBuf)}
|
||||||
|
#endif
|
||||||
|
if (!HttpQueryInfo (
|
||||||
|
hRequest,
|
||||||
|
HTTP_QUERY_STATUS_CODE | HTTP_QUERY_FLAG_NUMBER, // HTTP_QUERY_FLAG_NUMBER tells it to return a dword, not a string
|
||||||
|
(LPVOID)&HTTP_StatusCode,
|
||||||
|
&dwSizeOfStatusCode,
|
||||||
|
NULL))
|
||||||
|
{
|
||||||
|
#if defined(_DEBUG)
|
||||||
|
{DWORD dwLastError;dwLastError = GetLastError ();char szMsgBuf [1024];wsprintf (szMsgBuf,"%s\t"
|
||||||
|
"%s: %u=%s",__FUNCTION__,"ERROR: HttpQueryInfo",dwLastError,get_http_specific_error_description (dwLastError));ODS(szMsgBuf)}
|
||||||
|
#endif
|
||||||
|
enumResponseCode = RESPONSE_CODE__CANNOT_OBTAIN_STATUS_CODE;
|
||||||
|
}
|
||||||
|
else if (HTTP_STATUS_OK != HTTP_StatusCode)
|
||||||
|
{
|
||||||
|
#if defined(_DEBUG)
|
||||||
|
{DWORD dwLastError;dwLastError = GetLastError ();char szMsgBuf [1024];wsprintf (szMsgBuf,"%s\t"
|
||||||
|
"%s: %u=%s",__FUNCTION__,"ERROR: HttpQueryInfo",dwLastError,get_http_specific_error_description (dwLastError));ODS(szMsgBuf)}
|
||||||
|
#endif
|
||||||
|
enumResponseCode = RESPONSE_CODE__HTTP_STATUS_ERROR;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#if defined(_DEBUG)
|
||||||
|
{
|
||||||
|
{ char szMsgBuf [1024];wsprintf (szMsgBuf,"%s"
|
||||||
|
" - about to call HttpQueryInfo",__FUNCTION__);ODS(szMsgBuf)}
|
||||||
|
#endif
|
||||||
|
if (!HttpQueryInfo (
|
||||||
|
hRequest,
|
||||||
|
HTTP_QUERY_CONTENT_LENGTH | HTTP_QUERY_FLAG_NUMBER,
|
||||||
|
(LPVOID)&(m.dwContentLen),
|
||||||
|
&dwSizeOf_ContentLen,
|
||||||
|
NULL))
|
||||||
|
{
|
||||||
|
#if defined(_DEBUG)
|
||||||
|
{DWORD dwLastError;dwLastError = GetLastError ();char szMsgBuf [1024];wsprintf (szMsgBuf,"%s\t"
|
||||||
|
"%s: %u=%s",__FUNCTION__,"ERROR: HttpQueryInfo",dwLastError,get_http_specific_error_description (dwLastError));ODS(szMsgBuf)}
|
||||||
|
#endif
|
||||||
|
enumResponseCode = RESPONSE_CODE__CANNOT_OBTAIN_CONTENT_LENGTH;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// While response data is available is being successfully read
|
||||||
|
//
|
||||||
|
static const int NUM_HTTP_RESPONSE_DATA_BUFFER_BYTES = 8192;
|
||||||
|
char szHttpResponseData [NUM_HTTP_RESPONSE_DATA_BUFFER_BYTES];
|
||||||
|
DWORD dwNumBytesResponseDataRead = 0;
|
||||||
|
ENUM_RESPONSE_CODE enumResponseCode;
|
||||||
|
while (
|
||||||
|
(m.dwNumBytesResponseDataReadTotal < m.dwContentLen)
|
||||||
|
&&
|
||||||
|
(RESPONSE_CODE__SUCCESS == (enumResponseCode = response_data_available_and_successfully_read (
|
||||||
|
hRequest,
|
||||||
|
szHttpResponseData,
|
||||||
|
NUM_HTTP_RESPONSE_DATA_BUFFER_BYTES,
|
||||||
|
&dwNumBytesResponseDataRead)))
|
||||||
|
)
|
||||||
|
{
|
||||||
|
// Update the total number of response data bytes read
|
||||||
|
m.dwNumBytesResponseDataReadTotal += dwNumBytesResponseDataRead;
|
||||||
|
// If the destination file write fails
|
||||||
|
DWORD dwNumberOfBytesWritten;
|
||||||
|
if (!WriteFile (
|
||||||
|
hFile,
|
||||||
|
szHttpResponseData,
|
||||||
|
dwNumBytesResponseDataRead,
|
||||||
|
&dwNumberOfBytesWritten,
|
||||||
|
NULL))
|
||||||
|
{
|
||||||
|
enumResponseCode = RESPONSE_CODE__FILE_WRITE_FAILURE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (dwNumBytesResponseDataRead != dwNumberOfBytesWritten)
|
||||||
|
{
|
||||||
|
enumResponseCode = RESPONSE_CODE__UNEXPECTED_NUMBER_OF_BYTES_WRITTEN_TO_FILE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#if defined(_DEBUG)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Close the handle opened by the call to function HttpOpenRequest
|
||||||
|
//
|
||||||
|
if (hRequest)
|
||||||
|
{
|
||||||
|
InternetCloseHandle (hRequest);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close the handle opened by the call to function InternetConnect
|
||||||
|
//
|
||||||
|
if (hConnection)
|
||||||
|
{
|
||||||
|
InternetCloseHandle (hConnection);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close the Internet handle opened by the call to function InternetOpen
|
||||||
|
//
|
||||||
|
if (hSession)
|
||||||
|
{
|
||||||
|
InternetCloseHandle (hSession);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(_DEBUG)
|
||||||
|
{ char szMsgBuf [1024];wsprintf (szMsgBuf,"LEAVE: "
|
||||||
|
"%s",__FUNCTION__);ODS(szMsgBuf)}
|
||||||
|
#endif
|
||||||
|
return enumResponseCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
ENUM_RESPONSE_CODE CRunPiratesOnline::download_and_run_installer (const char * pszInstallerURL)
|
||||||
|
{
|
||||||
|
// If the request to obtain the path to temporary directory failed
|
||||||
|
char szTempPath [MAX_PATH];
|
||||||
|
if (0 == GetTempPath (MAX_PATH, szTempPath))
|
||||||
|
{
|
||||||
|
return RESPONSE_CODE__UNABLE_TO_OBTAIN_TEMP_PATHNAME;
|
||||||
|
}
|
||||||
|
// If the request to obtain a unique temporary filename failed
|
||||||
|
char szInstallerFullPathname [MAX_PATH];
|
||||||
|
if (0 == GetTempFileName (szTempPath, NULL, 0, szInstallerFullPathname))
|
||||||
|
{
|
||||||
|
return RESPONSE_CODE__UNABLE_TO_OBTAIN_TEMP_FILENAME;
|
||||||
|
}
|
||||||
|
// If the temporary file was not successfully opened for writing
|
||||||
|
HANDLE hFile;
|
||||||
|
if (INVALID_HANDLE_VALUE == (hFile = CreateFile (
|
||||||
|
szInstallerFullPathname,
|
||||||
|
GENERIC_WRITE,
|
||||||
|
0,
|
||||||
|
NULL,
|
||||||
|
CREATE_ALWAYS,
|
||||||
|
FILE_ATTRIBUTE_NORMAL,
|
||||||
|
NULL
|
||||||
|
)))
|
||||||
|
{
|
||||||
|
return RESPONSE_CODE__UNABLE_TO_CREATE_DESTINATION_FILENAME;
|
||||||
|
}
|
||||||
|
//
|
||||||
|
ENUM_RESPONSE_CODE enumResponseCode;
|
||||||
|
enumResponseCode = download_installer (hFile);
|
||||||
|
//
|
||||||
|
if (!CloseHandle (hFile))
|
||||||
|
{
|
||||||
|
enumResponseCode = RESPONSE_CODE__CANNOT_CLOSE_DESTINATION_FILE;
|
||||||
|
}
|
||||||
|
//
|
||||||
|
if (RESPONSE_CODE__SUCCESS != enumResponseCode)
|
||||||
|
{
|
||||||
|
DeleteFile (szInstallerFullPathname);
|
||||||
|
return enumResponseCode;
|
||||||
|
}
|
||||||
|
// Register file szInstallerFullPathname to be deleted when the system restarts
|
||||||
|
// NOTES:
|
||||||
|
// 1) The system moves the file immediately after AUTOCHK is executed, but before creating any
|
||||||
|
// paging files.
|
||||||
|
// 2) Parameter value MOVEFILE_DELAY_UNTIL_REBOOT can be used only if the process is in the
|
||||||
|
// context of a user who belongs to the administrator group or the LocalSystem account.
|
||||||
|
MoveFileEx (szInstallerFullPathname, NULL, MOVEFILE_DELAY_UNTIL_REBOOT);
|
||||||
|
// Set command line
|
||||||
|
CString strCommandLine (szInstallerFullPathname);
|
||||||
|
strCommandLine.Append (" ");
|
||||||
|
strCommandLine.Append (szInstallerCommandLineOptionPrefix);
|
||||||
|
strCommandLine.Append (szInstallerSilentRunModeOption);
|
||||||
|
strCommandLine.Append (" ");
|
||||||
|
strCommandLine.Append (szInstallerCommandLineOptionPrefix);
|
||||||
|
strCommandLine.Append (szEnvKeyToAddToChildProcessEnvBlock);
|
||||||
|
strCommandLine.Append (" ");
|
||||||
|
strCommandLine.Append (m.pszToken);
|
||||||
|
// Attempt to run the installer executable
|
||||||
|
return create_process (strCommandLine);
|
||||||
|
}
|
||||||
|
|
||||||
|
ENUM_RESPONSE_CODE CRunPiratesOnline::create_process (CString & strCommandLine)
|
||||||
|
{
|
||||||
|
// Create security attributes
|
||||||
|
SECURITY_DESCRIPTOR sd;
|
||||||
|
InitializeSecurityDescriptor (&sd, SECURITY_DESCRIPTOR_REVISION);
|
||||||
|
SetSecurityDescriptorDacl (&sd, TRUE, 0, FALSE);
|
||||||
|
SECURITY_ATTRIBUTES sa = { sizeof(SECURITY_ATTRIBUTES), &sd, true };
|
||||||
|
// Create child process environment block
|
||||||
|
CString strEnvForChildProcess;
|
||||||
|
CEnvBlock EnvBlock (m.pszToken);
|
||||||
|
EnvBlock.Create (szEnvKeyToAddToChildProcessEnvBlock, strEnvForChildProcess);
|
||||||
|
// Set startup information
|
||||||
|
STARTUPINFO si;
|
||||||
|
memset (&si, 0, sizeof (si));
|
||||||
|
si.cb = sizeof (si);
|
||||||
|
si.dwFlags = STARTF_USESHOWWINDOW;
|
||||||
|
si.wShowWindow = SW_SHOWNORMAL;
|
||||||
|
// Initialize process information structure
|
||||||
|
PROCESS_INFORMATION pi;
|
||||||
|
ZeroMemory (&pi, sizeof (pi));
|
||||||
|
// Attempt to run the executable
|
||||||
|
if (!CreateProcess (
|
||||||
|
NULL,
|
||||||
|
strCommandLine.GetBuffer (),
|
||||||
|
&sa,
|
||||||
|
&sa,
|
||||||
|
true,
|
||||||
|
0,
|
||||||
|
strEnvForChildProcess.GetBuffer (),
|
||||||
|
NULL,
|
||||||
|
&si,
|
||||||
|
&pi))
|
||||||
|
{
|
||||||
|
return RESPONSE_CODE__CREATE_PROCESS_FAILED;
|
||||||
|
}
|
||||||
|
return RESPONSE_CODE__SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CRunPiratesOnline::map_folder_to_csidl (const char * pszCSIDL,
|
||||||
|
int * pcsidl)
|
||||||
|
{
|
||||||
|
bool fRet = true;
|
||||||
|
//
|
||||||
|
*pcsidl = 0;
|
||||||
|
if (0 == _strcmpi (pszCSIDL /* .GetBuffer () */ , "ADMINTOOLS"))
|
||||||
|
{
|
||||||
|
// The file system directory that is used to store administrative tools for an individual user.
|
||||||
|
// The Microsoft Management Console (MMC) will save customized consoles to this directory, and
|
||||||
|
// it will roam with the user.
|
||||||
|
*pcsidl |= CSIDL_ADMINTOOLS;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if (0 == _strcmpi (pszCSIDL, "COMMON_ADMINTOOLS"))
|
||||||
|
{
|
||||||
|
// The file system directory containing administrative tools for all users of the computer.
|
||||||
|
*pcsidl |= CSIDL_COMMON_ADMINTOOLS;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if (0 == _strcmpi (pszCSIDL, "APPDATA"))
|
||||||
|
{
|
||||||
|
// The file system directory that serves as a common repository for application-specific data.
|
||||||
|
// A typical path is C:\Documents and Settings\username\Application Data.
|
||||||
|
// This CSIDL is supported by the redistributable Shfolder.dll for systems that do not have
|
||||||
|
// the Microsoft Internet Explorer 4.0 integrated Shell installed.
|
||||||
|
*pcsidl |= CSIDL_APPDATA;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if (0 == _strcmpi (pszCSIDL, "COMMON_APPDATA"))
|
||||||
|
{
|
||||||
|
// The file system directory containing application data for all users.
|
||||||
|
// A typical path is C:\Documents and Settings\All Users\Application Data.
|
||||||
|
*pcsidl |= CSIDL_COMMON_APPDATA;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if (0 == _strcmpi (pszCSIDL, "COMMON_DOCUMENTS"))
|
||||||
|
{
|
||||||
|
// The file system directory that contains documents that are common to all users.
|
||||||
|
// A typical paths is C:\Documents and Settings\All Users\Documents.
|
||||||
|
// Valid for Windows NT systems and Microsoft Windows 95 and Windows 98 systems with
|
||||||
|
// Shfolder.dll installed.
|
||||||
|
*pcsidl |= CSIDL_COMMON_DOCUMENTS;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if (0 == _strcmpi (pszCSIDL, "COOKIES"))
|
||||||
|
{
|
||||||
|
// The file system directory that serves as a common repository for Internet cookies.
|
||||||
|
// A typical path is C:\Documents and Settings\username\Cookies.
|
||||||
|
*pcsidl |= CSIDL_COOKIES;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if (0 == _strcmpi (pszCSIDL, "HISTORY"))
|
||||||
|
{
|
||||||
|
// The file system directory that serves as a common repository for Internet history items.
|
||||||
|
*pcsidl |= CSIDL_HISTORY;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if (0 == _strcmpi (pszCSIDL, "INTERNET_CACHE"))
|
||||||
|
{
|
||||||
|
// The file system directory that serves as a common repository for temporary Internet files.
|
||||||
|
// A typical path is C:\Documents and Settings\username\Local Settings\Temporary Internet Files.
|
||||||
|
*pcsidl |= CSIDL_INTERNET_CACHE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if (0 == _strcmpi (pszCSIDL, "LOCAL_APPDATA"))
|
||||||
|
{
|
||||||
|
// The file system directory that serves as a data repository for local (nonroaming) applications.
|
||||||
|
// A typical path is C:\Documents and Settings\username\Local Settings\Application Data.
|
||||||
|
*pcsidl |= CSIDL_LOCAL_APPDATA;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if (0 == _strcmpi (pszCSIDL, "MYPICTURES"))
|
||||||
|
{
|
||||||
|
// The file system directory that serves as a common repository for image files.
|
||||||
|
// A typical path is C:\Documents and Settings\username\My Documents\My Pictures.
|
||||||
|
*pcsidl |= CSIDL_MYPICTURES;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if (0 == _strcmpi (pszCSIDL, "PERSONAL"))
|
||||||
|
{
|
||||||
|
// The virtual folder representing the My Documents desktop item.
|
||||||
|
// This is equivalent to CSIDL_MYDOCUMENTS.
|
||||||
|
*pcsidl |= CSIDL_PERSONAL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if (0 == _strcmpi (pszCSIDL, "PROGRAM_FILES"))
|
||||||
|
{
|
||||||
|
// The Program Files folder.
|
||||||
|
// A typical path is C:\Program Files.
|
||||||
|
*pcsidl |= CSIDL_PROGRAM_FILES;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if (0 == _strcmpi (pszCSIDL, "PROGRAM_FILES_COMMON"))
|
||||||
|
{
|
||||||
|
// A folder for components that are shared across applications.
|
||||||
|
// A typical path is C:\Program Files\Common.
|
||||||
|
// Valid only for Windows NT, Windows 2000, and Windows XP systems.
|
||||||
|
// Not valid for Windows Millennium Edition (Windows Me).
|
||||||
|
*pcsidl |= CSIDL_PROGRAM_FILES_COMMON;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if (0 == _strcmpi (pszCSIDL, "SYSTEM"))
|
||||||
|
{
|
||||||
|
// The Windows System folder.
|
||||||
|
// A typical path is C:\Windows\System32.
|
||||||
|
*pcsidl |= CSIDL_SYSTEM;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if (0 == _strcmpi (pszCSIDL, "WINDOWS"))
|
||||||
|
{
|
||||||
|
// The Windows directory or SYSROOT.
|
||||||
|
// This corresponds to the %windir% or %SYSTEMROOT% environment variables.
|
||||||
|
// A typical path is C:\Windows.
|
||||||
|
*pcsidl |= CSIDL_WINDOWS;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fRet = false;
|
||||||
|
}
|
||||||
|
return fRet;
|
||||||
|
}
|
||||||
|
|
||||||
|
ENUM_RESPONSE_CODE CRunPiratesOnline::run_launcher (const char * pszLauncherCSIDL,
|
||||||
|
const char * pszLauncherPathname)
|
||||||
|
{
|
||||||
|
// Given a CSIDL as a string, if the corresponding pathname cannot be obtained
|
||||||
|
int csidl = 0;
|
||||||
|
if (!map_folder_to_csidl (pszLauncherCSIDL, &csidl))
|
||||||
|
{
|
||||||
|
return RESPONSE_CODE__UNRECOGNIZED_DESTINATION_FOLDER;
|
||||||
|
}
|
||||||
|
// Given a CSIDL of a folder, if a path was NOT returned
|
||||||
|
char szPathFromCSIDL [MAX_PATH];
|
||||||
|
if (!(SUCCEEDED(SHGetFolderPath (
|
||||||
|
NULL, // handle to an owner window
|
||||||
|
csidl, // CSIDL value that identifies the folder whose path is to be retrieved
|
||||||
|
NULL, // access token that can be used to represent a particular user
|
||||||
|
SHGFP_TYPE_CURRENT, // flags to specify which path is to be returned
|
||||||
|
szPathFromCSIDL // pointer to a null-terminated string of length MAX_PATH which will receive the path
|
||||||
|
))))
|
||||||
|
{
|
||||||
|
return RESPONSE_CODE__CANNOT_OBTAIN_SPECIAL_ROOT_FOLDER_PATHNAME;
|
||||||
|
}
|
||||||
|
// Obtain string lengths
|
||||||
|
size_t stPath_Len = strlen (szPathFromCSIDL);
|
||||||
|
size_t stLancherPathname_Len = strlen (pszLauncherPathname);
|
||||||
|
// If launcher executable full pathname will be too long
|
||||||
|
if (MAX_PATH <= (stPath_Len + stLancherPathname_Len))
|
||||||
|
{
|
||||||
|
return RESPONSE_CODE__LAUNCHER_FULL_PATHNAME_TOO_LONG;
|
||||||
|
}
|
||||||
|
// Set launcher executable full pathname
|
||||||
|
char szLauncherFullPathname [MAX_PATH];
|
||||||
|
strcpy (szLauncherFullPathname, szPathFromCSIDL);
|
||||||
|
strcat (szLauncherFullPathname, pszLauncherPathname);
|
||||||
|
// Set command line
|
||||||
|
CString strCommandLine (szLauncherFullPathname);
|
||||||
|
strCommandLine.Append (" ");
|
||||||
|
strCommandLine.Append (szEnvKeyToAddToChildProcessEnvBlock);
|
||||||
|
strCommandLine.Append ("=");
|
||||||
|
strCommandLine.Append (m.pszToken);
|
||||||
|
// Return indication of whether or not the launcher process was successfully created
|
||||||
|
return create_process (strCommandLine);
|
||||||
|
}
|
||||||
|
|
||||||
|
ENUM_RESPONSE_CODE CRunPiratesOnline::validate_inputs (const int ModeId)
|
||||||
|
{
|
||||||
|
ENUM_RESPONSE_CODE enumResponseCode = RESPONSE_CODE__INVALID_MODE;
|
||||||
|
for (m.immogFlavorIdx = 0; m.immogFlavorIdx < (sizeof (gsc_mmogFlavor) / sizeof (MMOG_FLAVOR)); m.immogFlavorIdx++)
|
||||||
|
{
|
||||||
|
if (gsc_mmogFlavor[m.immogFlavorIdx].mode == ModeId)
|
||||||
|
{
|
||||||
|
enumResponseCode = RESPONSE_CODE__SUCCESS;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return enumResponseCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
ULONG CRunPiratesOnline::Run (const int ModeId,
|
||||||
|
const char * pszToken)
|
||||||
|
{
|
||||||
|
m.pszToken = pszToken;
|
||||||
|
ENUM_RESPONSE_CODE ResponseCode;
|
||||||
|
if (RESPONSE_CODE__SUCCESS == (ResponseCode = validate_inputs (ModeId)))
|
||||||
|
{
|
||||||
|
if (RESPONSE_CODE__SUCCESS != (ResponseCode = run_launcher (
|
||||||
|
gsc_mmogFlavor[m.immogFlavorIdx].pszLauncherCSIDL,
|
||||||
|
gsc_mmogFlavor[m.immogFlavorIdx].pszLauncherPathname)))
|
||||||
|
{
|
||||||
|
ResponseCode = download_and_run_installer (
|
||||||
|
gsc_mmogFlavor[m.immogFlavorIdx].pszInstallerURL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ResponseCode;
|
||||||
|
}
|
130
otp/src/activex/DisneyOnlineGames/src/RunPiratesOnline.h
Normal file
130
otp/src/activex/DisneyOnlineGames/src/RunPiratesOnline.h
Normal file
|
@ -0,0 +1,130 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
enum ENUM_RESPONSE_CODE
|
||||||
|
{
|
||||||
|
RESPONSE_CODE__SUCCESS = 0,
|
||||||
|
// Success
|
||||||
|
RESPONSE_CODE__INVALID_MODE = 1,
|
||||||
|
// Mode input is invalid
|
||||||
|
RESPONSE_CODE__UNRECOGNIZED_DESTINATION_FOLDER = 2,
|
||||||
|
// Unrecognized Destination Folder argument
|
||||||
|
// Please reference [Valid Destination Folder Parameter Values] below
|
||||||
|
RESPONSE_CODE__CANNOT_OBTAIN_SPECIAL_ROOT_FOLDER_PATHNAME = 3,
|
||||||
|
// Cannot obtain special root folder pathname
|
||||||
|
RESPONSE_CODE__LAUNCHER_FULL_PATHNAME_TOO_LONG = 4,
|
||||||
|
// Full pathname to launcher executable is too long
|
||||||
|
RESPONSE_CODE__BAD_PATHNAME = 5,
|
||||||
|
// Possible issue: Relative paths are not allowed
|
||||||
|
RESPONSE_CODE__FILENAME_EXCED_RANGE = 6,
|
||||||
|
// Destination Folder + Destination Sub-folder + Destination Filename > 256 characters
|
||||||
|
RESPONSE_CODE__PATH_NOT_FOUND = 7,
|
||||||
|
// The system cannot find the path
|
||||||
|
// Possible issue: The path contains an invalid entry
|
||||||
|
RESPONSE_CODE__CANCELLED = 8,
|
||||||
|
// The user canceled the operation
|
||||||
|
RESPONSE_CODE__SHCDEX_UNRECOGNIZED_RET_CODE = 9,
|
||||||
|
// Call to create Destination Folder failed with an unrecognized reason code
|
||||||
|
RESPONSE_CODE__DESTINATION_FILENAME_TOO_LONG = 10,
|
||||||
|
// Destination filename too long
|
||||||
|
RESPONSE_CODE__DESTINATION_FILENAME_IS_A_DIRECTORY = 11,
|
||||||
|
// A directory exists with the same full pathname as the requested destination
|
||||||
|
RESPONSE_CODE__UNABLE_TO_CREATE_DESTINATION_FILENAME = 12,
|
||||||
|
// Unable to create destination file on user's HDD
|
||||||
|
RESPONSE_CODE__CANNOT_CRACK_SOURCE_URL = 13,
|
||||||
|
// Cannot crack source URL
|
||||||
|
RESPONSE_CODE__UNSUPPORTED_INTERNET_PROTOCOL_SCHEME = 14,
|
||||||
|
// Internet protocol scheme not supported
|
||||||
|
// Supported Internet protocol schemes: HTTP, HTTPS
|
||||||
|
RESPONSE_CODE__CANNOT_OBTAIN_CONTENT_LENGTH = 15,
|
||||||
|
// Cannot obtain content length from server
|
||||||
|
RESPONSE_CODE__CANNOT_OPEN_SESSION = 16,
|
||||||
|
// Call to open protocol session failed
|
||||||
|
RESPONSE_CODE__CANNOT_CONNECT = 17,
|
||||||
|
// Attempt to connect to server failed
|
||||||
|
RESPONSE_CODE__CANNOT_OPEN_REQUEST = 18,
|
||||||
|
// Protocol request handle creation failure
|
||||||
|
RESPONSE_CODE__CANNOT_OBTAIN_HEADERS_RETURNED_BY_SERVER = 19,
|
||||||
|
// Unable to retrieve header information associated with server request
|
||||||
|
RESPONSE_CODE__HTTP_SERVER_REQUEST_FAILURE = 20,
|
||||||
|
// Server request failure
|
||||||
|
RESPONSE_CODE__CANNOT_OBTAIN_STATUS_CODE = 21,
|
||||||
|
// Server request could not complete
|
||||||
|
RESPONSE_CODE__HTTP_STATUS_ERROR = 22,
|
||||||
|
// Status code returned from server indicates error
|
||||||
|
RESPONSE_CODE__CANNOT_QUERY_SERVER = 23,
|
||||||
|
// Cannot query server
|
||||||
|
// Failure occurred when querying server to determine data size
|
||||||
|
RESPONSE_CODE__INTERNET_READ_FAILURE = 24,
|
||||||
|
// Call to read data from server failed
|
||||||
|
RESPONSE_CODE__INVALID_NUMBER_OF_BYTES_READ = 25,
|
||||||
|
// The number of bytes requested to be read is not equal to the number of bytes read from
|
||||||
|
// the server
|
||||||
|
RESPONSE_CODE__FILE_WRITE_FAILURE = 26,
|
||||||
|
// HDD write failure
|
||||||
|
// User’s hard drive may be out of space
|
||||||
|
RESPONSE_CODE__UNEXPECTED_NUMBER_OF_BYTES_WRITTEN_TO_FILE = 27,
|
||||||
|
// Number of bytes written to HDD does not match the number of bytes requested to be written
|
||||||
|
RESPONSE_CODE__CANNOT_CLOSE_DESTINATION_FILE = 28,
|
||||||
|
// Call to close the Destination Filename failed
|
||||||
|
RESPONSE_CODE__CREATE_PROCESS_FAILED = 29,
|
||||||
|
// Unable to run downloaded executable
|
||||||
|
//
|
||||||
|
//
|
||||||
|
RESPONSE_CODE__UNABLE_TO_OBTAIN_TEMP_PATHNAME = 51,
|
||||||
|
RESPONSE_CODE__UNABLE_TO_OBTAIN_TEMP_FILENAME = 52,
|
||||||
|
//
|
||||||
|
//
|
||||||
|
RESPONSE_CODE__FAILURE = 99,
|
||||||
|
// Non-specific failure
|
||||||
|
};
|
||||||
|
|
||||||
|
class CRunPiratesOnline
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CRunPiratesOnline (void)
|
||||||
|
{
|
||||||
|
memset (&m, 0, sizeof (m));
|
||||||
|
}
|
||||||
|
~CRunPiratesOnline (void)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
ULONG Run (const int ModeId,
|
||||||
|
const char * pszToken);
|
||||||
|
private:
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
const char * pszToken;
|
||||||
|
int immogFlavorIdx;
|
||||||
|
DWORD dwContentLen;
|
||||||
|
DWORD dwNumBytesResponseDataReadTotal;
|
||||||
|
} m;
|
||||||
|
private:
|
||||||
|
#if defined(_DEBUG)
|
||||||
|
PSZ get_http_specific_error_description (DWORD dwError);
|
||||||
|
#endif
|
||||||
|
//
|
||||||
|
ENUM_RESPONSE_CODE response_data_available_and_successfully_read (HINTERNET hRequest,
|
||||||
|
char * pszHttpResponseData,
|
||||||
|
DWORD dwNumHttpResponseDataBufferBytes,
|
||||||
|
DWORD * pdwNumBytesResponseDataRead);
|
||||||
|
//
|
||||||
|
ENUM_RESPONSE_CODE download_installer (HANDLE hFile);
|
||||||
|
//
|
||||||
|
ENUM_RESPONSE_CODE download_and_run_installer (const char * pszInstallerURL);
|
||||||
|
//
|
||||||
|
void insert_env_block_key_value_pair (CString & strEnvForChildProcess,
|
||||||
|
int * pInsertIdx,
|
||||||
|
char * lpszVariable);
|
||||||
|
//
|
||||||
|
void create_child_process_environment_block (CString & strEnvForChildProcess);
|
||||||
|
//
|
||||||
|
ENUM_RESPONSE_CODE create_process (CString & strCommandLine);
|
||||||
|
//
|
||||||
|
ENUM_RESPONSE_CODE validate_inputs (const int ModeId);
|
||||||
|
//
|
||||||
|
ENUM_RESPONSE_CODE run_launcher (const char * pszLauncherCSIDL,
|
||||||
|
const char * pszLauncherPathname);
|
||||||
|
//
|
||||||
|
bool map_folder_to_csidl (const char * pszCSIDL,
|
||||||
|
int * pcsidl);
|
||||||
|
};
|
|
@ -0,0 +1,69 @@
|
||||||
|
#include "StdAfx.h"
|
||||||
|
|
||||||
|
#define INITIAL_NUM_WINDOW_HANDLES 10
|
||||||
|
#define NUM_WINDOW_HANDLE_ARRAY_INCREMENT 5
|
||||||
|
|
||||||
|
CTopLevelWindowIterator::CTopLevelWindowIterator (DWORD dwProcessId)
|
||||||
|
{
|
||||||
|
ZeroMemory (&m, sizeof (m));
|
||||||
|
m.dwProcessId = dwProcessId;
|
||||||
|
m.dwNumAlloced = INITIAL_NUM_WINDOW_HANDLES;
|
||||||
|
m.paHWND = new HWND [m.dwNumAlloced];
|
||||||
|
}
|
||||||
|
|
||||||
|
CTopLevelWindowIterator::~CTopLevelWindowIterator()
|
||||||
|
{
|
||||||
|
delete [] m.paHWND;
|
||||||
|
}
|
||||||
|
|
||||||
|
HWND CTopLevelWindowIterator::First()
|
||||||
|
{
|
||||||
|
// Enumerate all top-level windows
|
||||||
|
::EnumWindows(EnumProc, (LPARAM)this);
|
||||||
|
|
||||||
|
// Reset the HWND array current index
|
||||||
|
m.dwCurrIdx = 0;
|
||||||
|
|
||||||
|
// Return the first top level window created by the specified process
|
||||||
|
return Next();
|
||||||
|
}
|
||||||
|
|
||||||
|
HWND CTopLevelWindowIterator::Next()
|
||||||
|
{
|
||||||
|
if (m.paHWND && (m.dwCurrIdx < m.dwNumUsed))
|
||||||
|
{
|
||||||
|
return m.paHWND[m.dwCurrIdx++];
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL CALLBACK CTopLevelWindowIterator::EnumProc (HWND hwnd, LPARAM lp)
|
||||||
|
{
|
||||||
|
return ((CTopLevelWindowIterator*)lp)->OnEnumProc(hwnd);
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL CTopLevelWindowIterator::OnEnumProc (HWND hwnd)
|
||||||
|
{
|
||||||
|
// If the given top level window is visible
|
||||||
|
if (WS_VISIBLE & GetWindowLong (hwnd, GWL_STYLE))
|
||||||
|
{
|
||||||
|
// Retrieve the identifier of the process that created the given top level window
|
||||||
|
DWORD dwWindowThreadProcessId;
|
||||||
|
GetWindowThreadProcessId (hwnd, &dwWindowThreadProcessId);
|
||||||
|
|
||||||
|
// If the given top level window was created by the specified process
|
||||||
|
if (dwWindowThreadProcessId == m.dwProcessId)
|
||||||
|
{
|
||||||
|
if (m.dwNumUsed >= m.dwNumAlloced)
|
||||||
|
{
|
||||||
|
HWND * paHWND = new HWND [m.dwNumAlloced + NUM_WINDOW_HANDLE_ARRAY_INCREMENT];
|
||||||
|
memcpy (paHWND, m.paHWND, sizeof (HWND) * m.dwNumAlloced);
|
||||||
|
delete [] m.paHWND;
|
||||||
|
m.paHWND = paHWND;
|
||||||
|
m.dwNumAlloced += NUM_WINDOW_HANDLE_ARRAY_INCREMENT;
|
||||||
|
}
|
||||||
|
m.paHWND[m.dwNumUsed++] = hwnd;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return TRUE; // keep looking
|
||||||
|
}
|
|
@ -0,0 +1,23 @@
|
||||||
|
class CTopLevelWindowIterator
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CTopLevelWindowIterator(DWORD dwProcessId);
|
||||||
|
~CTopLevelWindowIterator();
|
||||||
|
|
||||||
|
HWND First();
|
||||||
|
HWND Next();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
static BOOL CALLBACK EnumProc(HWND hwnd, LPARAM lp);
|
||||||
|
|
||||||
|
BOOL OnEnumProc(HWND hwnd);
|
||||||
|
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
DWORD dwProcessId; // process id
|
||||||
|
DWORD dwNumAlloced; // number of HWND array elements allocated
|
||||||
|
DWORD dwNumUsed; // number of HWND array elements used
|
||||||
|
DWORD dwCurrIdx; // HWND array current index
|
||||||
|
HWND * paHWND; // pointer to the array of top level window handles
|
||||||
|
} m;
|
||||||
|
};
|
20
otp/src/activex/DisneyOnlineGames/src/resource.h
Normal file
20
otp/src/activex/DisneyOnlineGames/src/resource.h
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
//{{NO_DEPENDENCIES}}
|
||||||
|
// Microsoft Visual C++ generated include file.
|
||||||
|
// Used by DisneyOnlineGames.rc
|
||||||
|
//
|
||||||
|
|
||||||
|
#define IDS_DISNEYONLINEGAMES 1
|
||||||
|
#define IDS_DISNEYONLINEGAMES_PPG 2
|
||||||
|
|
||||||
|
#define IDS_DISNEYONLINEGAMES_PPG_CAPTION 200
|
||||||
|
|
||||||
|
#define IDD_PROPPAGE_DISNEYONLINEGAMES 200
|
||||||
|
|
||||||
|
|
||||||
|
#define IDB_DISNEYONLINEGAMES 1
|
||||||
|
|
||||||
|
|
||||||
|
#define _APS_NEXT_RESOURCE_VALUE 201
|
||||||
|
#define _APS_NEXT_CONTROL_VALUE 201
|
||||||
|
#define _APS_NEXT_SYMED_VALUE 101
|
||||||
|
#define _APS_NEXT_COMMAND_VALUE 32768
|
1
otp/src/activex/DisneyOnlineGames/src/stdafx.cpp
Normal file
1
otp/src/activex/DisneyOnlineGames/src/stdafx.cpp
Normal file
|
@ -0,0 +1 @@
|
||||||
|
#include "stdafx.h"
|
55
otp/src/activex/DisneyOnlineGames/src/stdafx.h
Normal file
55
otp/src/activex/DisneyOnlineGames/src/stdafx.h
Normal file
|
@ -0,0 +1,55 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#define _CRT_SECURE_NO_WARNINGS
|
||||||
|
|
||||||
|
#ifndef VC_EXTRALEAN
|
||||||
|
#define VC_EXTRALEAN // Exclude rarely-used stuff from Windows headers
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef WINVER
|
||||||
|
#define WINVER 0x0501
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef _WIN32_WINNT
|
||||||
|
#define _WIN32_WINNT 0x0501
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef _WIN32_IE
|
||||||
|
#define _WIN32_IE 0x0600
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define _ATL_CSTRING_EXPLICIT_CONSTRUCTORS // some CString constructors will be explicit
|
||||||
|
|
||||||
|
#include <afxctl.h> // MFC support for ActiveX Controls
|
||||||
|
#include <afxext.h> // MFC extensions
|
||||||
|
#ifndef _AFX_NO_OLE_SUPPORT
|
||||||
|
#include <afxdtctl.h> // MFC support for Internet Explorer 4 Comon Controls
|
||||||
|
#endif
|
||||||
|
#ifndef _AFX_NO_AFXCMN_SUPPORT
|
||||||
|
#include <afxcmn.h> // MFC support for Windows Common Controls
|
||||||
|
#endif // _AFX_NO_AFXCMN_SUPPORT
|
||||||
|
|
||||||
|
// Delete the two includes below if you do not wish to use the MFC
|
||||||
|
// database classes
|
||||||
|
#ifndef _WIN64
|
||||||
|
|
||||||
|
#ifndef _AFX_NO_DB_SUPPORT
|
||||||
|
#include <afxdb.h> // MFC ODBC database classes
|
||||||
|
#endif // _AFX_NO_DB_SUPPORT
|
||||||
|
|
||||||
|
#ifndef _AFX_NO_DAO_SUPPORT
|
||||||
|
#include <afxdao.h> // MFC DAO database classes
|
||||||
|
#endif // _AFX_NO_DAO_SUPPORT
|
||||||
|
|
||||||
|
#endif // _WIN64
|
||||||
|
|
||||||
|
#include <shlobj.h>
|
||||||
|
|
||||||
|
#include <afxwin.h>
|
||||||
|
|
||||||
|
#include <wininet.h>
|
||||||
|
#include <process.h>
|
||||||
|
|
||||||
|
#include "EnvBlock.h"
|
||||||
|
#include "RunPiratesOnline.h"
|
||||||
|
#include "TopLevelWindowIterator.h"
|
|
@ -0,0 +1,19 @@
|
||||||
|
Microsoft Visual Studio Solution File, Format Version 9.00
|
||||||
|
# Visual Studio 2005
|
||||||
|
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "testCoreFunctionality", "testCoreFunctionality.Visual Studio 2005.vcproj", "{72EC3673-7D59-4A82-8BFA-ABF504A3DA87}"
|
||||||
|
EndProject
|
||||||
|
Global
|
||||||
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
|
Debug|Win32 = Debug|Win32
|
||||||
|
Release|Win32 = Release|Win32
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||||
|
{72EC3673-7D59-4A82-8BFA-ABF504A3DA87}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||||
|
{72EC3673-7D59-4A82-8BFA-ABF504A3DA87}.Debug|Win32.Build.0 = Debug|Win32
|
||||||
|
{72EC3673-7D59-4A82-8BFA-ABF504A3DA87}.Release|Win32.ActiveCfg = Release|Win32
|
||||||
|
{72EC3673-7D59-4A82-8BFA-ABF504A3DA87}.Release|Win32.Build.0 = Release|Win32
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
|
HideSolutionNode = FALSE
|
||||||
|
EndGlobalSection
|
||||||
|
EndGlobal
|
|
@ -0,0 +1,246 @@
|
||||||
|
<?xml version="1.0" encoding="Windows-1252"?>
|
||||||
|
<VisualStudioProject
|
||||||
|
ProjectType="Visual C++"
|
||||||
|
Version="8.00"
|
||||||
|
Name="testCoreFunctionality"
|
||||||
|
ProjectGUID="{72EC3673-7D59-4A82-8BFA-ABF504A3DA87}"
|
||||||
|
RootNamespace="testCoreFunctionality"
|
||||||
|
Keyword="Win32Proj"
|
||||||
|
>
|
||||||
|
<Platforms>
|
||||||
|
<Platform
|
||||||
|
Name="Win32"
|
||||||
|
/>
|
||||||
|
</Platforms>
|
||||||
|
<ToolFiles>
|
||||||
|
</ToolFiles>
|
||||||
|
<Configurations>
|
||||||
|
<Configuration
|
||||||
|
Name="Debug|Win32"
|
||||||
|
OutputDirectory="Debug"
|
||||||
|
IntermediateDirectory="Debug"
|
||||||
|
ConfigurationType="1"
|
||||||
|
InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
|
||||||
|
UseOfMFC="1"
|
||||||
|
CharacterSet="2"
|
||||||
|
>
|
||||||
|
<Tool
|
||||||
|
Name="VCPreBuildEventTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCCustomBuildTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCXMLDataGeneratorTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCWebServiceProxyGeneratorTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCMIDLTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCCLCompilerTool"
|
||||||
|
Optimization="0"
|
||||||
|
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
|
||||||
|
MinimalRebuild="true"
|
||||||
|
BasicRuntimeChecks="3"
|
||||||
|
RuntimeLibrary="1"
|
||||||
|
TreatWChar_tAsBuiltInType="true"
|
||||||
|
UsePrecompiledHeader="2"
|
||||||
|
WarningLevel="3"
|
||||||
|
Detect64BitPortabilityProblems="true"
|
||||||
|
DebugInformationFormat="3"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCManagedResourceCompilerTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCResourceCompilerTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCPreLinkEventTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCLinkerTool"
|
||||||
|
AdditionalDependencies="wininet.lib"
|
||||||
|
OutputFile="$(OutDir)/testCoreFunctionality.exe"
|
||||||
|
LinkIncremental="1"
|
||||||
|
GenerateDebugInformation="true"
|
||||||
|
AssemblyDebug="1"
|
||||||
|
ProgramDatabaseFile="$(OutDir)/testCoreFunctionality.pdb"
|
||||||
|
SubSystem="1"
|
||||||
|
TargetMachine="1"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCALinkTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCManifestTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCXDCMakeTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCBscMakeTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCFxCopTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCAppVerifierTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCWebDeploymentTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCPostBuildEventTool"
|
||||||
|
/>
|
||||||
|
</Configuration>
|
||||||
|
<Configuration
|
||||||
|
Name="Release|Win32"
|
||||||
|
OutputDirectory="Release"
|
||||||
|
IntermediateDirectory="Release"
|
||||||
|
ConfigurationType="1"
|
||||||
|
InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
|
||||||
|
CharacterSet="2"
|
||||||
|
>
|
||||||
|
<Tool
|
||||||
|
Name="VCPreBuildEventTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCCustomBuildTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCXMLDataGeneratorTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCWebServiceProxyGeneratorTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCMIDLTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCCLCompilerTool"
|
||||||
|
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
|
||||||
|
RuntimeLibrary="0"
|
||||||
|
UsePrecompiledHeader="2"
|
||||||
|
WarningLevel="3"
|
||||||
|
Detect64BitPortabilityProblems="true"
|
||||||
|
DebugInformationFormat="3"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCManagedResourceCompilerTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCResourceCompilerTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCPreLinkEventTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCLinkerTool"
|
||||||
|
AdditionalDependencies="wininet.lib"
|
||||||
|
OutputFile="$(OutDir)/testCoreFunctionality.exe"
|
||||||
|
LinkIncremental="1"
|
||||||
|
GenerateDebugInformation="true"
|
||||||
|
SubSystem="1"
|
||||||
|
OptimizeReferences="2"
|
||||||
|
EnableCOMDATFolding="2"
|
||||||
|
TargetMachine="1"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCALinkTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCManifestTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCXDCMakeTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCBscMakeTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCFxCopTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCAppVerifierTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCWebDeploymentTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCPostBuildEventTool"
|
||||||
|
/>
|
||||||
|
</Configuration>
|
||||||
|
</Configurations>
|
||||||
|
<References>
|
||||||
|
</References>
|
||||||
|
<Files>
|
||||||
|
<Filter
|
||||||
|
Name="Source Files"
|
||||||
|
Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"
|
||||||
|
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
|
||||||
|
>
|
||||||
|
<File
|
||||||
|
RelativePath="..\src\EnvBlock.cpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\src\RunPiratesOnline.cpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\src\stdafx.cpp"
|
||||||
|
>
|
||||||
|
<FileConfiguration
|
||||||
|
Name="Debug|Win32"
|
||||||
|
>
|
||||||
|
<Tool
|
||||||
|
Name="VCCLCompilerTool"
|
||||||
|
UsePrecompiledHeader="1"
|
||||||
|
/>
|
||||||
|
</FileConfiguration>
|
||||||
|
<FileConfiguration
|
||||||
|
Name="Release|Win32"
|
||||||
|
>
|
||||||
|
<Tool
|
||||||
|
Name="VCCLCompilerTool"
|
||||||
|
UsePrecompiledHeader="1"
|
||||||
|
/>
|
||||||
|
</FileConfiguration>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\testCoreFunctionality.cpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
</Filter>
|
||||||
|
<Filter
|
||||||
|
Name="Header Files"
|
||||||
|
Filter="h;hpp;hxx;hm;inl;inc;xsd"
|
||||||
|
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
|
||||||
|
>
|
||||||
|
<File
|
||||||
|
RelativePath="..\src\EnvBlock.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\src\RunPiratesOnline.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\src\stdafx.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
</Filter>
|
||||||
|
<Filter
|
||||||
|
Name="Resource Files"
|
||||||
|
Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx"
|
||||||
|
UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
|
||||||
|
>
|
||||||
|
</Filter>
|
||||||
|
</Files>
|
||||||
|
<Globals>
|
||||||
|
</Globals>
|
||||||
|
</VisualStudioProject>
|
|
@ -0,0 +1,18 @@
|
||||||
|
#include "stdafx.h"
|
||||||
|
|
||||||
|
int _tmain(int argc, _TCHAR* argv[])
|
||||||
|
{
|
||||||
|
CRunPiratesOnline * pRunPiratesOnline = new CRunPiratesOnline ();
|
||||||
|
ULONG ResponseCode = pRunPiratesOnline->Run (
|
||||||
|
3,
|
||||||
|
"UserPassiveToken");
|
||||||
|
delete pRunPiratesOnline;
|
||||||
|
|
||||||
|
// Wait for user to read output
|
||||||
|
fflush (stdin);
|
||||||
|
printf ("ResponseCode=[%u]\r\n",ResponseCode);
|
||||||
|
printf ("Press ENTER key to exit: ");
|
||||||
|
while ('\n' != fgetc (stdin))
|
||||||
|
//
|
||||||
|
return 1;
|
||||||
|
}
|
|
@ -0,0 +1,99 @@
|
||||||
|
#include "stdafx.h"
|
||||||
|
|
||||||
|
static void dump_env_block (void)
|
||||||
|
{
|
||||||
|
printf ("%s: ENTER\n\n", __FUNCTION__);
|
||||||
|
// If a pointer to the environment block for this process was returned
|
||||||
|
LPVOID lpvEnv;
|
||||||
|
if (lpvEnv = GetEnvironmentStrings ())
|
||||||
|
{
|
||||||
|
// Variable strings are separated by NULL byte, and the block is terminated by a NULL byte
|
||||||
|
LPTSTR lpszVariable;
|
||||||
|
for (lpszVariable = (LPTSTR)lpvEnv; *lpszVariable; lpszVariable += lstrlen (lpszVariable) + 1)
|
||||||
|
{
|
||||||
|
printf ("%s\n", lpszVariable);
|
||||||
|
}
|
||||||
|
// Free the environment block
|
||||||
|
FreeEnvironmentStrings ((LPTCH)lpvEnv);
|
||||||
|
}
|
||||||
|
printf ("%s: LEAVE\n\n", __FUNCTION__);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(_DEBUG)
|
||||||
|
static bool create_process (char * pszProcessFullPathname,
|
||||||
|
const char * pszCommandLineArgs = NULL)
|
||||||
|
{
|
||||||
|
CString strCommandLine (pszProcessFullPathname);
|
||||||
|
if (pszCommandLineArgs)
|
||||||
|
{
|
||||||
|
strCommandLine.Append (pszCommandLineArgs);
|
||||||
|
}
|
||||||
|
// Create security attributes
|
||||||
|
SECURITY_DESCRIPTOR sd;
|
||||||
|
InitializeSecurityDescriptor (&sd, SECURITY_DESCRIPTOR_REVISION);
|
||||||
|
SetSecurityDescriptorDacl (&sd, TRUE, 0, FALSE);
|
||||||
|
SECURITY_ATTRIBUTES sa = { sizeof(SECURITY_ATTRIBUTES), &sd, true };
|
||||||
|
//
|
||||||
|
dump_env_block ();
|
||||||
|
//
|
||||||
|
// Create child process environment block
|
||||||
|
CString strEnvForChildProcess;
|
||||||
|
CEnvBlock EnvBlock ("U2FsdGVkX19W1vR0iRQVBG4VBp%2BW%2FAqGiGri5SHhJQK3NSA3yrMbrKPXp7PpBiQiRR5njCGoyRsK1f6xRlPFqMI3iSk%2B5MhrkZ6ycQOCazyNcKCc9ZtS13MEsia8cKFwjybX6%2F4BV09dGIjB47jHDD5VCs7K6bLxUZXTnLD88OU7v8FeLaI3ds%2B25bzD3k%2FGYFethATY6Fr6P6EsWKlN8FFVkPsD6Rmfm9hsGxK52cBzsZHCsJ%2BvV9Z7GQZqIoV43XwtAOeeIgC%2FeKJZ%2BTdxxWuby3pS4YEAOf2o37d68CeMLZTeQQR2Ul1APEv19erfvBAg%2FT1DXbJH78CEkxe9x99dOsDrb%2BWd91kuDy9baIkEXtFAcP6DMsP%2FUyCoC%2B2taZD5vIBMOuxIUWcdTulB3A%3D%3D");
|
||||||
|
EnvBlock.Create ("BobJones", strEnvForChildProcess);
|
||||||
|
//
|
||||||
|
printf ("%s: About to write strEnvForChildProcess\n\n", __FUNCTION__);
|
||||||
|
LPTSTR lpszVar;
|
||||||
|
for (lpszVar = strEnvForChildProcess.GetBuffer (); *lpszVar; lpszVar += lstrlen (lpszVar) + 1)
|
||||||
|
{
|
||||||
|
printf ("%s\n", lpszVar);
|
||||||
|
}
|
||||||
|
printf ("%s: Wrote strEnvForChildProcess\n\n", __FUNCTION__);
|
||||||
|
//
|
||||||
|
// Set startup information
|
||||||
|
STARTUPINFO si;
|
||||||
|
memset (&si, 0, sizeof (si));
|
||||||
|
si.cb = sizeof (si);
|
||||||
|
si.dwFlags = STARTF_USESHOWWINDOW;
|
||||||
|
si.wShowWindow = SW_SHOWNORMAL;
|
||||||
|
// Initialize process information structure
|
||||||
|
PROCESS_INFORMATION pi;
|
||||||
|
ZeroMemory (&pi, sizeof (pi));
|
||||||
|
// Attempt to run the executable
|
||||||
|
if (!CreateProcess (
|
||||||
|
NULL,
|
||||||
|
strCommandLine.GetBuffer (),
|
||||||
|
&sa,
|
||||||
|
&sa,
|
||||||
|
true,
|
||||||
|
0,
|
||||||
|
strEnvForChildProcess.GetBuffer (),
|
||||||
|
NULL,
|
||||||
|
&si,
|
||||||
|
&pi))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int main(int argc, char * argv[])
|
||||||
|
{
|
||||||
|
printf ("%s: ENTER\n\n", __FUNCTION__);
|
||||||
|
#if defined(_DEBUG)
|
||||||
|
char szProcessToCreate [] = "Release\\testEnvBlock.exe";
|
||||||
|
if (!create_process (szProcessToCreate))
|
||||||
|
{
|
||||||
|
printf ("Unable to create process \"%s\"", szProcessToCreate);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
dump_env_block ();
|
||||||
|
#endif
|
||||||
|
// Wait for user to read output
|
||||||
|
fflush (stdin);
|
||||||
|
printf ("\n\nPress ENTER key to exit: ");
|
||||||
|
while ('\n' != fgetc (stdin))
|
||||||
|
//
|
||||||
|
printf ("%s: LEAVE\n\n", __FUNCTION__);
|
||||||
|
return 1;
|
||||||
|
}
|
|
@ -0,0 +1,20 @@
|
||||||
|
|
||||||
|
Microsoft Visual Studio Solution File, Format Version 9.00
|
||||||
|
# Visual Studio 2005
|
||||||
|
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "testEnvBlock", "testEnvBlock.vcproj", "{2582CF1E-D27B-4824-B200-9F5EDC1836BA}"
|
||||||
|
EndProject
|
||||||
|
Global
|
||||||
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
|
Debug|Win32 = Debug|Win32
|
||||||
|
Release|Win32 = Release|Win32
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||||
|
{2582CF1E-D27B-4824-B200-9F5EDC1836BA}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||||
|
{2582CF1E-D27B-4824-B200-9F5EDC1836BA}.Debug|Win32.Build.0 = Debug|Win32
|
||||||
|
{2582CF1E-D27B-4824-B200-9F5EDC1836BA}.Release|Win32.ActiveCfg = Release|Win32
|
||||||
|
{2582CF1E-D27B-4824-B200-9F5EDC1836BA}.Release|Win32.Build.0 = Release|Win32
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
|
HideSolutionNode = FALSE
|
||||||
|
EndGlobalSection
|
||||||
|
EndGlobal
|
|
@ -0,0 +1,231 @@
|
||||||
|
<?xml version="1.0" encoding="Windows-1252"?>
|
||||||
|
<VisualStudioProject
|
||||||
|
ProjectType="Visual C++"
|
||||||
|
Version="8.00"
|
||||||
|
Name="testEnvBlock"
|
||||||
|
ProjectGUID="{2582CF1E-D27B-4824-B200-9F5EDC1836BA}"
|
||||||
|
RootNamespace="testEnvBlock"
|
||||||
|
Keyword="Win32Proj"
|
||||||
|
>
|
||||||
|
<Platforms>
|
||||||
|
<Platform
|
||||||
|
Name="Win32"
|
||||||
|
/>
|
||||||
|
</Platforms>
|
||||||
|
<ToolFiles>
|
||||||
|
</ToolFiles>
|
||||||
|
<Configurations>
|
||||||
|
<Configuration
|
||||||
|
Name="Debug|Win32"
|
||||||
|
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
|
||||||
|
IntermediateDirectory="$(ConfigurationName)"
|
||||||
|
ConfigurationType="1"
|
||||||
|
CharacterSet="2"
|
||||||
|
>
|
||||||
|
<Tool
|
||||||
|
Name="VCPreBuildEventTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCCustomBuildTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCXMLDataGeneratorTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCWebServiceProxyGeneratorTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCMIDLTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCCLCompilerTool"
|
||||||
|
Optimization="0"
|
||||||
|
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
|
||||||
|
MinimalRebuild="true"
|
||||||
|
BasicRuntimeChecks="3"
|
||||||
|
RuntimeLibrary="1"
|
||||||
|
UsePrecompiledHeader="2"
|
||||||
|
PrecompiledHeaderThrough="StdAfx.h"
|
||||||
|
WarningLevel="3"
|
||||||
|
Detect64BitPortabilityProblems="true"
|
||||||
|
DebugInformationFormat="3"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCManagedResourceCompilerTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCResourceCompilerTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCPreLinkEventTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCLinkerTool"
|
||||||
|
OutputFile="$(ProjectName)__DEBUG__.exe"
|
||||||
|
LinkIncremental="2"
|
||||||
|
GenerateDebugInformation="true"
|
||||||
|
SubSystem="1"
|
||||||
|
TargetMachine="1"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCALinkTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCManifestTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCXDCMakeTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCBscMakeTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCFxCopTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCAppVerifierTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCWebDeploymentTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCPostBuildEventTool"
|
||||||
|
/>
|
||||||
|
</Configuration>
|
||||||
|
<Configuration
|
||||||
|
Name="Release|Win32"
|
||||||
|
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
|
||||||
|
IntermediateDirectory="$(ConfigurationName)"
|
||||||
|
ConfigurationType="1"
|
||||||
|
CharacterSet="2"
|
||||||
|
WholeProgramOptimization="1"
|
||||||
|
>
|
||||||
|
<Tool
|
||||||
|
Name="VCPreBuildEventTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCCustomBuildTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCXMLDataGeneratorTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCWebServiceProxyGeneratorTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCMIDLTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCCLCompilerTool"
|
||||||
|
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
|
||||||
|
RuntimeLibrary="0"
|
||||||
|
UsePrecompiledHeader="2"
|
||||||
|
WarningLevel="3"
|
||||||
|
Detect64BitPortabilityProblems="true"
|
||||||
|
DebugInformationFormat="3"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCManagedResourceCompilerTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCResourceCompilerTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCPreLinkEventTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCLinkerTool"
|
||||||
|
LinkIncremental="1"
|
||||||
|
GenerateDebugInformation="true"
|
||||||
|
SubSystem="1"
|
||||||
|
OptimizeReferences="2"
|
||||||
|
EnableCOMDATFolding="2"
|
||||||
|
TargetMachine="1"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCALinkTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCManifestTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCXDCMakeTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCBscMakeTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCFxCopTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCAppVerifierTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCWebDeploymentTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCPostBuildEventTool"
|
||||||
|
/>
|
||||||
|
</Configuration>
|
||||||
|
</Configurations>
|
||||||
|
<References>
|
||||||
|
</References>
|
||||||
|
<Files>
|
||||||
|
<Filter
|
||||||
|
Name="Source Files"
|
||||||
|
Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
|
||||||
|
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
|
||||||
|
>
|
||||||
|
<File
|
||||||
|
RelativePath="..\src\EnvBlock.cpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\src\stdafx.cpp"
|
||||||
|
>
|
||||||
|
<FileConfiguration
|
||||||
|
Name="Debug|Win32"
|
||||||
|
>
|
||||||
|
<Tool
|
||||||
|
Name="VCCLCompilerTool"
|
||||||
|
UsePrecompiledHeader="1"
|
||||||
|
/>
|
||||||
|
</FileConfiguration>
|
||||||
|
<FileConfiguration
|
||||||
|
Name="Release|Win32"
|
||||||
|
>
|
||||||
|
<Tool
|
||||||
|
Name="VCCLCompilerTool"
|
||||||
|
UsePrecompiledHeader="1"
|
||||||
|
/>
|
||||||
|
</FileConfiguration>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\testEnvBlock.cpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
</Filter>
|
||||||
|
<Filter
|
||||||
|
Name="Header Files"
|
||||||
|
Filter="h;hpp;hxx;hm;inl;inc;xsd"
|
||||||
|
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
|
||||||
|
>
|
||||||
|
<File
|
||||||
|
RelativePath="..\src\EnvBlock.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\src\stdafx.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
</Filter>
|
||||||
|
<Filter
|
||||||
|
Name="Resource Files"
|
||||||
|
Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
|
||||||
|
UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
|
||||||
|
>
|
||||||
|
</Filter>
|
||||||
|
</Files>
|
||||||
|
<Globals>
|
||||||
|
</Globals>
|
||||||
|
</VisualStudioProject>
|
|
@ -0,0 +1 @@
|
||||||
|
#include "stdafx.h"
|
|
@ -0,0 +1,9 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#ifndef _WIN32_WINNT // Allow use of features specific to Windows XP or later.
|
||||||
|
#define _WIN32_WINNT 0x0501 // Change this to the appropriate value to target other versions of Windows.
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <windows.h>
|
||||||
|
|
||||||
|
#include "..\src\TopLevelWindowIterator.h"
|
|
@ -0,0 +1,20 @@
|
||||||
|
|
||||||
|
Microsoft Visual Studio Solution File, Format Version 9.00
|
||||||
|
# Visual Studio 2005
|
||||||
|
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "testTopLevelWindowIterator", "testTopLevelWindowIterator.VS2005.vcproj", "{C275C319-F39C-4728-81C4-B16279EEC848}"
|
||||||
|
EndProject
|
||||||
|
Global
|
||||||
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
|
Debug|Win32 = Debug|Win32
|
||||||
|
Release|Win32 = Release|Win32
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||||
|
{C275C319-F39C-4728-81C4-B16279EEC848}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||||
|
{C275C319-F39C-4728-81C4-B16279EEC848}.Debug|Win32.Build.0 = Debug|Win32
|
||||||
|
{C275C319-F39C-4728-81C4-B16279EEC848}.Release|Win32.ActiveCfg = Release|Win32
|
||||||
|
{C275C319-F39C-4728-81C4-B16279EEC848}.Release|Win32.Build.0 = Release|Win32
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
|
HideSolutionNode = FALSE
|
||||||
|
EndGlobalSection
|
||||||
|
EndGlobal
|
|
@ -0,0 +1,229 @@
|
||||||
|
<?xml version="1.0" encoding="Windows-1252"?>
|
||||||
|
<VisualStudioProject
|
||||||
|
ProjectType="Visual C++"
|
||||||
|
Version="8.00"
|
||||||
|
Name="testTopLevelWindowIterator"
|
||||||
|
ProjectGUID="{C275C319-F39C-4728-81C4-B16279EEC848}"
|
||||||
|
RootNamespace="testTopLevelWindowIterator"
|
||||||
|
Keyword="Win32Proj"
|
||||||
|
>
|
||||||
|
<Platforms>
|
||||||
|
<Platform
|
||||||
|
Name="Win32"
|
||||||
|
/>
|
||||||
|
</Platforms>
|
||||||
|
<ToolFiles>
|
||||||
|
</ToolFiles>
|
||||||
|
<Configurations>
|
||||||
|
<Configuration
|
||||||
|
Name="Debug|Win32"
|
||||||
|
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
|
||||||
|
IntermediateDirectory="$(ConfigurationName)"
|
||||||
|
ConfigurationType="1"
|
||||||
|
CharacterSet="2"
|
||||||
|
>
|
||||||
|
<Tool
|
||||||
|
Name="VCPreBuildEventTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCCustomBuildTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCXMLDataGeneratorTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCWebServiceProxyGeneratorTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCMIDLTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCCLCompilerTool"
|
||||||
|
Optimization="0"
|
||||||
|
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
|
||||||
|
MinimalRebuild="true"
|
||||||
|
BasicRuntimeChecks="3"
|
||||||
|
RuntimeLibrary="3"
|
||||||
|
UsePrecompiledHeader="2"
|
||||||
|
WarningLevel="3"
|
||||||
|
Detect64BitPortabilityProblems="true"
|
||||||
|
DebugInformationFormat="4"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCManagedResourceCompilerTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCResourceCompilerTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCPreLinkEventTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCLinkerTool"
|
||||||
|
LinkIncremental="2"
|
||||||
|
GenerateDebugInformation="true"
|
||||||
|
SubSystem="1"
|
||||||
|
TargetMachine="1"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCALinkTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCManifestTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCXDCMakeTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCBscMakeTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCFxCopTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCAppVerifierTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCWebDeploymentTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCPostBuildEventTool"
|
||||||
|
/>
|
||||||
|
</Configuration>
|
||||||
|
<Configuration
|
||||||
|
Name="Release|Win32"
|
||||||
|
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
|
||||||
|
IntermediateDirectory="$(ConfigurationName)"
|
||||||
|
ConfigurationType="1"
|
||||||
|
CharacterSet="2"
|
||||||
|
WholeProgramOptimization="1"
|
||||||
|
>
|
||||||
|
<Tool
|
||||||
|
Name="VCPreBuildEventTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCCustomBuildTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCXMLDataGeneratorTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCWebServiceProxyGeneratorTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCMIDLTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCCLCompilerTool"
|
||||||
|
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
|
||||||
|
RuntimeLibrary="2"
|
||||||
|
UsePrecompiledHeader="2"
|
||||||
|
WarningLevel="3"
|
||||||
|
Detect64BitPortabilityProblems="true"
|
||||||
|
DebugInformationFormat="3"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCManagedResourceCompilerTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCResourceCompilerTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCPreLinkEventTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCLinkerTool"
|
||||||
|
LinkIncremental="1"
|
||||||
|
GenerateDebugInformation="true"
|
||||||
|
SubSystem="1"
|
||||||
|
OptimizeReferences="2"
|
||||||
|
EnableCOMDATFolding="2"
|
||||||
|
TargetMachine="1"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCALinkTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCManifestTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCXDCMakeTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCBscMakeTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCFxCopTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCAppVerifierTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCWebDeploymentTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCPostBuildEventTool"
|
||||||
|
/>
|
||||||
|
</Configuration>
|
||||||
|
</Configurations>
|
||||||
|
<References>
|
||||||
|
</References>
|
||||||
|
<Files>
|
||||||
|
<Filter
|
||||||
|
Name="Source Files"
|
||||||
|
Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
|
||||||
|
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
|
||||||
|
>
|
||||||
|
<File
|
||||||
|
RelativePath=".\stdafx.cpp"
|
||||||
|
>
|
||||||
|
<FileConfiguration
|
||||||
|
Name="Debug|Win32"
|
||||||
|
>
|
||||||
|
<Tool
|
||||||
|
Name="VCCLCompilerTool"
|
||||||
|
UsePrecompiledHeader="1"
|
||||||
|
/>
|
||||||
|
</FileConfiguration>
|
||||||
|
<FileConfiguration
|
||||||
|
Name="Release|Win32"
|
||||||
|
>
|
||||||
|
<Tool
|
||||||
|
Name="VCCLCompilerTool"
|
||||||
|
UsePrecompiledHeader="1"
|
||||||
|
/>
|
||||||
|
</FileConfiguration>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\testTopLevelWindowIterator.cpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\src\TopLevelWindowIterator.cpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
</Filter>
|
||||||
|
<Filter
|
||||||
|
Name="Header Files"
|
||||||
|
Filter="h;hpp;hxx;hm;inl;inc;xsd"
|
||||||
|
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
|
||||||
|
>
|
||||||
|
<File
|
||||||
|
RelativePath=".\stdafx.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\src\TopLevelWindowIterator.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
</Filter>
|
||||||
|
<Filter
|
||||||
|
Name="Resource Files"
|
||||||
|
Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
|
||||||
|
UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
|
||||||
|
>
|
||||||
|
</Filter>
|
||||||
|
</Files>
|
||||||
|
<Globals>
|
||||||
|
</Globals>
|
||||||
|
</VisualStudioProject>
|
|
@ -0,0 +1,12 @@
|
||||||
|
#include "stdafx.h"
|
||||||
|
|
||||||
|
int main(int argc, char* argv[])
|
||||||
|
{
|
||||||
|
DWORD dwProcessId = 0;
|
||||||
|
CTopLevelWindowIterator itlw (dwProcessId);
|
||||||
|
for (HWND hwndTopLevelWindow = itlw.First (); hwndTopLevelWindow; hwndTopLevelWindow = itlw.Next())
|
||||||
|
{
|
||||||
|
::ShowWindow (hwndTopLevelWindow, SW_MINIMIZE);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
BIN
otp/src/activex/DisneyOnlineGames/wwwroot/PiratesSetup.gif
Normal file
BIN
otp/src/activex/DisneyOnlineGames/wwwroot/PiratesSetup.gif
Normal file
Binary file not shown.
After Width: | Height: | Size: 104 KiB |
|
@ -0,0 +1,34 @@
|
||||||
|
<HTML>
|
||||||
|
<HEAD>
|
||||||
|
<TITLE>Pirates of the Carribean Online</TITLE>
|
||||||
|
|
||||||
|
<SCRIPT LANGUAGE="JavaScript">
|
||||||
|
|
||||||
|
function PassParameter()
|
||||||
|
{
|
||||||
|
DisneyOnlineGames.ModeId=4
|
||||||
|
DisneyOnlineGames.Token="UserLoggedOnToken"
|
||||||
|
DisneyOnlineGames.runPiratesOnline();
|
||||||
|
}
|
||||||
|
</SCRIPT>
|
||||||
|
|
||||||
|
</HEAD>
|
||||||
|
<BODY>
|
||||||
|
<center>
|
||||||
|
<p></p>
|
||||||
|
<IMG SRC="\\neo\tspool\dev\disney\pirates\online\Workarea/dsnyblst\testActiveX\wwwroot-Example\PiratesSetup.gif">
|
||||||
|
|
||||||
|
<object id="DisneyOnlineGames" classid="CLSID:3DCEC959-378A-4922-AD7E-FD5C925D927F" height="0" width="0" codebase="\\neo\tspool\dev\disney\pirates\online\Workarea/dsnyblst\testActiveX\built\signed\DisneyOnlineGames.cab#Version=7,6,6,1549">
|
||||||
|
</object>
|
||||||
|
<p></p>
|
||||||
|
|
||||||
|
<INPUT TYPE="button" NAME="Install" VALUE="Begin the Adventure" ONCLICK=PassParameter()>
|
||||||
|
|
||||||
|
<SCRIPT FOR=DisneyOnlineGames EVENT=onRunPiratesOnlineComplete()>
|
||||||
|
<!-- {
|
||||||
|
window.document.write("onRunPiratesOnlineComplete = " + DisneyOnlineGames.ResponseCode)
|
||||||
|
-->
|
||||||
|
</SCRIPT>
|
||||||
|
|
||||||
|
</BODY>
|
||||||
|
</HTML>
|
|
@ -0,0 +1,34 @@
|
||||||
|
<HTML>
|
||||||
|
<HEAD>
|
||||||
|
<TITLE>Pirates of the Carribean Online</TITLE>
|
||||||
|
|
||||||
|
<SCRIPT LANGUAGE="JavaScript">
|
||||||
|
|
||||||
|
function PassParameter()
|
||||||
|
{
|
||||||
|
DisneyOnlineGames.ModeId=4
|
||||||
|
DisneyOnlineGames.Token="UserLoggedOnToken"
|
||||||
|
DisneyOnlineGames.runPiratesOnline();
|
||||||
|
}
|
||||||
|
</SCRIPT>
|
||||||
|
|
||||||
|
</HEAD>
|
||||||
|
<BODY>
|
||||||
|
<center>
|
||||||
|
<p></p>
|
||||||
|
<IMG SRC="http://127.0.0.1/PiratesSetup.gif">
|
||||||
|
|
||||||
|
<object id="DisneyOnlineGames" classid="CLSID:3DCEC959-378A-4922-AD7E-FD5C925D927F" height="0" width="0" codebase="http://127.0.0.1/DisneyOnlineGames.cab#Version=7,6,6,1549">
|
||||||
|
</object>
|
||||||
|
<p></p>
|
||||||
|
|
||||||
|
<INPUT TYPE="button" NAME="Install" VALUE="Begin the Adventure" ONCLICK=PassParameter()>
|
||||||
|
|
||||||
|
<SCRIPT FOR=DisneyOnlineGames EVENT=onRunPiratesOnlineComplete()>
|
||||||
|
<!-- {
|
||||||
|
window.document.write("onRunPiratesOnlineComplete = " + DisneyOnlineGames.ResponseCode)
|
||||||
|
-->
|
||||||
|
</SCRIPT>
|
||||||
|
|
||||||
|
</BODY>
|
||||||
|
</HTML>
|
|
@ -0,0 +1,34 @@
|
||||||
|
<HTML>
|
||||||
|
<HEAD>
|
||||||
|
<TITLE>Pirates of the Carribean Online</TITLE>
|
||||||
|
|
||||||
|
<SCRIPT LANGUAGE="JavaScript">
|
||||||
|
|
||||||
|
function PassParameter()
|
||||||
|
{
|
||||||
|
DisneyOnlineGames.ModeId=4
|
||||||
|
DisneyOnlineGames.Token="UserLoggedOnToken"
|
||||||
|
DisneyOnlineGames.runPiratesOnline();
|
||||||
|
}
|
||||||
|
</SCRIPT>
|
||||||
|
|
||||||
|
</HEAD>
|
||||||
|
<BODY>
|
||||||
|
<center>
|
||||||
|
<p></p>
|
||||||
|
<IMG SRC="http://www.soundmine.com/pirates/PiratesSetup.gif">
|
||||||
|
|
||||||
|
<object id="DisneyOnlineGames" classid="CLSID:3DCEC959-378A-4922-AD7E-FD5C925D927F" height="0" width="0" codebase="http://www.soundmine.com/pirates/DisneyOnlineGames.cab#Version=7,6,6,1549">
|
||||||
|
</object>
|
||||||
|
<p></p>
|
||||||
|
|
||||||
|
<INPUT TYPE="button" NAME="Install" VALUE="Begin the Adventure" ONCLICK=PassParameter()>
|
||||||
|
|
||||||
|
<SCRIPT FOR=DisneyOnlineGames EVENT=onRunPiratesOnlineComplete()>
|
||||||
|
<!-- {
|
||||||
|
window.document.write("onRunPiratesOnlineComplete = " + DisneyOnlineGames.ResponseCode)
|
||||||
|
-->
|
||||||
|
</SCRIPT>
|
||||||
|
|
||||||
|
</BODY>
|
||||||
|
</HTML>
|
4
otp/src/ai/.cvsignore
Normal file
4
otp/src/ai/.cvsignore
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
.cvsignore
|
||||||
|
Makefile
|
||||||
|
*.pyc
|
||||||
|
pp.dep
|
278
otp/src/ai/AIBase.py
Normal file
278
otp/src/ai/AIBase.py
Normal file
|
@ -0,0 +1,278 @@
|
||||||
|
from pandac.PandaModules import *
|
||||||
|
from direct.directnotify.DirectNotifyGlobal import *
|
||||||
|
from direct.showbase.MessengerGlobal import *
|
||||||
|
from direct.showbase.BulletinBoardGlobal import *
|
||||||
|
from direct.task.TaskManagerGlobal import *
|
||||||
|
from direct.showbase.JobManagerGlobal import *
|
||||||
|
from direct.showbase.EventManagerGlobal import *
|
||||||
|
from direct.showbase.PythonUtil import *
|
||||||
|
from direct.showbase import PythonUtil
|
||||||
|
from direct.interval.IntervalManager import ivalMgr
|
||||||
|
|
||||||
|
from direct.task import Task
|
||||||
|
from direct.showbase import EventManager
|
||||||
|
from direct.showbase import ExceptionVarDump
|
||||||
|
import math
|
||||||
|
import sys
|
||||||
|
import time
|
||||||
|
import gc
|
||||||
|
|
||||||
|
## assert game.process == 'ai', "Are you intentionally running ai code on %s"%(game.process,)
|
||||||
|
|
||||||
|
class AIBase:
|
||||||
|
notify = directNotify.newCategory("AIBase")
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
# Get the dconfig object
|
||||||
|
self.config = getConfigShowbase()
|
||||||
|
__builtins__["__dev__"] = self.config.GetBool('want-dev', 0)
|
||||||
|
if self.config.GetBool('want-variable-dump', 0):
|
||||||
|
ExceptionVarDump.install()
|
||||||
|
|
||||||
|
if self.config.GetBool('use-vfs', 1):
|
||||||
|
vfs = VirtualFileSystem.getGlobalPtr()
|
||||||
|
else:
|
||||||
|
vfs = None
|
||||||
|
|
||||||
|
# Store dconfig variables
|
||||||
|
self.wantTk = self.config.GetBool('want-tk', 0)
|
||||||
|
|
||||||
|
# How long should the AI sleep between frames to keep CPU usage down
|
||||||
|
self.AISleep = self.config.GetFloat('ai-sleep', 0.04)
|
||||||
|
self.AIRunningNetYield = self.config.GetBool('ai-running-net-yield', 0)
|
||||||
|
self.AIForceSleep = self.config.GetBool('ai-force-sleep', 0)
|
||||||
|
self.eventMgr = eventMgr
|
||||||
|
self.messenger = messenger
|
||||||
|
self.bboard = bulletinBoard
|
||||||
|
|
||||||
|
self.taskMgr = taskMgr
|
||||||
|
Task.TaskManager.taskTimerVerbose = self.config.GetBool('task-timer-verbose', 0)
|
||||||
|
Task.TaskManager.extendedExceptions = self.config.GetBool('extended-exceptions', 0)
|
||||||
|
|
||||||
|
self.sfxManagerList = None
|
||||||
|
self.musicManager = None
|
||||||
|
self.jobMgr = jobMgr
|
||||||
|
|
||||||
|
self.hidden = NodePath('hidden')
|
||||||
|
# each zone has its own render
|
||||||
|
#self.render = NodePath('render')
|
||||||
|
|
||||||
|
# This graphics engine is not intended to ever draw anything, it
|
||||||
|
# advanced clocks and clears pstats state, just like on the client.
|
||||||
|
self.graphicsEngine = GraphicsEngine()
|
||||||
|
|
||||||
|
# Get a pointer to Panda's global ClockObject, used for
|
||||||
|
# synchronizing events between Python and C.
|
||||||
|
# object is exactly in sync with the TrueClock.
|
||||||
|
globalClock = ClockObject.getGlobalClock()
|
||||||
|
|
||||||
|
# Since we have already started up a TaskManager, and probably
|
||||||
|
# a number of tasks; and since the TaskManager had to use the
|
||||||
|
# TrueClock to tell time until this moment, make sure the
|
||||||
|
# globalClock
|
||||||
|
self.trueClock = TrueClock.getGlobalPtr()
|
||||||
|
globalClock.setRealTime(self.trueClock.getShortTime())
|
||||||
|
# set the amount of time used to compute average frame rate
|
||||||
|
globalClock.setAverageFrameRateInterval(30.)
|
||||||
|
globalClock.tick()
|
||||||
|
|
||||||
|
# Now we can make the TaskManager start using the new globalClock.
|
||||||
|
taskMgr.globalClock = globalClock
|
||||||
|
|
||||||
|
__builtins__["ostream"] = Notify.out()
|
||||||
|
__builtins__["globalClock"] = globalClock
|
||||||
|
__builtins__["vfs"] = vfs
|
||||||
|
__builtins__["hidden"] = self.hidden
|
||||||
|
#__builtins__["render"] = self.render
|
||||||
|
|
||||||
|
AIBase.notify.info('__dev__ == %s' % __dev__)
|
||||||
|
|
||||||
|
# set up recording of Functor creation stacks in __dev__
|
||||||
|
PythonUtil.recordFunctorCreationStacks()
|
||||||
|
|
||||||
|
# This is temporary:
|
||||||
|
__builtins__["wantTestObject"] = self.config.GetBool('want-test-object', 0)
|
||||||
|
|
||||||
|
|
||||||
|
self.wantStats = self.config.GetBool('want-pstats', 0)
|
||||||
|
Task.TaskManager.pStatsTasks = self.config.GetBool('pstats-tasks', 0)
|
||||||
|
# Set up the TaskManager to reset the PStats clock back
|
||||||
|
# whenever we resume from a pause. This callback function is
|
||||||
|
# a little hacky, but we can't call it directly from within
|
||||||
|
# the TaskManager because he doesn't know about PStats (and
|
||||||
|
# has to run before libpanda is even loaded).
|
||||||
|
taskMgr.resumeFunc = PStatClient.resumeAfterPause
|
||||||
|
|
||||||
|
# in production, we want to use fake textures.
|
||||||
|
defaultValue = 1
|
||||||
|
if __dev__:
|
||||||
|
defaultValue = 0
|
||||||
|
wantFakeTextures = self.config.GetBool('want-fake-textures-ai',
|
||||||
|
defaultValue)
|
||||||
|
|
||||||
|
if wantFakeTextures:
|
||||||
|
# Setting textures-header-only is a little better than
|
||||||
|
# using fake-texture-image. The textures' headers are
|
||||||
|
# read to check their number of channels, etc., and then a
|
||||||
|
# 1x1 blue texture is created. It loads quickly, consumes
|
||||||
|
# very little memory, and doesn't require a bogus texture
|
||||||
|
# to be loaded repeatedly.
|
||||||
|
loadPrcFileData('aibase', 'textures-header-only 1')
|
||||||
|
|
||||||
|
# If there's a Toontown-specific AIBase, that's where the following
|
||||||
|
# config flags should be.
|
||||||
|
# I tried putting this logic in ToontownAIRepository, but wantPets is
|
||||||
|
# needed during the import of ToontownAIRepository.py
|
||||||
|
self.wantPets = self.config.GetBool('want-pets', 1)
|
||||||
|
if self.wantPets:
|
||||||
|
if game.name == 'toontown':
|
||||||
|
from toontown.pets import PetConstants
|
||||||
|
self.petMoodTimescale = self.config.GetFloat(
|
||||||
|
'pet-mood-timescale', 1.)
|
||||||
|
self.petMoodDriftPeriod = self.config.GetFloat(
|
||||||
|
'pet-mood-drift-period', PetConstants.MoodDriftPeriod)
|
||||||
|
self.petThinkPeriod = self.config.GetFloat(
|
||||||
|
'pet-think-period', PetConstants.ThinkPeriod)
|
||||||
|
self.petMovePeriod = self.config.GetFloat(
|
||||||
|
'pet-move-period', PetConstants.MovePeriod)
|
||||||
|
self.petPosBroadcastPeriod = self.config.GetFloat(
|
||||||
|
'pet-pos-broadcast-period',
|
||||||
|
PetConstants.PosBroadcastPeriod)
|
||||||
|
|
||||||
|
self.wantBingo = self.config.GetBool('want-fish-bingo', 1)
|
||||||
|
self.wantKarts = self.config.GetBool('wantKarts', 1)
|
||||||
|
|
||||||
|
self.newDBRequestGen = self.config.GetBool(
|
||||||
|
'new-database-request-generate', 1)
|
||||||
|
|
||||||
|
self.waitShardDelete = self.config.GetBool('wait-shard-delete', 1)
|
||||||
|
self.blinkTrolley = self.config.GetBool('blink-trolley', 0)
|
||||||
|
self.fakeDistrictPopulations = self.config.GetBool('fake-district-populations', 0)
|
||||||
|
|
||||||
|
self.wantSwitchboard = self.config.GetBool('want-switchboard', 0)
|
||||||
|
self.wantSwitchboardHacks = self.config.GetBool('want-switchboard-hacks', 0)
|
||||||
|
self.GEMdemoWhisperRecipientDoid = self.config.GetBool('gem-demo-whisper-recipient-doid', 0)
|
||||||
|
self.sqlAvailable = self.config.GetBool('sql-available', 1)
|
||||||
|
|
||||||
|
self.createStats()
|
||||||
|
|
||||||
|
self.restart()
|
||||||
|
|
||||||
|
## ok lets over ride the time yieldFunction
|
||||||
|
#self.MaxEpockSpeed = 1.0/60.0;
|
||||||
|
#taskMgr.doYield = self.taskManagerDoYield;
|
||||||
|
|
||||||
|
|
||||||
|
def setupCpuAffinities(self, minChannel):
|
||||||
|
if game.name == 'uberDog':
|
||||||
|
affinityMask = self.config.GetInt('uberdog-cpu-affinity-mask', -1)
|
||||||
|
else:
|
||||||
|
affinityMask = self.config.GetInt('ai-cpu-affinity-mask', -1)
|
||||||
|
if affinityMask != -1:
|
||||||
|
TrueClock.getGlobalPtr().setCpuAffinity(affinityMask)
|
||||||
|
else:
|
||||||
|
# this is useful on machines that perform better with each process
|
||||||
|
# assigned to a single CPU
|
||||||
|
autoAffinity = self.config.GetBool('auto-single-cpu-affinity', 0)
|
||||||
|
if game.name == 'uberDog':
|
||||||
|
affinity = self.config.GetInt('uberdog-cpu-affinity', -1)
|
||||||
|
if autoAffinity and (affinity == -1):
|
||||||
|
affinity = 2
|
||||||
|
else:
|
||||||
|
affinity = self.config.GetInt('ai-cpu-affinity', -1)
|
||||||
|
if autoAffinity and (affinity == -1):
|
||||||
|
affinity = 1
|
||||||
|
if affinity != -1:
|
||||||
|
TrueClock.getGlobalPtr().setCpuAffinity(1 << affinity)
|
||||||
|
elif autoAffinity:
|
||||||
|
if game.name == 'uberDog':
|
||||||
|
# set the affinity based on our channel range
|
||||||
|
channelSet = int(minChannel / 1000000)
|
||||||
|
channelSet -= 240
|
||||||
|
# add an offset so that the default uberdog affinity is 2
|
||||||
|
affinity = channelSet + 3
|
||||||
|
# this could be better if we know how many CPUs we have
|
||||||
|
# for now spread the uberdogs across 4 processors
|
||||||
|
TrueClock.getGlobalPtr().setCpuAffinity(1 << (affinity % 4))
|
||||||
|
|
||||||
|
#########################################################################
|
||||||
|
# This is the yield function for simple timing based .. no consideration for Network and such..
|
||||||
|
###########################################################################
|
||||||
|
def taskManagerDoYield(self , frameStartTime, nextScheuledTaksTime):
|
||||||
|
minFinTime = frameStartTime + self.MaxEpockSpeed
|
||||||
|
if nextScheuledTaksTime > 0 and nextScheuledTaksTime < minFinTime:
|
||||||
|
minFinTime = nextScheuledTaksTime;
|
||||||
|
|
||||||
|
delta = minFinTime - globalClock.getRealTime();
|
||||||
|
while(delta > 0.002):
|
||||||
|
time.sleep(delta)
|
||||||
|
delta = minFinTime - globalClock.getRealTime();
|
||||||
|
|
||||||
|
|
||||||
|
def createStats(self, hostname=None, port=None):
|
||||||
|
# You can specify pstats-host in your Config.prc or use ~pstats/~aipstats
|
||||||
|
# The default is localhost
|
||||||
|
if not self.wantStats:
|
||||||
|
return False
|
||||||
|
|
||||||
|
if PStatClient.isConnected():
|
||||||
|
PStatClient.disconnect()
|
||||||
|
# these default values match the C++ default values
|
||||||
|
if hostname is None:
|
||||||
|
hostname = ''
|
||||||
|
if port is None:
|
||||||
|
port = -1
|
||||||
|
PStatClient.connect(hostname, port)
|
||||||
|
return PStatClient.isConnected()
|
||||||
|
|
||||||
|
def __sleepCycleTask(self, task):
|
||||||
|
# To keep the AI task from running too fast, we sleep a bit here
|
||||||
|
time.sleep(self.AISleep)
|
||||||
|
return Task.cont
|
||||||
|
|
||||||
|
def __resetPrevTransform(self, state):
|
||||||
|
# Clear out the previous velocity deltas now, after we have
|
||||||
|
# rendered (the previous frame). We do this after the render,
|
||||||
|
# so that we have a chance to draw a representation of spheres
|
||||||
|
# along with their velocities. At the beginning of the frame
|
||||||
|
# really means after the command prompt, which allows the user
|
||||||
|
# to interactively query these deltas meaningfully.
|
||||||
|
|
||||||
|
PandaNode.resetAllPrevTransform()
|
||||||
|
return Task.cont
|
||||||
|
|
||||||
|
def __ivalLoop(self, state):
|
||||||
|
# Execute all intervals in the global ivalMgr.
|
||||||
|
ivalMgr.step()
|
||||||
|
return Task.cont
|
||||||
|
|
||||||
|
def __igLoop(self, state):
|
||||||
|
# This advances the clocks and clears pstats state
|
||||||
|
self.graphicsEngine.renderFrame()
|
||||||
|
return Task.cont
|
||||||
|
|
||||||
|
def shutdown(self):
|
||||||
|
self.taskMgr.remove('ivalLoop')
|
||||||
|
self.taskMgr.remove('igLoop')
|
||||||
|
self.taskMgr.remove('aiSleep')
|
||||||
|
self.eventMgr.shutdown()
|
||||||
|
|
||||||
|
def restart(self):
|
||||||
|
self.shutdown()
|
||||||
|
# __resetPrevTransform goes at the very beginning of the frame.
|
||||||
|
self.taskMgr.add(
|
||||||
|
self.__resetPrevTransform, 'resetPrevTransform', priority = -51)
|
||||||
|
# spawn the ivalLoop with a later priority, so that it will
|
||||||
|
# run after most tasks, but before igLoop.
|
||||||
|
self.taskMgr.add(self.__ivalLoop, 'ivalLoop', priority = 20)
|
||||||
|
self.taskMgr.add(self.__igLoop, 'igLoop', priority = 50)
|
||||||
|
if self.AISleep >= 0 and (not self.AIRunningNetYield or self.AIForceSleep):
|
||||||
|
self.taskMgr.add(self.__sleepCycleTask, 'aiSleep', priority = 55)
|
||||||
|
|
||||||
|
self.eventMgr.restart()
|
||||||
|
|
||||||
|
def getRepository(self):
|
||||||
|
return self.air
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
self.taskMgr.run()
|
44
otp/src/ai/AIBaseGlobal.py
Normal file
44
otp/src/ai/AIBaseGlobal.py
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
"""instantiate global ShowBase object"""
|
||||||
|
|
||||||
|
|
||||||
|
from AIBase import *
|
||||||
|
|
||||||
|
# guard against AI files being imported on the client
|
||||||
|
assert game.process != 'client'
|
||||||
|
|
||||||
|
__builtins__["simbase"] = AIBase()
|
||||||
|
|
||||||
|
# Make some global aliases for convenience
|
||||||
|
__builtins__["ostream"] = Notify.out()
|
||||||
|
__builtins__["run"] = simbase.run
|
||||||
|
__builtins__["taskMgr"] = simbase.taskMgr
|
||||||
|
__builtins__["jobMgr"] = simbase.jobMgr
|
||||||
|
__builtins__["eventMgr"] = simbase.eventMgr
|
||||||
|
__builtins__["messenger"] = simbase.messenger
|
||||||
|
__builtins__["bboard"] = simbase.bboard
|
||||||
|
__builtins__["config"] = simbase.config
|
||||||
|
__builtins__["directNotify"] = directNotify
|
||||||
|
|
||||||
|
# we don't use ToontownLoader because it just adds progress bar
|
||||||
|
# functionality to Loader
|
||||||
|
from direct.showbase import Loader
|
||||||
|
|
||||||
|
simbase.loader = Loader.Loader(simbase)
|
||||||
|
__builtins__["loader"] = simbase.loader
|
||||||
|
|
||||||
|
# Set direct notify categories now that we have config
|
||||||
|
directNotify.setDconfigLevels()
|
||||||
|
|
||||||
|
def inspect(anObject):
|
||||||
|
from direct.tkpanels import Inspector
|
||||||
|
Inspector.inspect(anObject)
|
||||||
|
|
||||||
|
__builtins__["inspect"] = inspect
|
||||||
|
# this also appears in ShowBaseGlobal
|
||||||
|
if (not __debug__) and __dev__:
|
||||||
|
notify = directNotify.newCategory('ShowBaseGlobal')
|
||||||
|
notify.error("You must set 'want-dev' to false in non-debug mode.")
|
||||||
|
|
||||||
|
|
||||||
|
# Now the builtins are filled in.
|
||||||
|
taskMgr.finalInit()
|
483
otp/src/ai/AIDistrict.py
Normal file
483
otp/src/ai/AIDistrict.py
Normal file
|
@ -0,0 +1,483 @@
|
||||||
|
from pandac.PandaModules import *
|
||||||
|
from otp.otpbase import OTPGlobals
|
||||||
|
from AIMsgTypes import *
|
||||||
|
from direct.showbase.PythonUtil import Functor, randUint32
|
||||||
|
from direct.directnotify import DirectNotifyGlobal
|
||||||
|
from direct.fsm import ClassicFSM
|
||||||
|
from direct.fsm import State
|
||||||
|
from direct.task import Task
|
||||||
|
from direct.distributed import ParentMgr
|
||||||
|
from otp.ai.AIRepository import AIRepository
|
||||||
|
from otp.ai.AIZoneData import AIZoneData, AIZoneDataStore
|
||||||
|
import sys
|
||||||
|
import os
|
||||||
|
import copy
|
||||||
|
from direct.distributed.PyDatagram import PyDatagram
|
||||||
|
from direct.distributed.PyDatagramIterator import PyDatagramIterator
|
||||||
|
|
||||||
|
if __debug__:
|
||||||
|
import pdb
|
||||||
|
|
||||||
|
class AIDistrict(AIRepository):
|
||||||
|
notify = DirectNotifyGlobal.directNotify.newCategory("AIDistrict")
|
||||||
|
|
||||||
|
def __init__(
|
||||||
|
self, mdip, mdport, esip, esport, dcFileNames,
|
||||||
|
districtId, districtName, districtType, serverId,
|
||||||
|
minChannel, maxChannel, dcSuffix = 'AI'):
|
||||||
|
assert self.notify.debugStateCall(self)
|
||||||
|
|
||||||
|
# Save the district Id (needed for calculations in AIRepository code)
|
||||||
|
self.districtId = districtId
|
||||||
|
self.districtName = districtName
|
||||||
|
self.districtType = districtType
|
||||||
|
|
||||||
|
AIRepository.__init__(
|
||||||
|
self, mdip, mdport, esip, esport, dcFileNames,
|
||||||
|
serverId,
|
||||||
|
minChannel, maxChannel, dcSuffix)
|
||||||
|
self.setClientDatagram(0)
|
||||||
|
assert minChannel > districtId
|
||||||
|
if hasattr(self, 'setVerbose'):
|
||||||
|
if self.config.GetBool('verbose-airepository'):
|
||||||
|
self.setVerbose(1)
|
||||||
|
|
||||||
|
# Save the state server id
|
||||||
|
self.serverId = serverId
|
||||||
|
|
||||||
|
# Record the reason each client leaves the shard, according to
|
||||||
|
# the client.
|
||||||
|
self._avatarDisconnectReasons = {}
|
||||||
|
|
||||||
|
# A list of avIds to pretend to disconnect at the next poll
|
||||||
|
# cycle, for debugging purposes only.
|
||||||
|
self._debugDisconnectIds = []
|
||||||
|
|
||||||
|
# player avatars will increment and decrement this count
|
||||||
|
self._population = 0
|
||||||
|
|
||||||
|
# The AI State machine
|
||||||
|
self.fsm = ClassicFSM.ClassicFSM('AIDistrict',
|
||||||
|
[State.State('off',
|
||||||
|
self.enterOff,
|
||||||
|
self.exitOff,
|
||||||
|
['connect']),
|
||||||
|
State.State('connect',
|
||||||
|
self.enterConnect,
|
||||||
|
self.exitConnect,
|
||||||
|
['districtReset', 'noConnection',
|
||||||
|
# I added this because Skyler removed the transition to
|
||||||
|
# districtReset -- Joe
|
||||||
|
'playGame',
|
||||||
|
]),
|
||||||
|
State.State('districtReset',
|
||||||
|
self.enterDistrictReset,
|
||||||
|
self.exitDistrictReset,
|
||||||
|
['playGame','noConnection']),
|
||||||
|
State.State('playGame',
|
||||||
|
self.enterPlayGame,
|
||||||
|
self.exitPlayGame,
|
||||||
|
['noConnection']),
|
||||||
|
State.State('noConnection',
|
||||||
|
self.enterNoConnection,
|
||||||
|
self.exitNoConnection,
|
||||||
|
['connect'])],
|
||||||
|
# initial state
|
||||||
|
'off',
|
||||||
|
# final state
|
||||||
|
'off',
|
||||||
|
)
|
||||||
|
|
||||||
|
self.fsm.enterInitialState()
|
||||||
|
|
||||||
|
self.fsm.request("connect")
|
||||||
|
|
||||||
|
def uniqueName(self, desc):
|
||||||
|
return desc+"-"+str(self.districtId)
|
||||||
|
|
||||||
|
def getGameDoId(self):
|
||||||
|
self.notify.error('derived must override')
|
||||||
|
|
||||||
|
def incrementPopulation(self):
|
||||||
|
self._population += 1
|
||||||
|
def decrementPopulation(self):
|
||||||
|
if __dev__:
|
||||||
|
assert self._population > 0
|
||||||
|
self._population = max(0, self._population - 1)
|
||||||
|
|
||||||
|
def getPopulation(self):
|
||||||
|
if simbase.fakeDistrictPopulations:
|
||||||
|
if not hasattr(self, '_fakePopulation'):
|
||||||
|
import random
|
||||||
|
self._fakePopulation = random.randrange(1000)
|
||||||
|
return self._fakePopulation
|
||||||
|
return self._population
|
||||||
|
|
||||||
|
def printPopulationToLog(self, task):
|
||||||
|
self.notify.info("district-name %s | district-id %s | population %s" % (self.districtName, self.districtId, self._population))
|
||||||
|
return Task.again
|
||||||
|
|
||||||
|
# check if this is a player avatar in a location where they should not be
|
||||||
|
def _isValidPlayerLocation(self, parentId, zoneId):
|
||||||
|
return True
|
||||||
|
|
||||||
|
#### Init ####
|
||||||
|
|
||||||
|
def writeServerEvent(self, eventType, who, description):
|
||||||
|
AIRepository.writeServerEvent(self, eventType, who, description,
|
||||||
|
serverId=self.districtId)
|
||||||
|
|
||||||
|
#### DistrictReset ####
|
||||||
|
def enterDistrictReset(self):
|
||||||
|
self.handler = self.handleDistrictReset
|
||||||
|
self.deleteDistrict(self.districtId)
|
||||||
|
|
||||||
|
def exitDistrictReset(self):
|
||||||
|
self.handler = None
|
||||||
|
|
||||||
|
def handleDistrictReset(self, msgType, di):
|
||||||
|
if msgType == STATESERVER_OBJECT_DELETE_RAM:
|
||||||
|
doId = di.getUint32()
|
||||||
|
self.notify.info("Got request to delete doId: " +str(doId))
|
||||||
|
if(doId == self.districtId):
|
||||||
|
self.fsm.request("playGame")
|
||||||
|
elif msgType == STATESERVER_OBJECT_NOTFOUND:
|
||||||
|
doId = di.getUint32()
|
||||||
|
self.notify.info("Got Not Found For doId: " +str(doId))
|
||||||
|
if(doId == self.districtId):
|
||||||
|
self.fsm.request("playGame")
|
||||||
|
else:
|
||||||
|
self.handleMessageType(msgType, di)
|
||||||
|
|
||||||
|
#### DistrictReset ####
|
||||||
|
def enterPlayGame(self):
|
||||||
|
self._zoneDataStore = AIZoneDataStore()
|
||||||
|
AIRepository.enterPlayGame(self)
|
||||||
|
if simbase.config.GetBool('game-server-tests', 0):
|
||||||
|
from otp.distributed import DistributedTestObjectAI
|
||||||
|
self.testObject = DistributedTestObjectAI.DistributedTestObjectAI(self)
|
||||||
|
self.testObject.generateOtpObject(self.getGameDoId(), 3)
|
||||||
|
|
||||||
|
taskMgr.doMethodLater(300, self.printPopulationToLog, self.uniqueName("printPopulationTask"))
|
||||||
|
|
||||||
|
|
||||||
|
def getZoneDataStore(self):
|
||||||
|
"""This will crash (as designed) if called outside of the PlayGame state."""
|
||||||
|
return self._zoneDataStore
|
||||||
|
|
||||||
|
def getRender(self, parentId, zoneId):
|
||||||
|
# distributed objects should call getRender on themselves rather than
|
||||||
|
# call this function. Only call this for zones that are actively being
|
||||||
|
# used, otherwise the zone data will be destroyed before this function
|
||||||
|
# returns
|
||||||
|
zd = AIZoneData(self, parentId, zoneId)
|
||||||
|
render = zd.getRender()
|
||||||
|
zd.destroy()
|
||||||
|
return render
|
||||||
|
|
||||||
|
def getNonCollidableParent(self, parentId, zoneId):
|
||||||
|
# distributed objects should call getNonCollidableParent on themselves rather than
|
||||||
|
# call this function. Only call this for zones that are actively being
|
||||||
|
# used, otherwise the zone data will be destroyed before this function
|
||||||
|
# returns
|
||||||
|
zd = AIZoneData(self, parentId, zoneId)
|
||||||
|
ncParent = zd.getNonCollidableParent()
|
||||||
|
zd.destroy()
|
||||||
|
return ncParent
|
||||||
|
|
||||||
|
def getCollTrav(self, parentId, zoneId, *args, **kArgs):
|
||||||
|
# see comment in getRender
|
||||||
|
zd = AIZoneData(self, parentId, zoneId)
|
||||||
|
collTrav = zd.getCollTrav(*args, **kArgs)
|
||||||
|
zd.destroy()
|
||||||
|
return collTrav
|
||||||
|
|
||||||
|
def getParentMgr(self, parentId, zoneId):
|
||||||
|
# see comment in getRender
|
||||||
|
zd = AIZoneData(self, parentId, zoneId)
|
||||||
|
parentMgr = zd.getParentMgr()
|
||||||
|
zd.destroy()
|
||||||
|
return parentMgr
|
||||||
|
|
||||||
|
def exitPlayGame(self):
|
||||||
|
if simbase.config.GetBool('game-server-tests', 0):
|
||||||
|
self.testObject.requestDelete()
|
||||||
|
del self.testObject
|
||||||
|
self._zoneDataStore.destroy()
|
||||||
|
del self._zoneDataStore
|
||||||
|
taskMgr.remove(self.uniqueName("printPopulationTask"))
|
||||||
|
AIRepository.exitPlayGame(self)
|
||||||
|
|
||||||
|
#### connect #####
|
||||||
|
def enterConnect(self):
|
||||||
|
self.handler = self.handleConnect
|
||||||
|
self.lastMessageTime = 0
|
||||||
|
|
||||||
|
self.connect([self.mdurl],
|
||||||
|
successCallback = self._connected,
|
||||||
|
failureCallback = self._failedToConnect)
|
||||||
|
|
||||||
|
def _failedToConnect(self, statusCode, statusString):
|
||||||
|
self.fsm.request("noConnection")
|
||||||
|
|
||||||
|
def _connected(self):
|
||||||
|
# Register our channel
|
||||||
|
self.setConnectionName(self.districtName)
|
||||||
|
AIRepository._connected(self)
|
||||||
|
self.registerShardDownMessage(self.serverId)
|
||||||
|
if self.districtType is not None:
|
||||||
|
self.fsm.request("districtReset")
|
||||||
|
|
||||||
|
def _handleValidDistrictDown(self, msgType, di):
|
||||||
|
downDistrictId = di.getUint32()
|
||||||
|
if (downDistrictId != self.districtId):
|
||||||
|
self.notify.error("Tried to bring down " +
|
||||||
|
str(self.districtId) +
|
||||||
|
" but " +
|
||||||
|
str(downDistrictId) +
|
||||||
|
" came down instead!")
|
||||||
|
else:
|
||||||
|
# We don't really need to do anything here.
|
||||||
|
pass
|
||||||
|
|
||||||
|
def _handleIgnorableObjectDelete(self, msgType, di):
|
||||||
|
doId = di.getUint32()
|
||||||
|
self.notify.debug("Ignoring request to delete doId: " +
|
||||||
|
str(doId))
|
||||||
|
|
||||||
|
def _handleValidDistrictUp(self, msgType, di):
|
||||||
|
if msgType == STATESERVER_DISTRICT_UP:
|
||||||
|
upDistrictId = di.getUint32()
|
||||||
|
if (upDistrictId != self.districtId):
|
||||||
|
self.notify.error("Tried to bring up " +
|
||||||
|
str(self.districtId) +
|
||||||
|
" but " +
|
||||||
|
str(downDistrictId) +
|
||||||
|
" came up instead!")
|
||||||
|
else:
|
||||||
|
self.notify.info("District %s %s is up. Creating objects..." %
|
||||||
|
(self.districtId, self.districtName))
|
||||||
|
self.fsm.request("playGame")
|
||||||
|
|
||||||
|
def exitConnect(self):
|
||||||
|
self.handler = None
|
||||||
|
# Clean up the create district tasks
|
||||||
|
taskMgr.remove(self.uniqueName("newDistrictWait"))
|
||||||
|
del self.lastMessageTime
|
||||||
|
|
||||||
|
def readerPollUntilEmpty(self, task):
|
||||||
|
# This overrides AIRepository.readerPollUntilEmpty()
|
||||||
|
# to provide an additional debugging hook.
|
||||||
|
|
||||||
|
while self._debugDisconnectIds:
|
||||||
|
avId = self._debugDisconnectIds.pop()
|
||||||
|
self._doDebugDisconnectAvatar(avId)
|
||||||
|
|
||||||
|
try:
|
||||||
|
return AIRepository.readerPollUntilEmpty(self, task)
|
||||||
|
except Exception, e:
|
||||||
|
appendStr(e, '\nSENDER ID: %s' % self.getAvatarIdFromSender())
|
||||||
|
raise
|
||||||
|
|
||||||
|
def handleReaderOverflow(self):
|
||||||
|
# may as well delete the shard at this point
|
||||||
|
self.deleteDistrict(self.districtId)
|
||||||
|
raise StandardError, ("incoming-datagram buffer overflowed, "
|
||||||
|
"aborting AI process")
|
||||||
|
|
||||||
|
##### General Purpose functions #####
|
||||||
|
|
||||||
|
def getAvatarExitEvent(self, avId):
|
||||||
|
return ("districtExit-" + str(avId))
|
||||||
|
|
||||||
|
def debugDisconnectAvatar(self, avId):
|
||||||
|
# This function will pretend to disconnect the indicated
|
||||||
|
# avatar at the next poll cycle, as if the avatar suddenly
|
||||||
|
# disconnected. This is for the purposes of debugging only.
|
||||||
|
# It makes the AI totally forget who this avatar is, but the
|
||||||
|
# avatar is still connected to the server.
|
||||||
|
self._debugDisconnectIds.append(avId)
|
||||||
|
|
||||||
|
def _doDebugDisconnectAvatar(self, avId):
|
||||||
|
obj = self.doId2do.get(avId)
|
||||||
|
if obj:
|
||||||
|
self.deleteDistObject(obj)
|
||||||
|
self._announceDistObjExit(avId)
|
||||||
|
|
||||||
|
def _announceDistObjExit(self, avId):
|
||||||
|
# This announces the exiting of this particular avatar
|
||||||
|
messenger.send(self.getAvatarExitEvent(avId))
|
||||||
|
|
||||||
|
# This announces generally that an avatar has left.
|
||||||
|
#messenger.send("avatarExited")
|
||||||
|
|
||||||
|
# Now we don't need to store the disconnect reason any more.
|
||||||
|
try:
|
||||||
|
del self._avatarDisconnectReasons[avId]
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
|
def setAvatarDisconnectReason(self, avId, disconnectReason):
|
||||||
|
# This is told us by the client just before he disconnects.
|
||||||
|
self._avatarDisconnectReasons[avId] = disconnectReason
|
||||||
|
|
||||||
|
def getAvatarDisconnectReason(self, avId):
|
||||||
|
# Returns the reason (as reported by the client) for an
|
||||||
|
# avatar's unexpected exit, or 0 if the reason is unknown. It
|
||||||
|
# is only valid to query this during the handler for the
|
||||||
|
# avatar's unexpected-exit event.
|
||||||
|
return self._avatarDisconnectReasons.get(avId, 0)
|
||||||
|
|
||||||
|
def _handleUnexpectedDistrictDown(self, di):
|
||||||
|
# Get the district Id
|
||||||
|
downDistrict = di.getUint32()
|
||||||
|
if downDistrict == self.districtId:
|
||||||
|
self.notify.warning("Somebody brought my district(" +
|
||||||
|
str(self.districtId) +
|
||||||
|
") down! I'm shutting down!")
|
||||||
|
sys.exit()
|
||||||
|
else:
|
||||||
|
self.notify.warning("Weird... My district is " +
|
||||||
|
str(self.districtId) +
|
||||||
|
" and I just got a message that district " +
|
||||||
|
str(downDistrict) +
|
||||||
|
" is going down. I'm ignoring it."
|
||||||
|
)
|
||||||
|
|
||||||
|
def _handleUnexpectedDistrictUp(self, di):
|
||||||
|
# Get the district Id
|
||||||
|
upDistrict = di.getUint32()
|
||||||
|
if upDistrict == self.districtId:
|
||||||
|
self.notify.warning("Somebody brought my district(" +
|
||||||
|
str(self.districtId) +
|
||||||
|
") up! I'm shutting down!")
|
||||||
|
sys.exit()
|
||||||
|
else:
|
||||||
|
self.notify.warning("Weird... My district is " +
|
||||||
|
str(self.districtId) +
|
||||||
|
" and I just got a message that district " +
|
||||||
|
str(upDistrict) +
|
||||||
|
" is coming up. I'm ignoring it."
|
||||||
|
)
|
||||||
|
|
||||||
|
def _handleMakeFriendsReply(self, di):
|
||||||
|
result = di.getUint8()
|
||||||
|
context = di.getUint32()
|
||||||
|
messenger.send("makeFriendsReply", [result, context])
|
||||||
|
|
||||||
|
def _handleRequestSecretReply(self, di):
|
||||||
|
result = di.getUint8()
|
||||||
|
secret = di.getString()
|
||||||
|
requesterId = di.getUint32()
|
||||||
|
messenger.send("requestSecretReply", [result, secret, requesterId])
|
||||||
|
|
||||||
|
def _handleSubmitSecretReply(self, di):
|
||||||
|
result = di.getUint8()
|
||||||
|
secret = di.getString()
|
||||||
|
requesterId = di.getUint32()
|
||||||
|
avId = di.getUint32()
|
||||||
|
self.writeServerEvent('entered-secret', requesterId, '%s|%s|%s' % (result, secret, avId))
|
||||||
|
messenger.send("submitSecretReply", [result, secret, requesterId, avId])
|
||||||
|
|
||||||
|
def registerShardDownMessage(self, stateserverid):
|
||||||
|
datagram = PyDatagram()
|
||||||
|
datagram.addServerHeader(
|
||||||
|
stateserverid, self.ourChannel, STATESERVER_SHARD_REST)
|
||||||
|
datagram.addChannel(self.ourChannel)
|
||||||
|
# schedule for execution on socket close
|
||||||
|
self.addPostSocketClose(datagram)
|
||||||
|
|
||||||
|
def sendSetZone(self, distobj, zoneId):
|
||||||
|
datagram = PyDatagram()
|
||||||
|
datagram.addServerHeader(
|
||||||
|
distobj.doId, self.ourChannel, STATESERVER_OBJECT_SET_ZONE)
|
||||||
|
# Add the zone parent id
|
||||||
|
# HACK:
|
||||||
|
parentId = oldParentId = self.districtId
|
||||||
|
datagram.addUint32(parentId)
|
||||||
|
# Put in the zone id
|
||||||
|
datagram.addUint32(zoneId)
|
||||||
|
# Send it
|
||||||
|
self.send(datagram)
|
||||||
|
# The servers don't inform us of this zone change, because we're the
|
||||||
|
# one that requested it. Update immediately.
|
||||||
|
# TODO: pass in the old parent and old zone
|
||||||
|
distobj.setLocation(parentId, zoneId) #, oldParentId, distobj.zoneId)
|
||||||
|
|
||||||
|
def deleteDistrict(self, districtId):
|
||||||
|
# Create a message
|
||||||
|
datagram = PyDatagram()
|
||||||
|
datagram.addServerHeader(
|
||||||
|
self.serverId, self.ourChannel, STATESERVER_OBJECT_DELETE_RAM)
|
||||||
|
# The Id of the object in question
|
||||||
|
datagram.addUint32(districtId)
|
||||||
|
# Send the message
|
||||||
|
self.send(datagram)
|
||||||
|
# Make sure the message gets there.
|
||||||
|
self.flush()
|
||||||
|
|
||||||
|
def makeFriends(self, avatarAId, avatarBId, flags, context):
|
||||||
|
"""
|
||||||
|
Requests to make a friendship between avatarA and avatarB with
|
||||||
|
the indicated flags (or upgrade an existing friendship with
|
||||||
|
the indicated flags). The context is any arbitrary 32-bit
|
||||||
|
integer. When the friendship is made, or the operation fails,
|
||||||
|
the "makeFriendsReply" event is generated, with two
|
||||||
|
parameters: an integer result code, and the supplied context.
|
||||||
|
"""
|
||||||
|
datagram = PyDatagram()
|
||||||
|
datagram.addServerHeader(
|
||||||
|
DBSERVER_ID, self.ourChannel, DBSERVER_MAKE_FRIENDS)
|
||||||
|
|
||||||
|
# Indicate the two avatars who are making friends
|
||||||
|
datagram.addUint32(avatarAId)
|
||||||
|
datagram.addUint32(avatarBId)
|
||||||
|
datagram.addUint8(flags)
|
||||||
|
datagram.addUint32(context)
|
||||||
|
self.send(datagram)
|
||||||
|
|
||||||
|
def requestSecret(self, requesterId):
|
||||||
|
"""
|
||||||
|
Requests a "secret" from the database server. This is a
|
||||||
|
unique string that will be associated with the indicated
|
||||||
|
requesterId, for the purposes of authenticating true-life
|
||||||
|
friends.
|
||||||
|
|
||||||
|
When the secret is ready, a "requestSecretReply" message will
|
||||||
|
be thrown with three parameters: the result code (0 or 1,
|
||||||
|
indicating failure or success), the generated secret, and the
|
||||||
|
requesterId again.
|
||||||
|
"""
|
||||||
|
datagram = PyDatagram()
|
||||||
|
datagram.addServerHeader(
|
||||||
|
DBSERVER_ID,self.ourChannel,DBSERVER_REQUEST_SECRET)
|
||||||
|
|
||||||
|
# Indicate the number we want to associate with the new secret.
|
||||||
|
datagram.addUint32(requesterId)
|
||||||
|
# Send it off!
|
||||||
|
self.send(datagram)
|
||||||
|
|
||||||
|
def submitSecret(self, requesterId, secret):
|
||||||
|
"""
|
||||||
|
Submits a "secret" back to the database server for validation.
|
||||||
|
This attempts to match the indicated string, entered by the
|
||||||
|
user, to a string returned by a previous call to
|
||||||
|
requestSecret().
|
||||||
|
|
||||||
|
When the response comes back from the server, a
|
||||||
|
"submitSecretReply" message will be thrown with four
|
||||||
|
parameters: the result code (0 or 1, indicating failure or
|
||||||
|
success), the secret again, the requesterId again, and the
|
||||||
|
number associated with the original secret (that is, the
|
||||||
|
original requesterId).
|
||||||
|
"""
|
||||||
|
datagram = PyDatagram()
|
||||||
|
datagram.addServerHeader(
|
||||||
|
DBSERVER_ID, self.ourChannel, DBSERVER_SUBMIT_SECRET)
|
||||||
|
# Pass in our identifying number, and the string.
|
||||||
|
datagram.addUint32(requesterId)
|
||||||
|
datagram.addString(secret)
|
||||||
|
self.send(datagram)
|
||||||
|
|
||||||
|
def replaceMethod(self, oldMethod, newFunction):
|
||||||
|
return 0
|
19
otp/src/ai/AIInterestHandles.py
Normal file
19
otp/src/ai/AIInterestHandles.py
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
|
||||||
|
# AIInterestHandles
|
||||||
|
#
|
||||||
|
# These are reserved interest handle id's to be used with calls
|
||||||
|
# to AIRepository.addInterestToConnection(). The high bit (16th) is set
|
||||||
|
# on all handle id's assigned by this function call so as not to collide
|
||||||
|
# with handles assigned by the Client.
|
||||||
|
|
||||||
|
# Pirates
|
||||||
|
PIRATES_CARDGAME = 1
|
||||||
|
PIRATES_CREW = 2
|
||||||
|
PIRATES_GUILD = 3
|
||||||
|
PIRATES_FRIENDS = 4
|
||||||
|
|
||||||
|
PIRATES_BAND = 5
|
||||||
|
PIRATES_PVP_RESPAWN = 6
|
||||||
|
PIRATES_TREASUREMAP = 7
|
||||||
|
|
||||||
|
PIRATES_SHIPPVP = 8
|
118
otp/src/ai/AIMsgTypes.py
Normal file
118
otp/src/ai/AIMsgTypes.py
Normal file
|
@ -0,0 +1,118 @@
|
||||||
|
"""
|
||||||
|
AIMsgTypes module:
|
||||||
|
Contains AI specific network message types
|
||||||
|
"""
|
||||||
|
|
||||||
|
from otp.distributed.OtpDoGlobals import *
|
||||||
|
from direct.showbase.PythonUtil import invertDictLossless
|
||||||
|
|
||||||
|
# top level object (root):
|
||||||
|
OTP_SERVER_ROOT_DO_ID = 4007
|
||||||
|
|
||||||
|
CHANNEL_CLIENT_BROADCAST = 4014
|
||||||
|
|
||||||
|
BAD_CHANNEL_ID = 0 # 0xffffffffffffffff # -1
|
||||||
|
BAD_ZONE_ID = 0 # 0xffffffff # -1
|
||||||
|
BAD_DO_ID = 0 # 0xffffffff # -1
|
||||||
|
|
||||||
|
# Control Transactions
|
||||||
|
CONTROL_MESSAGE = 4001
|
||||||
|
CONTROL_SET_CHANNEL = 2001
|
||||||
|
CONTROL_REMOVE_CHANNEL = 2002
|
||||||
|
|
||||||
|
CONTROL_SET_CON_NAME = 2004
|
||||||
|
CONTROL_SET_CON_URL = 2005
|
||||||
|
|
||||||
|
CONTROL_ADD_RANGE = 2008
|
||||||
|
CONTROL_REMOVE_RANGE = 2009
|
||||||
|
CONTROL_ADD_POST_REMOVE = 2010 # ADD A MESSAGE TO THE CLOSING EVENT ON A DIRECTOR SOCKET
|
||||||
|
CONTROL_CLEAR_POST_REMOVE = 2011 # CLEAR ALL THE EVENTS..
|
||||||
|
|
||||||
|
AIMsgName2Id = {
|
||||||
|
# State Server Transactions
|
||||||
|
'STATESERVER_OBJECT_GENERATE_WITH_REQUIRED': 2001,
|
||||||
|
'STATESERVER_OBJECT_GENERATE_WITH_REQUIRED_OTHER': 2003,
|
||||||
|
'STATESERVER_OBJECT_UPDATE_FIELD': 2004,
|
||||||
|
'STATESERVER_OBJECT_UPDATE_FIELD_MULTIPLE': 2005,
|
||||||
|
'STATESERVER_OBJECT_DELETE_RAM': 2007,
|
||||||
|
'STATESERVER_OBJECT_SET_ZONE': 2008,
|
||||||
|
'STATESERVER_OBJECT_CHANGE_ZONE': 2009,
|
||||||
|
'STATESERVER_OBJECT_NOTFOUND': 2015,
|
||||||
|
|
||||||
|
'STATESERVER_QUERY_OBJECT_ALL': 2020,
|
||||||
|
'STATESERVER_QUERY_ZONE_OBJECT_ALL': 2021,
|
||||||
|
'STATESERVER_OBJECT_LOCATE': 2022,
|
||||||
|
'STATESERVER_OBJECT_LOCATE_RESP': 2023,
|
||||||
|
'STATESERVER_OBJECT_QUERY_FIELD': 2024, # See 2062
|
||||||
|
'STATESERVER_QUERY_OBJECT_ALL_RESP': 2030,
|
||||||
|
|
||||||
|
'STATESERVER_SHARD_REST': 2061,
|
||||||
|
'STATESERVER_ADD_AI_RECV': 2045,
|
||||||
|
'STATESERVER_QUERY_ZONE_OBJECT_ALL_DONE': 2046,
|
||||||
|
'STATESERVER_OBJECT_CREATE_WITH_REQUIRED_CONTEXT': 2050,
|
||||||
|
'STATESERVER_OBJECT_CREATE_WITH_REQUIR_OTHER_CONTEXT': 2051,
|
||||||
|
'STATESERVER_OBJECT_CREATE_WITH_REQUIRED_CONTEXT_RESP': 2052,
|
||||||
|
'STATESERVER_OBJECT_CREATE_WITH_REQUIR_OTHER_CONTEXT_RESP': 2053,
|
||||||
|
'STATESERVER_OBJECT_DELETE_DISK': 2060,
|
||||||
|
'STATESERVER_OBJECT_QUERY_FIELD_RESP': 2062, # See 2024
|
||||||
|
|
||||||
|
'STATESERVER_OBJECT_ENTERZONE_WITH_REQUIRED_OTHER': 2066,
|
||||||
|
'STATESERVER_OBJECT_ENTER_AI_RECV': 2067,
|
||||||
|
'STATESERVER_OBJECT_LEAVING_AI_INTEREST': 2033, # This is the new name for 2033
|
||||||
|
|
||||||
|
'STATESERVER_OBJECT_ENTER_OWNER_RECV': 2068, # new obj with owner
|
||||||
|
'STATESERVER_OBJECT_CHANGE_OWNER_RECV': 2069, # obj has new owner
|
||||||
|
'STATESERVER_OBJECT_SET_OWNER_RECV': 2070, # ???
|
||||||
|
|
||||||
|
'STATESERVER_OBJECT_QUERY_FIELDS': 2080,
|
||||||
|
'STATESERVER_OBJECT_QUERY_FIELDS_RESP': 2081,
|
||||||
|
'STATESERVER_OBJECT_QUERY_FIELDS_STRING': 2082,
|
||||||
|
'STATESERVER_OBJECT_QUERY_MANAGING_AI': 2083, # Should not be received by python code (it's for roger's server)
|
||||||
|
'STATESERVER_BOUNCE_MESSAGE': 2086,
|
||||||
|
|
||||||
|
'STATESERVER_QUERY_OBJECT_CHILDREN_LOCAL': 2087,
|
||||||
|
'STATESERVER_QUERY_OBJECT_CHILDREN_LOCAL_DONE': 2089,
|
||||||
|
'STATESERVER_QUERY_OBJECT_CHILDREN_RESP': 2087,
|
||||||
|
|
||||||
|
'ACCOUNT_AVATAR_USAGE': 3005, # Avatar online or offline
|
||||||
|
'ACCOUNT_ACCOUNT_USAGE': 3006, # Account login or log off
|
||||||
|
|
||||||
|
'CLIENT_AGENT_OPEN_CHANNEL': 3104,
|
||||||
|
'CLIENT_AGENT_CLOSE_CHANNEL': 3105,
|
||||||
|
'CLIENT_AGENT_SET_INTEREST': 3106,
|
||||||
|
'CLIENT_AGENT_REMOVE_INTEREST': 3107,
|
||||||
|
|
||||||
|
|
||||||
|
'CHANNEL_PUPPET_ACTION': 4004, # Account and Avatar online or offline
|
||||||
|
|
||||||
|
# direct-to-database-server transactions
|
||||||
|
'DBSERVER_MAKE_FRIENDS': 1017,
|
||||||
|
'DBSERVER_MAKE_FRIENDS_RESP': 1031,
|
||||||
|
'DBSERVER_REQUEST_SECRET': 1025,
|
||||||
|
'DBSERVER_REQUEST_SECRET_RESP': 1026,
|
||||||
|
'DBSERVER_SUBMIT_SECRET': 1027,
|
||||||
|
'DBSERVER_SUBMIT_SECRET_RESP': 1028,
|
||||||
|
|
||||||
|
'DBSERVER_CREATE_STORED_OBJECT': 1003,
|
||||||
|
'DBSERVER_CREATE_STORED_OBJECT_RESP': 1004,
|
||||||
|
'DBSERVER_DELETE_STORED_OBJECT': 1008,
|
||||||
|
|
||||||
|
'DBSERVER_GET_STORED_VALUES': 1012,
|
||||||
|
'DBSERVER_GET_STORED_VALUES_RESP': 1013,
|
||||||
|
'DBSERVER_SET_STORED_VALUES': 1014,
|
||||||
|
|
||||||
|
'SERVER_PING': 5002,
|
||||||
|
}
|
||||||
|
|
||||||
|
# create id->name table for debugging
|
||||||
|
AIMsgId2Names = invertDictLossless(AIMsgName2Id)
|
||||||
|
|
||||||
|
# put msg names in module scope, assigned to msg value
|
||||||
|
for name, value in AIMsgName2Id.items():
|
||||||
|
exec '%s = %s' % (name, value)
|
||||||
|
del name, value
|
||||||
|
|
||||||
|
# The ID number of the database server. The above direct-to-dbserver
|
||||||
|
# transactions are sent to this ID.
|
||||||
|
DBSERVER_ID = 4003
|
||||||
|
|
1913
otp/src/ai/AIRepository.py
Normal file
1913
otp/src/ai/AIRepository.py
Normal file
File diff suppressed because it is too large
Load diff
245
otp/src/ai/AIZoneData.py
Normal file
245
otp/src/ai/AIZoneData.py
Normal file
|
@ -0,0 +1,245 @@
|
||||||
|
from pandac.PandaModules import *
|
||||||
|
from direct.distributed import ParentMgr
|
||||||
|
from direct.directnotify.DirectNotifyGlobal import directNotify
|
||||||
|
from direct.task import Task
|
||||||
|
from direct.showbase import LeakDetectors
|
||||||
|
from otp.otpbase import OTPGlobals
|
||||||
|
import random
|
||||||
|
|
||||||
|
class AIZoneData:
|
||||||
|
"""This is a proxy to the AIZoneDataObj for a particular zone. When all
|
||||||
|
AIZoneData objects for a zone have been destroyed, the AIZoneDataObj
|
||||||
|
object for that zone is destroyed as well."""
|
||||||
|
notify = directNotify.newCategory('AIZoneData')
|
||||||
|
|
||||||
|
def __init__(self, air, parentId, zoneId):
|
||||||
|
self._air = air
|
||||||
|
self._parentId = parentId
|
||||||
|
self._zoneId = zoneId
|
||||||
|
self._data = self._air.getZoneDataStore().getDataForZone(self._parentId, self._zoneId)
|
||||||
|
def destroy(self):
|
||||||
|
del self._data
|
||||||
|
self._air.getZoneDataStore().releaseDataForZone(self._parentId, self._zoneId)
|
||||||
|
del self._zoneId
|
||||||
|
del self._parentId
|
||||||
|
del self._air
|
||||||
|
def __getattr__(self, attr):
|
||||||
|
# provide direct access to AIZoneDataStore methods on this object
|
||||||
|
return getattr(self._data, attr)
|
||||||
|
|
||||||
|
class AIZoneDataObj:
|
||||||
|
"""
|
||||||
|
This class stores per-zone information on an AI district. Only one of these
|
||||||
|
exists for a particular zone, and it only exists if somebody requested it.
|
||||||
|
"""
|
||||||
|
notify = directNotify.newCategory('AIZoneDataObj')
|
||||||
|
|
||||||
|
DefaultCTravName = 'default'
|
||||||
|
|
||||||
|
def __init__(self, parentId, zoneId):
|
||||||
|
assert self.notify.debug(
|
||||||
|
'AIZoneDataObj.__init__(%s, %s)' % (parentId, zoneId))
|
||||||
|
self._parentId = parentId
|
||||||
|
self._zoneId = zoneId
|
||||||
|
self._refCount = 0
|
||||||
|
self._collTravs = {}
|
||||||
|
self._collTravsStarted = set()
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
output = str(self._collTravs)
|
||||||
|
output += '\n'
|
||||||
|
totalColliders = 0
|
||||||
|
totalTraversers = 0
|
||||||
|
for currCollTrav in self._collTravs.values():
|
||||||
|
totalTraversers += 1
|
||||||
|
totalColliders += currCollTrav.getNumColliders()
|
||||||
|
output += 'Num traversers: %s Num total colliders: %s'%(totalTraversers,totalColliders)
|
||||||
|
return output
|
||||||
|
|
||||||
|
def _incRefCount(self):
|
||||||
|
self._refCount += 1
|
||||||
|
def _decRefCount(self):
|
||||||
|
self._refCount -= 1
|
||||||
|
def _getRefCount(self):
|
||||||
|
return self._refCount
|
||||||
|
|
||||||
|
def destroy(self):
|
||||||
|
assert self.notify.debug(
|
||||||
|
'AIZoneDataObj.destroy(%s, %s)' % (self._parentId, self._zoneId))
|
||||||
|
for name in list(self._collTravsStarted):
|
||||||
|
self.stopCollTrav(cTravName=name)
|
||||||
|
del self._collTravsStarted
|
||||||
|
del self._collTravs
|
||||||
|
if hasattr(self, '_nonCollidableParent'):
|
||||||
|
self._nonCollidableParent.removeNode()
|
||||||
|
del self._nonCollidableParent
|
||||||
|
if hasattr(self, '_render'):
|
||||||
|
if hasattr(self, '_renderLeakDetector'):
|
||||||
|
self._renderLeakDetector.destroy()
|
||||||
|
del self._renderLeakDetector
|
||||||
|
self._render.removeNode()
|
||||||
|
del self._render
|
||||||
|
if hasattr(self, '_parentMgr'):
|
||||||
|
self._parentMgr.destroy()
|
||||||
|
del self._parentMgr
|
||||||
|
del self._zoneId
|
||||||
|
del self._parentId
|
||||||
|
|
||||||
|
def getLocation(self):
|
||||||
|
return self._parentId, self._zoneId
|
||||||
|
|
||||||
|
def getRender(self):
|
||||||
|
if not hasattr(self, '_render'):
|
||||||
|
self._render = NodePath('render-%s-%s' % (self._parentId, self._zoneId))
|
||||||
|
if config.GetBool('leak-scene-graph', 0):
|
||||||
|
self._renderLeakDetector = LeakDetectors.SceneGraphLeakDetector(self._render)
|
||||||
|
return self._render
|
||||||
|
|
||||||
|
def getNonCollidableParent(self):
|
||||||
|
# this is a node for things that can't be collided against, so that that collision traverser
|
||||||
|
# only has to check once against this node. It's up to the show code to make sure that
|
||||||
|
# no collidables are put under this node
|
||||||
|
if not hasattr(self, '_nonCollidableParent'):
|
||||||
|
render = self.getRender()
|
||||||
|
self._nonCollidableParent = render.attachNewNode('nonCollidables')
|
||||||
|
if __dev__:
|
||||||
|
assert self._nonCollidableParent.getCollideMask() == BitMask32().allOff(),\
|
||||||
|
"collidable geometry under non-collidable parent node for location "\
|
||||||
|
"(%s,%s)" % (self._parentId, self._zoneId)
|
||||||
|
return self._nonCollidableParent
|
||||||
|
|
||||||
|
def getParentMgr(self):
|
||||||
|
if not hasattr(self, '_parentMgr'):
|
||||||
|
self._parentMgr = ParentMgr.ParentMgr()
|
||||||
|
self._parentMgr.registerParent(OTPGlobals.SPHidden, hidden)
|
||||||
|
self._parentMgr.registerParent(OTPGlobals.SPRender, self.getRender())
|
||||||
|
return self._parentMgr
|
||||||
|
|
||||||
|
def hasCollTrav(self, name=None):
|
||||||
|
if name is None:
|
||||||
|
name = AIZoneDataObj.DefaultCTravName
|
||||||
|
return name in self._collTravs
|
||||||
|
|
||||||
|
def getCollTrav(self, name=None):
|
||||||
|
#assert self.notify.debug('getCollTrav(%s, %s)' % (self._parentId, self._zoneId))
|
||||||
|
if name is None:
|
||||||
|
name = AIZoneDataObj.DefaultCTravName
|
||||||
|
if name not in self._collTravs:
|
||||||
|
self._collTravs[name] = CollisionTraverser('cTrav-%s-%s-%s' % (name, self._parentId, self._zoneId))
|
||||||
|
return self._collTravs[name]
|
||||||
|
def removeCollTrav(self, name):
|
||||||
|
if (self._collTravs.has_key(name)):
|
||||||
|
del self._collTravs[name]
|
||||||
|
|
||||||
|
def _getCTravTaskName(self, name=None):
|
||||||
|
if name is None:
|
||||||
|
name = AIZoneDataObj.DefaultCTravName
|
||||||
|
return 'collTrav-%s-%s-%s' % (name, self._parentId, self._zoneId)
|
||||||
|
|
||||||
|
def _doCollisions(self, task=None, topNode=None, cTravName=None):
|
||||||
|
render = self.getRender()
|
||||||
|
curTime = globalClock.getFrameTime()
|
||||||
|
render.setTag('lastTraverseTime', str(curTime))
|
||||||
|
if topNode is not None:
|
||||||
|
# make sure the topNode for collision traversal is a descendant of our render node
|
||||||
|
if not render.isAncestorOf(topNode):
|
||||||
|
self.notify.warning('invalid topNode for collision traversal in %s: %s' % (
|
||||||
|
self.getLocation(), topNode))
|
||||||
|
else:
|
||||||
|
topNode = render
|
||||||
|
|
||||||
|
if cTravName is None:
|
||||||
|
cTravName = AIZoneDataObj.DefaultCTravName
|
||||||
|
|
||||||
|
collTrav = self._collTravs[cTravName]
|
||||||
|
messenger.send('preColl-' + collTrav.getName())
|
||||||
|
collTrav.traverse(topNode)
|
||||||
|
messenger.send('postColl-' + collTrav.getName())
|
||||||
|
|
||||||
|
return Task.cont
|
||||||
|
|
||||||
|
def doCollTrav(self, topNode=None, cTravName=None):
|
||||||
|
# call this method to do a one-shot collision traversal (instead of starting up a task
|
||||||
|
# to traverse every frame)
|
||||||
|
assert self.notify.debug('doCollTrav(%s, %s)' % (self._parentId, self._zoneId))
|
||||||
|
self.getCollTrav(cTravName)
|
||||||
|
self._doCollisions(topNode=topNode, cTravName=cTravName)
|
||||||
|
|
||||||
|
def startCollTrav(self, respectPrevTransform=1, cTravName=None):
|
||||||
|
"""sets up and starts collision traverser for this zone.
|
||||||
|
Pass in zero for 'respectPrevTransform' to disable support for
|
||||||
|
tunneling/trailing sphere support. This will allow objects to
|
||||||
|
break through collision barriers, but may run faster -- see
|
||||||
|
drose for more info.
|
||||||
|
"""
|
||||||
|
if cTravName is None:
|
||||||
|
cTravName = AIZoneDataObj.DefaultCTravName
|
||||||
|
assert self.notify.debug(
|
||||||
|
'startCollTrav(%s, (%s, %s), %s)' % (cTravName, self._parentId, self._zoneId, respectPrevTransform))
|
||||||
|
if not cTravName in self._collTravsStarted:
|
||||||
|
# make sure we've got a collision traverser
|
||||||
|
self.getCollTrav(name=cTravName)
|
||||||
|
taskMgr.add(self._doCollisions, self._getCTravTaskName(name=cTravName),
|
||||||
|
priority=OTPGlobals.AICollisionPriority,
|
||||||
|
extraArgs=[self._zoneId])
|
||||||
|
self._collTravsStarted.add(cTravName)
|
||||||
|
assert self.notify.debug(
|
||||||
|
'adding %s collision traversal for (%s, %s)' % (cTravName, self._parentId, self._zoneId))
|
||||||
|
self.setRespectPrevTransform(respectPrevTransform, cTravName=cTravName)
|
||||||
|
|
||||||
|
def stopCollTrav(self, cTravName=None):
|
||||||
|
"""frees resources used by collision traverser for this zone"""
|
||||||
|
assert self.notify.debugStateCall(self)
|
||||||
|
if cTravName is None:
|
||||||
|
cTravName = AIZoneDataObj.DefaultCTravName
|
||||||
|
self.notify.debug('stopCollTrav(%s, %s, %s)' % (cTravName, self._parentId, self._zoneId))
|
||||||
|
if cTravName in self._collTravsStarted:
|
||||||
|
self.notify.info(
|
||||||
|
'removing %s collision traversal for (%s, %s)' % (cTravName, self._parentId, self._zoneId))
|
||||||
|
taskMgr.remove(self._getCTravTaskName(name=cTravName))
|
||||||
|
self._collTravsStarted.remove(cTravName)
|
||||||
|
|
||||||
|
def setRespectPrevTransform(self, flag, cTravName=None):
|
||||||
|
if cTravName is None:
|
||||||
|
cTravName = AIZoneDataObj.DefaultCTravName
|
||||||
|
self._collTravs[cTravName].setRespectPrevTransform(flag)
|
||||||
|
def getRespectPrevTransform(self, cTravName=None):
|
||||||
|
if cTravName is None:
|
||||||
|
cTravName = AIZoneDataObj.DefaultCTravName
|
||||||
|
return self._collTravs[cTravName].getRespectPrevTransform()
|
||||||
|
|
||||||
|
class AIZoneDataStore:
|
||||||
|
"""This class holds all of the AIZoneDataObj objects for a district."""
|
||||||
|
notify = directNotify.newCategory('AIZoneDataStore')
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
# table of (parentId, zoneId) -> AIZoneDataObj
|
||||||
|
self._zone2data = {}
|
||||||
|
def destroy(self):
|
||||||
|
for zone, data in self._zone2data.items():
|
||||||
|
data.destroy()
|
||||||
|
del self._zone2data
|
||||||
|
def hasDataForZone(self, parentId, zoneId):
|
||||||
|
key = (parentId, zoneId)
|
||||||
|
return key in self._zone2data
|
||||||
|
def getDataForZone(self, parentId, zoneId):
|
||||||
|
key = (parentId, zoneId)
|
||||||
|
if key not in self._zone2data:
|
||||||
|
self._zone2data[key] = AIZoneDataObj(parentId, zoneId)
|
||||||
|
self.printStats()
|
||||||
|
data = self._zone2data[key]
|
||||||
|
data._incRefCount()
|
||||||
|
return data
|
||||||
|
def releaseDataForZone(self, parentId, zoneId):
|
||||||
|
key = (parentId, zoneId)
|
||||||
|
data = self._zone2data[key]
|
||||||
|
data._decRefCount()
|
||||||
|
refCount = data._getRefCount()
|
||||||
|
assert (refCount >= 0)
|
||||||
|
if refCount == 0:
|
||||||
|
del self._zone2data[key]
|
||||||
|
data.destroy()
|
||||||
|
self.printStats()
|
||||||
|
def printStats(self):
|
||||||
|
self.notify.debug('%s zones have zone data allocated' % len(self._zone2data))
|
||||||
|
|
97
otp/src/ai/BanManagerAI.py
Normal file
97
otp/src/ai/BanManagerAI.py
Normal file
|
@ -0,0 +1,97 @@
|
||||||
|
#################################################################
|
||||||
|
# File: BanManagerAI.py
|
||||||
|
# Purpose: Module to ban avatars while inside the game and kick
|
||||||
|
# them out of the game
|
||||||
|
#################################################################
|
||||||
|
import urllib
|
||||||
|
import os
|
||||||
|
from pandac.PandaModules import HTTPClient, Ramfile
|
||||||
|
from direct.directnotify import DirectNotifyGlobal
|
||||||
|
|
||||||
|
class BanManagerAI:
|
||||||
|
notify = DirectNotifyGlobal.directNotify.newCategory("BanManagerAI")
|
||||||
|
|
||||||
|
# These URLS came from Alper Akture
|
||||||
|
# dev instance (but as of 7/1/2010 hooked to live disl)
|
||||||
|
# http://dnhdosapp01.wdig.com:8005/dis-hold/action/event
|
||||||
|
# qa instance
|
||||||
|
# http://qnhspapp02.wdig.com:8005/dis-hold/action/event
|
||||||
|
# live
|
||||||
|
# https://vapps.disl.starwave.com:8005/dis-hold/action/event
|
||||||
|
BanUrl = simbase.config.GetString("ban-base-url", "https://vapps.disl.starwave.com:8005/dis-hold/action/event")
|
||||||
|
App = simbase.config.GetString("ban-app-name", "TTWorldAI")
|
||||||
|
Product = simbase.config.GetString("ban-product", "Toontown")
|
||||||
|
EventName = simbase.config.GetString("ban-event-name", "tthackattempt")
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
"""Construct and initialize members."""
|
||||||
|
self.curBanRequestNum = 0
|
||||||
|
self.channels = {}
|
||||||
|
self.ramFiles = {}
|
||||||
|
|
||||||
|
def ban(self, avatarId, dislid, comment):
|
||||||
|
"""Ban the player"""
|
||||||
|
|
||||||
|
parameters = ""
|
||||||
|
parameters += "app=%s" % self.App
|
||||||
|
parameters += "&product=%s" % self.Product
|
||||||
|
parameters += "&user_id=%s" % dislid
|
||||||
|
parameters += "&event_name=%s" % self.EventName
|
||||||
|
commentWithAvatarId = "avId-%s " % avatarId
|
||||||
|
commentWithAvatarId += comment
|
||||||
|
parameters += "&comments=%s" % urllib.quote(str(commentWithAvatarId))
|
||||||
|
|
||||||
|
# get the base ban url from the environment variable first
|
||||||
|
baseUrlToUse = self.BanUrl
|
||||||
|
osBaseUrl = os.getenv("BAN_URL")
|
||||||
|
if osBaseUrl:
|
||||||
|
baseUrlToUse = osBaseUrl
|
||||||
|
fullUrl = baseUrlToUse + "?" + parameters
|
||||||
|
|
||||||
|
self.notify.info ("ban request %s dislid=%s comment=%s fullUrl=%s" % (self.curBanRequestNum, dislid, comment, fullUrl))
|
||||||
|
simbase.air.writeServerEvent('ban_request', avatarId, "%s|%s|%s" % (dislid, comment, fullUrl))
|
||||||
|
|
||||||
|
if simbase.config.GetBool('do-actual-ban',False):
|
||||||
|
newTaskName = "ban-task-%d" % self.curBanRequestNum
|
||||||
|
newTask = taskMgr.add(self.doBanUrlTask, newTaskName)
|
||||||
|
newTask.banRequestNum = self.curBanRequestNum
|
||||||
|
http = HTTPClient.getGlobalPtr()
|
||||||
|
channel = http.makeChannel(False) # hmm should we make true for a persistent connection?
|
||||||
|
self.channels [ self.curBanRequestNum] = channel
|
||||||
|
rf = Ramfile()
|
||||||
|
self.ramFiles [ self.curBanRequestNum] = rf
|
||||||
|
|
||||||
|
channel.beginGetDocument(fullUrl)
|
||||||
|
channel.downloadToRam(rf)
|
||||||
|
|
||||||
|
self.curBanRequestNum += 1
|
||||||
|
|
||||||
|
def cleanupBanReq(self, banReq):
|
||||||
|
"""Cleanup stuff that's associated with this ban request."""
|
||||||
|
channel = self.channels.get(banReq)
|
||||||
|
if channel:
|
||||||
|
del self.channels[banReq]
|
||||||
|
ramfile = self.ramFiles.get(banReq)
|
||||||
|
if ramfile:
|
||||||
|
del self.ramFiles[banReq]
|
||||||
|
|
||||||
|
|
||||||
|
def doBanUrlTask(self, task):
|
||||||
|
"""Continue downloading the ban url if needed."""
|
||||||
|
banReq = task.banRequestNum
|
||||||
|
channel = self.channels.get(banReq)
|
||||||
|
if channel:
|
||||||
|
if channel.run():
|
||||||
|
return task.cont
|
||||||
|
else:
|
||||||
|
self.notify.warning("no channel for ban req %s" % banReq)
|
||||||
|
self.cleanupBanReq(banReq)
|
||||||
|
return task.done
|
||||||
|
|
||||||
|
result = ""
|
||||||
|
ramfile = self.ramFiles.get(banReq)
|
||||||
|
if ramfile:
|
||||||
|
result = ramfile.getData()
|
||||||
|
self.notify.info("done processing ban request %s, ramFile=%s" % (banReq, result))
|
||||||
|
self.cleanupBanReq(banReq)
|
||||||
|
return task.done
|
138
otp/src/ai/Barrier.py
Normal file
138
otp/src/ai/Barrier.py
Normal file
|
@ -0,0 +1,138 @@
|
||||||
|
""" Barrier.py: contains the Barrier class: utility class for AI objects that must wait for a message from each of a list of Avatars """
|
||||||
|
|
||||||
|
from otp.ai.AIBase import *
|
||||||
|
from direct.task import Task
|
||||||
|
from direct.showbase import DirectObject
|
||||||
|
import random
|
||||||
|
|
||||||
|
class Barrier(DirectObject.DirectObject):
|
||||||
|
notify = directNotify.newCategory('Barrier')
|
||||||
|
|
||||||
|
def __init__(self, name, uniqueName, avIdList, timeout,
|
||||||
|
clearedFunc = None, timeoutFunc = None,
|
||||||
|
doneFunc = None):
|
||||||
|
"""
|
||||||
|
name: a context name that should be used in common with the
|
||||||
|
client code.
|
||||||
|
uniqueName: should be a unique name for this Barrier, used
|
||||||
|
for timeout doLater
|
||||||
|
avIdList: list of avatars from which we'll expect responses
|
||||||
|
timeout: how long to wait before giving up
|
||||||
|
clearedFunc: func to call when all avatars have cleared the barrier;
|
||||||
|
takes no arguments
|
||||||
|
timeoutFunc: func to call when the timeout has expired;
|
||||||
|
takes list of avIds of avatars that did not
|
||||||
|
clear the barrier
|
||||||
|
doneFunc: func to call when the the barrier is complete for
|
||||||
|
either reason; takes list of avIds of avatars that
|
||||||
|
successfully cleared the barrier
|
||||||
|
|
||||||
|
Call Barrier.clear(avId) when you get a response from
|
||||||
|
each avatar.
|
||||||
|
|
||||||
|
If you need to have additional parameters passed to your
|
||||||
|
callback funcs, see PythonUtil.Functor
|
||||||
|
"""
|
||||||
|
self.name = name
|
||||||
|
self.uniqueName = uniqueName + '-Barrier'
|
||||||
|
self.avIdList = avIdList[:]
|
||||||
|
self.pendingAvatars = self.avIdList[:]
|
||||||
|
self.timeout = timeout
|
||||||
|
self.clearedFunc = clearedFunc
|
||||||
|
self.timeoutFunc = timeoutFunc
|
||||||
|
self.doneFunc = doneFunc
|
||||||
|
|
||||||
|
if len(self.pendingAvatars) == 0:
|
||||||
|
# If we are initialized with an empty list of avatars to
|
||||||
|
# wait for, we consider ourselves cleared immediately.
|
||||||
|
self.notify.debug(
|
||||||
|
'%s: barrier with empty list' % (self.uniqueName))
|
||||||
|
self.active = 0
|
||||||
|
if self.clearedFunc:
|
||||||
|
self.clearedFunc()
|
||||||
|
if self.doneFunc:
|
||||||
|
self.doneFunc(self.avIdList)
|
||||||
|
return
|
||||||
|
|
||||||
|
# choose a name for the timeout task
|
||||||
|
self.taskName = self.uniqueName + '-Timeout'
|
||||||
|
# this shouldn't be necessary, and it's kind of ugly;
|
||||||
|
# in any case, it's better than bringing down the AI server
|
||||||
|
# with an assert
|
||||||
|
origTaskName = self.taskName
|
||||||
|
while taskMgr.hasTaskNamed(self.taskName):
|
||||||
|
self.taskName = origTaskName + '-' + str(random.randint(0, 10000))
|
||||||
|
|
||||||
|
# start the timeout
|
||||||
|
taskMgr.doMethodLater(self.timeout,
|
||||||
|
self.__timerExpired,
|
||||||
|
self.taskName)
|
||||||
|
|
||||||
|
# Hang hooks for each avatar to disappear.
|
||||||
|
for avId in self.avIdList:
|
||||||
|
event = simbase.air.getAvatarExitEvent(avId)
|
||||||
|
self.acceptOnce(event, self.__handleUnexpectedExit, extraArgs=[avId])
|
||||||
|
|
||||||
|
self.notify.debug(
|
||||||
|
'%s: expecting responses from %s within %s seconds' %
|
||||||
|
(self.uniqueName, self.avIdList, self.timeout))
|
||||||
|
|
||||||
|
self.active = 1
|
||||||
|
|
||||||
|
def cleanup(self):
|
||||||
|
"""
|
||||||
|
call this if you're abandoning the barrier condition and
|
||||||
|
discarding this object
|
||||||
|
"""
|
||||||
|
if self.active:
|
||||||
|
taskMgr.remove(self.taskName)
|
||||||
|
self.active = 0
|
||||||
|
self.ignoreAll()
|
||||||
|
|
||||||
|
def clear(self, avId):
|
||||||
|
if not (avId in self.pendingAvatars):
|
||||||
|
self.notify.warning(
|
||||||
|
"%s: tried to clear %s, who was not listed." %
|
||||||
|
(self.uniqueName, avId))
|
||||||
|
return
|
||||||
|
|
||||||
|
self.notify.debug('%s: clearing avatar %s' % (self.uniqueName, avId))
|
||||||
|
self.pendingAvatars.remove(avId)
|
||||||
|
if len(self.pendingAvatars) == 0:
|
||||||
|
self.notify.debug(
|
||||||
|
'%s: barrier cleared by %s' % (self.uniqueName, self.avIdList))
|
||||||
|
self.cleanup()
|
||||||
|
if self.clearedFunc:
|
||||||
|
self.clearedFunc()
|
||||||
|
if self.doneFunc:
|
||||||
|
self.doneFunc(self.avIdList)
|
||||||
|
|
||||||
|
def isActive(self):
|
||||||
|
return self.active
|
||||||
|
|
||||||
|
def getPendingAvatars(self):
|
||||||
|
return self.pendingAvatars[:]
|
||||||
|
|
||||||
|
def __timerExpired(self, task):
|
||||||
|
self.notify.warning(
|
||||||
|
'%s: timeout expired; responses not received from %s' %
|
||||||
|
(self.uniqueName, self.pendingAvatars))
|
||||||
|
self.cleanup()
|
||||||
|
# report which avatars have not responded
|
||||||
|
if self.timeoutFunc:
|
||||||
|
self.timeoutFunc(self.pendingAvatars[:])
|
||||||
|
if self.doneFunc:
|
||||||
|
clearedAvIds = self.avIdList[:]
|
||||||
|
for avId in self.pendingAvatars:
|
||||||
|
clearedAvIds.remove(avId)
|
||||||
|
self.doneFunc(clearedAvIds)
|
||||||
|
|
||||||
|
return Task.done
|
||||||
|
|
||||||
|
def __handleUnexpectedExit(self, avId):
|
||||||
|
if avId not in self.avIdList:
|
||||||
|
return
|
||||||
|
|
||||||
|
self.avIdList.remove(avId)
|
||||||
|
if avId in self.pendingAvatars:
|
||||||
|
self.clear(avId)
|
44
otp/src/ai/GarbageLeakServerEventAggregator.py
Normal file
44
otp/src/ai/GarbageLeakServerEventAggregator.py
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
from direct.showbase.DirectObject import DirectObject
|
||||||
|
from direct.showbase import GarbageReport
|
||||||
|
|
||||||
|
class GarbageLeakServerEventAggregator(DirectObject):
|
||||||
|
def __init__(self, cr):
|
||||||
|
self.cr = cr
|
||||||
|
self._doLaterName = None
|
||||||
|
self._sentLeakDesc2num = {}
|
||||||
|
self._curLeakDesc2num = {}
|
||||||
|
self.accept(GarbageReport.GarbageCycleCountAnnounceEvent,
|
||||||
|
self._handleCycleCounts)
|
||||||
|
|
||||||
|
def destroy(self):
|
||||||
|
self._stopSending()
|
||||||
|
self.ignoreAll()
|
||||||
|
del self.cr
|
||||||
|
|
||||||
|
def _handleCycleCounts(self, desc2num):
|
||||||
|
self._curLeakDesc2num = desc2num
|
||||||
|
self._startSending()
|
||||||
|
|
||||||
|
def _startSending(self):
|
||||||
|
if not self._doLaterName:
|
||||||
|
self._sendLeaks()
|
||||||
|
self._doLaterName = uniqueName('%s-sendGarbageLeakInfo' % self.__class__.__name__)
|
||||||
|
self.doMethodLater(60 * 60., self._sendLeaks, self._doLaterName)
|
||||||
|
|
||||||
|
def _stopSending(self):
|
||||||
|
if self._doLaterName:
|
||||||
|
self.removeTask(self._doLaterName)
|
||||||
|
self._doLaterName = None
|
||||||
|
|
||||||
|
def _sendLeaks(self, task=None):
|
||||||
|
for desc, curNum in self._curLeakDesc2num.iteritems():
|
||||||
|
# only send the number of occurrences of each leak that
|
||||||
|
# we haven't already sent
|
||||||
|
self._sentLeakDesc2num.setdefault(desc, 0)
|
||||||
|
num = curNum - self._sentLeakDesc2num[desc]
|
||||||
|
if num > 0:
|
||||||
|
self.cr.timeManager.d_setClientGarbageLeak(num, desc)
|
||||||
|
self._sentLeakDesc2num[desc] = curNum
|
||||||
|
if task:
|
||||||
|
return task.again
|
||||||
|
|
89
otp/src/ai/GarbageLeakServerEventAggregatorAI.py
Normal file
89
otp/src/ai/GarbageLeakServerEventAggregatorAI.py
Normal file
|
@ -0,0 +1,89 @@
|
||||||
|
from direct.showbase.DirectObject import DirectObject
|
||||||
|
from direct.showbase import GarbageReport
|
||||||
|
|
||||||
|
class GarbageLeakServerEventAggregatorAI(DirectObject):
|
||||||
|
ClientLeakEvent = 'LeakAggregator-ClientGarbageLeakReceived'
|
||||||
|
def __init__(self, air):
|
||||||
|
self.air = air
|
||||||
|
self._eventFreq = config.GetFloat('garbage-leak-server-event-frequency', 60 * 60.)
|
||||||
|
self._doLaterName = None
|
||||||
|
self._sentLeakDesc2num = {}
|
||||||
|
self._curLeakDesc2num = {}
|
||||||
|
self.accept(GarbageReport.GarbageCycleCountAnnounceEvent,
|
||||||
|
self._handleCycleCounts)
|
||||||
|
self._clientStartFDC = None
|
||||||
|
self._doLaterNameClient = None
|
||||||
|
self._sentClientDesc2num = {}
|
||||||
|
self._curClientDesc2num = {}
|
||||||
|
self.accept(self.ClientLeakEvent, self._handleClientCycleCount)
|
||||||
|
|
||||||
|
def destroy(self):
|
||||||
|
self.ignoreAll()
|
||||||
|
self._clientStartFDC.destroy()
|
||||||
|
self._stopSending()
|
||||||
|
self._stopSendingClientLeaks()
|
||||||
|
del self.air
|
||||||
|
|
||||||
|
def _handleCycleCounts(self, desc2num):
|
||||||
|
self._curLeakDesc2num = desc2num
|
||||||
|
self._startSending()
|
||||||
|
|
||||||
|
def _handleClientCycleCount(self, num, description):
|
||||||
|
self._curClientDesc2num.setdefault(description, 0)
|
||||||
|
self._curClientDesc2num[description] += num
|
||||||
|
if not self._clientStartFDC:
|
||||||
|
# do an FDC to allow other concurrent client events to make it in, for dev/testing
|
||||||
|
self._clientStartFDC = FrameDelayedCall(
|
||||||
|
uniqueName('%s-startClientSend' % self.__class__.__name__),
|
||||||
|
self._startSendingClientLeaks)
|
||||||
|
|
||||||
|
def _startSending(self):
|
||||||
|
if not self._doLaterName:
|
||||||
|
self._sendLeaks()
|
||||||
|
self._doLaterName = uniqueName('%s-sendGarbageServerEvents' % self.__class__.__name__)
|
||||||
|
self.doMethodLater(self._eventFreq, self._sendLeaks, self._doLaterName)
|
||||||
|
|
||||||
|
def _stopSending(self):
|
||||||
|
self.removeTask(self._doLaterName)
|
||||||
|
self._doLaterName = None
|
||||||
|
|
||||||
|
def _sendLeaks(self, task=None):
|
||||||
|
# only send the number of occurences of each leak that
|
||||||
|
# we haven't already sent
|
||||||
|
for desc, curNum in self._curLeakDesc2num.iteritems():
|
||||||
|
self._sentLeakDesc2num.setdefault(desc, 0)
|
||||||
|
num = curNum - self._sentLeakDesc2num[desc]
|
||||||
|
if num > 0:
|
||||||
|
if hasattr(self.air, 'districtId'):
|
||||||
|
who = self.air.districtId
|
||||||
|
eventName = 'ai-garbage'
|
||||||
|
else:
|
||||||
|
who = self.air.ourChannel
|
||||||
|
eventName = 'ud-garbage'
|
||||||
|
self.air.writeServerEvent(eventName, who, '%s|%s' % (num, desc))
|
||||||
|
self._sentLeakDesc2num[desc] = curNum
|
||||||
|
if task:
|
||||||
|
return task.again
|
||||||
|
|
||||||
|
def _startSendingClientLeaks(self):
|
||||||
|
if not self._doLaterNameClient:
|
||||||
|
self._sendClientLeaks()
|
||||||
|
self._doLaterNameClient = uniqueName(
|
||||||
|
'%s-sendClientGarbageServerEvents' % self.__class__.__name__)
|
||||||
|
self.doMethodLater(self._eventFreq, self._sendClientLeaks, self._doLaterNameClient)
|
||||||
|
|
||||||
|
def _stopSendingClientLeaks(self):
|
||||||
|
self.removeTask(self._doLaterNameClient)
|
||||||
|
self._doLaterNameClient = None
|
||||||
|
|
||||||
|
def _sendClientLeaks(self, task=None):
|
||||||
|
# only send the number of occurences of each leak that
|
||||||
|
# we haven't already sent
|
||||||
|
for desc, curNum in self._curClientDesc2num.iteritems():
|
||||||
|
self._sentClientDesc2num.setdefault(desc, 0)
|
||||||
|
num = curNum - self._sentClientDesc2num[desc]
|
||||||
|
if num > 0:
|
||||||
|
self.air.writeServerEvent('client-garbage', self.air.districtId, '%s|%s' % (num, desc))
|
||||||
|
self._sentClientDesc2num[desc] = curNum
|
||||||
|
if task:
|
||||||
|
return task.again
|
44
otp/src/ai/GlobalDistributedClassAI.py
Normal file
44
otp/src/ai/GlobalDistributedClassAI.py
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
from otp.ai.AIBaseGlobal import *
|
||||||
|
from pandac.PandaModules import *
|
||||||
|
from direct.distributed.ClockDelta import *
|
||||||
|
from direct.task import Task
|
||||||
|
from direct.showbase import DirectObject
|
||||||
|
#from direct.directnotify import DirectNotifyGlobal
|
||||||
|
import time
|
||||||
|
|
||||||
|
class GlobalDistributedClassAI(DirectObject.DirectObject):
|
||||||
|
notify = DirectNotifyGlobal.directNotify.newCategory("GlobalDistributedClassAI")
|
||||||
|
|
||||||
|
def __init__(self, air, doid, className):
|
||||||
|
self.doId = doid
|
||||||
|
self.air = air
|
||||||
|
# Setting teh Zone to None means No zone logic for this object
|
||||||
|
self.zoneId = None
|
||||||
|
self.dclass = air.dclassesByName[className]
|
||||||
|
# upside registration
|
||||||
|
self.air.addDOToTables(self)
|
||||||
|
self.air.registerForChannel(self.doId)
|
||||||
|
|
||||||
|
def remove():
|
||||||
|
self.air.unregisterForChannel(do.doId)
|
||||||
|
# This is a race, you may have messages pending delivery that are already
|
||||||
|
# on there way to or in the local queue:
|
||||||
|
self.air.removeDOFromTables(self)
|
||||||
|
del self.air
|
||||||
|
del sel.doId
|
||||||
|
|
||||||
|
#############################
|
||||||
|
## Support Functions
|
||||||
|
#############################
|
||||||
|
|
||||||
|
def sendUpdateToAvatarIdFromDOID(self, avId, fieldName, args):
|
||||||
|
channelId = self.GetPuppetConnectionChannel(avId)
|
||||||
|
self.sendUpdateToChannelFromDOID(channelId, fieldName, args)
|
||||||
|
|
||||||
|
########
|
||||||
|
# Special Function to set return address to the DOID
|
||||||
|
########
|
||||||
|
def sendUpdateToChannelFromDOID(self, channelId, fieldName, args):
|
||||||
|
self.air.sendUpdateToChannelFrom(self, channelId, fieldName,self.doId, args)
|
||||||
|
|
||||||
|
|
1116
otp/src/ai/MagicWordManager.py
Normal file
1116
otp/src/ai/MagicWordManager.py
Normal file
File diff suppressed because it is too large
Load diff
597
otp/src/ai/MagicWordManagerAI.py
Normal file
597
otp/src/ai/MagicWordManagerAI.py
Normal file
|
@ -0,0 +1,597 @@
|
||||||
|
from AIBaseGlobal import *
|
||||||
|
from pandac.PandaModules import *
|
||||||
|
from direct.distributed import DistributedObjectAI
|
||||||
|
from direct.directnotify import DirectNotifyGlobal
|
||||||
|
from otp.otpbase import OTPGlobals
|
||||||
|
from direct.showbase import PythonUtil, GarbageReport, ContainerReport, MessengerLeakDetector
|
||||||
|
from direct.showbase import ContainerLeakDetector
|
||||||
|
from direct.showbase.PythonUtil import Functor, DelayedCall, formatTimeCompact
|
||||||
|
import fpformat
|
||||||
|
import string
|
||||||
|
import time
|
||||||
|
import re
|
||||||
|
from direct.task import Task
|
||||||
|
|
||||||
|
class MagicWordManagerAI(DistributedObjectAI.DistributedObjectAI):
|
||||||
|
notify = DirectNotifyGlobal.directNotify.newCategory("MagicWordManagerAI")
|
||||||
|
|
||||||
|
supportSuperchat = simbase.config.GetBool('support-superchat', 0)
|
||||||
|
supportRename = simbase.config.GetBool('support-rename', 0)
|
||||||
|
|
||||||
|
# Fill in by subclass
|
||||||
|
GameAvatarClass = None
|
||||||
|
|
||||||
|
# This will hold the local namespace we evaluate '~ai' messages
|
||||||
|
# within.
|
||||||
|
ExecNamespace = { }
|
||||||
|
|
||||||
|
def __init__(self, air):
|
||||||
|
DistributedObjectAI.DistributedObjectAI.__init__(self, air)
|
||||||
|
|
||||||
|
def setMagicWord(self, word, avId, zoneId, signature):
|
||||||
|
senderId = self.air.getAvatarIdFromSender()
|
||||||
|
|
||||||
|
sender = self.air.doId2do.get(senderId, None)
|
||||||
|
if sender:
|
||||||
|
if senderId == avId:
|
||||||
|
sender = "%s/%s(%s)" % (sender.accountName, sender.name, senderId)
|
||||||
|
else:
|
||||||
|
sender = "%s/%s(%s) (for %d)" % (sender.accountName, sender.name, senderId, avId)
|
||||||
|
else:
|
||||||
|
sender = "Unknown avatar %d" % (senderId)
|
||||||
|
|
||||||
|
self.notify.info("%s (%s) just said the magic word: %s" % (sender, signature, word))
|
||||||
|
self.air.writeServerEvent('magic-word', senderId, "%s|%s|%s" % (sender, signature, word))
|
||||||
|
if self.air.doId2do.has_key(avId):
|
||||||
|
av = self.air.doId2do[avId]
|
||||||
|
|
||||||
|
try:
|
||||||
|
self.doMagicWord(word, av, zoneId, senderId)
|
||||||
|
except:
|
||||||
|
response = PythonUtil.describeException(backTrace = 1)
|
||||||
|
self.notify.warning("Ignoring error in magic word:\n%s" % response)
|
||||||
|
self.down_setMagicWordResponse(senderId, response)
|
||||||
|
else:
|
||||||
|
self.notify.info("Don't know avatar %d." % (avId))
|
||||||
|
|
||||||
|
def wordIs(self, word, w):
|
||||||
|
return word == w or word[:(len(w)+1)] == ('%s ' % w)
|
||||||
|
|
||||||
|
def getWordIs(self, word):
|
||||||
|
# bind a word to self.wordIs and return a callable obj
|
||||||
|
return Functor(self.wordIs, word)
|
||||||
|
|
||||||
|
def doMagicWord(self, word, av, zoneId, senderId):
|
||||||
|
wordIs = self.getWordIs(word)
|
||||||
|
|
||||||
|
if wordIs("~rename"):
|
||||||
|
if (not self.supportRename):
|
||||||
|
self.notify.warning("Rename is not supported for %s, requested by %d" % (av.name, senderId))
|
||||||
|
else:
|
||||||
|
name = string.strip(word[8:])
|
||||||
|
if name == "":
|
||||||
|
response = "No name."
|
||||||
|
else:
|
||||||
|
av.d_setName(name)
|
||||||
|
|
||||||
|
elif wordIs("~badname"):
|
||||||
|
self.notify.warning("Renaming inappropriately named toon %s (doId %d)." % (av.name, av.doId))
|
||||||
|
name = "toon%d" % (av.doId % 1000000)
|
||||||
|
av.d_setName(name)
|
||||||
|
|
||||||
|
elif wordIs("~chat"):
|
||||||
|
if (not self.supportSuperchat) and (senderId != av.doId):
|
||||||
|
self.notify.warning("Super chat is not supported for %s, requested by %d" % (av.name, senderId))
|
||||||
|
else:
|
||||||
|
av.d_setCommonChatFlags(OTPGlobals.CommonChat)
|
||||||
|
self.notify.debug("Giving common chat permission to " + av.name)
|
||||||
|
elif wordIs("~superchat"):
|
||||||
|
if not self.supportSuperchat:
|
||||||
|
self.notify.warning("Super chat is not supported for " + av.name)
|
||||||
|
else:
|
||||||
|
av.d_setCommonChatFlags(OTPGlobals.SuperChat)
|
||||||
|
self.notify.debug("Giving super chat permission to " + av.name)
|
||||||
|
elif wordIs("~nochat"):
|
||||||
|
av.d_setCommonChatFlags(0)
|
||||||
|
self.notify.debug("Removing special chat permissions for " + av.name)
|
||||||
|
|
||||||
|
elif wordIs("~listen"):
|
||||||
|
if (not self.supportSuperchat) and (senderId != av.doId):
|
||||||
|
self.notify.warning("Listen is not supported for %s, requested by %d" % (av.name, senderId))
|
||||||
|
else:
|
||||||
|
# This is a client-side word.
|
||||||
|
if (senderId != av.doId):
|
||||||
|
self.sendUpdateToAvatarId(av.doId, 'setMagicWord', [word, av.doId, zoneId])
|
||||||
|
|
||||||
|
elif wordIs("~fix"):
|
||||||
|
anyChanged = av.fixAvatar()
|
||||||
|
if anyChanged:
|
||||||
|
response = "avatar fixed."
|
||||||
|
else:
|
||||||
|
response = "avatar does not need fixing."
|
||||||
|
self.down_setMagicWordResponse(senderId, response)
|
||||||
|
|
||||||
|
self.down_setMagicWordResponse(senderId, response)
|
||||||
|
|
||||||
|
elif wordIs("~who all"):
|
||||||
|
str = ''
|
||||||
|
for obj in self.air.doId2do.values():
|
||||||
|
if hasattr(obj, "accountName"):
|
||||||
|
str += '%s %s\n' % (obj.accountName, obj.name)
|
||||||
|
if not str:
|
||||||
|
str = "No avatars."
|
||||||
|
self.down_setMagicWordResponse(senderId, str)
|
||||||
|
|
||||||
|
elif wordIs("~ouch"):
|
||||||
|
if av.hp < 1:
|
||||||
|
av.b_setHp(0)
|
||||||
|
av.toonUp(1)
|
||||||
|
else:
|
||||||
|
av.b_setHp(1)
|
||||||
|
self.notify.debug("Only 1 hp for " + av.name)
|
||||||
|
elif wordIs("~sad"):
|
||||||
|
av.b_setHp(0)
|
||||||
|
self.notify.debug("Only 0 hp for " + av.name)
|
||||||
|
elif wordIs("~dead"):
|
||||||
|
av.takeDamage(av.hp)
|
||||||
|
self.notify.debug(av.name + " is dead")
|
||||||
|
elif wordIs("~waydead"):
|
||||||
|
av.takeDamage(av.hp)
|
||||||
|
av.b_setHp(-100)
|
||||||
|
self.notify.debug(av.name + " is way dead")
|
||||||
|
elif wordIs("~toonup"):
|
||||||
|
av.toonUp(av.maxHp)
|
||||||
|
self.notify.debug("Full heal for " + av.name)
|
||||||
|
elif wordIs('~hp'):
|
||||||
|
args = word.split()
|
||||||
|
hp = int(args[1])
|
||||||
|
av.b_setHp(hp)
|
||||||
|
self.notify.debug('Set hp to %s for %s' % (hp, av.name))
|
||||||
|
|
||||||
|
elif wordIs("~ainotify"):
|
||||||
|
args = word.split()
|
||||||
|
n = Notify.ptr().getCategory(args[1])
|
||||||
|
n.setSeverity(
|
||||||
|
{'error': NSError,
|
||||||
|
'warning': NSWarning,
|
||||||
|
'info': NSInfo,
|
||||||
|
'debug': NSDebug,
|
||||||
|
'spam': NSSpam,}[args[2]])
|
||||||
|
|
||||||
|
elif wordIs("~ghost"):
|
||||||
|
# Toggle ghost mode. Ghost mode == 2 indicates a magic
|
||||||
|
# word was the source.
|
||||||
|
if av.ghostMode:
|
||||||
|
av.b_setGhostMode(0)
|
||||||
|
else:
|
||||||
|
av.b_setGhostMode(2)
|
||||||
|
|
||||||
|
elif wordIs('~immortal'):
|
||||||
|
# ~immortal toggles immortal mode on and off
|
||||||
|
# ~immortal 0/1 and ~immortal on/off sets the mode explicitly
|
||||||
|
args = word.split()
|
||||||
|
invalid = False
|
||||||
|
if len(args) > 1 and args[1] in ('0', 'off'):
|
||||||
|
immortal = False
|
||||||
|
elif len(args) > 1 and args[1] in ('1', 'on'):
|
||||||
|
immortal = True
|
||||||
|
elif len(args) > 1:
|
||||||
|
invalid = True
|
||||||
|
else:
|
||||||
|
immortal = not av.immortalMode
|
||||||
|
|
||||||
|
if invalid:
|
||||||
|
self.down_setMagicWordResponse(senderId, 'unknown argument %s' % args[1])
|
||||||
|
else:
|
||||||
|
# immortality
|
||||||
|
av.setImmortalMode(immortal)
|
||||||
|
if av.immortalMode:
|
||||||
|
response = 'immortality ON'
|
||||||
|
else:
|
||||||
|
response = 'immortality OFF'
|
||||||
|
self.down_setMagicWordResponse(senderId, response)
|
||||||
|
|
||||||
|
elif wordIs("~dna"):
|
||||||
|
# Fiddle with your dna.
|
||||||
|
self.doDna(word, av, zoneId, senderId)
|
||||||
|
|
||||||
|
elif wordIs('~ai'):
|
||||||
|
# Execute an arbitrary Python command on the AI.
|
||||||
|
command = string.strip(word[3:])
|
||||||
|
self.notify.warning("Executing command '%s' from %s" % (command, senderId))
|
||||||
|
text = self.__execMessage(command)[:simbase.config.GetInt("ai-debug-length",300)]
|
||||||
|
self.down_setMagicWordResponse(
|
||||||
|
senderId, text)
|
||||||
|
|
||||||
|
elif wordIs('~ud'):
|
||||||
|
# Execute an arbitrary Python command on the ud.
|
||||||
|
print word
|
||||||
|
channel,command = re.match("~ud ([0-9]+) (.+)", word).groups()
|
||||||
|
channel = int(channel)
|
||||||
|
if(simbase.air.doId2do.get(channel)):
|
||||||
|
self.notify.warning("Passing command '%s' to %s from %s" % (command, channel, senderId))
|
||||||
|
|
||||||
|
try:
|
||||||
|
simbase.air.doId2do[channel].sendUpdate("execCommand", [command, self.doId, senderId, zoneId])
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
|
elif wordIs('~aiobjects'):
|
||||||
|
args = word.split()
|
||||||
|
from direct.showbase import ObjectReport
|
||||||
|
report = ObjectReport.ObjectReport('AI ~objects')
|
||||||
|
|
||||||
|
if 'all' in args:
|
||||||
|
self.notify.info('printing full object set...')
|
||||||
|
report.getObjectPool().printObjsByType(printReferrers='ref' in args)
|
||||||
|
|
||||||
|
if hasattr(self, 'baselineObjReport'):
|
||||||
|
self.notify.info('calculating diff from baseline ObjectReport...')
|
||||||
|
self.lastDiff = self.baselineObjReport.diff(report)
|
||||||
|
self.lastDiff.printOut(full=('diff' in args or 'dif' in args))
|
||||||
|
|
||||||
|
if 'baseline' in args or not hasattr(self, 'baselineObjReport'):
|
||||||
|
self.notify.info('recording baseline ObjectReport...')
|
||||||
|
if hasattr(self, 'baselineObjReport'):
|
||||||
|
self.baselineObjReport.destroy()
|
||||||
|
self.baselineObjReport = report
|
||||||
|
|
||||||
|
self.down_setMagicWordResponse(senderId, 'objects logged')
|
||||||
|
|
||||||
|
elif wordIs('~aiobjecthg'):
|
||||||
|
import gc
|
||||||
|
objs = gc.get_objects()
|
||||||
|
type2count = {}
|
||||||
|
for obj in objs:
|
||||||
|
tn = safeTypeName(obj)
|
||||||
|
type2count.setdefault(tn, 0)
|
||||||
|
type2count[tn] += 1
|
||||||
|
count2type = invertDictLossless(type2count)
|
||||||
|
counts = count2type.keys()
|
||||||
|
counts.sort()
|
||||||
|
counts.reverse()
|
||||||
|
for count in counts:
|
||||||
|
print '%s: %s' % (count, count2type[count])
|
||||||
|
self.down_setMagicWordResponse(senderId, '~aiobjecthg complete')
|
||||||
|
|
||||||
|
elif wordIs('~aicrash'):
|
||||||
|
# TODO: require a typed explanation in production
|
||||||
|
# if we call notify.error directly, the magic word mgr will catch it
|
||||||
|
# self.notify.error doesn't seem to work either
|
||||||
|
DelayedCall(Functor(simbase.air.notify.error, '~aicrash: simulating an AI crash'))
|
||||||
|
|
||||||
|
elif wordIs('~aicontainers'):
|
||||||
|
args = word.split()
|
||||||
|
limit = 30
|
||||||
|
if 'full' in args:
|
||||||
|
limit = None
|
||||||
|
ContainerReport.ContainerReport('~aicontainers', log=True, limit=limit, threaded=True)
|
||||||
|
|
||||||
|
elif wordIs('~aigarbage'):
|
||||||
|
args = word.split()
|
||||||
|
# it can take a LOOONG time to print out the garbage referrers and referents
|
||||||
|
# by reference (as opposed to by number)
|
||||||
|
full = ('full' in args)
|
||||||
|
safeMode = ('safe' in args)
|
||||||
|
verbose = ('verbose' in args)
|
||||||
|
delOnly = ('delonly' in args)
|
||||||
|
def handleGarbageDone(senderId, garbageReport):
|
||||||
|
self.down_setMagicWordResponse(senderId, 'garbage logged, %s AI cycles' % garbageReport.getNumCycles())
|
||||||
|
# This does a garbage collection and dumps the list of leaked (uncollectable) objects to the AI log.
|
||||||
|
GarbageReport.GarbageReport('~aigarbage', fullReport=full, verbose=verbose, log=True, threaded=True,
|
||||||
|
doneCallback=Functor(handleGarbageDone, senderId), safeMode=safeMode, delOnly=delOnly)
|
||||||
|
|
||||||
|
elif wordIs("~creategarbage"):
|
||||||
|
args = word.split()
|
||||||
|
num = 1
|
||||||
|
if len(args) > 1:
|
||||||
|
num = int(args[1])
|
||||||
|
GarbageReport._createGarbage(num)
|
||||||
|
self.down_setMagicWordResponse(senderId, 'leaked garbage created')
|
||||||
|
|
||||||
|
elif wordIs('~leaktask'):
|
||||||
|
def leakTask(task):
|
||||||
|
return task.cont
|
||||||
|
taskMgr.add(leakTask, uniqueName('leakedTask'))
|
||||||
|
leakTask = None
|
||||||
|
self.down_setMagicWordResponse(senderId, 'leaked task created')
|
||||||
|
|
||||||
|
elif wordIs('~aileakmessage'):
|
||||||
|
MessengerLeakDetector._leakMessengerObject()
|
||||||
|
self.down_setMagicWordResponse(senderId, 'messenger leak object created')
|
||||||
|
|
||||||
|
elif wordIs('~leakContainer'):
|
||||||
|
ContainerLeakDetector._createContainerLeak()
|
||||||
|
self.down_setMagicWordResponse(senderId, 'leak container task created')
|
||||||
|
|
||||||
|
elif wordIs('~aipstats'):
|
||||||
|
args = word.split()
|
||||||
|
hostname = None
|
||||||
|
port = None
|
||||||
|
if len(args) > 1:
|
||||||
|
hostname = args[1]
|
||||||
|
if len(args) > 2:
|
||||||
|
port = int(args[2])
|
||||||
|
# make sure pstats is enabled
|
||||||
|
simbase.wantStats = 1
|
||||||
|
Task.TaskManager.pStatsTasks = 1
|
||||||
|
result = simbase.createStats(hostname, port)
|
||||||
|
connectionName = '%s' % hostname
|
||||||
|
if port is not None:
|
||||||
|
connectionName += ':%s' % port
|
||||||
|
if result:
|
||||||
|
response = 'connected AI pstats to %s' % connectionName
|
||||||
|
else:
|
||||||
|
response = 'could not connect AI pstats to %s' % connectionName
|
||||||
|
self.down_setMagicWordResponse(senderId, response)
|
||||||
|
|
||||||
|
elif wordIs('~aiprofile'):
|
||||||
|
args = word.split()
|
||||||
|
if len(args) > 1:
|
||||||
|
num = int(args[1])
|
||||||
|
else:
|
||||||
|
num = 5
|
||||||
|
session = taskMgr.getProfileSession('~aiprofile')
|
||||||
|
session.setLogAfterProfile(True)
|
||||||
|
taskMgr.profileFrames(num, session)
|
||||||
|
self.down_setMagicWordResponse(senderId, 'profiling %s AI frames...' % num)
|
||||||
|
|
||||||
|
elif wordIs('~aiframeprofile'):
|
||||||
|
args = word.split()
|
||||||
|
wasOn = bool(taskMgr.getProfileFrames())
|
||||||
|
if len(args) > 1:
|
||||||
|
setting = bool(int(args[1]))
|
||||||
|
else:
|
||||||
|
setting = not wasOn
|
||||||
|
taskMgr.setProfileFrames(setting)
|
||||||
|
self.down_setMagicWordResponse(
|
||||||
|
senderId,
|
||||||
|
'AI frame profiling %s%s' % (choice(setting, 'ON', 'OFF'),
|
||||||
|
choice(wasOn == setting, ' already', '')))
|
||||||
|
|
||||||
|
elif wordIs('~aitaskprofile'):
|
||||||
|
args = word.split()
|
||||||
|
wasOn = bool(taskMgr.getProfileTasks())
|
||||||
|
if len(args) > 1:
|
||||||
|
setting = bool(int(args[1]))
|
||||||
|
else:
|
||||||
|
setting = not wasOn
|
||||||
|
taskMgr.setProfileTasks(setting)
|
||||||
|
self.down_setMagicWordResponse(
|
||||||
|
senderId,
|
||||||
|
'AI task profiling %s%s' % (choice(setting, 'ON', 'OFF'),
|
||||||
|
choice(wasOn == setting, ' already', '')))
|
||||||
|
|
||||||
|
elif wordIs('~aitaskspikethreshold'):
|
||||||
|
from direct.task.TaskProfiler import TaskProfiler
|
||||||
|
args = word.split()
|
||||||
|
if len(args) > 1:
|
||||||
|
threshold = float(args[1])
|
||||||
|
response = 'AI task spike threshold set to %ss' % threshold
|
||||||
|
else:
|
||||||
|
threshold = TaskProfiler.GetDefaultSpikeThreshold()
|
||||||
|
response = 'AI task spike threshold reset to %ss' % threshold
|
||||||
|
TaskProfiler.SetSpikeThreshold(threshold)
|
||||||
|
self.down_setMagicWordResponse(senderId, response)
|
||||||
|
|
||||||
|
elif wordIs('~ailogtaskprofiles'):
|
||||||
|
args = word.split()
|
||||||
|
if len(args) > 1:
|
||||||
|
name = args[1]
|
||||||
|
else:
|
||||||
|
name = None
|
||||||
|
taskMgr.logTaskProfiles(name)
|
||||||
|
response = 'logged AI task profiles%s' % choice(name, ' for %s' % name, '')
|
||||||
|
self.down_setMagicWordResponse(senderId, response)
|
||||||
|
|
||||||
|
elif wordIs('~aitaskprofileflush'):
|
||||||
|
args = word.split()
|
||||||
|
if len(args) > 1:
|
||||||
|
name = args[1]
|
||||||
|
else:
|
||||||
|
name = None
|
||||||
|
taskMgr.flushTaskProfiles(name)
|
||||||
|
response = 'flushed AI task profiles%s' % choice(name, ' for %s' % name, '')
|
||||||
|
self.down_setMagicWordResponse(senderId, response)
|
||||||
|
|
||||||
|
elif wordIs('~aiobjectcount'):
|
||||||
|
simbase.air.printObjectCount()
|
||||||
|
self.down_setMagicWordResponse(senderId, 'logging AI distributed object count...')
|
||||||
|
|
||||||
|
elif wordIs('~aitaskmgr'):
|
||||||
|
print taskMgr
|
||||||
|
self.down_setMagicWordResponse(senderId, 'logging AI taskMgr...')
|
||||||
|
|
||||||
|
elif wordIs('~aijobmgr'):
|
||||||
|
print jobMgr
|
||||||
|
self.down_setMagicWordResponse(senderId, 'logging AI jobMgr...')
|
||||||
|
|
||||||
|
elif wordIs('~aijobtime'):
|
||||||
|
args = word.split()
|
||||||
|
if len(args) > 1:
|
||||||
|
time = float(args[1])
|
||||||
|
else:
|
||||||
|
time = None
|
||||||
|
response = ''
|
||||||
|
if time is None:
|
||||||
|
time = jobMgr.getDefaultTimeslice()
|
||||||
|
time = time * 1000.
|
||||||
|
response = 'reset AI jobMgr timeslice to %s ms' % time
|
||||||
|
else:
|
||||||
|
response = 'set AI jobMgr timeslice to %s ms' % time
|
||||||
|
time = time / 1000.
|
||||||
|
jobMgr.setTimeslice(time)
|
||||||
|
self.down_setMagicWordResponse(senderId, response)
|
||||||
|
|
||||||
|
elif wordIs('~aidetectleaks'):
|
||||||
|
started = self.air.startLeakDetector()
|
||||||
|
self.down_setMagicWordResponse(senderId,
|
||||||
|
choice(started,
|
||||||
|
'AI leak detector started',
|
||||||
|
'AI leak detector already started',
|
||||||
|
))
|
||||||
|
|
||||||
|
elif wordIs('~aitaskthreshold'):
|
||||||
|
args = word.split()
|
||||||
|
if len(args) > 1.:
|
||||||
|
threshold = float(args[1])
|
||||||
|
else:
|
||||||
|
threshold = None
|
||||||
|
response = ''
|
||||||
|
if threshold is None:
|
||||||
|
threshold = taskMgr.DefTaskDurationWarningThreshold
|
||||||
|
response = 'reset AI task duration warning threshold to %s' % threshold
|
||||||
|
else:
|
||||||
|
response = 'set AI task duration warning threshold to %s' % threshold
|
||||||
|
taskMgr.setTaskDurationWarningThreshold(threshold)
|
||||||
|
self.down_setMagicWordResponse(senderId, response)
|
||||||
|
|
||||||
|
elif wordIs('~aimessenger'):
|
||||||
|
print messenger
|
||||||
|
self.down_setMagicWordResponse(senderId, 'logging AI messenger...')
|
||||||
|
|
||||||
|
elif wordIs('~requestdeleted'):
|
||||||
|
requestDeletedDOs = self.air.getRequestDeletedDOs()
|
||||||
|
response = '%s requestDeleted AI objects%s' % (
|
||||||
|
len(requestDeletedDOs), choice(len(requestDeletedDOs), ', logging...', ''))
|
||||||
|
s = '~requestDeleted: ['
|
||||||
|
for do, age in requestDeletedDOs:
|
||||||
|
s += '[%s, %s]' % (do.__class__.__name__, age)
|
||||||
|
s += ']'
|
||||||
|
self.notify.info(s)
|
||||||
|
if len(requestDeletedDOs):
|
||||||
|
response += '\noldest: %s, %s' % (
|
||||||
|
requestDeletedDOs[0][0].__class__.__name__,
|
||||||
|
formatTimeCompact(requestDeletedDOs[0][1]))
|
||||||
|
self.down_setMagicWordResponse(senderId, response)
|
||||||
|
|
||||||
|
elif wordIs('~aigptc'):
|
||||||
|
args = word.split()
|
||||||
|
if len(args) > 1. and hasattr(self.cr, 'leakDetector'):
|
||||||
|
gptcJob = self.cr.leakDetector.getPathsToContainers(
|
||||||
|
'~aigptc', args[1], Functor(self._handleGPTCfinished, senderId, args[1]))
|
||||||
|
else:
|
||||||
|
self.down_setMagicWordResponse(senderId, 'error')
|
||||||
|
|
||||||
|
elif wordIs('~aigptcn'):
|
||||||
|
args = word.split()
|
||||||
|
if len(args) > 1. and hasattr(self.cr, 'leakDetector'):
|
||||||
|
gptcnJob = self.cr.leakDetector.getPathsToContainersNamed(
|
||||||
|
'~aigptcn', args[1], Functor(self._handleGPTCNfinished, senderId, args[1]))
|
||||||
|
else:
|
||||||
|
self.down_setMagicWordResponse(senderId, 'error')
|
||||||
|
|
||||||
|
else:
|
||||||
|
# The word is not an AI-side magic word. If the sender is
|
||||||
|
# different than the target avatar, then pass the magic
|
||||||
|
# word down to the target client-side MagicWordManager to
|
||||||
|
# execute a client-side magic word.
|
||||||
|
# MPG this gets done in child class
|
||||||
|
#if (senderId != av.doId):
|
||||||
|
# self.sendUpdateToAvatarId(av.doId, 'setMagicWord', [word, av.doId, zoneId])
|
||||||
|
return 0
|
||||||
|
return 1
|
||||||
|
|
||||||
|
# MPG define in child class
|
||||||
|
"""
|
||||||
|
def doDna(self, word, av, zoneId, senderId):
|
||||||
|
# Handle the ~dna magic word: change your dna
|
||||||
|
|
||||||
|
# Strip of the "~dna" part; everything else is parameters to
|
||||||
|
# AvatarDNA.updateToonProperties.
|
||||||
|
parms = string.strip(word[4:])
|
||||||
|
|
||||||
|
# Get a copy of the avatar's current DNA.
|
||||||
|
dna = ToonDNA.ToonDNA(av.dna.makeNetString())
|
||||||
|
|
||||||
|
# Modify it according to the user's parameter selection.
|
||||||
|
eval("dna.updateToonProperties(%s)" % (parms))
|
||||||
|
|
||||||
|
av.b_setDNAString(dna.makeNetString())
|
||||||
|
response = "%s" % (dna.asTuple(),)
|
||||||
|
|
||||||
|
self.down_setMagicWordResponse(senderId, response)
|
||||||
|
"""
|
||||||
|
|
||||||
|
def _handleGPTCfinished(self, senderId, ct, gptcJob):
|
||||||
|
self.down_setMagicWordResponse(senderId, 'aigptc(%s) finished' % ct)
|
||||||
|
|
||||||
|
def _handleGPTCNfinished(self, senderId, cn, gptcnJob):
|
||||||
|
self.down_setMagicWordResponse(senderId, 'aigptcn(%s) finished' % cn)
|
||||||
|
|
||||||
|
def __execMessage(self, message):
|
||||||
|
if not self.ExecNamespace:
|
||||||
|
# Import some useful variables into the ExecNamespace initially.
|
||||||
|
exec 'from pandac.PandaModules import *' in globals(), self.ExecNamespace
|
||||||
|
#self.importExecNamespace()
|
||||||
|
|
||||||
|
# Now try to evaluate the expression using ChatInputNormal.ExecNamespace as
|
||||||
|
# the local namespace.
|
||||||
|
try:
|
||||||
|
return str(eval(message, globals(), self.ExecNamespace))
|
||||||
|
|
||||||
|
except SyntaxError:
|
||||||
|
# Maybe it's only a statement, like "x = 1", or
|
||||||
|
# "import math". These aren't expressions, so eval()
|
||||||
|
# fails, but they can be exec'ed.
|
||||||
|
try:
|
||||||
|
exec message in globals(), self.ExecNamespace
|
||||||
|
return 'ok'
|
||||||
|
except:
|
||||||
|
exception = sys.exc_info()[0]
|
||||||
|
extraInfo = sys.exc_info()[1]
|
||||||
|
if extraInfo:
|
||||||
|
return str(extraInfo)
|
||||||
|
else:
|
||||||
|
return str(exception)
|
||||||
|
except:
|
||||||
|
exception = sys.exc_info()[0]
|
||||||
|
extraInfo = sys.exc_info()[1]
|
||||||
|
if extraInfo:
|
||||||
|
return str(extraInfo)
|
||||||
|
else:
|
||||||
|
return str(exception)
|
||||||
|
|
||||||
|
def down_setMagicWordResponse(self, avId, response):
|
||||||
|
"""down_setMagicWordResponse(self, avId, string response)
|
||||||
|
|
||||||
|
Send a response to the avatar who said the magic word.
|
||||||
|
"""
|
||||||
|
self.sendUpdateToAvatarId(avId, 'setMagicWordResponse', [response])
|
||||||
|
|
||||||
|
def setWho(self, avIds):
|
||||||
|
# Sent by the client in response to ~who.
|
||||||
|
str = ''
|
||||||
|
for avId in avIds:
|
||||||
|
obj = self.air.doId2do.get(avId, None)
|
||||||
|
if not obj:
|
||||||
|
self.air.writeServerEvent('suspicious', avId, 'MagicWordManager.setWho not a valid avId: %s' % avId)
|
||||||
|
return
|
||||||
|
elif obj.__class__ == self.GameAvatarClass:
|
||||||
|
str += '%s %s\n' % (obj.accountName, obj.name)
|
||||||
|
if not str:
|
||||||
|
str = "No avatars."
|
||||||
|
|
||||||
|
senderId = self.air.getAvatarIdFromSender()
|
||||||
|
self.down_setMagicWordResponse(senderId, str)
|
||||||
|
|
||||||
|
class FakeAv:
|
||||||
|
# fake avatar object that we can pass in to prevent magic words from crashing
|
||||||
|
def __init__(self, senderId):
|
||||||
|
self.hp = 100
|
||||||
|
self.doId = senderId
|
||||||
|
self.name = 'FakeAv'
|
||||||
|
def b_setHp(*args):
|
||||||
|
pass
|
||||||
|
def b_setMojo(*args):
|
||||||
|
pass
|
||||||
|
def toonUp(*args):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def magicWord(mw, av=None, zoneId=0, senderId=0):
|
||||||
|
if av is None:
|
||||||
|
av = FakeAv(senderId)
|
||||||
|
simbase.air.magicWordManager.doMagicWord(mw, av, zoneId, senderId)
|
||||||
|
|
||||||
|
import __builtin__
|
||||||
|
__builtin__.magicWord = magicWord
|
18
otp/src/ai/ShowBaseAI.py
Normal file
18
otp/src/ai/ShowBaseAI.py
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
from pandac.PandaModules import WindowProperties
|
||||||
|
from direct.showbase import ShowBase
|
||||||
|
|
||||||
|
class ShowBaseAI(ShowBase.ShowBase):
|
||||||
|
def __init__(self, windowTitle=None):
|
||||||
|
self.windowTitle = windowTitle
|
||||||
|
ShowBase.ShowBase.__init__(self)
|
||||||
|
|
||||||
|
def openMainWindow(self, *args, **kw):
|
||||||
|
ShowBase.ShowBase.openMainWindow(self, *args, **kw)
|
||||||
|
if self.windowTitle is not None:
|
||||||
|
wp = WindowProperties()
|
||||||
|
wp.setTitle(self.windowTitle)
|
||||||
|
self.win.requestProperties(wp)
|
||||||
|
|
||||||
|
def finalizeExit(self):
|
||||||
|
# don't shut down the app when user closes the window
|
||||||
|
pass
|
0
otp/src/ai/Sources.pp
Normal file
0
otp/src/ai/Sources.pp
Normal file
485
otp/src/ai/TimeManager.py
Normal file
485
otp/src/ai/TimeManager.py
Normal file
|
@ -0,0 +1,485 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
from pandac.PandaModules import *
|
||||||
|
from direct.showbase.DirectObject import *
|
||||||
|
from direct.distributed.ClockDelta import *
|
||||||
|
from direct.task import Task
|
||||||
|
|
||||||
|
from direct.distributed import DistributedObject
|
||||||
|
from direct.directnotify import DirectNotifyGlobal
|
||||||
|
from otp.otpbase import OTPGlobals
|
||||||
|
from direct.showbase import PythonUtil
|
||||||
|
from direct.showbase import GarbageReport
|
||||||
|
import time
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
import re
|
||||||
|
|
||||||
|
class TimeManager(DistributedObject.DistributedObject):
|
||||||
|
"""
|
||||||
|
This DistributedObject lives on the AI and on the client side, and
|
||||||
|
serves to synchronize the time between them so they both agree, to
|
||||||
|
within a few hundred milliseconds at least, what time it is.
|
||||||
|
|
||||||
|
This used to use a push model where the AI side would push the
|
||||||
|
time down to the client periodically, but now it uses a pull model
|
||||||
|
where the client can request a synchronization check from time to
|
||||||
|
time. It also employs a round-trip measurement to minimize the
|
||||||
|
effect of latency.
|
||||||
|
"""
|
||||||
|
notify = DirectNotifyGlobal.directNotify.newCategory("TimeManager")
|
||||||
|
|
||||||
|
neverDisable = 1
|
||||||
|
|
||||||
|
def __init__(self, cr):
|
||||||
|
DistributedObject.DistributedObject.__init__(self, cr)
|
||||||
|
|
||||||
|
# The number of seconds to wait between automatic
|
||||||
|
# synchronizations. Set to 0 to disable auto sync after
|
||||||
|
# startup.
|
||||||
|
self.updateFreq = base.config.GetFloat('time-manager-freq', 1800)
|
||||||
|
|
||||||
|
# The minimum number of seconds to wait between two unrelated
|
||||||
|
# synchronization attempts. Increasing this number cuts down
|
||||||
|
# on frivolous synchronizations.
|
||||||
|
self.minWait = base.config.GetFloat('time-manager-min-wait', 10)
|
||||||
|
|
||||||
|
# The maximum number of seconds of uncertainty to tolerate in
|
||||||
|
# the clock delta without trying again.
|
||||||
|
self.maxUncertainty = base.config.GetFloat('time-manager-max-uncertainty', 1)
|
||||||
|
|
||||||
|
# The maximum number of attempts to try to get a low-latency
|
||||||
|
# time measurement before giving up and accepting whatever we
|
||||||
|
# get.
|
||||||
|
self.maxAttempts = base.config.GetInt('time-manager-max-attempts', 5)
|
||||||
|
|
||||||
|
# A simulated clock skew for debugging, in seconds.
|
||||||
|
self.extraSkew = base.config.GetInt('time-manager-extra-skew', 0)
|
||||||
|
|
||||||
|
if self.extraSkew != 0:
|
||||||
|
self.notify.info("Simulating clock skew of %0.3f s" % self.extraSkew)
|
||||||
|
|
||||||
|
self.reportFrameRateInterval = base.config.GetDouble('report-frame-rate-interval', 300.0)
|
||||||
|
|
||||||
|
self.talkResult = 0
|
||||||
|
self.thisContext = -1
|
||||||
|
self.nextContext = 0
|
||||||
|
self.attemptCount = 0
|
||||||
|
self.start = 0
|
||||||
|
self.lastAttempt = -self.minWait*2
|
||||||
|
|
||||||
|
self.setFrameRateInterval(self.reportFrameRateInterval)
|
||||||
|
|
||||||
|
self._numClientGarbage = 0
|
||||||
|
|
||||||
|
### DistributedObject methods ###
|
||||||
|
|
||||||
|
def generate(self):
|
||||||
|
"""
|
||||||
|
This method is called when the DistributedObject is reintroduced
|
||||||
|
to the world, either for the first time or from the cache.
|
||||||
|
"""
|
||||||
|
self._gotFirstTimeSync = False
|
||||||
|
if self.cr.timeManager != None:
|
||||||
|
self.cr.timeManager.delete()
|
||||||
|
self.cr.timeManager = self
|
||||||
|
DistributedObject.DistributedObject.generate(self)
|
||||||
|
|
||||||
|
self.accept(OTPGlobals.SynchronizeHotkey, self.handleHotkey)
|
||||||
|
self.accept('clock_error', self.handleClockError)
|
||||||
|
|
||||||
|
if __dev__ and base.config.GetBool('enable-garbage-hotkey', 0):
|
||||||
|
self.accept(OTPGlobals.DetectGarbageHotkey, self.handleDetectGarbageHotkey)
|
||||||
|
|
||||||
|
if self.updateFreq > 0:
|
||||||
|
self.startTask()
|
||||||
|
|
||||||
|
def announceGenerate(self):
|
||||||
|
DistributedObject.DistributedObject.announceGenerate(self)
|
||||||
|
self.synchronize("TimeManager.announceGenerate")
|
||||||
|
|
||||||
|
def gotInitialTimeSync(self):
|
||||||
|
return self._gotFirstTimeSync
|
||||||
|
|
||||||
|
def disable(self):
|
||||||
|
"""
|
||||||
|
This method is called when the DistributedObject is removed from
|
||||||
|
active duty and stored in a cache.
|
||||||
|
"""
|
||||||
|
# Warning! disable() is NOT called for TimeManager! Duh!
|
||||||
|
self.ignore(OTPGlobals.SynchronizeHotkey)
|
||||||
|
if __dev__:
|
||||||
|
self.ignore(OTPGlobals.DetectGarbageHotkey)
|
||||||
|
self.ignore('clock_error')
|
||||||
|
self.stopTask()
|
||||||
|
taskMgr.remove('frameRateMonitor')
|
||||||
|
if self.cr.timeManager == self:
|
||||||
|
self.cr.timeManager = None
|
||||||
|
del self._gotFirstTimeSync
|
||||||
|
DistributedObject.DistributedObject.disable(self)
|
||||||
|
|
||||||
|
def delete(self):
|
||||||
|
"""
|
||||||
|
This method is called when the DistributedObject is permanently
|
||||||
|
removed from the world and deleted from the cache.
|
||||||
|
"""
|
||||||
|
self.ignore(OTPGlobals.SynchronizeHotkey)
|
||||||
|
self.ignore(OTPGlobals.DetectGarbageHotkey)
|
||||||
|
self.ignore('clock_error')
|
||||||
|
self.stopTask()
|
||||||
|
taskMgr.remove('frameRateMonitor')
|
||||||
|
if self.cr.timeManager == self:
|
||||||
|
self.cr.timeManager = None
|
||||||
|
DistributedObject.DistributedObject.delete(self)
|
||||||
|
|
||||||
|
### Task management methods ###
|
||||||
|
|
||||||
|
def startTask(self):
|
||||||
|
self.stopTask()
|
||||||
|
taskMgr.doMethodLater(self.updateFreq, self.doUpdate, "timeMgrTask")
|
||||||
|
|
||||||
|
def stopTask(self):
|
||||||
|
taskMgr.remove("timeMgrTask")
|
||||||
|
|
||||||
|
def doUpdate(self, task):
|
||||||
|
self.synchronize("timer")
|
||||||
|
# Spawn the next one
|
||||||
|
taskMgr.doMethodLater(self.updateFreq, self.doUpdate, "timeMgrTask")
|
||||||
|
return Task.done
|
||||||
|
|
||||||
|
### User hotkey handling ###
|
||||||
|
|
||||||
|
def handleHotkey(self):
|
||||||
|
# For now, we don't impose any restrictions on the amount of
|
||||||
|
# time we must wait between user-suggested resyncs. Comment
|
||||||
|
# this out to change this behavior.
|
||||||
|
self.lastAttempt = -self.minWait*2
|
||||||
|
|
||||||
|
if self.synchronize("user hotkey"):
|
||||||
|
self.talkResult = 1
|
||||||
|
else:
|
||||||
|
# This should change to be more generic
|
||||||
|
# maybe self.cr.localAv
|
||||||
|
base.localAvatar.setChatAbsolute("Too soon.", CFSpeech | CFTimeout)
|
||||||
|
|
||||||
|
### Automatic clock error handling ###
|
||||||
|
|
||||||
|
def handleClockError(self):
|
||||||
|
self.synchronize("clock error")
|
||||||
|
|
||||||
|
### Synchronization methods ###
|
||||||
|
|
||||||
|
def synchronize(self, description):
|
||||||
|
"""synchronize(self, string description)
|
||||||
|
|
||||||
|
Call this function from time to time to synchronize watches
|
||||||
|
with the server. This initiates a round-trip transaction;
|
||||||
|
when the transaction completes, the time will be synced.
|
||||||
|
|
||||||
|
The description is the string that will be written to the log
|
||||||
|
file regarding the reason for this synchronization attempt.
|
||||||
|
|
||||||
|
The return value is true if the attempt is made, or false if
|
||||||
|
it is too soon since the last attempt.
|
||||||
|
"""
|
||||||
|
now = globalClock.getRealTime()
|
||||||
|
|
||||||
|
if now - self.lastAttempt < self.minWait:
|
||||||
|
self.notify.debug("Not resyncing (too soon): %s" % (description))
|
||||||
|
return 0
|
||||||
|
|
||||||
|
self.talkResult = 0
|
||||||
|
self.thisContext = self.nextContext
|
||||||
|
self.attemptCount = 0
|
||||||
|
self.nextContext = (self.nextContext + 1) & 255
|
||||||
|
self.notify.info("Clock sync: %s" % (description))
|
||||||
|
self.start = now
|
||||||
|
self.lastAttempt = now
|
||||||
|
self.sendUpdate("requestServerTime", [self.thisContext])
|
||||||
|
|
||||||
|
return 1
|
||||||
|
|
||||||
|
|
||||||
|
def serverTime(self, context, timestamp, timeOfDay):
|
||||||
|
"""serverTime(self, int8 context, int32 timestamp, uint32 timeOfDay)
|
||||||
|
|
||||||
|
This message is sent from the AI to the client in response to
|
||||||
|
a previous requestServerTime. It contains the time of day as
|
||||||
|
observed by the AI.
|
||||||
|
|
||||||
|
The client should use this, in conjunction with the time
|
||||||
|
measurement taken before calling requestServerTime (above), to
|
||||||
|
determine the clock delta between the AI and the client
|
||||||
|
machines.
|
||||||
|
"""
|
||||||
|
end = globalClock.getRealTime()
|
||||||
|
|
||||||
|
# Compare the AI's current time with that previously reported
|
||||||
|
# by the server at login (and adjusted since then by the local
|
||||||
|
# clock). It shouldn't be very different.
|
||||||
|
aiTimeSkew = timeOfDay - self.cr.getServerTimeOfDay()
|
||||||
|
|
||||||
|
if context != self.thisContext:
|
||||||
|
self.notify.info("Ignoring TimeManager response for old context %d" % (context))
|
||||||
|
return
|
||||||
|
|
||||||
|
elapsed = end - self.start
|
||||||
|
self.attemptCount += 1
|
||||||
|
self.notify.info("Clock sync roundtrip took %0.3f ms" % (elapsed * 1000.0))
|
||||||
|
self.notify.info("AI time delta is %s from server delta" % (PythonUtil.formatElapsedSeconds(aiTimeSkew)))
|
||||||
|
|
||||||
|
average = (self.start + end) / 2.0 - self.extraSkew
|
||||||
|
uncertainty = (end - self.start) / 2.0 + abs(self.extraSkew)
|
||||||
|
|
||||||
|
globalClockDelta.resynchronize(average, timestamp, uncertainty)
|
||||||
|
|
||||||
|
self.notify.info("Local clock uncertainty +/- %.3f s" % (globalClockDelta.getUncertainty()))
|
||||||
|
|
||||||
|
if globalClockDelta.getUncertainty() > self.maxUncertainty:
|
||||||
|
if self.attemptCount < self.maxAttempts:
|
||||||
|
self.notify.info("Uncertainty is too high, trying again.")
|
||||||
|
self.start = globalClock.getRealTime()
|
||||||
|
self.sendUpdate("requestServerTime", [self.thisContext])
|
||||||
|
return
|
||||||
|
self.notify.info("Giving up on uncertainty requirement.")
|
||||||
|
|
||||||
|
if self.talkResult:
|
||||||
|
# This should change to be more generic
|
||||||
|
# maybe self.cr.localAv
|
||||||
|
base.localAvatar.setChatAbsolute("latency %0.0f ms, sync ±%0.0f ms" % (elapsed * 1000.0, globalClockDelta.getUncertainty() * 1000.0), CFSpeech | CFTimeout)
|
||||||
|
|
||||||
|
self._gotFirstTimeSync = True
|
||||||
|
messenger.send("gotTimeSync")
|
||||||
|
|
||||||
|
|
||||||
|
def setDisconnectReason(self, disconnectCode):
|
||||||
|
"""setDisconnectReason(self, uint8 disconnectCode)
|
||||||
|
|
||||||
|
This method is called by the client just before it leaves a
|
||||||
|
shard to alert the AI as to the reason it's going. If the AI
|
||||||
|
doesn't get this message, it can assume the client aborted
|
||||||
|
messily or its internet connection was dropped.
|
||||||
|
"""
|
||||||
|
self.notify.info("Client disconnect reason %s." % (disconnectCode))
|
||||||
|
self.sendUpdate("setDisconnectReason", [disconnectCode])
|
||||||
|
|
||||||
|
def setExceptionInfo(self):
|
||||||
|
"""
|
||||||
|
In the case of the client leaving for a Python exception, we
|
||||||
|
also follow up the above message with this one, which just
|
||||||
|
sends a text string describing the exception for the AI log.
|
||||||
|
"""
|
||||||
|
info = PythonUtil.describeException()
|
||||||
|
self.notify.info("Client exception: %s" % (info))
|
||||||
|
self.sendUpdate("setExceptionInfo", [info])
|
||||||
|
self.cr.flush()
|
||||||
|
|
||||||
|
def d_setSignature(self, signature, hash, pyc):
|
||||||
|
"""
|
||||||
|
This method is called by the client at startup time, to send
|
||||||
|
the xrc signature and the prc hash to the AI for logging in
|
||||||
|
case the client does anything suspicious.
|
||||||
|
"""
|
||||||
|
self.sendUpdate("setSignature", [signature, hash, pyc])
|
||||||
|
|
||||||
|
def sendCpuInfo(self):
|
||||||
|
"""
|
||||||
|
This method is called by the client at startup time, to send
|
||||||
|
the detailed CPU information to the server for logging.
|
||||||
|
"""
|
||||||
|
|
||||||
|
if not base.pipe:
|
||||||
|
return
|
||||||
|
|
||||||
|
di = base.pipe.getDisplayInformation()
|
||||||
|
if di.getNumCpuCores() == 0 and hasattr(base.pipe, 'lookupCpuData'):
|
||||||
|
# If it says we have no CPU's, assume the data hasn't been
|
||||||
|
# looked up yet, and look it up now.
|
||||||
|
base.pipe.lookupCpuData()
|
||||||
|
di = base.pipe.getDisplayInformation()
|
||||||
|
|
||||||
|
di.updateCpuFrequency(0)
|
||||||
|
cacheStatus = preloadCache()
|
||||||
|
|
||||||
|
ooghz = 1.0e-009
|
||||||
|
cpuSpeed = (di.getMaximumCpuFrequency() * ooghz,
|
||||||
|
di.getCurrentCpuFrequency() * ooghz)
|
||||||
|
|
||||||
|
numCpuCores = di.getNumCpuCores()
|
||||||
|
numLogicalCpus = di.getNumLogicalCpus()
|
||||||
|
|
||||||
|
info = '%s|%s|%d|%d|%s|%s cpus' % (
|
||||||
|
di.getCpuVendorString(), di.getCpuBrandString(),
|
||||||
|
di.getCpuVersionInformation(), di.getCpuBrandIndex(),
|
||||||
|
'%0.03f,%0.03f' % cpuSpeed,
|
||||||
|
'%d,%d' % (numCpuCores, numLogicalCpus))
|
||||||
|
|
||||||
|
print "cpu info: %s" % (info)
|
||||||
|
self.sendUpdate("setCpuInfo", [info, cacheStatus])
|
||||||
|
|
||||||
|
|
||||||
|
def setFrameRateInterval(self, frameRateInterval):
|
||||||
|
""" This message is called at startup time, to start sending
|
||||||
|
frame rate reports. """
|
||||||
|
|
||||||
|
if frameRateInterval == 0:
|
||||||
|
return
|
||||||
|
|
||||||
|
if not base.frameRateMeter:
|
||||||
|
# If we're not displaying a frame rate meter, go ahead and
|
||||||
|
# set the global clock to the same interval, so we will be
|
||||||
|
# reporting the average frame rate over the whole
|
||||||
|
# interval. (If we are displaying a frame rate meter,
|
||||||
|
# don't do this, so the frame rate meter will be more
|
||||||
|
# responsive.)
|
||||||
|
|
||||||
|
# However, we'll put a cap on the frame rate interval, so
|
||||||
|
# it doesn't go unreasonably wide if we set the reporting
|
||||||
|
# interval to be fairly slow.
|
||||||
|
maxFrameRateInterval = base.config.GetDouble('max-frame-rate-interval', 30.0)
|
||||||
|
globalClock.setAverageFrameRateInterval(min(frameRateInterval, maxFrameRateInterval))
|
||||||
|
|
||||||
|
taskMgr.remove('frameRateMonitor')
|
||||||
|
taskMgr.doMethodLater(frameRateInterval,
|
||||||
|
self.frameRateMonitor, 'frameRateMonitor')
|
||||||
|
|
||||||
|
def frameRateMonitor(self, task):
|
||||||
|
""" This method is called every once in a while to report the
|
||||||
|
user's average frame rate to the server. """
|
||||||
|
|
||||||
|
from otp.avatar.Avatar import Avatar
|
||||||
|
|
||||||
|
vendorId = 0
|
||||||
|
deviceId = 0
|
||||||
|
processMemory = 0
|
||||||
|
pageFileUsage = 0
|
||||||
|
physicalMemory = 0
|
||||||
|
pageFaultCount = 0
|
||||||
|
|
||||||
|
osInfo = (os.name, 0, 0, 0)
|
||||||
|
cpuSpeed = (0, 0)
|
||||||
|
numCpuCores = 0
|
||||||
|
numLogicalCpus = 0
|
||||||
|
apiName = 'None'
|
||||||
|
|
||||||
|
if getattr(base, 'pipe', None):
|
||||||
|
di = base.pipe.getDisplayInformation()
|
||||||
|
if (di.getDisplayState() == DisplayInformation.DSSuccess):
|
||||||
|
vendorId = di.getVendorId()
|
||||||
|
deviceId = di.getDeviceId()
|
||||||
|
|
||||||
|
di.updateMemoryInformation()
|
||||||
|
oomb = 1.0 / (1024.0 * 1024.0)
|
||||||
|
processMemory = di.getProcessMemory() * oomb
|
||||||
|
pageFileUsage = di.getPageFileUsage() * oomb
|
||||||
|
physicalMemory = di.getPhysicalMemory() * oomb
|
||||||
|
pageFaultCount = di.getPageFaultCount() / 1000.0
|
||||||
|
osInfo = (os.name, di.getOsPlatformId(), di.getOsVersionMajor(), di.getOsVersionMinor())
|
||||||
|
if sys.platform == 'darwin':
|
||||||
|
osInfo = self.getMacOsInfo(osInfo)
|
||||||
|
di.updateCpuFrequency(0)
|
||||||
|
|
||||||
|
ooghz = 1.0e-009
|
||||||
|
cpuSpeed = (di.getMaximumCpuFrequency() * ooghz,
|
||||||
|
di.getCurrentCpuFrequency() * ooghz)
|
||||||
|
|
||||||
|
numCpuCores = di.getNumCpuCores()
|
||||||
|
numLogicalCpus = di.getNumLogicalCpus()
|
||||||
|
|
||||||
|
apiName = base.pipe.getInterfaceName()
|
||||||
|
|
||||||
|
|
||||||
|
self.d_setFrameRate(
|
||||||
|
max(0, globalClock.getAverageFrameRate()),
|
||||||
|
max(0, globalClock.calcFrameRateDeviation()),
|
||||||
|
len(Avatar.ActiveAvatars),
|
||||||
|
base.locationCode or '',
|
||||||
|
max(0,time.time() - base.locationCodeChanged),
|
||||||
|
max(0,globalClock.getRealTime()),
|
||||||
|
base.gameOptionsCode,
|
||||||
|
vendorId, deviceId, processMemory, pageFileUsage,
|
||||||
|
physicalMemory, pageFaultCount, osInfo, cpuSpeed,
|
||||||
|
numCpuCores, numLogicalCpus, apiName)
|
||||||
|
|
||||||
|
return task.again
|
||||||
|
|
||||||
|
def d_setFrameRate(self, fps, deviation, numAvs,
|
||||||
|
locationCode, timeInLocation, timeInGame,
|
||||||
|
gameOptionsCode, vendorId, deviceId,
|
||||||
|
processMemory, pageFileUsage, physicalMemory,
|
||||||
|
pageFaultCount, osInfo, cpuSpeed,
|
||||||
|
numCpuCores, numLogicalCpus, apiName):
|
||||||
|
""" Called by frameRateMonitor to report the current frame
|
||||||
|
rate to the server.
|
||||||
|
"""
|
||||||
|
info = '%0.1f fps|%0.3fd|%s avs|%s|%d|%d|%s|0x%04x|0x%04x|%0.1fMB|%0.1fMB|%0.1fMB|%d|%s|%s|%s cpus|%s' % (
|
||||||
|
fps, deviation, numAvs, locationCode, timeInLocation,
|
||||||
|
timeInGame, gameOptionsCode,
|
||||||
|
vendorId, deviceId, processMemory, pageFileUsage, physicalMemory,
|
||||||
|
pageFaultCount, '%s.%d.%d.%d' % osInfo, '%0.03f,%0.03f' % cpuSpeed,
|
||||||
|
'%d,%d' % (numCpuCores, numLogicalCpus),
|
||||||
|
apiName)
|
||||||
|
print "frame rate: %s" % (info)
|
||||||
|
|
||||||
|
self.sendUpdate("setFrameRate", [
|
||||||
|
fps, deviation, numAvs, locationCode,
|
||||||
|
timeInLocation, timeInGame, gameOptionsCode,
|
||||||
|
vendorId, deviceId, processMemory, pageFileUsage,
|
||||||
|
physicalMemory, pageFaultCount, osInfo, cpuSpeed,
|
||||||
|
numCpuCores, numLogicalCpus, apiName])
|
||||||
|
|
||||||
|
if __dev__:
|
||||||
|
def handleDetectGarbageHotkey(self):
|
||||||
|
self._numClientGarbage = GarbageReport.b_checkForGarbageLeaks(wantReply=True)
|
||||||
|
if self._numClientGarbage:
|
||||||
|
s = "%s client garbage cycles found, see log" % self._numClientGarbage
|
||||||
|
else:
|
||||||
|
s = "0 client garbage cycles found"
|
||||||
|
localAvatar.setChatAbsolute(s, CFSpeech | CFTimeout)
|
||||||
|
|
||||||
|
def d_checkForGarbageLeaks(self, wantReply):
|
||||||
|
# if wantReply is True, AI will send back a setNumAIGarbageLeaks msg
|
||||||
|
self.sendUpdate('checkForGarbageLeaks', [wantReply])
|
||||||
|
|
||||||
|
def setNumAIGarbageLeaks(self, numLeaks):
|
||||||
|
if self._numClientGarbage and numLeaks:
|
||||||
|
s = "%s client and %s AI garbage cycles found, see logs" % (self._numClientGarbage, numLeaks)
|
||||||
|
elif numLeaks:
|
||||||
|
s = "0 client and %s AI garbage cycles found, see log" % numLeaks
|
||||||
|
else:
|
||||||
|
s = "0 client and 0 AI garbage cycles found"
|
||||||
|
localAvatar.setChatAbsolute(s, CFSpeech | CFTimeout)
|
||||||
|
|
||||||
|
def d_setClientGarbageLeak(self, num, description):
|
||||||
|
self.sendUpdate('setClientGarbageLeak', [num, description])
|
||||||
|
|
||||||
|
def getMacOsInfo(self, defaultOsInfo):
|
||||||
|
"""Return a tuple of os name, platormid, major ver, minor ver."""
|
||||||
|
result = defaultOsInfo
|
||||||
|
try:
|
||||||
|
theFile = open('/System/Library/CoreServices/SystemVersion.plist')
|
||||||
|
except IOError:
|
||||||
|
# hmm plain darwin box do nothing
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
key = re.search(
|
||||||
|
r'<key>ProductUserVisibleVersion</key>\s*' +
|
||||||
|
r'<string>(.*?)</string>', theFile.read())
|
||||||
|
theFile.close()
|
||||||
|
if key is not None:
|
||||||
|
try:
|
||||||
|
verString = key.group(1)
|
||||||
|
# we should now have something like 10.5.8
|
||||||
|
parts = verString.split('.')
|
||||||
|
major = int(parts[0])
|
||||||
|
minor = int(parts[1])
|
||||||
|
bugfix = int(parts[2])
|
||||||
|
# since platform id is -1, i'll put the bug fix number in there instead, better than an arbitrary number
|
||||||
|
result = (sys.platform,
|
||||||
|
bugfix, # what do we put for platform id?
|
||||||
|
major,
|
||||||
|
minor)
|
||||||
|
except Exception, e:
|
||||||
|
self.notify.debug("getMacOsInfo %s" % str(e))
|
||||||
|
self.notify.debug('getMacOsInfo returning %s' % str(result))
|
||||||
|
return result
|
||||||
|
|
151
otp/src/ai/TimeManagerAI.py
Normal file
151
otp/src/ai/TimeManagerAI.py
Normal file
|
@ -0,0 +1,151 @@
|
||||||
|
from AIBaseGlobal import *
|
||||||
|
from pandac.PandaModules import *
|
||||||
|
from direct.distributed.ClockDelta import *
|
||||||
|
from direct.task import Task
|
||||||
|
from direct.distributed import DistributedObjectAI
|
||||||
|
from direct.directnotify import DirectNotifyGlobal
|
||||||
|
from direct.showbase import GarbageReport
|
||||||
|
from otp.otpbase import OTPGlobals
|
||||||
|
from otp.ai.GarbageLeakServerEventAggregatorAI import GarbageLeakServerEventAggregatorAI
|
||||||
|
import time
|
||||||
|
|
||||||
|
class TimeManagerAI(DistributedObjectAI.DistributedObjectAI):
|
||||||
|
notify = DirectNotifyGlobal.directNotify.newCategory("TimeManagerAI")
|
||||||
|
|
||||||
|
def __init__(self, air):
|
||||||
|
DistributedObjectAI.DistributedObjectAI.__init__(self, air)
|
||||||
|
if not __dev__:
|
||||||
|
# double-check that we're not implementing a client-sendable debug DC method in production
|
||||||
|
if hasattr(self, 'checkForGarbageLeaks'):
|
||||||
|
self.notify.error('checkForGarbageLeaks should not be defined outside of __dev__')
|
||||||
|
|
||||||
|
def requestServerTime(self, context):
|
||||||
|
"""requestServerTime(self, int8 context)
|
||||||
|
|
||||||
|
This message is sent from the client to the AI to initiate a
|
||||||
|
synchronization phase. The AI should immediately report back
|
||||||
|
with its current time. The client will then measure the round
|
||||||
|
trip.
|
||||||
|
"""
|
||||||
|
timestamp = globalClockDelta.getRealNetworkTime(bits=32)
|
||||||
|
requesterId = self.air.getAvatarIdFromSender()
|
||||||
|
timeOfDay = int(time.time())
|
||||||
|
self.sendUpdateToAvatarId(requesterId, "serverTime",
|
||||||
|
[context, timestamp, timeOfDay])
|
||||||
|
|
||||||
|
def setDisconnectReason(self, disconnectCode):
|
||||||
|
"""setDisconnectReason(self, uint8 disconnectCode)
|
||||||
|
|
||||||
|
This method is called by the client just before it leaves a
|
||||||
|
shard to alert the AI as to the reason it's going. If the AI
|
||||||
|
doesn't get this message, it can assume the client aborted
|
||||||
|
messily or its internet connection was dropped.
|
||||||
|
"""
|
||||||
|
requesterId = self.air.getAvatarIdFromSender()
|
||||||
|
self.notify.info("Client %s leaving for reason %s (%s)." % (
|
||||||
|
requesterId, disconnectCode,
|
||||||
|
OTPGlobals.DisconnectReasons.get(disconnectCode,
|
||||||
|
'invalid reason')))
|
||||||
|
|
||||||
|
if disconnectCode in OTPGlobals.DisconnectReasons:
|
||||||
|
self.air.setAvatarDisconnectReason(requesterId, disconnectCode)
|
||||||
|
else:
|
||||||
|
self.air.writeServerEvent(
|
||||||
|
'suspicious', requesterId, 'invalid disconnect reason: %s' % disconnectCode)
|
||||||
|
|
||||||
|
def setExceptionInfo(self, info):
|
||||||
|
"""setExceptionInfo(self, string info)
|
||||||
|
|
||||||
|
In the case of the client leaving for a Python exception, we
|
||||||
|
also follow up the above message with this one, which just
|
||||||
|
sends a text string describing the exception for the AI log.
|
||||||
|
"""
|
||||||
|
requesterId = self.air.getAvatarIdFromSender()
|
||||||
|
self.notify.info("Client %s exception: %s" % (requesterId, info))
|
||||||
|
serverVersion = simbase.config.GetString('server-version','')
|
||||||
|
self.air.writeServerEvent('client-exception', requesterId, '%s|%s' % (serverVersion,info))
|
||||||
|
|
||||||
|
def setSignature(self, signature, hash, pyc):
|
||||||
|
"""
|
||||||
|
This method is called by the client at startup time, to send
|
||||||
|
the xrc signature and the prc hash to the AI for logging in
|
||||||
|
case the client does anything suspicious.
|
||||||
|
"""
|
||||||
|
if signature:
|
||||||
|
requesterId = self.air.getAvatarIdFromSender()
|
||||||
|
prcHash = HashVal()
|
||||||
|
prcHash.setFromBin(hash)
|
||||||
|
info = '%s|%s' % (signature, prcHash.asHex())
|
||||||
|
self.notify.info('Client %s signature: %s' % (requesterId, info))
|
||||||
|
self.air.writeServerEvent('client-signature', requesterId, info)
|
||||||
|
|
||||||
|
pycHash = HashVal()
|
||||||
|
pycHash.setFromBin(pyc)
|
||||||
|
if pycHash != HashVal():
|
||||||
|
info = pycHash.asHex()
|
||||||
|
self.notify.info('Client %s py signature: %s' % (requesterId, info))
|
||||||
|
self.air.writeServerEvent('client-py-signature', requesterId, info)
|
||||||
|
|
||||||
|
def setCpuInfo(self, info, cacheStatus):
|
||||||
|
"""
|
||||||
|
This method is called by the client at startup time, to send
|
||||||
|
the detailed CPU information to the server for logging.
|
||||||
|
"""
|
||||||
|
requesterId = self.air.getAvatarIdFromSender()
|
||||||
|
|
||||||
|
self.notify.info('client-cpu %s|%s' % (requesterId, info))
|
||||||
|
self.air.writeServerEvent('client-cpu', requesterId, info)
|
||||||
|
# We call this cacheStatus, but really it's the mac address or
|
||||||
|
# other client fingerprint information, in a simple
|
||||||
|
# obfuscating cipher. Decode it.
|
||||||
|
key = 'outrageous'
|
||||||
|
p = 0
|
||||||
|
fingerprint = ''
|
||||||
|
for ch in cacheStatus:
|
||||||
|
ic = ord(ch) ^ ord(key[p])
|
||||||
|
p += 1
|
||||||
|
if p >= len(key):
|
||||||
|
p = 0
|
||||||
|
fingerprint += chr(ic)
|
||||||
|
|
||||||
|
self.notify.info('client-fingerprint %s|%s' % (requesterId, fingerprint))
|
||||||
|
self.air.writeServerEvent('client-fingerprint', requesterId, fingerprint)
|
||||||
|
if hasattr(self.air, 'cpuInfoMgr'):
|
||||||
|
self.air.cpuInfoMgr.sendCpuInfoToUd(info, fingerprint)
|
||||||
|
|
||||||
|
|
||||||
|
def setFrameRate(self, fps, deviation, numAvs,
|
||||||
|
locationCode, timeInLocation, timeInGame,
|
||||||
|
gameOptionsCode, vendorId, deviceId,
|
||||||
|
processMemory, pageFileUsage, physicalMemory,
|
||||||
|
pageFaultCount, osInfo, cpuSpeed,
|
||||||
|
numCpuCores, numLogicalCpus, apiName):
|
||||||
|
""" This method is called by the client at the interval
|
||||||
|
specified by getFrameRateInterval(), to report its current
|
||||||
|
frame rate. """
|
||||||
|
|
||||||
|
requesterId = self.air.getAvatarIdFromSender()
|
||||||
|
info = '%0.1f fps|%0.3fd|%s avs|%s|%d|%d|%s|0x%04x|0x%04x|%0.1fMB|%0.1fMB|%0.1fMB|%d|%s|%s|%s cpus|%s' % (
|
||||||
|
fps, deviation, numAvs, locationCode, timeInLocation,
|
||||||
|
timeInGame, gameOptionsCode,
|
||||||
|
vendorId, deviceId, processMemory, pageFileUsage, physicalMemory,
|
||||||
|
pageFaultCount, '%s.%d.%d.%d' % osInfo, '%0.03f,%0.03f' % cpuSpeed,
|
||||||
|
'%d,%d' % (numCpuCores, numLogicalCpus),
|
||||||
|
apiName)
|
||||||
|
self.notify.info('client-fps %s|%s' % (requesterId, info))
|
||||||
|
self.air.writeServerEvent('client-fps', requesterId, info)
|
||||||
|
|
||||||
|
if __dev__:
|
||||||
|
def checkForGarbageLeaks(self, wantReply):
|
||||||
|
senderId = self.air.getAvatarIdFromSender()
|
||||||
|
self.notify.info("checking for garbage leaks requested by %s" % senderId)
|
||||||
|
# okay checking for garbage leaks should only be done by devs, it's rare enough i'll flag it
|
||||||
|
# as suspicious
|
||||||
|
self.air.writeServerEvent('suspicious', senderId, 'checkForGarbageLeaks')
|
||||||
|
numLeaks = GarbageReport.checkForGarbageLeaks()
|
||||||
|
if wantReply:
|
||||||
|
requesterId = self.air.getAvatarIdFromSender()
|
||||||
|
self.sendUpdateToAvatarId(requesterId, 'setNumAIGarbageLeaks', [numLeaks])
|
||||||
|
|
||||||
|
def setClientGarbageLeak(self, num, description):
|
||||||
|
messenger.send(GarbageLeakServerEventAggregatorAI.ClientLeakEvent, [num, description])
|
0
otp/src/ai/__init__.py
Normal file
0
otp/src/ai/__init__.py
Normal file
4
otp/src/avatar/.cvsignore
Normal file
4
otp/src/avatar/.cvsignore
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
.cvsignore
|
||||||
|
Makefile
|
||||||
|
*.pyc
|
||||||
|
pp.dep
|
1010
otp/src/avatar/Avatar.py
Normal file
1010
otp/src/avatar/Avatar.py
Normal file
File diff suppressed because it is too large
Load diff
55
otp/src/avatar/AvatarDNA.py
Normal file
55
otp/src/avatar/AvatarDNA.py
Normal file
|
@ -0,0 +1,55 @@
|
||||||
|
"""
|
||||||
|
AvatarDNA module: contains the methods and definitions for describing
|
||||||
|
multipart actors with a simple class
|
||||||
|
"""
|
||||||
|
|
||||||
|
#import whrandom
|
||||||
|
from pandac.PandaModules import *
|
||||||
|
from direct.directnotify.DirectNotifyGlobal import *
|
||||||
|
import random
|
||||||
|
from direct.distributed.PyDatagram import PyDatagram
|
||||||
|
from direct.distributed.PyDatagramIterator import PyDatagramIterator
|
||||||
|
|
||||||
|
notify = directNotify.newCategory("AvatarDNA")
|
||||||
|
|
||||||
|
class AvatarDNA:
|
||||||
|
"""
|
||||||
|
Contains methods for describing avatars with a
|
||||||
|
simple class. The AvatarDNA class may be converted to lists of strings
|
||||||
|
for network transmission. Also, AvatarDNA objects can be constructed
|
||||||
|
from lists of strings recieved over the network. Some examples are in
|
||||||
|
order.
|
||||||
|
|
||||||
|
# create a toon from a network packet (list of strings)
|
||||||
|
dna = AvatarDNA()
|
||||||
|
dna.makeFromNetString(networkPacket)
|
||||||
|
|
||||||
|
"""
|
||||||
|
# special methods
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
"""
|
||||||
|
Avatar DNA print method
|
||||||
|
"""
|
||||||
|
return "avatar parent class: type undefined"
|
||||||
|
|
||||||
|
# stringification methods
|
||||||
|
def makeNetString(self):
|
||||||
|
notify.error("called makeNetString on avatarDNA parent class")
|
||||||
|
|
||||||
|
def printNetString(self):
|
||||||
|
string = self.makeNetString()
|
||||||
|
dg = PyDatagram(string)
|
||||||
|
dg.dumpHex(ostream)
|
||||||
|
|
||||||
|
def makeFromNetString(self, string):
|
||||||
|
notify.error("called makeFromNetString on avatarDNA parent class")
|
||||||
|
|
||||||
|
# dna methods
|
||||||
|
|
||||||
|
def getType(self):
|
||||||
|
"""
|
||||||
|
Return which type of actor this dna represents.
|
||||||
|
"""
|
||||||
|
notify.error("Invalid DNA type: ", self.type)
|
||||||
|
return type
|
80
otp/src/avatar/AvatarDetail.py
Normal file
80
otp/src/avatar/AvatarDetail.py
Normal file
|
@ -0,0 +1,80 @@
|
||||||
|
from direct.directnotify.DirectNotifyGlobal import directNotify
|
||||||
|
from otp.avatar import Avatar
|
||||||
|
|
||||||
|
"""
|
||||||
|
instantiate this class with an avatar Id and a callback,
|
||||||
|
and the callback will be called when the avatar is loaded.
|
||||||
|
NOTE: if there is a problem, the avatar will be "None"!
|
||||||
|
"""
|
||||||
|
|
||||||
|
class AvatarDetail:
|
||||||
|
notify = directNotify.newCategory("AvatarDetail")
|
||||||
|
#notify.setDebug(True)
|
||||||
|
|
||||||
|
def __init__(self, doId, callWhenDone):
|
||||||
|
#print("Getting avatar detail for %s from the DB" % doId)
|
||||||
|
self.id = doId
|
||||||
|
self.callWhenDone = callWhenDone
|
||||||
|
self.enterQuery()
|
||||||
|
|
||||||
|
def isReady(self):
|
||||||
|
return true
|
||||||
|
|
||||||
|
def getId(self):
|
||||||
|
return self.id
|
||||||
|
|
||||||
|
##### Query state #####
|
||||||
|
|
||||||
|
# We are waiting for detailed information on the avatar to return
|
||||||
|
# from the server.
|
||||||
|
|
||||||
|
def enterQuery(self):
|
||||||
|
# We need to get a DistributedObject handle for the indicated
|
||||||
|
# avatar. Maybe we have one already, if the avatar is
|
||||||
|
# somewhere nearby.
|
||||||
|
self.avatar = base.cr.doId2do.get(self.id)
|
||||||
|
if self.avatar != None and not self.avatar.ghostMode:
|
||||||
|
self.createdAvatar = 0
|
||||||
|
dclass=self.getDClass()
|
||||||
|
self.__handleResponse(True, self.avatar, dclass)
|
||||||
|
else:
|
||||||
|
# Otherwise, we have to make one up just to hold the
|
||||||
|
# detail query response. This is less than stellar,
|
||||||
|
# because it means we'll do a lot of extra work we don't
|
||||||
|
# need (like loading up models and binding animations,
|
||||||
|
# etc.), but it's not *too* horrible.
|
||||||
|
self.avatar = self.createHolder()
|
||||||
|
self.createdAvatar = 1
|
||||||
|
self.avatar.doId = self.id
|
||||||
|
|
||||||
|
# Now ask the server to tell us more about this avatar.
|
||||||
|
dclass = self.getDClass()
|
||||||
|
base.cr.getAvatarDetails(self.avatar, self.__handleResponse, dclass)
|
||||||
|
|
||||||
|
def exitQuery(self):
|
||||||
|
return true
|
||||||
|
|
||||||
|
def createHolder(self):
|
||||||
|
assert 0, "This must be defined by the subclass!"
|
||||||
|
|
||||||
|
def getDClass(self):
|
||||||
|
assert 0, "This must be defined by the subclass!"
|
||||||
|
|
||||||
|
def __handleResponse(self, gotData, avatar, dclass):
|
||||||
|
if (avatar != self.avatar):
|
||||||
|
# This may be a query response coming back from a previous
|
||||||
|
# request. Ignore it.
|
||||||
|
self.notify.warning("Ignoring unexpected request for avatar %s" % (avatar.doId))
|
||||||
|
return
|
||||||
|
|
||||||
|
if gotData:
|
||||||
|
# We got a valid response.
|
||||||
|
self.callWhenDone(self.avatar)
|
||||||
|
del self.callWhenDone
|
||||||
|
else:
|
||||||
|
# No information available about the avatar. This is an
|
||||||
|
# unexpected error condition, but we go out of our way to
|
||||||
|
# handle it gracefully.
|
||||||
|
self.callWhenDone(None)
|
||||||
|
del self.callWhenDone
|
||||||
|
|
20
otp/src/avatar/AvatarHandle.py
Normal file
20
otp/src/avatar/AvatarHandle.py
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
class AvatarHandle:
|
||||||
|
dclassName = "AvatarHandle"
|
||||||
|
def getName(self):
|
||||||
|
if __dev__:
|
||||||
|
assert False, 'Must override this in inheriting class'
|
||||||
|
return ''
|
||||||
|
|
||||||
|
def isOnline(self):
|
||||||
|
if __dev__:
|
||||||
|
assert False, 'Must override this in inheriting class'
|
||||||
|
return False
|
||||||
|
|
||||||
|
def isUnderstandable(self):
|
||||||
|
if __dev__:
|
||||||
|
assert False, 'Must override this in inheriting class'
|
||||||
|
return True
|
||||||
|
|
||||||
|
def setTalkWhisper(self, fromAV, fromAC, avatarName, chat, mods, flags):
|
||||||
|
newText, scrubbed = localAvatar.scrubTalk(chat, mods)
|
||||||
|
base.talkAssistant.receiveWhisperTalk(fromAV, avatarName, fromAC, None, self.avatarId, self.getName(), newText, scrubbed)
|
98
otp/src/avatar/AvatarPanel.py
Normal file
98
otp/src/avatar/AvatarPanel.py
Normal file
|
@ -0,0 +1,98 @@
|
||||||
|
from pandac.PandaModules import *
|
||||||
|
from direct.gui.DirectGui import *
|
||||||
|
from direct.showbase import DirectObject
|
||||||
|
import Avatar
|
||||||
|
from direct.distributed import DistributedObject
|
||||||
|
|
||||||
|
class AvatarPanel(DirectObject.DirectObject):
|
||||||
|
"""
|
||||||
|
This is a panel that pops up in response to clicking on a Toon or
|
||||||
|
Cog nearby you, or to picking a Toon from your friends list. It
|
||||||
|
draws a little picture of the avatar's head, and gives you a few
|
||||||
|
options to pick from re the avatar.
|
||||||
|
"""
|
||||||
|
# Limit to only have one avatar panel at a time
|
||||||
|
currentAvatarPanel = None
|
||||||
|
|
||||||
|
def __init__(self, avatar, FriendsListPanel = None):
|
||||||
|
# You can only have one open at a time
|
||||||
|
if AvatarPanel.currentAvatarPanel:
|
||||||
|
AvatarPanel.currentAvatarPanel.cleanup()
|
||||||
|
AvatarPanel.currentAvatarPanel = self
|
||||||
|
|
||||||
|
# Clean up any friends list panels that may be up
|
||||||
|
self.friendsListShown = False
|
||||||
|
self.FriendsListPanel = FriendsListPanel
|
||||||
|
if FriendsListPanel:
|
||||||
|
self.friendsListShown = FriendsListPanel.isFriendsListShown()
|
||||||
|
FriendsListPanel.hideFriendsList()
|
||||||
|
|
||||||
|
if avatar:
|
||||||
|
self.avatar = avatar
|
||||||
|
self.avName = avatar.getName()
|
||||||
|
else:
|
||||||
|
self.avatar = None
|
||||||
|
self.avName = "Player"
|
||||||
|
|
||||||
|
if (hasattr(avatar, "uniqueName")):
|
||||||
|
self.avId = avatar.doId
|
||||||
|
self.avDisableName = avatar.uniqueName('disable')
|
||||||
|
self.avGenerateName = avatar.uniqueName('generate')
|
||||||
|
self.avHpChangeName = avatar.uniqueName('hpChange')
|
||||||
|
|
||||||
|
# If we have an actual DistributedObject for this avatar, use
|
||||||
|
# that one instead of whatever we're given.
|
||||||
|
if base.cr.doId2do.has_key(self.avId):
|
||||||
|
self.avatar = base.cr.doId2do[self.avId]
|
||||||
|
else:
|
||||||
|
self.avDisableName = None
|
||||||
|
self.avGenerateName = None
|
||||||
|
self.avHpChangeName = None
|
||||||
|
self.avId = None
|
||||||
|
|
||||||
|
if self.avDisableName:
|
||||||
|
self.accept(self.avDisableName, self.__handleDisableAvatar)
|
||||||
|
|
||||||
|
def cleanup(self):
|
||||||
|
if AvatarPanel.currentAvatarPanel != self:
|
||||||
|
# Must already be cleaned up
|
||||||
|
return
|
||||||
|
|
||||||
|
if self.avDisableName:
|
||||||
|
self.ignore(self.avDisableName)
|
||||||
|
if self.avGenerateName:
|
||||||
|
self.ignore(self.avGenerateName)
|
||||||
|
if self.avHpChangeName:
|
||||||
|
self.ignore(self.avHpChangeName)
|
||||||
|
|
||||||
|
AvatarPanel.currentAvatarPanel = None
|
||||||
|
|
||||||
|
def __handleClose(self):
|
||||||
|
self.cleanup()
|
||||||
|
AvatarPanel.currentAvatarPanel = None
|
||||||
|
if self.friendsListShown:
|
||||||
|
# Restore the friends list if it was up before.
|
||||||
|
self.FriendsListPanel.showFriendsList()
|
||||||
|
|
||||||
|
def __handleDisableAvatar(self):
|
||||||
|
# the old __handleDisableAvatar was sneaking past the inherited class
|
||||||
|
if AvatarPanel.currentAvatarPanel:
|
||||||
|
AvatarPanel.currentAvatarPanel.handleDisableAvatar()
|
||||||
|
else:
|
||||||
|
self.handleDisableAvatar()
|
||||||
|
|
||||||
|
def handleDisableAvatar(self):
|
||||||
|
"""
|
||||||
|
Called whenever an avatar is disabled, this should cleanup the
|
||||||
|
avatar panel if it's not a friend.
|
||||||
|
"""
|
||||||
|
# If the avatar wandered away (or disconnected) shut down the panel.
|
||||||
|
self.cleanup()
|
||||||
|
AvatarPanel.currentAvatarPanel = None
|
||||||
|
|
||||||
|
def isHidden(self):
|
||||||
|
# this function should be sub-classed
|
||||||
|
return 1
|
||||||
|
|
||||||
|
def getType(self):
|
||||||
|
return None
|
446
otp/src/avatar/DistributedAvatar.py
Normal file
446
otp/src/avatar/DistributedAvatar.py
Normal file
|
@ -0,0 +1,446 @@
|
||||||
|
import time
|
||||||
|
import string
|
||||||
|
|
||||||
|
from pandac.PandaModules import *
|
||||||
|
|
||||||
|
from direct.distributed import DistributedNode
|
||||||
|
from direct.actor.DistributedActor import DistributedActor
|
||||||
|
from direct.task import Task
|
||||||
|
from direct.showbase import PythonUtil
|
||||||
|
|
||||||
|
from libotp import Nametag
|
||||||
|
from otp.otpbase import OTPGlobals
|
||||||
|
from otp.otpbase import OTPLocalizer
|
||||||
|
from otp.speedchat import SCDecoders
|
||||||
|
from otp.chat import ChatGarbler
|
||||||
|
from otp.chat import ChatManager
|
||||||
|
|
||||||
|
import random
|
||||||
|
|
||||||
|
from Avatar import Avatar
|
||||||
|
import AvatarDNA
|
||||||
|
|
||||||
|
|
||||||
|
class DistributedAvatar(DistributedActor, Avatar):
|
||||||
|
# This is a text node used to create the numbers that appear over the
|
||||||
|
# heads of the avatars.
|
||||||
|
HpTextGenerator = TextNode("HpTextGenerator")
|
||||||
|
|
||||||
|
# This is used to enable/disable the display of the hp numbers
|
||||||
|
HpTextEnabled = 1
|
||||||
|
|
||||||
|
# set this True so that we can start accepting nametagAmbientLightChanged in generate
|
||||||
|
# and ignore it in disable
|
||||||
|
ManagesNametagAmbientLightChanged = True
|
||||||
|
|
||||||
|
def __init__(self, cr):
|
||||||
|
"""
|
||||||
|
Handle distributed updates
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
self.DistributedAvatar_initialized
|
||||||
|
return
|
||||||
|
except:
|
||||||
|
self.DistributedAvatar_initialized = 1
|
||||||
|
|
||||||
|
Avatar.__init__(self)
|
||||||
|
DistributedActor.__init__(self, cr)
|
||||||
|
|
||||||
|
# The node that shows the number of hp just gained or lost
|
||||||
|
self.hpText = None
|
||||||
|
self.hp = None
|
||||||
|
self.maxHp = None
|
||||||
|
|
||||||
|
|
||||||
|
### managing ActiveAvatars ###
|
||||||
|
|
||||||
|
def disable(self):
|
||||||
|
"""
|
||||||
|
This method is called when the DistributedObject is removed from
|
||||||
|
active duty and stored in a cache.
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
del self.DistributedAvatar_announced
|
||||||
|
except:
|
||||||
|
return
|
||||||
|
self.reparentTo(hidden)
|
||||||
|
self.removeActive()
|
||||||
|
self.disableBodyCollisions()
|
||||||
|
self.hideHpText()
|
||||||
|
# By setting hp to None, when the distributed avatar is "uncached",
|
||||||
|
# and the hp gets set, it will be as if the avatar is new, and no
|
||||||
|
# number will appear over his head. If we don't set this to None,
|
||||||
|
# the setHp call might think that the number has changed and call
|
||||||
|
# showHpText, which we don't want.
|
||||||
|
self.hp = None
|
||||||
|
self.ignore("nameTagShowAvId")
|
||||||
|
self.ignore("nameTagShowName")
|
||||||
|
|
||||||
|
DistributedActor.disable(self)
|
||||||
|
|
||||||
|
def delete(self):
|
||||||
|
"""
|
||||||
|
This method is called when the DistributedObject is permanently
|
||||||
|
removed from the world and deleted from the cache.
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
self.DistributedAvatar_deleted
|
||||||
|
except:
|
||||||
|
self.DistributedAvatar_deleted = 1
|
||||||
|
Avatar.delete(self)
|
||||||
|
DistributedActor.delete(self)
|
||||||
|
|
||||||
|
|
||||||
|
def generate(self):
|
||||||
|
"""
|
||||||
|
This method is called when the DistributedObject is reintroduced
|
||||||
|
to the world, either for the first time or from the cache.
|
||||||
|
"""
|
||||||
|
|
||||||
|
DistributedActor.generate(self)
|
||||||
|
if not self.isLocal():
|
||||||
|
self.addActive()
|
||||||
|
self.considerUnderstandable()
|
||||||
|
|
||||||
|
# Initially, a DistributedAvatar is always parented to hidden
|
||||||
|
# on generate, until we are told otherwise.
|
||||||
|
self.setParent(OTPGlobals.SPHidden)
|
||||||
|
|
||||||
|
# Now that we have a doId, set a tag so others who find us in
|
||||||
|
# the collision system can figure out what avatar they hit.
|
||||||
|
self.setTag('avatarDoId', str(self.doId))
|
||||||
|
self.accept("nameTagShowAvId",self.__nameTagShowAvId)
|
||||||
|
self.accept("nameTagShowName",self.__nameTagShowName)
|
||||||
|
|
||||||
|
def announceGenerate(self):
|
||||||
|
try:
|
||||||
|
self.DistributedAvatar_announced
|
||||||
|
return
|
||||||
|
except:
|
||||||
|
self.DistributedAvatar_announced = 1
|
||||||
|
|
||||||
|
if(not self.isLocal()):
|
||||||
|
self.initializeBodyCollisions("distAvatarCollNode-" + str(self.doId))
|
||||||
|
|
||||||
|
DistributedActor.announceGenerate(self)
|
||||||
|
|
||||||
|
|
||||||
|
def __setTags(self, extra = None):
|
||||||
|
if hasattr(base, "idTags"):
|
||||||
|
if base.idTags:
|
||||||
|
self.__nameTagShowAvId()
|
||||||
|
else:
|
||||||
|
self.__nameTagShowName()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### setParent ###
|
||||||
|
|
||||||
|
def do_setParent(self, parentToken):
|
||||||
|
"""do_setParent(self, int parentToken)
|
||||||
|
|
||||||
|
This overrides a function defined in DistributedNode to
|
||||||
|
reparent the node somewhere. A DistributedAvatar wants to
|
||||||
|
hide the onscreen nametag when the parent is hidden.
|
||||||
|
"""
|
||||||
|
if not self.isDisabled():
|
||||||
|
if parentToken == OTPGlobals.SPHidden:
|
||||||
|
self.nametag2dDist &= ~Nametag.CName
|
||||||
|
else:
|
||||||
|
self.nametag2dDist |= Nametag.CName
|
||||||
|
self.nametag.getNametag2d().setContents(
|
||||||
|
self.nametag2dContents & self.nametag2dDist)
|
||||||
|
DistributedActor.do_setParent(self, parentToken)
|
||||||
|
self.__setTags()
|
||||||
|
|
||||||
|
### setHp ###
|
||||||
|
|
||||||
|
def toonUp(self, hpGained):
|
||||||
|
# WARNING This is extended in DistributedToon.py, please change that
|
||||||
|
# as well if any changes are made here
|
||||||
|
# Adjusts the avatar's hp upward by the indicated value
|
||||||
|
# (limited by maxHp) and shows green numbers flying out of the
|
||||||
|
# avatar's head.
|
||||||
|
|
||||||
|
if self.hp == None or hpGained < 0:
|
||||||
|
return
|
||||||
|
|
||||||
|
oldHp = self.hp
|
||||||
|
|
||||||
|
# If hp is below zero, it might mean we're at a timeout in the
|
||||||
|
# playground, in which case we respect that it is below zero
|
||||||
|
# until we get our head above water. If our toonUp would
|
||||||
|
# take us above zero, then we pretend we started at zero in
|
||||||
|
# the first place, ignoring the timeout.
|
||||||
|
if self.hp + hpGained <= 0:
|
||||||
|
self.hp += hpGained
|
||||||
|
else:
|
||||||
|
self.hp = min(max(self.hp, 0) + hpGained, self.maxHp)
|
||||||
|
|
||||||
|
hpGained = self.hp - max(oldHp, 0)
|
||||||
|
if hpGained > 0:
|
||||||
|
self.showHpText(hpGained)
|
||||||
|
self.hpChange(quietly = 0)
|
||||||
|
|
||||||
|
def takeDamage(self, hpLost, bonus=0):
|
||||||
|
# Adjusts the avatar's hp downward by the indicated value
|
||||||
|
# (limited by 0) and shows red numbers flying out of the
|
||||||
|
# avatar's head.
|
||||||
|
if self.hp == None or hpLost < 0:
|
||||||
|
return
|
||||||
|
|
||||||
|
oldHp = self.hp
|
||||||
|
self.hp = max(self.hp - hpLost, 0)
|
||||||
|
|
||||||
|
hpLost = oldHp - self.hp
|
||||||
|
if hpLost > 0:
|
||||||
|
self.showHpText(-hpLost, bonus)
|
||||||
|
self.hpChange(quietly = 0)
|
||||||
|
|
||||||
|
if self.hp <= 0 and oldHp > 0:
|
||||||
|
self.died()
|
||||||
|
|
||||||
|
def setHp(self, hitPoints):
|
||||||
|
# We no longer fly numbers out of the avatar's head just for
|
||||||
|
# calling setHp(). Instead, toonUp() and takeDamage() divide
|
||||||
|
# that responsibility, and setHp() is just used to quietly
|
||||||
|
# reset the hp from the AI.
|
||||||
|
|
||||||
|
justRanOutOfHp = (hitPoints is not None and
|
||||||
|
self.hp is not None and
|
||||||
|
self.hp - hitPoints > 0 and
|
||||||
|
hitPoints <= 0)
|
||||||
|
|
||||||
|
# Store the new value.
|
||||||
|
self.hp = hitPoints
|
||||||
|
|
||||||
|
# Send events so that the hp meter and others can know about the
|
||||||
|
# change to hp.
|
||||||
|
self.hpChange(quietly = 1)
|
||||||
|
|
||||||
|
if justRanOutOfHp:
|
||||||
|
self.died()
|
||||||
|
|
||||||
|
def hpChange(self, quietly = 0):
|
||||||
|
# We may not have a doId yet... in which case we can't send the
|
||||||
|
# event, and don't need to anyway.
|
||||||
|
if hasattr(self, "doId"):
|
||||||
|
if self.hp != None and self.maxHp != None:
|
||||||
|
messenger.send(self.uniqueName("hpChange"), [self.hp, self.maxHp, quietly])
|
||||||
|
if self.hp != None and self.hp > 0:
|
||||||
|
messenger.send(self.uniqueName("positiveHP"))
|
||||||
|
|
||||||
|
def died(self):
|
||||||
|
"""
|
||||||
|
This is a hook for derived classes to do something when the
|
||||||
|
avatar runs out of HP. The base function doesn't do anything.
|
||||||
|
"""
|
||||||
|
pass
|
||||||
|
|
||||||
|
def getHp(self):
|
||||||
|
return self.hp
|
||||||
|
|
||||||
|
|
||||||
|
### setMaxHp ###
|
||||||
|
|
||||||
|
def setMaxHp(self, hitPoints):
|
||||||
|
self.maxHp = hitPoints
|
||||||
|
self.hpChange()
|
||||||
|
|
||||||
|
def getMaxHp(self):
|
||||||
|
return self.maxHp
|
||||||
|
|
||||||
|
### getName ###
|
||||||
|
|
||||||
|
def getName(self):
|
||||||
|
return(Avatar.getName(self))
|
||||||
|
|
||||||
|
def setName(self, name):
|
||||||
|
# Set the name of our top node, so it will be easy to identify
|
||||||
|
# this avatar in the scene graph.
|
||||||
|
try:
|
||||||
|
self.node().setName("%s-%d" % (name, self.doId))
|
||||||
|
self.gotName = 1
|
||||||
|
except:
|
||||||
|
# This might fail if the doId hasn't been set yet.
|
||||||
|
# No big deal.
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
return(Avatar.setName(self, name))
|
||||||
|
|
||||||
|
### hpText ####
|
||||||
|
|
||||||
|
def showHpText(self, number, bonus=0, scale=1):
|
||||||
|
# WARNING if this changes please also change DistributedToon.py
|
||||||
|
if self.HpTextEnabled and not self.ghostMode:
|
||||||
|
# We don't show zero change.
|
||||||
|
if number != 0:
|
||||||
|
# Get rid of the number if it is already there.
|
||||||
|
if self.hpText:
|
||||||
|
self.hideHpText()
|
||||||
|
# Set the font
|
||||||
|
self.HpTextGenerator.setFont(OTPGlobals.getSignFont())
|
||||||
|
# Show both negative and positive signs
|
||||||
|
if number < 0:
|
||||||
|
self.HpTextGenerator.setText(str(number))
|
||||||
|
else:
|
||||||
|
self.HpTextGenerator.setText("+" + str(number))
|
||||||
|
# No shadow
|
||||||
|
self.HpTextGenerator.clearShadow()
|
||||||
|
# Put a shadow on there
|
||||||
|
#self.HpTextGenerator.setShadow(0.05, 0.05)
|
||||||
|
#self.HpTextGenerator.setShadowColor(0, 0, 0, 1)
|
||||||
|
# Center the number
|
||||||
|
self.HpTextGenerator.setAlign(TextNode.ACenter)
|
||||||
|
# Red for negative, green for positive, yellow for bonus
|
||||||
|
if bonus == 1:
|
||||||
|
r = 1.0
|
||||||
|
g = 1.0
|
||||||
|
b = 0
|
||||||
|
a = 1
|
||||||
|
elif bonus == 2:
|
||||||
|
r = 1.0
|
||||||
|
g = 0.5
|
||||||
|
b = 0
|
||||||
|
a = 1
|
||||||
|
elif number < 0:
|
||||||
|
r = 0.9
|
||||||
|
g = 0
|
||||||
|
b = 0
|
||||||
|
a = 1
|
||||||
|
else:
|
||||||
|
r = 0
|
||||||
|
g = 0.9
|
||||||
|
b = 0
|
||||||
|
a = 1
|
||||||
|
|
||||||
|
self.HpTextGenerator.setTextColor(r, g, b, a)
|
||||||
|
|
||||||
|
self.hpTextNode = self.HpTextGenerator.generate()
|
||||||
|
|
||||||
|
# Put the hpText over the head of the avatar
|
||||||
|
self.hpText = self.attachNewNode(self.hpTextNode)
|
||||||
|
self.hpText.setScale(scale)
|
||||||
|
# Make sure it is a billboard
|
||||||
|
self.hpText.setBillboardPointEye()
|
||||||
|
# Render it after other things in the scene.
|
||||||
|
self.hpText.setBin('fixed', 100)
|
||||||
|
|
||||||
|
# Initial position ... Center of the body... the "tan tien"
|
||||||
|
self.hpText.setPos(0, 0, self.height/2)
|
||||||
|
seq = Task.sequence(
|
||||||
|
# Fly the number out of the character
|
||||||
|
self.hpText.lerpPos(Point3(0, 0, self.height + 1.5),
|
||||||
|
1.0,
|
||||||
|
blendType = 'easeOut'),
|
||||||
|
# Wait 2 seconds
|
||||||
|
Task.pause(0.85),
|
||||||
|
# Fade the number
|
||||||
|
self.hpText.lerpColor(Vec4(r, g, b, a),
|
||||||
|
Vec4(r, g, b, 0),
|
||||||
|
0.1),
|
||||||
|
# Get rid of the number
|
||||||
|
Task.Task(self.hideHpTextTask))
|
||||||
|
taskMgr.add(seq, self.uniqueName("hpText"))
|
||||||
|
else:
|
||||||
|
# Just play the sound effect.
|
||||||
|
# TODO: Put in the sound effect!
|
||||||
|
pass
|
||||||
|
|
||||||
|
def showHpString(self, text, duration=0.85, scale=0.7):
|
||||||
|
if self.HpTextEnabled and not self.ghostMode:
|
||||||
|
# We don't show empty strings
|
||||||
|
if text != '':
|
||||||
|
# Get rid of text if it is already there.
|
||||||
|
if self.hpText:
|
||||||
|
self.hideHpText()
|
||||||
|
# Set the font
|
||||||
|
self.HpTextGenerator.setFont(OTPGlobals.getSignFont())
|
||||||
|
# Write the text
|
||||||
|
self.HpTextGenerator.setText(text)
|
||||||
|
# No shadow
|
||||||
|
self.HpTextGenerator.clearShadow()
|
||||||
|
# Put a shadow on there
|
||||||
|
#self.HpTextGenerator.setShadow(0.05, 0.05)
|
||||||
|
#self.HpTextGenerator.setShadowColor(0, 0, 0, 1)
|
||||||
|
# Center the text
|
||||||
|
self.HpTextGenerator.setAlign(TextNode.ACenter)
|
||||||
|
# Set the color and alpha scale (a)
|
||||||
|
r = a = 1.0
|
||||||
|
g = b = 0.0
|
||||||
|
|
||||||
|
self.HpTextGenerator.setTextColor(r, g, b, a)
|
||||||
|
|
||||||
|
self.hpTextNode = self.HpTextGenerator.generate()
|
||||||
|
|
||||||
|
# Put the hpText over the head of the avatar
|
||||||
|
self.hpText = self.attachNewNode(self.hpTextNode)
|
||||||
|
# Set its scale
|
||||||
|
self.hpText.setScale(scale)
|
||||||
|
# Make sure it is a billboard
|
||||||
|
self.hpText.setBillboardAxis()
|
||||||
|
|
||||||
|
# Initial position ... Center of the body... the "tan tien"
|
||||||
|
self.hpText.setPos(0, 0, self.height/2)
|
||||||
|
seq = Task.sequence(
|
||||||
|
# Fly the number out of the character
|
||||||
|
self.hpText.lerpPos(Point3(0, 0, self.height + 1.5),
|
||||||
|
1.0,
|
||||||
|
blendType = 'easeOut'),
|
||||||
|
# Wait 2 seconds
|
||||||
|
Task.pause(duration),
|
||||||
|
# Fade the number
|
||||||
|
self.hpText.lerpColor(Vec4(r, g, b, a),
|
||||||
|
Vec4(r, g, b, 0),
|
||||||
|
0.1),
|
||||||
|
# Get rid of the number
|
||||||
|
Task.Task(self.hideHpTextTask))
|
||||||
|
taskMgr.add(seq, self.uniqueName("hpText"))
|
||||||
|
else:
|
||||||
|
# Just play the sound effect.
|
||||||
|
# TODO: Put in the sound effect!
|
||||||
|
pass
|
||||||
|
|
||||||
|
def hideHpTextTask(self, task):
|
||||||
|
self.hideHpText()
|
||||||
|
return Task.done
|
||||||
|
|
||||||
|
def hideHpText(self):
|
||||||
|
if self.hpText:
|
||||||
|
taskMgr.remove(self.uniqueName("hpText"))
|
||||||
|
self.hpText.removeNode()
|
||||||
|
self.hpText = None
|
||||||
|
|
||||||
|
def getStareAtNodeAndOffset(self):
|
||||||
|
return self, Point3(0,0,self.height)
|
||||||
|
|
||||||
|
def getAvIdName(self):
|
||||||
|
# Derived classes can override the base.idTags display.
|
||||||
|
return "%s\n%s" % (self.getName(), self.doId)
|
||||||
|
|
||||||
|
def __nameTagShowAvId(self, extra = None):
|
||||||
|
self.setDisplayName(self.getAvIdName())
|
||||||
|
|
||||||
|
def __nameTagShowName(self, extra = None):
|
||||||
|
self.setDisplayName(self.getName())
|
||||||
|
|
||||||
|
def askAvOnShard(self, avId):
|
||||||
|
#determines if a given avId in on my shard
|
||||||
|
if base.cr.doId2do.get(avId):
|
||||||
|
#print("Found Locally")
|
||||||
|
messenger.send("AvOnShard%s"%(avId), [True])
|
||||||
|
else:
|
||||||
|
#print("asking AI")
|
||||||
|
self.sendUpdate("checkAvOnShard", [avId])
|
||||||
|
|
||||||
|
def confirmAvOnShard(self, avId, onShard = True):
|
||||||
|
messenger.send(("AvOnShard%s"%(avId)), [onShard])
|
||||||
|
|
||||||
|
### play dialog sounds ###
|
||||||
|
|
||||||
|
def getDialogueArray(self):
|
||||||
|
# Inheritors should override
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
103
otp/src/avatar/DistributedAvatarAI.py
Normal file
103
otp/src/avatar/DistributedAvatarAI.py
Normal file
|
@ -0,0 +1,103 @@
|
||||||
|
|
||||||
|
from otp.ai.AIBaseGlobal import *
|
||||||
|
from otp.otpbase import OTPGlobals
|
||||||
|
|
||||||
|
from direct.fsm import ClassicFSM
|
||||||
|
from direct.fsm import State
|
||||||
|
from direct.distributed import DistributedNodeAI
|
||||||
|
from direct.task import Task
|
||||||
|
|
||||||
|
class DistributedAvatarAI(DistributedNodeAI.DistributedNodeAI):
|
||||||
|
def __init__(self, air):
|
||||||
|
DistributedNodeAI.DistributedNodeAI.__init__(self, air)
|
||||||
|
self.hp = 0
|
||||||
|
self.maxHp = 0
|
||||||
|
|
||||||
|
def b_setName(self, name):
|
||||||
|
self.setName(name)
|
||||||
|
self.d_setName(name)
|
||||||
|
|
||||||
|
def d_setName(self, name):
|
||||||
|
self.sendUpdate("setName", [name])
|
||||||
|
|
||||||
|
def setName(self, name):
|
||||||
|
self.name = name
|
||||||
|
|
||||||
|
def getName(self):
|
||||||
|
return self.name
|
||||||
|
|
||||||
|
def b_setMaxHp(self, maxHp):
|
||||||
|
self.d_setMaxHp(maxHp)
|
||||||
|
self.setMaxHp(maxHp)
|
||||||
|
|
||||||
|
def d_setMaxHp(self, maxHp):
|
||||||
|
self.sendUpdate('setMaxHp', [maxHp])
|
||||||
|
|
||||||
|
def setMaxHp(self, maxHp):
|
||||||
|
self.maxHp = maxHp
|
||||||
|
|
||||||
|
def getMaxHp(self):
|
||||||
|
return self.maxHp
|
||||||
|
|
||||||
|
def b_setHp(self, hp):
|
||||||
|
self.d_setHp(hp)
|
||||||
|
self.setHp(hp)
|
||||||
|
|
||||||
|
def d_setHp(self, hp):
|
||||||
|
self.sendUpdate('setHp', [hp])
|
||||||
|
|
||||||
|
def setHp(self, hp):
|
||||||
|
self.hp = hp
|
||||||
|
|
||||||
|
def getHp(self):
|
||||||
|
return self.hp
|
||||||
|
|
||||||
|
#----------------------------------
|
||||||
|
|
||||||
|
def b_setLocationName(self, locationName):
|
||||||
|
self.d_setLocationName(locationName)
|
||||||
|
self.setLocationName(locationName)
|
||||||
|
|
||||||
|
def d_setLocationName(self, locationName):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def setLocationName(self, locationName):
|
||||||
|
self.locationName = locationName
|
||||||
|
|
||||||
|
def getLocationName(self):
|
||||||
|
return self.locationName
|
||||||
|
|
||||||
|
#----------------------------------
|
||||||
|
|
||||||
|
def b_setActivity(self, activity):
|
||||||
|
self.d_setActivity(activity)
|
||||||
|
self.setActivity(activity)
|
||||||
|
|
||||||
|
def d_setActivity(self, activity):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def setActivity(self, activity):
|
||||||
|
self.activity = activity
|
||||||
|
|
||||||
|
def getActivity(self):
|
||||||
|
return self.activity
|
||||||
|
|
||||||
|
#----------------------------------
|
||||||
|
|
||||||
|
def toonUp(self, num):
|
||||||
|
# The default toonup is HP recharge. If other games want
|
||||||
|
# a more involved toonup, they can redefine this function
|
||||||
|
if self.hp >= self.maxHp:
|
||||||
|
return
|
||||||
|
self.hp = min(self.hp + num, self.maxHp)
|
||||||
|
self.b_setHp(self.hp)
|
||||||
|
|
||||||
|
def getRadius(self):
|
||||||
|
return OTPGlobals.AvatarDefaultRadius
|
||||||
|
|
||||||
|
def checkAvOnShard(self, avId):
|
||||||
|
senderId = self.air.getAvatarIdFromSender()
|
||||||
|
onShard = False
|
||||||
|
if simbase.air.doId2do.get(avId):
|
||||||
|
onShard = True
|
||||||
|
self.sendUpdateToAvatarId(senderId,"confirmAvOnShard",[avId, onShard])
|
27
otp/src/avatar/DistributedAvatarUD.py
Normal file
27
otp/src/avatar/DistributedAvatarUD.py
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
|
||||||
|
from otp.ai.AIBaseGlobal import *
|
||||||
|
from otp.otpbase import OTPGlobals
|
||||||
|
|
||||||
|
#from direct.fsm import ClassicFSM
|
||||||
|
#from direct.fsm import State
|
||||||
|
from direct.distributed.DistributedNodeAI import DistributedNodeAI
|
||||||
|
#from direct.task import Task
|
||||||
|
|
||||||
|
class DistributedAvatarUD(DistributedNodeAI):
|
||||||
|
def __init__(self, air):
|
||||||
|
DistributedNodeAI.__init__(self, air)
|
||||||
|
self.hp = 0
|
||||||
|
self.maxHp = 0
|
||||||
|
|
||||||
|
def b_setName(self, name):
|
||||||
|
self.setName(name)
|
||||||
|
self.d_setName(name)
|
||||||
|
|
||||||
|
def d_setName(self, name):
|
||||||
|
self.sendUpdate("setName", [name])
|
||||||
|
|
||||||
|
def setName(self, name):
|
||||||
|
self.name = name
|
||||||
|
|
||||||
|
def getName(self):
|
||||||
|
return self.name
|
707
otp/src/avatar/DistributedPlayer.py
Normal file
707
otp/src/avatar/DistributedPlayer.py
Normal file
|
@ -0,0 +1,707 @@
|
||||||
|
"""DistributedPlayer module: contains the DistributedPlayer class"""
|
||||||
|
|
||||||
|
from pandac.PandaModules import *
|
||||||
|
from libotp import WhisperPopup
|
||||||
|
from libotp import CFQuicktalker, CFPageButton, CFQuitButton, CFSpeech, CFThought, CFTimeout
|
||||||
|
from otp.chat import ChatGarbler
|
||||||
|
import string
|
||||||
|
from direct.task import Task
|
||||||
|
from otp.otpbase import OTPLocalizer
|
||||||
|
from otp.speedchat import SCDecoders
|
||||||
|
from direct.showbase import PythonUtil
|
||||||
|
from otp.avatar import DistributedAvatar
|
||||||
|
import time
|
||||||
|
from otp.avatar import Avatar, PlayerBase
|
||||||
|
from otp.chat import TalkAssistant
|
||||||
|
from otp.otpbase import OTPGlobals
|
||||||
|
|
||||||
|
#hack, init for client-side outgoing chat filter
|
||||||
|
if base.config.GetBool('want-chatfilter-hacks',0):
|
||||||
|
from otp.switchboard import badwordpy
|
||||||
|
import os
|
||||||
|
badwordpy.init(os.environ.get('OTP')+'\\src\\switchboard\\','')
|
||||||
|
|
||||||
|
|
||||||
|
class DistributedPlayer(DistributedAvatar.DistributedAvatar,
|
||||||
|
PlayerBase.PlayerBase):
|
||||||
|
"""Distributed Player class:"""
|
||||||
|
|
||||||
|
# This is the length of time that should elapse before we allow
|
||||||
|
# another failed-teleport message to be displayed from the same
|
||||||
|
# avatar.
|
||||||
|
TeleportFailureTimeout = 60.0
|
||||||
|
|
||||||
|
# Create a default chat garbler (can be overridden by child class)
|
||||||
|
chatGarbler = ChatGarbler.ChatGarbler()
|
||||||
|
|
||||||
|
def __init__(self, cr):
|
||||||
|
"""
|
||||||
|
Handle distributed updates
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
self.DistributedPlayer_initialized
|
||||||
|
except:
|
||||||
|
self.DistributedPlayer_initialized = 1
|
||||||
|
|
||||||
|
DistributedAvatar.DistributedAvatar.__init__(self, cr)
|
||||||
|
PlayerBase.PlayerBase.__init__(self)
|
||||||
|
|
||||||
|
self.__teleportAvailable = 0
|
||||||
|
|
||||||
|
self.inventory = None
|
||||||
|
self.experience = None
|
||||||
|
|
||||||
|
self.friendsList = []
|
||||||
|
self.oldFriendsList = None
|
||||||
|
self.timeFriendsListChanged = None
|
||||||
|
self.ignoreList = []
|
||||||
|
|
||||||
|
self.lastFailedTeleportMessage = {}
|
||||||
|
self._districtWeAreGeneratedOn = None
|
||||||
|
|
||||||
|
self.DISLname = ""
|
||||||
|
self.DISLid = 0
|
||||||
|
|
||||||
|
self.autoRun = 0
|
||||||
|
|
||||||
|
self.whiteListEnabled = base.config.GetBool('whitelist-chat-enabled', 1)
|
||||||
|
|
||||||
|
|
||||||
|
### managing ActiveAvatars ###
|
||||||
|
|
||||||
|
def disable(self):
|
||||||
|
"""
|
||||||
|
This method is called when the DistributedObject is removed from
|
||||||
|
active duty and stored in a cache.
|
||||||
|
"""
|
||||||
|
DistributedAvatar.DistributedAvatar.disable(self)
|
||||||
|
|
||||||
|
def delete(self):
|
||||||
|
"""
|
||||||
|
This method is called when the DistributedObject is permanently
|
||||||
|
removed from the world and deleted from the cache.
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
self.DistributedPlayer_deleted
|
||||||
|
except:
|
||||||
|
self.DistributedPlayer_deleted = 1
|
||||||
|
del self.experience
|
||||||
|
if self.inventory:
|
||||||
|
self.inventory.unload()
|
||||||
|
del self.inventory
|
||||||
|
DistributedAvatar.DistributedAvatar.delete(self)
|
||||||
|
|
||||||
|
def generate(self):
|
||||||
|
"""
|
||||||
|
This method is called when the DistributedObject is reintroduced
|
||||||
|
to the world, either for the first time or from the cache.
|
||||||
|
"""
|
||||||
|
DistributedAvatar.DistributedAvatar.generate(self)
|
||||||
|
|
||||||
|
def setLocation(self, parentId, zoneId, teleport=0):
|
||||||
|
DistributedAvatar.DistributedAvatar.setLocation(self, parentId, zoneId, teleport)
|
||||||
|
# if the avatar just got put somewhere it shouldn't be, delete it
|
||||||
|
# this is to prevent hackers from sidling over into an 'uber' zone, thereby
|
||||||
|
# keeping themselves on your client even after the client no longer has interest in the
|
||||||
|
# original, legitimate zone from which the hacker toon was generated
|
||||||
|
if not (parentId in (0, None) and zoneId in (0, None)):
|
||||||
|
if not self.cr._isValidPlayerLocation(parentId, zoneId):
|
||||||
|
self.cr.disableDoId(self.doId)
|
||||||
|
self.cr.deleteObject(self.doId)
|
||||||
|
|
||||||
|
def isGeneratedOnDistrict(self, districtId=None):
|
||||||
|
if districtId is None:
|
||||||
|
return self._districtWeAreGeneratedOn is not None
|
||||||
|
else:
|
||||||
|
return self._districtWeAreGeneratedOn == districtId
|
||||||
|
|
||||||
|
def getArrivedOnDistrictEvent(self, districtId=None):
|
||||||
|
if districtId is None:
|
||||||
|
return 'arrivedOnDistrict'
|
||||||
|
else:
|
||||||
|
return 'arrivedOnDistrict-%s' % districtId
|
||||||
|
|
||||||
|
def arrivedOnDistrict(self, districtId):
|
||||||
|
# we have been generated on this district
|
||||||
|
curFrameTime = globalClock.getFrameTime()
|
||||||
|
if hasattr(self,"frameTimeWeArrivedOnDistrict") and \
|
||||||
|
curFrameTime == self.frameTimeWeArrivedOnDistrict:
|
||||||
|
# rare case check if we get the zero from the shard we're leaving
|
||||||
|
# AFTER we get the district id of the shard we were going to
|
||||||
|
if districtId == 0 and self._districtWeAreGeneratedOn:
|
||||||
|
self.notify.warning("ignoring arrivedOnDistrict 0, since arrivedOnDistrict %d occured on the same frame" % self._districtWeAreGeneratedOn)
|
||||||
|
return
|
||||||
|
self._districtWeAreGeneratedOn = districtId
|
||||||
|
self.frameTimeWeArrivedOnDistrict = globalClock.getFrameTime()
|
||||||
|
messenger.send(self.getArrivedOnDistrictEvent(districtId))
|
||||||
|
messenger.send(self.getArrivedOnDistrictEvent())
|
||||||
|
|
||||||
|
def setLeftDistrict(self):
|
||||||
|
self._districtWeAreGeneratedOn = None
|
||||||
|
|
||||||
|
def hasParentingRules(self):
|
||||||
|
# we can't define setParentingRules for the localAvatar in the DC because
|
||||||
|
# that would define parenting rules for other players' avatars. Just
|
||||||
|
# override this and always return True for the sake of the DoInterestManager
|
||||||
|
if self is localAvatar:
|
||||||
|
return True
|
||||||
|
|
||||||
|
### setAccountName ###
|
||||||
|
|
||||||
|
def setAccountName(self, accountName):
|
||||||
|
self.accountName = accountName
|
||||||
|
|
||||||
|
### setWhisper ###
|
||||||
|
|
||||||
|
def setSystemMessage(self, aboutId, chatString,
|
||||||
|
whisperType = WhisperPopup.WTSystem):
|
||||||
|
"""setSystemMessage(self, int aboutId, string chatString)
|
||||||
|
|
||||||
|
A message generated from the system (or the AI, or something
|
||||||
|
like that). If this involves another avatar (e.g. Flippy is
|
||||||
|
now online), the aboutId is filled in; otherwise, aboutId is
|
||||||
|
zero.
|
||||||
|
"""
|
||||||
|
self.displayWhisper(aboutId, chatString, whisperType)
|
||||||
|
|
||||||
|
def displayWhisper(self, fromId, chatString, whisperType):
|
||||||
|
"""displayWhisper(self, int fromId, string chatString, int whisperType)
|
||||||
|
|
||||||
|
Displays the whisper message in whatever capacity makes sense.
|
||||||
|
This is separate from setWhisper so we can safely call it by
|
||||||
|
name from within setWhisper and expect the derived function to
|
||||||
|
override it.
|
||||||
|
"""
|
||||||
|
print "Whisper type %s from %s: %s" % (whisperType, fromId, chatString)
|
||||||
|
|
||||||
|
|
||||||
|
def displayWhisperPlayer(self, playerId, chatString, whisperType):
|
||||||
|
"""
|
||||||
|
Displays the whisper message in whatever capacity makes sense.
|
||||||
|
This is separate from setWhisper so we can safely call it by
|
||||||
|
name from within setWhisper and expect the derived function to
|
||||||
|
override it.
|
||||||
|
"""
|
||||||
|
print "WhisperPlayer type %s from %s: %s" % (whisperType, playerId, chatString)
|
||||||
|
|
||||||
|
### setWhisperSC ###
|
||||||
|
|
||||||
|
def whisperSCTo(self, msgIndex, sendToId, toPlayer):
|
||||||
|
"""
|
||||||
|
Sends a speedchat whisper message to the indicated
|
||||||
|
avatar/player.
|
||||||
|
"""
|
||||||
|
if toPlayer:
|
||||||
|
base.cr.playerFriendsManager.sendSCWhisper(sendToId, msgIndex)
|
||||||
|
else:
|
||||||
|
messenger.send("wakeup")
|
||||||
|
self.sendUpdate("setWhisperSCFrom", [self.doId, msgIndex], sendToId)
|
||||||
|
|
||||||
|
def setWhisperSCFrom(self, fromId, msgIndex):
|
||||||
|
"""
|
||||||
|
Receive and decode the SpeedChat message.
|
||||||
|
"""
|
||||||
|
handle = base.cr.identifyAvatar(fromId)
|
||||||
|
if handle == None:
|
||||||
|
return
|
||||||
|
|
||||||
|
if base.cr.avatarFriendsManager.checkIgnored(fromId):
|
||||||
|
# We're ignoring this jerk.
|
||||||
|
self.d_setWhisperIgnored(fromId)
|
||||||
|
return
|
||||||
|
|
||||||
|
if fromId in self.ignoreList:
|
||||||
|
# We're ignoring this jerk.
|
||||||
|
self.d_setWhisperIgnored(fromId)
|
||||||
|
return
|
||||||
|
|
||||||
|
chatString = SCDecoders.decodeSCStaticTextMsg(msgIndex)
|
||||||
|
if chatString:
|
||||||
|
self.displayWhisper(fromId, chatString, WhisperPopup.WTQuickTalker)
|
||||||
|
base.talkAssistant.receiveAvatarWhisperSpeedChat(TalkAssistant.SPEEDCHAT_NORMAL, msgIndex, fromId)
|
||||||
|
|
||||||
|
### setWhisperSCCustom ###
|
||||||
|
|
||||||
|
def whisperSCCustomTo(self, msgIndex, sendToId, toPlayer):
|
||||||
|
"""
|
||||||
|
Sends a speedchat whisper message to the indicated
|
||||||
|
toon, prefixed with our own name.
|
||||||
|
"""
|
||||||
|
if toPlayer:
|
||||||
|
base.cr.playerFriendsManager.sendSCCustomWhisper(sendToId, msgIndex)
|
||||||
|
return
|
||||||
|
|
||||||
|
messenger.send("wakeup")
|
||||||
|
self.sendUpdate("setWhisperSCCustomFrom", [self.doId, msgIndex],
|
||||||
|
sendToId)
|
||||||
|
|
||||||
|
def _isValidWhisperSource(self, source):
|
||||||
|
return True
|
||||||
|
|
||||||
|
def setWhisperSCCustomFrom(self, fromId, msgIndex):
|
||||||
|
"""
|
||||||
|
Receive and decode the SC message.
|
||||||
|
"""
|
||||||
|
handle = base.cr.identifyAvatar(fromId)
|
||||||
|
if handle == None:
|
||||||
|
return
|
||||||
|
|
||||||
|
if not self._isValidWhisperSource(handle):
|
||||||
|
self.notify.warning('displayWhisper from non-toon %s' % fromId)
|
||||||
|
return
|
||||||
|
|
||||||
|
# new ignore list is handled by the Friends manager's, there are now two types, avatar and player.
|
||||||
|
if base.cr.avatarFriendsManager.checkIgnored(fromId):
|
||||||
|
# We're ignoring this jerk.
|
||||||
|
self.d_setWhisperIgnored(fromId)
|
||||||
|
return
|
||||||
|
|
||||||
|
if fromId in self.ignoreList:
|
||||||
|
# We're ignoring this jerk.
|
||||||
|
self.d_setWhisperIgnored(fromId)
|
||||||
|
return
|
||||||
|
|
||||||
|
chatString = SCDecoders.decodeSCCustomMsg(msgIndex)
|
||||||
|
if chatString:
|
||||||
|
self.displayWhisper(fromId, chatString, WhisperPopup.WTQuickTalker)
|
||||||
|
base.talkAssistant.receiveAvatarWhisperSpeedChat(TalkAssistant.SPEEDCHAT_CUSTOM, msgIndex, fromId)
|
||||||
|
|
||||||
|
### setWhisperSCEmote ###
|
||||||
|
|
||||||
|
def whisperSCEmoteTo(self, emoteId, sendToId, toPlayer):
|
||||||
|
"""
|
||||||
|
Sends a speedchat whisper message to the indicated
|
||||||
|
toon, prefixed with our own name.
|
||||||
|
"""
|
||||||
|
print("whisperSCEmoteTo %s %s %s" % (emoteId, sendToId, toPlayer))
|
||||||
|
if toPlayer:
|
||||||
|
base.cr.playerFriendsManager.sendSCEmoteWhisper(sendToId, emoteId)
|
||||||
|
return
|
||||||
|
messenger.send("wakeup")
|
||||||
|
self.sendUpdate("setWhisperSCEmoteFrom", [self.doId, emoteId],
|
||||||
|
sendToId)
|
||||||
|
|
||||||
|
def setWhisperSCEmoteFrom(self, fromId, emoteId):
|
||||||
|
"""
|
||||||
|
Receive and decode the SC message.
|
||||||
|
"""
|
||||||
|
handle = base.cr.identifyAvatar(fromId)
|
||||||
|
if handle == None:
|
||||||
|
return
|
||||||
|
|
||||||
|
if base.cr.avatarFriendsManager.checkIgnored(fromId):
|
||||||
|
# We're ignoring this jerk.
|
||||||
|
self.d_setWhisperIgnored(fromId)
|
||||||
|
return
|
||||||
|
|
||||||
|
chatString = SCDecoders.decodeSCEmoteWhisperMsg(emoteId,
|
||||||
|
handle.getName())
|
||||||
|
if chatString:
|
||||||
|
self.displayWhisper(fromId, chatString, WhisperPopup.WTEmote)
|
||||||
|
base.talkAssistant.receiveAvatarWhisperSpeedChat(TalkAssistant.SPEEDCHAT_EMOTE, emoteId, fromId)
|
||||||
|
|
||||||
|
def d_setWhisperIgnored(self, sendToId):
|
||||||
|
# Don't send this message for the time being.
|
||||||
|
# I haven't removed it completely since we may
|
||||||
|
# want to send it in the future.
|
||||||
|
|
||||||
|
# self.sendUpdate("setWhisperIgnored", [self.doId], sendToId)
|
||||||
|
pass
|
||||||
|
|
||||||
|
### setChat ###
|
||||||
|
def setChatAbsolute(self, chatString, chatFlags, dialogue = None, interrupt = 1, quiet = 0):
|
||||||
|
DistributedAvatar.DistributedAvatar.setChatAbsolute(self, chatString, chatFlags, dialogue, interrupt)
|
||||||
|
if not quiet:
|
||||||
|
pass
|
||||||
|
|
||||||
|
def b_setChat(self, chatString, chatFlags):
|
||||||
|
# Is this a magic word? All magic words begin with a ~
|
||||||
|
if (self.cr.wantMagicWords and
|
||||||
|
(len(chatString) > 0) and (chatString[0] == "~")):
|
||||||
|
# Tell the magic word manager we just said a magic word
|
||||||
|
messenger.send("magicWord", [chatString])
|
||||||
|
else:
|
||||||
|
# HACK for demo - Outgoing dirty word check. NEVER RELY ON THIS.
|
||||||
|
if base.config.GetBool('want-chatfilter-hacks',0):
|
||||||
|
if base.config.GetBool('want-chatfilter-drop-offending',0):
|
||||||
|
if badwordpy.test(chatString):
|
||||||
|
return
|
||||||
|
else:
|
||||||
|
chatString = badwordpy.scrub(chatString)
|
||||||
|
|
||||||
|
# Local
|
||||||
|
# avoid having to check if this is the local toon
|
||||||
|
messenger.send("wakeup")
|
||||||
|
self.setChatAbsolute(chatString, chatFlags)
|
||||||
|
# Distributed
|
||||||
|
self.d_setChat(chatString, chatFlags)
|
||||||
|
|
||||||
|
|
||||||
|
def d_setChat(self, chatString, chatFlags):
|
||||||
|
self.sendUpdate("setChat", [chatString, chatFlags, 0])
|
||||||
|
|
||||||
|
#self.sendUpdate("setTalk", [0, 0, chatString, []])
|
||||||
|
|
||||||
|
|
||||||
|
def setTalk(self, fromAV, fromAC, avatarName, chat, mods, flags):
|
||||||
|
newText, scrubbed = self.scrubTalk(chat, mods)
|
||||||
|
self.displayTalk(newText)
|
||||||
|
if base.talkAssistant.isThought(newText):
|
||||||
|
newText = base.talkAssistant.removeThoughtPrefix(newText)
|
||||||
|
base.talkAssistant.receiveThought(fromAV, avatarName, fromAC, None, newText, scrubbed)
|
||||||
|
else:
|
||||||
|
base.talkAssistant.receiveOpenTalk(fromAV, avatarName, fromAC, None, newText, scrubbed)
|
||||||
|
|
||||||
|
def setTalkWhisper(self, fromAV, fromAC, avatarName, chat, mods, flags):
|
||||||
|
newText, scrubbed = self.scrubTalk(chat, mods)
|
||||||
|
#self.displayTalk(newText)
|
||||||
|
self.displayTalkWhisper(fromAV, avatarName, chat, mods)
|
||||||
|
base.talkAssistant.receiveWhisperTalk(fromAV, avatarName, fromAC, None, self.doId, self.getName(), newText, scrubbed)
|
||||||
|
|
||||||
|
def displayTalkWhisper(self, fromId, avatarName, chatString, mods):
|
||||||
|
"""displayTalkWhisper(self, int fromId, string chatString)
|
||||||
|
|
||||||
|
Displays the whisper message in whatever capacity makes sense.
|
||||||
|
This is separate from setWhisper so we can safely call it by
|
||||||
|
name from within setWhisper and expect the derived function to
|
||||||
|
override it.
|
||||||
|
"""
|
||||||
|
print "TalkWhisper from %s: %s" % (fromId, chatString)
|
||||||
|
|
||||||
|
def scrubTalk(self, chat, mods):
|
||||||
|
"""
|
||||||
|
returns chat where the mods have been replaced with appropreiate words
|
||||||
|
this is not in chat assistant because the replacement needs to be done
|
||||||
|
by the object that speeaks them. A pirate says "arr",
|
||||||
|
a duck says "quack", etc..
|
||||||
|
"""
|
||||||
|
return chat
|
||||||
|
|
||||||
|
def setChat(self, chatString, chatFlags, DISLid):
|
||||||
|
"""setChat(self, string)
|
||||||
|
Garble the message if needed, then pass message to setChatAbsolute
|
||||||
|
"""
|
||||||
|
self.notify.error("Should call setTalk")
|
||||||
|
chatString = base.talkAssistant.whiteListFilterMessage(chatString)
|
||||||
|
|
||||||
|
if base.cr.avatarFriendsManager.checkIgnored(self.doId):
|
||||||
|
# We're ignoring this jerk.
|
||||||
|
return
|
||||||
|
|
||||||
|
# if we don't have chat permission, garble the chat message
|
||||||
|
if base.localAvatar.garbleChat and (not self.isUnderstandable()):
|
||||||
|
chatString = self.chatGarbler.garble(self, chatString)
|
||||||
|
|
||||||
|
# Clear any buttons or speedchat state from the chat flags;
|
||||||
|
# both of these go through a different interface.
|
||||||
|
chatFlags &= ~(CFQuicktalker | CFPageButton | CFQuitButton)
|
||||||
|
|
||||||
|
# Also, enforce that either the speech or thought bit is set,
|
||||||
|
# and the timeout is set iff speech is set.
|
||||||
|
if (chatFlags & CFThought):
|
||||||
|
chatFlags &= ~(CFSpeech | CFTimeout)
|
||||||
|
else:
|
||||||
|
chatFlags |= (CFSpeech | CFTimeout)
|
||||||
|
|
||||||
|
self.setChatAbsolute(chatString, chatFlags)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### setSC ###
|
||||||
|
|
||||||
|
def b_setSC(self, msgIndex):
|
||||||
|
# Local
|
||||||
|
self.setSC(msgIndex)
|
||||||
|
# Distributed
|
||||||
|
self.d_setSC(msgIndex)
|
||||||
|
|
||||||
|
def d_setSC(self, msgIndex):
|
||||||
|
messenger.send("wakeup")
|
||||||
|
self.sendUpdate("setSC", [msgIndex])
|
||||||
|
|
||||||
|
def setSC(self, msgIndex):
|
||||||
|
"""
|
||||||
|
Receive and decode the SC message
|
||||||
|
"""
|
||||||
|
|
||||||
|
if base.cr.avatarFriendsManager.checkIgnored(self.doId):
|
||||||
|
# We're ignoring this jerk.
|
||||||
|
return
|
||||||
|
|
||||||
|
if self.doId in base.localAvatar.ignoreList:
|
||||||
|
# We're ignoring this jerk.
|
||||||
|
return
|
||||||
|
|
||||||
|
chatString = SCDecoders.decodeSCStaticTextMsg(msgIndex)
|
||||||
|
if chatString:
|
||||||
|
self.setChatAbsolute(chatString,
|
||||||
|
CFSpeech | CFQuicktalker | CFTimeout, quiet = 1)
|
||||||
|
base.talkAssistant.receiveOpenSpeedChat(TalkAssistant.SPEEDCHAT_NORMAL, msgIndex, self.doId)
|
||||||
|
|
||||||
|
### setSCCustom ###
|
||||||
|
|
||||||
|
def b_setSCCustom(self, msgIndex):
|
||||||
|
# Local
|
||||||
|
self.setSCCustom(msgIndex)
|
||||||
|
# Distributed
|
||||||
|
self.d_setSCCustom(msgIndex)
|
||||||
|
|
||||||
|
def d_setSCCustom(self, msgIndex):
|
||||||
|
messenger.send("wakeup")
|
||||||
|
self.sendUpdate("setSCCustom", [msgIndex])
|
||||||
|
|
||||||
|
def setSCCustom(self, msgIndex):
|
||||||
|
"""
|
||||||
|
Receive and decode the SC message
|
||||||
|
"""
|
||||||
|
# new ignore list is handled by the Friends manager's, there are now two types, avatar and player.
|
||||||
|
if base.cr.avatarFriendsManager.checkIgnored(self.doId):
|
||||||
|
# We're ignoring this jerk.
|
||||||
|
return
|
||||||
|
|
||||||
|
if self.doId in base.localAvatar.ignoreList:
|
||||||
|
# We're ignoring this jerk.
|
||||||
|
return
|
||||||
|
|
||||||
|
chatString = SCDecoders.decodeSCCustomMsg(msgIndex)
|
||||||
|
if chatString:
|
||||||
|
self.setChatAbsolute(chatString,
|
||||||
|
CFSpeech | CFQuicktalker | CFTimeout)
|
||||||
|
base.talkAssistant.receiveOpenSpeedChat(TalkAssistant.SPEEDCHAT_CUSTOM, msgIndex, self.doId)
|
||||||
|
|
||||||
|
### setSCEmote ###
|
||||||
|
|
||||||
|
def b_setSCEmote(self, emoteId):
|
||||||
|
self.b_setEmoteState(emoteId,
|
||||||
|
animMultiplier=self.animMultiplier)
|
||||||
|
|
||||||
|
def d_friendsNotify(self, avId, status):
|
||||||
|
self.sendUpdate("friendsNotify", [avId, status])
|
||||||
|
|
||||||
|
def friendsNotify(self, avId, status):
|
||||||
|
"""friendsNotify(self, int32 avId, int8 status)
|
||||||
|
|
||||||
|
This message is sent by the AI to notify the client when
|
||||||
|
friends are added or removed without the client's
|
||||||
|
participation, if the client happens to be logged in.
|
||||||
|
|
||||||
|
status is one of:
|
||||||
|
|
||||||
|
1 - The indicated avatar is no longer your friend.
|
||||||
|
2 - The indicated avatar is now your "special" friend.
|
||||||
|
|
||||||
|
Other changes don't require notification, because the client
|
||||||
|
was presumably in direct control.
|
||||||
|
"""
|
||||||
|
avatar = base.cr.identifyFriend(avId)
|
||||||
|
if (avatar != None):
|
||||||
|
if (status == 1):
|
||||||
|
self.setSystemMessage(avId, OTPLocalizer.WhisperNoLongerFriend % avatar.getName())
|
||||||
|
elif (status == 2):
|
||||||
|
self.setSystemMessage(avId, OTPLocalizer.WhisperNowSpecialFriend % avatar.getName())
|
||||||
|
|
||||||
|
### teleportQuery ###
|
||||||
|
|
||||||
|
def d_teleportQuery(self, requesterId, sendToId = None):
|
||||||
|
self.sendUpdate("teleportQuery", [requesterId], sendToId)
|
||||||
|
#print("sending teleportQuery %s %s" % (requesterId, sendToId))
|
||||||
|
|
||||||
|
def teleportQuery(self, requesterId):
|
||||||
|
"""teleportQuery(self, int requesterId)
|
||||||
|
|
||||||
|
This distributed message is sent peer-to-peer from one client
|
||||||
|
who is considering teleporting to another client. When it is
|
||||||
|
received, the receiving client should send back a
|
||||||
|
teleportResponse indicating whether she is available to be
|
||||||
|
teleported to (e.g. not on a trolley or something), and if so,
|
||||||
|
where she is.
|
||||||
|
"""
|
||||||
|
# Only consider teleport requests from toons who are on our
|
||||||
|
# friends list, or who are somewhere nearby.
|
||||||
|
#print("received teleportQuery %s" % (requesterId))
|
||||||
|
#avatar = base.cr.identifyAvatar(requesterId)
|
||||||
|
avatar = base.cr.playerFriendsManager.identifyFriend(requesterId)
|
||||||
|
|
||||||
|
if avatar != None:
|
||||||
|
# new ignore list is handled by the Friends manager's, there are now two types, avatar and player.
|
||||||
|
if base.cr.avatarFriendsManager.checkIgnored(requesterId):
|
||||||
|
self.d_teleportResponse(self.doId, 2, 0, 0, 0, sendToId = requesterId)
|
||||||
|
return
|
||||||
|
|
||||||
|
# We're ignoring this jerk. Send back a suitable response.
|
||||||
|
if requesterId in self.ignoreList:
|
||||||
|
self.d_teleportResponse(self.doId, 2, 0, 0, 0, sendToId = requesterId)
|
||||||
|
return
|
||||||
|
|
||||||
|
# If we're in a private party and the requester isn't invited, tell
|
||||||
|
# them we're busy (ie: let them down easy, don't rub it in their face)
|
||||||
|
if hasattr(base, "distributedParty"):
|
||||||
|
if base.distributedParty.partyInfo.isPrivate:
|
||||||
|
# We need to check the guest list of this party and see if
|
||||||
|
# requesterId is on the list
|
||||||
|
if requesterId not in base.distributedParty.inviteeIds:
|
||||||
|
# Sorry, not on the list, send a try-again-later message
|
||||||
|
self.d_teleportResponse(self.doId, 0, 0, 0, 0, sendToId = requesterId)
|
||||||
|
return
|
||||||
|
|
||||||
|
if base.distributedParty.isPartyEnding:
|
||||||
|
self.d_teleportResponse(self.doId, 0, 0, 0, 0, sendToId = requesterId)
|
||||||
|
return
|
||||||
|
|
||||||
|
#print("teleport Available %s Ghost %s" % (self.__teleportAvailable, self.ghostMode))
|
||||||
|
if self.__teleportAvailable and not self.ghostMode:
|
||||||
|
# Generate a whisper message that so-and-so is teleporting
|
||||||
|
# to us.
|
||||||
|
self.setSystemMessage(requesterId, OTPLocalizer.WhisperComingToVisit % (avatar.getName()))
|
||||||
|
|
||||||
|
# We don't know where we are, so send a teleportQuery
|
||||||
|
# to someone who does. Whoever hangs a hook on this
|
||||||
|
# event will call the appropriate teleportResponse.
|
||||||
|
messenger.send('teleportQuery', [avatar, self])
|
||||||
|
return
|
||||||
|
|
||||||
|
# Generate a whisper message that so-and-so wants to
|
||||||
|
# teleport to us, but can't because we're busy. But don't
|
||||||
|
# generate more than one of these per minute or so.
|
||||||
|
if self.failedTeleportMessageOk(requesterId):
|
||||||
|
self.setSystemMessage(requesterId, OTPLocalizer.WhisperFailedVisit % (avatar.getName()))
|
||||||
|
|
||||||
|
|
||||||
|
# Send back a try-again-later message.
|
||||||
|
self.d_teleportResponse(self.doId, 0, 0, 0, 0, sendToId = requesterId)
|
||||||
|
|
||||||
|
def failedTeleportMessageOk(self, fromId):
|
||||||
|
"""failedTeleportMessageOk(self, int fromId)
|
||||||
|
|
||||||
|
Registers a failure-to-teleport attempt from the indicated
|
||||||
|
avatar. Returns true if it is ok to display this message, or
|
||||||
|
false if the message should be suppressed (because we just
|
||||||
|
recently displayed one).
|
||||||
|
"""
|
||||||
|
now = globalClock.getFrameTime()
|
||||||
|
lastTime = self.lastFailedTeleportMessage.get(fromId, None)
|
||||||
|
if lastTime != None:
|
||||||
|
elapsed = now - lastTime
|
||||||
|
if elapsed < self.TeleportFailureTimeout:
|
||||||
|
return 0
|
||||||
|
|
||||||
|
self.lastFailedTeleportMessage[fromId] = now
|
||||||
|
return 1
|
||||||
|
|
||||||
|
### teleportResponse ###
|
||||||
|
|
||||||
|
def d_teleportResponse(self, avId, available, shardId, hoodId, zoneId,
|
||||||
|
sendToId = None):
|
||||||
|
self.sendUpdate("teleportResponse", [avId, available, shardId, hoodId, zoneId], sendToId)
|
||||||
|
|
||||||
|
def teleportResponse(self, avId, available, shardId, hoodId, zoneId):
|
||||||
|
messenger.send('teleportResponse', [avId, available, shardId, hoodId, zoneId])
|
||||||
|
|
||||||
|
### teleportGiveup ###
|
||||||
|
|
||||||
|
def d_teleportGiveup(self, requesterId, sendToId = None):
|
||||||
|
self.sendUpdate("teleportGiveup", [requesterId], sendToId)
|
||||||
|
|
||||||
|
def teleportGiveup(self, requesterId):
|
||||||
|
"""teleportGiveup(self, int requesterId)
|
||||||
|
|
||||||
|
This message is sent after a client has failed to teleport
|
||||||
|
successfully to another client, probably because the target
|
||||||
|
client didn't stay put. It just pops up a whisper message to
|
||||||
|
that effect.
|
||||||
|
|
||||||
|
"""
|
||||||
|
avatar = base.cr.identifyAvatar(requesterId)
|
||||||
|
|
||||||
|
if not self._isValidWhisperSource(avatar):
|
||||||
|
self.notify.warning('teleportGiveup from non-toon %s' % requesterId)
|
||||||
|
return
|
||||||
|
|
||||||
|
if avatar != None:
|
||||||
|
self.setSystemMessage(requesterId, OTPLocalizer.WhisperGiveupVisit % (avatar.getName()))
|
||||||
|
|
||||||
|
### teleportGreeting ###
|
||||||
|
|
||||||
|
# This message is sent on completion of teleport, to set up the
|
||||||
|
# automatic "Hi, so-and-so" chat balloon. We can't use setChat
|
||||||
|
# because that gets garbled for speedchat-only clients.
|
||||||
|
|
||||||
|
def b_teleportGreeting(self, avId):
|
||||||
|
self.d_teleportGreeting(avId)
|
||||||
|
self.teleportGreeting(avId)
|
||||||
|
|
||||||
|
def d_teleportGreeting(self, avId):
|
||||||
|
self.sendUpdate("teleportGreeting", [avId])
|
||||||
|
|
||||||
|
def teleportGreeting(self, avId):
|
||||||
|
# Normally, the greeting will be issued to someone who we have
|
||||||
|
# just teleported to, and is therefore in the same zone with
|
||||||
|
# us. If this is so, it is easy to determine what the greeted
|
||||||
|
# toon's actual name is; otherwise, something went wrong
|
||||||
|
# (maybe our greeted toon just left!) and we can simply ignore
|
||||||
|
# the message.
|
||||||
|
|
||||||
|
avatar = base.cr.getDo(avId)
|
||||||
|
if isinstance(avatar, Avatar.Avatar):
|
||||||
|
self.setChatAbsolute(OTPLocalizer.TeleportGreeting % (
|
||||||
|
avatar.getName()), CFSpeech | CFTimeout)
|
||||||
|
elif avatar is not None:
|
||||||
|
self.notify.warning(
|
||||||
|
'got teleportGreeting from %s referencing non-toon %s' % (
|
||||||
|
self.doId, avId))
|
||||||
|
|
||||||
|
### Teleport support functions ###
|
||||||
|
|
||||||
|
def setTeleportAvailable(self, available):
|
||||||
|
"""setTeleportAvailable(self, bool available)
|
||||||
|
|
||||||
|
Sets the 'teleportAvailable' flag. When this is true, the
|
||||||
|
client is deemed to be available to be teleported to, and
|
||||||
|
someone should be listening to teleportQuery messages from the
|
||||||
|
messenger. When it is false, teleport queries from nearby
|
||||||
|
toons will automatically be returned with a false response
|
||||||
|
without generating a teleportQuery message.
|
||||||
|
"""
|
||||||
|
self.__teleportAvailable = available
|
||||||
|
|
||||||
|
def getTeleportAvailable(self):
|
||||||
|
return self.__teleportAvailable
|
||||||
|
|
||||||
|
def getFriendsList(self):
|
||||||
|
return self.friendsList
|
||||||
|
|
||||||
|
def setFriendsList(self, friendsList):
|
||||||
|
self.oldFriendsList = self.friendsList
|
||||||
|
self.friendsList = friendsList
|
||||||
|
self.timeFriendsListChanged = globalClock.getFrameTime()
|
||||||
|
assert self.notify.debug("setting friends list to %s" % self.friendsList)
|
||||||
|
|
||||||
|
# We want to throw a special event whenever the LocalToon's
|
||||||
|
# friends list changes, although not when just any
|
||||||
|
# DistributedToon's friends list changes. It would be cleaner
|
||||||
|
# to define this special behavior in LocalToon.py, but as it
|
||||||
|
# happens, it won't get called there because of the way
|
||||||
|
# ClientDistUpdate.py works.
|
||||||
|
|
||||||
|
# Fortunately, this method will *only* get called for
|
||||||
|
# LocalToon, and not for any of the other DistributedToons.
|
||||||
|
# So we can get away with putting this here.
|
||||||
|
messenger.send('friendsListChanged')
|
||||||
|
|
||||||
|
# When our friends list changes, the set of other avatars we
|
||||||
|
# can understand might also change.
|
||||||
|
Avatar.reconsiderAllUnderstandable()
|
||||||
|
|
||||||
|
def setDISLname(self, name):
|
||||||
|
self.DISLname = name
|
||||||
|
|
||||||
|
def setDISLid(self, id):
|
||||||
|
self.DISLid = id
|
||||||
|
|
||||||
|
|
||||||
|
def setAutoRun(self, value):
|
||||||
|
self.autoRun = value
|
||||||
|
|
||||||
|
def getAutoRun(self):
|
||||||
|
return self.autoRun
|
158
otp/src/avatar/DistributedPlayerAI.py
Normal file
158
otp/src/avatar/DistributedPlayerAI.py
Normal file
|
@ -0,0 +1,158 @@
|
||||||
|
|
||||||
|
from direct.showbase import GarbageReport
|
||||||
|
from otp.ai.AIBaseGlobal import *
|
||||||
|
from otp.avatar import DistributedAvatarAI
|
||||||
|
from otp.avatar import PlayerBase
|
||||||
|
from otp.otpbase import OTPGlobals
|
||||||
|
|
||||||
|
class DistributedPlayerAI(DistributedAvatarAI.DistributedAvatarAI,
|
||||||
|
PlayerBase.PlayerBase):
|
||||||
|
def __init__(self, air):
|
||||||
|
DistributedAvatarAI.DistributedAvatarAI.__init__(self, air)
|
||||||
|
PlayerBase.PlayerBase.__init__(self)
|
||||||
|
self.friendsList = []
|
||||||
|
|
||||||
|
if __dev__:
|
||||||
|
def generate(self):
|
||||||
|
self._sentExitServerEvent = False
|
||||||
|
DistributedAvatarAI.DistributedAvatarAI.generate(self)
|
||||||
|
|
||||||
|
def announceGenerate(self):
|
||||||
|
DistributedAvatarAI.DistributedAvatarAI.announceGenerate(self)
|
||||||
|
self._doPlayerEnter()
|
||||||
|
|
||||||
|
def _announceArrival(self):
|
||||||
|
self.sendUpdate('arrivedOnDistrict', [self.air.districtId])
|
||||||
|
|
||||||
|
def _announceExit(self):
|
||||||
|
# clear out the 'arrivedOnDistrict' field
|
||||||
|
self.sendUpdate('arrivedOnDistrict', [0])
|
||||||
|
|
||||||
|
def _sendExitServerEvent(self):
|
||||||
|
"""call this in your delete() function. This would be an
|
||||||
|
override of delete(), but player classes typically use
|
||||||
|
multiple inheritance, and some other base class gets to
|
||||||
|
call down the chain to DistributedObjectAI before this
|
||||||
|
class gets a chance, and self.air & self.doId are removed
|
||||||
|
in the first call to DistributedObjectAI.delete(). Better
|
||||||
|
would be reference counting calls to generate() and delete()
|
||||||
|
in base classes that appear more than once in a class'
|
||||||
|
inheritance heirarchy"""
|
||||||
|
self.air.writeServerEvent('avatarExit', self.doId, '')
|
||||||
|
if __dev__:
|
||||||
|
self._sentExitServerEvent = True
|
||||||
|
|
||||||
|
def delete(self):
|
||||||
|
if __dev__:
|
||||||
|
# make sure _sendExitServerEvent() was called
|
||||||
|
assert self._sentExitServerEvent
|
||||||
|
del self._sentExitServerEvent
|
||||||
|
self._doPlayerExit()
|
||||||
|
if __dev__:
|
||||||
|
GarbageReport.checkForGarbageLeaks()
|
||||||
|
DistributedAvatarAI.DistributedAvatarAI.delete(self)
|
||||||
|
|
||||||
|
def isPlayerControlled(self):
|
||||||
|
return True
|
||||||
|
|
||||||
|
def setLocation(self, parentId, zoneId, teleport=0):
|
||||||
|
DistributedAvatarAI.DistributedAvatarAI.setLocation(self, parentId, zoneId, teleport)
|
||||||
|
if self.isPlayerControlled():
|
||||||
|
# hmm, did this come from a hacker trying to get somewhere they shouldn't be?
|
||||||
|
if not self.air._isValidPlayerLocation(parentId, zoneId):
|
||||||
|
self.notify.info('booting player %s for doing setLocation to (%s, %s)' % (
|
||||||
|
self.doId, parentId, zoneId))
|
||||||
|
self.air.writeServerEvent('suspicious', self.doId,
|
||||||
|
'invalid setLocation: (%s, %s)' % (parentId, zoneId))
|
||||||
|
self.requestDelete()
|
||||||
|
|
||||||
|
def _doPlayerEnter(self):
|
||||||
|
self.incrementPopulation()
|
||||||
|
self._announceArrival()
|
||||||
|
|
||||||
|
def _doPlayerExit(self):
|
||||||
|
self._announceExit()
|
||||||
|
self.decrementPopulation()
|
||||||
|
|
||||||
|
# override if you don't want to affect the population count for a
|
||||||
|
# particular PlayerAI
|
||||||
|
def incrementPopulation(self):
|
||||||
|
self.air.incrementPopulation()
|
||||||
|
def decrementPopulation(self):
|
||||||
|
# use simbase in case we've already deleted self.air
|
||||||
|
simbase.air.decrementPopulation()
|
||||||
|
|
||||||
|
def b_setChat(self, chatString, chatFlags):
|
||||||
|
# Local
|
||||||
|
self.setChat(chatString, chatFlags)
|
||||||
|
# Distributed
|
||||||
|
self.d_setChat(chatString, chatFlags)
|
||||||
|
|
||||||
|
def d_setChat(self, chatString, chatFlags):
|
||||||
|
self.sendUpdate("setChat", [chatString, chatFlags])
|
||||||
|
|
||||||
|
def setChat(self, chatString, chatFlags):
|
||||||
|
# I guess on the AI side there is nothing to do here
|
||||||
|
pass
|
||||||
|
|
||||||
|
def d_setMaxHp(self, maxHp):
|
||||||
|
DistributedAvatarAI.DistributedAvatarAI.d_setMaxHp(self, maxHp)
|
||||||
|
self.air.writeServerEvent('setMaxHp', self.doId, '%s' % maxHp)
|
||||||
|
|
||||||
|
def d_setSystemMessage(self, aboutId, chatString):
|
||||||
|
self.sendUpdate("setSystemMessage", [aboutId, chatString])
|
||||||
|
|
||||||
|
def d_setCommonChatFlags(self, flags):
|
||||||
|
self.sendUpdate("setCommonChatFlags", [flags])
|
||||||
|
|
||||||
|
def setCommonChatFlags(self, flags):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def d_friendsNotify(self, avId, status):
|
||||||
|
self.sendUpdate("friendsNotify", [avId, status])
|
||||||
|
|
||||||
|
def friendsNotify(self, avId, status):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def setAccountName(self, accountName):
|
||||||
|
self.accountName = accountName
|
||||||
|
|
||||||
|
def getAccountName(self):
|
||||||
|
return self.accountName
|
||||||
|
|
||||||
|
def setDISLid(self, id):
|
||||||
|
self.DISLid = id
|
||||||
|
|
||||||
|
def d_setFriendsList(self, friendsList):
|
||||||
|
self.sendUpdate("setFriendsList", [friendsList])
|
||||||
|
|
||||||
|
def setFriendsList(self, friendsList):
|
||||||
|
self.friendsList = friendsList
|
||||||
|
self.notify.debug("setting friends list to %s" % self.friendsList)
|
||||||
|
|
||||||
|
def getFriendsList(self):
|
||||||
|
return self.friendsList
|
||||||
|
|
||||||
|
def extendFriendsList(self, friendId, friendCode):
|
||||||
|
# This is called only by the friend manager when a new friend
|
||||||
|
# transaction is successfully completed. Its purpose is
|
||||||
|
# simply to update the AI's own copy of the avatar's friends
|
||||||
|
# list, mainly so that the quest manager can reliably know
|
||||||
|
# if the avatar has any friends.
|
||||||
|
|
||||||
|
# First, see if we already had this friend.
|
||||||
|
for i in range(len(self.friendsList)):
|
||||||
|
friendPair = self.friendsList[i]
|
||||||
|
if friendPair[0] == friendId:
|
||||||
|
# We did. Update the code.
|
||||||
|
self.friendsList[i] = (friendId, friendCode)
|
||||||
|
return
|
||||||
|
|
||||||
|
# We didn't already have this friend; tack it on.
|
||||||
|
self.friendsList.append((friendId, friendCode))
|
||||||
|
|
||||||
|
# Note that if an avatar *breaks* a friendship, the AI never
|
||||||
|
# hears about it. So our friends list will not be 100%
|
||||||
|
# up-to-date, but it will at least be good enough for the
|
||||||
|
# quest manager.
|
||||||
|
|
29
otp/src/avatar/Emote.py
Normal file
29
otp/src/avatar/Emote.py
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
from otp.otpbase import OTPLocalizer
|
||||||
|
import types
|
||||||
|
|
||||||
|
class Emote:
|
||||||
|
|
||||||
|
EmoteClear = -1
|
||||||
|
EmoteEnableStateChanged = 'EmoteEnableStateChanged'
|
||||||
|
|
||||||
|
# Emote data is stored in the order it appears in the SpeedChat m
|
||||||
|
# The integer stored is the reference count to the Emote. If the
|
||||||
|
# count goes above zero, it means that the emote is disabled. Fo
|
||||||
|
# a minigame might increment the reference count if it wants to e
|
||||||
|
# disable emotes.
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
self.emoteFunc = None
|
||||||
|
|
||||||
|
def isEnabled(self, index):
|
||||||
|
# find the emotes index if we are given a string
|
||||||
|
if isinstance(index, types.StringType):
|
||||||
|
index = OTPLocalizer.EmoteFuncDict[index]
|
||||||
|
|
||||||
|
if self.emoteFunc == None:
|
||||||
|
return 0
|
||||||
|
elif self.emoteFunc[index][1] == 0:
|
||||||
|
return 1
|
||||||
|
return 0
|
||||||
|
|
||||||
|
globalEmote = None
|
2050
otp/src/avatar/LocalAvatar.py
Normal file
2050
otp/src/avatar/LocalAvatar.py
Normal file
File diff suppressed because it is too large
Load diff
23
otp/src/avatar/PlayerBase.py
Normal file
23
otp/src/avatar/PlayerBase.py
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
|
||||||
|
class PlayerBase:
|
||||||
|
# player code shared by AI & client
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
self.gmState = False
|
||||||
|
pass
|
||||||
|
|
||||||
|
def atLocation(self, locationId):
|
||||||
|
return True
|
||||||
|
|
||||||
|
def getLocation(self):
|
||||||
|
# return a list of locationIds, starting from general location
|
||||||
|
# (i.e. 'Pirates') down to specific location (i.e. jungle ID)
|
||||||
|
return []
|
||||||
|
|
||||||
|
def setAsGM(self, state):
|
||||||
|
""" Toggle GM privilages """
|
||||||
|
self.gmState = state
|
||||||
|
|
||||||
|
def isGM(self):
|
||||||
|
return self.gmState
|
||||||
|
|
159
otp/src/avatar/PositionExaminer.py
Normal file
159
otp/src/avatar/PositionExaminer.py
Normal file
|
@ -0,0 +1,159 @@
|
||||||
|
|
||||||
|
from pandac.PandaModules import *
|
||||||
|
from direct.showbase.DirectObject import DirectObject
|
||||||
|
from otp.otpbase import OTPGlobals
|
||||||
|
|
||||||
|
class PositionExaminer(DirectObject, NodePath):
|
||||||
|
"""
|
||||||
|
This class defines an object that can be used to examine a point in
|
||||||
|
space for suitability for standing on. It's used, for instance,
|
||||||
|
to choose a particular point to Go to when you Goto a friend.
|
||||||
|
|
||||||
|
A valid destination point is one that (a) has a ground whose
|
||||||
|
height is not too far from our target height, (b) is not already
|
||||||
|
occupied, and (c) is not behind a wall.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
try:
|
||||||
|
self.__initialized
|
||||||
|
return
|
||||||
|
except:
|
||||||
|
self.__initialized = 1
|
||||||
|
|
||||||
|
# initialize our NodePath essence
|
||||||
|
NodePath.__init__(self, hidden.attachNewNode('PositionExaminer'))
|
||||||
|
|
||||||
|
# Set up the collison ray. This is a ray cast from the head
|
||||||
|
# height down to detect floor polygons. It will tell us the
|
||||||
|
# height of the floor at our proposed position.
|
||||||
|
self.cRay = CollisionRay(0.0, 0.0, 6.0, 0.0, 0.0, -1.0)
|
||||||
|
self.cRayNode = CollisionNode('cRayNode')
|
||||||
|
self.cRayNode.addSolid(self.cRay)
|
||||||
|
self.cRayNodePath = self.attachNewNode(self.cRayNode)
|
||||||
|
self.cRayNodePath.hide()
|
||||||
|
self.cRayBitMask = OTPGlobals.FloorBitmask
|
||||||
|
self.cRayNode.setFromCollideMask(self.cRayBitMask)
|
||||||
|
self.cRayNode.setIntoCollideMask(BitMask32.allOff())
|
||||||
|
|
||||||
|
# Set up the collision sphere. This is a sphere on the ground
|
||||||
|
# that exactly matches the position and size of an avatar's
|
||||||
|
# sphere. It will tell us if our proposed position is occupied
|
||||||
|
# by anyone else.
|
||||||
|
self.cSphere = CollisionSphere(0.0, 0.0, 0.0, 1.5)
|
||||||
|
self.cSphereNode = CollisionNode('cSphereNode')
|
||||||
|
self.cSphereNode.addSolid(self.cSphere)
|
||||||
|
self.cSphereNodePath = self.attachNewNode(self.cSphereNode)
|
||||||
|
self.cSphereNodePath.hide()
|
||||||
|
self.cSphereBitMask = OTPGlobals.WallBitmask
|
||||||
|
self.cSphereNode.setFromCollideMask(self.cSphereBitMask)
|
||||||
|
self.cSphereNode.setIntoCollideMask(BitMask32.allOff())
|
||||||
|
|
||||||
|
# Set up the camera obstruction test line segment. This is a
|
||||||
|
# line segment from the proposed position point to our target
|
||||||
|
# position, to ensure that we are not behind a wall.
|
||||||
|
self.ccLine = CollisionSegment(0.0, 0.0, 0.0, 1.0, 0.0, 0.0)
|
||||||
|
self.ccLineNode = CollisionNode('ccLineNode')
|
||||||
|
self.ccLineNode.addSolid(self.ccLine)
|
||||||
|
self.ccLineNodePath = self.attachNewNode(self.ccLineNode)
|
||||||
|
self.ccLineNodePath.hide()
|
||||||
|
self.ccLineBitMask = OTPGlobals.CameraBitmask
|
||||||
|
self.ccLineNode.setFromCollideMask(self.ccLineBitMask)
|
||||||
|
self.ccLineNode.setIntoCollideMask(BitMask32.allOff())
|
||||||
|
|
||||||
|
# Now the gnarly part. Each of the above colliders must have
|
||||||
|
# a separate traverser, so we can independently activate each
|
||||||
|
# one and query the results.
|
||||||
|
self.cRayTrav = CollisionTraverser("PositionExaminer.cRayTrav")
|
||||||
|
self.cRayTrav.setRespectPrevTransform(False)
|
||||||
|
self.cRayQueue = CollisionHandlerQueue()
|
||||||
|
self.cRayTrav.addCollider(self.cRayNodePath, self.cRayQueue)
|
||||||
|
|
||||||
|
self.cSphereTrav = CollisionTraverser("PositionExaminer.cSphereTrav")
|
||||||
|
self.cSphereTrav.setRespectPrevTransform(False)
|
||||||
|
self.cSphereQueue = CollisionHandlerQueue()
|
||||||
|
self.cSphereTrav.addCollider(self.cSphereNodePath, self.cSphereQueue)
|
||||||
|
|
||||||
|
self.ccLineTrav = CollisionTraverser("PositionExaminer.ccLineTrav")
|
||||||
|
self.ccLineTrav.setRespectPrevTransform(False)
|
||||||
|
self.ccLineQueue = CollisionHandlerQueue()
|
||||||
|
self.ccLineTrav.addCollider(self.ccLineNodePath, self.ccLineQueue)
|
||||||
|
|
||||||
|
def delete(self):
|
||||||
|
del self.cRay
|
||||||
|
del self.cRayNode
|
||||||
|
self.cRayNodePath.removeNode()
|
||||||
|
del self.cRayNodePath
|
||||||
|
|
||||||
|
del self.cSphere
|
||||||
|
del self.cSphereNode
|
||||||
|
self.cSphereNodePath.removeNode()
|
||||||
|
del self.cSphereNodePath
|
||||||
|
|
||||||
|
del self.ccLine
|
||||||
|
del self.ccLineNode
|
||||||
|
self.ccLineNodePath.removeNode()
|
||||||
|
del self.ccLineNodePath
|
||||||
|
|
||||||
|
del self.cRayTrav
|
||||||
|
del self.cRayQueue
|
||||||
|
|
||||||
|
del self.cSphereTrav
|
||||||
|
del self.cSphereQueue
|
||||||
|
|
||||||
|
del self.ccLineTrav
|
||||||
|
del self.ccLineQueue
|
||||||
|
|
||||||
|
|
||||||
|
def consider(self, node, pos, eyeHeight):
|
||||||
|
"""consider(self, NodePath node, Point3 pos, eyeHeight)
|
||||||
|
|
||||||
|
Considers the indicated point, relative to the given NodePath.
|
||||||
|
The point must have a floor polygon that's within a foot or
|
||||||
|
two of the NodePath's origin, there must be no one standing
|
||||||
|
near the point, and it must have a clear line-of-sight to the
|
||||||
|
NodePath's origin.
|
||||||
|
|
||||||
|
Returns the actual point to stand if all these conditions are
|
||||||
|
met, or None if one of them fails.
|
||||||
|
"""
|
||||||
|
self.reparentTo(node)
|
||||||
|
self.setPos(pos)
|
||||||
|
|
||||||
|
result = None
|
||||||
|
|
||||||
|
# First, check that we have a good floor here.
|
||||||
|
self.cRayTrav.traverse(render)
|
||||||
|
if self.cRayQueue.getNumEntries() != 0:
|
||||||
|
|
||||||
|
# Ok, we have a floor. Choose the highest of the possibly
|
||||||
|
# several floors we're over.
|
||||||
|
|
||||||
|
self.cRayQueue.sortEntries()
|
||||||
|
floorPoint = self.cRayQueue.getEntry(0).getSurfacePoint(self.cRayNodePath)
|
||||||
|
|
||||||
|
if abs(floorPoint[2]) <= 4.0:
|
||||||
|
# And the floor is not too high or too low.
|
||||||
|
pos += floorPoint
|
||||||
|
self.setPos(pos)
|
||||||
|
|
||||||
|
# Now check that no one else is standing right here.
|
||||||
|
self.cSphereTrav.traverse(render)
|
||||||
|
if self.cSphereQueue.getNumEntries() == 0:
|
||||||
|
# No one's standing there, and there's no wall.
|
||||||
|
|
||||||
|
# Now check that we have a clear line-of-sight.
|
||||||
|
self.ccLine.setPointA(0, 0, eyeHeight)
|
||||||
|
self.ccLine.setPointB(-pos[0], -pos[1], eyeHeight)
|
||||||
|
self.ccLineTrav.traverse(render)
|
||||||
|
if self.ccLineQueue.getNumEntries() == 0:
|
||||||
|
# We're not behind a wall or anything.
|
||||||
|
result = pos
|
||||||
|
|
||||||
|
self.reparentTo(hidden)
|
||||||
|
self.cRayQueue.clearEntries()
|
||||||
|
self.cSphereQueue.clearEntries()
|
||||||
|
self.ccLineQueue.clearEntries()
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
198
otp/src/avatar/ShadowCaster.py
Normal file
198
otp/src/avatar/ShadowCaster.py
Normal file
|
@ -0,0 +1,198 @@
|
||||||
|
|
||||||
|
from pandac.PandaModules import *
|
||||||
|
from pandac.PandaModules import *
|
||||||
|
from direct.directnotify import DirectNotifyGlobal
|
||||||
|
from direct.showbase.ShadowPlacer import ShadowPlacer
|
||||||
|
from otp.otpbase import OTPGlobals
|
||||||
|
|
||||||
|
# This global variable will be set true or false according to whether
|
||||||
|
# all avatar's drop shadows should be made visible, by the
|
||||||
|
# TimeOfDayManager (which currently manages projected shadows).
|
||||||
|
# Always change its state via this function, instead of monkeying with
|
||||||
|
# it directly.
|
||||||
|
globalDropShadowFlag = 1
|
||||||
|
def setGlobalDropShadowFlag(flag):
|
||||||
|
global globalDropShadowFlag
|
||||||
|
if flag != globalDropShadowFlag:
|
||||||
|
globalDropShadowFlag = flag
|
||||||
|
messenger.send('globalDropShadowFlagChanged')
|
||||||
|
|
||||||
|
# A similar trick to control the global gray level of the drop shadows.
|
||||||
|
globalDropShadowGrayLevel = 0.5
|
||||||
|
def setGlobalDropShadowGrayLevel(grayLevel):
|
||||||
|
global globalDropShadowGrayLevel
|
||||||
|
if grayLevel != globalDropShadowGrayLevel:
|
||||||
|
globalDropShadowGrayLevel = grayLevel
|
||||||
|
messenger.send('globalDropShadowGrayLevelChanged')
|
||||||
|
|
||||||
|
# I made this inherit from DirectObject so that non-distributed things can cast shadows
|
||||||
|
|
||||||
|
class ShadowCaster:
|
||||||
|
|
||||||
|
notify = DirectNotifyGlobal.directNotify.newCategory("ShadowCaster")
|
||||||
|
#notify.setDebug(1)
|
||||||
|
|
||||||
|
def __init__(self, squareShadow = False):
|
||||||
|
assert self.notify.debugStateCall(self)
|
||||||
|
# some shadow initialization stuff
|
||||||
|
if squareShadow:
|
||||||
|
self.shadowFileName = "phase_3/models/props/square_drop_shadow"
|
||||||
|
else:
|
||||||
|
self.shadowFileName = "phase_3/models/props/drop_shadow"
|
||||||
|
|
||||||
|
self.dropShadow = None
|
||||||
|
self.shadowPlacer = None
|
||||||
|
self.activeShadow = 0
|
||||||
|
self.wantsActive = 1
|
||||||
|
self.storedActiveState = 0
|
||||||
|
|
||||||
|
# Only create these hooks if we're running a game that cares
|
||||||
|
# about them.
|
||||||
|
if hasattr(base,"wantDynamicShadows") and base.wantDynamicShadows:
|
||||||
|
messenger.accept('globalDropShadowFlagChanged', self, self.__globalDropShadowFlagChanged)
|
||||||
|
messenger.accept('globalDropShadowGrayLevelChanged', self, self.__globalDropShadowGrayLevelChanged)
|
||||||
|
|
||||||
|
def delete(self):
|
||||||
|
assert self.notify.debugStateCall(self)
|
||||||
|
|
||||||
|
# Only remove these hooks if we're running a game that cares
|
||||||
|
# about them.
|
||||||
|
if hasattr(base,"wantDynamicShadows") and base.wantDynamicShadows:
|
||||||
|
messenger.ignore('globalDropShadowFlagChanged', self)
|
||||||
|
messenger.ignore('globalDropShadowGrayLevelChanged', self)
|
||||||
|
self.deleteDropShadow()
|
||||||
|
self.shadowJoint = None
|
||||||
|
|
||||||
|
def initializeDropShadow(self, hasGeomNode=True):
|
||||||
|
"""
|
||||||
|
Load up and arrange the drop shadow
|
||||||
|
"""
|
||||||
|
assert self.notify.debugStateCall(self)
|
||||||
|
# First, protect this function from being called twice by
|
||||||
|
# removing the old ones first.
|
||||||
|
self.deleteDropShadow()
|
||||||
|
|
||||||
|
# This will be used by the shadow system to identify things
|
||||||
|
# that might want to have projected shadows drawn.
|
||||||
|
if hasGeomNode:
|
||||||
|
self.getGeomNode().setTag('cam', 'caster')
|
||||||
|
|
||||||
|
# make the object float above the shadow slightly
|
||||||
|
# not necessarily a good idea for all avatars
|
||||||
|
#self.getGeomNode().setZ(0.025)
|
||||||
|
|
||||||
|
# load and prep the drop shadow
|
||||||
|
dropShadow = loader.loadModel(self.shadowFileName)
|
||||||
|
dropShadow.setScale(0.4) # Slightly smaller to compensate for billboard
|
||||||
|
|
||||||
|
dropShadow.flattenMedium()
|
||||||
|
dropShadow.setBillboardAxis(2) # slide the shadow towards the camera
|
||||||
|
dropShadow.setColor(0.0, 0.0, 0.0, globalDropShadowGrayLevel, 1) # override of 1 to prevent avatar.setColor() from affecting shadows.
|
||||||
|
self.shadowPlacer = ShadowPlacer(
|
||||||
|
base.shadowTrav, dropShadow,
|
||||||
|
OTPGlobals.WallBitmask, OTPGlobals.FloorBitmask)
|
||||||
|
self.dropShadow = dropShadow
|
||||||
|
if not globalDropShadowFlag:
|
||||||
|
self.dropShadow.hide()
|
||||||
|
if self.getShadowJoint():
|
||||||
|
dropShadow.reparentTo(self.getShadowJoint())
|
||||||
|
else:
|
||||||
|
self.dropShadow.hide()
|
||||||
|
|
||||||
|
# Set the state of the shadow placers (in case someone set the
|
||||||
|
# value before now):
|
||||||
|
self.setActiveShadow(self.wantsActive)
|
||||||
|
|
||||||
|
self.__globalDropShadowFlagChanged()
|
||||||
|
self.__globalDropShadowGrayLevelChanged()
|
||||||
|
|
||||||
|
def update(self):
|
||||||
|
"""This method is meant to be overriden."""
|
||||||
|
# Toontown doesn't have self.update() for all shadowcasters
|
||||||
|
# but initializeDropShadow calls it, so this prevents a crash.
|
||||||
|
pass
|
||||||
|
|
||||||
|
def deleteDropShadow(self):
|
||||||
|
"""
|
||||||
|
Lose the drop shadows
|
||||||
|
"""
|
||||||
|
assert self.notify.debugStateCall(self)
|
||||||
|
if self.shadowPlacer:
|
||||||
|
self.shadowPlacer.delete()
|
||||||
|
self.shadowPlacer = None
|
||||||
|
|
||||||
|
if self.dropShadow:
|
||||||
|
self.dropShadow.removeNode()
|
||||||
|
self.dropShadow = None
|
||||||
|
|
||||||
|
def setActiveShadow(self, isActive=1):
|
||||||
|
"""
|
||||||
|
Turn the shadow placement on or off.
|
||||||
|
"""
|
||||||
|
assert self.notify.debugStateCall(self)
|
||||||
|
|
||||||
|
isActive = isActive and self.wantsActive
|
||||||
|
if(not globalDropShadowFlag):
|
||||||
|
self.storedActiveState = isActive
|
||||||
|
# changed logic to prevent crash (test remark 13203) - grw
|
||||||
|
if self.shadowPlacer != None:
|
||||||
|
isActive = isActive and globalDropShadowFlag
|
||||||
|
if self.activeShadow != isActive:
|
||||||
|
self.activeShadow = isActive
|
||||||
|
if isActive:
|
||||||
|
self.shadowPlacer.on()
|
||||||
|
else:
|
||||||
|
self.shadowPlacer.off()
|
||||||
|
|
||||||
|
|
||||||
|
def setShadowHeight(self, shadowHeight):
|
||||||
|
"""
|
||||||
|
Places the shadow at a particular height below the avatar (in
|
||||||
|
effect, asserting that the avatar is shadowHeight feet above
|
||||||
|
the ground).
|
||||||
|
|
||||||
|
This is only useful when the active shadow is disabled via
|
||||||
|
setActiveShadow(0).
|
||||||
|
"""
|
||||||
|
assert self.notify.debugStateCall(self)
|
||||||
|
if self.dropShadow:
|
||||||
|
self.dropShadow.setZ(-shadowHeight)
|
||||||
|
|
||||||
|
def getShadowJoint(self):
|
||||||
|
assert self.notify.debugStateCall(self)
|
||||||
|
if hasattr(self, "shadowJoint"):
|
||||||
|
return self.shadowJoint
|
||||||
|
shadowJoint = self.find('**/attachShadow')
|
||||||
|
if shadowJoint.isEmpty():
|
||||||
|
# We make a fresh NodePath that refers to the same node as
|
||||||
|
# self, rather than assigning self directly--this will
|
||||||
|
# prevent a cyclic Python reference.
|
||||||
|
self.shadowJoint = NodePath(self)
|
||||||
|
else:
|
||||||
|
self.shadowJoint = shadowJoint
|
||||||
|
return self.shadowJoint
|
||||||
|
|
||||||
|
def hideShadow(self):
|
||||||
|
assert self.notify.debugStateCall(self)
|
||||||
|
self.dropShadow.hide()
|
||||||
|
|
||||||
|
def showShadow(self):
|
||||||
|
assert self.notify.debugStateCall(self)
|
||||||
|
if not globalDropShadowFlag:
|
||||||
|
self.dropShadow.hide()
|
||||||
|
else:
|
||||||
|
self.dropShadow.show()
|
||||||
|
|
||||||
|
def __globalDropShadowFlagChanged(self):
|
||||||
|
if (self.dropShadow != None):
|
||||||
|
if(globalDropShadowFlag == 0):
|
||||||
|
if(self.activeShadow == 1):
|
||||||
|
self.storedActiveState = 1
|
||||||
|
self.setActiveShadow(0)
|
||||||
|
elif(self.activeShadow == 0):
|
||||||
|
self.setActiveShadow(1)
|
||||||
|
self.showShadow()
|
||||||
|
|
||||||
|
def __globalDropShadowGrayLevelChanged(self):
|
||||||
|
if (self.dropShadow != None):
|
||||||
|
self.dropShadow.setColor(0.0, 0.0, 0.0, globalDropShadowGrayLevel, 1)
|
3
otp/src/avatar/Sources.pp
Normal file
3
otp/src/avatar/Sources.pp
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
// For now, since we are not installing Python files, this file can
|
||||||
|
// remain empty.
|
||||||
|
|
0
otp/src/avatar/__init__.py
Normal file
0
otp/src/avatar/__init__.py
Normal file
4
otp/src/chat/.cvsignore
Normal file
4
otp/src/chat/.cvsignore
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
.cvsignore
|
||||||
|
Makefile
|
||||||
|
*.pyc
|
||||||
|
pp.dep
|
56
otp/src/chat/ChatGarbler.py
Normal file
56
otp/src/chat/ChatGarbler.py
Normal file
|
@ -0,0 +1,56 @@
|
||||||
|
"""ChatGarbler module: conatins the ChatGarbler class"""
|
||||||
|
|
||||||
|
import string
|
||||||
|
#import whrandom
|
||||||
|
import random
|
||||||
|
from otp.otpbase import OTPLocalizer
|
||||||
|
|
||||||
|
class ChatGarbler:
|
||||||
|
"""ChatGarbler class: contains methods to convert chat messages
|
||||||
|
to animal sounds"""
|
||||||
|
|
||||||
|
def garble(self, avatar, message):
|
||||||
|
"""garble(self, Avatar, string)
|
||||||
|
Replace a chat message with a series of animal sounds
|
||||||
|
based on the toon's animal type
|
||||||
|
Algorithm completely disregards original message to
|
||||||
|
prohibit any sort of meaningful communication
|
||||||
|
"""
|
||||||
|
newMessage = ""
|
||||||
|
|
||||||
|
numWords = random.randint(1, 7)
|
||||||
|
|
||||||
|
wordlist = OTPLocalizer.ChatGarblerDefault
|
||||||
|
|
||||||
|
for i in range(1, numWords+1):
|
||||||
|
wordIndex = random.randint(0, len(wordlist)-1)
|
||||||
|
newMessage = newMessage + wordlist[wordIndex]
|
||||||
|
if (i < numWords):
|
||||||
|
newMessage = newMessage + " "
|
||||||
|
|
||||||
|
return newMessage
|
||||||
|
|
||||||
|
def garbleSingle(self, avatar, message):
|
||||||
|
"""garble(self, Avatar, string)
|
||||||
|
Replace a chat message with a series of animal sounds
|
||||||
|
based on the toon's animal type
|
||||||
|
Algorithm completely disregards original message to
|
||||||
|
prohibit any sort of meaningful communication
|
||||||
|
"""
|
||||||
|
newMessage = ""
|
||||||
|
|
||||||
|
numWords = 1
|
||||||
|
|
||||||
|
wordlist = OTPLocalizer.ChatGarblerDefault
|
||||||
|
|
||||||
|
for i in range(1, numWords+1):
|
||||||
|
wordIndex = random.randint(0, len(wordlist)-1)
|
||||||
|
newMessage = newMessage + wordlist[wordIndex]
|
||||||
|
if (i < numWords):
|
||||||
|
newMessage = newMessage + " "
|
||||||
|
|
||||||
|
return newMessage
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
77
otp/src/chat/ChatGlobals.py
Normal file
77
otp/src/chat/ChatGlobals.py
Normal file
|
@ -0,0 +1,77 @@
|
||||||
|
import string
|
||||||
|
|
||||||
|
NORMAL_CHAT = 1
|
||||||
|
WHISPER_CHAT = 2
|
||||||
|
GUILD_CHAT = 3
|
||||||
|
CREW_CHAT = 4
|
||||||
|
SHIPPVP_CHAT = 5
|
||||||
|
|
||||||
|
# ERROR CODES
|
||||||
|
ERROR_NONE = None
|
||||||
|
ERROR_NO_OPEN_CHAT = 1
|
||||||
|
ERROR_NOT_FRIENDS = 2
|
||||||
|
ERROR_NO_RECEIVER = 3
|
||||||
|
ERROR_NO_GUILD_CHAT = 4
|
||||||
|
ERROR_NO_CREW_CHAT = 5
|
||||||
|
ERROR_NO_SHIPPVP_CHAT = 6
|
||||||
|
|
||||||
|
#CHAT TYPES
|
||||||
|
TYPEDCHAT = 0
|
||||||
|
SPEEDCHAT_NORMAL = 1
|
||||||
|
SPEEDCHAT_EMOTE = 2
|
||||||
|
SPEEDCHAT_CUSTOM = 3
|
||||||
|
SYSTEMCHAT = 4
|
||||||
|
GAMECHAT = 5
|
||||||
|
GUILDCHAT = 6
|
||||||
|
PARTYCHAT = 7
|
||||||
|
SPEEDCHAT_QUEST = 8
|
||||||
|
FRIEND_UPDATE = 9
|
||||||
|
CREW_UPDATE = 10
|
||||||
|
GUILD_UPDATE = 11
|
||||||
|
AVATAR_UNAVAILABLE = 12
|
||||||
|
SHIPPVPCHAT = 13
|
||||||
|
GMCHAT = 14
|
||||||
|
|
||||||
|
# the events are hierarchical; when a
|
||||||
|
# speedchat msg is picked, for instance, the
|
||||||
|
# following events will be sent:
|
||||||
|
# 'ChatEvent', 'SCChatEvent'
|
||||||
|
ChatEvent = 'ChatEvent'
|
||||||
|
NormalChatEvent = 'NormalChatEvent'
|
||||||
|
SCChatEvent = 'SCChatEvent'
|
||||||
|
SCCustomChatEvent = 'SCCustomChatEvent'
|
||||||
|
SCEmoteChatEvent = 'SCEmoteChatEvent'
|
||||||
|
SCQuestEvent = 'SCQuestEvent'
|
||||||
|
|
||||||
|
OnScreen = 0
|
||||||
|
OffScreen = 1
|
||||||
|
Thought = 2
|
||||||
|
ThoughtPrefix = '.'
|
||||||
|
|
||||||
|
# thought methods
|
||||||
|
def isThought(message):
|
||||||
|
"""
|
||||||
|
message is a string.
|
||||||
|
|
||||||
|
Return 1 if the given string contains the thought prefix,
|
||||||
|
Return 0 otherwise
|
||||||
|
"""
|
||||||
|
if (len(message) == 0):
|
||||||
|
# empty string cannot be a thought
|
||||||
|
return 0
|
||||||
|
elif (string.find(message, ThoughtPrefix, 0,
|
||||||
|
len(ThoughtPrefix)) >= 0):
|
||||||
|
return 1
|
||||||
|
else:
|
||||||
|
return 0
|
||||||
|
|
||||||
|
def removeThoughtPrefix(message):
|
||||||
|
"""
|
||||||
|
message is a string.
|
||||||
|
|
||||||
|
Return the string with the thought prefix removed
|
||||||
|
"""
|
||||||
|
if (isThought(message)):
|
||||||
|
return message[len(ThoughtPrefix):]
|
||||||
|
else:
|
||||||
|
return message
|
204
otp/src/chat/ChatInputNormal.py
Normal file
204
otp/src/chat/ChatInputNormal.py
Normal file
|
@ -0,0 +1,204 @@
|
||||||
|
"""ChatInputNormal module: contains the ChatInputNormal class"""
|
||||||
|
|
||||||
|
from direct.showbase import DirectObject
|
||||||
|
from otp.otpbase import OTPGlobals
|
||||||
|
import sys
|
||||||
|
from direct.gui.DirectGui import *
|
||||||
|
from pandac.PandaModules import *
|
||||||
|
from otp.otpbase import OTPLocalizer
|
||||||
|
|
||||||
|
class ChatInputNormal(DirectObject.DirectObject):
|
||||||
|
"""ChatInputNormal class: controls the chat input bubble, and handles
|
||||||
|
chat message construction"""
|
||||||
|
|
||||||
|
# This will hold the local namespace we evaluate '>chat' messages
|
||||||
|
# within.
|
||||||
|
ExecNamespace = None
|
||||||
|
|
||||||
|
# special methods
|
||||||
|
def __init__(self, chatMgr):
|
||||||
|
self.chatMgr = chatMgr
|
||||||
|
|
||||||
|
self.normalPos = Vec3(-1.083, 0, 0.804)
|
||||||
|
self.whisperPos = Vec3(0.0, 0, 0.71)
|
||||||
|
|
||||||
|
self.whisperAvatarName = None
|
||||||
|
self.whisperAvatarId = None
|
||||||
|
self.toPlayer = 0
|
||||||
|
|
||||||
|
wantHistory = 0
|
||||||
|
if __dev__:
|
||||||
|
wantHistory = 1
|
||||||
|
self.wantHistory = base.config.GetBool('want-chat-history', wantHistory)
|
||||||
|
self.history = ['']
|
||||||
|
self.historySize = base.config.GetInt('chat-history-size', 10)
|
||||||
|
self.historyIndex = 0
|
||||||
|
|
||||||
|
# It is up to a derived class, like TTChatInputNormal, to
|
||||||
|
# define self.chatFrame, self.chatButton, self.cancelButton,
|
||||||
|
# and self.whisperLabel.
|
||||||
|
|
||||||
|
|
||||||
|
def typeCallback(self, extraArgs):
|
||||||
|
messenger.send('enterNormalChat')
|
||||||
|
|
||||||
|
def delete(self):
|
||||||
|
self.ignore('arrow_up-up')
|
||||||
|
self.ignore('arrow_down-up')
|
||||||
|
self.chatFrame.destroy()
|
||||||
|
del self.chatFrame
|
||||||
|
del self.chatButton
|
||||||
|
del self.cancelButton
|
||||||
|
del self.chatEntry
|
||||||
|
del self.whisperLabel
|
||||||
|
del self.chatMgr
|
||||||
|
|
||||||
|
def activateByData(self, whisperAvatarId = None, toPlayer = 0):
|
||||||
|
self.toPlayer = toPlayer
|
||||||
|
self.whisperAvatarId = whisperAvatarId
|
||||||
|
self.whisperAvatarName = base.talkAssistant.findName(self.whisperAvatarId, self.toPlayer)
|
||||||
|
if self.whisperAvatarId:
|
||||||
|
self.chatFrame.setPos(self.whisperPos)
|
||||||
|
self.whisperLabel["text"] = (OTPLocalizer.ChatInputWhisperLabel %
|
||||||
|
(self.whisperAvatarName))
|
||||||
|
self.whisperLabel.show()
|
||||||
|
else:
|
||||||
|
self.chatFrame.setPos(self.normalPos)
|
||||||
|
self.whisperLabel.hide()
|
||||||
|
self.chatEntry['focus'] = 1
|
||||||
|
self.chatFrame.show()
|
||||||
|
|
||||||
|
if self.wantHistory:
|
||||||
|
self.accept('arrow_up-up', self.getPrevHistory)
|
||||||
|
self.accept('arrow_down-up', self.getNextHistory)
|
||||||
|
|
||||||
|
def deactivate(self):
|
||||||
|
self.chatEntry.set("")
|
||||||
|
self.chatEntry['focus'] = 0
|
||||||
|
self.chatFrame.hide()
|
||||||
|
self.whisperLabel.hide()
|
||||||
|
base.win.closeIme()
|
||||||
|
self.ignore('arrow_up-up')
|
||||||
|
self.ignore('arrow_down-up')
|
||||||
|
|
||||||
|
def checkForOverRide(self):
|
||||||
|
#ChatInputNormal likes to intercept other direct entries
|
||||||
|
#too much was hard wired to the chatManagar so I'm adding a final stage override - JML
|
||||||
|
return False
|
||||||
|
|
||||||
|
def sendChat(self, text):
|
||||||
|
"""
|
||||||
|
Send the text from the entry
|
||||||
|
"""
|
||||||
|
if self.checkForOverRide():
|
||||||
|
self.chatEntry.enterText("")
|
||||||
|
return
|
||||||
|
# Done for now, go away
|
||||||
|
self.deactivate()
|
||||||
|
self.chatMgr.fsm.request("mainMenu")
|
||||||
|
|
||||||
|
# Filter out empty string
|
||||||
|
if text:
|
||||||
|
if self.toPlayer:
|
||||||
|
if self.whisperAvatarId:
|
||||||
|
#base.cr.playerFriendsManager.sendWhisper(self.whisperAvatarId, text)
|
||||||
|
#base.chatAssistant.sendPlayerWhisperTypedChat(text, self.whisperAvatarId)
|
||||||
|
self.whisperAvatarName = None
|
||||||
|
self.whisperAvatarId = None
|
||||||
|
self.toPlayer = 0
|
||||||
|
|
||||||
|
elif self.whisperAvatarId:
|
||||||
|
self.chatMgr.sendWhisperString(text, self.whisperAvatarId)
|
||||||
|
self.whisperAvatarName = None
|
||||||
|
self.whisperAvatarId = None
|
||||||
|
else:
|
||||||
|
if self.chatMgr.execChat:
|
||||||
|
# Exec a python command
|
||||||
|
if (text[0] == '>'):
|
||||||
|
text = self.__execMessage(text[1:])
|
||||||
|
base.localAvatar.setChatAbsolute(text, CFSpeech | CFTimeout)
|
||||||
|
return
|
||||||
|
|
||||||
|
base.talkAssistant.sendOpenTalk(text)
|
||||||
|
|
||||||
|
if self.wantHistory:
|
||||||
|
self.addToHistory(text)
|
||||||
|
|
||||||
|
def chatOverflow(self, overflowText):
|
||||||
|
"""
|
||||||
|
When the user types too many lines of text, an event gets thrown
|
||||||
|
which calls this function. Right now it just sends the text just
|
||||||
|
as if you hit return to complete the sentence.
|
||||||
|
"""
|
||||||
|
self.sendChat(self.chatEntry.get())
|
||||||
|
|
||||||
|
def __execMessage(self, message):
|
||||||
|
if not ChatInputNormal.ExecNamespace:
|
||||||
|
# Import some useful variables into the ExecNamespace initially.
|
||||||
|
ChatInputNormal.ExecNamespace = { }
|
||||||
|
exec 'from pandac.PandaModules import *' in globals(), self.ExecNamespace
|
||||||
|
self.importExecNamespace()
|
||||||
|
|
||||||
|
# Now try to evaluate the expression using ChatInputNormal.ExecNamespace as
|
||||||
|
# the local namespace.
|
||||||
|
try:
|
||||||
|
return str(eval(message, globals(), ChatInputNormal.ExecNamespace))
|
||||||
|
|
||||||
|
except SyntaxError:
|
||||||
|
# Maybe it's only a statement, like "x = 1", or
|
||||||
|
# "import math". These aren't expressions, so eval()
|
||||||
|
# fails, but they can be exec'ed.
|
||||||
|
try:
|
||||||
|
exec message in globals(), ChatInputNormal.ExecNamespace
|
||||||
|
return 'ok'
|
||||||
|
except:
|
||||||
|
exception = sys.exc_info()[0]
|
||||||
|
extraInfo = sys.exc_info()[1]
|
||||||
|
if extraInfo:
|
||||||
|
return str(extraInfo)
|
||||||
|
else:
|
||||||
|
return str(exception)
|
||||||
|
except:
|
||||||
|
exception = sys.exc_info()[0]
|
||||||
|
extraInfo = sys.exc_info()[1]
|
||||||
|
if extraInfo:
|
||||||
|
return str(extraInfo)
|
||||||
|
else:
|
||||||
|
return str(exception)
|
||||||
|
|
||||||
|
# button event handlers
|
||||||
|
def cancelButtonPressed(self):
|
||||||
|
self.chatEntry.set("")
|
||||||
|
self.chatMgr.fsm.request("mainMenu")
|
||||||
|
|
||||||
|
def chatButtonPressed(self):
|
||||||
|
self.sendChat(self.chatEntry.get())
|
||||||
|
|
||||||
|
def importExecNamespace(self):
|
||||||
|
# Derived classes should take advantage of this hook to import
|
||||||
|
# useful variables into the chat namespace for developer
|
||||||
|
# access.
|
||||||
|
pass
|
||||||
|
|
||||||
|
def addToHistory(self, text):
|
||||||
|
self.history = [text] + self.history[:self.historySize-1]
|
||||||
|
self.historyIndex = 0
|
||||||
|
|
||||||
|
def getPrevHistory(self):
|
||||||
|
self.chatEntry.set(self.history[self.historyIndex])
|
||||||
|
self.historyIndex += 1
|
||||||
|
self.historyIndex %= len(self.history)
|
||||||
|
|
||||||
|
def getNextHistory(self):
|
||||||
|
self.chatEntry.set(self.history[self.historyIndex])
|
||||||
|
self.historyIndex -= 1
|
||||||
|
self.historyIndex %= len(self.history)
|
||||||
|
|
||||||
|
def setPos(self, posX, posY = None, posZ = None):
|
||||||
|
if posX and posY and posZ:
|
||||||
|
self.chatFrame.setPos(posX,posY,posZ)
|
||||||
|
else:
|
||||||
|
self.chatFrame.setPos(posX)
|
||||||
|
|
||||||
|
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue