From: vitler Date: Fri, 10 Apr 2026 22:44:06 +0000 (+0100) Subject: a smart nwn np project, or agent npc - anpc X-Git-Url: https://vgcfreebox.myrthtech.pt/gitweb/alentejosemlei.git/commitdiff_plain/95ab26eae90065d40149b3a7c3ae7b823f95864f a smart nwn np project, or agent npc - anpc --- 95ab26eae90065d40149b3a7c3ae7b823f95864f diff --git a/docker-compose.yaml b/docker-compose.yaml new file mode 100644 index 0000000..17dd765 --- /dev/null +++ b/docker-compose.yaml @@ -0,0 +1,24 @@ +services: + redis: + image: redis:latest + container_name: nwn_redis + ports: + - "6380:6379" + restart: unless-stopped + nwserver: + image: nwnxee/unified:latest + container_name: nwn_game_server + depends_on: + - redis + ports: + - "5121:5121/udp" + environment: + - NWN_SERVERNAME=Alentejo Sem Lei + - NWN_MODULE=Smart NPC + - NWN_PUBLICSERVER=0 + - NWNX_CORE_SKIP=n + - NWNX_REDIS_SKIP=n + - NWNX_REDIS_HOST=redis + volumes: + - ./server_data:/nwn/home + restart: unless-stopped \ No newline at end of file diff --git a/redis_bridge.py b/redis_bridge.py new file mode 100644 index 0000000..bc40dfa --- /dev/null +++ b/redis_bridge.py @@ -0,0 +1,74 @@ +import redis +import json +import requests + +print("Initializing Redis Bridge...") + +# 1. Force the correct Windows IP address and test the connection immediately +try: + r = redis.Redis(host='127.0.0.1', port=6380, decode_responses=True) + r.ping() # This will crash immediately if the connection is bad + print("SUCCESS: Connected to the Docker Redis database!") +except Exception as e: + print(f"CRITICAL ERROR: Could not connect to Redis. {e}") + exit() + +NPC_SYSTEM_PROMPT = """ +You are Elrendur Arna. You are currently residing in Alentejo Sem Lei. +Keep your responses under 3 sentences. +""" +chat_history = [{"role": "system", "content": NPC_SYSTEM_PROMPT}] + +print("\nReady! Listening for game messages on 'nwn_to_llm'...") + +while True: + try: + # This line freezes the script until a message arrives + result = r.blpop('nwn_to_llm') + + # --- IF IT HEARS THE GAME, IT WILL PRINT THIS --- + print(f"\n--- WAKE UP! NEW MESSAGE RECEIVED ---") + + queue_name, message_data = result + print(f"Raw data from Redis: {message_data}") + + # Try to parse the JSON + data = json.loads(message_data) + player_name = data.get('player', 'Unknown') + npc_tag = data.get('npc_tag', 'UnknownNPC') + message = data.get('message', '') + + print(f"Parsed: {player_name} said to {npc_tag}: '{message}'") + + chat_history.append({"role": "user", "content": f"{player_name} says: {message}"}) + + # Talk to Ollama + print("Thinking... (Sending to local Ollama)") + response = requests.post('http://localhost:11434/api/chat', json={ + "model": "llama3", + "messages": chat_history, + "stream": False + }, timeout=45) + + response.raise_for_status() # Triggers an error if Ollama is broken + reply_text = response.json()['message']['content'] + + print(f"Ollama Replied: {reply_text}") + chat_history.append({"role": "assistant", "content": reply_text}) + + # Package and send back to the game + reply_payload = { + "player": player_name, + "npc_tag": npc_tag, + "reply": reply_text + } + + r.rpush('llm_to_nwn', json.dumps(reply_payload)) + print("SUCCESS: Sent reply to the 'llm_to_nwn' queue for the game to pick up!") + + except json.JSONDecodeError as e: + print(f"ERROR: The game sent bad JSON data: {e}") + except requests.exceptions.RequestException as e: + print(f"ERROR: Failed to talk to Ollama. Is it running? {e}") + except Exception as e: + print(f"UNEXPECTED ERROR: {e}") \ No newline at end of file diff --git a/server_data/modules/Smart NPC.mod b/server_data/modules/Smart NPC.mod new file mode 100644 index 0000000..3808390 Binary files /dev/null and b/server_data/modules/Smart NPC.mod differ