Guest User

Untitled

a guest
Jul 18th, 2022
136
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
MySQL 11.48 KB | None | 0 0
  1. -- Some game objects have UUIDs, like players and worlds.
  2. -- Based on my research I store them as BINARY(16).
  3. -- I would like to use MySQL's UUID_TO_BIN functions but
  4. -- MariaDB doesn't support that. So use HEX/UNHEX and
  5. -- do the rest java-side.
  6.  
  7. -- "actions" are descriptive words that describe an event I log. "block-break", "item-drop", etc.
  8. -- actions are stored here only once so we can FK them
  9. -- I expect < 100 total
  10. CREATE TABLE `prism_actions` (
  11.   `action_id` tinyint(3) unsigned NOT NULL AUTO_INCREMENT,
  12.   `action` varchar(25) NOT NULL,
  13.   PRIMARY KEY (`action_id`),
  14.   UNIQUE KEY `action` (`action`)
  15. ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
  16.  
  17. -- this is the big guy
  18. -- "activities" are the actual log of game events. a game event is when a player does
  19. -- anything the server owner wants to track. we do this so server owners can track abuse.
  20. -- 90% of this table is foreign keys
  21. -- NOTE: I have not yet added any indexes for queries. Server OPs can search this data in many ways
  22. -- so it's difficult to make good indexes
  23. -- depending on how our users configure logging and purges this could store tens of millions of rows
  24. CREATE TABLE `prism_activities` (
  25.   `activity_id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  26.   `timestamp` int(10) unsigned NOT NULL,
  27.   `world_id` tinyint(3) unsigned NOT NULL,
  28.   `x` int(11) NOT NULL,
  29.   `y` int(11) NOT NULL,
  30.   `z` int(11) NOT NULL,
  31.   `action_id` tinyint(3) unsigned NOT NULL,
  32.   `material_id` smallint(5) unsigned DEFAULT NULL,
  33.   `old_material_id` smallint(5) unsigned DEFAULT NULL,
  34.   `entity_type_id` smallint(5) unsigned DEFAULT NULL,
  35.   `cause_id` int(10) unsigned NOT NULL,
  36.   `descriptor` varchar(255) DEFAULT NULL,
  37.   PRIMARY KEY (`activity_id`),
  38.   KEY `actionId_idx` (`action_id`),
  39.   KEY `causeId_idx` (`cause_id`),
  40.   KEY `entityTypeId_idx` (`entity_type_id`),
  41.   KEY `materialId_idx` (`material_id`),
  42.   KEY `oldMaterialId_idx` (`old_material_id`),
  43.   KEY `worldId_idx` (`world_id`),
  44.   CONSTRAINT `actionId` FOREIGN KEY (`action_id`) REFERENCES `prism_actions` (`action_id`),
  45.   CONSTRAINT `causeId` FOREIGN KEY (`cause_id`) REFERENCES `prism_causes` (`cause_id`),
  46.   CONSTRAINT `entityTypeId` FOREIGN KEY (`entity_type_id`) REFERENCES `prism_entity_types` (`entity_type_id`),
  47.   CONSTRAINT `materialId` FOREIGN KEY (`material_id`) REFERENCES `prism_materials` (`material_id`),
  48.   CONSTRAINT `oldMaterialId` FOREIGN KEY (`old_material_id`) REFERENCES `prism_materials` (`material_id`),
  49.   CONSTRAINT `worldId` FOREIGN KEY (`world_id`) REFERENCES `prism_worlds` (`world_id`)
  50. ) ENGINE=InnoDB CHARSET=utf8mb4;
  51.  
  52. -- this table tracks optional extra/custom data for activities. the data is a serialized string.
  53. -- we don't always know which format something will be serialized as so it might be JSON, but could be a custom json-like format.
  54. CREATE TABLE `prism_activities_custom_data` (
  55.   `extra_id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  56.   `activity_id` int(10) unsigned NOT NULL,
  57.   `version` smallint(6) DEFAULT NULL,
  58.   `data` text,
  59.   PRIMARY KEY (`extra_id`),
  60.   KEY `activityId_idx` (`activity_id`),
  61.   CONSTRAINT `activityId` FOREIGN KEY (`activity_id`) REFERENCES `prism_activities` (`activity_id`) ON DELETE CASCADE
  62. ) ENGINE=InnoDB CHARSET=utf8mb4;
  63.  
  64. -- "causes" are either a player or a named game object like a creature, explosion, etc.
  65. -- this table will usually have < 1000 rows but for busy servers could be < 100,000
  66. CREATE TABLE `prism_causes` (
  67.   `cause_id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  68.   `cause` varchar(25) DEFAULT NULL,
  69.   `player_id` int(10) unsigned DEFAULT NULL,
  70.   PRIMARY KEY (`cause_id`),
  71.   UNIQUE KEY `cause` (`cause`),
  72.   KEY `playerId_idx` (`player_id`),
  73.   CONSTRAINT `playerId` FOREIGN KEY (`player_id`) REFERENCES `prism_players` (`player_id`)
  74. ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
  75.  
  76. -- "entities" is what Minecraft calls creatures. cows, zombies, etc.
  77. -- entities are stored here only once so we can FK them
  78. -- this table will probably have < 100,000 records
  79. CREATE TABLE `prism_entity_types` (
  80.   `entity_type_id` smallint(5) unsigned NOT NULL AUTO_INCREMENT,
  81.   `entity_type` varchar(45) DEFAULT NULL,
  82.   PRIMARY KEY (`entity_type_id`),
  83.   UNIQUE KEY `entityType` (`entity_type`)
  84. ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
  85.  
  86. -- "materials" refer to items and blocks. "material" is a base type and "data" is extra for variations.
  87. -- I'm debating storing these together as other databases can't do compound indexes as well
  88. -- and I'm not sure there's a reason to keep them separate.
  89. -- materials are stored here only once so we can FK them
  90. -- this table will probably have < 100,000 records
  91. CREATE TABLE `prism_materials` (
  92.   `material_id` smallint(5) unsigned NOT NULL AUTO_INCREMENT,
  93.   `material` varchar(45) DEFAULT NULL,
  94.   `data` varchar(155) DEFAULT NULL,
  95.   PRIMARY KEY (`material_id`),
  96.   UNIQUE KEY `materialData` (`material`,`data`)
  97. ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
  98.  
  99. -- simple table to store random plugin-used data like schema versions etc
  100. -- this table will be tiny, likely having like 20 records
  101. CREATE TABLE `prism_meta` (
  102.   `meta_id` tinyint(3) unsigned NOT NULL AUTO_INCREMENT,
  103.   `k` varchar(25) NOT NULL,
  104.   `v` varchar(155) NOT NULL,
  105.   PRIMARY KEY (`meta_id`),
  106.   UNIQUE KEY `k` (`k`)
  107. ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
  108.  
  109. -- "players" refer to Minecraft players.
  110. -- The game gives players a UUID. Maybe I should be using that as the PK too and drop a column?
  111. -- this table will usually have < 1000 rows but for busy servers could be < 100,000
  112. CREATE TABLE `prism_players` (
  113.   `player_id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  114.   `player` varchar(16) NOT NULL,
  115.   `player_uuid` binary(16) NOT NULL,
  116.   PRIMARY KEY (`player_id`),
  117.   UNIQUE KEY `player_uuid` (`player_uuid`),
  118.   KEY `player` (`player`,`player_uuid`)
  119. ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
  120.  
  121. -- "worlds" refer to game worlds, dimensions that players play in.
  122. -- the game gives worlds a UUID. Same PK comment here
  123. -- this table will be tiny, usually having < 5 records but maybe < 20 lifetime
  124. CREATE TABLE `prism_worlds` (
  125.   `world_id` tinyint(3) unsigned NOT NULL AUTO_INCREMENT,
  126.   `world` varchar(255) NOT NULL,
  127.   `world_uuid` binary(16) NOT NULL,
  128.   PRIMARY KEY (`world_id`),
  129.   UNIQUE KEY `world_uuid` (`world_uuid`,`world`)
  130. ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
  131.  
  132.  
  133. -- In this new plugin I'm adding procedures to shift some of my logic to the DB server.
  134. -- Not all users have permission to CREATE PROCEDURE so those users will have to live
  135. -- with java doing that work.
  136.  
  137.  
  138. -- A big procedure to create activity data and create or get FK data
  139. DELIMITER;
  140. CREATE PROCEDURE `createActivity`(
  141.   IN `timestamp` INT,
  142.   IN `x` INT,
  143.   IN `y` INT,
  144.   IN `z` INT,
  145.   IN `action` VARCHAR(25),
  146.   IN `cause` VARCHAR(25),
  147.   IN `player` VARCHAR(16),
  148.   IN `playerUuid` VARCHAR(55),
  149.   IN `entityType` VARCHAR(25),
  150.   IN `material` VARCHAR(45),
  151.   IN `blockData` VARCHAR(155),
  152.   IN `oldMaterial` VARCHAR(45),
  153.   IN `oldBlockData` VARCHAR(155),
  154.   IN `world` VARCHAR(255),
  155.   IN `worldUuid` VARCHAR(55),
  156.   IN `customDataVersion` SMALLINT,
  157.   IN `customData` TEXT,
  158.   IN `descriptor` VARCHAR(255),
  159.   OUT `activityId` INT
  160. ) BEGIN
  161. SET
  162.   @entityId = NULL;
  163. SET
  164.   @materialId = NULL;
  165. SET
  166.   @oldMaterialId = NULL;
  167. SET
  168.   @playerId = NULL;
  169. CALL getOrCreateAction(`action`, @actionId);
  170. IF `playerUuid` IS NOT NULL THEN CALL getOrCreatePlayer(
  171.   `player`, `playerUuid`, @playerId
  172. );
  173. END IF;
  174. CALL getOrCreateCause(`cause`, @playerId, @causeId);
  175. CALL getOrCreateWorld(`world`, `worldUuid`, @worldId);
  176. IF `entityType` IS NOT NULL THEN CALL getOrCreateEntityType(entityType, @entityId);
  177. END IF;
  178. IF `material` IS NOT NULL THEN CALL getOrCreateMaterial(material, blockData, @materialId);
  179. END IF;
  180. IF `oldMaterial` IS NOT NULL THEN CALL getOrCreateMaterial(
  181.   oldMaterial, oldBlockData, @oldMaterialId
  182. );
  183. END IF;
  184. INSERT INTO `prism_activities` (
  185.   `timestamp`, `world_id`, `x`, `y`,
  186.   `z`, `action_id`, `material_id`,
  187.   `old_material_id`, `entity_type_id`,
  188.   `cause_id`, `descriptor`
  189. )
  190. VALUES
  191.   (
  192.     `timestamp`, @worldId, `x`, `y`, `z`,
  193.     @actionId, @materialId, @oldMaterialId,
  194.     @entityId, @causeId, `descriptor`
  195.   );
  196. SET
  197.   `activityId` = LAST_INSERT_ID();
  198. IF `customData` IS NOT NULL THEN INSERT INTO `prism_activities_custom_data` (`activity_id`, `version`, `data`)
  199. VALUES
  200.   (
  201.     `activityId`, `customDataVersion`,
  202.     `customData`
  203.   );
  204. END IF;
  205. END;
  206. DELIMITER;
  207.  
  208.  
  209. -- A procedure to get or create "actions"
  210. DELIMITER;
  211. CREATE PROCEDURE `getOrCreateAction`(
  212.   IN `actionKey` VARCHAR(25),
  213.   OUT `actionId` TINYINT
  214. ) BEGIN
  215. SELECT
  216.   action_id INTO `actionId`
  217. FROM
  218.   prism_actions
  219. WHERE
  220.   action = `actionKey`;
  221. IF `actionId` IS NULL THEN INSERT INTO prism_actions (`action`)
  222. VALUES
  223.   (`actionKey`);
  224. SET
  225.   `actionId` = LAST_INSERT_ID();
  226. END IF;
  227. END;
  228. DELIMITER;
  229.  
  230.  
  231. -- A procedure to get or create "causes"
  232. DELIMITER;
  233. CREATE PROCEDURE `getOrCreateCause`(
  234.   IN `causeStr` VARCHAR(25),
  235.   IN `playerId` INT,
  236.   OUT `causeId` INT
  237. ) BEGIN IF `playerId` IS NOT NULL THEN
  238. SELECT
  239.   cause_id INTO `causeId`
  240. FROM
  241.   prism_causes
  242. WHERE
  243.   player_id = `playerId`;
  244. ELSEIF `causeStr` IS NOT NULL THEN
  245. SELECT
  246.   cause_id INTO `causeId`
  247. FROM
  248.   prism_causes
  249. WHERE
  250.   cause = `causeStr`;
  251. END IF;
  252. IF `causeId` IS NULL THEN INSERT INTO prism_causes (`cause`, `player_id`)
  253. VALUES
  254.   (`causeStr`, `playerId`);
  255. SET
  256.   `causeId` = LAST_INSERT_ID();
  257. END IF;
  258. END;
  259. DELIMITER;
  260.  
  261.  
  262. -- A procedure to get or create "entity types"
  263. DELIMITER;
  264. CREATE PROCEDURE `getOrCreateEntityType`(
  265.   IN `entityType` VARCHAR(25),
  266.   OUT `entityTypeId` SMALLINT
  267. ) BEGIN
  268. SELECT
  269.   entity_type_id INTO `entityTypeId`
  270. FROM
  271.   prism_entity_types
  272. WHERE
  273.   entity_type = `entityType`;
  274. IF `entityTypeId` IS NULL THEN INSERT INTO prism_entity_types (`entity_type`)
  275. VALUES
  276.   (`entityType`);
  277. SET
  278.   `entityTypeId` = LAST_INSERT_ID();
  279. END IF;
  280. END;
  281. DELIMITER;
  282.  
  283.  
  284. -- A procedure to get or create "materials"
  285. DELIMITER;
  286. CREATE PROCEDURE `getOrCreateMaterial`(
  287.   IN `materialKey` VARCHAR(45),
  288.   IN `blockData` VARCHAR(155),
  289.   OUT `materialId` SMALLINT
  290. ) BEGIN IF blockData IS NOT NULL THEN
  291. SELECT
  292.   material_id INTO `materialId`
  293. FROM
  294.   prism_materials
  295. WHERE
  296.   material = `materialKey`
  297.   AND data = `blockData`;
  298. ELSE
  299. SELECT
  300.   material_id INTO `materialId`
  301. FROM
  302.   prism_materials
  303. WHERE
  304.   material = `materialKey`
  305.   AND data IS NULL;
  306. END IF;
  307. IF `materialId` IS NULL THEN INSERT INTO prism_materials (`material`, `data`)
  308. VALUES
  309.   (`materialKey`, `blockData`);
  310. SET
  311.   `materialId` = LAST_INSERT_ID();
  312. END IF;
  313. END;
  314. DELIMITER;
  315.  
  316.  
  317. -- A procedure to get or create "players"
  318. DELIMITER;
  319. CREATE PROCEDURE `getOrCreatePlayer`(
  320.   IN `playerName` VARCHAR(16),
  321.   IN `uuid` VARCHAR(55),
  322.   OUT `playerId` INT
  323. ) BEGIN
  324. SELECT
  325.   player_id INTO `playerId`
  326. FROM
  327.   prism_players
  328. WHERE
  329.   player_uuid = UNHEX(`uuid`);
  330. IF `playerId` IS NULL THEN INSERT INTO prism_players (`player`, `player_uuid`)
  331. VALUES
  332.   (
  333.     `playerName`,
  334.     UNHEX(`uuid`)
  335.   );
  336. SET
  337.   `playerId` = LAST_INSERT_ID();
  338. END IF;
  339. END;
  340. DELIMITER;
  341.  
  342.  
  343. -- A procedure to get or create "worlds"
  344. DELIMITER;
  345. CREATE PROCEDURE `getOrCreateWorld`(
  346.   IN `worldName` VARCHAR(255),
  347.   IN `uuid` VARCHAR(55),
  348.   OUT `worldId` TINYINT
  349. ) BEGIN
  350. SELECT
  351.   world_id INTO `worldId`
  352. FROM
  353.   prism_worlds
  354. WHERE
  355.   world_uuid = UNHEX(`uuid`);
  356. IF `worldId` IS NULL THEN INSERT INTO prism_worlds (`world`, `world_uuid`)
  357. VALUES
  358.   (
  359.     `worldName`,
  360.     UNHEX(`uuid`)
  361.   );
  362. SET
  363.   `worldId` = LAST_INSERT_ID();
  364. END IF;
  365. END;
  366. DELIMITER;
  367.  
  368.  
Advertisement
Add Comment
Please, Sign In to add comment