Checked quickly and this seems to work now. CommanderDJ's code needed some minor fixes but for the most part worked. One short cut he took exposed a rather dangerous flaw in the multiplayer-SEXP system though so the patch also includes changes designed to fix that too.
Index: code/network/multi_sexp.cpp
===================================================================
--- code/network/multi_sexp.cpp (revision 7475)
+++ code/network/multi_sexp.cpp (working copy)
@@ -318,6 +318,39 @@
int multi_sexp_get_next_operator()
{
+ if (current_argument_count != 0) {
+ // we have a problem here, either the argument count is wrong or the last SEXP didn't remove all its data from the packet
+ ubyte possible_terminator;
+ bool terminator_found = false;
+ for (int i=0; i < current_argument_count ; i++) {
+ GET_DATA(possible_terminator);
+ Multi_sexp_bytes_left--;
+
+ if (possible_terminator == PACKET_TERMINATOR) {
+ Warning(LOCATION, "%s has returned to multi_sexp_eval() claiming %d arguments left. %d actually found. Trace out and fix this!"), Operators[op_num].text, current_argument_count, i;
+ terminator_found = true;
+ break;
+ }
+ }
+
+ // if we still haven't found the terminator it probably means the last SEXP didn't remove all its data from the packet
+ if (!terminator_found) {
+ GET_DATA(possible_terminator);
+ Multi_sexp_bytes_left--;
+
+ if (possible_terminator != PACKET_TERMINATOR) {
+ // discard remainder of packet if we still haven't found the terminator as it is hopelessly corrupt
+ Warning(LOCATION, "%s has returned to multi_sexp_eval() without finding the terminator. Discarding packet! Trace out and fix this!", Operators[op_num].text);
+ Multi_sexp_bytes_left = 0;
+ return -1;
+ }
+ else {
+ Warning(LOCATION, "%s has returned to multi_sexp_eval() without removing all its data from the packet. Trace out and fix this!", Operators[op_num].text);
+ op_num = -1;
+ }
+ }
+ }
+
GET_INT(op_num);
Multi_sexp_bytes_left -= sizeof(int);
GET_INT(current_argument_count);
@@ -493,3 +526,10 @@
return true;
}
+
+void multi_discard_remaining_packet()
+{
+ if (!multi_sexp_discard_operator()) {
+ Warning(LOCATION, "Attempt to discard SEXP packet failed! Operator %d packet lacks proper termination. Entire packet may be corrupt. Discarding remaining packet");
+ }
+}
\ No newline at end of file
Index: code/network/multi_sexp.h
===================================================================
--- code/network/multi_sexp.h (revision 7475)
+++ code/network/multi_sexp.h (working copy)
@@ -14,7 +14,7 @@
void multi_end_packet();
void multi_sexp_flush_packet();
-// data fillers
+// server side packet fillers
void multi_send_int(int value);
void multi_send_ship(ship *shipp);
void multi_send_ship(int shipnum);
@@ -28,6 +28,9 @@
int multi_sexp_get_operator();
bool multi_sexp_discard_operator();
+void multi_discard_remaining_packet();
+
+// client side packet emptiers
bool multi_get_int(int &value);
bool multi_get_ship(int &value);
bool multi_get_ship(ship*& shipp);
Index: code/parse/sexp.cpp
===================================================================
--- code/parse/sexp.cpp (revision 7475)
+++ code/parse/sexp.cpp (working copy)
@@ -18253,8 +18253,43 @@
}
cam->set_position(&camera_vec, camera_time, camera_acc_time, camera_dec_time);
+
+ //multiplayer callback
+ multi_start_packet();
+ multi_send_float(camera_vec.xyz.x);
+ multi_send_float(camera_vec.xyz.y);
+ multi_send_float(camera_vec.xyz.z);
+ multi_send_float(camera_time);
+ multi_send_float(camera_acc_time);
+ multi_send_float(camera_dec_time);
+ multi_end_packet();
}
+//CommanderDJ
+void multi_sexp_set_camera_position()
+{
+ camera *cam = sexp_get_set_camera();
+
+ if(cam == NULL) {
+ Int3();
+ return;
+ }
+
+ vec3d camera_vec;
+ float camera_time = 0.0f;
+ float camera_acc_time = 0.0f;
+ float camera_dec_time = 0.0f;
+
+ multi_get_float(camera_vec.xyz.x);
+ multi_get_float(camera_vec.xyz.y);
+ multi_get_float(camera_vec.xyz.z);
+ multi_get_float(camera_time);
+ multi_get_float(camera_acc_time);
+ multi_get_float(camera_dec_time);
+
+ cam->set_position(&camera_vec, camera_time, camera_acc_time, camera_dec_time);
+}
+
void sexp_set_camera_rotation(int n)
{
camera *cam = sexp_get_set_camera();
@@ -18324,32 +18359,43 @@
}
cam->set_rotation_facing(&location, rot_time, rot_acc_time, rot_dec_time);
+
+ //multiplayer callback
+ multi_start_packet();
+ multi_send_float(location.xyz.x);
+ multi_send_float(location.xyz.y);
+ multi_send_float(location.xyz.z);
+ multi_send_float(rot_time);
+ multi_send_float(rot_acc_time);
+ multi_send_float(rot_dec_time);
+ multi_end_packet();
}
-void sexp_set_camera_facing_object(int n)
+void multi_sexp_set_camera_facing()
{
- char *object_name = CTEXT(n);
+ camera *cam = sexp_get_set_camera();
+ if(cam == NULL)
+ return;
+
+ vec3d location;
float rot_time = 0.0f;
float rot_acc_time = 0.0f;
float rot_dec_time = 0.0f;
- //Now get the rotation time values
- n = CDR(n);
- if(n != -1)
- {
- rot_time = eval_num(n) / 1000.0f;
- n = CDR(n);
- if(n != -1)
- {
- rot_dec_time = rot_acc_time = eval_num(n) / 1000.0f;
- n = CDR(n);
- if(n != -1)
- {
- rot_dec_time = eval_num(n) / 1000.0f;
- }
- }
- }
+ multi_get_float(location.xyz.x);
+ multi_get_float(location.xyz.y);
+ multi_get_float(location.xyz.z);
+ multi_get_float(rot_time);
+ multi_get_float(rot_acc_time);
+ multi_get_float(rot_dec_time);
+
+ cam->set_rotation_facing(&location, rot_time, rot_acc_time, rot_dec_time);
+}
+//CommanderDJ
+//helper function for set_camera_facing_object
+void actually_set_camera_facing_object(char *object_name, float rot_time, float rot_acc_time, float rot_dec_time)
+{
object_ship_wing_point_team oswpt;
sexp_get_object_ship_wing_point_team(&oswpt, object_name);
@@ -18375,6 +18421,56 @@
}
}
+void sexp_set_camera_facing_object(int n)
+{
+ char *object_name = CTEXT(n);
+ float rot_time = 0.0f;
+ float rot_acc_time = 0.0f;
+ float rot_dec_time = 0.0f;
+
+ //Now get the rotation time values
+ n = CDR(n);
+ if(n != -1)
+ {
+ rot_time = eval_num(n) / 1000.0f;
+ n = CDR(n);
+ if(n != -1)
+ {
+ rot_dec_time = rot_acc_time = eval_num(n) / 1000.0f;
+ n = CDR(n);
+ if(n != -1)
+ {
+ rot_dec_time = eval_num(n) / 1000.0f;
+ }
+ }
+ }
+ actually_set_camera_facing_object(object_name, rot_time, rot_acc_time, rot_dec_time);
+
+ //multiplayer callback
+ multi_start_packet();
+ multi_send_string(object_name);
+ multi_send_float(rot_time);
+ multi_send_float(rot_acc_time);
+ multi_send_float(rot_dec_time);
+ multi_end_packet();
+}
+
+//CommanderDJ
+void multi_sexp_set_camera_facing_object()
+{
+ char object_name[TOKEN_LENGTH];
+ float rot_time = 0.0f;
+ float rot_acc_time = 0.0f;
+ float rot_dec_time = 0.0f;
+
+ multi_get_string(object_name);
+ multi_get_float(rot_time);
+ multi_get_float(rot_acc_time);
+ multi_get_float(rot_dec_time);
+
+ actually_set_camera_facing_object(object_name, rot_time, rot_acc_time, rot_dec_time);
+}
+
extern float VIEWER_ZOOM_DEFAULT;
void sexp_set_camera_fov(int n)
{
@@ -18407,8 +18503,37 @@
}
cam->set_fov(camera_fov, camera_time, camera_acc_time, camera_dec_time);
+
+
+ multi_start_packet();
+ multi_send_float(camera_fov);
+ multi_send_float(camera_time);
+ multi_send_float(camera_acc_time);
+ multi_send_float(camera_dec_time);
+ multi_end_packet();
}
+//CommanderDJ
+void multi_sexp_set_camera_fov()
+{
+ camera *cam = sexp_get_set_camera();
+
+ if(cam == NULL)
+ return;
+
+ float camera_fov = VIEWER_ZOOM_DEFAULT;
+ float camera_time = 0.0f;
+ float camera_acc_time = 0.0f;
+ float camera_dec_time = 0.0f;
+
+ multi_get_float(camera_fov);
+ multi_get_float(camera_time);
+ multi_get_float(camera_acc_time);
+ multi_get_float(camera_dec_time);
+
+ cam->set_fov(camera_fov, camera_time, camera_acc_time, camera_dec_time);
+}
+
//Internal helper function for set-target and set-host
object *sexp_camera_get_objsub(int node, int *o_submodel)
{
@@ -18538,11 +18663,23 @@
if(is_sexp_true(node))
{
cam->reset();
+ multi_start_packet();
+ multi_end_packet();
}
}
cam_reset_camera();
}
+void multi_sexp_reset_camera()
+{
+ camera *cam = cam_get_current().getCamera();
+ if(cam != NULL)
+ {
+ cam->reset();
+ }
+ cam_reset_camera();
+}
+
void sexp_show_subtitle(int node)
{
//These should be set to the default if not required to be explicitly defined
@@ -18992,18 +19129,18 @@
void sexp_set_jumpnode_name(int n) //CommanderDJ
{
jump_node *jnp = jumpnode_get_by_name(CTEXT(n));
-
+
+ char *new_name = CTEXT(n); //for multi
char *old_name = CTEXT(n); //for multi
- if(jnp==NULL)
+ if(jnp==NULL) {
return;
+ }
n=CDR(n);
jnp->set_name(CTEXT(n));
- char *new_name = CTEXT(n); //for multi
-
//multiplayer callback
multi_start_packet();
multi_send_string(old_name);
@@ -19011,14 +19148,12 @@
multi_end_packet();
}
-void multi_sexp_set_jumpnode_name(int n) //CommanderDJ
+void multi_sexp_set_jumpnode_name() //CommanderDJ
{
- char *old_name = "\0";
+ char old_name[TOKEN_LENGTH];
+ char new_name[TOKEN_LENGTH];
multi_get_string(old_name);
-
- char *new_name = "\0";
-
multi_get_string(new_name);
jump_node *jnp = jumpnode_get_by_name(old_name);
@@ -19036,11 +19171,51 @@
if(jnp==NULL)
return;
+ char* jumpnode_name = CTEXT(n); //for multi
+
n=CDR(n);
- jnp->set_alphacolor(eval_num(n),eval_num(CDR(n)),eval_num(CDR(CDR(n))),eval_num(CDR(CDR(CDR(n)))));
+ int red = eval_num(n);
+
+ int green = eval_num(CDR(n));
+
+ int blue = eval_num(CDR(CDR(n)));
+
+ int alpha = eval_num(CDR(CDR(CDR(n))));
+
+ jnp->set_alphacolor(red, green, blue, alpha);
+
+ multi_start_packet();
+ multi_send_string(jumpnode_name);
+ multi_send_int(red);
+ multi_send_int(green);
+ multi_send_int(blue);
+ multi_send_int(alpha);
+ multi_end_packet();
}
+//CommanderDJ
+void multi_sexp_set_jumpnode_color()
+{
+ char jumpnode_name[TOKEN_LENGTH] ;
+ int red, blue, green, alpha;
+
+ multi_get_string(jumpnode_name);
+ jump_node *jnp = jumpnode_get_by_name(jumpnode_name);
+
+ if(jnp==NULL) {
+ multi_discard_remaining_packet();
+ return;
+ }
+
+ multi_get_int(red);
+ multi_get_int(green);
+ multi_get_int(blue);
+ multi_get_int(alpha);
+
+ jnp->set_alphacolor(red, green, blue, alpha);
+}
+
void sexp_set_jumpnode_model(int n)
{
jump_node *jnp = jumpnode_get_by_name(CTEXT(n));
@@ -19048,27 +19223,90 @@
if(jnp==NULL)
return;
- n=CDR(n);
+ char* jumpnode_name = CTEXT(n);
- jnp->set_model(CTEXT(n), is_sexp_true(CDR(n)) != 0);
+ char* model_name = CTEXT(CDR(n));
+
+ bool show_polys = CDR(CDR(n));
+
+ jnp->set_model(model_name, (is_sexp_true(show_polys) != 0));
+
+ multi_start_packet();
+ multi_send_string(jumpnode_name);
+ multi_send_string(model_name);
+ multi_send_bool(show_polys);
+ multi_end_packet();
}
+void multi_sexp_set_jumpnode_model()
+{
+ char jumpnode_name[TOKEN_LENGTH];
+ char model_name[TOKEN_LENGTH];
+
+ multi_get_string(jumpnode_name);
+ multi_get_string(model_name);
+
+ jump_node *jnp = jumpnode_get_by_name(jumpnode_name);
+
+ if(jnp==NULL)
+ return;
+
+ bool show_polys;
+
+ show_polys = multi_get_bool(show_polys);
+
+ jnp->set_model(model_name, (is_sexp_true(show_polys) != 0));
+
+}
+
void sexp_show_jumpnode(int n)
{
jump_node *jnp = jumpnode_get_by_name(CTEXT(n));
if(jnp!=NULL)
jnp->show(true);
+
+ multi_start_packet();
+ multi_send_string(CTEXT(n));
+ multi_end_packet();
}
+void multi_sexp_show_jumpnode()
+{
+ char jumpnode_name[TOKEN_LENGTH] ;
+
+ multi_get_string(jumpnode_name);
+
+ jump_node *jnp = jumpnode_get_by_name(jumpnode_name);
+
+ if(jnp!=NULL)
+ jnp->show(true);
+}
+
void sexp_hide_jumpnode(int n)
{
jump_node *jnp = jumpnode_get_by_name(CTEXT(n));
if(jnp!=NULL)
jnp->show(false);
+
+ multi_start_packet();
+ multi_send_string(CTEXT(n));
+ multi_end_packet();
}
+void multi_sexp_hide_jumpnode()
+{
+ char jumpnode_name[TOKEN_LENGTH] ;
+
+ multi_get_string(jumpnode_name);
+
+ jump_node *jnp = jumpnode_get_by_name(jumpnode_name);
+
+ if(jnp!=NULL)
+ jnp->show(false);
+}
+
//WMC - This is a bit of a hack, however, it's easier than
//coding in a whole new SCript_system function.
int sexp_script_eval(int node, int return_type)
@@ -21622,18 +21860,54 @@
multi_sexp_toggle_cutscene_bars(op_num == OP_CUTSCENES_SET_CUTSCENE_BARS );
break;
+ case OP_CUTSCENES_SET_CAMERA_FACING:
+ multi_sexp_set_camera_facing();
+ break;
+
+ case OP_CUTSCENES_SET_CAMERA_FACING_OBJECT:
+ multi_sexp_set_camera_facing_object();
+ break;
+
+ case OP_CUTSCENES_SET_CAMERA_FOV:
+ multi_sexp_set_camera_fov();
+ break;
+
+ case OP_CUTSCENES_SET_CAMERA_POSITION:
+ multi_sexp_set_camera_position();
+ break;
+
case OP_SET_CAMERA_SHUDDER:
multi_sexp_set_camera_shudder();
break;
+ case OP_CUTSCENES_RESET_CAMERA:
+ multi_sexp_reset_camera();
+ break;
+
case OP_JUMP_NODE_SET_JUMPNODE_NAME:
- multi_sexp_set_jumpnode_name(op_num == OP_JUMP_NODE_SET_JUMPNODE_NAME);
+ multi_sexp_set_jumpnode_name();
break;
case OP_IGNORE_KEY:
multi_sexp_ignore_key();
break;
+ case OP_JUMP_NODE_SET_JUMPNODE_COLOR:
+ multi_sexp_set_jumpnode_color();
+ break;
+
+ case OP_JUMP_NODE_SET_JUMPNODE_MODEL:
+ multi_sexp_set_jumpnode_model();
+ break;
+
+ case OP_JUMP_NODE_SHOW_JUMPNODE:
+ multi_sexp_show_jumpnode();
+ break;
+
+ case OP_JUMP_NODE_HIDE_JUMPNODE:
+ multi_sexp_hide_jumpnode();
+ break;
+
// bad sexp in the packet
default:
// probably just a version error where the host supports a SEXP but a client does not
@@ -21642,7 +21916,7 @@
}
// a more major problem
else {
- Warning(LOCATION, "Received invalid SEXP packet from host. Function involving operator %d lacks termination. Entire packet may be corrupt. Discarding remaining packet");
+ Warning(LOCATION, "Received invalid SEXP packet from host. Function involving operator %d lacks termination. Entire packet may be corrupt. Discarding remaining packet", op_num);
Int3();
return;
}
[attachment deleted by ninja]