Overview

Namespaces

  • aliuly
    • common
      • selectors
    • loader
  • xPaw

Classes

  • aliuly\common\ArmorItems
  • aliuly\common\BasicCli
  • aliuly\common\BasicHelp
  • aliuly\common\BasicPlugin
  • aliuly\common\ChatSession
  • aliuly\common\Cmd
  • aliuly\common\CmdSelector
  • aliuly\common\ExpandVars
  • aliuly\common\FastTransfer
  • aliuly\common\FileUtils
  • aliuly\common\FreezeSession
  • aliuly\common\GetMotd
  • aliuly\common\GetMotdAsyncTask
  • aliuly\common\InvisibleSession
  • aliuly\common\InvUtils
  • aliuly\common\ItemName
  • aliuly\common\mc
  • aliuly\common\mc2
  • aliuly\common\MoneyAPI
  • aliuly\common\MPMU
  • aliuly\common\Npc
  • aliuly\common\PermUtils
  • aliuly\common\PluginAsyncTask
  • aliuly\common\PluginCallbackTask
  • aliuly\common\PMScript
  • aliuly\common\QueryAsyncTask
  • aliuly\common\Rcon
  • aliuly\common\RconTask
  • aliuly\common\selectors\All
  • aliuly\common\selectors\AllEntity
  • aliuly\common\selectors\BaseSelector
  • aliuly\common\selectors\Random
  • aliuly\common\Session
  • aliuly\common\ShieldSession
  • aliuly\common\ShoppingCart
  • aliuly\common\SignUtils
  • aliuly\common\SkinUtils
  • aliuly\common\SpySession
  • aliuly\common\SubCommandMap
  • aliuly\common\TPUtils
  • aliuly\loader\Main
  • xPaw\MinecraftQuery

Exceptions

  • xPaw\MinecraftQueryException
  • Overview
  • Namespace
  • Class
  1: <?php
  2: //# ## PMScript
  3: //:
  4: //: The PMScript module implements a simple [PHP](https://secure.php.net/)
  5: //: based scripting engine.  It can be used to enter multiple PocketMine
  6: //: commands while allowing you to add PHP code to control the flow of
  7: //: the script.
  8: //:
  9: //: While you can embed any arbitrary PHP code, for readability purposes
 10: //: it is recommended that you use
 11: //: [PHP's alternative syntax](http://php.net/manual/en/control-structures.alternative-syntax.php)
 12: //:
 13: //: By convention, PMScript's have a file extension of ".pms" and they are
 14: //: just simple text file containing PHP console commands (without the "/").
 15: //:
 16: //: To control the execution you can use the following prefixes when
 17: //: entering commands:
 18: //:
 19: //: * **+op:** - will give Op access to the player (temporarily) before executing
 20: //:   a command
 21: //: * **+console:** - run the command as if it was run from the console.
 22: //: * **+rcon:** - like **+console:** but the output is sent to the player.
 23: //:
 24: //: Also, before executing a command variable expansion (e.g. {vars}) and
 25: //: command selector expansion (e.g. @a, @r, etc) takes place.
 26: //:
 27: //: Available variables depend on installed plugins, pocketmine.yml
 28: //: settings, execution context, etc.
 29: //:
 30: //: It is possible to use PHP functions and variables in command lines by
 31: //: surrounding PHP expressions with:
 32: //:
 33: //:      '.(php expression).'
 34: //:
 35: //: For example:
 36: //:
 37: //:      echo MaxPlayers: '.$interp->getServer()->getMaxPlayers().'
 38: //:
 39: //: ### Adding logic flow to PMScripts
 40: //:
 41: //: Arbitrary PHP code can be added to your pmscripts.  Lines that start
 42: //: with "@" are treated as PHP code.  For your convenience,
 43: //: you can ommit ";" at the end of the line.
 44: //:
 45: //: Any valid PHP code can be used, but for readability, the use of
 46: //: alternative syntax is recommended.
 47: //:
 48: //: The execution context for this PHP code has the following variables
 49: //: available:
 50: //:
 51: //: * **$interp** - reference to the running PMSCript object.
 52: //: * **$context** - This is the CommandSender that is executing the script
 53: //: * **$vars** - This is the variables array used for variable substitution
 54: //:   when executing commands.
 55: //: * **$args** - Command line arguments.
 56: //: * **$env** - execution environment.  Empty by default but may be used
 57: //:   by third party plugins.
 58: //: * **$v_xxxxx** - When posible the variables use for command variable
 59: //:   substitution are made available as **$v_xxxx**.  For example, the
 60: //:   **{tps}** variable, will be available as **$v_tps**
 61: //:
 62: //: Example:
 63: //:
 64: //:     # Sample PMScript
 65: //:     #
 66: //:     ; You can use ";" or "#" as comments
 67: //:     #
 68: //:     # Just place your commands as you would enter them on the console
 69: //:     # on your .pms file.
 70: //:     echo You have the following plugins:
 71: //:     plugins
 72: //:     echo {GOLD}Variable {RED}Expansions {BLUE}are {GREEN}possible
 73: //:     echo libcommon: {libcommon} MOTD: {MOTD}
 74: //:     #
 75: //:     # You can include in there PHP expressions...
 76: //:     say '.$context->getName().' is AWESOME!
 77: //:     # CommandSelectors are possible...
 78: //:     echo Greeting everybody
 79: //:     say Hello @a
 80: //:     ;
 81: //:     # Adding PHP control code is possible:
 82: //:     @if ($v_tps > 10):
 83: //:       echo Your TPS {tps} is greater than 10
 84: //:     @else:
 85: //:       echo Your TPS {tps} is less or equal to 10
 86: //:     @endif
 87: //:     ;
 88: //:     ;
 89: //:     echo The following variables are available in this context:
 90: //:     echo '.print_r($vars,true).'
 91: //:     echo You passed {#} arguments to this script.
 92: 
 93: 
 94: namespace aliuly\common;
 95: 
 96: use pocketmine\command\CommandSender;
 97: use pocketmine\plugin\Plugin;
 98: use pocketmine\Player;
 99: use pocketmine\utils\TextFormat;
100: 
101: use aliuly\common\CmdSelector;
102: use aliuly\common\ExpandVars;
103: use aliuly\common\Cmd;
104: /**
105:  * Class that implements a PocketMine-MP scripting engine
106:  */
107: class PMScript {
108:   protected $owner;
109:   protected $selector;
110:   protected $perms;
111:   protected $vars;
112:   protected $globs;
113: 
114:   /**
115:    * @param Plugin $owner - plugin that owns this interpreter
116:    * @param bool|ExpandVars $vars - allow for standard variable expansion
117:    * @param bool $perms - allow the use of Cmd::opexec
118:    * @param int $selector - if 0, command selctors are not used, otherwise max commands
119:    */
120:   public function __construct(Plugin $owner, $vars = true, $perms = true, $selector = 100) {
121:     $this->owner = $owner;
122:     $this->selector = $selector;
123:     $this->globs = [];
124: 
125:     if ($perms) {
126:       $this->perms = [ __NAMESPACE__."\\Cmd" , "opexec" ];
127:     } else {
128:       $this->perms = [ $this->owner->getServer(), "dispatchCommand" ];
129:     }
130: 
131:     if ($vars) {
132:       if ($vars instanceof ExpandVars) {
133:         $this->vars = $vars;
134:       } else {
135:         $this->vars = new ExpandVars($owner);
136:       }
137:     } else {
138:       $this->vars = null;
139:     }
140: 
141:   }
142:   /**
143:    * Execute a command
144:    * @param CommandSender $ctx - Command context
145:    * @param str $cmdline - Command to execute
146:    * @param array $vars - Variables table for variable expansion
147:    */
148:   public function exec(CommandSender $ctx, $cmdline, $vars) {
149:     $cmdline = strtr($cmdline,$vars);
150:     if ($this->selector) {
151:       $cmds = CmdSelector::expandSelectors($this->getServer(),$ctx, $cmdline, $this->selector);
152:       if ($cmds == false) {
153:         $cmds = [ $cmdline ];
154:       }
155:     } else {
156:       $cmds = [ $cmdline ];
157:     }
158:     $cmdex = $this->perms;
159:     foreach ($cmds as $ln) {
160:       $cmdex($ctx,$ln);
161:     }
162:   }
163:   /**
164:    * If GrabBag is available, try to get a single shared instance of
165:    * PMScript
166:    */
167:   static public function getCommonInterp(Plugin $owner) {
168:     $pm = $owner->getServer()->getPluginManager();
169:     if (($gb = $pm->getPlugin("GrabBag")) !== null) {
170:       if ($gb->isEnabled() && MPMU::apiCheck($gb->getDescription()->getVersion(),"2.3")) {
171:         $vars =  $gb->api->getInterp();
172:         if ($vars instanceof PMScript) return $vars;
173:       }
174:     }
175:     return new PMScript($owner, ExpandVars::getCommonVars($owner));
176:   }
177:   /**
178:    * Define additional constants on the fly...
179:    * @param str $name
180:    * @param mixed $value
181:    */
182:   public function define($str,$value) {
183:     if ($this->vars !== null) $this->vars->define($str,$value);
184:   }
185:   /** Return plugin owner */
186:   public function getOwner() {
187:     return $this->owner;
188:   }
189:   /** Return server */
190:   public function getServer() {
191:     return $this->owner->getServer();
192:   }
193: 
194:   /**
195:    * @param str $label - global variable to get
196:    * @param mixed $default - default value to return is no global found
197:    * @return mixed
198:    */
199:   public function getGlob($label,$default) {
200:     if (!isset($this->globs[$label])) return $default;
201:     return $this->globs[$label];
202:   }
203:   /**
204:    * Set global variable
205:    *
206:    * @param str $label - state variable to set
207:    * @param mixed $val - value to set
208:    * @return mixed
209:    */
210:   public function setGlob($label,$val) {
211:     $this->globs[$label] = $val;
212:     return $val;
213:   }
214:   /**
215:    * Clears a global variable
216:    *
217:    * @param str $label - state variable to clear
218:    */
219:   public function unsetGlob($label) {
220:     if (!isset($this->globs[$label])) return;
221:     unset($this->globs[$label]);
222:   }
223:   ////////////////////////////////////////////////////////////////////////
224:   // Main implementation
225:   ////////////////////////////////////////////////////////////////////////
226: 
227:   /**
228:    * Run a script file
229:    * @param CommandSender $ctx - Command context
230:    * @param callable $php - Loaded PMScript
231:    * @param array $args - Command args
232:    * @param array $opts - Some environemnt variables
233:    */
234:   public function runScriptFile(CommandSender $ctx, $path, array &$args, array &$opts) {
235:     $php = $this->loadScriptFile($path);
236:     if ($php === false) return false;
237:     $this->executeScript($ctx,$php,$args,$opts);
238:     return true;
239:   }
240: 
241:   /**
242:    * load a script from file (May implement a cache in the future...)
243:    * @param str $path - path to file to load
244:    * @param bool $cache - enable/disable caching
245:    */
246:   public function loadScriptFile($path,$cache = false) {
247:     return $this->loadScriptCode(file_get_contents($path));
248:   }
249:   /**
250:    * Execute a PMScript
251:    *
252:    * @param CommandSender $ctx - Command context
253:    * @param callable $php - Loaded PMScript
254:    * @param array $args - Command args
255:    * @param array $opts - Some environemnt variables
256:    */
257:   public function runScriptCode(CommandSender $ctx,$pmscode,array &$args,array &$opts) {
258:     $php = $this->loadScriptCode($pmscode);
259:     if ($php === false) return false;
260:     $this->executeScript($ctx,$php,$args,$opts);
261:     return true;
262:   }
263:   /**
264:    * Execute preloaded PHP code
265:    * @param CommandSender $ctx - Command context
266:    * @param callable $php - Loaded PMScript
267:    * @param array $args - Command args
268:    */
269:   public function executeScript(CommandSender $ctx, $php, array &$args, array &$opts) {
270:     if ($this->vars === null) {
271:       $vars = [];
272:     } else {
273:       $vars = $this->vars->getConsts();
274:       $this->vars->sysVars($vars);
275:       if ($ctx instanceof Player) $this->vars->playerVars($ctx,$vars);
276:     }
277:     $vars["{#}"] = count($args);
278:     $i = 0;
279:     foreach ($args as $j) {
280:       $vars["{".($i++)."}"] = $j;
281:     }
282:     foreach ($opts as $i=>&$j) {
283:       if (is_string($j)) $vars["{".$i."}"] = $j;
284:     }
285:     try {
286:       $php($this,$ctx,$vars,$args,$opts);
287:     } catch (\Exception $e) {
288:       $ctx->sendMessage(TextFormat::RED.mc::_("Exception: %1%",$e->getMessage()));
289:     }
290:   }
291:   /**
292:    * Prepare PMScript and convert into a PHP callable
293:    * @param str $pmscript - text script
294:    */
295:    public function loadScriptCode($pmscript) {
296:      $php = "";
297:      // Prefix code ...
298:      $php .= " return function (\$interp,\$context,&\$vars,&\$args,&\$env) {";
299:      $php .= "  foreach (\$vars as \$i=>\$j) {\n";
300:      $php .= "    if (preg_match(\"/^\\{([_a-zA-Z][_a-zA-Z0-9]*)\\}\\\$/\",\$i,\$mv)) {\n";
301:      $php .= "       eval(\"\\\$v_\" . \$mv[1] . \" = \\\$j;\\n\");\n";
302:      $php .= "    }\n";
303:      $php .= "  }\n";
304:      foreach (explode("\n",$pmscript) as $ln) {
305:        $ln = trim($ln);
306:        if ($ln == "" || $ln{0} == "#" || $ln{0} == ";") continue;
307:        if ($ln{0} == "@") {
308:          $c = substr($ln,-1);
309:          $q = ($c == ":" || $c == ";") ? "\n" : ";\n";
310:          $php .= substr($ln,1).$q;
311:        } else {
312:          $php .= "  \$interp->exec(\$context,'".$ln."',\$vars);\n";
313:        }
314:      }
315:      $php .= "};";
316:      return eval($php);
317:   }
318: }
319: 
API documentation generated by ApiGen