diff --git a/client/packhand.cpp b/client/packhand.cpp index 372e23f385..a990b6692e 100644 --- a/client/packhand.cpp +++ b/client/packhand.cpp @@ -194,6 +194,8 @@ static struct unit *unpackage_unit(const struct packet_unit_info *packet) unit_tile_set(punit, index_to_tile(&(wld.map), packet->tile)); punit->facing = packet->facing; punit->homecity = packet->homecity; + punit->name = QString::fromUtf8(QByteArray(packet->name, + ARRAY_SIZE(packet->name))); output_type_iterate(o) { punit->upkeep[o] = packet->upkeep[o]; } output_type_iterate_end; punit->moves_left = packet->movesleft; @@ -290,6 +292,7 @@ unpackage_short_unit(const struct packet_unit_short_info *packet) punit->veteran = packet->veteran; punit->hp = packet->hp; punit->activity = static_cast(packet->activity); + punit->name = QString::fromUtf8(packet->name, ARRAY_SIZE(packet->name)); if (packet->activity_tgt == EXTRA_NONE) { punit->activity_target = NULL; diff --git a/common/networking/packets.def b/common/networking/packets.def index 31364901f4..79c428f8b4 100644 --- a/common/networking/packets.def +++ b/common/networking/packets.def @@ -1040,6 +1040,7 @@ PACKET_UNIT_INFO = 63; sc, lsend, is-game-info, cancel(PACKET_UNIT_SHORT_INFO) EXTRA changed_from_tgt; SINT8 battlegroup; + STRING name[MAX_LEN_NAME]; BOOL has_orders; UINT16 orders_length, orders_index; @@ -1059,6 +1060,7 @@ PACKET_UNIT_SHORT_INFO = 64; sc, lsend, is-game-info, force, cancel(PACKET_UNIT_ UINT8 veteran; BOOL occupied, transported; + STRING name[MAX_LEN_NAME]; UINT8 hp, activity; EXTRA activity_tgt; @@ -1152,6 +1154,11 @@ PACKET_UNIT_ACTIONS = 90; sc, dsend ACT_PROB action_probabilities[MAX_NUM_ACTIONS]; end +PACKET_UNIT_RENAME = 91; cs, dsend + UNIT unit_id; + STRING name[MAX_LEN_NAME]; +end + PACKET_UNIT_CHANGE_ACTIVITY = 222; cs, dsend UNIT unit_id; ACTIVITY activity; diff --git a/common/unit.h b/common/unit.h index 79182cbc38..646affa3a4 100644 --- a/common/unit.h +++ b/common/unit.h @@ -127,6 +127,7 @@ struct unit { struct player *nationality; int id; int homecity; + QString name; int upkeep[O_LAST]; // unit upkeep with regards to the homecity diff --git a/server/unithand.cpp b/server/unithand.cpp index b2950236b8..60a094d455 100644 --- a/server/unithand.cpp +++ b/server/unithand.cpp @@ -1940,6 +1940,19 @@ void handle_unit_get_actions(struct connection *pc, const int actor_unit_id, } } +/** + * Handle request to rename a unit. + */ +void handle_unit_rename(player *pplayer, int unit_id, const char *name) +{ + auto unit = game_unit_by_number(unit_id); + fc_assert_ret(unit != nullptr); + fc_assert_ret(pplayer == unit->owner); + + // Use the QByteArray overload to prevent unbounded read + unit->name = QString::fromUtf8(name, MAX_LEN_NAME); +} + /** Try to explain to the player why an action is illegal. diff --git a/server/unittools.cpp b/server/unittools.cpp index 2db673d031..360c2ad835 100644 --- a/server/unittools.cpp +++ b/server/unittools.cpp @@ -2539,6 +2539,7 @@ void package_unit(struct unit *punit, struct packet_unit_info *packet) packet->tile = tile_index(unit_tile(punit)); packet->facing = punit->facing; packet->homecity = punit->homecity; + fc_strlcpy(packet->name, punit->name.toUtf8(), ARRAY_SIZE(packet->name)); output_type_iterate(o) { packet->upkeep[o] = punit->upkeep[o]; } output_type_iterate_end; packet->veteran = punit->veteran; @@ -2624,6 +2625,7 @@ void package_short_unit(struct unit *punit, packet->type = utype_number(unit_type_get(punit)); packet->hp = punit->hp; packet->occupied = (get_transporter_occupancy(punit) > 0); + fc_strlcpy(packet->name, punit->name.toUtf8(), ARRAY_SIZE(packet->name)); if (punit->activity == ACTIVITY_EXPLORE || punit->activity == ACTIVITY_GOTO) { packet->activity = ACTIVITY_IDLE;