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