
水鱼拿起尘封已久的树莓派4B干了件大事。创建用户minecraft给到需要的权限(id minecraftuid1001(minecraft) gid1001(minecraft) groups1001(minecraft),46(plugdev),100(users),102(input))创建~/.xinitrc文件给到以下。#!/bin/bash xset s off xset -dpms exec /usr/bin/minecraft-pi-reborn这个就是伪kiosk精髓了开机默认minecraft用户然后开游戏。讲究点加个音效文件记得找libminecraftpe0608.so。其他在树莓派上是不灵光的没有声音。再讲究点加个70元xbox手柄但是自己要写映射键位据说可以不写映射直接玩我是没试成功游戏无响应。#路径是/usr/local/bin/mcpi-pad #!/usr/bin/env bash set -euo pipefail ACTION${1:-} PID_FILE/run/mcpi-pad.pid LOG_FILE/tmp/mcpi-pad.log DAEMON/usr/local/bin/mcpi-pad-daemon.py is_running() { if [[ ! -f $PID_FILE ]]; then return 1 fi local pid pid$(cat $PID_FILE 2/dev/null || true) [[ -n $pid ]] kill -0 $pid 2/dev/null } start_pad() { if is_running; then echo mcpi-pad daemon is already running ps -fp $(cat $PID_FILE) || true return 0 fi sudo pkill -9 -x xboxdrv 2/dev/null || true nohup python3 $DAEMON $LOG_FILE 21 echo $! | sudo tee $PID_FILE /dev/null sleep 0.5 if is_running; then echo mcpi-pad daemon started ps -fp $(cat $PID_FILE) else echo mcpi-pad daemon failed to start [[ -f $LOG_FILE ]] tail -n 80 $LOG_FILE exit 1 fi } stop_pad() { if is_running; then local pid pid$(cat $PID_FILE) kill $pid 2/dev/null || true sleep 0.2 kill -9 $pid 2/dev/null || true sudo rm -f $PID_FILE echo mcpi-pad daemon stopped else echo mcpi-pad daemon is not running fi } status_pad() { if is_running; then echo mcpi-pad daemon is running ps -fp $(cat $PID_FILE) else echo mcpi-pad daemon is not running fi } case $ACTION in start) start_pad ;; stop) stop_pad ;; restart) stop_pad start_pad ;; status) status_pad ;; log) [[ -f $LOG_FILE ]] tail -n 120 $LOG_FILE || echo No log file: $LOG_FILE ;; *) echo Usage: sudo mcpi-pad {start|stop|restart|status|log} exit 2 ;; esac以及#路径/usr/local/bin/mcpi-pad-daemon.py #!/usr/bin/env python3 import signal import sys import time from collections import defaultdict from evdev import InputDevice, UInput, ecodes DEVICE_NAME Xbox Wireless Controller THRESHOLD 12000 CENTER 32768 MOUSE_DEADZONE 5000 MOUSE_MAX_STEP 25 def find_event_device() - str: with open(/proc/bus/input/devices, r, encodingutf-8) as f: blocks f.read().split(\n\n) for block in blocks: if DEVICE_NAME in block: for tok in block.split(): if tok.startswith(event) and tok[5:].isdigit(): return f/dev/input/{tok} raise RuntimeError(Xbox controller event device not found) pressed defaultdict(set) def press(ui: UInput, src: str, key: int) - None: if key in pressed[src]: return pressed[src].add(key) if not any(key in v for k, v in pressed.items() if k ! src): ui.write(ecodes.EV_KEY, key, 1) def release(ui: UInput, src: str, key: int) - None: if key not in pressed[src]: return pressed[src].remove(key) if not any(key in v for v in pressed.values()): ui.write(ecodes.EV_KEY, key, 0) def set_axis(ui: UInput, src: str, neg: int, pos: int, value: int) - None: delta value - CENTER if delta -THRESHOLD: press(ui, src, neg) release(ui, src, pos) elif delta THRESHOLD: press(ui, src, pos) release(ui, src, neg) else: release(ui, src, neg) release(ui, src, pos) def set_hat(ui: UInput, src: str, neg: int, pos: int, value: int) - None: if value 0: press(ui, src, neg) release(ui, src, pos) elif value 0: press(ui, src, pos) release(ui, src, neg) else: release(ui, src, neg) release(ui, src, pos) def emit_mouse_rel(ui: UInput, rel_code: int, value: int, invert: bool False) - bool: delta value - CENTER if abs(delta) MOUSE_DEADZONE: return False span 32767 - MOUSE_DEADZONE magnitude int(((abs(delta) - MOUSE_DEADZONE) / span) * MOUSE_MAX_STEP) magnitude max(1, min(MOUSE_MAX_STEP, magnitude)) direction -1 if delta 0 else 1 if invert: direction * -1 ui.write(ecodes.EV_REL, rel_code, direction * magnitude) return True def release_all(ui: UInput) - None: keys set() for ks in pressed.values(): keys.update(ks) for key in keys: ui.write(ecodes.EV_KEY, key, 0) ui.syn() def main() - int: event_dev find_event_device() pad InputDevice(event_dev) kb_ui UInput( { ecodes.EV_KEY: [ ecodes.KEY_W, ecodes.KEY_A, ecodes.KEY_S, ecodes.KEY_D, ecodes.KEY_SPACE, ecodes.KEY_LEFTCTRL, ecodes.KEY_ESC, ecodes.KEY_E, ] }, nameMCPI Pad Keyboard, bustype0x03, ) mouse_ui UInput( { ecodes.EV_KEY: [ecodes.BTN_LEFT, ecodes.BTN_RIGHT], ecodes.EV_REL: [ecodes.REL_X, ecodes.REL_Y], }, nameMCPI Pad Mouse, bustype0x03, ) btn_map { ecodes.BTN_SOUTH: ecodes.KEY_SPACE, ecodes.BTN_EAST: ecodes.KEY_LEFTCTRL, ecodes.BTN_C: ecodes.KEY_ESC, ecodes.BTN_Z: ecodes.KEY_E, } stop False def _stop(_sig, _frm): nonlocal stop stop True signal.signal(signal.SIGTERM, _stop) signal.signal(signal.SIGINT, _stop) while not stop: try: for ev in pad.read_loop(): if stop: break if ev.type ecodes.EV_KEY and ev.code in btn_map: key btn_map[ev.code] if ev.value: press(kb_ui, btn, key) else: release(kb_ui, btn, key) kb_ui.syn() elif ev.type ecodes.EV_ABS: if ev.code ecodes.ABS_X: set_axis(kb_ui, lx, ecodes.KEY_A, ecodes.KEY_D, ev.value) kb_ui.syn() elif ev.code ecodes.ABS_Y: set_axis(kb_ui, ly, ecodes.KEY_W, ecodes.KEY_S, ev.value) kb_ui.syn() elif ev.code ecodes.ABS_RX: if emit_mouse_rel(mouse_ui, ecodes.REL_X, ev.value): mouse_ui.syn() elif ev.code ecodes.ABS_RY: if emit_mouse_rel(mouse_ui, ecodes.REL_Y, ev.value, invertTrue): mouse_ui.syn() elif ev.code ecodes.ABS_HAT0X: set_hat(kb_ui, hx, ecodes.KEY_A, ecodes.KEY_D, ev.value) kb_ui.syn() elif ev.code ecodes.ABS_HAT0Y: set_hat(kb_ui, hy, ecodes.KEY_W, ecodes.KEY_S, ev.value) kb_ui.syn() except OSError: time.sleep(0.2) try: event_dev find_event_device() pad InputDevice(event_dev) except Exception: time.sleep(0.5) release_all(kb_ui) pad.close() kb_ui.close() mouse_ui.close() return 0 if __name__ __main__: sys.exit(main())反正最后游戏柄还是很难调试还是键鼠套餐香。