Merge branch 'script'

This commit is contained in:
Marc Zinnschlag 2011-04-28 10:30:32 +02:00
commit 5b6ec405e3
19 changed files with 240 additions and 123 deletions

View file

@ -17,6 +17,8 @@ namespace MWGui
ConsoleInterpreterContext (Console& console, MWWorld::Environment& environment, ConsoleInterpreterContext (Console& console, MWWorld::Environment& environment,
MWWorld::Ptr reference); MWWorld::Ptr reference);
virtual void report (const std::string& message);
}; };
ConsoleInterpreterContext::ConsoleInterpreterContext (Console& console, ConsoleInterpreterContext::ConsoleInterpreterContext (Console& console,
@ -26,6 +28,11 @@ namespace MWGui
mConsole (console) mConsole (console)
{} {}
void ConsoleInterpreterContext::report (const std::string& message)
{
mConsole.printOK (message);
}
bool Console::compile (const std::string& cmd, Compiler::Output& output) bool Console::compile (const std::string& cmd, Compiler::Output& output)
{ {
try try

View file

@ -191,7 +191,7 @@ void MWScene::scaleObject (const std::string& handle, float scale)
} }
void MWScene::toggleCollisionMode() bool MWScene::toggleCollisionMode()
{ {
for(std::map<std::string,OEngine::Physic::PhysicActor*>::iterator it = eng->PhysicActorMap.begin(); it != eng->PhysicActorMap.end();it++) for(std::map<std::string,OEngine::Physic::PhysicActor*>::iterator it = eng->PhysicActorMap.begin(); it != eng->PhysicActorMap.end();it++)
{ {
@ -203,6 +203,7 @@ void MWScene::toggleCollisionMode()
act->setGravity(0.); act->setGravity(0.);
act->setVerticalVelocity(0); act->setVerticalVelocity(0);
mFreeFly = true; mFreeFly = true;
return false;
} }
else else
{ {
@ -210,11 +211,15 @@ void MWScene::toggleCollisionMode()
act->enableCollisions(true); act->enableCollisions(true);
act->setGravity(4.); act->setGravity(4.);
act->setVerticalVelocity(0); act->setVerticalVelocity(0);
return true;
} }
} }
return false; // This should never happen, but it shall not bother us now, since
// this part of the code needs a rewrite anyway.
} }
void MWScene::toggleRenderMode (int mode) bool MWScene::toggleRenderMode (int mode)
{ {
switch (mode) switch (mode)
{ {
@ -223,6 +228,8 @@ void MWScene::toggleRenderMode (int mode)
// TODO use a proper function instead of accessing the member variable // TODO use a proper function instead of accessing the member variable
// directly. // directly.
eng->setDebugRenderingMode (!eng->isDebugCreated); eng->setDebugRenderingMode (!eng->isDebugCreated);
break; return eng->isDebugCreated;
} }
return false;
} }

View file

@ -91,12 +91,14 @@ namespace MWRender
/// Toggle collision mode for player. If disabled player object should ignore /// Toggle collision mode for player. If disabled player object should ignore
/// collisions and gravity. /// collisions and gravity.
void toggleCollisionMode(); /// \return Resulting mode
bool toggleCollisionMode();
/// Toggle render mode /// Toggle render mode
/// \todo Using an int instead of a enum here to avoid cyclic includes. Will be fixed /// \todo Using an int instead of a enum here to avoid cyclic includes. Will be fixed
/// when the mw*-refactoring is done. /// when the mw*-refactoring is done.
void toggleRenderMode (int mode); /// \return Resulting mode
bool toggleRenderMode (int mode);
}; };
} }

View file

@ -102,10 +102,42 @@ namespace MWScript
} }
}; };
class OpGetPCCell : public Interpreter::Opcode0
{
public:
virtual void execute (Interpreter::Runtime& runtime)
{
InterpreterContext& context
= static_cast<InterpreterContext&> (runtime.getContext());
std::string name = runtime.getStringLiteral (runtime[0].mInteger);
runtime.pop();
const ESM::Cell *cell = context.getWorld().getPlayer().getPlayer().getCell()->cell;
std::string current = cell->name;
if (!(cell->data.flags & ESM::Cell::Interior) && current.empty())
{
const ESM::Region *region =
context.getWorld().getStore().regions.find (cell->region);
current = region->name;
}
bool match = current.length()>=name.length() &&
current.substr (0, name.length())==name;
runtime.push (match ? 1 : 0);
}
};
const int opcodeCellChanged = 0x2000000; const int opcodeCellChanged = 0x2000000;
const int opcodeCOC = 0x2000026; const int opcodeCOC = 0x2000026;
const int opcodeCOE = 0x200008e; const int opcodeCOE = 0x200008e;
const int opcodeGetInterior = 0x2000131; const int opcodeGetInterior = 0x2000131;
const int opcodeGetPCCell = 0x2000136;
void registerExtensions (Compiler::Extensions& extensions) void registerExtensions (Compiler::Extensions& extensions)
{ {
@ -115,6 +147,7 @@ namespace MWScript
extensions.registerInstruction ("coe", "ll", opcodeCOE); extensions.registerInstruction ("coe", "ll", opcodeCOE);
extensions.registerInstruction ("centeronexterior", "ll", opcodeCOE); extensions.registerInstruction ("centeronexterior", "ll", opcodeCOE);
extensions.registerFunction ("getinterior", 'l', "", opcodeGetInterior); extensions.registerFunction ("getinterior", 'l', "", opcodeGetInterior);
extensions.registerFunction ("getpccell", 'l', "c", opcodeGetPCCell);
} }
void installOpcodes (Interpreter::Interpreter& interpreter) void installOpcodes (Interpreter::Interpreter& interpreter)
@ -123,6 +156,7 @@ namespace MWScript
interpreter.installSegment5 (opcodeCOC, new OpCOC); interpreter.installSegment5 (opcodeCOC, new OpCOC);
interpreter.installSegment5 (opcodeCOE, new OpCOE); interpreter.installSegment5 (opcodeCOE, new OpCOE);
interpreter.installSegment5 (opcodeGetInterior, new OpGetInterior); interpreter.installSegment5 (opcodeGetInterior, new OpGetInterior);
interpreter.installSegment5 (opcodeGetPCCell, new OpGetPCCell);
} }
} }
} }

View file

@ -46,7 +46,9 @@ namespace MWScript
InterpreterContext& context InterpreterContext& context
= static_cast<InterpreterContext&> (runtime.getContext()); = static_cast<InterpreterContext&> (runtime.getContext());
context.getWorld().toggleCollisionMode(); bool enabled = context.getWorld().toggleCollisionMode();
context.report (enabled ? "Collsion -> On" : "Collision -> Off");
} }
}; };
@ -74,6 +76,7 @@ namespace MWScript
} }
extensions.registerInstruction ("togglecollision", "", opcodeToggleCollision); extensions.registerInstruction ("togglecollision", "", opcodeToggleCollision);
extensions.registerInstruction ("tcl", "", opcodeToggleCollision);
} }
void installOpcodes (Interpreter::Interpreter& interpreter) void installOpcodes (Interpreter::Interpreter& interpreter)

View file

@ -107,4 +107,5 @@ op 0x2000132: ToggleCollsionDebug
op 0x2000133: Journal op 0x2000133: Journal
op 0x2000134: SetJournalIndex op 0x2000134: SetJournalIndex
op 0x2000135: GetJournalIndex op 0x2000135: GetJournalIndex
opcodes 0x2000136-0x3ffffff unused op 0x2000136: GetPCCell
opcodes 0x2000137-0x3ffffff unused

View file

@ -110,6 +110,11 @@ namespace MWScript
mEnvironment.mWindowManager->messageBox (message, buttons); mEnvironment.mWindowManager->messageBox (message, buttons);
} }
void InterpreterContext::report (const std::string& message)
{
messageBox (message);
}
bool InterpreterContext::menuMode() bool InterpreterContext::menuMode()
{ {
return mEnvironment.mWindowManager->isGuiMode(); return mEnvironment.mWindowManager->isGuiMode();

View file

@ -57,9 +57,13 @@ namespace MWScript
virtual void setLocalFloat (int index, float value); virtual void setLocalFloat (int index, float value);
using Interpreter::Context::messageBox; using Interpreter::Context::messageBox;
virtual void messageBox (const std::string& message, virtual void messageBox (const std::string& message,
const std::vector<std::string>& buttons); const std::vector<std::string>& buttons);
virtual void report (const std::string& message);
///< By default echo via messageBox.
virtual bool menuMode(); virtual bool menuMode();
virtual int getGlobalShort (const std::string& name) const; virtual int getGlobalShort (const std::string& name) const;

View file

@ -99,7 +99,11 @@ namespace MWScript
InterpreterContext& context = InterpreterContext& context =
static_cast<InterpreterContext&> (runtime.getContext()); static_cast<InterpreterContext&> (runtime.getContext());
context.getWorld().toggleRenderMode (MWWorld::World::Render_CollisionDebug); bool enabled =
context.getWorld().toggleRenderMode (MWWorld::World::Render_CollisionDebug);
context.report (enabled ?
"Collsion Mesh Rendering -> On" : "Collision Mesh Rendering -> Off");
} }
}; };

View file

@ -16,68 +16,70 @@ namespace MWScript
class OpToggleSky : public Interpreter::Opcode0 class OpToggleSky : public Interpreter::Opcode0
{ {
public: public:
virtual void execute (Interpreter::Runtime& runtime) virtual void execute (Interpreter::Runtime& runtime)
{ {
InterpreterContext& context = InterpreterContext& context =
static_cast<InterpreterContext&> (runtime.getContext()); static_cast<InterpreterContext&> (runtime.getContext());
context.getWorld().toggleSky(); bool enabled = context.getWorld().toggleSky();
}
}; context.report (enabled ? "Sky -> On" : "Sky -> Off");
}
};
class OpTurnMoonWhite : public Interpreter::Opcode0 class OpTurnMoonWhite : public Interpreter::Opcode0
{ {
public: public:
virtual void execute (Interpreter::Runtime& runtime) virtual void execute (Interpreter::Runtime& runtime)
{ {
InterpreterContext& context = InterpreterContext& context =
static_cast<InterpreterContext&> (runtime.getContext()); static_cast<InterpreterContext&> (runtime.getContext());
context.getWorld().setMoonColour (false); context.getWorld().setMoonColour (false);
} }
}; };
class OpTurnMoonRed : public Interpreter::Opcode0 class OpTurnMoonRed : public Interpreter::Opcode0
{ {
public: public:
virtual void execute (Interpreter::Runtime& runtime) virtual void execute (Interpreter::Runtime& runtime)
{ {
InterpreterContext& context = InterpreterContext& context =
static_cast<InterpreterContext&> (runtime.getContext()); static_cast<InterpreterContext&> (runtime.getContext());
context.getWorld().setMoonColour (true); context.getWorld().setMoonColour (true);
} }
}; };
class OpGetMasserPhase : public Interpreter::Opcode0 class OpGetMasserPhase : public Interpreter::Opcode0
{ {
public: public:
virtual void execute (Interpreter::Runtime& runtime) virtual void execute (Interpreter::Runtime& runtime)
{ {
InterpreterContext& context = InterpreterContext& context =
static_cast<InterpreterContext&> (runtime.getContext()); static_cast<InterpreterContext&> (runtime.getContext());
runtime.push (context.getWorld().getMasserPhase()); runtime.push (context.getWorld().getMasserPhase());
} }
}; };
class OpGetSecundaPhase : public Interpreter::Opcode0 class OpGetSecundaPhase : public Interpreter::Opcode0
{ {
public: public:
virtual void execute (Interpreter::Runtime& runtime) virtual void execute (Interpreter::Runtime& runtime)
{ {
InterpreterContext& context = InterpreterContext& context =
static_cast<InterpreterContext&> (runtime.getContext()); static_cast<InterpreterContext&> (runtime.getContext());
runtime.push (context.getWorld().getSecundaPhase()); runtime.push (context.getWorld().getSecundaPhase());
} }
}; };
const int opcodeToggleSky = 0x2000021; const int opcodeToggleSky = 0x2000021;
const int opcodeTurnMoonWhite = 0x2000022; const int opcodeTurnMoonWhite = 0x2000022;
const int opcodeTurnMoonRed = 0x2000023; const int opcodeTurnMoonRed = 0x2000023;
@ -93,7 +95,7 @@ namespace MWScript
extensions.registerFunction ("getmasserphase", 'l', "", opcodeGetMasserPhase); extensions.registerFunction ("getmasserphase", 'l', "", opcodeGetMasserPhase);
extensions.registerFunction ("getsecundaphase", 'l', "", opcodeGetSecundaPhase); extensions.registerFunction ("getsecundaphase", 'l', "", opcodeGetSecundaPhase);
} }
void installOpcodes (Interpreter::Interpreter& interpreter) void installOpcodes (Interpreter::Interpreter& interpreter)
{ {
interpreter.installSegment5 (opcodeToggleSky, new OpToggleSky); interpreter.installSegment5 (opcodeToggleSky, new OpToggleSky);
@ -101,7 +103,6 @@ namespace MWScript
interpreter.installSegment5 (opcodeTurnMoonRed, new OpTurnMoonRed); interpreter.installSegment5 (opcodeTurnMoonRed, new OpTurnMoonRed);
interpreter.installSegment5 (opcodeGetMasserPhase, new OpGetMasserPhase); interpreter.installSegment5 (opcodeGetMasserPhase, new OpGetMasserPhase);
interpreter.installSegment5 (opcodeGetSecundaPhase, new OpGetSecundaPhase); interpreter.installSegment5 (opcodeGetSecundaPhase, new OpGetSecundaPhase);
} }
} }
} }

View file

@ -650,12 +650,13 @@ namespace MWWorld
mSkyManager->setDate (mGlobalVariables->getInt ("day"), month); mSkyManager->setDate (mGlobalVariables->getInt ("day"), month);
} }
void World::toggleSky() bool World::toggleSky()
{ {
if (mSky) if (mSky)
{ {
mSky = false; mSky = false;
mSkyManager->disable(); mSkyManager->disable();
return false;
} }
else else
{ {
@ -665,6 +666,7 @@ namespace MWWorld
mSkyManager->setDate (mGlobalVariables->getInt ("day"), mSkyManager->setDate (mGlobalVariables->getInt ("day"),
mGlobalVariables->getInt ("month")); mGlobalVariables->getInt ("month"));
mSkyManager->enable(); mSkyManager->enable();
return true;
} }
} }
@ -858,13 +860,13 @@ namespace MWWorld
mScene.doPhysics (duration, *this, actors); mScene.doPhysics (duration, *this, actors);
} }
void World::toggleCollisionMode() bool World::toggleCollisionMode()
{ {
mScene.toggleCollisionMode(); return mScene.toggleCollisionMode();
} }
void World::toggleRenderMode (RenderMode mode) bool World::toggleRenderMode (RenderMode mode)
{ {
mScene.toggleRenderMode (mode); return mScene.toggleRenderMode (mode);
} }
} }

View file

@ -149,7 +149,8 @@ namespace MWWorld
void setDay (int day); void setDay (int day);
void toggleSky(); bool toggleSky();
///< \return Resulting mode
int getMasserPhase() const; int getMasserPhase() const;
@ -187,12 +188,14 @@ namespace MWWorld
float duration); float duration);
///< Run physics simulation and modify \a world accordingly. ///< Run physics simulation and modify \a world accordingly.
void toggleCollisionMode(); bool toggleCollisionMode();
///< Toggle collision mode for player. If disabled player object should ignore ///< Toggle collision mode for player. If disabled player object should ignore
/// collisions and gravity. /// collisions and gravity.
///< \return Resulting mode
void toggleRenderMode (RenderMode mode); bool toggleRenderMode (RenderMode mode);
///< Toggle a render mode. ///< Toggle a render mode.
///< \return Resulting mode
}; };
} }

View file

@ -125,6 +125,11 @@ namespace
code.push_back (Compiler::Generator::segment3 (0, buttons)); code.push_back (Compiler::Generator::segment3 (0, buttons));
} }
void opReport (Compiler::Generator::CodeContainer& code)
{
code.push_back (Compiler::Generator::segment5 (58));
}
void opFetchLocalShort (Compiler::Generator::CodeContainer& code) void opFetchLocalShort (Compiler::Generator::CodeContainer& code)
{ {
code.push_back (Compiler::Generator::segment5 (21)); code.push_back (Compiler::Generator::segment5 (21));
@ -516,6 +521,14 @@ namespace Compiler
opMessageBox (code, buttons); opMessageBox (code, buttons);
} }
void report (CodeContainer& code, Literals& literals, const std::string& message)
{
int index = literals.addString (message);
opPushInt (code, index);
opReport (code);
}
void fetchLocal (CodeContainer& code, char localType, int localIndex) void fetchLocal (CodeContainer& code, char localType, int localIndex)
{ {
opPushInt (code, localIndex); opPushInt (code, localIndex);

View file

@ -81,6 +81,8 @@ namespace Compiler
void message (CodeContainer& code, Literals& literals, const std::string& message, void message (CodeContainer& code, Literals& literals, const std::string& message,
int buttons); int buttons);
void report (CodeContainer& code, Literals& literals, const std::string& message);
void fetchLocal (CodeContainer& code, char localType, int localIndex); void fetchLocal (CodeContainer& code, char localType, int localIndex);
void jump (CodeContainer& code, int offset); void jump (CodeContainer& code, int offset);

View file

@ -30,12 +30,12 @@ namespace Compiler
{ {
case 'l': case 'l':
Generator::message (mCode, mLiterals, "%g", 0); Generator::report (mCode, mLiterals, "%g");
break; break;
case 'f': case 'f':
Generator::message (mCode, mLiterals, "%f", 0); Generator::report (mCode, mLiterals, "%f");
break; break;
default: default:

View file

@ -18,21 +18,23 @@ namespace Interpreter
virtual float getLocalFloat (int index) const = 0; virtual float getLocalFloat (int index) const = 0;
virtual void setLocalShort (int index, int value) = 0; virtual void setLocalShort (int index, int value) = 0;
virtual void setLocalLong (int index, int value) = 0; virtual void setLocalLong (int index, int value) = 0;
virtual void setLocalFloat (int index, float value) = 0; virtual void setLocalFloat (int index, float value) = 0;
virtual void messageBox (const std::string& message, virtual void messageBox (const std::string& message,
const std::vector<std::string>& buttons) = 0; const std::vector<std::string>& buttons) = 0;
void messageBox (const std::string& message) void messageBox (const std::string& message)
{ {
std::vector<std::string> empty; std::vector<std::string> empty;
messageBox (message, empty); messageBox (message, empty);
} }
virtual void report (const std::string& message) = 0;
virtual bool menuMode() = 0; virtual bool menuMode() = 0;
virtual int getGlobalShort (const std::string& name) const = 0; virtual int getGlobalShort (const std::string& name) const = 0;
@ -41,31 +43,29 @@ namespace Interpreter
virtual float getGlobalFloat (const std::string& name) const = 0; virtual float getGlobalFloat (const std::string& name) const = 0;
virtual void setGlobalShort (const std::string& name, int value) = 0; virtual void setGlobalShort (const std::string& name, int value) = 0;
virtual void setGlobalLong (const std::string& name, int value) = 0; virtual void setGlobalLong (const std::string& name, int value) = 0;
virtual void setGlobalFloat (const std::string& name, float value) = 0;
virtual void setGlobalFloat (const std::string& name, float value) = 0;
virtual bool isScriptRunning (const std::string& name) const = 0; virtual bool isScriptRunning (const std::string& name) const = 0;
virtual void startScript (const std::string& name) = 0; virtual void startScript (const std::string& name) = 0;
virtual void stopScript (const std::string& name) = 0; virtual void stopScript (const std::string& name) = 0;
virtual float getDistance (const std::string& name, const std::string& id = "") const virtual float getDistance (const std::string& name, const std::string& id = "") const
= 0; = 0;
virtual float getSecondsPassed() const = 0; virtual float getSecondsPassed() const = 0;
virtual bool isDisabled (const std::string& id = "") const = 0; virtual bool isDisabled (const std::string& id = "") const = 0;
virtual void enable (const std::string& id = "") = 0; virtual void enable (const std::string& id = "") = 0;
virtual void disable (const std::string& id = "") = 0; virtual void disable (const std::string& id = "") = 0;
}; };
} }
#endif #endif

View file

@ -117,5 +117,9 @@ op 55: explicit reference = stack[0]; pop; disable explicit reference
op 56: explicit reference = stack[0]; pop; push 1, if explicit reference is disabled, 0 else op 56: explicit reference = stack[0]; pop; push 1, if explicit reference is disabled, 0 else
op 57: explicit reference = stack[0]; pop; op 57: explicit reference = stack[0]; pop;
replace stack[0] with distance between explicit reference and a reference of ID stack[0] replace stack[0] with distance between explicit reference and a reference of ID stack[0]
opcodes 58-33554431 unused op 58: report string literal index in stack[0];
additional arguments (if any) in stack[n]..stack[1];
n is determined according to the message string
all arguments are removed from stack
opcodes 59-33554431 unused
opcodes 33554432-67108863 reserved for extensions opcodes 33554432-67108863 reserved for extensions

View file

@ -95,6 +95,7 @@ namespace Interpreter
interpreter.installSegment5 (54, new OpEnableExplicit); interpreter.installSegment5 (54, new OpEnableExplicit);
interpreter.installSegment5 (55, new OpDisableExplicit); interpreter.installSegment5 (55, new OpDisableExplicit);
interpreter.installSegment5 (56, new OpGetDisabledExplicit); interpreter.installSegment5 (56, new OpGetDisabledExplicit);
interpreter.installSegment5 (58, new OpReport);
// script control // script control
interpreter.installSegment5 (46, new OpScriptRunning); interpreter.installSegment5 (46, new OpScriptRunning);
@ -106,4 +107,3 @@ namespace Interpreter
interpreter.installSegment5 (57, new OpGetDistanceExplicit); interpreter.installSegment5 (57, new OpGetDistanceExplicit);
} }
} }

View file

@ -13,6 +13,66 @@
namespace Interpreter namespace Interpreter
{ {
inline std::string formatMessage (const std::string& message, Runtime& runtime)
{
std::string formattedMessage;
for (std::size_t i=0; i<message.size(); ++i)
{
char c = message[i];
if (c!='%')
formattedMessage += c;
else
{
++i;
if (i<message.size())
{
c = message[i];
if (c=='S' || c=='s')
{
int index = runtime[0].mInteger;
runtime.pop();
formattedMessage += runtime.getStringLiteral (index);
}
else if (c=='g' || c=='G')
{
Type_Integer value = runtime[0].mInteger;
runtime.pop();
std::ostringstream out;
out << value;
formattedMessage += out.str();
}
else if (c=='f' || c=='F' || c=='.')
{
while (c!='f' && i<message.size())
{
++i;
}
float value = runtime[0].mFloat;
runtime.pop();
std::ostringstream out;
out << value;
formattedMessage += out.str();
}
else if (c=='%')
formattedMessage += "%";
else
{
formattedMessage += "%";
formattedMessage += c;
}
}
}
}
return formattedMessage;
}
class OpMessageBox : public Opcode1 class OpMessageBox : public Opcode1
{ {
public: public:
@ -36,66 +96,31 @@ namespace Interpreter
std::reverse (buttons.begin(), buttons.end()); std::reverse (buttons.begin(), buttons.end());
// additional parameters // handle additional parameters
std::string formattedMessage; std::string formattedMessage = formatMessage (message, runtime);
for (std::size_t i=0; i<message.size(); ++i)
{
char c = message[i];
if (c!='%')
formattedMessage += c;
else
{
++i;
if (i<message.size())
{
c = message[i];
if (c=='S' || c=='s')
{
int index = runtime[0].mInteger;
runtime.pop();
formattedMessage += runtime.getStringLiteral (index);
}
else if (c=='g' || c=='G')
{
Type_Integer value = runtime[0].mInteger;
runtime.pop();
std::ostringstream out;
out << value;
formattedMessage += out.str();
}
else if (c=='f' || c=='F' || c=='.')
{
while (c!='f' && i<message.size())
{
++i;
}
float value = runtime[0].mFloat;
runtime.pop();
std::ostringstream out;
out << value;
formattedMessage += out.str();
}
else if (c=='%')
formattedMessage += "%";
else
{
formattedMessage += "%";
formattedMessage += c;
}
}
}
}
runtime.getContext().messageBox (formattedMessage, buttons); runtime.getContext().messageBox (formattedMessage, buttons);
} }
}; };
class OpReport : public Opcode0
{
public:
virtual void execute (Runtime& runtime)
{
// message
int index = runtime[0].mInteger;
runtime.pop();
std::string message = runtime.getStringLiteral (index);
// handle additional parameters
std::string formattedMessage = formatMessage (message, runtime);
runtime.getContext().report (formattedMessage);
}
};
class OpMenuMode : public Opcode0 class OpMenuMode : public Opcode0
{ {
public: public: