diff --git a/Resources/Database/Characters.sql b/Resources/Database/Characters.sql deleted file mode 100644 index cf1543f..0000000 --- a/Resources/Database/Characters.sql +++ /dev/null @@ -1,24 +0,0 @@ -CREATE SEQUENCE IF NOT EXISTS public.characters_id_seq - INCREMENT 1 - START 1 - MINVALUE 1 - MAXVALUE 9223372036854775807 - CACHE 1; - -ALTER SEQUENCE public.characters_id_seq - OWNER TO postgres; - -CREATE TABLE IF NOT EXISTS public.characters -( - id bigint NOT NULL DEFAULT nextval('characters_id_seq'::regclass), - name text COLLATE pg_catalog."default" NOT NULL, - permissionlevel smallint NOT NULL DEFAULT 0, - CONSTRAINT characters_pkey PRIMARY KEY (id) -); - -ALTER SEQUENCE public.characters_id_seq - OWNED BY public.characters.id; - -INSERT INTO public.characters( - id, name, permissionlevel) - VALUES (1, 'dev', 5); \ No newline at end of file diff --git a/Resources/Database/Database.sql b/Resources/Database/Database.sql new file mode 100644 index 0000000..5aab5b6 --- /dev/null +++ b/Resources/Database/Database.sql @@ -0,0 +1,819 @@ +-- +-- PostgreSQL database dump +-- + +-- Dumped from database version 16.3 +-- Dumped by pg_dump version 16.3 + +-- Started on 2024-07-31 15:30:22 + +SET statement_timeout = 0; +SET lock_timeout = 0; +SET idle_in_transaction_session_timeout = 0; +SET client_encoding = 'UTF8'; +SET standard_conforming_strings = on; +SELECT pg_catalog.set_config('search_path', '', false); +SET check_function_bodies = false; +SET xmloption = content; +SET client_min_messages = warning; +SET row_security = off; + +SET default_tablespace = ''; + +SET default_table_access_method = heap; + +-- +-- TOC entry 231 (class 1259 OID 32930) +-- Name: character_currency; Type: TABLE; Schema: public; Owner: postgres +-- + +DROP TABLE IF EXISTS public.character_currency CASCADE; +CREATE TABLE public.character_currency ( + id bigint NOT NULL, + characterid bigint NOT NULL, + currencyid smallint NOT NULL, + value bigint DEFAULT 0 NOT NULL +); + + +ALTER TABLE public.character_currency OWNER TO postgres; + +-- +-- TOC entry 230 (class 1259 OID 32929) +-- Name: character_currency_id_seq; Type: SEQUENCE; Schema: public; Owner: postgres +-- + +CREATE SEQUENCE public.character_currency_id_seq + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + + +ALTER SEQUENCE public.character_currency_id_seq OWNER TO postgres; + +-- +-- TOC entry 4942 (class 0 OID 0) +-- Dependencies: 230 +-- Name: character_currency_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: postgres +-- + +ALTER SEQUENCE public.character_currency_id_seq OWNED BY public.character_currency.id; + + +-- +-- TOC entry 227 (class 1259 OID 32864) +-- Name: character_permission_groups; Type: TABLE; Schema: public; Owner: postgres +-- + +DROP TABLE IF EXISTS public.character_permission_groups CASCADE; +CREATE TABLE public.character_permission_groups ( + id bigint NOT NULL, + characterid bigint NOT NULL, + permissiongroupid smallint NOT NULL +); + + +ALTER TABLE public.character_permission_groups OWNER TO postgres; + +-- +-- TOC entry 226 (class 1259 OID 32863) +-- Name: character_permission_groups_id_seq; Type: SEQUENCE; Schema: public; Owner: postgres +-- + +CREATE SEQUENCE public.character_permission_groups_id_seq + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + + +ALTER SEQUENCE public.character_permission_groups_id_seq OWNER TO postgres; + +-- +-- TOC entry 4943 (class 0 OID 0) +-- Dependencies: 226 +-- Name: character_permission_groups_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: postgres +-- + +ALTER SEQUENCE public.character_permission_groups_id_seq OWNED BY public.character_permission_groups.id; + + +-- +-- TOC entry 225 (class 1259 OID 32857) +-- Name: character_permissions; Type: TABLE; Schema: public; Owner: postgres +-- + +DROP TABLE IF EXISTS public.character_permissions CASCADE; +CREATE TABLE public.character_permissions ( + id bigint NOT NULL, + characterid bigint NOT NULL, + permissionid smallint NOT NULL +); + + +ALTER TABLE public.character_permissions OWNER TO postgres; + +-- +-- TOC entry 224 (class 1259 OID 32856) +-- Name: character_permissions_id_seq; Type: SEQUENCE; Schema: public; Owner: postgres +-- + +CREATE SEQUENCE public.character_permissions_id_seq + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + + +ALTER SEQUENCE public.character_permissions_id_seq OWNER TO postgres; + +-- +-- TOC entry 4944 (class 0 OID 0) +-- Dependencies: 224 +-- Name: character_permissions_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: postgres +-- + +ALTER SEQUENCE public.character_permissions_id_seq OWNED BY public.character_permissions.id; + + +-- +-- TOC entry 217 (class 1259 OID 16406) +-- Name: characters; Type: TABLE; Schema: public; Owner: postgres +-- + +DROP TABLE IF EXISTS public.characters CASCADE; +CREATE TABLE public.characters ( + id bigint NOT NULL, + accountid integer DEFAULT 0 NOT NULL, + name character varying(12) NOT NULL, + totaltime integer DEFAULT 0 NOT NULL, + leveltime integer DEFAULT 0 NOT NULL, + logouttime bigint DEFAULT 0 NOT NULL, + flags integer DEFAULT 0 NOT NULL, + racegenderclass smallint NOT NULL, + level smallint DEFAULT 1 NOT NULL, + experiencepoints bigint DEFAULT 0 NOT NULL, + mapid smallint DEFAULT 0 NOT NULL, + position_x numeric(10,4) DEFAULT 0.0 NOT NULL, + position_y numeric(10,4) DEFAULT 0.0 NOT NULL, + position_z numeric(10,4) DEFAULT 0.0 NOT NULL, + position_o numeric(10,4) DEFAULT 0.0 NOT NULL +); + + +ALTER TABLE public.characters OWNER TO postgres; + +-- +-- TOC entry 216 (class 1259 OID 16405) +-- Name: characters_id_seq; Type: SEQUENCE; Schema: public; Owner: postgres +-- + +CREATE SEQUENCE public.characters_id_seq + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + + +ALTER SEQUENCE public.characters_id_seq OWNER TO postgres; + +-- +-- TOC entry 4945 (class 0 OID 0) +-- Dependencies: 216 +-- Name: characters_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: postgres +-- + +ALTER SEQUENCE public.characters_id_seq OWNED BY public.characters.id; + + +-- +-- TOC entry 229 (class 1259 OID 32901) +-- Name: currency; Type: TABLE; Schema: public; Owner: postgres +-- + +DROP TABLE IF EXISTS public.currency CASCADE; +CREATE TABLE public.currency ( + id smallint NOT NULL, + name text NOT NULL +); + + +ALTER TABLE public.currency OWNER TO postgres; + +-- +-- TOC entry 228 (class 1259 OID 32900) +-- Name: currency_id_seq; Type: SEQUENCE; Schema: public; Owner: postgres +-- + +CREATE SEQUENCE public.currency_id_seq + AS smallint + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + + +ALTER SEQUENCE public.currency_id_seq OWNER TO postgres; + +-- +-- TOC entry 4946 (class 0 OID 0) +-- Dependencies: 228 +-- Name: currency_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: postgres +-- + +ALTER SEQUENCE public.currency_id_seq OWNED BY public.currency.id; + + +-- +-- TOC entry 223 (class 1259 OID 32850) +-- Name: permission_group_data; Type: TABLE; Schema: public; Owner: postgres +-- + +DROP TABLE IF EXISTS public.permission_group_data CASCADE; +CREATE TABLE public.permission_group_data ( + id integer NOT NULL, + groupid smallint NOT NULL, + permissionid smallint NOT NULL +); + + +ALTER TABLE public.permission_group_data OWNER TO postgres; + +-- +-- TOC entry 222 (class 1259 OID 32849) +-- Name: permission_group_data_id_seq; Type: SEQUENCE; Schema: public; Owner: postgres +-- + +CREATE SEQUENCE public.permission_group_data_id_seq + AS integer + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + + +ALTER SEQUENCE public.permission_group_data_id_seq OWNER TO postgres; + +-- +-- TOC entry 4947 (class 0 OID 0) +-- Dependencies: 222 +-- Name: permission_group_data_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: postgres +-- + +ALTER SEQUENCE public.permission_group_data_id_seq OWNED BY public.permission_group_data.id; + + +-- +-- TOC entry 221 (class 1259 OID 32841) +-- Name: permission_groups; Type: TABLE; Schema: public; Owner: postgres +-- + +DROP TABLE IF EXISTS public.permission_groups CASCADE; +CREATE TABLE public.permission_groups ( + id smallint NOT NULL, + name text NOT NULL +); + + +ALTER TABLE public.permission_groups OWNER TO postgres; + +-- +-- TOC entry 220 (class 1259 OID 32840) +-- Name: permission_groups_id_seq; Type: SEQUENCE; Schema: public; Owner: postgres +-- + +CREATE SEQUENCE public.permission_groups_id_seq + AS smallint + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + + +ALTER SEQUENCE public.permission_groups_id_seq OWNER TO postgres; + +-- +-- TOC entry 4948 (class 0 OID 0) +-- Dependencies: 220 +-- Name: permission_groups_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: postgres +-- + +ALTER SEQUENCE public.permission_groups_id_seq OWNED BY public.permission_groups.id; + + +-- +-- TOC entry 219 (class 1259 OID 32832) +-- Name: permissions; Type: TABLE; Schema: public; Owner: postgres +-- + +DROP TABLE IF EXISTS public.permissions CASCADE; +CREATE TABLE public.permissions ( + id smallint NOT NULL, + name text NOT NULL +); + + +ALTER TABLE public.permissions OWNER TO postgres; + +-- +-- TOC entry 218 (class 1259 OID 32831) +-- Name: permissions_id_seq; Type: SEQUENCE; Schema: public; Owner: postgres +-- + +CREATE SEQUENCE public.permissions_id_seq + AS smallint + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + + +ALTER SEQUENCE public.permissions_id_seq OWNER TO postgres; + +-- +-- TOC entry 4949 (class 0 OID 0) +-- Dependencies: 218 +-- Name: permissions_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: postgres +-- + +ALTER SEQUENCE public.permissions_id_seq OWNED BY public.permissions.id; + + +-- +-- TOC entry 4735 (class 2604 OID 32933) +-- Name: character_currency id; Type: DEFAULT; Schema: public; Owner: postgres +-- + +ALTER TABLE ONLY public.character_currency ALTER COLUMN id SET DEFAULT nextval('public.character_currency_id_seq'::regclass); + + +-- +-- TOC entry 4733 (class 2604 OID 32867) +-- Name: character_permission_groups id; Type: DEFAULT; Schema: public; Owner: postgres +-- + +ALTER TABLE ONLY public.character_permission_groups ALTER COLUMN id SET DEFAULT nextval('public.character_permission_groups_id_seq'::regclass); + + +-- +-- TOC entry 4732 (class 2604 OID 32860) +-- Name: character_permissions id; Type: DEFAULT; Schema: public; Owner: postgres +-- + +ALTER TABLE ONLY public.character_permissions ALTER COLUMN id SET DEFAULT nextval('public.character_permissions_id_seq'::regclass); + + +-- +-- TOC entry 4716 (class 2604 OID 16409) +-- Name: characters id; Type: DEFAULT; Schema: public; Owner: postgres +-- + +ALTER TABLE ONLY public.characters ALTER COLUMN id SET DEFAULT nextval('public.characters_id_seq'::regclass); + + +-- +-- TOC entry 4734 (class 2604 OID 32904) +-- Name: currency id; Type: DEFAULT; Schema: public; Owner: postgres +-- + +ALTER TABLE ONLY public.currency ALTER COLUMN id SET DEFAULT nextval('public.currency_id_seq'::regclass); + + +-- +-- TOC entry 4731 (class 2604 OID 32853) +-- Name: permission_group_data id; Type: DEFAULT; Schema: public; Owner: postgres +-- + +ALTER TABLE ONLY public.permission_group_data ALTER COLUMN id SET DEFAULT nextval('public.permission_group_data_id_seq'::regclass); + + +-- +-- TOC entry 4730 (class 2604 OID 32844) +-- Name: permission_groups id; Type: DEFAULT; Schema: public; Owner: postgres +-- + +ALTER TABLE ONLY public.permission_groups ALTER COLUMN id SET DEFAULT nextval('public.permission_groups_id_seq'::regclass); + + +-- +-- TOC entry 4729 (class 2604 OID 32835) +-- Name: permissions id; Type: DEFAULT; Schema: public; Owner: postgres +-- + +ALTER TABLE ONLY public.permissions ALTER COLUMN id SET DEFAULT nextval('public.permissions_id_seq'::regclass); + + +-- +-- TOC entry 4936 (class 0 OID 32930) +-- Dependencies: 231 +-- Data for Name: character_currency; Type: TABLE DATA; Schema: public; Owner: postgres +-- + +INSERT INTO public.character_currency (id, characterid, currencyid, value) VALUES (1, 1, 1, 0); + + +-- +-- TOC entry 4932 (class 0 OID 32864) +-- Dependencies: 227 +-- Data for Name: character_permission_groups; Type: TABLE DATA; Schema: public; Owner: postgres +-- + +INSERT INTO public.character_permission_groups (id, characterid, permissiongroupid) VALUES (1, 1, 1); +INSERT INTO public.character_permission_groups (id, characterid, permissiongroupid) VALUES (2, 1, 2); + + +-- +-- TOC entry 4930 (class 0 OID 32857) +-- Dependencies: 225 +-- Data for Name: character_permissions; Type: TABLE DATA; Schema: public; Owner: postgres +-- + + + +-- +-- TOC entry 4922 (class 0 OID 16406) +-- Dependencies: 217 +-- Data for Name: characters; Type: TABLE DATA; Schema: public; Owner: postgres +-- + +INSERT INTO public.characters (id, accountid, name, totaltime, leveltime, logouttime, flags, racegenderclass, level, experiencepoints, mapid, position_x, position_y, position_z, position_o) VALUES (1, 0, 'dev', 0, 0, 0, 0, 1, 1, 0, 0, 0.0000, 0.0000, 0.0000, 0.0000); + + +-- +-- TOC entry 4934 (class 0 OID 32901) +-- Dependencies: 229 +-- Data for Name: currency; Type: TABLE DATA; Schema: public; Owner: postgres +-- + +INSERT INTO public.currency (id, name) VALUES (1, 'gold'); + + +-- +-- TOC entry 4928 (class 0 OID 32850) +-- Dependencies: 223 +-- Data for Name: permission_group_data; Type: TABLE DATA; Schema: public; Owner: postgres +-- + +INSERT INTO public.permission_group_data (id, groupid, permissionid) VALUES (1, 1, 8); +INSERT INTO public.permission_group_data (id, groupid, permissionid) VALUES (2, 1, 9); +INSERT INTO public.permission_group_data (id, groupid, permissionid) VALUES (3, 1, 10); +INSERT INTO public.permission_group_data (id, groupid, permissionid) VALUES (4, 1, 11); +INSERT INTO public.permission_group_data (id, groupid, permissionid) VALUES (5, 1, 12); +INSERT INTO public.permission_group_data (id, groupid, permissionid) VALUES (6, 1, 13); +INSERT INTO public.permission_group_data (id, groupid, permissionid) VALUES (7, 2, 1); +INSERT INTO public.permission_group_data (id, groupid, permissionid) VALUES (8, 2, 2); +INSERT INTO public.permission_group_data (id, groupid, permissionid) VALUES (9, 2, 3); +INSERT INTO public.permission_group_data (id, groupid, permissionid) VALUES (10, 2, 4); +INSERT INTO public.permission_group_data (id, groupid, permissionid) VALUES (11, 2, 5); +INSERT INTO public.permission_group_data (id, groupid, permissionid) VALUES (12, 2, 6); +INSERT INTO public.permission_group_data (id, groupid, permissionid) VALUES (13, 2, 7); +INSERT INTO public.permission_group_data (id, groupid, permissionid) VALUES (14, 2, 14); + + +-- +-- TOC entry 4926 (class 0 OID 32841) +-- Dependencies: 221 +-- Data for Name: permission_groups; Type: TABLE DATA; Schema: public; Owner: postgres +-- + +INSERT INTO public.permission_groups (id, name) VALUES (1, 'admin'); +INSERT INTO public.permission_groups (id, name) VALUES (2, 'gamemaster'); +INSERT INTO public.permission_groups (id, name) VALUES (3, 'moderator'); +INSERT INTO public.permission_groups (id, name) VALUES (4, 'qa'); +INSERT INTO public.permission_groups (id, name) VALUES (5, 'tester'); + + +-- +-- TOC entry 4924 (class 0 OID 32832) +-- Dependencies: 219 +-- Data for Name: permissions; Type: TABLE DATA; Schema: public; Owner: postgres +-- + +INSERT INTO public.permissions (id, name) VALUES (1, 'cheatdamage'); +INSERT INTO public.permissions (id, name) VALUES (2, 'cheatheal'); +INSERT INTO public.permissions (id, name) VALUES (3, 'cheatkill'); +INSERT INTO public.permissions (id, name) VALUES (4, 'cheatresurrect'); +INSERT INTO public.permissions (id, name) VALUES (5, 'cheatmorph'); +INSERT INTO public.permissions (id, name) VALUES (6, 'cheatdemorph'); +INSERT INTO public.permissions (id, name) VALUES (7, 'cheatteleport'); +INSERT INTO public.permissions (id, name) VALUES (8, 'cheatcreatechar'); +INSERT INTO public.permissions (id, name) VALUES (9, 'cheatdeletechar'); +INSERT INTO public.permissions (id, name) VALUES (10, 'cheatdeletepermission'); +INSERT INTO public.permissions (id, name) VALUES (11, 'cheatsetpermission'); +INSERT INTO public.permissions (id, name) VALUES (12, 'cheatdeletepermissiongroup'); +INSERT INTO public.permissions (id, name) VALUES (13, 'cheatsetpermissiongroup'); +INSERT INTO public.permissions (id, name) VALUES (14, 'cheatsetcurrency'); + + +-- +-- TOC entry 4950 (class 0 OID 0) +-- Dependencies: 230 +-- Name: character_currency_id_seq; Type: SEQUENCE SET; Schema: public; Owner: postgres +-- + +SELECT pg_catalog.setval('public.character_currency_id_seq', 1, true); + + +-- +-- TOC entry 4951 (class 0 OID 0) +-- Dependencies: 226 +-- Name: character_permission_groups_id_seq; Type: SEQUENCE SET; Schema: public; Owner: postgres +-- + +SELECT pg_catalog.setval('public.character_permission_groups_id_seq', 2, true); + + +-- +-- TOC entry 4952 (class 0 OID 0) +-- Dependencies: 224 +-- Name: character_permissions_id_seq; Type: SEQUENCE SET; Schema: public; Owner: postgres +-- + +SELECT pg_catalog.setval('public.character_permissions_id_seq', 1, false); + + +-- +-- TOC entry 4953 (class 0 OID 0) +-- Dependencies: 216 +-- Name: characters_id_seq; Type: SEQUENCE SET; Schema: public; Owner: postgres +-- + +SELECT pg_catalog.setval('public.characters_id_seq', 1, true); + + +-- +-- TOC entry 4954 (class 0 OID 0) +-- Dependencies: 228 +-- Name: currency_id_seq; Type: SEQUENCE SET; Schema: public; Owner: postgres +-- + +SELECT pg_catalog.setval('public.currency_id_seq', 1, true); + + +-- +-- TOC entry 4955 (class 0 OID 0) +-- Dependencies: 222 +-- Name: permission_group_data_id_seq; Type: SEQUENCE SET; Schema: public; Owner: postgres +-- + +SELECT pg_catalog.setval('public.permission_group_data_id_seq', 14, true); + + +-- +-- TOC entry 4956 (class 0 OID 0) +-- Dependencies: 220 +-- Name: permission_groups_id_seq; Type: SEQUENCE SET; Schema: public; Owner: postgres +-- + +SELECT pg_catalog.setval('public.permission_groups_id_seq', 5, true); + + +-- +-- TOC entry 4957 (class 0 OID 0) +-- Dependencies: 218 +-- Name: permissions_id_seq; Type: SEQUENCE SET; Schema: public; Owner: postgres +-- + +SELECT pg_catalog.setval('public.permissions_id_seq', 14, true); + + +-- +-- TOC entry 4767 (class 2606 OID 32935) +-- Name: character_currency character_currency_pkey; Type: CONSTRAINT; Schema: public; Owner: postgres +-- + +ALTER TABLE ONLY public.character_currency + ADD CONSTRAINT character_currency_pkey PRIMARY KEY (id); + + +-- +-- TOC entry 4759 (class 2606 OID 32869) +-- Name: character_permission_groups character_permission_groups_pkey; Type: CONSTRAINT; Schema: public; Owner: postgres +-- + +ALTER TABLE ONLY public.character_permission_groups + ADD CONSTRAINT character_permission_groups_pkey PRIMARY KEY (id); + + +-- +-- TOC entry 4755 (class 2606 OID 32862) +-- Name: character_permissions character_permissions_pkey; Type: CONSTRAINT; Schema: public; Owner: postgres +-- + +ALTER TABLE ONLY public.character_permissions + ADD CONSTRAINT character_permissions_pkey PRIMARY KEY (id); + + +-- +-- TOC entry 4739 (class 2606 OID 16413) +-- Name: characters characters_pkey; Type: CONSTRAINT; Schema: public; Owner: postgres +-- + +ALTER TABLE ONLY public.characters + ADD CONSTRAINT characters_pkey PRIMARY KEY (id); + + +-- +-- TOC entry 4737 (class 2606 OID 32910) +-- Name: characters checknamelength; Type: CHECK CONSTRAINT; Schema: public; Owner: postgres +-- + +ALTER TABLE public.characters + ADD CONSTRAINT checknamelength CHECK ((char_length((name)::text) >= 2)) NOT VALID; + + +-- +-- TOC entry 4763 (class 2606 OID 32908) +-- Name: currency currency_pkey; Type: CONSTRAINT; Schema: public; Owner: postgres +-- + +ALTER TABLE ONLY public.currency + ADD CONSTRAINT currency_pkey PRIMARY KEY (id); + + +-- +-- TOC entry 4751 (class 2606 OID 32855) +-- Name: permission_group_data permission_group_data_pkey; Type: CONSTRAINT; Schema: public; Owner: postgres +-- + +ALTER TABLE ONLY public.permission_group_data + ADD CONSTRAINT permission_group_data_pkey PRIMARY KEY (id); + + +-- +-- TOC entry 4747 (class 2606 OID 32848) +-- Name: permission_groups permission_groups_pkey; Type: CONSTRAINT; Schema: public; Owner: postgres +-- + +ALTER TABLE ONLY public.permission_groups + ADD CONSTRAINT permission_groups_pkey PRIMARY KEY (id); + + +-- +-- TOC entry 4743 (class 2606 OID 32839) +-- Name: permissions permissions_pkey; Type: CONSTRAINT; Schema: public; Owner: postgres +-- + +ALTER TABLE ONLY public.permissions + ADD CONSTRAINT permissions_pkey PRIMARY KEY (id); + + +-- +-- TOC entry 4741 (class 2606 OID 32912) +-- Name: characters unique character name; Type: CONSTRAINT; Schema: public; Owner: postgres +-- + +ALTER TABLE ONLY public.characters + ADD CONSTRAINT "unique character name" UNIQUE (name); + + +-- +-- TOC entry 4769 (class 2606 OID 32948) +-- Name: character_currency unique characterid to currencyid; Type: CONSTRAINT; Schema: public; Owner: postgres +-- + +ALTER TABLE ONLY public.character_currency + ADD CONSTRAINT "unique characterid to currencyid" UNIQUE (characterid, currencyid); + + +-- +-- TOC entry 4761 (class 2606 OID 32924) +-- Name: character_permission_groups unique characterid to permissiongroupid; Type: CONSTRAINT; Schema: public; Owner: postgres +-- + +ALTER TABLE ONLY public.character_permission_groups + ADD CONSTRAINT "unique characterid to permissiongroupid" UNIQUE (characterid, permissiongroupid); + + +-- +-- TOC entry 4757 (class 2606 OID 32926) +-- Name: character_permissions unique characterid to permissionid; Type: CONSTRAINT; Schema: public; Owner: postgres +-- + +ALTER TABLE ONLY public.character_permissions + ADD CONSTRAINT "unique characterid to permissionid" UNIQUE (characterid, permissionid); + + +-- +-- TOC entry 4765 (class 2606 OID 32914) +-- Name: currency unique currency name; Type: CONSTRAINT; Schema: public; Owner: postgres +-- + +ALTER TABLE ONLY public.currency + ADD CONSTRAINT "unique currency name" UNIQUE (name); + + +-- +-- TOC entry 4749 (class 2606 OID 32918) +-- Name: permission_groups unique permission group name; Type: CONSTRAINT; Schema: public; Owner: postgres +-- + +ALTER TABLE ONLY public.permission_groups + ADD CONSTRAINT "unique permission group name" UNIQUE (name); + + +-- +-- TOC entry 4745 (class 2606 OID 32916) +-- Name: permissions unique permission name; Type: CONSTRAINT; Schema: public; Owner: postgres +-- + +ALTER TABLE ONLY public.permissions + ADD CONSTRAINT "unique permission name" UNIQUE (name); + + +-- +-- TOC entry 4753 (class 2606 OID 32928) +-- Name: permission_group_data unique permissiongroupid to permissionid; Type: CONSTRAINT; Schema: public; Owner: postgres +-- + +ALTER TABLE ONLY public.permission_group_data + ADD CONSTRAINT "unique permissiongroupid to permissionid" UNIQUE (groupid, permissionid); + + +-- +-- TOC entry 4772 (class 2606 OID 32870) +-- Name: character_permissions characterid; Type: FK CONSTRAINT; Schema: public; Owner: postgres +-- + +ALTER TABLE ONLY public.character_permissions + ADD CONSTRAINT characterid FOREIGN KEY (characterid) REFERENCES public.characters(id) ON DELETE CASCADE NOT VALID; + + +-- +-- TOC entry 4774 (class 2606 OID 32880) +-- Name: character_permission_groups characterid; Type: FK CONSTRAINT; Schema: public; Owner: postgres +-- + +ALTER TABLE ONLY public.character_permission_groups + ADD CONSTRAINT characterid FOREIGN KEY (characterid) REFERENCES public.characters(id) ON DELETE CASCADE NOT VALID; + + +-- +-- TOC entry 4776 (class 2606 OID 32936) +-- Name: character_currency characterid; Type: FK CONSTRAINT; Schema: public; Owner: postgres +-- + +ALTER TABLE ONLY public.character_currency + ADD CONSTRAINT characterid FOREIGN KEY (characterid) REFERENCES public.characters(id) ON DELETE CASCADE; + + +-- +-- TOC entry 4777 (class 2606 OID 32941) +-- Name: character_currency currencyid; Type: FK CONSTRAINT; Schema: public; Owner: postgres +-- + +ALTER TABLE ONLY public.character_currency + ADD CONSTRAINT currencyid FOREIGN KEY (currencyid) REFERENCES public.currency(id) ON DELETE CASCADE; + + +-- +-- TOC entry 4770 (class 2606 OID 32890) +-- Name: permission_group_data groupid; Type: FK CONSTRAINT; Schema: public; Owner: postgres +-- + +ALTER TABLE ONLY public.permission_group_data + ADD CONSTRAINT groupid FOREIGN KEY (groupid) REFERENCES public.permission_groups(id) ON DELETE CASCADE NOT VALID; + + +-- +-- TOC entry 4775 (class 2606 OID 32885) +-- Name: character_permission_groups permissiongroupid; Type: FK CONSTRAINT; Schema: public; Owner: postgres +-- + +ALTER TABLE ONLY public.character_permission_groups + ADD CONSTRAINT permissiongroupid FOREIGN KEY (permissiongroupid) REFERENCES public.permission_groups(id) NOT VALID; + + +-- +-- TOC entry 4773 (class 2606 OID 32875) +-- Name: character_permissions permissionid; Type: FK CONSTRAINT; Schema: public; Owner: postgres +-- + +ALTER TABLE ONLY public.character_permissions + ADD CONSTRAINT permissionid FOREIGN KEY (permissionid) REFERENCES public.permissions(id) ON DELETE CASCADE NOT VALID; + + +-- +-- TOC entry 4771 (class 2606 OID 32895) +-- Name: permission_group_data permissionid; Type: FK CONSTRAINT; Schema: public; Owner: postgres +-- + +ALTER TABLE ONLY public.permission_group_data + ADD CONSTRAINT permissionid FOREIGN KEY (permissionid) REFERENCES public.permissions(id) ON DELETE CASCADE NOT VALID; + + +-- Completed on 2024-07-31 15:30:22 + +-- +-- PostgreSQL database dump complete +-- + diff --git a/Resources/Database/Updates/Characters_300720241722.sql b/Resources/Database/Updates/Characters_300720241722.sql deleted file mode 100644 index 8ccd1e3..0000000 --- a/Resources/Database/Updates/Characters_300720241722.sql +++ /dev/null @@ -1,5 +0,0 @@ -ALTER TABLE public.characters - ADD position_x numeric NOT NULL DEFAULT 0.0, - ADD position_y numeric NOT NULL DEFAULT 0.0, - ADD position_z numeric NOT NULL DEFAULT 0.0, - ADD position_o numeric NOT NULL DEFAULT 0.0; \ No newline at end of file diff --git a/Source/Server-Common/Server-Common/Database/DBController.h b/Source/Server-Common/Server-Common/Database/DBController.h index 19a1c4c..df55ad7 100644 --- a/Source/Server-Common/Server-Common/Database/DBController.h +++ b/Source/Server-Common/Server-Common/Database/DBController.h @@ -5,7 +5,7 @@ #include -namespace Server::Database +namespace Database { enum class DBType { @@ -61,7 +61,8 @@ namespace Server::Database } } - pqxx::work Context() { return pqxx::work(*connection); } + pqxx::nontransaction NewNonTransaction() { return pqxx::nontransaction(*connection); } + pqxx::work NewTransaction() { return pqxx::work(*connection); } public: pqxx::connection* connection = nullptr; diff --git a/Source/Server-Common/Server-Common/Database/Definitions.h b/Source/Server-Common/Server-Common/Database/Definitions.h new file mode 100644 index 0000000..b98ca8a --- /dev/null +++ b/Source/Server-Common/Server-Common/Database/Definitions.h @@ -0,0 +1,88 @@ +#pragma once +#include + +#include + +#include + +namespace Database +{ + struct CharacterDefinition + { + public: + u64 id = std::numeric_limits().max(); + u32 accountid = 0; + std::string name = ""; + u32 totalTime = 0; + u32 levelTime = 0; + u32 logoutTime = 0; + u32 flags = 0; + u16 raceGenderClass = 0; + u16 level = 0; + u64 experiencePoints = 0; + u16 mapID = 0; + vec3 position = vec3(0.0f); + f32 orientation = 0.0f; + + public: + GameDefine::Race GetRace() const { return static_cast(raceGenderClass & 0x7F); } + GameDefine::Gender GetGender() const { return static_cast((raceGenderClass >> 7) & 0x3); } + GameDefine::GameClass GetGameClass() const { return static_cast((raceGenderClass >> 9) & 0x7f); } + }; + struct CharacterCurrency + { + public: + u16 currencyID = 0; + u64 value = 0; + }; + + struct Permission + { + public: + u16 id = 0; + std::string name; + }; + struct PermissionGroup + { + public: + u16 id = 0; + std::string name; + }; + struct PermissionGroupData + { + public: + u16 groupID = 0; + u16 permissionID = 0; + }; + + struct Currency + { + public: + u16 id = 0; + std::string name; + }; + + struct PermissionTables + { + public: + robin_hood::unordered_map idToDefinition; + robin_hood::unordered_map groupIDToDefinition; + robin_hood::unordered_map> groupIDToData; + }; + + struct CurrencyTables + { + public: + robin_hood::unordered_map idToDefinition; + }; + + struct CharacterTables + { + public: + robin_hood::unordered_map idToDefinition; + robin_hood::unordered_map nameHashToID; + robin_hood::unordered_map> idToPermissions; + robin_hood::unordered_map> idToPermissionGroups; + robin_hood::unordered_map> idToCurrency; + }; +} \ No newline at end of file diff --git a/Source/Server-Common/Server-Common/Database/Util/CharacterUtils.cpp b/Source/Server-Common/Server-Common/Database/Util/CharacterUtils.cpp new file mode 100644 index 0000000..3680c8d --- /dev/null +++ b/Source/Server-Common/Server-Common/Database/Util/CharacterUtils.cpp @@ -0,0 +1,182 @@ +#include "CharacterUtils.h" +#include "Server-Common/Database/DBController.h" + +#include +#include + +#include + +namespace Database::Util::Character +{ + void InitCharacterTablesPreparedStatements(std::shared_ptr& dbConnection) + { + NC_LOG_INFO("Loading Prepared Statements Character Tables..."); + + dbConnection->connection->prepare("CreateCharacter", "INSERT INTO public.characters (name, racegenderclass) VALUES ($1, $2) RETURNING id"); + dbConnection->connection->prepare("DeleteCharacter", "DELETE FROM public.characters WHERE id = $1"); + + dbConnection->connection->prepare("SetCharacterCurrency", "INSERT INTO public.character_currency (characterid, currencyid, value) VALUES ($1, $2, $3) ON CONFLICT(characterid, currencyid) DO UPDATE SET value = EXCLUDED.value"); + dbConnection->connection->prepare("DeleteCharacterCurrency", "DELETE FROM public.character_currency WHERE characterid = $1 AND currencyid = $2"); + + dbConnection->connection->prepare("SetCharacterPermission", "INSERT INTO public.character_permissions (characterid, permissionid) VALUES ($1, $2) ON CONFLICT(characterid, permissionid) DO NOTHING"); + dbConnection->connection->prepare("DeleteCharacterPermission", "DELETE FROM public.character_permissions WHERE characterid = $1 AND permissionid = $2"); + + dbConnection->connection->prepare("SetCharacterPermissionGroup", "INSERT INTO public.character_permission_groups (characterid, permissiongroupid) VALUES ($1, $2) ON CONFLICT(characterid, permissiongroupid) DO NOTHING"); + dbConnection->connection->prepare("DeleteCharacterPermissionGroup", "DELETE FROM public.character_permission_groups WHERE characterid = $1 AND permissiongroupid = $2"); + + NC_LOG_INFO("Loaded Prepared Statements Character Tables\n"); + } + + void LoadCharacterTables(std::shared_ptr& dbConnection, Database::CharacterTables& characterTables) + { + NC_LOG_INFO("-- Loading Character Tables --"); + + u64 totalRows = 0; + totalRows += LoadCharacterData(dbConnection, characterTables); + totalRows += LoadCharacterPermissions(dbConnection, characterTables); + totalRows += LoadCharacterPermissionGroups(dbConnection, characterTables); + totalRows += LoadCharacterCurrency(dbConnection, characterTables); + + NC_LOG_INFO("-- Loaded Character Tables ({0} rows) --\n", totalRows); + } + + u64 LoadCharacterData(std::shared_ptr& dbConnection, Database::CharacterTables& characterTables) + { + NC_LOG_INFO("Loading Table 'characters'..."); + + pqxx::nontransaction nonTransaction = dbConnection->NewNonTransaction(); + + auto result = nonTransaction.exec("SELECT COUNT(*) FROM public.characters"); + u64 numRows = result[0][0].as(); + + characterTables.idToDefinition.clear(); + characterTables.nameHashToID.clear(); + + if (numRows == 0) + { + NC_LOG_INFO("Skipped Table 'characters'"); + return 0; + } + + characterTables.idToDefinition.reserve(numRows); + characterTables.nameHashToID.reserve(numRows); + + nonTransaction.for_stream("SELECT * FROM public.characters", [&characterTables](u64 id, u32 accountID, const std::string& name, u32 totalTime, u32 levelTime, u32 logoutTime, u32 flags, u16 raceGenderClass, u16 level, u64 experiencePoints, u16 mapID, f32 posX, f32 posY, f32 posZ, f32 orientation) + { + Database::CharacterDefinition character = + { + .id = id, + .accountid = accountID, + .name = name, + .totalTime = totalTime, + .levelTime = levelTime, + .logoutTime = logoutTime, + .flags = flags, + .raceGenderClass = raceGenderClass, + .level = level, + .experiencePoints = experiencePoints, + .mapID = mapID, + .position = vec3(posX, posY, posZ), + .orientation = orientation + }; + + u32 characterNameHash = StringUtils::fnv1a_32(character.name.c_str(), character.name.size()); + + characterTables.idToDefinition.insert({ character.id, character }); + characterTables.nameHashToID.insert({ characterNameHash, character.id }); + }); + + NC_LOG_INFO("Loaded Table 'characters' ({0} Rows)", numRows); + return numRows; + } + u64 LoadCharacterPermissions(std::shared_ptr& dbConnection, Database::CharacterTables& characterTables) + { + NC_LOG_INFO("Loading Table 'character_permissions'"); + + pqxx::nontransaction nonTransaction = dbConnection->NewNonTransaction(); + + auto result = nonTransaction.exec("SELECT COUNT(*) FROM public.character_permissions"); + u64 numRows = result[0][0].as(); + + characterTables.idToPermissions.clear(); + + if (numRows == 0) + { + NC_LOG_INFO("Skipped Table 'character_permissions'"); + return 0; + } + + characterTables.idToPermissions.reserve(numRows); + + nonTransaction.for_stream("SELECT * FROM public.character_permissions", [&characterTables](u64 id, u64 characterID, u16 permissionID) + { + std::vector& permissions = characterTables.idToPermissions[characterID]; + permissions.push_back(permissionID); + }); + + NC_LOG_INFO("Loaded Table 'character_permissions' ({0} Rows)", numRows); + return numRows; + } + u64 LoadCharacterPermissionGroups(std::shared_ptr& dbConnection, Database::CharacterTables& characterTables) + { + NC_LOG_INFO("Loading Table 'character_permission_groups'"); + + pqxx::nontransaction nonTransaction = dbConnection->NewNonTransaction(); + + auto result = nonTransaction.exec("SELECT COUNT(*) FROM public.character_permission_groups"); + u64 numRows = result[0][0].as(); + + characterTables.idToPermissionGroups.clear(); + + if (numRows == 0) + { + NC_LOG_INFO("Skipped Table 'character_permission_groups'"); + return 0; + } + + characterTables.idToPermissionGroups.reserve(numRows); + + nonTransaction.for_stream("SELECT * FROM public.character_permission_groups", [&characterTables](u64 id, u64 characterID, u16 permissionGroupID) + { + std::vector& permissionGroups = characterTables.idToPermissionGroups[characterID]; + permissionGroups.push_back(permissionGroupID); + }); + + NC_LOG_INFO("Loaded Table 'character_permission_groups' ({0} Rows)", numRows); + return numRows; + } + u64 LoadCharacterCurrency(std::shared_ptr& dbConnection, Database::CharacterTables& characterTables) + { + NC_LOG_INFO("Loading Table 'character_currency'"); + + pqxx::nontransaction nonTransaction = dbConnection->NewNonTransaction(); + + auto result = nonTransaction.exec("SELECT COUNT(*) FROM public.character_currency"); + u64 numRows = result[0][0].as(); + + characterTables.idToCurrency.clear(); + + if (numRows == 0) + { + NC_LOG_INFO("Skipped Table 'character_currency'"); + return 0; + } + + characterTables.idToCurrency.reserve(numRows); + + nonTransaction.for_stream("SELECT * FROM public.character_currency", [&characterTables](u64 id, u64 characterID, u16 currencyID, u64 value) + { + CharacterCurrency currency = + { + .currencyID = currencyID, + .value = value + }; + + std::vector& characterCurrencies = characterTables.idToCurrency[characterID]; + characterCurrencies.push_back(currency); + }); + + NC_LOG_INFO("Loaded Table 'character_currency' ({0} Rows)", numRows); + return numRows; + } +} \ No newline at end of file diff --git a/Source/Server-Common/Server-Common/Database/Util/CharacterUtils.h b/Source/Server-Common/Server-Common/Database/Util/CharacterUtils.h new file mode 100644 index 0000000..541ed1a --- /dev/null +++ b/Source/Server-Common/Server-Common/Database/Util/CharacterUtils.h @@ -0,0 +1,20 @@ +#pragma once +#include "Server-Common/Database/Definitions.h" + +#include + +namespace Database +{ + struct DBConnection; + + namespace Util::Character + { + void InitCharacterTablesPreparedStatements(std::shared_ptr& dbConnection); + + void LoadCharacterTables(std::shared_ptr& dbConnection, Database::CharacterTables& characterTables); + u64 LoadCharacterData(std::shared_ptr& dbConnection, Database::CharacterTables& characterTables); + u64 LoadCharacterPermissions(std::shared_ptr& dbConnection, Database::CharacterTables& characterTables); + u64 LoadCharacterPermissionGroups(std::shared_ptr& dbConnection, Database::CharacterTables& characterTables); + u64 LoadCharacterCurrency(std::shared_ptr& dbConnection, Database::CharacterTables& characterTables); + } +} \ No newline at end of file diff --git a/Source/Server-Common/Server-Common/Database/Util/CurrencyUtils.cpp b/Source/Server-Common/Server-Common/Database/Util/CurrencyUtils.cpp new file mode 100644 index 0000000..7d9d001 --- /dev/null +++ b/Source/Server-Common/Server-Common/Database/Util/CurrencyUtils.cpp @@ -0,0 +1,60 @@ +#include "CurrencyUtils.h" +#include "Server-Common/Database/DBController.h" + +#include + +#include + +namespace Database::Util::Currency +{ + void InitCurrencyTablesPreparedStatements(std::shared_ptr& dbConnection) + { + NC_LOG_INFO("Loading Prepared Statements Currency Tables..."); + + NC_LOG_INFO("Loaded Currency Tables Prepared Statements\n"); + } + + void LoadCurrencyTables(std::shared_ptr& dbConnection, Database::CurrencyTables& currencyTables) + { + NC_LOG_INFO("-- Loading Currency Tables --"); + + u64 totalRows = 0; + totalRows += LoadCurrencyTable(dbConnection, currencyTables); + + NC_LOG_INFO("-- Loaded Currency Tables ({0} Rows) --\n", totalRows); + } + + u64 LoadCurrencyTable(std::shared_ptr& dbConnection, Database::CurrencyTables& currencyTables) + { + NC_LOG_INFO("Loading Table 'currency'"); + + pqxx::nontransaction nonTransaction = dbConnection->NewNonTransaction(); + + auto result = nonTransaction.exec("SELECT COUNT(*) FROM public.currency"); + u64 numRows = result[0][0].as(); + + currencyTables.idToDefinition.clear(); + + if (numRows == 0) + { + NC_LOG_INFO("Skipped Table 'currency'"); + return 0; + } + + currencyTables.idToDefinition.reserve(numRows); + + nonTransaction.for_stream("SELECT * FROM public.currency", [¤cyTables](u16 id, const std::string& name) + { + ::Database::Currency currency = + { + .id = id, + .name = name + }; + + currencyTables.idToDefinition.insert({ id, currency }); + }); + + NC_LOG_INFO("Loading Table 'currency' ({0} Rows)", numRows); + return numRows; + } +} \ No newline at end of file diff --git a/Source/Server-Common/Server-Common/Database/Util/CurrencyUtils.h b/Source/Server-Common/Server-Common/Database/Util/CurrencyUtils.h new file mode 100644 index 0000000..4e28f94 --- /dev/null +++ b/Source/Server-Common/Server-Common/Database/Util/CurrencyUtils.h @@ -0,0 +1,17 @@ +#pragma once +#include "Server-Common/Database/Definitions.h" + +#include + +namespace Database +{ + struct DBConnection; + + namespace Util::Currency + { + void InitCurrencyTablesPreparedStatements(std::shared_ptr& dbConnection); + + void LoadCurrencyTables(std::shared_ptr& dbConnection, Database::CurrencyTables& currencyTables); + u64 LoadCurrencyTable(std::shared_ptr& dbConnection, Database::CurrencyTables& currencyTables); + } +} \ No newline at end of file diff --git a/Source/Server-Common/Server-Common/Database/Util/PermissionUtils.cpp b/Source/Server-Common/Server-Common/Database/Util/PermissionUtils.cpp new file mode 100644 index 0000000..81c3fce --- /dev/null +++ b/Source/Server-Common/Server-Common/Database/Util/PermissionUtils.cpp @@ -0,0 +1,129 @@ +#include "PermissionUtils.h" +#include "Server-Common/Database/DBController.h" + +#include + +#include + +namespace Database::Util::Permission +{ + void InitPermissionTablesPreparedStatements(std::shared_ptr& dbConnection) + { + NC_LOG_INFO("Loading Prepared Statements for Permission Tables..."); + + NC_LOG_INFO("Loaded Prepared Statements for Permission Tables\n"); + } + + void LoadPermissionTables(std::shared_ptr& dbConnection, Database::PermissionTables& permissionTables) + { + NC_LOG_INFO("-- Loading Permission Tables --"); + + u64 totalRows = 0; + totalRows += LoadPermissionsTable(dbConnection, permissionTables); + totalRows += LoadPermissionGroupsTable(dbConnection, permissionTables); + totalRows += LoadPermissionGroupDataTable(dbConnection, permissionTables); + + NC_LOG_INFO("-- Loaded Permission Tables ({0} Rows) --\n", totalRows); + } + + u64 LoadPermissionsTable(std::shared_ptr& dbConnection, Database::PermissionTables& permissionTables) + { + NC_LOG_INFO("Loading Table 'permissions'"); + + pqxx::nontransaction nonTransaction = dbConnection->NewNonTransaction(); + + auto result = nonTransaction.exec("SELECT COUNT(*) FROM public.permissions"); + u64 numRows = result[0][0].as(); + + permissionTables.idToDefinition.clear(); + + if (numRows == 0) + { + NC_LOG_INFO("Skipped Table 'permissions'"); + return 0; + } + + permissionTables.idToDefinition.reserve(numRows); + + nonTransaction.for_stream("SELECT * FROM public.permissions", [&permissionTables](u16 id, const std::string& name) + { + ::Database::Permission permission = + { + .id = id, + .name = name + }; + + permissionTables.idToDefinition.insert({ id, permission }); + }); + + NC_LOG_INFO("Loaded Table 'permissions' ({0} Rows)", numRows); + return numRows; + } + u64 LoadPermissionGroupsTable(std::shared_ptr& dbConnection, Database::PermissionTables& permissionTables) + { + NC_LOG_INFO("Loading Table 'permission_groups'"); + + pqxx::nontransaction nonTransaction = dbConnection->NewNonTransaction(); + + auto result = nonTransaction.exec("SELECT COUNT(*) FROM public.permission_groups"); + u64 numRows = result[0][0].as(); + + permissionTables.groupIDToDefinition.clear(); + + if (numRows == 0) + { + NC_LOG_INFO("Skipped Table 'permission_groups'"); + return 0; + } + + permissionTables.groupIDToDefinition.reserve(numRows); + + nonTransaction.for_stream("SELECT * FROM public.permission_groups", [&permissionTables](u16 id, const std::string& name) + { + ::Database::PermissionGroup permissionGroup = + { + .id = id, + .name = name + }; + + permissionTables.groupIDToDefinition.insert({ id, permissionGroup }); + }); + + NC_LOG_INFO("Loaded Table 'permission_groups' ({0} Rows)", numRows); + return numRows; + } + u64 LoadPermissionGroupDataTable(std::shared_ptr& dbConnection, Database::PermissionTables& permissionTables) + { + NC_LOG_INFO("Loading Table 'permission_group_data'"); + + pqxx::nontransaction nonTransaction = dbConnection->NewNonTransaction(); + + auto result = nonTransaction.exec("SELECT COUNT(*) FROM public.permission_group_data"); + u64 numRows = result[0][0].as(); + + permissionTables.groupIDToData.clear(); + + if (numRows == 0) + { + NC_LOG_INFO("Skipped Table 'permission_group_data'"); + return 0; + } + + permissionTables.groupIDToData.reserve(numRows); + + nonTransaction.for_stream("SELECT * FROM public.permission_group_data", [&permissionTables](u32 id, u16 groupID, u16 permissionID) + { + ::Database::PermissionGroupData permissionGroupData = + { + .groupID = groupID, + .permissionID = permissionID + }; + + std::vector<::Database::PermissionGroupData>& permissionGroupDatas = permissionTables.groupIDToData[groupID]; + permissionGroupDatas.push_back(permissionGroupData); + }); + + NC_LOG_INFO("Loaded Table 'permission_group_data' ({0} Rows)", numRows); + return numRows; + } +} \ No newline at end of file diff --git a/Source/Server-Common/Server-Common/Database/Util/PermissionUtils.h b/Source/Server-Common/Server-Common/Database/Util/PermissionUtils.h new file mode 100644 index 0000000..8c975fb --- /dev/null +++ b/Source/Server-Common/Server-Common/Database/Util/PermissionUtils.h @@ -0,0 +1,19 @@ +#pragma once +#include "Server-Common/Database/Definitions.h" + +#include + +namespace Database +{ + struct DBConnection; + + namespace Util::Permission + { + void InitPermissionTablesPreparedStatements(std::shared_ptr& dbConnection); + + void LoadPermissionTables(std::shared_ptr& dbConnection, Database::PermissionTables& permissionTables); + u64 LoadPermissionsTable(std::shared_ptr& dbConnection, Database::PermissionTables& permissionTables); + u64 LoadPermissionGroupsTable(std::shared_ptr& dbConnection, Database::PermissionTables& permissionTables); + u64 LoadPermissionGroupDataTable(std::shared_ptr& dbConnection, Database::PermissionTables& permissionTables); + } +} \ No newline at end of file diff --git a/Source/Server-Game/Server-Game/ECS/Components/DisplayInfo.h b/Source/Server-Game/Server-Game/ECS/Components/DisplayInfo.h index 57d1bb2..47a1c75 100644 --- a/Source/Server-Game/Server-Game/ECS/Components/DisplayInfo.h +++ b/Source/Server-Game/Server-Game/ECS/Components/DisplayInfo.h @@ -1,11 +1,16 @@ #pragma once #include +#include + namespace ECS::Components { struct DisplayInfo { public: + GameDefine::Race race = GameDefine::Race::None; + GameDefine::Gender gender = GameDefine::Gender::None; + u32 displayID; }; } \ No newline at end of file diff --git a/Source/Server-Game/Server-Game/ECS/Scheduler.cpp b/Source/Server-Game/Server-Game/ECS/Scheduler.cpp index 7a74b32..f73188f 100644 --- a/Source/Server-Game/Server-Game/ECS/Scheduler.cpp +++ b/Source/Server-Game/Server-Game/ECS/Scheduler.cpp @@ -1,6 +1,6 @@ #include "Scheduler.h" -#include "Server-Game/ECS/Components/Transform.h" +#include "Server-Game/ECS/Systems/CharacterLoginHandler.h" #include "Server-Game/ECS/Systems/DatabaseSetup.h" #include "Server-Game/ECS/Systems/NetworkConnection.h" #include "Server-Game/ECS/Systems/UpdatePower.h" @@ -20,8 +20,9 @@ namespace ECS void Scheduler::Init(entt::registry& registry) { Systems::DatabaseSetup::Init(registry); - Systems::SimpleReplication::Init(registry); Systems::NetworkConnection::Init(registry); + Systems::CharacterLoginHandler::Init(registry); + Systems::SimpleReplication::Init(registry); Systems::UpdatePower::Init(registry); Systems::UpdateSpell::Init(registry); Systems::UpdateScripts::Init(registry); @@ -32,6 +33,7 @@ namespace ECS // TODO: You know, actually scheduling stuff and multithreading (enkiTS tasks?) Systems::DatabaseSetup::Update(registry, deltaTime); Systems::NetworkConnection::Update(registry, deltaTime); + Systems::CharacterLoginHandler::Update(registry, deltaTime); Systems::UpdatePower::Update(registry, deltaTime); Systems::UpdateSpell::Update(registry, deltaTime); Systems::UpdateScripts::Update(registry, deltaTime); diff --git a/Source/Server-Game/Server-Game/ECS/Singletons/DatabaseState.h b/Source/Server-Game/Server-Game/ECS/Singletons/DatabaseState.h index d65f0d1..82edd81 100644 --- a/Source/Server-Game/Server-Game/ECS/Singletons/DatabaseState.h +++ b/Source/Server-Game/Server-Game/ECS/Singletons/DatabaseState.h @@ -1,32 +1,26 @@ #pragma once +#include "Server-Common/Database/Definitions.h" + #include #include #include -namespace Server::Database +namespace Database { class DBController; - - struct CharacterDefinition - { - u32 id = std::numeric_limits().max(); - std::string name = ""; - u16 permissionLevel = 0; - - vec3 position = vec3(0.0f); - f32 orientation = 0.0f; - }; } + namespace ECS::Singletons { struct DatabaseState { public: nlohmann::json config; - std::unique_ptr controller; + std::unique_ptr controller; - robin_hood::unordered_map characterIDToDefinition; - robin_hood::unordered_map characterNameToDefinition; + Database::PermissionTables permissionTables; + Database::CurrencyTables currencyTables; + Database::CharacterTables characterTables; }; } \ No newline at end of file diff --git a/Source/Server-Game/Server-Game/ECS/Singletons/NetworkState.h b/Source/Server-Game/Server-Game/ECS/Singletons/NetworkState.h index 5372609..84b19c9 100644 --- a/Source/Server-Game/Server-Game/ECS/Singletons/NetworkState.h +++ b/Source/Server-Game/Server-Game/ECS/Singletons/NetworkState.h @@ -14,18 +14,29 @@ namespace Network class GameMessageRouter; } -namespace ECS::Singletons +namespace ECS { - struct NetworkState + struct CharacterLoginRequest { - public: - std::unique_ptr server; - std::unique_ptr gameMessageRouter; - - robin_hood::unordered_set socketIDRequestedToClose; - robin_hood::unordered_map socketIDToCharacterID; - robin_hood::unordered_map socketIDToEntity; - robin_hood::unordered_map characterIDToSocketID; - robin_hood::unordered_map EntityToSocketID; + Network::SocketID socketID; + u32 nameHash; }; + + namespace Singletons + { + struct NetworkState + { + public: + std::unique_ptr server; + std::unique_ptr gameMessageRouter; + + robin_hood::unordered_set socketIDRequestedToClose; + robin_hood::unordered_map socketIDToCharacterID; + robin_hood::unordered_map socketIDToEntity; + robin_hood::unordered_map characterIDToSocketID; + robin_hood::unordered_map entityToSocketID; + + moodycamel::ConcurrentQueue characterLoginRequest; + }; + } } \ No newline at end of file diff --git a/Source/Server-Game/Server-Game/ECS/Systems/CharacterLoginHandler.cpp b/Source/Server-Game/Server-Game/ECS/Systems/CharacterLoginHandler.cpp new file mode 100644 index 0000000..0a6459b --- /dev/null +++ b/Source/Server-Game/Server-Game/ECS/Systems/CharacterLoginHandler.cpp @@ -0,0 +1,112 @@ +#include "CharacterLoginHandler.h" + +#include "Server-Game/ECS/Components/DisplayInfo.h" +#include "Server-Game/ECS/Components/TargetInfo.h" +#include "Server-Game/ECS/Components/Transform.h" +#include "Server-Game/ECS/Components/UnitStatsComponent.h" +#include "Server-Game/ECS/Singletons/DatabaseState.h" +#include "Server-Game/ECS/Singletons/GridSingleton.h" +#include "Server-Game/ECS/Singletons/NetworkState.h" +#include "Server-Game/ECS/Util/MessageBuilderUtil.h" +#include "Server-Game/Util/UnitUtils.h" + +#include + +#include + +#include +#include + +namespace ECS::Systems +{ + void CharacterLoginHandler::Init(entt::registry& registry) + { + } + + void CharacterLoginHandler::Update(entt::registry& registry, f32 deltaTime) + { + entt::registry::context& ctx = registry.ctx(); + Singletons::NetworkState& networkState = ctx.get(); + + u32 approxRequests = static_cast(networkState.characterLoginRequest.size_approx()); + if (approxRequests == 0) + return; + + Singletons::DatabaseState& databaseState = ctx.get(); + Singletons::GridSingleton& gridSingleton = ctx.get(); + + CharacterLoginRequest request; + while (networkState.characterLoginRequest.try_dequeue(request)) + { + Network::SocketID socketID = request.socketID; + u32 characterNameHash = request.nameHash; + u64 characterID = std::numeric_limits::max(); + + bool characterDoesNotExist = !databaseState.characterTables.nameHashToID.contains(characterNameHash); + bool alreadyConnectedToACharacter = networkState.socketIDToCharacterID.contains(socketID); + bool characterInUse = false; + + if (!characterDoesNotExist && !alreadyConnectedToACharacter) + { + characterID = databaseState.characterTables.nameHashToID[characterNameHash]; + characterInUse = networkState.characterIDToSocketID.contains(characterID); + } + + if (characterDoesNotExist || alreadyConnectedToACharacter || characterInUse) + { + std::shared_ptr buffer = Bytebuffer::Borrow<16>(); + if (Util::MessageBuilder::Authentication::BuildConnectedMessage(buffer, Network::ConnectResult::Failed)) + { + networkState.server->SendPacket(socketID, buffer); + } + + networkState.server->CloseSocketID(socketID); + continue; + } + + entt::entity socketEntity = registry.create(); + + networkState.socketIDToCharacterID[socketID] = characterID; + networkState.socketIDToEntity[socketID] = socketEntity; + networkState.characterIDToSocketID[characterID] = socketID; + networkState.entityToSocketID[socketEntity] = socketID; + + Database::CharacterDefinition& characterDefinition = databaseState.characterTables.idToDefinition[characterID]; + + Components::Transform& transform = registry.emplace(socketEntity); + transform.position = characterDefinition.position; + transform.rotation = quat(vec3(0.0f, characterDefinition.orientation, 0.0f)); + + Components::DisplayInfo& displayInfo = registry.emplace(socketEntity); + displayInfo.race = characterDefinition.GetRace(); + displayInfo.gender = characterDefinition.GetGender(); + displayInfo.displayID = UnitUtils::GetDisplayIDFromRaceGender(displayInfo.race, displayInfo.gender); + + UnitUtils::AddStatsComponent(registry, socketEntity); + + Components::TargetInfo& targetInfo = registry.emplace(socketEntity); + targetInfo.target = entt::null; + + std::shared_ptr buffer = Bytebuffer::Borrow<512>(); + + bool failed = false; + failed |= !Util::MessageBuilder::Authentication::BuildConnectedMessage(buffer, Network::ConnectResult::Success); + failed |= !Util::MessageBuilder::Unit::BuildUnitCreate(buffer, registry, socketEntity); + failed |= !Util::MessageBuilder::Entity::BuildSetMoverMessage(buffer, socketEntity); + + if (failed) + { + NC_LOG_ERROR("Failed to build character login message for characterID: {0}", characterID); + + networkState.server->CloseSocketID(socketID); + continue; + } + + gridSingleton.cell.mutex.lock(); + gridSingleton.cell.players.entering.insert(socketEntity); + gridSingleton.cell.mutex.unlock(); + + networkState.server->SendPacket(socketID, buffer); + } + } +} \ No newline at end of file diff --git a/Source/Server-Game/Server-Game/ECS/Systems/CharacterLoginHandler.h b/Source/Server-Game/Server-Game/ECS/Systems/CharacterLoginHandler.h new file mode 100644 index 0000000..bcf4cd2 --- /dev/null +++ b/Source/Server-Game/Server-Game/ECS/Systems/CharacterLoginHandler.h @@ -0,0 +1,13 @@ +#pragma once +#include +#include + +namespace ECS::Systems +{ + class CharacterLoginHandler + { + public: + static void Init(entt::registry& registry); + static void Update(entt::registry& registry, f32 deltaTime); + }; +} \ No newline at end of file diff --git a/Source/Server-Game/Server-Game/ECS/Systems/DatabaseSetup.cpp b/Source/Server-Game/Server-Game/ECS/Systems/DatabaseSetup.cpp index 252b937..559e3b5 100644 --- a/Source/Server-Game/Server-Game/ECS/Systems/DatabaseSetup.cpp +++ b/Source/Server-Game/Server-Game/ECS/Systems/DatabaseSetup.cpp @@ -3,10 +3,14 @@ #include "Server-Game/ECS/Singletons/DatabaseState.h" #include "Server-Game/Util/ServiceLocator.h" +#include +#include +#include +#include + #include #include - -#include +#include #include @@ -39,39 +43,35 @@ namespace ECS::Systems // Setup DatabaseState { - databaseState.controller = std::make_unique(); + databaseState.controller = std::make_unique(); nlohmann::json& connection = databaseState.config["Connection"]; - Server::Database::DBEntry dbEntry(connection["address"], connection["port"], connection["database"], connection["user"], connection["password"]); + Database::DBEntry dbEntry(connection["address"], connection["port"], connection["database"], connection["user"], connection["password"]); + + databaseState.controller->SetDBEntry(Database::DBType::Auth, dbEntry); + databaseState.controller->SetDBEntry(Database::DBType::Character, dbEntry); + databaseState.controller->SetDBEntry(Database::DBType::World, dbEntry); + } + + auto authConnection = databaseState.controller->GetConnection(Database::DBType::Auth); + auto characterConnection = databaseState.controller->GetConnection(Database::DBType::Character); + auto worldConnection = databaseState.controller->GetConnection(Database::DBType::World); - databaseState.controller->SetDBEntry(Server::Database::DBType::Auth, dbEntry); - databaseState.controller->SetDBEntry(Server::Database::DBType::Character, dbEntry); - databaseState.controller->SetDBEntry(Server::Database::DBType::World, dbEntry); + if (authConnection == nullptr || characterConnection == nullptr || worldConnection == nullptr) + { + NC_LOG_CRITICAL("[Database] : Failed to connect to the database"); + return; } - // Load Character Table + // Load Character Tables { + Database::Util::Permission::InitPermissionTablesPreparedStatements(characterConnection); + Database::Util::Currency::InitCurrencyTablesPreparedStatements(characterConnection); + Database::Util::Character::InitCharacterTablesPreparedStatements(characterConnection); - if (auto conn = databaseState.controller->GetConnection(Server::Database::DBType::Character)) - { - conn->connection->prepare("CreateCharacter", "INSERT INTO public.characters (name, permissionlevel) VALUES ($1, $2) RETURNING id"); - conn->connection->prepare("DeleteCharacter", "DELETE FROM public.characters WHERE id = $1"); - - for (auto& [id, name, permissionLevel, position_x, position_y, position_z, position_o] : conn->Context().query("SELECT id, name, permissionlevel, position_x, position_y, position_z, position_o FROM public.characters ORDER BY id")) - { - Server::Database::CharacterDefinition character = - { - .id = id, - .name = name, - .permissionLevel = permissionLevel, - .position = vec3(position_x, position_y, position_z), - .orientation = position_o - }; - - databaseState.characterIDToDefinition.insert({ id, character }); - databaseState.characterNameToDefinition.insert({ name, character }); - } - } + Database::Util::Permission::LoadPermissionTables(characterConnection, databaseState.permissionTables); + Database::Util::Currency::LoadCurrencyTables(characterConnection, databaseState.currencyTables); + Database::Util::Character::LoadCharacterTables(characterConnection, databaseState.characterTables); } } diff --git a/Source/Server-Game/Server-Game/ECS/Systems/NetworkConnection.cpp b/Source/Server-Game/Server-Game/ECS/Systems/NetworkConnection.cpp index 046a6b6..03476a3 100644 --- a/Source/Server-Game/Server-Game/ECS/Systems/NetworkConnection.cpp +++ b/Source/Server-Game/Server-Game/ECS/Systems/NetworkConnection.cpp @@ -36,253 +36,29 @@ namespace ECS::Systems if (!recvPacket->GetString(charName)) return false; + if (!StringUtils::StringIsAlphaAndAtLeastLength(charName, 2)) + return false; + entt::registry::context& ctx = ServiceLocator::GetEnttRegistries()->gameRegistry->ctx(); - Singletons::DatabaseState& databaseState = ctx.get(); - Singletons::GridSingleton& gridSingleton = ctx.get(); Singletons::NetworkState& networkState = ctx.get(); - u32 characterID = std::numeric_limits().max(); - - struct Result - { - u8 CharacterDoesNotExist : 1 = 0; - u8 AlreadyConnectedToACharacter : 1 = 0; - u8 CharacterInUse : 1 = 0; - u8 Unused : 5 = 0; + CharacterLoginRequest characterLoginRequest = + { + .socketID = socketID, + .nameHash = StringUtils::fnv1a_32(charName.c_str(), charName.length()) }; - Result result; - - // Check if the character exists - { - if (!databaseState.characterNameToDefinition.contains(charName)) - { - // Send back that the character does not exist - result.CharacterDoesNotExist = 1; - } - else - { - characterID = databaseState.characterNameToDefinition[charName].id; - } - } - - // Check if socketID is already connected to a character - if (!result.CharacterDoesNotExist) - { - if (networkState.socketIDToCharacterID.contains(socketID)) - { - // Send back that the socketID is already connected to a character - result.AlreadyConnectedToACharacter = 1; - } - } - - // Check if someone else is already connected to this character - if (!result.AlreadyConnectedToACharacter) - { - if (networkState.characterIDToSocketID.contains(characterID)) - { - // Send back that the character is already in use or kick current user out - result.CharacterInUse = 1; - } - } - - u8 resultAsValue = *reinterpret_cast(&result); - if (result.CharacterDoesNotExist || result.AlreadyConnectedToACharacter || result.CharacterInUse) - { - std::shared_ptr connectionMessage = Bytebuffer::Borrow<64>(); - if (!Util::MessageBuilder::Authentication::BuildConnectedMessage(connectionMessage, resultAsValue, entt::null)) - return false; - - networkState.server->SendPacket(socketID, connectionMessage); - return true; - } - - entt::registry* registry = ServiceLocator::GetEnttRegistries()->gameRegistry; - entt::entity entity = registry->create(); - - // Setup network state for the character, and send back confirmation - networkState.socketIDToCharacterID[socketID] = characterID; - networkState.characterIDToSocketID[characterID] = socketID; - - networkState.socketIDToEntity[socketID] = entity; - networkState.EntityToSocketID[entity] = socketID; - - // Add To Grid - { - gridSingleton.cell.mutex.lock(); - gridSingleton.cell.players.entering.insert(entity); - gridSingleton.cell.mutex.unlock(); - } - - { - std::shared_ptr connectionMessage = Bytebuffer::Borrow<64>(); - if (!Util::MessageBuilder::Authentication::BuildConnectedMessage(connectionMessage, resultAsValue, entity, &charName)) - return false; - - std::shared_ptr unitStatsMessage = Bytebuffer::Borrow<256>(); - Components::UnitStatsComponent& unitStatsComponent = UnitUtils::AddStatsComponent(*registry, entity); - if (!Util::MessageBuilder::Entity::BuildUnitStatsMessage(unitStatsMessage, entity, unitStatsComponent)) - return false; - - Components::TargetInfo& targetInfo = registry->emplace(entity); - targetInfo.target = entt::null; - - registry->emplace(entity); - auto& displayInfo = registry->emplace(entity); - displayInfo.displayID = 50; - - networkState.server->SendPacket(socketID, connectionMessage); - ECS::Util::Grid::SendToGrid(entity, unitStatsMessage, ECS::Singletons::GridUpdateFlag{ .SendToSelf = true }); - } - + networkState.characterLoginRequest.enqueue(characterLoginRequest); return true; } - bool HandleOnEntityMove(Network::SocketID socketID, std::shared_ptr& recvPacket) - { - vec3 position = vec3(0.0f); - quat rotation = quat(1.0f, 0.0f, 0.0f, 0.0f); - Components::MovementFlags movementFlags = {}; - f32 verticalVelocity = 0.0f; - - if (!recvPacket->Get(position)) - return false; - - if (!recvPacket->Get(rotation)) - return false; - - if (!recvPacket->Get(movementFlags)) - return false; - - if (!recvPacket->Get(verticalVelocity)) - return false; - - entt::registry* registry = ServiceLocator::GetEnttRegistries()->gameRegistry; - Singletons::NetworkState& networkState = registry->ctx().get(); - - if (!networkState.socketIDToEntity.contains(socketID)) - return false; - - entt::entity socketEntity = networkState.socketIDToEntity[socketID]; - Components::Transform& transform = registry->get(socketEntity); - transform.position = position; - transform.rotation = rotation; - - std::shared_ptr entityMoveMessage = Bytebuffer::Borrow<64>(); - if (!Util::MessageBuilder::Entity::BuildEntityMoveMessage(entityMoveMessage, socketEntity, position, rotation, movementFlags, verticalVelocity)) - return false; - - ECS::Util::Grid::SendToGrid(socketEntity, entityMoveMessage); - return true; - } - - bool HandleOnEntityTargetUpdate(Network::SocketID socketID, std::shared_ptr& recvPacket) + bool HandleOnCheatDamage(Network::SocketID socketID, entt::entity socketEntity, std::shared_ptr& recvPacket) { - entt::entity targetEntity = entt::null; - - if (!recvPacket->Get(targetEntity)) + u32 damage = 0.0f; + if (!recvPacket->GetU32(damage)) return false; entt::registry* registry = ServiceLocator::GetEnttRegistries()->gameRegistry; - Singletons::NetworkState& networkState = registry->ctx().get(); - - if (!networkState.socketIDToEntity.contains(socketID)) - return false; - - entt::entity socketEntity = networkState.socketIDToEntity[socketID]; - - Components::TargetInfo& targetInfo = registry->get(socketEntity); - targetInfo.target = targetEntity; - - std::shared_ptr targetUpdateMessage = Bytebuffer::Borrow<64>(); - if (!Util::MessageBuilder::Entity::BuildEntityTargetUpdateMessage(targetUpdateMessage, socketEntity, targetEntity)) - return false; - - ECS::Util::Grid::SendToGrid(socketEntity, targetUpdateMessage); - - return true; - } - - bool HandleOnRequestSpellCast(Network::SocketID socketID, std::shared_ptr& recvPacket) - { - u32 spellID = 0; - - if (!recvPacket->GetU32(spellID)) - return false; - - entt::registry* registry = ServiceLocator::GetEnttRegistries()->gameRegistry; - Singletons::NetworkState& networkState = registry->ctx().get(); - - if (!networkState.socketIDToEntity.contains(socketID)) - return false; - - entt::entity socketEntity = networkState.socketIDToEntity[socketID]; - if (!registry->valid(socketEntity)) - return false; - - u8 result = 0; - Components::TargetInfo* targetInfo = registry->try_get(socketEntity); - - if (registry->all_of(socketEntity)) - { - result = 0x1; - } - else if (!targetInfo || !registry->valid(targetInfo->target)) - { - result = 0x2; - } - - if (result != 0x0) - { - std::shared_ptr castResultMessage = Bytebuffer::Borrow<64>(); - if (!Util::MessageBuilder::Spell::BuildSpellCastResultMessage(castResultMessage, socketEntity, result, 0.0f, 0.0f)) - return false; - - networkState.server->SendPacket(socketID, castResultMessage); - return true; - } - - Components::CastInfo& castInfo = registry->emplace(socketEntity); - - castInfo.target = targetInfo->target; - castInfo.castTime = 1.5f; - castInfo.duration = 0.0f; - - std::shared_ptr castResultMessage = Bytebuffer::Borrow<64>(); - if (!Util::MessageBuilder::Spell::BuildSpellCastResultMessage(castResultMessage, socketEntity, result, castInfo.castTime, castInfo.duration)) - return false; - - networkState.server->SendPacket(socketID, castResultMessage); - - // Send Grid Message - { - std::shared_ptr entityCastSpellMessage = Bytebuffer::Borrow<64>(); - if (!Util::MessageBuilder::Entity::BuildEntitySpellCastMessage(entityCastSpellMessage, socketEntity, castInfo.castTime, castInfo.duration)) - return false; - - ECS::Util::Grid::SendToGrid(socketEntity, entityCastSpellMessage); - } - - return true; - } - - bool HandleOnCheatDamage(Network::SocketID socketID, std::shared_ptr& recvPacket) - { - f32 damage = 0.0f; - - if (!recvPacket->GetF32(damage)) - return false; - - entt::registry* registry = ServiceLocator::GetEnttRegistries()->gameRegistry; - Singletons::NetworkState& networkState = registry->ctx().get(); - - if (!networkState.socketIDToEntity.contains(socketID)) - return false; - - entt::entity socketEntity = networkState.socketIDToEntity[socketID]; - if (!registry->valid(socketEntity)) - return false; - entt::entity targetEntity = socketEntity; if (auto* targetInfo = registry->try_get(socketEntity)) { @@ -297,7 +73,7 @@ namespace ECS::Systems if (unitStatsComponent->currentHealth <= 0) return true; - f32 damageToDeal = glm::min(damage, unitStatsComponent->currentHealth); + f32 damageToDeal = glm::min(static_cast(damage), unitStatsComponent->currentHealth); unitStatsComponent->currentHealth -= damageToDeal; unitStatsComponent->healthIsDirty = true; @@ -314,18 +90,9 @@ namespace ECS::Systems return true; } - - bool HandleOnCheatKill(Network::SocketID socketID, std::shared_ptr& recvPacket) + bool HandleOnCheatKill(Network::SocketID socketID, entt::entity socketEntity, std::shared_ptr& recvPacket) { entt::registry* registry = ServiceLocator::GetEnttRegistries()->gameRegistry; - Singletons::NetworkState& networkState = registry->ctx().get(); - - if (!networkState.socketIDToEntity.contains(socketID)) - return false; - - entt::entity socketEntity = networkState.socketIDToEntity[socketID]; - if (!registry->valid(socketEntity)) - return false; entt::entity targetEntity = socketEntity; if (auto* targetInfo = registry->try_get(socketEntity)) @@ -358,18 +125,9 @@ namespace ECS::Systems return true; } - - bool HandleOnCheatResurrect(Network::SocketID socketID, std::shared_ptr& recvPacket) + bool HandleOnCheatResurrect(Network::SocketID socketID, entt::entity socketEntity, std::shared_ptr& recvPacket) { entt::registry* registry = ServiceLocator::GetEnttRegistries()->gameRegistry; - Singletons::NetworkState& networkState = registry->ctx().get(); - - if (!networkState.socketIDToEntity.contains(socketID)) - return false; - - entt::entity socketEntity = networkState.socketIDToEntity[socketID]; - if (!registry->valid(socketEntity)) - return false; entt::entity targetEntity = socketEntity; if (auto* targetInfo = registry->try_get(socketEntity)) @@ -397,23 +155,13 @@ namespace ECS::Systems return true; } - - bool HandleOnCheatMorph(Network::SocketID socketID, std::shared_ptr& recvPacket) + bool HandleOnCheatMorph(Network::SocketID socketID, entt::entity socketEntity, std::shared_ptr& recvPacket) { u32 displayID = 0; - if (!recvPacket->GetU32(displayID)) return false; entt::registry* registry = ServiceLocator::GetEnttRegistries()->gameRegistry; - Singletons::NetworkState& networkState = registry->ctx().get(); - - if (!networkState.socketIDToEntity.contains(socketID)) - return false; - - entt::entity socketEntity = networkState.socketIDToEntity[socketID]; - if (!registry->valid(socketEntity)) - return false; auto& displayInfo = registry->get(socketEntity); displayInfo.displayID = displayID; @@ -426,12 +174,28 @@ namespace ECS::Systems return true; } + bool HandleOnCheatDemorph(Network::SocketID socketID, entt::entity socketEntity, std::shared_ptr& recvPacket) + { + entt::registry* registry = ServiceLocator::GetEnttRegistries()->gameRegistry; - bool HandleOnCheatCreateCharacter(Network::SocketID socketID, std::shared_ptr& recvPacket) + auto& displayInfo = registry->get(socketEntity); + + u32 originalDisplayID = displayInfo.displayID; + displayInfo.displayID = UnitUtils::GetDisplayIDFromRaceGender(displayInfo.race, displayInfo.gender); + + if (originalDisplayID == displayInfo.displayID) + return true; + + std::shared_ptr displayInfoUpdateMessage = Bytebuffer::Borrow<64>(); + if (!Util::MessageBuilder::Entity::BuildEntityDisplayInfoUpdateMessage(displayInfoUpdateMessage, socketEntity, displayInfo.displayID)) + return false; + + ECS::Util::Grid::SendToGrid(socketEntity, displayInfoUpdateMessage, { .SendToSelf = 1 }); + return true; + } + bool HandleOnCheatCreateCharacter(Network::SocketID socketID, entt::entity socketEntity, std::shared_ptr& recvPacket) { std::string charName = ""; - u16 permissionlevel = 0; - if (!recvPacket->GetString(charName)) return false; @@ -439,16 +203,13 @@ namespace ECS::Systems Singletons::DatabaseState& databaseState = ctx.get(); Singletons::NetworkState& networkState = ctx.get(); - if (!networkState.socketIDToCharacterID.contains(socketID)) - return false; - - u32 characterID = networkState.socketIDToCharacterID[socketID]; - if (!databaseState.characterIDToDefinition.contains(characterID)) + u64 characterID = networkState.socketIDToCharacterID[socketID]; + if (!databaseState.characterTables.idToDefinition.contains(characterID)) return false; - auto& socketCharacterDefinition = databaseState.characterIDToDefinition[characterID]; - if (socketCharacterDefinition.permissionLevel <= 3) - return false; + auto& socketCharacterDefinition = databaseState.characterTables.idToDefinition[characterID]; + //if (socketCharacterDefinition.permissionLevel <= 3) + // return false; struct Result { @@ -459,12 +220,12 @@ namespace ECS::Systems }; Result result; - + u32 charNameHash = StringUtils::fnv1a_32(charName.c_str(), charName.length()); if (!StringUtils::StringIsAlphaAndAtLeastLength(charName, 2)) { result.NameIsInvalid = 1; } - else if (databaseState.characterNameToDefinition.contains(charName)) + else if (databaseState.characterTables.nameHashToID.contains(charNameHash)) { result.CharacterAlreadyExists = 1; } @@ -473,7 +234,7 @@ namespace ECS::Systems if (resultAsValue != 0) { std::shared_ptr characterCreateResultMessage = Bytebuffer::Borrow<64>(); - if (!Util::MessageBuilder::Cheat::BuildCharacterCreateResultMessage(characterCreateResultMessage, charName, resultAsValue)) + if (!Util::MessageBuilder::Cheat::BuildCheatCreateCharacterResponse(characterCreateResultMessage, resultAsValue)) return false; networkState.server->SendPacket(socketID, characterCreateResultMessage); @@ -484,24 +245,24 @@ namespace ECS::Systems { Singletons::DatabaseState& databaseState = ctx.get(); - if (auto conn = databaseState.controller->GetConnection(Server::Database::DBType::Character)) + if (auto conn = databaseState.controller->GetConnection(Database::DBType::Character)) { - auto context = conn->Context(); - auto queryResult = context.exec_prepared("CreateCharacter", charName, permissionlevel); + auto transaction = conn->NewTransaction(); + auto queryResult = transaction.exec_prepared("CreateCharacter", charName, 1); if (queryResult.empty()) { result.DatabaseTransactionFailed = true; - context.abort(); + transaction.abort(); } else { u32 characterID = queryResult[0][0].as(); - Server::Database::CharacterDefinition characterDefinition = { .id = characterID, .name = charName, .permissionLevel = permissionlevel }; + Database::CharacterDefinition characterDefinition = { .id = characterID, .name = charName, .raceGenderClass = 1 }; - databaseState.characterIDToDefinition[characterID] = characterDefinition; - databaseState.characterNameToDefinition[charName] = characterDefinition; + databaseState.characterTables.idToDefinition[characterID] = characterDefinition; + databaseState.characterTables.nameHashToID[charNameHash] = characterID; - context.commit(); + transaction.commit(); } } else @@ -512,17 +273,15 @@ namespace ECS::Systems // Send Packet std::shared_ptr characterCreateResultMessage = Bytebuffer::Borrow<64>(); - if (!Util::MessageBuilder::Cheat::BuildCharacterCreateResultMessage(characterCreateResultMessage, charName, resultAsValue)) + if (!Util::MessageBuilder::Cheat::BuildCheatCreateCharacterResponse(characterCreateResultMessage, resultAsValue)) return false; networkState.server->SendPacket(socketID, characterCreateResultMessage); return true; } - - bool HandleOnCheatDeleteCharacter(Network::SocketID socketID, std::shared_ptr& recvPacket) + bool HandleOnCheatDeleteCharacter(Network::SocketID socketID, entt::entity socketEntity, std::shared_ptr& recvPacket) { std::string charName = ""; - if (!recvPacket->GetString(charName)) return false; @@ -530,16 +289,13 @@ namespace ECS::Systems Singletons::DatabaseState& databaseState = ctx.get(); Singletons::NetworkState& networkState = ctx.get(); - if (!networkState.socketIDToCharacterID.contains(socketID)) - return false; - - u32 characterID = networkState.socketIDToCharacterID[socketID]; - if (!databaseState.characterIDToDefinition.contains(characterID)) + u64 characterID = networkState.socketIDToCharacterID[socketID]; + if (!databaseState.characterTables.idToDefinition.contains(characterID)) return false; - auto& socketCharacterDefinition = databaseState.characterIDToDefinition[characterID]; - if (socketCharacterDefinition.permissionLevel <= 3) - return false; + auto& socketCharacterDefinition = databaseState.characterTables.idToDefinition[characterID]; + //if (socketCharacterDefinition.permissionLevel <= 3) + // return false; struct Result { @@ -550,7 +306,8 @@ namespace ECS::Systems }; Result result; - if (!StringUtils::StringIsAlphaAndAtLeastLength(charName, 2) || !databaseState.characterNameToDefinition.contains(charName)) + u32 charNameHash = StringUtils::fnv1a_32(charName.c_str(), charName.length()); + if (!StringUtils::StringIsAlphaAndAtLeastLength(charName, 2) || !databaseState.characterTables.nameHashToID.contains(charNameHash)) { // Send back that the character does not exist result.CharacterDoesNotExist = 1; @@ -559,7 +316,7 @@ namespace ECS::Systems u8 resultAsValue = *reinterpret_cast(&result); std::shared_ptr characterDeleteResultMessage = Bytebuffer::Borrow<64>(); - if (!Util::MessageBuilder::Cheat::BuildCharacterDeleteResultMessage(characterDeleteResultMessage, charName, resultAsValue)) + if (!Util::MessageBuilder::Cheat::BuildCheatDeleteCharacterResponse(characterDeleteResultMessage, resultAsValue)) return false; networkState.server->SendPacket(socketID, characterDeleteResultMessage); @@ -567,22 +324,23 @@ namespace ECS::Systems } // Disconnect Character if online - auto& characterDefinition = databaseState.characterNameToDefinition[charName]; - - if (characterDefinition.permissionLevel >= socketCharacterDefinition.permissionLevel) - { - result.InsufficientPermission = 1; - - // Send Packet with Result - u8 resultAsValue = *reinterpret_cast(&result); - - std::shared_ptr characterDeleteResultMessage = Bytebuffer::Borrow<64>(); - if (!Util::MessageBuilder::Cheat::BuildCharacterDeleteResultMessage(characterDeleteResultMessage, charName, resultAsValue)) - return false; - - networkState.server->SendPacket(socketID, characterDeleteResultMessage); - return true; - } + u64 deleteCharacterID = databaseState.characterTables.nameHashToID[charNameHash]; + auto& characterDefinition = databaseState.characterTables.idToDefinition[deleteCharacterID]; + + //if (characterDefinition.permissionLevel >= socketCharacterDefinition.permissionLevel) + //{ + // result.InsufficientPermission = 1; + // + // // Send Packet with Result + // u8 resultAsValue = *reinterpret_cast(&result); + // + // std::shared_ptr characterDeleteResultMessage = Bytebuffer::Borrow<64>(); + // if (!Util::MessageBuilder::Cheat::BuildCharacterDeleteResultMessage(characterDeleteResultMessage, charName, resultAsValue)) + // return false; + // + // networkState.server->SendPacket(socketID, characterDeleteResultMessage); + // return true; + //} if (networkState.characterIDToSocketID.contains(characterDefinition.id)) { @@ -594,22 +352,22 @@ namespace ECS::Systems { Singletons::DatabaseState& databaseState = ctx.get(); - if (auto conn = databaseState.controller->GetConnection(Server::Database::DBType::Character)) + if (auto conn = databaseState.controller->GetConnection(Database::DBType::Character)) { - auto context = conn->Context(); - auto queryResult = context.exec_prepared("DeleteCharacter", characterDefinition.id); + auto transaction = conn->NewTransaction(); + auto queryResult = transaction.exec_prepared("DeleteCharacter", characterDefinition.id); if (queryResult.affected_rows() == 0) { result.DatabaseTransactionFailed = true; - context.abort(); + transaction.abort(); } else { - databaseState.characterIDToDefinition.erase(databaseState.characterNameToDefinition[charName].id); - databaseState.characterNameToDefinition.erase(charName); + databaseState.characterTables.idToDefinition.erase(characterDefinition.id); + databaseState.characterTables.nameHashToID.erase(charNameHash); - context.commit(); + transaction.commit(); } } else @@ -622,12 +380,198 @@ namespace ECS::Systems u8 resultAsValue = *reinterpret_cast(&result); std::shared_ptr characterDeleteResultMessage = Bytebuffer::Borrow<64>(); - if (!Util::MessageBuilder::Cheat::BuildCharacterDeleteResultMessage(characterDeleteResultMessage, charName, resultAsValue)) + if (!Util::MessageBuilder::Cheat::BuildCheatDeleteCharacterResponse(characterDeleteResultMessage, resultAsValue)) return false; networkState.server->SendPacket(socketID, characterDeleteResultMessage); return true; } + bool HandleOnSendCheatCommand(Network::SocketID socketID, std::shared_ptr& recvPacket) + { + entt::registry* registry = ServiceLocator::GetEnttRegistries()->gameRegistry; + Singletons::NetworkState& networkState = registry->ctx().get(); + + if (!networkState.socketIDToEntity.contains(socketID)) + return false; + + entt::entity socketEntity = networkState.socketIDToEntity[socketID]; + if (!registry->valid(socketEntity)) + return false; + + Network::CheatCommands command = Network::CheatCommands::None; + if (!recvPacket->Get(command)) + return false; + + switch (command) + { + case Network::CheatCommands::Damage: + { + return HandleOnCheatDamage(socketID, socketEntity, recvPacket); + } + + case Network::CheatCommands::Kill: + { + return HandleOnCheatKill(socketID, socketEntity, recvPacket); + } + + case Network::CheatCommands::Resurrect: + { + return HandleOnCheatResurrect(socketID, socketEntity, recvPacket); + } + + case Network::CheatCommands::Morph: + { + return HandleOnCheatMorph(socketID, socketEntity, recvPacket); + } + + case Network::CheatCommands::Demorph: + { + return HandleOnCheatDemorph(socketID, socketEntity, recvPacket); + } + + case Network::CheatCommands::CreateCharacter: + { + return HandleOnCheatCreateCharacter(socketID, socketEntity, recvPacket); + } + + case Network::CheatCommands::DeleteCharacter: + { + return HandleOnCheatDeleteCharacter(socketID, socketEntity, recvPacket); + } + + default: break; + } + + return true; + } + + bool HandleOnEntityMove(Network::SocketID socketID, std::shared_ptr& recvPacket) + { + vec3 position = vec3(0.0f); + quat rotation = quat(1.0f, 0.0f, 0.0f, 0.0f); + Components::MovementFlags movementFlags = {}; + f32 verticalVelocity = 0.0f; + + if (!recvPacket->Get(position)) + return false; + + if (!recvPacket->Get(rotation)) + return false; + + if (!recvPacket->Get(movementFlags)) + return false; + + if (!recvPacket->Get(verticalVelocity)) + return false; + + entt::registry* registry = ServiceLocator::GetEnttRegistries()->gameRegistry; + Singletons::NetworkState& networkState = registry->ctx().get(); + + if (!networkState.socketIDToEntity.contains(socketID)) + return false; + + entt::entity socketEntity = networkState.socketIDToEntity[socketID]; + Components::Transform& transform = registry->get(socketEntity); + + transform.position = position; + transform.rotation = rotation; + + std::shared_ptr entityMoveMessage = Bytebuffer::Borrow<64>(); + if (!Util::MessageBuilder::Entity::BuildEntityMoveMessage(entityMoveMessage, socketEntity, position, rotation, movementFlags, verticalVelocity)) + return false; + + ECS::Util::Grid::SendToGrid(socketEntity, entityMoveMessage); + return true; + } + bool HandleOnEntityTargetUpdate(Network::SocketID socketID, std::shared_ptr& recvPacket) + { + entt::entity targetEntity = entt::null; + + if (!recvPacket->Get(targetEntity)) + return false; + + entt::registry* registry = ServiceLocator::GetEnttRegistries()->gameRegistry; + Singletons::NetworkState& networkState = registry->ctx().get(); + + if (!networkState.socketIDToEntity.contains(socketID)) + return false; + + entt::entity socketEntity = networkState.socketIDToEntity[socketID]; + + Components::TargetInfo& targetInfo = registry->get(socketEntity); + targetInfo.target = targetEntity; + + std::shared_ptr targetUpdateMessage = Bytebuffer::Borrow<64>(); + if (!Util::MessageBuilder::Entity::BuildEntityTargetUpdateMessage(targetUpdateMessage, socketEntity, targetEntity)) + return false; + + ECS::Util::Grid::SendToGrid(socketEntity, targetUpdateMessage); + + return true; + } + + bool HandleOnRequestSpellCast(Network::SocketID socketID, std::shared_ptr& recvPacket) + { + u32 spellID = 0; + + if (!recvPacket->GetU32(spellID)) + return false; + + entt::registry* registry = ServiceLocator::GetEnttRegistries()->gameRegistry; + Singletons::NetworkState& networkState = registry->ctx().get(); + + if (!networkState.socketIDToEntity.contains(socketID)) + return false; + + entt::entity socketEntity = networkState.socketIDToEntity[socketID]; + if (!registry->valid(socketEntity)) + return false; + + u8 result = 0; + Components::TargetInfo* targetInfo = registry->try_get(socketEntity); + + if (registry->all_of(socketEntity)) + { + result = 0x1; + } + else if (!targetInfo || !registry->valid(targetInfo->target)) + { + result = 0x2; + } + + if (result != 0x0) + { + std::shared_ptr castResultMessage = Bytebuffer::Borrow<64>(); + if (!Util::MessageBuilder::Spell::BuildSpellCastResultMessage(castResultMessage, socketEntity, result, 0.0f, 0.0f)) + return false; + + networkState.server->SendPacket(socketID, castResultMessage); + return true; + } + + Components::CastInfo& castInfo = registry->emplace(socketEntity); + + castInfo.target = targetInfo->target; + castInfo.castTime = 1.5f; + castInfo.duration = 0.0f; + + std::shared_ptr castResultMessage = Bytebuffer::Borrow<64>(); + if (!Util::MessageBuilder::Spell::BuildSpellCastResultMessage(castResultMessage, socketEntity, result, castInfo.castTime, castInfo.duration)) + return false; + + networkState.server->SendPacket(socketID, castResultMessage); + + // Send Grid Message + { + std::shared_ptr entityCastSpellMessage = Bytebuffer::Borrow<64>(); + if (!Util::MessageBuilder::Entity::BuildEntitySpellCastMessage(entityCastSpellMessage, socketEntity, castInfo.castTime, castInfo.duration)) + return false; + + ECS::Util::Grid::SendToGrid(socketEntity, entityCastSpellMessage); + } + + return true; + } void NetworkConnection::Init(entt::registry& registry) { @@ -640,16 +584,14 @@ namespace ECS::Systems networkState.server = std::make_unique(); networkState.gameMessageRouter = std::make_unique(); - networkState.gameMessageRouter->SetMessageHandler(Network::GameOpcode::Client_Connect, Network::GameMessageHandler(Network::ConnectionStatus::None, 3u, 11u, &HandleOnConnected)); - networkState.gameMessageRouter->SetMessageHandler(Network::GameOpcode::Shared_EntityMove, Network::GameMessageHandler(Network::ConnectionStatus::Connected, 36u, &HandleOnEntityMove)); - networkState.gameMessageRouter->SetMessageHandler(Network::GameOpcode::Shared_EntityTargetUpdate, Network::GameMessageHandler(Network::ConnectionStatus::Connected, 4u, &HandleOnEntityTargetUpdate)); - networkState.gameMessageRouter->SetMessageHandler(Network::GameOpcode::Client_LocalRequestSpellCast, Network::GameMessageHandler(Network::ConnectionStatus::Connected, 4u, &HandleOnRequestSpellCast)); - //networkState.gameMessageRouter->SetMessageHandler(Network::GameOpcode::Client_SendCheatCommand, Network::GameMessageHandler(Network::ConnectionStatus::Connected, 4u, &HandleOnCheatDamage)); - //networkState.gameMessageRouter->SetMessageHandler(Network::GameOpcode::Client_SendCheatCommand, Network::GameMessageHandler(Network::ConnectionStatus::Connected, 0u, &HandleOnCheatKill)); - //networkState.gameMessageRouter->SetMessageHandler(Network::GameOpcode::Client_SendCheatCommand, Network::GameMessageHandler(Network::ConnectionStatus::Connected, 0u, &HandleOnCheatResurrect)); - //networkState.gameMessageRouter->SetMessageHandler(Network::GameOpcode::Client_SendCheatCommand, Network::GameMessageHandler(Network::ConnectionStatus::Connected, 4u, &HandleOnCheatMorph)); - //networkState.gameMessageRouter->SetMessageHandler(Network::GameOpcode::Client_SendCheatCommand, Network::GameMessageHandler(Network::ConnectionStatus::Connected, 3u, 11u, &HandleOnCheatCreateCharacter)); - //networkState.gameMessageRouter->SetMessageHandler(Network::GameOpcode::Client_SendCheatCommand, Network::GameMessageHandler(Network::ConnectionStatus::Connected, 3u, 11u, &HandleOnCheatDeleteCharacter)); + networkState.gameMessageRouter->SetMessageHandler(Network::GameOpcode::Client_Connect, Network::GameMessageHandler(Network::ConnectionStatus::None, 0u, -1, &HandleOnConnected)); + + networkState.gameMessageRouter->SetMessageHandler(Network::GameOpcode::Client_SendCheatCommand, Network::GameMessageHandler(Network::ConnectionStatus::Connected, 0u, -1, &HandleOnSendCheatCommand)); + + networkState.gameMessageRouter->SetMessageHandler(Network::GameOpcode::Shared_EntityMove, Network::GameMessageHandler(Network::ConnectionStatus::Connected, 0u, -1, &HandleOnEntityMove)); + networkState.gameMessageRouter->SetMessageHandler(Network::GameOpcode::Shared_EntityTargetUpdate, Network::GameMessageHandler(Network::ConnectionStatus::Connected, 0u, -1, &HandleOnEntityTargetUpdate)); + + networkState.gameMessageRouter->SetMessageHandler(Network::GameOpcode::Client_LocalRequestSpellCast, Network::GameMessageHandler(Network::ConnectionStatus::Connected, 0u, -1, &HandleOnRequestSpellCast)); // Bind to IP/Port std::string ipAddress = "0.0.0.0"; @@ -701,7 +643,7 @@ namespace ECS::Systems { if (networkState.socketIDToCharacterID.contains(disconnectedEvent.socketID)) { - u32 characterID = networkState.socketIDToCharacterID[disconnectedEvent.socketID]; + u64 characterID = networkState.socketIDToCharacterID[disconnectedEvent.socketID]; if (networkState.characterIDToSocketID.contains(characterID)) { @@ -722,9 +664,9 @@ namespace ECS::Systems gridSingleton.cell.mutex.unlock(); } - if (networkState.EntityToSocketID.contains(entity)) + if (networkState.entityToSocketID.contains(entity)) { - networkState.EntityToSocketID.erase(entity); + networkState.entityToSocketID.erase(entity); } networkState.socketIDToEntity.erase(disconnectedEvent.socketID); diff --git a/Source/Server-Game/Server-Game/ECS/Systems/SimpleReplication.cpp b/Source/Server-Game/Server-Game/ECS/Systems/SimpleReplication.cpp index fe8eb4a..b80b89d 100644 --- a/Source/Server-Game/Server-Game/ECS/Systems/SimpleReplication.cpp +++ b/Source/Server-Game/Server-Game/ECS/Systems/SimpleReplication.cpp @@ -66,7 +66,7 @@ namespace ECS::Systems // Send Destroy Message to all players in the cell for (entt::entity entity : gridSingleton.cell.players.list) { - Network::SocketID socketID = networkState.EntityToSocketID[entity]; + Network::SocketID socketID = networkState.entityToSocketID[entity]; for (Singletons::GridUpdate& update : updates) { @@ -100,11 +100,9 @@ namespace ECS::Systems if (!registry.valid(entity)) continue; - auto& transform = registry.get(entity); - auto& displayInfo = registry.get(entity); + std::shared_ptr buffer = Bytebuffer::Borrow<512>(); - std::shared_ptr buffer = Bytebuffer::Borrow<64>(); - if (!Util::MessageBuilder::Entity::BuildEntityCreateMessage(buffer, entity, transform, displayInfo.displayID)) + if (!Util::MessageBuilder::Unit::BuildUnitCreate(buffer, registry, entity)) continue; listUpdates.push_back({ entity, {}, std::move(buffer) }); @@ -117,14 +115,11 @@ namespace ECS::Systems if (!registry.valid(entity)) continue; - if (!networkState.EntityToSocketID.contains(entity)) + if (!networkState.entityToSocketID.contains(entity)) continue; - Components::Transform& transform = registry.get(entity); - auto& displayInfo = registry.get(entity); - - std::shared_ptr buffer = Bytebuffer::Borrow<64>(); - if (!Util::MessageBuilder::Entity::BuildEntityCreateMessage(buffer, entity, transform, displayInfo.displayID)) + std::shared_ptr buffer = Bytebuffer::Borrow<512>(); + if (!Util::MessageBuilder::Unit::BuildUnitCreate(buffer, registry, entity)) continue; enterUpdates.push_back({ entity, {}, std::move(buffer) }); @@ -135,7 +130,7 @@ namespace ECS::Systems // Send Create Messages to all players in the cell for (entt::entity entity : gridSingleton.cell.players.list) { - Network::SocketID socketID = networkState.EntityToSocketID[entity]; + Network::SocketID socketID = networkState.entityToSocketID[entity]; bool justEntered = gridSingleton.cell.players.entering.contains(entity); if (justEntered) @@ -174,7 +169,7 @@ namespace ECS::Systems if (shouldSkip) continue; - Network::SocketID socketID = networkState.EntityToSocketID[entity]; + Network::SocketID socketID = networkState.entityToSocketID[entity]; networkState.server->SendPacket(socketID, update.buffer); } diff --git a/Source/Server-Game/Server-Game/ECS/Systems/UpdatePower.cpp b/Source/Server-Game/Server-Game/ECS/Systems/UpdatePower.cpp index d1bcca8..cbda46f 100644 --- a/Source/Server-Game/Server-Game/ECS/Systems/UpdatePower.cpp +++ b/Source/Server-Game/Server-Game/ECS/Systems/UpdatePower.cpp @@ -30,7 +30,7 @@ namespace ECS::Systems static constexpr f32 healthGainRate = 5.0f; static constexpr f32 powerGainRate = 25.0f; - if (!networkState.EntityToSocketID.contains(entity)) + if (!networkState.entityToSocketID.contains(entity)) return; bool isUnitStatsDirty = false; diff --git a/Source/Server-Game/Server-Game/ECS/Util/MessageBuilderUtil.cpp b/Source/Server-Game/Server-Game/ECS/Util/MessageBuilderUtil.cpp index 1fa6315..029e961 100644 --- a/Source/Server-Game/Server-Game/ECS/Util/MessageBuilderUtil.cpp +++ b/Source/Server-Game/Server-Game/ECS/Util/MessageBuilderUtil.cpp @@ -1,5 +1,6 @@ #include "MessageBuilderUtil.h" #include "Server-Game/ECS/Components/CombatLog.h" +#include "Server-Game/ECS/Components/DisplayInfo.h" #include "Server-Game/ECS/Components/UnitStatsComponent.h" #include @@ -38,7 +39,7 @@ namespace ECS::Util::MessageBuilder return true; } - bool CreatePacket(std::shared_ptr& buffer, Network::GameOpcode opcode, std::function func) + bool CreatePacket(std::shared_ptr& buffer, Network::GameOpcode opcode, std::function&& func) { if (!buffer) return false; @@ -55,52 +56,11 @@ namespace ECS::Util::MessageBuilder namespace Authentication { - bool BuildConnectedMessage(std::shared_ptr& buffer, u8 result, entt::entity entity, const std::string* resultString) + bool BuildConnectedMessage(std::shared_ptr& buffer, Network::ConnectResult result) { - static const std::string EmptyStr = ""; - static const std::string CharacterDoesNotExist = "Character does not exist"; - static const std::string AlreadyConnectedToACharacter = "Already connected to a character"; - static const std::string CharacterInUse = "Character is in use"; - - if (!resultString) - resultString = &EmptyStr; - - switch (result) - { - case 0: break; - - default: - { - switch (result) - { - case 0x1: - { - resultString = &CharacterDoesNotExist; - break; - } - - case 0x2: - { - resultString = &AlreadyConnectedToACharacter; - break; - } - - case 0x4: - { - resultString = &CharacterInUse; - break; - } - } - - break; - } - } - - bool createPacketResult = CreatePacket(buffer, Network::GameOpcode::Server_Connected, [&]() + bool createPacketResult = CreatePacket(buffer, Network::GameOpcode::Server_Connected, [&buffer, result]() { - buffer->PutU8(result); - buffer->Put(entity); - buffer->PutString(*resultString); + buffer->Put(result); }); return createPacketResult; @@ -109,25 +69,33 @@ namespace ECS::Util::MessageBuilder namespace Entity { - bool BuildEntityMoveMessage(std::shared_ptr& buffer, entt::entity entity, const vec3& position, const quat& rotation, const Components::MovementFlags& movementFlags, f32 verticalVelocity) + bool BuildEntityMoveMessage(std::shared_ptr& buffer, entt::entity entity, const vec3& position, const quat& rotation, const Components::MovementFlags movementFlags, f32 verticalVelocity) { - bool result = CreatePacket(buffer, Network::GameOpcode::Shared_EntityMove, [&]() + bool result = CreatePacket(buffer, Network::GameOpcode::Shared_EntityMove, [&buffer, &position, &rotation, entity, movementFlags, verticalVelocity]() { buffer->Put(entity); buffer->Put(position); buffer->Put(rotation); buffer->Put(movementFlags); - buffer->Put(verticalVelocity); + buffer->PutF32(verticalVelocity); }); return result; } - bool BuildEntityCreateMessage(std::shared_ptr& buffer, entt::entity entity, const Components::Transform& transform, u32 displayID) + bool BuildSetMoverMessage(std::shared_ptr& buffer, entt::entity entity) { - bool result = CreatePacket(buffer, Network::GameOpcode::Server_EntityCreate, [&]() + bool result = CreatePacket(buffer, Network::GameOpcode::Server_SetMover, [&buffer, entity]() + { + buffer->Put(entity); + }); + + return result; + } + bool BuildEntityCreateMessage(std::shared_ptr& buffer, entt::entity entity, const Components::Transform& transform) + { + bool result = CreatePacket(buffer, Network::GameOpcode::Server_EntityCreate, [&buffer, &transform, entity]() { buffer->Put(entity); - buffer->PutU32(displayID); buffer->Put(transform); }); @@ -135,7 +103,7 @@ namespace ECS::Util::MessageBuilder } bool BuildEntityDestroyMessage(std::shared_ptr& buffer, entt::entity entity) { - bool result = CreatePacket(buffer, Network::GameOpcode::Server_EntityDestroy, [&]() + bool result = CreatePacket(buffer, Network::GameOpcode::Server_EntityDestroy, [&buffer, entity]() { buffer->Put(entity); }); @@ -144,7 +112,7 @@ namespace ECS::Util::MessageBuilder } bool BuildUnitStatsMessage(std::shared_ptr& buffer, entt::entity entity, const Components::UnitStatsComponent& unitStatsComponent) { - bool result = CreatePacket(buffer, Network::GameOpcode::Server_EntityResourcesUpdate, [&]() + bool result = CreatePacket(buffer, Network::GameOpcode::Server_EntityResourcesUpdate, [&buffer, &unitStatsComponent, entity]() { buffer->Put(entity); buffer->Put(Components::PowerType::Health); @@ -180,7 +148,7 @@ namespace ECS::Util::MessageBuilder } bool BuildEntityTargetUpdateMessage(std::shared_ptr& buffer, entt::entity entity, entt::entity target) { - bool result = CreatePacket(buffer, Network::GameOpcode::Shared_EntityTargetUpdate, [&]() + bool result = CreatePacket(buffer, Network::GameOpcode::Shared_EntityTargetUpdate, [&buffer, entity, target]() { buffer->Put(entity); buffer->Put(target); @@ -190,7 +158,7 @@ namespace ECS::Util::MessageBuilder } bool BuildEntitySpellCastMessage(std::shared_ptr& buffer, entt::entity entity, f32 castTime, f32 castDuration) { - bool result = CreatePacket(buffer, Network::GameOpcode::Server_EntityCastSpell, [&]() + bool result = CreatePacket(buffer, Network::GameOpcode::Server_EntityCastSpell, [&buffer, entity, castTime, castDuration]() { buffer->Put(entity); buffer->PutF32(castTime); @@ -201,7 +169,7 @@ namespace ECS::Util::MessageBuilder } bool BuildEntityDisplayInfoUpdateMessage(std::shared_ptr& buffer, entt::entity entity, u32 displayID) { - bool result = CreatePacket(buffer, Network::GameOpcode::Server_EntityDisplayInfoUpdate, [&]() + bool result = CreatePacket(buffer, Network::GameOpcode::Server_EntityDisplayInfoUpdate, [&buffer, entity, displayID]() { buffer->Put(entity); buffer->PutU32(displayID); @@ -211,6 +179,23 @@ namespace ECS::Util::MessageBuilder } } + namespace Unit + { + bool BuildUnitCreate(std::shared_ptr& buffer, entt::registry& registry, entt::entity entity) + { + Components::Transform& transform = registry.get(entity); + Components::UnitStatsComponent& unitStatsComponent = registry.get(entity); + Components::DisplayInfo& displayInfo = registry.get(entity); + + bool failed = false; + failed |= !Entity::BuildEntityCreateMessage(buffer, entity, transform); + failed |= !Entity::BuildEntityDisplayInfoUpdateMessage(buffer, entity, displayInfo.displayID); + failed |= !Entity::BuildUnitStatsMessage(buffer, entity, unitStatsComponent); + + return !failed; + } + } + namespace Spell { bool BuildSpellCastResultMessage(std::shared_ptr& buffer, entt::entity entity, u8 result, f32 castTime, f32 castDuration) @@ -219,7 +204,7 @@ namespace ECS::Util::MessageBuilder if (result == 0) { - result = CreatePacket(buffer, Network::GameOpcode::Server_SendSpellCastResult, [&]() + result = CreatePacket(buffer, Network::GameOpcode::Server_SendSpellCastResult, [&buffer, entity, result, castTime, castDuration]() { buffer->PutU8(result); buffer->PutF32(castTime); @@ -250,7 +235,7 @@ namespace ECS::Util::MessageBuilder default: break; } - createPacketResult = CreatePacket(buffer, Network::GameOpcode::Server_SendSpellCastResult, [&]() + createPacketResult = CreatePacket(buffer, Network::GameOpcode::Server_SendSpellCastResult, [&buffer, &errorString, result]() { buffer->PutU8(result); buffer->PutString(*errorString); @@ -277,7 +262,7 @@ namespace ECS::Util::MessageBuilder } bool BuildHealingDoneMessage(std::shared_ptr& buffer, entt::entity source, entt::entity target, f32 healing) { - bool result = CreatePacket(buffer, Network::GameOpcode::Server_SendCombatEvent, [&]() + bool result = CreatePacket(buffer, Network::GameOpcode::Server_SendCombatEvent, [&buffer, source, target, healing]() { buffer->Put(Components::CombatLogEvents::HealingDone); buffer->Put(source); @@ -289,7 +274,7 @@ namespace ECS::Util::MessageBuilder } bool BuildRessurectedMessage(std::shared_ptr& buffer, entt::entity source, entt::entity target) { - bool result = CreatePacket(buffer, Network::GameOpcode::Server_SendCombatEvent, [&]() + bool result = CreatePacket(buffer, Network::GameOpcode::Server_SendCombatEvent, [&buffer, source, target]() { buffer->Put(Components::CombatLogEvents::Ressurected); buffer->Put(source); @@ -302,7 +287,18 @@ namespace ECS::Util::MessageBuilder namespace Cheat { - bool BuildCharacterCreateResultMessage(std::shared_ptr& buffer, const std::string& name, u8 result) + bool BuildCheatCommandResultMessage(std::shared_ptr& buffer, u8 result, const std::string& response) + { + bool createdPacket = CreatePacket(buffer, Network::GameOpcode::Server_SendCheatCommandResult, [&buffer, &response, result]() + { + buffer->PutU8(result); + buffer->PutString(response); + }); + + return createdPacket; + } + + bool BuildCheatCreateCharacterResponse(std::shared_ptr& buffer, u8 result) { static const std::string EmptyStr = ""; static const std::string InvalidNameSupplied = "Character creation failed due to invalid name"; @@ -340,16 +336,9 @@ namespace ECS::Util::MessageBuilder default: break; } - bool createPacketResult = CreatePacket(buffer, Network::GameOpcode::Server_SendCheatCommandResult , [&]() - { - buffer->PutU8(result); - buffer->PutString(*resultString); - }); - - return createPacketResult; + return BuildCheatCommandResultMessage(buffer, result, *resultString); } - - bool BuildCharacterDeleteResultMessage(std::shared_ptr& buffer, const std::string& name, u8 result) + bool BuildCheatDeleteCharacterResponse(std::shared_ptr& buffer, u8 result) { static const std::string EmptyStr = ""; static const std::string CharacterWasDeleted = "Character was deleted"; @@ -387,13 +376,7 @@ namespace ECS::Util::MessageBuilder default: break; } - bool createPacketResult = CreatePacket(buffer, Network::GameOpcode::Server_SendCheatCommandResult, [&]() - { - buffer->PutU8(result); - buffer->PutString(*resultString); - }); - - return createPacketResult; + return BuildCheatCommandResultMessage(buffer, result, *resultString); } } } \ No newline at end of file diff --git a/Source/Server-Game/Server-Game/ECS/Util/MessageBuilderUtil.h b/Source/Server-Game/Server-Game/ECS/Util/MessageBuilderUtil.h index d28d1a1..db03527 100644 --- a/Source/Server-Game/Server-Game/ECS/Util/MessageBuilderUtil.h +++ b/Source/Server-Game/Server-Game/ECS/Util/MessageBuilderUtil.h @@ -4,6 +4,7 @@ #include #include +#include "Gameplay/Network/Define.h" #include "Gameplay/Network/Opcode.h" #include @@ -24,24 +25,30 @@ namespace ECS { u32 AddHeader(std::shared_ptr& buffer, Network::GameOpcode opcode, u16 size = 0); bool ValidatePacket(const std::shared_ptr& buffer, u32 headerPos); - bool CreatePacket(std::shared_ptr& buffer, Network::GameOpcode opcode, std::function func); + bool CreatePacket(std::shared_ptr& buffer, Network::GameOpcode opcode, std::function&& func = nullptr); namespace Authentication { - bool BuildConnectedMessage(std::shared_ptr& buffer, u8 result, entt::entity entity, const std::string* resultString = nullptr); + bool BuildConnectedMessage(std::shared_ptr& buffer, Network::ConnectResult result); } namespace Entity { - bool BuildEntityCreateMessage(std::shared_ptr& buffer, entt::entity entity, const Components::Transform& transform, u32 displayID); + bool BuildSetMoverMessage(std::shared_ptr& buffer, entt::entity entity); + bool BuildEntityCreateMessage(std::shared_ptr& buffer, entt::entity entity, const Components::Transform& transform); bool BuildEntityDestroyMessage(std::shared_ptr& buffer, entt::entity entity); - bool BuildEntityMoveMessage(std::shared_ptr& buffer, entt::entity entity, const vec3& position, const quat& rotation, const Components::MovementFlags& movementFlags, f32 verticalVelocity); + bool BuildEntityMoveMessage(std::shared_ptr& buffer, entt::entity entity, const vec3& position, const quat& rotation, const Components::MovementFlags movementFlags, f32 verticalVelocity); bool BuildUnitStatsMessage(std::shared_ptr& buffer, entt::entity entity, const Components::UnitStatsComponent& unitStatsComponent); bool BuildEntityTargetUpdateMessage(std::shared_ptr& buffer, entt::entity entity, entt::entity target); bool BuildEntitySpellCastMessage(std::shared_ptr& buffer, entt::entity entity, f32 castTime, f32 castDuration); bool BuildEntityDisplayInfoUpdateMessage(std::shared_ptr& buffer, entt::entity entity, u32 displayID); } + namespace Unit + { + bool BuildUnitCreate(std::shared_ptr& buffer, entt::registry& registry, entt::entity entity); + } + namespace Spell { bool BuildSpellCastResultMessage(std::shared_ptr& buffer, entt::entity entity, u8 result, f32 castTime, f32 castDuration); @@ -56,8 +63,10 @@ namespace ECS namespace Cheat { - bool BuildCharacterCreateResultMessage(std::shared_ptr& buffer, const std::string& name, u8 result); - bool BuildCharacterDeleteResultMessage(std::shared_ptr& buffer, const std::string& name, u8 result); + bool BuildCheatCommandResultMessage(std::shared_ptr& buffer, u8 result, const std::string& response); + + bool BuildCheatCreateCharacterResponse(std::shared_ptr& buffer, u8 result); + bool BuildCheatDeleteCharacterResponse(std::shared_ptr& buffer, u8 result); } } } diff --git a/Source/Server-Game/Server-Game/Util/UnitUtils.cpp b/Source/Server-Game/Server-Game/Util/UnitUtils.cpp index 1ccf611..e4dbc10 100644 --- a/Source/Server-Game/Server-Game/Util/UnitUtils.cpp +++ b/Source/Server-Game/Server-Game/Util/UnitUtils.cpp @@ -8,6 +8,61 @@ using namespace ECS; namespace UnitUtils { + u32 GetDisplayIDFromRaceGender(GameDefine::Race race, GameDefine::Gender gender) + { + u32 displayID = 0; + + switch (race) + { + case GameDefine::Race::Human: + { + displayID = 49; + break; + } + case GameDefine::Race::Orc: + { + displayID = 51; + break; + } + case GameDefine::Race::Dwarf: + { + displayID = 53; + break; + } + case GameDefine::Race::NightElf: + { + displayID = 55; + break; + } + case GameDefine::Race::Undead: + { + displayID = 57; + break; + } + case GameDefine::Race::Tauren: + { + displayID = 59; + break; + } + case GameDefine::Race::Gnome: + { + displayID = 1563; + break; + } + case GameDefine::Race::Troll: + { + displayID = 1478; + break; + } + + default: break; + } + + displayID += 1 * (gender != GameDefine::Gender::Male); + + return displayID; + } + Components::UnitStatsComponent& AddStatsComponent(entt::registry& registry, entt::entity entity) { auto& unitStatsComponent = registry.emplace_or_replace(entity); diff --git a/Source/Server-Game/Server-Game/Util/UnitUtils.h b/Source/Server-Game/Server-Game/Util/UnitUtils.h index 0838270..89fd550 100644 --- a/Source/Server-Game/Server-Game/Util/UnitUtils.h +++ b/Source/Server-Game/Server-Game/Util/UnitUtils.h @@ -1,6 +1,8 @@ #pragma once #include +#include + #include namespace ECS::Components @@ -10,7 +12,9 @@ namespace ECS::Components namespace UnitUtils { + u32 GetDisplayIDFromRaceGender(GameDefine::Race race, GameDefine::Gender gender); ECS::Components::UnitStatsComponent& AddStatsComponent(entt::registry& registry, entt::entity entity); + f32 HandleRageRegen(f32 current, f32 rateModifier, f32 deltaTime); f32 HandleEnergyRegen(f32 current, f32 max, f32 rateModifier, f32 deltaTime); } \ No newline at end of file diff --git a/Source/Server-Game/Server-Game/main.cpp b/Source/Server-Game/Server-Game/main.cpp index 3ebc7c9..7a25280 100644 --- a/Source/Server-Game/Server-Game/main.cpp +++ b/Source/Server-Game/Server-Game/main.cpp @@ -14,8 +14,13 @@ i32 main() { quill::Backend::start(); - auto console_sink = quill::Frontend::create_or_get_sink("console_sink_1"); - quill::Logger* logger = quill::Frontend::create_or_get_logger("root", std::move(console_sink), "%(time:<16) LOG_%(log_level:<11) %(message)", "%H:%M:%S.%Qms", quill::Timezone::LocalTime, quill::ClockSourceType::System); + quill::ConsoleColours consoleColours; + consoleColours.set_default_colours(); + consoleColours.set_colour(quill::LogLevel::Info, quill::ConsoleColours::white); + + auto consoleSinkPtr = quill::Frontend::create_or_get_sink("consolesink", consoleColours); + + quill::Logger* logger = quill::Frontend::create_or_get_logger("root", std::move(consoleSinkPtr), "%(time:<16) LOG_%(log_level:<11) %(message)", "%H:%M:%S.%Qms", quill::Timezone::LocalTime, quill::ClockSourceType::System); Application app; app.Start(); diff --git a/Submodules/Engine b/Submodules/Engine index c8ac3a8..953cdff 160000 --- a/Submodules/Engine +++ b/Submodules/Engine @@ -1 +1 @@ -Subproject commit c8ac3a84b26b360398b41ae885030948a58ef730 +Subproject commit 953cdfff4af3e943c910062f17367d27abda18bf