javascript在游戏服务器的应用

JavaScript,一开始定位为浏览器表单验证的“玩具语言”,发展到如今,却能胜任各种舞台。nodejs,es6等等,奠定了其作为后端语言的地位。

在JVM里,我们也可以直接使用javascript代码,因为jdk已默认绑定其实现。由于拥有动态语言灵活的特点,我们可以用来作很多有趣的事情。在游戏服务端开发,我们越来越多可以看到它的身影。

下面我们就来看下javascript在游戏服务器里的应用。

用作公式计算器

数值是游戏的灵魂,很多游戏其实玩的就是数据。所以游戏里有各种各样的公式计算,最常见的就是玩家战斗力的计算。如果我们把游戏的数值公式硬性写进代码里,那么当策划需要在程序运行过程中修改公式的话,我们就要热更代码了。但如果我们把公式作为数据配置,那么策划只需要重载下数据表,成本就低很多。要在游戏里运行公式的话,用java写一套基于栈的公式计算器也是可以实现的,但比较麻烦。最简单的,莫过于使用javascript这个神器了。代码如下:

@Test
public void testCalculator() throws Exception {
	String formula = "a + b * c + Math.max(5,10)";
	ScriptEngineManager engineManager= new ScriptEngineManager();
	ScriptEngine scriptEngine = engineManager.getEngineByName("JavaScript");
	Map params = new HashMap<>();
	params.put("a", 3);
	params.put("b", 4);
	params.put("c", 5);
	Object value = scriptEngine.eval(formula, new SimpleBindings(params));
	double result = Double.valueOf(value.toString());
	Assert.assertEquals(33.0, result);
}

作为数据配置

从上面的例子,我们可以看出,java可以执行javascript代码。SimpleBindings里绑定的变量除了可以是基本类型,还可以数据对象!这样的话,我们就可以传入一个javabean。从而将js代码作为数据配置。话不多说,看个例子就懂了。

假设我们有一个js文件,里面只有一行配置

config.maxPackagePerSecond = 30

同时我们也有一个javabean,其字段与上面的一致

/**
 * 防火墙配置
 * @author kingston
 *
 */
public class FireWallConfig {
	
	/** 每秒最大收包数量 */
	private int maxPackagePerSecond;

	public int getMaxPackagePerSecond() {
		return maxPackagePerSecond;
	}

	public void setMaxPackagePerSecond(int maxPackagePerSecond) {
		this.maxPackagePerSecond = maxPackagePerSecond;
	}

	@Override
	public String toString() {
		return "FireWallConfig [maxPackagePerSecond=" + maxPackagePerSecond + "]";
	}

}

那么,使用下面的代码,我们就可以直接把js配置映射到对应的javabean里了,非常神奇。

注意:SimpleBindings里的config变量,必须与js配置的变量一致。

@Test
public void testReadConfig() throws Exception {
	// 这里只是把js文件作为文本流读取出来
	String content = FileUtils.readText("firewall.cfg.js");

	FireWallConfig config = new FireWallConfig();
	Map params = new HashMap<>();
	params.put("config", config);

	ScriptEngineManager engineManager= new ScriptEngineManager();
	ScriptEngine scriptEngine = engineManager.getEngineByName("JavaScript");

	Object response = scriptEngine.eval(content, new SimpleBindings(params));
	System.err.println(config);
}

程序执行结果

FireWallConfig [maxPackagePerSecond=30]

在游戏生产环境执行代码块

在游戏运行过程中,我们经常需要查看程序的内存数据,或者执行部分代码块。如果使用java方式,我们就需要将需要的代码编译成class,再拿到游戏里进行热更求值。但如果采用脚本语言,例如js或者groovy,我们就可以直接使用源代码。

从上面看以看出,java可以直接运行js代码,只需要以下几行代码

ScriptEngineManager engineManager= new ScriptEngineManager();
ScriptEngine scriptEngine = engineManager.getEngineByName("JavaScript");
Object response = scriptEngine.eval(jsCode);

那么,我们可以执行任意有效的js代码,要么查看内存数据,要么执行任意代码块。

// 查看内存数据
var playerSize = com.kingston.jforgame.server.game.player.PlayerManager.getInstance().getOnlinePlayers();

com.kingston.jforgame.server.logs.LoggerUtils.error("在线玩家数据为" + playerSize);

// 调用java代码
com.kingston.jforgame.server.game.player.PlayerManager.getInstance().kickPlayer(123);

结合JMX,我们的javascript简直无敌。具体见

-->使用JMX监控游戏服务器


当然,javascript在游戏服务器的应用肯定不止如此。随着对javascript的深入了解,相信能够发现更多有趣的应用。



你可能感兴趣的:(手游服务端)