示例#1
0
Error MultiplayerAPI::send_bytes(PoolVector<uint8_t> p_data, int p_to) {

	ERR_FAIL_COND_V(p_data.size() < 1, ERR_INVALID_DATA);
	ERR_FAIL_COND_V(!network_peer.is_valid(), ERR_UNCONFIGURED);
	ERR_FAIL_COND_V(network_peer->get_connection_status() != NetworkedMultiplayerPeer::CONNECTION_CONNECTED, ERR_UNCONFIGURED);

	MAKE_ROOM(p_data.size() + 1);
	PoolVector<uint8_t>::Read r = p_data.read();
	packet_cache[0] = NETWORK_COMMAND_RAW;
	memcpy(&packet_cache[1], &r[0], p_data.size());
	network_peer->set_target_peer(p_to);
	return network_peer->put_packet(packet_cache.ptr(), p_data.size() + 1);
}
示例#2
0
Error MultiplayerAPI::send_bytes(PoolVector<uint8_t> p_data, int p_to, NetworkedMultiplayerPeer::TransferMode p_mode) {

	ERR_EXPLAIN("Trying to send an empty raw packet.");
	ERR_FAIL_COND_V(p_data.size() < 1, ERR_INVALID_DATA);
	ERR_EXPLAIN("Trying to send a raw packet while no network peer is active.");
	ERR_FAIL_COND_V(!network_peer.is_valid(), ERR_UNCONFIGURED);
	ERR_EXPLAIN("Trying to send a raw packet via a network peer which is not connected.");
	ERR_FAIL_COND_V(network_peer->get_connection_status() != NetworkedMultiplayerPeer::CONNECTION_CONNECTED, ERR_UNCONFIGURED);

	MAKE_ROOM(p_data.size() + 1);
	PoolVector<uint8_t>::Read r = p_data.read();
	packet_cache.write[0] = NETWORK_COMMAND_RAW;
	memcpy(&packet_cache.write[1], &r[0], p_data.size());

	network_peer->set_target_peer(p_to);
	network_peer->set_transfer_mode(p_mode);

	return network_peer->put_packet(packet_cache.ptr(), p_data.size() + 1);
}
示例#3
0
void MultiplayerAPI::_send_rpc(Node *p_from, int p_to, bool p_unreliable, bool p_set, const StringName &p_name, const Variant **p_arg, int p_argcount) {

	if (network_peer.is_null()) {
		ERR_EXPLAIN("Attempt to remote call/set when networking is not active in SceneTree.");
		ERR_FAIL();
	}

	if (network_peer->get_connection_status() == NetworkedMultiplayerPeer::CONNECTION_CONNECTING) {
		ERR_EXPLAIN("Attempt to remote call/set when networking is not connected yet in SceneTree.");
		ERR_FAIL();
	}

	if (network_peer->get_connection_status() == NetworkedMultiplayerPeer::CONNECTION_DISCONNECTED) {
		ERR_EXPLAIN("Attempt to remote call/set when networking is disconnected.");
		ERR_FAIL();
	}

	if (p_argcount > 255) {
		ERR_EXPLAIN("Too many arguments >255.");
		ERR_FAIL();
	}

	if (p_to != 0 && !connected_peers.has(ABS(p_to))) {
		if (p_to == network_peer->get_unique_id()) {
			ERR_EXPLAIN("Attempt to remote call/set yourself! unique ID: " + itos(network_peer->get_unique_id()));
		} else {
			ERR_EXPLAIN("Attempt to remote call unexisting ID: " + itos(p_to));
		}

		ERR_FAIL();
	}

	NodePath from_path = (root_node->get_path()).rel_path_to(p_from->get_path());
	ERR_EXPLAIN("Unable to send RPC. Relative path is empty. THIS IS LIKELY A BUG IN THE ENGINE!");
	ERR_FAIL_COND(from_path.is_empty());

	// See if the path is cached.
	PathSentCache *psc = path_send_cache.getptr(from_path);
	if (!psc) {
		// Path is not cached, create.
		path_send_cache[from_path] = PathSentCache();
		psc = path_send_cache.getptr(from_path);
		psc->id = last_send_cache_id++;
	}

	// Create base packet, lots of hardcode because it must be tight.

	int ofs = 0;

#define MAKE_ROOM(m_amount) \
	if (packet_cache.size() < m_amount) packet_cache.resize(m_amount);

	// Encode type.
	MAKE_ROOM(1);
	packet_cache.write[0] = p_set ? NETWORK_COMMAND_REMOTE_SET : NETWORK_COMMAND_REMOTE_CALL;
	ofs += 1;

	// Encode ID.
	MAKE_ROOM(ofs + 4);
	encode_uint32(psc->id, &(packet_cache.write[ofs]));
	ofs += 4;

	// Encode function name.
	CharString name = String(p_name).utf8();
	int len = encode_cstring(name.get_data(), NULL);
	MAKE_ROOM(ofs + len);
	encode_cstring(name.get_data(), &(packet_cache.write[ofs]));
	ofs += len;

	if (p_set) {
		// Set argument.
		Error err = encode_variant(*p_arg[0], NULL, len, allow_object_decoding || network_peer->is_object_decoding_allowed());
		ERR_EXPLAIN("Unable to encode RSET value. THIS IS LIKELY A BUG IN THE ENGINE!");
		ERR_FAIL_COND(err != OK);
		MAKE_ROOM(ofs + len);
		encode_variant(*p_arg[0], &(packet_cache.write[ofs]), len, allow_object_decoding || network_peer->is_object_decoding_allowed());
		ofs += len;

	} else {
		// Call arguments.
		MAKE_ROOM(ofs + 1);
		packet_cache.write[ofs] = p_argcount;
		ofs += 1;
		for (int i = 0; i < p_argcount; i++) {
			Error err = encode_variant(*p_arg[i], NULL, len, allow_object_decoding || network_peer->is_object_decoding_allowed());
			ERR_EXPLAIN("Unable to encode RPC argument. THIS IS LIKELY A BUG IN THE ENGINE!");
			ERR_FAIL_COND(err != OK);
			MAKE_ROOM(ofs + len);
			encode_variant(*p_arg[i], &(packet_cache.write[ofs]), len, allow_object_decoding || network_peer->is_object_decoding_allowed());
			ofs += len;
		}
	}

	// See if all peers have cached path (is so, call can be fast).
	bool has_all_peers = _send_confirm_path(from_path, psc, p_to);

	// Take chance and set transfer mode, since all send methods will use it.
	network_peer->set_transfer_mode(p_unreliable ? NetworkedMultiplayerPeer::TRANSFER_MODE_UNRELIABLE : NetworkedMultiplayerPeer::TRANSFER_MODE_RELIABLE);

	if (has_all_peers) {

		// They all have verified paths, so send fast.
		network_peer->set_target_peer(p_to); // To all of you.
		network_peer->put_packet(packet_cache.ptr(), ofs); // A message with love.
	} else {
		// Not all verified path, so send one by one.

		// Append path at the end, since we will need it for some packets.
		CharString pname = String(from_path).utf8();
		int path_len = encode_cstring(pname.get_data(), NULL);
		MAKE_ROOM(ofs + path_len);
		encode_cstring(pname.get_data(), &(packet_cache.write[ofs]));

		for (Set<int>::Element *E = connected_peers.front(); E; E = E->next()) {

			if (p_to < 0 && E->get() == -p_to)
				continue; // Continue, excluded.

			if (p_to > 0 && E->get() != p_to)
				continue; // Continue, not for this peer.

			Map<int, bool>::Element *F = psc->confirmed_peers.find(E->get());
			ERR_CONTINUE(!F); // Should never happen.

			network_peer->set_target_peer(E->get()); // To this one specifically.

			if (F->get()) {
				// This one confirmed path, so use id.
				encode_uint32(psc->id, &(packet_cache.write[1]));
				network_peer->put_packet(packet_cache.ptr(), ofs);
			} else {
				// This one did not confirm path yet, so use entire path (sorry!).
				encode_uint32(0x80000000 | ofs, &(packet_cache.write[1])); // Offset to path and flag.
				network_peer->put_packet(packet_cache.ptr(), ofs + path_len);
			}
		}
	}
}