Skip to main content

nil_core/
error.rs

1// Copyright (C) Call of Nil contributors
2// SPDX-License-Identifier: AGPL-3.0-only
3
4use crate::continent::coord::Coord;
5use crate::continent::index::ContinentIndex;
6use crate::infrastructure::building::level::BuildingLevel;
7use crate::infrastructure::building::{BuildingId, MineId, StorageId};
8use crate::military::army::ArmyId;
9use crate::military::maneuver::ManeuverId;
10use crate::military::unit::UnitId;
11use crate::npc::bot::BotId;
12use crate::npc::precursor::PrecursorId;
13use crate::player::PlayerId;
14use crate::report::ReportId;
15use crate::resources::Resources;
16use crate::ruler::Ruler;
17use serde::Serialize;
18use serde::ser::Serializer;
19use std::result::Result as StdResult;
20use strum::EnumIs;
21
22#[doc(hidden)]
23pub type Result<T, E = Error> = StdResult<T, E>;
24#[doc(hidden)]
25pub type AnyResult<T> = anyhow::Result<T>;
26
27#[derive(Clone, Debug, EnumIs, thiserror::Error)]
28#[cfg_attr(feature = "typescript", derive(ts_rs::TS))]
29#[cfg_attr(feature = "typescript", ts(as = "String"))]
30#[remain::sorted]
31pub enum Error {
32  #[error("Army not found")]
33  ArmyNotFound(ArmyId),
34
35  #[error("Army is not idle")]
36  ArmyNotIdle(ArmyId),
37
38  #[error("Bot already spawned: {0}")]
39  BotAlreadySpawned(BotId),
40
41  #[error("Bot not found: {0}")]
42  BotNotFound(BotId),
43
44  #[error("No stats found for building \"{0}\"")]
45  BuildingStatsNotFound(BuildingId),
46
47  #[error("No stats found for building \"{0}\" at level {1}")]
48  BuildingStatsNotFoundForLevel(BuildingId, BuildingLevel),
49
50  #[error("Building \"{0}\" is already at its minimum level")]
51  CannotDecreaseBuildingLevel(BuildingId),
52
53  #[error("Building \"{0}\" is already at its maximum level")]
54  CannotIncreaseBuildingLevel(BuildingId),
55
56  #[error("Cheating is not allowed in this world")]
57  CheatingNotAllowed,
58
59  #[error("City not found: {0}")]
60  CityNotFound(Coord),
61
62  #[error("Failed to deserialize event")]
63  FailedToDeserializeEvent,
64
65  #[error("Failed to read savedata file")]
66  FailedToReadSavedata,
67
68  #[error("Failed to serialize event")]
69  FailedToSerializeEvent,
70
71  #[error("Failed to write savedata file")]
72  FailedToWriteSavedata,
73
74  #[error("{0} is not empty")]
75  FieldNotEmpty(Coord),
76
77  #[error("Not authorized to execute this action")]
78  Forbidden,
79
80  #[error("Index out of bounds: {0}")]
81  IndexOutOfBounds(ContinentIndex),
82
83  #[error("Insufficient gold")]
84  InsufficientGold,
85
86  #[error("Insufficient resources")]
87  InsufficientResources,
88
89  #[error("Insufficient units")]
90  InsufficientUnits,
91
92  #[error("Expected maneuver to be pending, but it is done")]
93  ManeuverIsDone(ManeuverId),
94
95  #[error("Expected maneuver to be done, but it is pending")]
96  ManeuverIsPending(ManeuverId),
97
98  #[error("Maneuver is already returning")]
99  ManeuverIsReturning(ManeuverId),
100
101  #[error("Maneuver not found")]
102  ManeuverNotFound(ManeuverId),
103
104  #[error("No stats found for mine \"{0}\"")]
105  MineStatsNotFound(MineId),
106
107  #[error("No stats found for mine \"{0}\" at level {1}")]
108  MineStatsNotFoundForLevel(MineId, BuildingLevel),
109
110  #[error("Not enough resources in the market vault")]
111  NotEnoughResourcesInMarketVault,
112
113  #[error("Player \"{0}\" has already taken their turn")]
114  NotWaitingPlayer(PlayerId),
115
116  #[error("Origin and destination have the same coords")]
117  OriginIsDestination(Coord),
118
119  #[error("Player already spawned: {0}")]
120  PlayerAlreadySpawned(PlayerId),
121
122  #[error("Player not found: {0}")]
123  PlayerNotFound(PlayerId),
124
125  #[error("Precursor not found: {0}")]
126  PrecursorNotFound(PrecursorId),
127
128  #[error("Report not found")]
129  ReportNotFound(ReportId),
130
131  #[error("Cannot send resources to self")]
132  ResourceReceiverIsSender(Ruler),
133
134  #[error("Round already started")]
135  RoundAlreadyStarted,
136
137  #[error("Round has pending players")]
138  RoundHasPendingPlayers,
139
140  #[error("Round has not started yet")]
141  RoundNotStarted,
142
143  #[error("No stats found for storage \"{0}\"")]
144  StorageStatsNotFound(StorageId),
145
146  #[error("No stats found for storage \"{0}\" at level {1}")]
147  StorageStatsNotFoundForLevel(StorageId, BuildingLevel),
148
149  #[error("Too many resources")]
150  TooManyResources(Resources),
151
152  #[error("Expected \"{0}\", got \"{1}\"")]
153  UnexpectedUnit(UnitId, UnitId),
154
155  #[error("No stats found for wall at level {0}")]
156  WallStatsNotFoundForLevel(BuildingLevel),
157
158  #[error("World is full")]
159  WorldIsFull,
160}
161
162impl Serialize for Error {
163  fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
164  where
165    S: Serializer,
166  {
167    serializer.serialize_str(self.to_string().as_str())
168  }
169}